use crate::types::EntityId;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum AttributionType {
Ability,
Benevolence,
Integrity,
#[default]
Unknown,
}
impl AttributionType {
#[must_use]
pub const fn name(&self) -> &'static str {
match self {
AttributionType::Ability => "Ability",
AttributionType::Benevolence => "Benevolence",
AttributionType::Integrity => "Integrity",
AttributionType::Unknown => "Unknown",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum AttributionStability {
Stable,
#[default]
Unstable,
}
impl AttributionStability {
#[must_use]
pub const fn is_stable(&self) -> bool {
matches!(self, AttributionStability::Stable)
}
#[must_use]
pub const fn is_unstable(&self) -> bool {
matches!(self, AttributionStability::Unstable)
}
#[must_use]
pub const fn name(&self) -> &'static str {
match self {
AttributionStability::Stable => "Stable",
AttributionStability::Unstable => "Unstable",
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub enum Attribution {
SelfCaused(AttributionStability),
Other(EntityId, AttributionStability),
Situational(AttributionStability),
#[default]
Unknown,
}
impl Attribution {
#[must_use]
pub const fn self_caused(stability: AttributionStability) -> Self {
Attribution::SelfCaused(stability)
}
#[must_use]
pub fn other(entity_id: EntityId, stability: AttributionStability) -> Self {
Attribution::Other(entity_id, stability)
}
#[must_use]
pub const fn situational(stability: AttributionStability) -> Self {
Attribution::Situational(stability)
}
#[must_use]
pub const fn unknown() -> Self {
Attribution::Unknown
}
#[must_use]
pub fn stability(&self) -> Option<AttributionStability> {
match self {
Attribution::SelfCaused(s) => Some(*s),
Attribution::Other(_, s) => Some(*s),
Attribution::Situational(s) => Some(*s),
Attribution::Unknown => None,
}
}
#[must_use]
pub fn is_stable(&self) -> bool {
self.stability().is_some_and(|s| s.is_stable())
}
#[must_use]
pub const fn is_self_caused(&self) -> bool {
matches!(self, Attribution::SelfCaused(_))
}
#[must_use]
pub const fn is_other(&self) -> bool {
matches!(self, Attribution::Other(_, _))
}
#[must_use]
pub const fn is_situational(&self) -> bool {
matches!(self, Attribution::Situational(_))
}
#[must_use]
pub const fn is_unknown(&self) -> bool {
matches!(self, Attribution::Unknown)
}
#[must_use]
pub fn other_entity(&self) -> Option<&EntityId> {
match self {
Attribution::Other(id, _) => Some(id),
_ => None,
}
}
#[must_use]
pub const fn type_name(&self) -> &'static str {
match self {
Attribution::SelfCaused(_) => "Self-Caused",
Attribution::Other(_, _) => "Other",
Attribution::Situational(_) => "Situational",
Attribution::Unknown => "Unknown",
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn attribution_type_variant_names() {
assert_eq!(AttributionType::Ability.name(), "Ability");
assert_eq!(AttributionType::Benevolence.name(), "Benevolence");
assert_eq!(AttributionType::Integrity.name(), "Integrity");
assert_eq!(AttributionType::Unknown.name(), "Unknown");
}
#[test]
fn attribution_type_default_is_unknown() {
assert_eq!(AttributionType::default(), AttributionType::Unknown);
}
#[test]
fn attribution_stability_is_stable() {
assert!(AttributionStability::Stable.is_stable());
assert!(!AttributionStability::Unstable.is_stable());
}
#[test]
fn attribution_stability_is_unstable() {
assert!(AttributionStability::Unstable.is_unstable());
assert!(!AttributionStability::Stable.is_unstable());
}
#[test]
fn attribution_stability_default_is_unstable() {
assert_eq!(
AttributionStability::default(),
AttributionStability::Unstable
);
}
#[test]
fn attribution_stability_names() {
assert_eq!(AttributionStability::Stable.name(), "Stable");
assert_eq!(AttributionStability::Unstable.name(), "Unstable");
}
#[test]
fn attribution_self_caused_creation() {
let attr = Attribution::self_caused(AttributionStability::Stable);
assert!(attr.is_self_caused());
assert!(attr.is_stable());
assert_eq!(attr.stability(), Some(AttributionStability::Stable));
}
#[test]
fn attribution_other_creation() {
let entity = EntityId::new("person_001").unwrap();
let attr = Attribution::other(entity.clone(), AttributionStability::Unstable);
assert!(attr.is_other());
assert!(!attr.is_stable());
assert_eq!(attr.other_entity(), Some(&entity));
}
#[test]
fn attribution_situational_creation() {
let attr = Attribution::situational(AttributionStability::Stable);
assert!(attr.is_situational());
assert!(attr.is_stable());
}
#[test]
fn attribution_unknown_creation() {
let attr = Attribution::unknown();
assert!(attr.is_unknown());
assert!(!attr.is_stable());
assert_eq!(attr.stability(), None);
}
#[test]
fn attribution_default_is_unknown() {
assert_eq!(Attribution::default(), Attribution::Unknown);
}
#[test]
fn attribution_type_names() {
let self_attr = Attribution::SelfCaused(AttributionStability::Stable);
assert_eq!(self_attr.type_name(), "Self-Caused");
let entity = EntityId::new("person").unwrap();
let other_attr = Attribution::Other(entity, AttributionStability::Unstable);
assert_eq!(other_attr.type_name(), "Other");
let situational = Attribution::Situational(AttributionStability::Stable);
assert_eq!(situational.type_name(), "Situational");
let unknown = Attribution::Unknown;
assert_eq!(unknown.type_name(), "Unknown");
}
#[test]
fn attribution_other_entity_none_for_non_other() {
let self_attr = Attribution::SelfCaused(AttributionStability::Stable);
assert!(self_attr.other_entity().is_none());
let situational = Attribution::Situational(AttributionStability::Stable);
assert!(situational.other_entity().is_none());
let unknown = Attribution::Unknown;
assert!(unknown.other_entity().is_none());
}
#[test]
fn attribution_is_predicates() {
let self_attr = Attribution::SelfCaused(AttributionStability::Stable);
assert!(self_attr.is_self_caused());
assert!(!self_attr.is_other());
assert!(!self_attr.is_situational());
assert!(!self_attr.is_unknown());
let entity = EntityId::new("person").unwrap();
let other_attr = Attribution::Other(entity, AttributionStability::Unstable);
assert!(!other_attr.is_self_caused());
assert!(other_attr.is_other());
assert!(!other_attr.is_situational());
assert!(!other_attr.is_unknown());
}
#[test]
fn attribution_stability_is_copy() {
let s1 = AttributionStability::Stable;
let s2 = s1;
assert_eq!(s1, s2);
}
#[test]
fn attribution_clone() {
let entity = EntityId::new("person").unwrap();
let attr = Attribution::Other(entity, AttributionStability::Stable);
let cloned = attr.clone();
assert_eq!(attr, cloned);
}
#[test]
fn attribution_debug_format() {
let attr = Attribution::SelfCaused(AttributionStability::Stable);
let debug = format!("{:?}", attr);
assert!(debug.contains("SelfCaused"));
assert!(debug.contains("Stable"));
}
#[test]
fn attribution_stability_debug_format() {
let stability = AttributionStability::Stable;
let debug = format!("{:?}", stability);
assert!(debug.contains("Stable"));
}
#[test]
fn attribution_is_stable_false_for_unknown() {
let attr = Attribution::Unknown;
assert!(!attr.is_stable());
}
}