vidyut_chandas/
chandas.rs1use crate::akshara::{scan_lines, Akshara};
2use crate::vrtta::{MatchType, Vrtta};
3use std::error::Error;
4use std::fs;
5use std::path::{Path, PathBuf};
6
7pub struct MatchResult {
9 vrtta: Option<Vrtta>,
10 match_type: MatchType,
11 aksharas: Vec<Vec<Akshara>>,
12}
13
14impl MatchResult {
15 pub fn vrtta(&self) -> &Option<Vrtta> {
17 &self.vrtta
18 }
19
20 pub fn match_type(&self) -> MatchType {
22 self.match_type
23 }
24
25 pub fn aksharas(&self) -> &Vec<Vec<Akshara>> {
27 &self.aksharas
28 }
29}
30
31#[derive(Clone, Debug, Eq, Hash, PartialEq)]
52pub struct Chandas {
53 vrttas: Vec<Vrtta>,
54}
55
56impl Chandas {
57 pub fn new(vrttas: Vec<Vrtta>) -> Chandas {
59 Self { vrttas }
60 }
61
62 pub fn from_text(data: &str) -> Result<Self, Box<dyn Error>> {
67 let vrttas: Result<Vec<_>, _> = data.lines().map(Vrtta::try_from).collect();
68 Ok(Self::new(vrttas?))
69 }
70
71 pub fn from_file(path: &Path) -> Result<Self, Box<dyn Error>> {
73 let path = PathBuf::from(path).join(path);
74 let data = fs::read_to_string(path)?;
75 let vrttas: Result<Vec<_>, _> = data.lines().map(Vrtta::try_from).collect();
76
77 Ok(Self::new(vrttas?))
78 }
79
80 pub fn vrttas(&self) -> &Vec<Vrtta> {
82 &self.vrttas
83 }
84
85 pub fn classify(&self, text: impl AsRef<str>) -> MatchResult {
89 let aksharas = scan_lines(text.as_ref().lines());
90
91 let mut best_match = MatchType::None;
92 let mut i_best = None;
93 for (i, vrtta) in self.vrttas.iter().enumerate() {
94 let match_type = vrtta.try_match(&aksharas);
95 if match_type > best_match {
96 i_best = Some(i);
97 best_match = match_type;
98 }
99 }
100
101 if let Some(i) = i_best {
102 MatchResult {
103 vrtta: Some(self.vrttas[i].clone()),
104 match_type: best_match,
105 aksharas,
106 }
107 } else {
108 MatchResult {
109 vrtta: None,
110 match_type: best_match,
111 aksharas,
112 }
113 }
114 }
115}
116
117#[cfg(test)]
118mod tests {
119 use super::*;
120
121 fn assert_has_vrtta(c: &Chandas, text: &str, expected: &str) {
122 let res = c.classify(text);
123 assert_eq!(res.vrtta().as_ref().unwrap().name(), expected);
124 }
125
126 fn new_chandas() -> Chandas {
127 Chandas::new(vec![
128 "vasantatilakA\tvrtta\tGGLGLLLGLLGLGG".try_into().unwrap(),
129 "mandAkrAntA\tvrtta\tGGGGLLLLLGGLGGLGG".try_into().unwrap(),
130 "puzpitAgrA\tvrtta\tLLLLLLGLGLGG/LLLLGLLGLGLGG"
131 .try_into()
132 .unwrap(),
133 "udgatA\tvrtta\tLLGLGLLLGL/LLLLLGLGLG/GLLLLLLGLLG/LLGLGLLLGLGLG"
134 .try_into()
135 .unwrap(),
136 ])
137 }
138
139 #[test]
140 fn classify_samavrtta_single_pada() {
141 let c = new_chandas();
142 assert_has_vrtta(&c, "mAtaH samastajagatAM maDukEwaBAreH", "vasantatilakA");
143 assert_has_vrtta(&c, "mAtaH\nsamastajagatAM\nmaDukEwaBAreH", "vasantatilakA");
144 }
145
146 #[test]
147 fn classify_samavrtta_full_verse() {
148 let c = new_chandas();
149 assert_has_vrtta(
150 &c,
151 "kaScitkAntAvirahaguruRA svADikArapramattaH
152 zApenAstaMgamitamahimA varzaBogyeRa BartuH .
153 yakzaScakre janakatanayAsnAnapuRyodakezu
154 snigDacCAyAtaruzu vasatiM rAmagiryASramezu .. 1 ..",
155 "mandAkrAntA",
156 );
157 assert!(c.classify("mo mo go go vidyunmAlA").vrtta().is_none());
158 }
159
160 #[test]
161 fn classify_ardhasamavrtta_pada_1() {
162 let c = new_chandas();
163 assert_has_vrtta(&c, "aTa madanavaDUrupaplavAntaM", "puzpitAgrA");
164 }
165
166 #[test]
167 fn classify_ardhasamavrtta_half() {
168 let c = new_chandas();
169 assert_has_vrtta(
170 &c,
171 "aTa madanavaDUrupaplavAntaM vyasanakfSA paripAlayAmbaBUva",
172 "puzpitAgrA",
173 );
174 assert_has_vrtta(
175 &c,
176 "aTa\nmadanavaDUrupaplavAntaM\nvyasanakfSA\nparipAlayAmbaBUva",
177 "puzpitAgrA",
178 );
179 }
180
181 #[test]
182 fn classify_ardhasamavrtta_full_verse() {
183 let c = new_chandas();
184 assert_has_vrtta(
185 &c,
186 "aTa madanavaDUrupaplavAntaM vyasanakfSA paripAlayAmbaBUva |
187 SaSina iva divAtanasya leKA kiraRaparikzayaDUsarA pradozam ||",
188 "puzpitAgrA",
189 );
190 }
191
192 #[test]
193 fn classify_vishamavrtta_pada_1() {
194 let c = new_chandas();
195 assert_has_vrtta(&c, "aTa vAsavasya vacanena", "udgatA");
196 }
197
198 #[test]
199 fn classify_vishamavrtta_full_verse() {
200 let c = new_chandas();
201 assert_has_vrtta(
202 &c,
203 "aTa vAsavasya vacanena ruciravadanastrilocanam |
204 klAntirahitamaBirADayituM viDivattapAMsi vidaDe DanaMjayaH ||",
205 "udgatA",
206 );
207 }
208}