91 lines
2.6 KiB
Rust
91 lines
2.6 KiB
Rust
use anyhow::Result;
|
|
use serde::Deserialize;
|
|
use std::collections::HashMap;
|
|
|
|
#[derive(Deserialize)]
|
|
struct PricePoints {
|
|
normal: HashMap<String, f64>,
|
|
foil: HashMap<String, f64>,
|
|
}
|
|
|
|
#[derive(Deserialize)]
|
|
struct PriceList {
|
|
retail: Option<PricePoints>,
|
|
}
|
|
|
|
#[derive(Deserialize)]
|
|
struct PriceRecord {
|
|
paper: Option<HashMap<String, PriceList>>,
|
|
}
|
|
|
|
#[derive(Deserialize)]
|
|
struct PriceDB {
|
|
data: HashMap<String, PriceRecord>,
|
|
}
|
|
|
|
pub fn get_cards_in_budget(prices_file: Vec<u8>, price_filter: f64) -> Result<Vec<String>> {
|
|
// 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<String, PriceList>) -> 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<String, PriceList> = 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);
|
|
}
|
|
}
|