use std::fmt::Debug;
use std::sync::{Arc, Mutex};
use solverforge_core::domain::PlanningSolution;
use solverforge_scoring::Director;
use super::entity::{EntityReference, EntitySelector};
#[derive(Debug, Default, Clone, Copy)]
struct MimicState {
has_next_recorded: bool,
has_next: bool,
next_recorded: bool,
recorded_entity: Option<EntityReference>,
}
#[derive(Clone)]
pub struct MimicRecorder {
shared: Arc<Mutex<MimicState>>,
id: String,
}
impl MimicRecorder {
pub fn new(id: impl Into<String>) -> Self {
Self {
shared: Arc::new(Mutex::new(MimicState::default())),
id: id.into(),
}
}
fn record_has_next(&self, has_next: bool) {
*self.shared.lock().unwrap() = MimicState {
has_next_recorded: true,
has_next,
next_recorded: false,
recorded_entity: None,
};
}
fn record_next(&self, entity: EntityReference) {
*self.shared.lock().unwrap() = MimicState {
has_next_recorded: true,
has_next: true,
next_recorded: true,
recorded_entity: Some(entity),
};
}
pub fn get_has_next(&self) -> Option<bool> {
let state = self.shared.lock().unwrap();
if state.has_next_recorded {
Some(state.has_next)
} else {
None
}
}
pub fn get_recorded_entity(&self) -> Option<EntityReference> {
let state = self.shared.lock().unwrap();
if state.next_recorded {
state.recorded_entity
} else {
None
}
}
pub fn id(&self) -> &str {
&self.id
}
pub fn reset(&self) {
*self.shared.lock().unwrap() = MimicState::default();
}
}
impl Debug for MimicRecorder {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("MimicRecorder")
.field("id", &self.id)
.field("state", &*self.shared.lock().unwrap())
.finish()
}
}
pub struct MimicRecordingEntitySelector<S, ES> {
child: ES,
recorder: MimicRecorder,
_phantom: std::marker::PhantomData<fn() -> S>,
}
impl<S, ES> MimicRecordingEntitySelector<S, ES> {
pub fn new(child: ES, recorder: MimicRecorder) -> Self {
Self {
child,
recorder,
_phantom: std::marker::PhantomData,
}
}
pub fn recorder(&self) -> MimicRecorder {
self.recorder.clone()
}
}
impl<S: PlanningSolution, ES: Debug> Debug for MimicRecordingEntitySelector<S, ES> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("MimicRecordingEntitySelector")
.field("child", &self.child)
.field("recorder_id", &self.recorder.id)
.finish()
}
}
impl<S, ES> EntitySelector<S> for MimicRecordingEntitySelector<S, ES>
where
S: PlanningSolution,
ES: EntitySelector<S>,
{
fn iter<'a, D: Director<S>>(
&'a self,
score_director: &D,
) -> impl Iterator<Item = EntityReference> + 'a {
self.recorder.reset();
let child_iter = self.child.iter(score_director);
RecordingIterator {
inner: child_iter,
recorder: &self.recorder,
}
}
fn size<D: Director<S>>(&self, score_director: &D) -> usize {
self.child.size(score_director)
}
fn is_never_ending(&self) -> bool {
self.child.is_never_ending()
}
}
struct RecordingIterator<'a, I> {
inner: I,
recorder: &'a MimicRecorder,
}
impl<'a, I: Iterator<Item = EntityReference>> Iterator for RecordingIterator<'a, I> {
type Item = EntityReference;
fn next(&mut self) -> Option<Self::Item> {
let next = self.inner.next();
match next {
Some(entity) => {
self.recorder.record_next(entity);
Some(entity)
}
None => {
self.recorder.record_has_next(false);
None
}
}
}
}
pub struct MimicReplayingEntitySelector {
recorder: MimicRecorder,
}
impl MimicReplayingEntitySelector {
pub fn new(recorder: MimicRecorder) -> Self {
Self { recorder }
}
}
impl Debug for MimicReplayingEntitySelector {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("MimicReplayingEntitySelector")
.field("recorder_id", &self.recorder.id)
.finish()
}
}
impl<S: PlanningSolution> EntitySelector<S> for MimicReplayingEntitySelector {
fn iter<'a, D: Director<S>>(
&'a self,
_score_director: &D,
) -> impl Iterator<Item = EntityReference> + 'a {
ReplayingIterator {
recorder: &self.recorder,
returned: false,
}
}
fn size<D: Director<S>>(&self, _score_director: &D) -> usize {
if self.recorder.get_recorded_entity().is_some() {
1
} else {
0
}
}
fn is_never_ending(&self) -> bool {
false
}
}
struct ReplayingIterator<'a> {
recorder: &'a MimicRecorder,
returned: bool,
}
impl<'a> Iterator for ReplayingIterator<'a> {
type Item = EntityReference;
fn next(&mut self) -> Option<Self::Item> {
if self.returned {
return None;
}
match self.recorder.get_recorded_entity() {
Some(entity) => {
self.returned = true;
Some(entity)
}
None => {
match self.recorder.get_has_next() {
Some(false) => None, Some(true) => panic!(
"MimicReplayingEntitySelector: Recording selector's hasNext() was true \
but next() was never called. Ensure the recording selector's iterator \
is advanced before using the replaying selector."
),
None => panic!(
"MimicReplayingEntitySelector: No recording found. \
The recording selector must be iterated before the replaying selector."
),
}
}
}
}
}