betex 0.26.0

Betfair / Prediction Market Exchange
Documentation
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(),
    }
}