use necsim_impls_std::event_log::recorder::EventLogConfig;
use necsim_partitioning_core::reporter::ReporterContext;
use tiny_keccak::{Hasher, Keccak};
use rustcoalescence_algorithms::{
result::SimulationOutcome as AlgorithmOutcome, AlgorithmDispatch,
};
use necsim_core::{
cogs::{MathsCore, RngCore, SeedableRng},
reporter::Reporter,
};
use necsim_core_bond::NonNegativeF64;
use rustcoalescence_scenarios::{Scenario, ScenarioCogs};
use crate::{
args::config::{
partitioning::Partitioning,
rng::{Base32RngState, Rng as RngArgs},
sample::Sample,
},
cli::simulate::parse,
};
use super::{
super::super::{BufferingSimulateArgsBuilder, SimulationOutcome},
info,
};
#[allow(clippy::too_many_arguments)]
pub(super) fn dispatch<
M: MathsCore,
G: RngCore<M>,
A: AlgorithmDispatch<M, G, O, R>,
O: Scenario<M, G>,
R: Reporter,
P: ReporterContext<Reporter = R>,
>(
partitioning: Partitioning,
event_log: Option<EventLogConfig>,
reporter_context: P,
sample: Sample,
algorithm_args: A::Arguments,
scenario: ScenarioCogs<M, G, O>,
pause_before: Option<NonNegativeF64>,
ron_args: &str,
normalised_args: &mut BufferingSimulateArgsBuilder,
) -> anyhow::Result<SimulationOutcome>
where
Result<AlgorithmOutcome<M, G>, A::Error>: anyhow::Context<AlgorithmOutcome<M, G>, A::Error>,
{
let rng: G = match parse::rng::parse_and_normalise(
ron_args,
normalised_args,
partitioning.get_logical_partition_size::<M, G, O, R, A>(&algorithm_args),
)? {
RngArgs::Seed(seed) => SeedableRng::seed_from_u64(seed),
RngArgs::Sponge(bytes) => {
let mut seed = G::Seed::default();
let mut sponge = Keccak::v256();
sponge.update(&bytes);
sponge.finalize(seed.as_mut());
RngCore::from_seed(seed)
},
RngArgs::State(state) => state.into(),
};
let result = info::dispatch::<M, G, A, O, R, P>(
partitioning,
event_log,
reporter_context,
sample,
rng,
scenario,
algorithm_args,
pause_before,
normalised_args,
)?;
match result {
AlgorithmOutcome::Done { time, steps } => Ok(SimulationOutcome::Done { time, steps }),
AlgorithmOutcome::Paused {
time,
steps,
lineages,
rng: paused_rng,
..
} => {
normalised_args.rng(&RngArgs::State(Base32RngState::from(paused_rng)));
Ok(SimulationOutcome::Paused {
time,
steps,
lineages,
})
},
}
}