Documentation
//! 传统文献中既定的吉凶等级标签 (5 级)。
//!
//! 注意:这是格局/神煞自身在传统文献中的**固定吉凶定性**,而非由计算得出的得分。
//! 调用方仍可结合具体盘面、用神生克自行加减判断;本库不做任何动态评分。

use std::fmt::Display;
use std::fmt::Formatter;

/// 吉凶等级 (5 级)。
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Auspice {
    /// 大吉 — 极佳格局
    GreatAuspicious,
    /// 吉 — 寻常吉格
    Auspicious,
    /// 中和 — 平稳无显著吉凶。
    Neutral,
    /// 凶 — 普通凶格
    Inauspicious,
    /// 大凶 — 极差格局
    GreatInauspicious,
}

impl Auspice {
    /// 中文名称 (大吉/吉/中和/凶/大凶)。
    pub const fn name(self) -> &'static str {
        match self {
            Self::GreatAuspicious => "大吉",
            Self::Auspicious => "",
            Self::Neutral => "中和",
            Self::Inauspicious => "",
            Self::GreatInauspicious => "大凶",
        }
    }

    /// 是否为吉象 (大吉或吉)。
    pub const fn is_auspicious(self) -> bool { matches!(self, Self::GreatAuspicious | Self::Auspicious) }

    /// 是否为凶象 (大凶或凶)。
    pub const fn is_inauspicious(self) -> bool { matches!(self, Self::GreatInauspicious | Self::Inauspicious) }

    /// 是否为极端 (大吉或大凶)。
    pub const fn is_extreme(self) -> bool { matches!(self, Self::GreatAuspicious | Self::GreatInauspicious) }
}

impl Display for Auspice {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.write_str(self.name()) }
}

/// 具有"名称 / 客观描述 / 吉凶等级"三个属性的领域实体的统一接口。
///
/// 库内所有"格局/神煞/卦/长生十二宫"等领域实体都实现该 trait,
/// 调用方可以用泛型 `fn print<T: Auspicious>(t: &T)` 统一处理。
///
/// 使用前需 `use qimen::Auspicious`。
pub trait Auspicious {
    /// 中文名称。
    fn name(&self) -> &'static str;

    /// 客观一句话描述。
    fn summary(&self) -> &'static str;

    /// 传统文献既定的吉凶等级 (5 级)。
    fn auspice(&self) -> Auspice;
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn auspicious_classification() {
        assert!(Auspice::GreatAuspicious.is_auspicious());
        assert!(Auspice::Auspicious.is_auspicious());
        assert!(!Auspice::Neutral.is_auspicious());
        assert!(!Auspice::Inauspicious.is_auspicious());

        assert!(Auspice::GreatInauspicious.is_inauspicious());
        assert!(Auspice::Inauspicious.is_inauspicious());
        assert!(!Auspice::Neutral.is_inauspicious());

        assert!(Auspice::GreatAuspicious.is_extreme());
        assert!(Auspice::GreatInauspicious.is_extreme());
        assert!(!Auspice::Auspicious.is_extreme());
    }

    #[test]
    fn names() {
        assert_eq!(Auspice::GreatAuspicious.name(), "大吉");
        assert_eq!(Auspice::Inauspicious.name(), "");
    }
}