use std::fmt;
#[derive(Debug, Clone)]
pub struct TraceEntry<E: Clone> {
pub turn: u32,
pub source: TraceSource<E>,
pub effect: E,
}
#[derive(Debug, Clone)]
pub enum TraceSource<E: Clone> {
Rule { name: &'static str },
Reaction { name: &'static str, trigger: Box<E> },
}
#[derive(Clone)]
pub struct Trace<E: Clone + PartialEq> {
pub entries: Vec<TraceEntry<E>>,
pub enabled: bool,
}
impl<E: Clone + PartialEq> Default for Trace<E> {
fn default() -> Self {
Self {
entries: Vec::new(),
enabled: false,
}
}
}
impl<E: Clone + PartialEq> Trace<E> {
pub fn record(&mut self, effect: &E, source: TraceSource<E>, turn: u32) {
if self.enabled {
self.entries.push(TraceEntry {
turn,
source,
effect: effect.clone(),
});
}
}
pub fn contains(&self, effect: &E) -> bool {
self.entries.iter().any(|e| &e.effect == effect)
}
pub fn from_rule(&self, name: &str) -> Vec<&E> {
self.entries
.iter()
.filter(|e| matches!(&e.source, TraceSource::Rule { name: n } if *n == name))
.map(|e| &e.effect)
.collect()
}
pub fn effects_matching<F>(&self, predicate: F) -> Vec<&E>
where
F: Fn(&E) -> bool,
{
self.entries
.iter()
.filter(|e| predicate(&e.effect))
.map(|e| &e.effect)
.collect()
}
}
impl<E: Clone + PartialEq + fmt::Debug> fmt::Debug for Trace<E> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Trace")
.field("enabled", &self.enabled)
.field("entries", &self.entries.len())
.finish()
}
}
impl<E: Clone + PartialEq + fmt::Debug> fmt::Display for Trace<E> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for entry in &self.entries {
writeln!(
f,
" Turn {}: [{:?}] {:?}",
entry.turn, entry.source, entry.effect
)?;
}
Ok(())
}
}
#[derive(Debug, Clone)]
pub struct RuleOutput<E, P> {
pub effects: Vec<E>,
pub presentation: Vec<P>,
}
impl<E, P> Default for RuleOutput<E, P> {
fn default() -> Self {
Self {
effects: Vec::new(),
presentation: Vec::new(),
}
}
}