use crate::export::{export_lp, export_mps};
use fts_core::{
models::{DemandCurve, DemandGroup, Map, ProductGroup},
ports::Solver,
};
use serde::{Deserialize, Serialize};
use std::io::Write;
use std::{fmt, hash::Hash};
macro_rules! string_wrapper {
($struct:ident) => {
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
#[serde(transparent)]
#[doc = concat!("A newtype wrapper for ", stringify!($struct))]
pub struct $struct(String);
impl fmt::Display for $struct {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.0)
}
}
};
}
string_wrapper!(DemandId);
string_wrapper!(PortfolioId);
string_wrapper!(ProductId);
#[derive(Debug, Serialize, Deserialize)]
pub struct Portfolio {
demand_group: DemandGroup<DemandId>,
product_group: ProductGroup<ProductId>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Auction {
pub demand_curves: Map<DemandId, DemandCurve>,
pub portfolios: Map<PortfolioId, Portfolio>,
}
#[derive(Serialize, Deserialize)]
pub struct Outcome<PortfolioOutcome, ProductOutcome> {
pub portfolios: Map<PortfolioId, PortfolioOutcome>,
pub products: Map<ProductId, ProductOutcome>,
}
impl Auction {
pub async fn solve<T: Solver<DemandId, PortfolioId, ProductId>>(
self,
solver: T,
) -> Outcome<T::PortfolioOutcome, T::ProductOutcome> {
let portfolios = self
.portfolios
.into_iter()
.map(
|(
portfolio_id,
Portfolio {
demand_group,
product_group,
},
)| (portfolio_id, (demand_group, product_group)),
)
.collect::<Map<_, _>>();
let (portfolio_outcomes, product_outcomes) = solver
.solve(self.demand_curves, portfolios, Default::default())
.await
.unwrap();
Outcome {
portfolios: portfolio_outcomes,
products: product_outcomes,
}
}
pub fn export_lp(self, buffer: &mut impl Write) -> Result<(), std::io::Error> {
let portfolios = self
.portfolios
.into_iter()
.map(
|(
portfolio_id,
Portfolio {
demand_group,
product_group,
},
)| (portfolio_id, (demand_group, product_group)),
)
.collect();
export_lp(self.demand_curves, portfolios, buffer)
}
pub fn export_mps(self, buffer: &mut impl Write) -> Result<(), std::io::Error> {
let portfolios = self
.portfolios
.into_iter()
.map(
|(
portfolio_id,
Portfolio {
demand_group,
product_group,
},
)| (portfolio_id, (demand_group, product_group)),
)
.collect();
export_mps(self.demand_curves, portfolios, buffer)
}
}