use std::collections::BTreeMap;
use crate::conlang::types::morphology::Morphology;
use crate::conlang::Phonology;
use crate::language_entry::DictionaryEntry;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct RoundTrip {
pub english: String,
pub conlang: String,
pub recovered: String,
pub covered: bool,
}
pub fn round_trip(
phon: &Phonology,
morph: &Morphology,
typology: &BTreeMap<String, String>,
entries: &[DictionaryEntry],
english: &str,
) -> RoundTrip {
let fwd = super::translate(phon, morph, typology, entries, english);
let covered = fwd.unresolved.is_empty() && !fwd.target.trim().is_empty();
let rev = super::reverse::reverse(phon, morph, typology, entries, &fwd.target);
RoundTrip {
english: english.to_string(),
conlang: fwd.target,
recovered: rev.english,
covered,
}
}
pub fn round_trip_all(
phon: &Phonology,
morph: &Morphology,
typology: &BTreeMap<String, String>,
entries: &[DictionaryEntry],
test_set: &[String],
) -> Vec<RoundTrip> {
test_set
.iter()
.filter(|s| !s.trim().is_empty())
.map(|s| round_trip(phon, morph, typology, entries, s.trim()))
.collect()
}
pub fn coverage(items: &[RoundTrip]) -> f32 {
if items.is_empty() {
return 0.0;
}
items.iter().filter(|i| i.covered).count() as f32 / items.len() as f32
}
#[cfg(test)]
mod tests {
use super::*;
fn entry(word: &str, pos: &str, translation: &str) -> DictionaryEntry {
DictionaryEntry {
word: word.into(),
pos: pos.into(),
translation: translation.into(),
..Default::default()
}
}
#[test]
fn round_trip_recovers_a_covered_sentence() {
let phon = Phonology::default();
let morph = Morphology::default();
let mut typ = BTreeMap::new();
typ.insert("word_order".to_string(), "svo".to_string());
let entries = vec![
entry("kira", "noun", "bird"),
entry("nami", "verb", "to see"),
entry("pata", "noun", "stone"),
];
let rt = round_trip(&phon, &morph, &typ, &entries, "the bird sees the stone");
assert!(rt.covered);
assert_eq!(rt.conlang, "kira nami pata");
assert_eq!(rt.recovered, "the bird sees the stone");
}
#[test]
fn uncovered_sentence_is_flagged() {
let phon = Phonology::default();
let morph = Morphology::default();
let mut typ = BTreeMap::new();
typ.insert("word_order".to_string(), "svo".to_string());
let entries = vec![entry("kira", "noun", "bird"), entry("nami", "verb", "to see")];
let items =
round_trip_all(&phon, &morph, &typ, &entries, &["the bird sees the dragon".to_string()]);
assert!(!items[0].covered); assert_eq!(coverage(&items), 0.0);
}
}