use serde::{Deserialize, Serialize};
use std::any::Any;
use weasel::{
battle_rules, battle_rules_with_user, rules::empty::*, Battle, BattleRules, Event, EventKind,
EventProcessor, EventQueue, EventTrigger, UserEventPacker, UserRules, WeaselError,
WeaselResult,
};
pub(crate) const PIZZAS_CREATED_METRIC: &str = "pizzas_created";
battle_rules_with_user! { CustomUserRules }
#[derive(Default)]
pub struct CustomUserRules {}
impl UserRules<CustomRules> for CustomUserRules {
type UserMetricId = String;
type UserEventPackage = EventPackage;
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct MakePizza {
name: String,
}
impl MakePizza {
pub(crate) fn trigger<P: EventProcessor<CustomRules>>(
processor: &mut P,
name: String,
) -> MakePizzaTrigger<P> {
MakePizzaTrigger { processor, name }
}
}
impl Event<CustomRules> for MakePizza {
fn verify(&self, _battle: &Battle<CustomRules>) -> WeaselResult<(), CustomRules> {
Ok(())
}
fn apply(
&self,
battle: &mut Battle<CustomRules>,
_event_queue: &mut Option<EventQueue<CustomRules>>,
) {
let mut writer = battle.metrics_mut();
writer
.add_user_u64(PIZZAS_CREATED_METRIC.to_string(), 1)
.unwrap();
}
fn kind(&self) -> EventKind {
EventKind::UserEvent(0)
}
fn box_clone(&self) -> Box<dyn Event<CustomRules> + Send> {
Box::new(self.clone())
}
fn as_any(&self) -> &dyn Any {
self
}
}
pub(crate) struct MakePizzaTrigger<'a, P>
where
P: EventProcessor<CustomRules>,
{
processor: &'a mut P,
name: String,
}
impl<'a, P> EventTrigger<'a, CustomRules, P> for MakePizzaTrigger<'a, P>
where
P: EventProcessor<CustomRules>,
{
fn processor(&'a mut self) -> &'a mut P {
self.processor
}
fn event(&self) -> Box<dyn Event<CustomRules> + Send> {
Box::new(MakePizza {
name: self.name.clone(),
})
}
}
#[derive(Serialize, Deserialize)]
pub(crate) enum EventPackage {
MakePizza(MakePizza),
}
impl UserEventPacker<CustomRules> for EventPackage {
fn boxed(self) -> WeaselResult<Box<dyn Event<CustomRules> + Send>, CustomRules> {
let event = match self {
Self::MakePizza(event) => Box::new(event) as Box<dyn Event<CustomRules> + Send>,
};
Ok(event)
}
fn flattened(event: Box<dyn Event<CustomRules> + Send>) -> WeaselResult<Self, CustomRules> {
match event.as_any().downcast_ref::<MakePizza>() {
Some(event) => Ok(Self::MakePizza(event.clone())),
None => Err(WeaselError::UserEventPackingError(
event.clone(),
"bad cast".into(),
)),
}
}
}