/
Sevlagor
/
MGT_Utils
Обзор
Документация
Войти
/
Sevlagor
/
MGT_Utils
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
tmp
src/data.rs
615 строк
17 KB
Sevlagor
+trait ViewComponent, +Label
05 янв 2026, 14:15
05 янв 2026, 14:15
4602429
Код
Авторство
О чём код?
use core::slice::Iter; use std::{ collections::HashSet, fs::File, io::{BufRead, BufReader}, sync::{OnceLock, RwLock}, cell::OnceCell, }; use crate::{ campaign::{Campaign, EMPTY}, constants::*, game_genre::GameGenre, game_info::{GameInfo, Target, Theme}, tunings::{ConstTunings, FloatTunings, Slider}, err, }; pub static STD_GAMES_INFO: OnceLock<Vec<GameInfo<'_>>> = OnceLock::new(); pub static ALL_THEMES_INFO: OnceLock<HashSet<Theme<'_>>> = OnceLock::new(); pub static CAMPAIGN: RwLock<Campaign> = RwLock::new(EMPTY); static IS_DATA_CREATED: OnceLock<bool> = OnceLock::new(); pub struct Data { is_init: OnceCell<bool>, std_games: Vec<GameInfo<'static>>, all_themes: HashSet<Theme<'static>>, campaign: Campaign, } pub fn new() -> Option<Data> { if IS_DATA_CREATED.get().is_none() { _ = IS_DATA_CREATED.set(true); Some(Data { is_init: OnceCell::new(), std_games: Vec::<GameInfo>::new(), all_themes: HashSet::new(), campaign: Campaign::new(), }) } else { None } } impl Data { pub fn init(&mut self) { if self.is_init.get().is_none() { _ = self.is_init.set(true); (self.std_games, self.all_themes) = load_std_games_info() .expect(&err("Ошибка в data::load_std_games_info()")); } } pub fn new_camp(&mut self, name: String) { self.campaign.init(name); } #[cfg(debug_assertions)] pub fn all_themes<'a>(&'a self) -> &'a HashSet<Theme<'a>> { &self.all_themes } pub fn camp_name(&self) -> String { self.campaign.name.get().unwrap_or(&".. не определена ..".to_string()).to_string() } } pub fn visual_tests_init(_name: String) { let (std_gi, all_themes) = load_std_games_info().expect("Ошибка"); _ = STD_GAMES_INFO.set(std_gi); _ = ALL_THEMES_INFO.set(all_themes); // let camp = Campaign::init(name); // *CAMPAIGN.write().unwrap() = camp; } fn load_lines_from_file(path: &str) -> Result<Vec<String>, std::io::Error> { let file = File::open(path)?; let reader = BufReader::new(file); Ok(reader.lines().map_while(|x| x.ok()).collect()) } fn load_std_games_info() -> Option<(Vec<GameInfo<'static>>, HashSet<Theme<'static>>)> { let mut std_game_info: Vec<GameInfo<'_>> = vec![]; let mut all_themes = create_all_themes(); let lines = load_lines_from_file(LOAD_PATH) .expect( "Error: Could not open file 'GamesInfo.txt'. Please make sure it exists in the correct directory." ); let mut lines_iter = lines.iter(); let mut current_genre: GameGenre = GameGenre::Action; while let Some(str) = lines_iter.next() { let mut game_info = GameInfo::new(); if "#" == str { if let Some(genre) = load_genre(&mut lines_iter) { current_genre = genre; game_info.main_genre = genre; std_game_info.push(game_info); } else { break; }; } if str.starts_with(KEY_RELEASE_DATE) { std_game_info.last_mut().unwrap().date = str.strip_prefix(KEY_RELEASE_DATE).unwrap_or("").to_string(); } if KEY_TARGET_GROUP == str { while let Some(target) = load_target_group(&mut lines_iter) { std_game_info.last_mut().unwrap().target_group.push(target); } } if KEY_SUB_GENRES == str { while let Some(genre) = load_genre(&mut lines_iter) { std_game_info.last_mut().unwrap().sub_genres.push(genre); } } if KEY_FLOAT_SETTINGS == str { std_game_info.last_mut().unwrap().float_settings = load_float_settings(&mut lines_iter); } if KEY_CONST_SETTINGS == str { std_game_info.last_mut().unwrap().const_settings = load_const_settings(&mut lines_iter); } if KEY_THEMES == str { let theme_str = lines_iter.next().unwrap(); let vec_themes: Vec<&str> = theme_str.split(", ").collect(); for name_theme in &vec_themes { if let Some(mut theme) = all_themes.take(*name_theme) { theme.game_genres.push(current_genre); _ = all_themes.insert(theme.clone()); std_game_info.last_mut().unwrap().themes.push(theme.name); }; } } } Some((std_game_info, all_themes)) } fn create_all_themes() -> HashSet<Theme<'static>> { ALL_THEMES .map(|name| Theme { name, game_genres: vec![], }) .into() } fn load_target_group(lines_iter: &mut Iter<String>) -> Option<Target> { if let Some(str) = lines_iter.next() { Target::from_str(str) } else { None } } fn load_genre(lines_iter: &mut Iter<String>) -> Option<GameGenre> { if let Some(str) = lines_iter.next() { GameGenre::from_str(str) } else { None } } fn load_float_settings(lines_iter: &mut Iter<String>) -> FloatTunings { let mut float = FloatTunings::new(); float .tuns1 .iter_mut() .for_each(|v| v.set_val(load_num_setting(lines_iter) - 5)); lines_iter.next(); // пропустить строку с "~" float .tuns2 .iter_mut() .for_each(|v| v.set_val(load_num_setting(lines_iter))); float } fn load_num_setting(lines_iter: &mut Iter<String>) -> i8 { lines_iter .next() .unwrap() .split(": ") .last() .unwrap_or("5") .parse::<i8>() .unwrap() } fn load_const_settings(lines_iter: &mut Iter<String>) -> ConstTunings { let mut const_set = ConstTunings::new(); const_set .tuns .iter_mut() .for_each(|v| *v = load_proc_setting(lines_iter)); const_set } fn load_proc_setting(lines_iter: &mut Iter<String>) -> Slider { let mut sl = Slider::new_p(); sl.set_val( lines_iter .next() .unwrap() .split(": ") .last() .unwrap_or("25%") .strip_suffix("%") .unwrap_or("25") .parse::<i8>() .unwrap_or(25), ); sl } #[cfg(test)] mod tests { use super::*; #[test] fn check_themes_for_main_genres() { visual_tests_init("".to_string()); for game in STD_GAMES_INFO.wait().iter() { for theme in &game.themes { assert!( ALL_THEMES_INFO .wait() .get(*theme) .unwrap() .game_genres .contains(&game.main_genre) ); } } } #[test] fn full_check_contains_themes_for_main_genres() { let all_themes = ALL_THEMES_INFO.wait(); let v_games_info = STD_GAMES_INFO.wait(); for theme in all_themes { for game in v_games_info.iter() { assert_eq!( theme.game_genres.contains(&game.main_genre), game.themes.contains(&theme.name) ); } } } #[test] fn check_count_contains_themes() { let all_themes = ALL_THEMES_INFO.wait(); let v_games_info = STD_GAMES_INFO.wait(); for theme in all_themes { assert_eq!( theme.game_genres.len(), v_games_info .iter() .filter(|game| game.themes.contains(&theme.name)) .count() ); } } #[test] fn test_game_info_main() { let v_games_info = STD_GAMES_INFO.wait(); let tst_gi = &v_games_info[6]; assert_eq!(tst_gi.main_genre, GameGenre::Action); } #[test] fn test_game_info_date() { let v_games_info = STD_GAMES_INFO.wait(); let tst_gi = &v_games_info[6]; assert_eq!(tst_gi.date, "Август 1979".to_string()); } #[test] fn test_game_info_target() { let v_games_info = STD_GAMES_INFO.wait(); let tst_gi = &v_games_info[6]; use Target::*; assert_eq!(tst_gi.target_group, [Teenagers, Grownups].to_vec()); } #[test] fn test_game_info_subgenre() { let v_games_info = STD_GAMES_INFO.wait(); let tst_gi = &v_games_info[6]; use GameGenre::*; assert_eq!( tst_gi.sub_genres, [ Skill, Advenchure, RPG, Platformer, Fighting, FirstPersonShooter, TheerdPersonShooter, Survival ] .to_vec() ); } #[test] fn test_game_info_fltset() { let v_games_info = STD_GAMES_INFO.wait(); let simp_gi = make_simple_action_game(); let tst_gi = &v_games_info[6]; assert_eq!(tst_gi.float_settings, simp_gi.float_settings); } #[test] fn test_game_info_cnsset() { let v_games_info = STD_GAMES_INFO.wait(); let simp_gi = make_simple_action_game(); let tst_gi = &v_games_info[6]; assert_eq!(tst_gi.const_settings, simp_gi.const_settings); } #[test] fn test_game_info_themes() { let v_games_info = STD_GAMES_INFO.wait(); let simp_gi = make_simple_action_game(); let tst_gi = &v_games_info[6]; assert_eq!(tst_gi.themes, simp_gi.themes); } #[test] fn test_game_info_all() { let v_games_info = STD_GAMES_INFO.wait(); let simp_gi = make_simple_action_game(); let tst_gi = &v_games_info[6]; assert_eq!(*tst_gi, simp_gi); } #[test] #[should_panic] fn fail_game_info_main_genre() { let v_games_info = STD_GAMES_INFO.wait(); let tst = &v_games_info[6]; assert_eq!(tst.main_genre, GameGenre::Skill); } #[test] #[should_panic] fn fail_game_info_sub_genre() { let v_games_info = STD_GAMES_INFO.wait(); let tst = &v_games_info[5]; let simp = make_simple_action_game(); assert_eq!(tst.sub_genres, simp.sub_genres); } #[test] #[should_panic] fn fail_game_info_target_group() { let v_games_info = STD_GAMES_INFO.wait(); let tst = &v_games_info[5]; let simp = make_simple_action_game(); assert_eq!(tst.target_group, simp.target_group); } #[test] #[should_panic] fn fail_game_info_date() { let v_games_info = STD_GAMES_INFO.wait(); let tst = &v_games_info[5]; let simp = make_simple_action_game(); assert_eq!(tst.date, simp.date); } #[test] #[should_panic] fn fail_game_info_float_set() { let v_games_info = STD_GAMES_INFO.wait(); let tst = &v_games_info[5]; let simp = make_simple_action_game(); assert_eq!(tst.float_settings, simp.float_settings); } #[test] #[should_panic] fn fail_game_info_const_set() { let v_games_info = STD_GAMES_INFO.wait(); let tst = &v_games_info[5]; let simp = make_simple_action_game(); assert_eq!(tst.const_settings, simp.const_settings); } #[test] #[should_panic] fn fail_game_info_themes() { let v_games_info = STD_GAMES_INFO.wait(); let tst = &v_games_info[5]; let simp = make_simple_action_game(); assert_eq!(tst.themes, simp.themes); } fn make_simple_action_game() -> GameInfo<'static> { use GameGenre::*; use Target::*; GameInfo { main_genre: GameGenre::Action, date: "Август 1979".to_string(), target_group: [Teenagers, Grownups].to_vec(), sub_genres: [ Skill, Advenchure, RPG, Platformer, Fighting, FirstPersonShooter, TheerdPersonShooter, Survival, ] .to_vec(), float_settings: FloatTunings::news([-2, -3, 2, 1, -1, -1, 5, -1], [5, 7, 9]), const_settings: ConstTunings::news([10, 40, 30, 20]), themes: [ "Агенты", "Ад", "Альпинизм", "Ангелы", "Андроиды", "Аниме", "Апокалипсис", "Астероиды", "Астронавты", "Атлантида", "Ацтеки", "Барды", "Белки", "Боги", "Боевые искусства", "Бокс", "Борьба", "Бункер", "Вампиры", "Варвары", "Ведьмы", "Вертолеты", "Викинги", "Вирусы", "Военные", "Волшебники", "Воры", "Выживание", "Гангстеры", "Гоблины", "Гладиаторы", "Греческая мифология", "Дайвинг", "Дельфины", "Демоны", "Детективы", "Дикий Запад", "Дизельпанк", "Динозавры", "Дирижабли", "Джунгли", "Драконы", "Дроны", "Древний Египет", "Древний Китай", "Дьяволы", "Диверсанты", "Животные", "Завоевание", "Загадки", "Заговоры", "Замки", "Зомби", "Инки", "Искатели сокровищ", "История", "Каменный век", "Камни", "Каратэ", "Карлики", "Канализация", "Киберпанк", "Киберпространство", "Киборги", "Ковбои", "Кикбоксинг", "Комедия", "Конец света", "Копатель", "Космические корабли", "Космические станции", "Космос", "Кунг Фу", "Крокодилы", "Кладбища", "Ледниковый период", "Магия", "Мафия", "Меха", "Мировые войны", "Монстры", "Мутанты", "Муравьи", "Мумии", "НЛО", "Насекомые", "Наёмники", "Наёмный убийца", "Ниндзя", "Обезьяны", "Оборотни", "Океаны", "Орки", "Охота", "Охотники за головами", "Параллельные миры", "Пауки", "Паркур", "Пейнтбол", "Пираты", "Питомцы", "Пустыня", "Планеты", "Прыжки с парашютом", "Подводные лодки", "Подземелья", "Пожарная часть", "Полиция", "Порталы", "Преступность", "Призраки", "Пришельцы", "Путешествие во времени", "Радиация", "Растения", "Революция", "Римляне", "Римская империя", "Роботы", "Рыцари", "Самолеты", "Самураи", "Скелеты", "Скалолазание", "Сокровища", "Спецназ", "Средневековье", "Старьё", "Стимпанк", "Стрельба из лука", "Супергерои", "Суперзлодеи", "Танки", "Тролли", "Тюрьма", "Убийцы", "Ужасы", "Фехтование", "Фэнтези", "Хищники", "Черви", "Шпионаж", "Эльфы", "Якудза", ] .to_vec(), } } }