jpreprocess_jpcommon/feature/
builder.rs

1use std::rc::Rc;
2
3use jlabel::{
4    AccentPhraseCurrent, AccentPhrasePrevNext, BreathGroupCurrent, BreathGroupPrevNext, Label,
5    Mora, Phoneme, Utterance, Word,
6};
7
8pub struct FeatureBuilderUtterance {
9    k: Utterance,
10}
11
12impl FeatureBuilderUtterance {
13    pub fn new(k: Utterance) -> Rc<Self> {
14        Rc::new(Self { k })
15    }
16}
17
18pub trait TFeatureBuilderUtterance {
19    fn with_hij(
20        &self,
21        h: Option<BreathGroupPrevNext>,
22        i: BreathGroupCurrent,
23        j: Option<BreathGroupPrevNext>,
24    ) -> Rc<FeatureBuilderBreathGroup>;
25    fn with_hj(
26        &self,
27        h: Option<BreathGroupPrevNext>,
28        j: Option<BreathGroupPrevNext>,
29    ) -> Rc<FeatureBuilderBreathGroup>;
30}
31
32impl TFeatureBuilderUtterance for Rc<FeatureBuilderUtterance> {
33    fn with_hij(
34        &self,
35        h: Option<BreathGroupPrevNext>,
36        i: BreathGroupCurrent,
37        j: Option<BreathGroupPrevNext>,
38    ) -> Rc<FeatureBuilderBreathGroup> {
39        Rc::new(FeatureBuilderBreathGroup {
40            utterance: self.clone(),
41            h,
42            i: Some(i),
43            j,
44        })
45    }
46    fn with_hj(
47        &self,
48        h: Option<BreathGroupPrevNext>,
49        j: Option<BreathGroupPrevNext>,
50    ) -> Rc<FeatureBuilderBreathGroup> {
51        Rc::new(FeatureBuilderBreathGroup {
52            utterance: self.clone(),
53            h,
54            i: None,
55            j,
56        })
57    }
58}
59
60pub struct FeatureBuilderBreathGroup {
61    utterance: Rc<FeatureBuilderUtterance>,
62    h: Option<BreathGroupPrevNext>,
63    i: Option<BreathGroupCurrent>,
64    j: Option<BreathGroupPrevNext>,
65}
66
67pub trait TFeatureBuilderBreathGroup {
68    fn with_efg(
69        &self,
70        e: Option<AccentPhrasePrevNext>,
71        f: AccentPhraseCurrent,
72        g: Option<AccentPhrasePrevNext>,
73    ) -> Rc<FeatureBuilderAccentPhrase>;
74    fn with_eg(
75        &self,
76        e: Option<AccentPhrasePrevNext>,
77        g: Option<AccentPhrasePrevNext>,
78    ) -> Rc<FeatureBuilderAccentPhrase>;
79}
80
81impl TFeatureBuilderBreathGroup for Rc<FeatureBuilderBreathGroup> {
82    fn with_efg(
83        &self,
84        e: Option<AccentPhrasePrevNext>,
85        f: AccentPhraseCurrent,
86        g: Option<AccentPhrasePrevNext>,
87    ) -> Rc<FeatureBuilderAccentPhrase> {
88        Rc::new(FeatureBuilderAccentPhrase {
89            breath_group: self.clone(),
90            e,
91            f: Some(f),
92            g,
93        })
94    }
95    fn with_eg(
96        &self,
97        e: Option<AccentPhrasePrevNext>,
98        g: Option<AccentPhrasePrevNext>,
99    ) -> Rc<FeatureBuilderAccentPhrase> {
100        Rc::new(FeatureBuilderAccentPhrase {
101            breath_group: self.clone(),
102            e,
103            f: None,
104            g,
105        })
106    }
107}
108
109pub struct FeatureBuilderAccentPhrase {
110    breath_group: Rc<FeatureBuilderBreathGroup>,
111    e: Option<AccentPhrasePrevNext>,
112    f: Option<AccentPhraseCurrent>,
113    g: Option<AccentPhrasePrevNext>,
114}
115
116pub trait TFeatureBuilderAccentPhrase {
117    fn with_bcd(&self, b: Option<Word>, c: Word, d: Option<Word>) -> Rc<FeatureBuilderWord>;
118    fn with_bd(&self, b: Option<Word>, d: Option<Word>) -> Rc<FeatureBuilderWord>;
119}
120
121impl TFeatureBuilderAccentPhrase for Rc<FeatureBuilderAccentPhrase> {
122    fn with_bcd(&self, b: Option<Word>, c: Word, d: Option<Word>) -> Rc<FeatureBuilderWord> {
123        Rc::new(FeatureBuilderWord {
124            accent_phrase: self.clone(),
125            b,
126            c: Some(c),
127            d,
128        })
129    }
130    fn with_bd(&self, b: Option<Word>, d: Option<Word>) -> Rc<FeatureBuilderWord> {
131        Rc::new(FeatureBuilderWord {
132            accent_phrase: self.clone(),
133            b,
134            c: None,
135            d,
136        })
137    }
138}
139
140pub struct FeatureBuilderWord {
141    accent_phrase: Rc<FeatureBuilderAccentPhrase>,
142    b: Option<Word>,
143    c: Option<Word>,
144    d: Option<Word>,
145}
146
147pub trait TFeatureBuilderWord {
148    fn with_a(&self, a: Mora) -> FeatureBuilder;
149    fn without_a(&self) -> FeatureBuilder;
150}
151
152impl TFeatureBuilderWord for Rc<FeatureBuilderWord> {
153    fn with_a(&self, a: Mora) -> FeatureBuilder {
154        FeatureBuilder {
155            word: self.clone(),
156            a: Some(a),
157            is_b_valid: true,
158            is_d_valid: true,
159        }
160    }
161    fn without_a(&self) -> FeatureBuilder {
162        FeatureBuilder {
163            word: self.clone(),
164            a: None,
165            is_b_valid: true,
166            is_d_valid: true,
167        }
168    }
169}
170
171#[derive(Clone)]
172pub struct FeatureBuilder {
173    word: Rc<FeatureBuilderWord>,
174    a: Option<Mora>,
175    is_b_valid: bool,
176    is_d_valid: bool,
177}
178
179impl FeatureBuilder {
180    /* for first and last silence */
181    pub fn ignore_b(&mut self) {
182        self.is_b_valid = false;
183    }
184    pub fn ignore_d(&mut self) {
185        self.is_d_valid = false;
186    }
187
188    pub fn build(&self, phoneme: Phoneme) -> Label {
189        Label {
190            phoneme,
191            mora: self.a.clone(),
192            word_prev: self.is_b_valid.then_some(()).and(self.word.b.clone()),
193            word_curr: self.word.c.clone(),
194            word_next: self.is_d_valid.then_some(()).and(self.word.d.clone()),
195            accent_phrase_prev: self.word.accent_phrase.e.clone(),
196            accent_phrase_curr: self.word.accent_phrase.f.clone(),
197            accent_phrase_next: self.word.accent_phrase.g.clone(),
198            breath_group_prev: self.word.accent_phrase.breath_group.h.clone(),
199            breath_group_curr: self.word.accent_phrase.breath_group.i.clone(),
200            breath_group_next: self.word.accent_phrase.breath_group.j.clone(),
201            utterance: self.word.accent_phrase.breath_group.utterance.k.clone(),
202        }
203    }
204
205    #[cfg(test)]
206    pub fn dummy() -> Self {
207        let utterance = FeatureBuilderUtterance::new(Utterance {
208            breath_group_count: 0,
209            accent_phrase_count: 0,
210            mora_count: 0,
211        });
212        let breath_group = utterance.with_hj(None, None);
213        let accent_phrase = breath_group.with_eg(None, None);
214        let word = accent_phrase.with_bd(None, None);
215        word.without_a()
216    }
217
218    #[cfg(test)]
219    pub fn to_string_without_phoneme(&self) -> String {
220        let phoneme = Phoneme {
221            p2: None,
222            p1: None,
223            c: None,
224            n1: None,
225            n2: None,
226        };
227        let label = self.build(phoneme).to_string();
228        let (_, feature) = label.split_at(14);
229        feature.to_string()
230    }
231}