use anyhow::Context;
use rustcoalescence_algorithms::{result::SimulationOutcome, Algorithm};
use necsim_core::{
cogs::{MathsCore, RngCore},
reporter::Reporter,
};
use necsim_core_bond::{NonNegativeF64, PositiveF64};
use necsim_impls_no_std::cogs::origin_sampler::pre_sampler::OriginPreSampler;
use necsim_partitioning_core::LocalPartition;
use rustcoalescence_scenarios::{Scenario, ScenarioCogs};
use crate::args::config::sample::{Sample, SampleMode, SampleModeRestart, SampleOrigin};
pub(super) fn simulate<
'p,
M: MathsCore,
G: RngCore<M>,
A: Algorithm<'p, M, G, O, R, P>,
O: Scenario<M, G>,
R: Reporter,
P: LocalPartition<'p, R>,
>(
local_partition: &mut P,
sample: Sample,
rng: G,
scenario: ScenarioCogs<M, G, O>,
algorithm_args: A::Arguments,
pause_before: Option<NonNegativeF64>,
) -> anyhow::Result<SimulationOutcome<M, G>> {
let lineages = match sample.origin {
SampleOrigin::Habitat => {
return A::initialise_and_simulate(
algorithm_args,
rng,
scenario,
OriginPreSampler::all().percentage(sample.percentage),
pause_before,
local_partition,
)
.context("Failed to perform the fresh simulation.")
},
SampleOrigin::List(lineages) => lineages,
SampleOrigin::Bincode(loader) => loader.into_lineages(),
};
match sample.mode {
SampleMode::Genesis => A::initialise_and_simulate(
algorithm_args,
rng,
scenario,
OriginPreSampler::all().percentage(sample.percentage),
pause_before,
local_partition,
)
.context("Failed to perform the fresh simulation."),
SampleMode::Resume => A::resume_and_simulate(
algorithm_args,
rng,
scenario,
OriginPreSampler::all().percentage(sample.percentage),
lineages.into_iter(),
None,
pause_before,
local_partition,
)
.context("Failed to perform the resuming simulation."),
SampleMode::FixUp(strategy) => A::fixup_for_restart(
algorithm_args,
rng,
scenario,
OriginPreSampler::all().percentage(sample.percentage),
lineages.into_iter(),
PositiveF64::new(pause_before.unwrap().get()).unwrap(),
strategy,
local_partition,
)
.context("Failed to fix-up the restarting simulation."),
SampleMode::Restart(SampleModeRestart { after }) => A::resume_and_simulate(
algorithm_args,
rng,
scenario,
OriginPreSampler::all().percentage(sample.percentage),
lineages.into_iter(),
Some(after),
pause_before,
local_partition,
)
.context("Failed to perform the restarting simulation."),
}
}