jpreprocess_jpcommon/feature/
builder.rs1use 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 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}