Skip to main content

egui_charts/drawings/domain/
elliott.rs

1//! The degree of an Elliott wave count.
2
3use serde::{Deserialize, Serialize};
4
5/// The degree of an Elliott wave count, which sets the notation of its labels so that counts of
6/// different degree on one chart can be told apart. From the largest degree to the smallest.
7///
8/// Corrective waves, the waves of a triangle and of combinations (A to E, W, X, Y, Z) take the
9/// letter notation of their degree.
10#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
11#[non_exhaustive]
12pub enum ElliottDegree {
13    /// Waves ((I)) to ((V)) and ((A)), ((B)), ((C)).
14    GrandSupercycle,
15    /// Waves (I) to (V) and (A), (B), (C).
16    Supercycle,
17    /// Waves I to V and A, B, C.
18    Cycle,
19    /// Waves ((1)) to ((5)) and ((A)), ((B)), ((C)).
20    Primary,
21    /// Waves (1) to (5) and (A), (B), (C).
22    Intermediate,
23    /// Waves 1 to 5 and A, B, C, the degree of a new drawing.
24    #[default]
25    Minor,
26    /// Waves ((i)) to ((v)) and ((a)), ((b)), ((c)).
27    Minute,
28    /// Waves (i) to (v) and (a), (b), (c).
29    Minuette,
30    /// Waves i to v and a, b, c.
31    Subminuette,
32}
33
34impl ElliottDegree {
35    /// Every degree, from the largest to the smallest.
36    #[cfg(feature = "ui")]
37    pub(crate) const ALL: [Self; 9] = [
38        Self::GrandSupercycle,
39        Self::Supercycle,
40        Self::Cycle,
41        Self::Primary,
42        Self::Intermediate,
43        Self::Minor,
44        Self::Minute,
45        Self::Minuette,
46        Self::Subminuette,
47    ];
48
49    /// The name of the degree, such as "Minor".
50    #[cfg(feature = "ui")]
51    pub(crate) fn name(self) -> &'static str {
52        match self {
53            Self::GrandSupercycle => "Grand Supercycle",
54            Self::Supercycle => "Supercycle",
55            Self::Cycle => "Cycle",
56            Self::Primary => "Primary",
57            Self::Intermediate => "Intermediate",
58            Self::Minor => "Minor",
59            Self::Minute => "Minute",
60            Self::Minuette => "Minuette",
61            Self::Subminuette => "Subminuette",
62        }
63    }
64
65    /// The label of `wave`, a digit `'1'` to `'5'` for a motive wave or a capital letter for a
66    /// corrective one, in this degree's notation.
67    pub(crate) fn label(self, wave: char) -> String {
68        let (open, close) = match self {
69            Self::GrandSupercycle | Self::Primary | Self::Minute => ("((", "))"),
70            Self::Supercycle | Self::Intermediate | Self::Minuette => ("(", ")"),
71            Self::Cycle | Self::Minor | Self::Subminuette => ("", ""),
72        };
73        let lower = matches!(self, Self::Minute | Self::Minuette | Self::Subminuette);
74        let numeral = wave
75            .to_digit(10)
76            .filter(|n| (1..=5).contains(n))
77            .map(|n| n as usize - 1);
78        let mut label = String::from(open);
79        match (self, numeral) {
80            (Self::GrandSupercycle | Self::Supercycle | Self::Cycle, Some(n)) => {
81                label.push_str(["I", "II", "III", "IV", "V"][n]);
82            }
83            (_, Some(n)) if lower => label.push_str(["i", "ii", "iii", "iv", "v"][n]),
84            _ if lower => label.push(wave.to_ascii_lowercase()),
85            _ => label.push(wave),
86        }
87        label.push_str(close);
88        label
89    }
90}