use std::fmt::Debug;
use std::marker::PhantomData;
use solverforge_core::domain::PlanningSolution;
use solverforge_scoring::Director;
use super::Termination;
use crate::scope::ProgressCallback;
use crate::scope::SolverScope;
#[derive(Clone)]
pub struct OrTermination<T, S, D>(pub T, PhantomData<fn(S, D)>);
impl<T: Debug, S, D> Debug for OrTermination<T, S, D> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("OrTermination").field(&self.0).finish()
}
}
impl<T, S, D> OrTermination<T, S, D> {
pub fn new(terminations: T) -> Self {
Self(terminations, PhantomData)
}
}
#[derive(Clone)]
pub struct AndTermination<T, S, D>(pub T, PhantomData<fn(S, D)>);
impl<T: Debug, S, D> Debug for AndTermination<T, S, D> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("AndTermination").field(&self.0).finish()
}
}
impl<T, S, D> AndTermination<T, S, D> {
pub fn new(terminations: T) -> Self {
Self(terminations, PhantomData)
}
}
macro_rules! impl_composite_termination {
($($idx:tt: $T:ident),+) => {
impl<S, D, BestCb, $($T),+> Termination<S, D, BestCb> for OrTermination<($($T,)+), S, D>
where
S: PlanningSolution,
D: Director<S>,
BestCb: ProgressCallback<S>,
$($T: Termination<S, D, BestCb>,)+
{
fn is_terminated(&self, solver_scope: &SolverScope<S, D, BestCb>) -> bool {
$(
if self.0.$idx.is_terminated(solver_scope) {
return true;
}
)+
false
}
fn install_inphase_limits(&self, solver_scope: &mut SolverScope<S, D, BestCb>) {
$(
self.0.$idx.install_inphase_limits(solver_scope);
)+
}
}
impl<S, D, BestCb, $($T),+> Termination<S, D, BestCb> for AndTermination<($($T,)+), S, D>
where
S: PlanningSolution,
D: Director<S>,
BestCb: ProgressCallback<S>,
$($T: Termination<S, D, BestCb>,)+
{
fn is_terminated(&self, solver_scope: &SolverScope<S, D, BestCb>) -> bool {
$(
if !self.0.$idx.is_terminated(solver_scope) {
return false;
}
)+
true
}
fn install_inphase_limits(&self, solver_scope: &mut SolverScope<S, D, BestCb>) {
$(
self.0.$idx.install_inphase_limits(solver_scope);
)+
}
}
};
}
impl_composite_termination!(0: T0);
impl_composite_termination!(0: T0, 1: T1);
impl_composite_termination!(0: T0, 1: T1, 2: T2);
impl_composite_termination!(0: T0, 1: T1, 2: T2, 3: T3);
impl_composite_termination!(0: T0, 1: T1, 2: T2, 3: T3, 4: T4);
impl_composite_termination!(0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5);
impl_composite_termination!(0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5, 6: T6);
impl_composite_termination!(0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5, 6: T6, 7: T7);