diff --git a/src/fullcontext_label.rs b/src/fullcontext_label.rs index a5451d8..1cad631 100644 --- a/src/fullcontext_label.rs +++ b/src/fullcontext_label.rs @@ -1,11 +1,3 @@ -use crate::{ - question::position::{ - BooleanPosition, CategoryPosition, PhonePosition, SignedRangePosition, - UnsignedRangePosition, - }, - question::AllQuestion, -}; - #[derive(Debug, Clone, PartialEq, Eq)] pub struct Label { pub phoneme: Phoneme, @@ -22,174 +14,6 @@ pub struct Label { pub utterance: Utterance, } -impl Label { - pub fn satisfies(&self, question: &AllQuestion) -> bool { - use AllQuestion::*; - match question { - Phone(question) => { - use PhonePosition::*; - match question.position { - P1 => question.test(&self.phoneme.p1), - P2 => question.test(&self.phoneme.p2), - P3 => question.test(&self.phoneme.c), - P4 => question.test(&self.phoneme.n1), - P5 => question.test(&self.phoneme.n2), - } - } - SignedRange(question) => { - use SignedRangePosition::*; - match question.position { - A1 => question.test(&self.mora.as_ref().map(|m| m.relative_accent_position)), - } - } - UnsignedRange(question) => { - use UnsignedRangePosition::*; - match question.position { - A2 => question.test(&self.mora.as_ref().map(|m| m.position_forward)), - A3 => question.test(&self.mora.as_ref().map(|m| m.position_backward)), - E1 => question.test(&self.accent_phrase_prev.as_ref().map(|a| a.mora_count)), - E2 => { - question.test(&self.accent_phrase_prev.as_ref().map(|a| a.accent_position)) - } - F1 => question.test(&self.accent_phrase_curr.as_ref().map(|a| a.mora_count)), - F2 => { - question.test(&self.accent_phrase_curr.as_ref().map(|a| a.accent_position)) - } - F5 => question.test( - &self - .accent_phrase_curr - .as_ref() - .map(|a| a.accent_phrase_position_forward), - ), - F6 => question.test( - &self - .accent_phrase_curr - .as_ref() - .map(|a| a.accent_phrase_position_backward), - ), - F7 => question.test( - &self - .accent_phrase_curr - .as_ref() - .map(|a| a.mora_position_forward), - ), - F8 => question.test( - &self - .accent_phrase_curr - .as_ref() - .map(|a| a.mora_position_backward), - ), - G1 => question.test(&self.accent_phrase_next.as_ref().map(|a| a.mora_count)), - G2 => { - question.test(&self.accent_phrase_next.as_ref().map(|a| a.accent_position)) - } - H1 => question.test( - &self - .breath_group_prev - .as_ref() - .map(|b| b.accent_phrase_count), - ), - H2 => question.test(&self.breath_group_prev.as_ref().map(|b| b.mora_count)), - I1 => question.test( - &self - .breath_group_curr - .as_ref() - .map(|b| b.accent_phrase_count), - ), - I2 => question.test(&self.breath_group_curr.as_ref().map(|b| b.mora_count)), - I3 => question.test( - &self - .breath_group_curr - .as_ref() - .map(|b| b.breath_group_position_forward), - ), - I4 => question.test( - &self - .breath_group_curr - .as_ref() - .map(|b| b.breath_group_position_backward), - ), - I5 => question.test( - &self - .breath_group_curr - .as_ref() - .map(|b| b.accent_phrase_position_forward), - ), - I6 => question.test( - &self - .breath_group_curr - .as_ref() - .map(|b| b.accent_phrase_position_backward), - ), - I7 => question.test( - &self - .breath_group_curr - .as_ref() - .map(|b| b.mora_position_forward), - ), - I8 => question.test( - &self - .breath_group_curr - .as_ref() - .map(|b| b.mora_position_backward), - ), - J1 => question.test( - &self - .breath_group_next - .as_ref() - .map(|b| b.accent_phrase_count), - ), - J2 => question.test(&self.breath_group_next.as_ref().map(|b| b.mora_count)), - K1 => question.test(&Some(self.utterance.breath_group_count)), - K2 => question.test(&Some(self.utterance.accent_phrase_count)), - K3 => question.test(&Some(self.utterance.mora_count)), - } - } - Boolean(question) => { - use BooleanPosition::*; - match question.position { - E3 => { - question.test(&self.accent_phrase_prev.as_ref().map(|a| a.is_interrogative)) - } - E5 => question.test( - &self - .accent_phrase_prev - .as_ref() - .and_then(|a| a.is_pause_insertion), - ), - F3 => { - question.test(&self.accent_phrase_curr.as_ref().map(|a| a.is_interrogative)) - } - G3 => { - question.test(&self.accent_phrase_next.as_ref().map(|a| a.is_interrogative)) - } - G5 => question.test( - &self - .accent_phrase_next - .as_ref() - .and_then(|a| a.is_pause_insertion), - ), - } - } - Category(question) => { - use CategoryPosition::*; - match question.position { - B1 => question.test(&self.word_prev.as_ref().and_then(|w| w.pos)), - B2 => question.test(&self.word_prev.as_ref().and_then(|w| w.ctype)), - B3 => question.test(&self.word_prev.as_ref().and_then(|w| w.cform)), - C1 => question.test(&self.word_curr.as_ref().and_then(|w| w.pos)), - C2 => question.test(&self.word_curr.as_ref().and_then(|w| w.ctype)), - C3 => question.test(&self.word_curr.as_ref().and_then(|w| w.cform)), - D1 => question.test(&self.word_next.as_ref().and_then(|w| w.pos)), - D2 => question.test(&self.word_next.as_ref().and_then(|w| w.ctype)), - D3 => question.test(&self.word_next.as_ref().and_then(|w| w.cform)), - } - } - Undefined(_) => true, - } - } -} - #[derive(Debug, Clone, PartialEq, Eq)] pub struct Phoneme { pub p2: Option, @@ -286,193 +110,3 @@ pub struct Utterance { /// the number of moras in this utterance pub mora_count: u8, } - -#[cfg(test)] -mod tests { - use crate::{ - fullcontext_label::{Mora, Word}, - question::{question, AllQuestion, Question}, - Label, - }; - - use super::{Phoneme, Utterance}; - - #[test] - fn query() { - // Note: this Label is created randomly, and is invalid. - let label = Label { - phoneme: Phoneme { - p2: Some("b".to_string()), - p1: Some("o".to_string()), - c: Some("N".to_string()), - n1: Some("s".to_string()), - n2: Some("a".to_string()), - }, - mora: Some(Mora { - relative_accent_position: -6, - position_forward: 2, - position_backward: 8, - }), - word_prev: None, - word_curr: Some(Word { - pos: Some(1), - ctype: None, - cform: None, - }), - word_next: None, - accent_phrase_prev: None, - accent_phrase_curr: None, - accent_phrase_next: None, - breath_group_prev: None, - breath_group_curr: None, - breath_group_next: None, - utterance: Utterance { - breath_group_count: 3, - accent_phrase_count: 6, - mora_count: 10, - }, - }; - - assert!(!label.satisfies(&question(&["*=i/A:*"]).unwrap())); - - assert!(!label.satisfies(&question(&["*/A:-??+*", "*/A:-9+*"]).unwrap())); - assert!(label.satisfies(&question(&["*/A:-6+*"]).unwrap())); - - assert!(label.satisfies(&question(&["*+8/B:*"]).unwrap())); - - assert!(label.satisfies(&question(&["*-xx_*"]).unwrap())); - assert!(label.satisfies(&question(&["*/C:01_*"]).unwrap())); - } - - #[test] - fn all_query() { - let label = Label { - phoneme: Phoneme { - p2: None, - p1: None, - c: None, - n1: None, - n2: None, - }, - mora: None, - word_prev: None, - word_curr: None, - word_next: None, - accent_phrase_prev: None, - accent_phrase_curr: None, - accent_phrase_next: None, - breath_group_prev: None, - breath_group_curr: None, - breath_group_next: None, - utterance: Utterance { - breath_group_count: 3, - accent_phrase_count: 6, - mora_count: 10, - }, - }; - - use crate::question::position::*; - - for position in [ - PhonePosition::P1, - PhonePosition::P2, - PhonePosition::P3, - PhonePosition::P4, - PhonePosition::P5, - ] { - assert!(label.satisfies(&AllQuestion::Phone(Question { - position, - range: None, - }))); - } - - for position in [ - CategoryPosition::B1, - CategoryPosition::B2, - CategoryPosition::B3, - CategoryPosition::C1, - CategoryPosition::C2, - CategoryPosition::C3, - CategoryPosition::D1, - CategoryPosition::D2, - CategoryPosition::D3, - ] { - assert!(label.satisfies(&AllQuestion::Category(Question { - position, - range: None, - }))); - } - - assert!(label.satisfies(&AllQuestion::SignedRange(Question { - position: SignedRangePosition::A1, - range: None, - }))); - - for position in [ - UnsignedRangePosition::A2, - UnsignedRangePosition::A3, - UnsignedRangePosition::E1, - UnsignedRangePosition::E2, - UnsignedRangePosition::F1, - UnsignedRangePosition::F2, - UnsignedRangePosition::F5, - UnsignedRangePosition::F6, - UnsignedRangePosition::F7, - UnsignedRangePosition::F8, - UnsignedRangePosition::G1, - UnsignedRangePosition::G2, - UnsignedRangePosition::H1, - UnsignedRangePosition::H2, - UnsignedRangePosition::I1, - UnsignedRangePosition::I2, - UnsignedRangePosition::I3, - UnsignedRangePosition::I4, - UnsignedRangePosition::I5, - UnsignedRangePosition::I6, - UnsignedRangePosition::I7, - UnsignedRangePosition::I8, - UnsignedRangePosition::J1, - UnsignedRangePosition::J2, - ] { - assert!(label.satisfies(&AllQuestion::UnsignedRange(Question { - position: position.clone(), - range: None, - }))); - assert!(!label.satisfies(&AllQuestion::UnsignedRange(Question { - position: position.clone(), - range: Some(1..2), - }))); - } - - for position in [ - BooleanPosition::E3, - BooleanPosition::E5, - BooleanPosition::F3, - BooleanPosition::G3, - BooleanPosition::G5, - ] { - assert!(label.satisfies(&AllQuestion::Boolean(Question { - position, - range: None, - }))); - } - - assert!(label.satisfies(&AllQuestion::UnsignedRange(Question { - position: UnsignedRangePosition::K1, - range: Some(3..4), - }))); - assert!(label.satisfies(&AllQuestion::UnsignedRange(Question { - position: UnsignedRangePosition::K2, - range: Some(6..7), - }))); - assert!(label.satisfies(&AllQuestion::UnsignedRange(Question { - position: UnsignedRangePosition::K3, - range: Some(5..11), - }))); - - assert!(label.satisfies(&AllQuestion::Undefined(Question { - position: UndefinedPotision::E4, - range: None, - }))); - } -} diff --git a/src/question/mod.rs b/src/question/mod.rs index d037503..baae98c 100644 --- a/src/question/mod.rs +++ b/src/question/mod.rs @@ -7,6 +7,8 @@ use position::{ SignedRangePosition, UndefinedPotision, UnsignedRangePosition, }; +use crate::Label; + #[derive(Debug, Clone, thiserror::Error, PartialEq, Eq)] pub enum ParseError { #[error("Failed splitting")] @@ -99,6 +101,19 @@ pub enum AllQuestion { Undefined(Question), } +impl AllQuestion { + pub fn test(&self, label: &Label) -> bool { + match self { + Self::Phone(q) => q.test(label), + Self::SignedRange(q) => q.test(label), + Self::UnsignedRange(q) => q.test(label), + Self::Boolean(q) => q.test(label), + Self::Category(q) => q.test(label), + Self::Undefined(q) => q.test(label), + } + } +} + #[derive(Debug, Clone, PartialEq, Eq)] pub struct Question { pub position: P, @@ -120,8 +135,8 @@ impl Question

{ } } - pub fn test(&self, target: &Option) -> bool { - match (&self.range, target) { + pub fn test(&self, label: &Label) -> bool { + match (&self.range, self.position.get(&label)) { (Some(range), Some(target)) => self.position.test(range, target), (None, None) => true, _ => false, @@ -130,82 +145,4 @@ impl Question

{ } #[cfg(test)] -mod tests { - use crate::question::{ - position::{ - BooleanPosition, CategoryPosition, PhonePosition, SignedRangePosition, - UndefinedPotision, UnsignedRangePosition, - }, - question, AllQuestion, Question, - }; - - use super::split_pattern; - - #[test] - fn splitter() { - assert_eq!(split_pattern("a^*"), Some(("", "a", "^*"))); - assert_eq!(split_pattern("*/A:-??+*"), Some(("*/A:", "-??", "+*"))); - assert_eq!(split_pattern("*|?+*"), Some(("*|", "?", "+*"))); - assert_eq!(split_pattern("*-1"), Some(("*-", "1", ""))); - } - - #[test] - fn parse_question() { - assert_eq!( - question(&["a^*", "A^*"]).unwrap(), - AllQuestion::Phone(Question { - position: PhonePosition::P1, - range: Some(vec!["a".to_string(), "A".to_string()]) - }) - ); - assert_eq!( - question(&["*/A:-3+*"]).unwrap(), - AllQuestion::SignedRange(Question { - position: SignedRangePosition::A1, - range: Some(-3..-2) - }) - ); - assert_eq!( - question(&["*/A:-??+*", "*/A:-?+*", "*/A:?+*", "*/A:10+*", "*/A:11+*",]).unwrap(), - AllQuestion::SignedRange(Question { - position: SignedRangePosition::A1, - range: Some(-99..12) - }) - ); - assert_eq!( - question(&["*_42/I:*"]).unwrap(), - AllQuestion::UnsignedRange(Question { - position: UnsignedRangePosition::H2, - range: Some(42..43) - }) - ); - assert_eq!( - question(&["*_?/I:*", "*_1?/I:*", "*_2?/I:*", "*_30/I:*", "*_31/I:*",]).unwrap(), - AllQuestion::UnsignedRange(Question { - position: UnsignedRangePosition::H2, - range: Some(1..32) - }) - ); - assert_eq!( - question(&["*%1_*"]).unwrap(), - AllQuestion::Boolean(Question { - position: BooleanPosition::G3, - range: Some(true) - }) - ); - assert_eq!( - question(&["*/B:17-*", "*/B:20-*"]).unwrap(), - AllQuestion::Category(Question { - position: CategoryPosition::B1, - range: Some(vec![17, 20]) - }) - ); - assert_eq!( - question(&["*_xx_*"]).unwrap(), - AllQuestion::Undefined(Question { - position: UndefinedPotision::G4, - range: None - }) - ); - } -} +mod tests; diff --git a/src/question/position.rs b/src/question/position.rs index e4aa1c6..cf87427 100644 --- a/src/question/position.rs +++ b/src/question/position.rs @@ -1,5 +1,7 @@ use std::{fmt::Debug, ops::Range}; +use crate::Label; + use super::ParseError; pub fn position(prefix: &str, suffix: &str) -> Option { @@ -92,6 +94,7 @@ pub trait Position { type Range; fn range(&self, ranges: &[&str]) -> Result; + fn get<'a>(&self, label: &'a Label) -> Option<&'a Self::Target>; fn test(&self, range: &Self::Range, target: &Self::Target) -> bool; } @@ -112,6 +115,16 @@ impl Position for PhonePosition { Ok(ranges.iter().map(|s| s.to_string()).collect()) } + fn get<'a>(&self, label: &'a Label) -> Option<&'a Self::Target> { + match self { + Self::P1 => label.phoneme.p1.as_ref(), + Self::P2 => label.phoneme.p2.as_ref(), + Self::P3 => label.phoneme.c.as_ref(), + Self::P4 => label.phoneme.n1.as_ref(), + Self::P5 => label.phoneme.n2.as_ref(), + } + } + fn test(&self, range: &Self::Range, target: &Self::Target) -> bool { range.contains(target) } @@ -136,6 +149,12 @@ impl Position for SignedRangePosition { Ok(range) } + fn get<'a>(&self, label: &'a Label) -> Option<&'a Self::Target> { + match self { + Self::A1 => label.mora.as_ref().map(|m| &m.relative_accent_position), + } + } + fn test(&self, range: &Self::Range, target: &Self::Target) -> bool { range.contains(target) } @@ -213,6 +232,86 @@ impl Position for UnsignedRangePosition { Ok(range) } + fn get<'a>(&self, label: &'a Label) -> Option<&'a Self::Target> { + match self { + Self::A2 => label.mora.as_ref().map(|m| &m.position_forward), + Self::A3 => label.mora.as_ref().map(|m| &m.position_backward), + Self::E1 => label.accent_phrase_prev.as_ref().map(|a| &a.mora_count), + Self::E2 => label + .accent_phrase_prev + .as_ref() + .map(|a| &a.accent_position), + Self::F1 => label.accent_phrase_curr.as_ref().map(|a| &a.mora_count), + Self::F2 => label + .accent_phrase_curr + .as_ref() + .map(|a| &a.accent_position), + Self::F5 => label + .accent_phrase_curr + .as_ref() + .map(|a| &a.accent_phrase_position_forward), + Self::F6 => label + .accent_phrase_curr + .as_ref() + .map(|a| &a.accent_phrase_position_backward), + Self::F7 => label + .accent_phrase_curr + .as_ref() + .map(|a| &a.mora_position_forward), + Self::F8 => label + .accent_phrase_curr + .as_ref() + .map(|a| &a.mora_position_backward), + Self::G1 => label.accent_phrase_next.as_ref().map(|a| &a.mora_count), + Self::G2 => label + .accent_phrase_next + .as_ref() + .map(|a| &a.accent_position), + Self::H1 => label + .breath_group_prev + .as_ref() + .map(|b| &b.accent_phrase_count), + Self::H2 => label.breath_group_prev.as_ref().map(|b| &b.mora_count), + Self::I1 => label + .breath_group_curr + .as_ref() + .map(|b| &b.accent_phrase_count), + Self::I2 => label.breath_group_curr.as_ref().map(|b| &b.mora_count), + Self::I3 => label + .breath_group_curr + .as_ref() + .map(|b| &b.breath_group_position_forward), + Self::I4 => label + .breath_group_curr + .as_ref() + .map(|b| &b.breath_group_position_backward), + Self::I5 => label + .breath_group_curr + .as_ref() + .map(|b| &b.accent_phrase_position_forward), + Self::I6 => label + .breath_group_curr + .as_ref() + .map(|b| &b.accent_phrase_position_backward), + Self::I7 => label + .breath_group_curr + .as_ref() + .map(|b| &b.mora_position_forward), + Self::I8 => label + .breath_group_curr + .as_ref() + .map(|b| &b.mora_position_backward), + Self::J1 => label + .breath_group_next + .as_ref() + .map(|b| &b.accent_phrase_count), + Self::J2 => label.breath_group_next.as_ref().map(|b| &b.mora_count), + Self::K1 => Some(&label.utterance.breath_group_count), + Self::K2 => Some(&label.utterance.accent_phrase_count), + Self::K3 => Some(&label.utterance.mora_count), + } + } + fn test(&self, range: &Self::Range, target: &Self::Target) -> bool { range.contains(target) } @@ -275,6 +374,31 @@ impl Position for BooleanPosition { } } + fn get<'a>(&self, label: &'a Label) -> Option<&'a Self::Target> { + match self { + Self::E3 => label + .accent_phrase_prev + .as_ref() + .map(|a| &a.is_interrogative), + Self::E5 => label + .accent_phrase_prev + .as_ref() + .and_then(|a| a.is_pause_insertion.as_ref()), + Self::F3 => label + .accent_phrase_curr + .as_ref() + .map(|a| &a.is_interrogative), + Self::G3 => label + .accent_phrase_next + .as_ref() + .map(|a| &a.is_interrogative), + Self::G5 => label + .accent_phrase_next + .as_ref() + .and_then(|b| b.is_pause_insertion.as_ref()), + } + } + fn test(&self, range: &Self::Range, target: &Self::Target) -> bool { range == target } @@ -304,6 +428,20 @@ impl Position for CategoryPosition { .collect() } + fn get<'a>(&self, label: &'a Label) -> Option<&'a Self::Target> { + match self { + Self::B1 => label.word_prev.as_ref().and_then(|w| w.pos.as_ref()), + Self::B2 => label.word_prev.as_ref().and_then(|w| w.ctype.as_ref()), + Self::B3 => label.word_prev.as_ref().and_then(|w| w.cform.as_ref()), + Self::C1 => label.word_curr.as_ref().and_then(|w| w.pos.as_ref()), + Self::C2 => label.word_curr.as_ref().and_then(|w| w.ctype.as_ref()), + Self::C3 => label.word_curr.as_ref().and_then(|w| w.cform.as_ref()), + Self::D1 => label.word_next.as_ref().and_then(|w| w.pos.as_ref()), + Self::D2 => label.word_next.as_ref().and_then(|w| w.ctype.as_ref()), + Self::D3 => label.word_next.as_ref().and_then(|w| w.cform.as_ref()), + } + } + fn test(&self, range: &Self::Range, target: &Self::Target) -> bool { range.contains(target) } @@ -324,6 +462,10 @@ impl Position for UndefinedPotision { Ok(()) } + fn get<'a>(&self, _: &'a Label) -> Option<&'a Self::Target> { + None + } + fn test(&self, _: &Self::Range, _: &Self::Target) -> bool { true } diff --git a/src/question/tests.rs b/src/question/tests.rs new file mode 100644 index 0000000..703eb8e --- /dev/null +++ b/src/question/tests.rs @@ -0,0 +1,269 @@ +use crate::{ + question::{ + position::{ + BooleanPosition, CategoryPosition, PhonePosition, SignedRangePosition, + UndefinedPotision, UnsignedRangePosition, + }, + question, AllQuestion, Question, + }, + Label, Mora, Phoneme, Utterance, Word, +}; + +use super::split_pattern; + +#[test] +fn splitter() { + assert_eq!(split_pattern("a^*"), Some(("", "a", "^*"))); + assert_eq!(split_pattern("*/A:-??+*"), Some(("*/A:", "-??", "+*"))); + assert_eq!(split_pattern("*|?+*"), Some(("*|", "?", "+*"))); + assert_eq!(split_pattern("*-1"), Some(("*-", "1", ""))); +} + +#[test] +fn parse_question() { + assert_eq!( + question(&["a^*", "A^*"]).unwrap(), + AllQuestion::Phone(Question { + position: PhonePosition::P1, + range: Some(vec!["a".to_string(), "A".to_string()]) + }) + ); + assert_eq!( + question(&["*/A:-3+*"]).unwrap(), + AllQuestion::SignedRange(Question { + position: SignedRangePosition::A1, + range: Some(-3..-2) + }) + ); + assert_eq!( + question(&["*/A:-??+*", "*/A:-?+*", "*/A:?+*", "*/A:10+*", "*/A:11+*",]).unwrap(), + AllQuestion::SignedRange(Question { + position: SignedRangePosition::A1, + range: Some(-99..12) + }) + ); + assert_eq!( + question(&["*_42/I:*"]).unwrap(), + AllQuestion::UnsignedRange(Question { + position: UnsignedRangePosition::H2, + range: Some(42..43) + }) + ); + assert_eq!( + question(&["*_?/I:*", "*_1?/I:*", "*_2?/I:*", "*_30/I:*", "*_31/I:*",]).unwrap(), + AllQuestion::UnsignedRange(Question { + position: UnsignedRangePosition::H2, + range: Some(1..32) + }) + ); + assert_eq!( + question(&["*%1_*"]).unwrap(), + AllQuestion::Boolean(Question { + position: BooleanPosition::G3, + range: Some(true) + }) + ); + assert_eq!( + question(&["*/B:17-*", "*/B:20-*"]).unwrap(), + AllQuestion::Category(Question { + position: CategoryPosition::B1, + range: Some(vec![17, 20]) + }) + ); + assert_eq!( + question(&["*_xx_*"]).unwrap(), + AllQuestion::Undefined(Question { + position: UndefinedPotision::G4, + range: None + }) + ); +} + +#[test] +fn query() { + // Note: this Label is created randomly, and is invalid. + let label = Label { + phoneme: Phoneme { + p2: Some("b".to_string()), + p1: Some("o".to_string()), + c: Some("N".to_string()), + n1: Some("s".to_string()), + n2: Some("a".to_string()), + }, + mora: Some(Mora { + relative_accent_position: -6, + position_forward: 2, + position_backward: 8, + }), + word_prev: None, + word_curr: Some(Word { + pos: Some(1), + ctype: None, + cform: None, + }), + word_next: None, + accent_phrase_prev: None, + accent_phrase_curr: None, + accent_phrase_next: None, + breath_group_prev: None, + breath_group_curr: None, + breath_group_next: None, + utterance: Utterance { + breath_group_count: 3, + accent_phrase_count: 6, + mora_count: 10, + }, + }; + + assert!(!question(&["*=i/A:*"]).unwrap().test(&label)); + + assert!(!question(&["*/A:-??+*", "*/A:-9+*"]).unwrap().test(&label)); + assert!(question(&["*/A:-6+*"]).unwrap().test(&label)); + + assert!(question(&["*+8/B:*"]).unwrap().test(&label)); + + assert!(question(&["*-xx_*"]).unwrap().test(&label)); + assert!(question(&["*/C:01_*"]).unwrap().test(&label)); +} + +#[test] +fn all_query() { + let label = Label { + phoneme: Phoneme { + p2: None, + p1: None, + c: None, + n1: None, + n2: None, + }, + mora: None, + word_prev: None, + word_curr: None, + word_next: None, + accent_phrase_prev: None, + accent_phrase_curr: None, + accent_phrase_next: None, + breath_group_prev: None, + breath_group_curr: None, + breath_group_next: None, + utterance: Utterance { + breath_group_count: 3, + accent_phrase_count: 6, + mora_count: 10, + }, + }; + + use crate::question::position::*; + + for position in [ + PhonePosition::P1, + PhonePosition::P2, + PhonePosition::P3, + PhonePosition::P4, + PhonePosition::P5, + ] { + let q = AllQuestion::Phone(Question { + position, + range: None, + }); + assert!(q.test(&label)); + } + + for position in [ + CategoryPosition::B1, + CategoryPosition::B2, + CategoryPosition::B3, + CategoryPosition::C1, + CategoryPosition::C2, + CategoryPosition::C3, + CategoryPosition::D1, + CategoryPosition::D2, + CategoryPosition::D3, + ] { + let q = Question { + position, + range: None, + }; + assert!(q.test(&label)); + } + + let q = Question { + position: SignedRangePosition::A1, + range: None, + }; + assert!(q.test(&label)); + + for position in [ + UnsignedRangePosition::A2, + UnsignedRangePosition::A3, + UnsignedRangePosition::E1, + UnsignedRangePosition::E2, + UnsignedRangePosition::F1, + UnsignedRangePosition::F2, + UnsignedRangePosition::F5, + UnsignedRangePosition::F6, + UnsignedRangePosition::F7, + UnsignedRangePosition::F8, + UnsignedRangePosition::G1, + UnsignedRangePosition::G2, + UnsignedRangePosition::H1, + UnsignedRangePosition::H2, + UnsignedRangePosition::I1, + UnsignedRangePosition::I2, + UnsignedRangePosition::I3, + UnsignedRangePosition::I4, + UnsignedRangePosition::I5, + UnsignedRangePosition::I6, + UnsignedRangePosition::I7, + UnsignedRangePosition::I8, + UnsignedRangePosition::J1, + UnsignedRangePosition::J2, + ] { + let q = Question { + position: position.clone(), + range: None, + }; + assert!(q.test(&label)); + let q = Question { + position: position.clone(), + range: Some(0..1), + }; + assert!(!q.test(&label)); + } + + for position in [ + BooleanPosition::E3, + BooleanPosition::E5, + BooleanPosition::F3, + BooleanPosition::G3, + BooleanPosition::G5, + ] { + let q = Question { + position, + range: None, + }; + assert!(q.test(&label)); + } + + let q = Question { + position: UnsignedRangePosition::K1, + range: Some(3..4), + }; + assert!(q.test(&label)); + let q = Question { + position: UnsignedRangePosition::K2, + range: Some(6..7), + }; + assert!(q.test(&label)); + let q = Question { + position: UnsignedRangePosition::K3, + range: Some(5..11), + }; + assert!(q.test(&label)); + + let q = Question { + position: UndefinedPotision::E4, + range: None, + }; + assert!(q.test(&label)); +}