use std::{
cmp::Ordering,
ops::{Add, Sub},
};
use num_traits::Zero;
use vcg_auction::vcg_auction;
#[derive(Copy, Clone, Debug, Default, PartialEq)]
struct FloatValue(pub f64);
impl Eq for FloatValue {}
impl Ord for FloatValue {
fn cmp(&self, other: &Self) -> Ordering {
self.0.total_cmp(&other.0)
}
}
impl PartialOrd for FloatValue {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Zero for FloatValue {
fn zero() -> Self {
Self(0.0)
}
fn is_zero(&self) -> bool {
self.0 == 0.0
}
}
impl Add for FloatValue {
type Output = Self;
fn add(self, other: Self) -> Self {
Self(self.0 + other.0)
}
}
impl Sub for FloatValue {
type Output = Self;
fn sub(self, other: Self) -> Self {
Self(self.0 - other.0)
}
}
#[derive(Debug, Clone, PartialEq)]
struct FloatBid {
name: String,
value: FloatValue,
items: Vec<(String, f64)>,
}
impl FloatBid {
fn new(
name: impl Into<String>,
value: f64,
items: Vec<(String, f64)>,
) -> Self {
Self {
name: name.into(),
value: FloatValue(value),
items,
}
}
}
impl vcg_auction::Bid for FloatBid {
type Name = String;
type Value = FloatValue;
type Item = String;
type Quantity = f64;
fn bidder_name(&self) -> &Self::Name {
&self.name
}
fn bid_value(&self) -> &Self::Value {
&self.value
}
fn bid_items(&self) -> &[(Self::Item, Self::Quantity)] {
&self.items
}
}
#[test]
fn simple_float_case() {
let items = vec![("kg of rare metal".into(), 2.2)];
let bids = vec![
vec![
FloatBid::new("Alice", 5.5, vec![("kg of rare metal".into(), 1.0)]),
FloatBid::new("Alice", 7.0, vec![("kg of rare metal".into(), 2.1)]),
],
vec![FloatBid::new(
"Bob",
4.1,
vec![("kg of rare metal".into(), 1.1)],
)],
];
let result = vcg_auction(&items, &bids).unwrap();
assert_eq!(result.winning_bids, [&bids[0][0], &bids[1][0]]);
assert_eq!(
result.payments,
[
(&"Alice".into(), FloatValue(0.0)),
(&"Bob".into(), FloatValue(1.5))
]
);
}