use std::fmt::Debug;
use std::marker::PhantomData;
use solverforge_core::domain::PlanningSolution;
use solverforge_scoring::Director;
use super::{Move, MoveArena};
pub struct CompositeMove<S, M1, M2>
where
S: PlanningSolution,
M1: Move<S>,
M2: Move<S>,
{
index_1: usize,
index_2: usize,
_phantom: PhantomData<(fn() -> S, fn() -> M1, fn() -> M2)>,
}
impl<S, M1, M2> CompositeMove<S, M1, M2>
where
S: PlanningSolution,
M1: Move<S>,
M2: Move<S>,
{
pub fn new(index_1: usize, index_2: usize) -> Self {
Self {
index_1,
index_2,
_phantom: PhantomData,
}
}
pub fn index_1(&self) -> usize {
self.index_1
}
pub fn index_2(&self) -> usize {
self.index_2
}
pub fn is_doable_with_arenas<D: Director<S>>(
&self,
arena_1: &MoveArena<M1>,
arena_2: &MoveArena<M2>,
score_director: &D,
) -> bool {
let m1 = arena_1.get(self.index_1);
let m2 = arena_2.get(self.index_2);
match (m1, m2) {
(Some(m1), Some(m2)) => m1.is_doable(score_director) || m2.is_doable(score_director),
_ => false,
}
}
pub fn do_move_with_arenas<D: Director<S>>(
&self,
arena_1: &MoveArena<M1>,
arena_2: &MoveArena<M2>,
score_director: &mut D,
) {
if let Some(m1) = arena_1.get(self.index_1) {
m1.do_move(score_director);
}
if let Some(m2) = arena_2.get(self.index_2) {
m2.do_move(score_director);
}
}
}
impl<S, M1, M2> Clone for CompositeMove<S, M1, M2>
where
S: PlanningSolution,
M1: Move<S>,
M2: Move<S>,
{
fn clone(&self) -> Self {
*self
}
}
impl<S, M1, M2> Copy for CompositeMove<S, M1, M2>
where
S: PlanningSolution,
M1: Move<S>,
M2: Move<S>,
{
}
impl<S, M1, M2> Debug for CompositeMove<S, M1, M2>
where
S: PlanningSolution,
M1: Move<S>,
M2: Move<S>,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("CompositeMove")
.field("index_1", &self.index_1)
.field("index_2", &self.index_2)
.finish()
}
}