tawasuyu

tawasuyu/brahman

Rust 326TOML 123JSON 17Markdown 144606 Sutichaykuna

⎇ d3649bfd1a80153652c2a028315369bb4b184024 crates/modules/tahuantinsuyu/tahuantinsuyu-engine/src/dignity.rs Rust · 141 siq'ikuna · 4.8 KB Ñawpa willay Pi imata llamkarqan ch'uya

feat(tahuantinsuyu): fase 18 — aspect list + hover tooltips + dignidades + export SVG 2cd34c82d · sergio ·

1//! Dignidades esenciales clásicas — tabla data-only.
2//!
3//! Cada planeta tradicional tiene cuatro estatus posibles según el
4//! signo en el que cae:
5//!
6//! - **Domicilio** (rulership) — el signo del que es regente.
7//! - **Exaltación** — un signo "huésped" que le da fuerza extra.
8//! - **Exilio** (detriment) — opuesto al domicilio, debilita.
9//! - **Caída** (fall) — opuesto a la exaltación, debilita.
10//!
11//! Esta tabla usa las regencias **clásicas** (Aries=Marte, Escorpio=
12//! Marte, Acuario=Saturno, Piscis=Júpiter) — los planetas modernos
13//! (Urano/Neptuno/Plutón) no tienen regencia clásica por convención.
14//! En una fase futura podemos exponer un toggle "regencias modernas"
15//! que mapee Escorpio→Plutón, Acuario→Urano, Piscis→Neptuno.
16
17use eternal_sky::Body;
18
19/// Status de dignidad esencial de un cuerpo en un signo dado.
20#[derive(Debug, Clone, Copy, PartialEq, Eq)]
21pub enum Dignity {
22    /// Domicilio. Marker `"+"`.
23    Rulership,
24    /// Exaltación. Marker `"·"`.
25    Exaltation,
26    /// Exilio. Marker `"−"`.
27    Detriment,
28    /// Caída. Marker `"*"`.
29    Fall,
30}
31
32impl Dignity {
33    pub fn marker(self) -> &'static str {
34        match self {
35            Dignity::Rulership => "+",
36            Dignity::Exaltation => "·",
37            Dignity::Detriment => "−",
38            Dignity::Fall => "*",
39        }
40    }
41}
42
43/// Devuelve el status de dignidad de `body` en `sign_index` (0..12,
44/// Aries=0) o `None` si no aplica (sin dignidad / cuerpo moderno sin
45/// regencia clásica).
46pub fn essential_dignity(body: Body, sign_index: u8) -> Option<Dignity> {
47    let sign = sign_index % 12;
48    let opposite = (sign + 6) % 12;
49
50    // Rulership clásico — el "regente" del signo.
51    if rules_classical(body, sign) {
52        return Some(Dignity::Rulership);
53    }
54    // Detriment = el cuerpo gobierna el signo opuesto.
55    if rules_classical(body, opposite) {
56        return Some(Dignity::Detriment);
57    }
58    // Exaltación tabular.
59    if exalts_at(body) == Some(sign) {
60        return Some(Dignity::Exaltation);
61    }
62    // Caída = opuesto a la exaltación.
63    if exalts_at(body) == Some(opposite) {
64        return Some(Dignity::Fall);
65    }
66    None
67}
68
69/// Devuelve true si `body` gobierna `sign` (0=Aries..11=Pisces) en el
70/// esquema clásico de 7 planetas.
71fn rules_classical(body: Body, sign: u8) -> bool {
72    match (body, sign) {
73        // Sol: Leo (4)
74        (Body::Sun, 4) => true,
75        // Luna: Cancer (3)
76        (Body::Moon, 3) => true,
77        // Mercurio: Gemini (2), Virgo (5)
78        (Body::Mercury, 2) | (Body::Mercury, 5) => true,
79        // Venus: Taurus (1), Libra (6)
80        (Body::Venus, 1) | (Body::Venus, 6) => true,
81        // Marte: Aries (0), Scorpio (7)
82        (Body::Mars, 0) | (Body::Mars, 7) => true,
83        // Júpiter: Sagittarius (8), Pisces (11)
84        (Body::Jupiter, 8) | (Body::Jupiter, 11) => true,
85        // Saturno: Capricorn (9), Aquarius (10)
86        (Body::Saturn, 9) | (Body::Saturn, 10) => true,
87        _ => false,
88    }
89}
90
91/// Devuelve el signo (0..12) donde el cuerpo exalta, o `None` si no
92/// tiene exaltación clásica documentada.
93fn exalts_at(body: Body) -> Option<u8> {
94    Some(match body {
95        Body::Sun => 0,       // Aries
96        Body::Moon => 1,      // Taurus
97        Body::Mercury => 5,   // Virgo (algunas tradiciones la ponen acá)
98        Body::Venus => 11,    // Pisces
99        Body::Mars => 9,      // Capricorn
100        Body::Jupiter => 3,   // Cancer
101        Body::Saturn => 6,    // Libra
102        _ => return None,
103    })
104}
105
106#[cfg(test)]
107mod tests {
108    use super::*;
109
110    #[test]
111    fn rulership_examples() {
112        assert_eq!(essential_dignity(Body::Sun, 4), Some(Dignity::Rulership)); // Sol en Leo
113        assert_eq!(essential_dignity(Body::Moon, 3), Some(Dignity::Rulership)); // Luna en Cancer
114        assert_eq!(essential_dignity(Body::Mars, 7), Some(Dignity::Rulership)); // Marte en Scorpio
115    }
116
117    #[test]
118    fn detriment_examples() {
119        assert_eq!(essential_dignity(Body::Sun, 10), Some(Dignity::Detriment)); // Sol en Acuario
120        assert_eq!(essential_dignity(Body::Moon, 9), Some(Dignity::Detriment)); // Luna en Capricornio
121    }
122
123    #[test]
124    fn exaltation_examples() {
125        assert_eq!(essential_dignity(Body::Sun, 0), Some(Dignity::Exaltation)); // Sol en Aries
126        assert_eq!(essential_dignity(Body::Saturn, 6), Some(Dignity::Exaltation)); // Saturno en Libra
127    }
128
129    #[test]
130    fn fall_examples() {
131        assert_eq!(essential_dignity(Body::Sun, 6), Some(Dignity::Fall)); // Sol en Libra
132        assert_eq!(essential_dignity(Body::Saturn, 0), Some(Dignity::Fall)); // Saturno en Aries
133    }
134
135    #[test]
136    fn modern_planets_no_classical_dignity() {
137        assert_eq!(essential_dignity(Body::Uranus, 10), None);
138        assert_eq!(essential_dignity(Body::Neptune, 11), None);
139        assert_eq!(essential_dignity(Body::Pluto, 7), None);
140    }
141}