use crate::*;
use anyhow::Result;
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use std::{
collections::HashMap,
path::{Path, PathBuf},
};
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Settings {
pub lang: Locale,
pub sub_lang: Option<Locale>,
pub bgm_volume: u8,
pub voice_volume: u8,
pub video_volume: u8,
}
impl Default for Settings {
fn default() -> Self {
Self {
lang: Locale::default(),
sub_lang: None,
bgm_volume: 100,
voice_volume: 100,
video_volume: 100,
}
}
}
#[derive(Debug, Default, Clone, Deserialize, Serialize)]
pub struct GlobalRecord {
pub record: HashMap<String, usize>,
}
impl GlobalRecord {
pub fn visited(&self, ctx: &RawContext) -> bool {
if let Some(max_act) = self.record.get(&ctx.cur_para) {
log::debug!("Test act: {}, max act: {}", ctx.cur_act, max_act);
*max_act >= ctx.cur_act
} else {
false
}
}
pub fn update(&mut self, ctx: &RawContext) {
self.record
.entry(ctx.cur_para.clone())
.and_modify(|act| *act = (*act).max(ctx.cur_act))
.or_insert(ctx.cur_act);
}
}
#[derive(Debug, Default, Clone, Deserialize, Serialize)]
pub struct ActionRecord {
pub history: Vec<RawContext>,
}
impl ActionRecord {
pub fn last_ctx(&self) -> Option<&RawContext> {
self.history.last()
}
pub fn last_ctx_with_game(&self, game: &Game) -> RawContext {
self.last_ctx()
.cloned()
.unwrap_or_else(|| game.start_context())
}
}
pub trait SettingsManager {
fn load_file<T: DeserializeOwned>(&self, path: impl AsRef<Path>) -> Result<T>;
fn save_file<T: Serialize>(&self, path: impl AsRef<Path>, data: &T, pretty: bool)
-> Result<()>;
fn settings_path(&self) -> Result<PathBuf>;
fn load_settings(&self) -> Result<Settings> {
self.load_file(self.settings_path()?)
}
fn save_settings(&self, data: &Settings) -> Result<()> {
self.save_file(self.settings_path()?, data, true)
}
fn global_record_path(&self, game: &str) -> Result<PathBuf>;
fn load_global_record(&self, game: &str) -> Result<GlobalRecord> {
self.load_file(self.global_record_path(game)?)
}
fn save_global_record(&self, game: &str, data: &GlobalRecord) -> Result<()> {
self.save_file(self.global_record_path(game)?, data, false)
}
fn records_path(&self, game: &str) -> Result<impl Iterator<Item = Result<PathBuf>>>;
fn record_path(&self, game: &str, i: usize) -> Result<PathBuf>;
fn load_records(&self, game: &str) -> Result<Vec<ActionRecord>> {
self.records_path(game)?
.map(|path| path.and_then(|path| self.load_file(path)))
.collect()
}
fn save_records(&self, game: &str, contexts: &[ActionRecord]) -> Result<()> {
for (i, ctx) in contexts.iter().enumerate() {
self.save_file(self.record_path(game, i)?, ctx, false)?;
}
Ok(())
}
}