game_manager_lib\utils/
series.rs1use std::sync::OnceLock;
7
8fn get_known_series() -> &'static Vec<String> {
10 static SERIES_CACHE: OnceLock<Vec<String>> = OnceLock::new();
11 SERIES_CACHE.get_or_init(|| {
12 let json_content = include_str!("../data/known_series.json");
13 let mut list: Vec<String> =
14 serde_json::from_str(json_content).expect("Erro ao carregar known_series.json");
15 list.sort_by_key(|b| std::cmp::Reverse(b.len()));
17 list
18 })
19}
20
21fn normalize_name(name: &str) -> String {
22 name.to_lowercase()
23 .replace(['™', '®', '©', ':'], "")
24 .trim()
25 .to_string()
26}
27
28pub fn infer_series(game_name: &str) -> Option<String> {
30 let normalized_target = normalize_name(game_name);
31 let known_list = get_known_series();
32
33 for series in known_list {
35 let normalized_series = normalize_name(series);
36 if normalized_target.contains(&normalized_series) {
37 return Some(series.clone());
38 }
39 }
40
41 let splitters = [":", " -", " –"];
44 for pattern in splitters {
45 if let Some(pos) = game_name.find(pattern) {
46 let base = game_name[..pos].trim();
47 if base.len() >= 3 {
48 return Some(base.to_string());
49 }
50 }
51 }
52
53 None
54}