blah-rs/src/price.rs

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);
}
}