use super::SceneRegistry;
#[derive(Debug, Clone, PartialEq)]
pub struct WordEntry {
pub id: usize,
pub key: String,
pub values: Vec<String>,
}
pub struct WordDefRegistry {
entries: Vec<WordEntry>,
}
impl WordDefRegistry {
pub fn new() -> Self {
Self {
entries: Vec::new(),
}
}
pub fn register_global(&mut self, name: &str, values: Vec<String>) -> usize {
let id = self.entries.len();
let key = name.to_string();
self.entries.push(WordEntry { id, key, values });
id
}
pub fn register_local(&mut self, module_name: &str, name: &str, values: Vec<String>) -> usize {
let id = self.entries.len();
let sanitized_module = Self::sanitize_name(module_name);
let key = format!(":{}:{}", sanitized_module, name);
self.entries.push(WordEntry { id, key, values });
id
}
pub fn register_actor(&mut self, actor_name: &str, name: &str, values: Vec<String>) -> usize {
let id = self.entries.len();
let sanitized_actor = Self::sanitize_name(actor_name);
let key = format!(":__actor_{}__:{}", sanitized_actor, name);
self.entries.push(WordEntry { id, key, values });
id
}
pub fn all_entries(&self) -> &[WordEntry] {
&self.entries
}
pub fn into_entries(self) -> Vec<WordEntry> {
self.entries
}
pub fn sanitize_name(name: &str) -> String {
SceneRegistry::sanitize_name(name)
}
pub fn merge_from(&mut self, other: WordDefRegistry) {
for mut entry in other.entries {
entry.id = self.entries.len();
self.entries.push(entry);
}
}
}
impl Default for WordDefRegistry {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_new_registry_is_empty() {
let registry = WordDefRegistry::new();
assert!(registry.all_entries().is_empty());
}
#[test]
fn test_register_global_basic() {
let mut registry = WordDefRegistry::new();
let id = registry.register_global(
"挨拶",
vec!["こんにちは".to_string(), "おはよう".to_string()],
);
assert_eq!(id, 0);
let entries = registry.all_entries();
assert_eq!(entries.len(), 1);
assert_eq!(entries[0].id, 0);
assert_eq!(entries[0].key, "挨拶");
assert_eq!(entries[0].values, vec!["こんにちは", "おはよう"]);
}
#[test]
fn test_register_global_multiple() {
let mut registry = WordDefRegistry::new();
let id1 = registry.register_global("場所", vec!["東京".to_string()]);
let id2 = registry.register_global("天気", vec!["晴れ".to_string()]);
let id3 = registry.register_global("場所", vec!["大阪".to_string()]);
assert_eq!(id1, 0);
assert_eq!(id2, 1);
assert_eq!(id3, 2);
let entries = registry.all_entries();
assert_eq!(entries.len(), 3);
assert_eq!(entries[0].key, "場所");
assert_eq!(entries[2].key, "場所");
}
#[test]
fn test_register_local_basic() {
let mut registry = WordDefRegistry::new();
let id = registry.register_local("会話", "挨拶", vec!["やあ".to_string()]);
assert_eq!(id, 0);
let entries = registry.all_entries();
assert_eq!(entries.len(), 1);
assert_eq!(entries[0].key, ":会話:挨拶");
assert_eq!(entries[0].values, vec!["やあ"]);
}
#[test]
fn test_register_local_with_sanitization() {
let mut registry = WordDefRegistry::new();
let id = registry.register_local("会話-テスト", "挨拶", vec!["こんにちは".to_string()]);
assert_eq!(id, 0);
let entries = registry.all_entries();
assert_eq!(entries[0].key, ":会話_テスト:挨拶");
}
#[test]
fn test_global_and_local_mixed() {
let mut registry = WordDefRegistry::new();
let id1 = registry.register_global("挨拶", vec!["こんにちは".to_string()]);
let id2 = registry.register_local("会話", "挨拶", vec!["やあ".to_string()]);
let id3 = registry.register_global("挨拶", vec!["おはよう".to_string()]);
assert_eq!(id1, 0);
assert_eq!(id2, 1);
assert_eq!(id3, 2);
let entries = registry.all_entries();
assert_eq!(entries.len(), 3);
assert_eq!(entries[0].key, "挨拶"); assert_eq!(entries[1].key, ":会話:挨拶"); assert_eq!(entries[2].key, "挨拶"); }
#[test]
fn test_entry_id_sequential() {
let mut registry = WordDefRegistry::new();
for i in 0..10 {
let id = registry.register_global(&format!("word{}", i), vec!["value".to_string()]);
assert_eq!(id, i);
}
assert_eq!(registry.all_entries().len(), 10);
}
#[test]
fn test_sanitize_name() {
assert_eq!(WordDefRegistry::sanitize_name("hello"), "hello");
assert_eq!(WordDefRegistry::sanitize_name("hello-world"), "hello_world");
assert_eq!(WordDefRegistry::sanitize_name("会話"), "会話");
assert_eq!(WordDefRegistry::sanitize_name("*会話"), "_会話");
}
#[test]
fn test_into_entries() {
let mut registry = WordDefRegistry::new();
registry.register_global("test", vec!["value".to_string()]);
let entries = registry.into_entries();
assert_eq!(entries.len(), 1);
assert_eq!(entries[0].key, "test");
}
#[test]
fn test_register_actor_basic() {
let mut registry = WordDefRegistry::new();
let id = registry.register_actor("さくら", "通常", vec!["\\s[0]".to_string()]);
assert_eq!(id, 0);
let entries = registry.all_entries();
assert_eq!(entries.len(), 1);
assert_eq!(entries[0].key, ":__actor_さくら__:通常");
assert_eq!(entries[0].values, vec!["\\s[0]"]);
}
#[test]
fn test_register_actor_with_sanitization() {
let mut registry = WordDefRegistry::new();
let id = registry.register_actor("さくら-太郎", "表情", vec!["\\s[1]".to_string()]);
assert_eq!(id, 0);
let entries = registry.all_entries();
assert_eq!(entries[0].key, ":__actor_さくら_太郎__:表情");
}
#[test]
fn test_register_actor_multiple_values() {
let mut registry = WordDefRegistry::new();
let id = registry.register_actor(
"さくら",
"表情",
vec![
"\\s[0]".to_string(),
"\\s[1]".to_string(),
"\\s[2]".to_string(),
],
);
assert_eq!(id, 0);
let entries = registry.all_entries();
assert_eq!(entries[0].values.len(), 3);
}
#[test]
fn test_global_local_actor_mixed() {
let mut registry = WordDefRegistry::new();
let id1 = registry.register_global("挨拶", vec!["こんにちは".to_string()]);
let id2 = registry.register_local("会話", "挨拶", vec!["やあ".to_string()]);
let id3 = registry.register_actor("さくら", "表情", vec!["\\s[0]".to_string()]);
assert_eq!(id1, 0);
assert_eq!(id2, 1);
assert_eq!(id3, 2);
let entries = registry.all_entries();
assert_eq!(entries.len(), 3);
assert_eq!(entries[0].key, "挨拶"); assert_eq!(entries[1].key, ":会話:挨拶"); assert_eq!(entries[2].key, ":__actor_さくら__:表情"); }
}