use anyhow::Result; use serde::Deserialize; use std::collections::HashMap; #[derive(Deserialize)] struct PricePoints { normal: HashMap, foil: HashMap, } #[derive(Deserialize)] struct PriceList { retail: Option, } #[derive(Deserialize)] struct PriceRecord { paper: Option>, } #[derive(Deserialize)] struct PriceDB { data: HashMap, } pub fn get_cards_in_budget(prices_file: Vec, price_filter: f64) -> Result> { // Read prices file let price_db: PriceDB = serde_json::from_slice(&prices_file)?; // Filter cards we care about Ok(price_db .data .iter() .filter(|(_, price_list)| match &price_list.paper { Some(prices) => get_lowest_price(prices) < price_filter, None => false, }) .map(|(uuid, _)| uuid.clone()) .collect()) } fn get_lowest_price(sellers: &HashMap) -> f64 { // Iterate over each seller and their price list sellers .iter() .flat_map(|(_, price_list)| { // Extract the retail price list, if it exists price_list.retail.as_ref().map(|retail| { // Combine normal and foil price lists retail .normal .iter() .chain(retail.foil.iter()) // Extract the prices from the price lists .map(|(_, &price)| price) }) }) // Flatten the nested iterators into a single iterator .flatten() // Find the minimum price using the fold function .fold(f64::MAX, |min_price, price| min_price.min(price)) } #[cfg(test)] mod tests { use super::*; #[test] fn test_get_lowest_price() { let mut sellers: HashMap = HashMap::new(); let price_list1 = PriceList { retail: Some(PricePoints { normal: vec![("2022-01-22".to_string(), 10.0)].into_iter().collect(), foil: vec![("2022-01-22".to_string(), 20.0)].into_iter().collect(), }), }; sellers.insert("seller1".to_string(), price_list1); let price_list2: PriceList = PriceList { retail: Some(PricePoints { normal: vec![("2022-01-22".to_string(), 15.0)].into_iter().collect(), foil: vec![("2022-01-22".to_string(), 25.0)].into_iter().collect(), }), }; sellers.insert("seller2".to_string(), price_list2); let lowest_price = get_lowest_price(&sellers); assert_eq!(lowest_price, 10.0); } }