use std::collections::HashMap;
use crate::models::skyblock::{Bazaar, BazaarProduct, SkyBlockAuction};
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct BazaarSpread {
pub buy_order_price: f64,
pub sell_order_price: f64,
}
impl BazaarSpread {
pub fn margin(&self) -> f64 {
(self.sell_order_price - self.buy_order_price).abs()
}
}
pub fn bazaar_spread(product: &BazaarProduct) -> Option<BazaarSpread> {
let sell_order_price = product.sell_summary.first()?.price_per_unit;
let buy_order_price = product.buy_summary.first()?.price_per_unit;
Some(BazaarSpread {
buy_order_price,
sell_order_price,
})
}
pub fn bazaar_spreads(bazaar: &Bazaar) -> HashMap<String, BazaarSpread> {
bazaar
.products
.iter()
.filter_map(|(id, product)| bazaar_spread(product).map(|s| (id.clone(), s)))
.collect()
}
pub fn lowest_bin(auctions: &[SkyBlockAuction]) -> HashMap<String, i64> {
let mut lowest: HashMap<String, i64> = HashMap::new();
for auction in auctions {
if !auction.bin {
continue;
}
lowest
.entry(auction.item_name.clone())
.and_modify(|price| {
if auction.starting_bid < *price {
*price = auction.starting_bid;
}
})
.or_insert(auction.starting_bid);
}
lowest
}
#[cfg(test)]
mod tests {
use super::*;
use crate::models::skyblock::{BazaarOrder, BazaarProduct};
fn product(sell: f64, buy: f64) -> BazaarProduct {
BazaarProduct {
product_id: "X".into(),
sell_summary: vec![BazaarOrder {
amount: 1,
price_per_unit: sell,
orders: 1,
}],
buy_summary: vec![BazaarOrder {
amount: 1,
price_per_unit: buy,
orders: 1,
}],
quick_status: None,
}
}
#[test]
fn computes_spread_margin() {
let spread = bazaar_spread(&product(5.0, 4.2)).unwrap();
assert_eq!(spread.sell_order_price, 5.0);
assert_eq!(spread.buy_order_price, 4.2);
assert!((spread.margin() - 0.8).abs() < 1e-9);
}
}