use super::{BookEvent, BookMarketState, RunnerResultEntry, RunnerSettlement, ensure_state_change};
use crate::{book::protocol::reject::RejectReason, types::RunnerId};
use std::collections::BTreeSet;
pub(crate) fn validate_market_settlement(
state: BookMarketState,
runner_results: &[RunnerSettlement],
active_runner_ids: impl IntoIterator<Item = RunnerId>,
) -> Result<(), RejectReason> {
ensure_state_change(state, BookMarketState::Settled)?;
if state != BookMarketState::Closed {
return Err(RejectReason::MarketNotClosed);
}
let result_runners: BTreeSet<_> = runner_results
.iter()
.map(|runner| runner.runner_id)
.collect();
if result_runners.len() != runner_results.len() {
return Err(RejectReason::DuplicateRunner);
}
let active_runners: BTreeSet<_> = active_runner_ids.into_iter().collect();
if result_runners != active_runners {
return Err(RejectReason::IncompleteResults);
}
Ok(())
}
pub(crate) fn build_market_settled_event(
runner_results: &[RunnerSettlement],
void_reason: &str,
mut runner_label: impl FnMut(RunnerId) -> String,
) -> BookEvent {
BookEvent::MarketSettled {
runner_results: runner_results
.iter()
.map(|runner| RunnerResultEntry {
runner_id: runner.runner_id,
runner_label: runner_label(runner.runner_id),
result: runner.result,
void_factor: runner.void_factor.clone(),
deadheat_factor: runner.deadheat_factor.clone(),
})
.collect(),
void_reason: void_reason.to_string(),
}
}