Can add text to a universal string.
Some checks failed
Gitea Actions Demo / Explore-Gitea-Actions (push) Failing after 1s

This commit is contained in:
2026-03-15 14:05:49 -04:00
parent 6014a3bb25
commit 7d8de156c7

View File

@@ -4,6 +4,7 @@ use std::{
cmp::Ordering, cmp::Ordering,
collections::HashMap, collections::HashMap,
ops::{Add, AddAssign}, ops::{Add, AddAssign},
str::Split,
time::Duration, time::Duration,
}; };
use uuid::Uuid; use uuid::Uuid;
@@ -417,6 +418,7 @@ mod paragraph_data {
} }
} }
#[derive(Clone, Debug)]
struct Paragraph { struct Paragraph {
data: HashMap<Language, ParagraphData>, data: HashMap<Language, ParagraphData>,
} }
@@ -575,44 +577,120 @@ mod paragraphs {
} }
} }
#[derive(Clone, Debug)]
struct UniversalString { struct UniversalString {
data: Paragraph, paragraphs: HashMap<Uuid, Paragraph>,
revisions: Vec<Vec<Uuid>>,
} }
impl UniversalString { impl UniversalString {
fn split_string(text: String) -> Vec<String> {
let holder = text.as_str();
let mut output = Vec::new();
for item in holder.split("\u{2029}") {
output.push(item.to_string());
}
output
}
fn new(lang: Language, text: String) -> Self { fn new(lang: Language, text: String) -> Self {
let input = Self::split_string(text);
let mut paragraphs = HashMap::new();
let mut revision = Vec::new();
for paragraph in input {
let mut id = Uuid::new_v4();
while paragraphs.contains_key(&id) {
id = Uuid::new_v4();
}
if paragraph != "" {
revision.push(id.clone());
paragraphs.insert(id, Paragraph::new(lang.clone(), paragraph.to_string()));
}
}
Self { Self {
data: Paragraph::new(lang, text), paragraphs: paragraphs,
revisions: vec![revision],
} }
} }
fn get(&self, lang: &Language) -> Option<&String> { fn get(&self, lang: &Language) -> Option<String> {
self.data.get(lang) let latest = self.revisions.iter().last().unwrap();
let mut output = "".to_string();
for id in latest.iter() {
let paragraph = self.paragraphs.get(id).unwrap();
let text = paragraph.get(lang).unwrap();
output += text;
output += "\u{2029}";
}
Some(output)
}
fn revision_count(&self) -> usize {
self.revisions.len() - 1
}
fn update(&mut self, lang: Language, text: String) {
let input = Self::split_string(text);
let mut version = Vec::new();
for paragraph in input {
if paragraph != "" {
let mut id = Uuid::nil();
for (key, value) in self.paragraphs.iter() {
if &paragraph == value.get(&lang).unwrap() {
println!("--- Got here ---");
id = key.clone();
break;
}
}
if id == Uuid::nil() {
id = Uuid::new_v4();
while self.paragraphs.contains_key(&id) {
id = Uuid::new_v4();
}
self.paragraphs.insert(
id.clone(),
Paragraph::new(lang.clone(), paragraph.to_string()),
);
}
version.push(id);
}
}
self.revisions.push(version);
} }
} }
#[cfg(test)] #[cfg(test)]
mod universal_strings { mod universal_strings {
use super::*; use super::*;
use rand::random_range;
const INITIAL_DATA: [&str; 5] = ["one", "two", "three", "four", "five"]; const ENGLISH_DATA: [&str; 5] = ["one", "two", "three", "four", "five"];
const JAPANESE_DATA: [&str; 5] = ["", "", "", "", ""];
struct TestData { struct TestData;
data: Vec<String>,
}
impl TestData { impl TestData {
fn new(paragraphs: Vec<&str>) -> Self { fn english() -> (Language, Vec<String>) {
let mut holder = Vec::new(); let lang = Language::from_639_1("en").unwrap();
for item in paragraphs.iter() { let mut data = Vec::new();
holder.push(item.to_string()); for text in ENGLISH_DATA.iter() {
data.push(text.to_string());
} }
Self { data: holder } (lang, data)
} }
fn get_text(&self) -> String { fn japanese() -> (Language, Vec<String>) {
let lang = Language::from_639_1("ja").unwrap();
let mut data = Vec::new();
for text in JAPANESE_DATA.iter() {
data.push(text.to_string());
}
(lang, data)
}
fn to_input(data: Vec<String>) -> String {
let mut output = "".to_string(); let mut output = "".to_string();
for paragraph in self.data.iter() { for paragraph in data.iter() {
output += paragraph; output += paragraph;
output += "\u{2029}"; output += "\u{2029}";
} }
@@ -629,15 +707,34 @@ mod universal_strings {
]; ];
for i in 0..text.len() { for i in 0..text.len() {
let ustr = UniversalString::new(languages[i].clone(), text[i].to_string()); let ustr = UniversalString::new(languages[i].clone(), text[i].to_string());
assert_eq!(ustr.get(&languages[i]).unwrap(), text[i]); let expected = text[i].to_string() + "\u{2029}";
assert_eq!(ustr.get(&languages[i]).unwrap(), expected);
assert_eq!(ustr.revision_count(), 0);
assert_eq!(ustr.paragraphs.len(), 1);
} }
} }
#[test] #[test]
fn accepts_strings_with_multiple_paragraphs() { fn accepts_strings_with_multiple_paragraphs() {
let lang = Language::from_639_1("en").unwrap(); let (lang, data) = TestData::english();
let input = TestData::new(INITIAL_DATA.to_vec()); let input = TestData::to_input(data.clone());
let ustr = UniversalString::new(lang.clone(), input.get_text()); let ustr = UniversalString::new(lang.clone(), input.clone());
assert_eq!(ustr.get(&lang).unwrap(), &input.get_text()); assert_eq!(ustr.get(&lang).unwrap(), input);
assert_eq!(ustr.revision_count(), 0);
assert_eq!(ustr.paragraphs.len(), data.len(), "{:?}", ustr);
}
#[test]
fn can_insert_text_into_string() {
let (lang, mut data) = TestData::english();
let initial = TestData::to_input(data.clone());
let mut ustr = UniversalString::new(lang.clone(), initial.clone());
let position = random_range(..data.len());
data.insert(position, "something".to_string());
let expected = TestData::to_input(data.clone());
ustr.update(lang.clone(), expected.clone());
assert_eq!(ustr.get(&lang).unwrap(), expected);
assert_eq!(ustr.revision_count(), 1);
assert_eq!(ustr.paragraphs.len(), data.len(), "{:?}", ustr);
} }
} }