jpreprocess_jpcommon/label/
utterance.rs

1use jpreprocess_njd::NJDNode;
2
3use crate::limit::Limit;
4
5use super::*;
6
7#[derive(Clone, Debug)]
8pub struct Utterance {
9    pub breath_groups: Vec<BreathGroup>,
10}
11
12impl Utterance {
13    pub fn to_k(&self) -> jlabel::Utterance {
14        jlabel::Utterance {
15            breath_group_count: Limit::S.ulimit(self.breath_groups.len()),
16            accent_phrase_count: Limit::M.ulimit(self.count_accent_phrase()),
17            mora_count: Limit::LL.ulimit(self.count_mora()),
18        }
19    }
20
21    pub fn count_accent_phrase(&self) -> usize {
22        self.breath_groups
23            .iter()
24            .map(|bg| bg.count_accent_phrase())
25            .sum()
26    }
27    pub fn count_mora(&self) -> usize {
28        self.breath_groups.iter().map(|bg| bg.count_mora()).sum()
29    }
30}
31
32impl From<&[NJDNode]> for Utterance {
33    fn from(nodes: &[NJDNode]) -> Self {
34        let mut breath_groups: Vec<BreathGroup> = Vec::new();
35        let mut accent_phrases: Vec<AccentPhrase> = Vec::with_capacity(nodes.len());
36
37        for node in nodes {
38            if node.get_pron().is_question() {
39                if let Some(accent_phrase) = accent_phrases.last_mut() {
40                    accent_phrase.set_interrogative();
41                } else {
42                    eprintln!("WARN: First mora should not be question flag.");
43                }
44            }
45            if node.get_pron().is_touten() || node.get_pron().is_question() {
46                if !accent_phrases.is_empty() {
47                    breath_groups.push(BreathGroup::new(accent_phrases));
48                }
49                accent_phrases = Vec::new();
50                continue;
51            }
52
53            if matches!(node.get_chain_flag(), Some(true)) {
54                if let Some(accent_phrase) = accent_phrases.last_mut() {
55                    accent_phrase.push_node(node);
56                } else {
57                    accent_phrases.push(AccentPhrase::new(node));
58                    eprintln!("WARN: First mora cannot be chained.");
59                }
60            } else {
61                accent_phrases.push(AccentPhrase::new(node));
62            }
63        }
64        if !accent_phrases.is_empty() {
65            breath_groups.push(BreathGroup::new(accent_phrases));
66        }
67
68        Self { breath_groups }
69    }
70}
71
72#[cfg(test)]
73mod tests {
74    use crate::Utterance;
75
76    #[test]
77    fn test_send() {
78        fn assert_send<T: Send>() {}
79        assert_send::<Utterance>();
80    }
81
82    #[test]
83    fn test_sync() {
84        fn assert_sync<T: Sync>() {}
85        assert_sync::<Utterance>();
86    }
87}