wOxlf/src/game/global_data.rs

152 lines
4.0 KiB
Rust

use std::sync::Arc;
use serenity::prelude::{Mutex, TypeMapKey};
use std::fs::File;
use std::io::{Read, Write};
use crate::config::{BotConfig, GameConfig};
use crate::error::{Result, WoxlfError};
use crate::game::game_state::GameState;
use crate::game::Phase;
use crate::imgur::{get_album_images, Image};
use crate::messages::MessageTemplates;
use chrono::Duration;
#[derive(Debug, Clone)]
pub struct GlobalData {
pub cfg: BotConfig,
pub game_cfg: Option<GameConfig>,
pub templates: Option<MessageTemplates>,
pub game_state: Option<GameState>,
}
impl GlobalData {
pub fn new(cfg: BotConfig) -> Self {
Self {
cfg,
game_cfg: None,
templates: None,
game_state: None,
}
}
pub fn start_game(
&mut self,
game_name: &str,
starting_phase: Phase,
starting_phase_duration: Duration,
) -> Result<()> {
let game_config = self.cfg.get_game_config(game_name).unwrap();
self.templates = Some(MessageTemplates::try_from(game_config.messages.clone())?);
self.game_cfg = Some(game_config);
self.game_state = Some(GameState::new(
starting_phase,
starting_phase_duration,
game_name,
));
Ok(())
}
pub fn save_game_state(&mut self) -> Result<()> {
if let Some(game_state) = &mut self.game_state {
let s = toml::to_string_pretty(game_state)?;
let mut file = File::create(self.cfg.get_game_state_path())?;
file.write_all(s.as_bytes())?;
Ok(())
} else {
Err(WoxlfError::GameNotInProgress)
}
}
pub fn game_state_exists(&self) -> bool {
self.cfg.get_game_state_path().exists()
}
pub fn load_game_state(&mut self) -> Result<()> {
let mut file = File::open(self.cfg.get_game_state_path())?;
let mut data = String::new();
file.read_to_string(&mut data)?;
self.game_state = Some(toml::from_str(&data)?);
let game_config = self
.cfg
.get_game_config(&self.game_state.as_ref().unwrap().game_name)
.unwrap();
self.templates = Some(MessageTemplates::try_from(game_config.messages.clone())?);
self.game_cfg = Some(game_config);
Ok(())
}
pub fn game_state_mut(&mut self) -> Result<&mut GameState> {
match &mut self.game_state {
None => Err(WoxlfError::GameNotInProgress),
Some(game_state) => Ok(game_state),
}
}
pub fn game_state(&self) -> Result<&GameState> {
match &self.game_state {
None => Err(WoxlfError::GameNotInProgress),
Some(game_state) => Ok(game_state),
}
}
pub fn templates(&self) -> Result<&MessageTemplates> {
match &self.templates {
None => Err(WoxlfError::GameNotInProgress),
Some(templates) => Ok(templates),
}
}
pub fn game_cfg(&self) -> Result<&GameConfig> {
match &self.game_cfg {
None => Err(WoxlfError::GameNotInProgress),
Some(game_config) => Ok(game_config),
}
}
pub fn clear_game_state(&mut self) -> Result<()> {
self.game_state = None;
self.game_cfg = None;
self.templates = None;
if self.game_state_exists() {
std::fs::remove_file(self.cfg.get_game_state_path())?;
}
Ok(())
}
pub async fn get_profile_pic_album(&self) -> Result<Vec<Image>> {
Ok(get_album_images(
&self.cfg.imgur_client_id,
&self.game_cfg()?.profile_album_hash,
)
.await?)
}
pub fn get_phase_name(&self) -> Result<String> {
let game_cfg = self.game_cfg()?;
let state = self.game_state()?;
Ok(if state.current_phase == Phase::Day {
game_cfg.vote_phase_name.clone()
} else {
game_cfg.enemy_phase_name.clone()
})
}
}
impl TypeMapKey for GlobalData {
type Value = Arc<Mutex<GlobalData>>;
}