use canwu_core::{ArmyId, BoundaryId, CommandId, EntityRef, EventId, PersonId, TerritoryId};
use canwu_time::SimTime;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(tag = "type", content = "id", rename_all = "snake_case")]
pub enum CauseRef {
Boundary(BoundaryId),
Command(CommandId),
Event(EventId),
System(String),
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum EventKind {
MoveOrdered {
army: ArmyId,
from: TerritoryId,
to: TerritoryId,
arrival_at: SimTime,
},
ArmyArrived {
army: ArmyId,
territory: TerritoryId,
},
ReportDispatched {
recipient: PersonId,
army: ArmyId,
arrives_at: SimTime,
},
KnowledgeUpdated {
recipient: PersonId,
army: ArmyId,
known_location: TerritoryId,
},
DebugFieldChanged {
entity: EntityRef,
field: String,
old_value: String,
new_value: String,
},
Plugin {
plugin: String,
event_type: String,
},
}
#[derive(Clone, Debug, Default, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
#[serde(tag = "type", content = "value", rename_all = "snake_case")]
pub enum EventAudience {
Public,
Actor(PersonId),
Actors(Vec<PersonId>),
AffectedActors,
#[default]
Private,
}
impl EventKind {
#[must_use]
pub const fn event_type(&self) -> &'static str {
match self {
Self::MoveOrdered { .. } => "move_ordered",
Self::ArmyArrived { .. } => "army_arrived",
Self::ReportDispatched { .. } => "report_dispatched",
Self::KnowledgeUpdated { .. } => "knowledge_updated",
Self::DebugFieldChanged { .. } => "debug_field_changed",
Self::Plugin { .. } => "plugin",
}
}
#[must_use]
pub fn qualified_event_type(&self) -> String {
match self {
Self::Plugin { plugin, event_type } => format!("{plugin}.{event_type}"),
_ => self.event_type().to_owned(),
}
}
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct SimEvent {
pub id: EventId,
pub timestamp: SimTime,
pub kind: EventKind,
pub affected_entities: Vec<EntityRef>,
pub summary: String,
pub cause: Option<CauseRef>,
pub correlation_id: u64,
}
#[cfg(test)]
mod tests {
use super::EventKind;
use canwu_core::{ArmyId, TerritoryId};
#[test]
fn qualified_event_type_preserves_legacy_labels_and_disambiguates_plugins() {
let built_in = EventKind::ArmyArrived {
army: ArmyId::new(1),
territory: TerritoryId::new(2),
};
assert_eq!(built_in.event_type(), "army_arrived");
assert_eq!(built_in.qualified_event_type(), "army_arrived");
let supply = EventKind::Plugin {
plugin: "example-supply".to_owned(),
event_type: "grain_allocated".to_owned(),
};
let demand = EventKind::Plugin {
plugin: "example-demand".to_owned(),
event_type: "grain_allocated".to_owned(),
};
assert_eq!(supply.event_type(), "plugin");
assert_eq!(
supply.qualified_event_type(),
"example-supply.grain_allocated"
);
assert_eq!(
demand.qualified_event_type(),
"example-demand.grain_allocated"
);
assert_ne!(supply.qualified_event_type(), demand.qualified_event_type());
}
}