1use crate::{
2 divination_method::DivinationMethod, line::Line, symbols::big_line::LINE_SPACER,
3 trigram::Trigram,
4};
5
6#[derive(Clone, Copy)]
10pub enum HexagramOrdering {
11 KingWen,
13 Binary,
15 Mawangdui,
17}
18
19pub struct Hexagram {
26 above: Trigram,
27 below: Trigram,
28}
29
30impl Hexagram {
31 pub fn new(above: Trigram, below: Trigram) -> Self {
33 Hexagram { above, below }
34 }
35
36 pub fn above(&self) -> &Trigram {
37 &self.above
38 }
39
40 pub fn below(&self) -> &Trigram {
41 &self.below
42 }
43
44 pub fn new_random(divination_method: DivinationMethod) -> Self {
46 Hexagram {
47 above: Trigram::new_random(divination_method),
48 below: Trigram::new_random(divination_method),
49 }
50 }
51
52 pub fn symbol(&self, with_changes: bool) -> &str {
55 use crate::symbols::hexagram::*;
56 use crate::trigram::TrigramName::*;
57
58 let relating_hexagram = with_changes.then(|| self.relating_hexagram()).flatten();
59 let hexagram = relating_hexagram.as_ref().unwrap_or(self);
60
61 match (hexagram.above.into(), hexagram.below.into()) {
62 (Qian, Qian) => QIAN_QIAN_SYMBOL,
63 (Qian, Kun) => QIAN_KUN_SYMBOL,
64 (Qian, Zhen) => QIAN_ZHEN_SYMBOL,
65 (Qian, Kan) => QIAN_KAN_SYMBOL,
66 (Qian, Gen) => QIAN_GEN_SYMBOL,
67 (Qian, Xun) => QIAN_XUN_SYMBOL,
68 (Qian, Li) => QIAN_LI_SYMBOL,
69 (Qian, Dui) => QIAN_DUI_SYMBOL,
70 (Kun, Qian) => KUN_QIAN_SYMBOL,
71 (Kun, Kun) => KUN_KUN_SYMBOL,
72 (Kun, Zhen) => KUN_ZHEN_SYMBOL,
73 (Kun, Kan) => KUN_KAN_SYMBOL,
74 (Kun, Gen) => KUN_GEN_SYMBOL,
75 (Kun, Xun) => KUN_XUN_SYMBOL,
76 (Kun, Li) => KUN_LI_SYMBOL,
77 (Kun, Dui) => KUN_DUI_SYMBOL,
78 (Zhen, Qian) => ZHEN_QIAN_SYMBOL,
79 (Zhen, Kun) => ZHEN_KUN_SYMBOL,
80 (Zhen, Zhen) => ZHEN_ZHEN_SYMBOL,
81 (Zhen, Kan) => ZHEN_KAN_SYMBOL,
82 (Zhen, Gen) => ZHEN_GEN_SYMBOL,
83 (Zhen, Xun) => ZHEN_XUN_SYMBOL,
84 (Zhen, Li) => ZHEN_LI_SYMBOL,
85 (Zhen, Dui) => ZHEN_DUI_SYMBOL,
86 (Kan, Qian) => KAN_QIAN_SYMBOL,
87 (Kan, Kun) => KAN_KUN_SYMBOL,
88 (Kan, Zhen) => KAN_ZHEN_SYMBOL,
89 (Kan, Kan) => KAN_KAN_SYMBOL,
90 (Kan, Gen) => KAN_GEN_SYMBOL,
91 (Kan, Xun) => KAN_XUN_SYMBOL,
92 (Kan, Li) => KAN_LI_SYMBOL,
93 (Kan, Dui) => KAN_DUI_SYMBOL,
94 (Gen, Qian) => GEN_QIAN_SYMBOL,
95 (Gen, Kun) => GEN_KUN_SYMBOL,
96 (Gen, Zhen) => GEN_ZHEN_SYMBOL,
97 (Gen, Kan) => GEN_KAN_SYMBOL,
98 (Gen, Gen) => GEN_GEN_SYMBOL,
99 (Gen, Xun) => GEN_XUN_SYMBOL,
100 (Gen, Li) => GEN_LI_SYMBOL,
101 (Gen, Dui) => GEN_DUI_SYMBOL,
102 (Xun, Qian) => XUN_QIAN_SYMBOL,
103 (Xun, Kun) => XUN_KUN_SYMBOL,
104 (Xun, Zhen) => XUN_ZHEN_SYMBOL,
105 (Xun, Kan) => XUN_KAN_SYMBOL,
106 (Xun, Gen) => XUN_GEN_SYMBOL,
107 (Xun, Xun) => XUN_XUN_SYMBOL,
108 (Xun, Li) => XUN_LI_SYMBOL,
109 (Xun, Dui) => XUN_DUI_SYMBOL,
110 (Li, Qian) => LI_QIAN_SYMBOL,
111 (Li, Kun) => LI_KUN_SYMBOL,
112 (Li, Zhen) => LI_ZHEN_SYMBOL,
113 (Li, Kan) => LI_KAN_SYMBOL,
114 (Li, Gen) => LI_GEN_SYMBOL,
115 (Li, Xun) => LI_XUN_SYMBOL,
116 (Li, Li) => LI_LI_SYMBOL,
117 (Li, Dui) => LI_DUI_SYMBOL,
118 (Dui, Qian) => DUI_QIAN_SYMBOL,
119 (Dui, Kun) => DUI_KUN_SYMBOL,
120 (Dui, Zhen) => DUI_ZHEN_SYMBOL,
121 (Dui, Kan) => DUI_KAN_SYMBOL,
122 (Dui, Gen) => DUI_GEN_SYMBOL,
123 (Dui, Xun) => DUI_XUN_SYMBOL,
124 (Dui, Li) => DUI_LI_SYMBOL,
125 (Dui, Dui) => DUI_DUI_SYMBOL,
126 }
127 }
128
129 pub fn get_changing_line_positions(&self) -> Vec<usize> {
131 self.lines()
132 .enumerate()
133 .filter_map(|(index, &line)| {
134 if matches!(line, Line::Broken { changing: true })
135 || matches!(line, Line::Unbroken { changing: true })
136 {
137 Some(index + 1)
138 } else {
139 None
140 }
141 })
142 .collect()
143 }
144
145 pub fn lines(&self) -> impl Iterator<Item = &Line> {
147 self.above.lines().chain(self.below.lines())
148 }
149
150 pub fn print_big(&self) {
152 print!("{LINE_SPACER}");
153 self.above.print_big();
154 self.below.print_big();
155 }
156
157 pub fn relating_hexagram(&self) -> Option<Self> {
160 let Hexagram { above, below } = self;
161 let Trigram(a1, a2, a3) = above;
162 let Trigram(b1, b2, b3) = below;
163 let lines_are_changing = [a1, a2, a3, b1, b2, b3]
164 .iter()
165 .any(|line| line.is_changing());
166
167 if lines_are_changing {
168 Some(Hexagram::new(
169 Trigram(a1.settle(), a2.settle(), a3.settle()),
170 Trigram(b1.settle(), b2.settle(), b3.settle()),
171 ))
172 } else {
173 None
174 }
175 }
176}