use super::{GameState, action::Action};
use async_trait::async_trait;
use thiserror::Error;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum HistorianLock {
StatsStorageRead,
StatsStorageWrite,
VecRecords,
HandLog,
}
impl std::fmt::Display for HistorianLock {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::StatsStorageRead => write!(f, "StatsStorage read"),
Self::StatsStorageWrite => write!(f, "StatsStorage write"),
Self::VecRecords => write!(f, "VecHistorian records"),
Self::HandLog => write!(f, "HandLog tail"),
}
}
}
#[derive(Error, Debug)]
pub enum HistorianError {
#[error("Unable to record action")]
UnableToRecordAction,
#[error("IO Error: {0}")]
IOError(#[from] std::io::Error),
#[error("{lock} lock poisoned by a panicking thread")]
LockPoisoned { lock: HistorianLock },
#[cfg(any(test, feature = "serde"))]
#[error("JSON Error: {0}")]
JSONError(#[from] serde_json::Error),
#[error("Unexpected CFR Node: {0}")]
CFRUnexpectedNode(String),
#[error("Expected Node not found in tree")]
CFRNodeNotFound,
#[cfg(all(feature = "open-hand-history", feature = "arena"))]
#[error("OHH Conversion Error: {0}")]
OHHConversion(#[from] crate::arena::errors::OHHConversionError),
}
#[async_trait]
pub trait Historian: Send {
async fn record_action(
&mut self,
id: u128,
game_state: &GameState,
action: &Action,
) -> Result<(), HistorianError>;
}
pub trait HistorianGenerator {
fn generate(&self, game_state: &GameState) -> Box<dyn Historian>;
}
pub trait CloneHistorian: Historian {
fn clone_box(&self) -> Box<dyn Historian>;
}
impl<T> CloneHistorian for T
where
T: 'static + Historian + Clone,
{
fn clone_box(&self) -> Box<dyn Historian> {
Box::new(self.clone())
}
}
pub struct CloneHistorianGenerator<T> {
historian: T,
}
impl<T> CloneHistorianGenerator<T>
where
T: CloneHistorian,
{
pub fn new(historian: T) -> Self {
CloneHistorianGenerator { historian }
}
}
impl<T> HistorianGenerator for CloneHistorianGenerator<T>
where
T: CloneHistorian,
{
fn generate(&self, _game_state: &GameState) -> Box<dyn Historian> {
self.historian.clone_box()
}
}
mod failing;
mod fn_historian;
mod null;
mod stats_tracking;
mod vec;
#[cfg(any(test, feature = "serde"))]
mod directory_historian;
#[cfg(feature = "open-hand-history")]
mod open_hand_history;
pub use failing::FailingHistorian;
pub use fn_historian::FnHistorian;
pub use null::NullHistorian;
pub use vec::HistoryRecord;
pub use vec::SharedHistoryStorage;
pub use vec::VecHistorian;
#[cfg(any(test, feature = "serde"))]
pub use directory_historian::DirectoryHistorian;
pub use stats_tracking::{SharedStatsStorage, StatsStorage, StatsTrackingHistorian};
#[cfg(feature = "open-hand-history")]
pub use open_hand_history::OpenHandHistoryHistorian;
#[cfg(feature = "open-hand-history")]
pub use open_hand_history::OpenHandHistoryVecHistorian;