use crate::market::{History, Run, RunName, monte_carlo};
use crate::params::TaxTables;
use crate::plan::Plan;
use crate::project::{Projection, project};
use crate::search::{Progress, RunError};
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Measure {
Planned,
Success(f64),
}
impl Measure {
pub(crate) fn check(self) -> Result<(), RunError> {
match self {
Self::Success(target) if !(target > 0.0 && target <= 1.0) => Err(RunError::refused(
"success",
"must be a share above 0%, and no more than 100%",
)),
_ => Ok(()),
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct Judged {
pub is_met: bool,
pub projection: Projection,
pub success_rate: Option<f64>,
}
pub(crate) fn judge(
plan: &Plan,
tables: &TaxTables,
history: &History,
measure: Measure,
progress: &Progress,
) -> Result<Judged, RunError> {
if progress.is_cancelled() {
return Err(RunError::Cancelled);
}
let projection = project(plan, tables);
let (is_met, success_rate) = match measure {
Measure::Planned => {
let floor = plan.market().leave_at_least();
let run = Run::of(RunName::Planned, &projection, floor);
(run.is_success, None)
}
Measure::Success(target) => {
let rate = monte_carlo(plan, tables, history, progress)?
.runs
.success_rate();
(rate >= target, Some(rate))
}
};
Ok(Judged {
is_met,
projection,
success_rate,
})
}