squad-quest/src/quest/mod.rs
2ndbeam 0e8cdde697 feat!: Account features
- Bump version to 0.2.0
- Added trait SquadObject
- Implemented SquadObject for Quest and Account
- Implemented Config::load_accounts
- Removed src/quest/error.rs
- Added account tests in tests/main.rs

BREAKING CHANGE: Quest::{load,delete,save} are now provided by
SquadObject trait
2025-12-02 14:33:38 +03:00

139 lines
3.3 KiB
Rust

//! Text-based quests and user solutions for them
use std::{fs, io::Write, path::PathBuf};
use serde::{ Serialize, Deserialize };
use crate::{SquadObject, error::Error};
use toml::value::Date;
/// Difficulty of the quest
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
pub enum QuestDifficulty {
/// Easy quest
Easy,
/// Normal quest
Normal,
/// Hard quest
Hard,
/// Special case of hard quests. Also is a default value for enum
Secret
}
impl Default for QuestDifficulty {
fn default() -> Self {
QuestDifficulty::Secret
}
}
fn default_name() -> String {
"Slay the dragon".to_string()
}
fn default_description() -> String {
"Just do it in any way".to_string()
}
fn default_answer() -> String {
"Attachment should show that the dragon was slain".to_string()
}
/// Quest struct
#[derive(Serialize, Deserialize, Debug, PartialEq)]
#[serde(default)]
pub struct Quest {
/// Quest identifier
pub id: u16,
/// Difficulty of this quest
pub difficulty: QuestDifficulty,
/// Reward for the quest
pub reward: u32,
/// Visible quest name
pub name: String,
/// Visible quest description
pub description: String,
/// Quest answer, available for admins
pub answer: String,
/// Is quest available for regular users
pub public: bool,
/// When quest becomes public
pub available_on: Option<Date>,
/// When quest expires
pub deadline: Option<Date>
}
impl Default for Quest {
fn default() -> Self {
Quest {
id: u16::default(),
difficulty: QuestDifficulty::default(),
reward: u32::default(),
name: default_name(),
description: default_description(),
answer: default_answer(),
public: false,
available_on: None,
deadline: None
}
}
}
impl SquadObject for Quest {
fn load(path: PathBuf) -> Result<Self, Error> {
match std::fs::read_to_string(path) {
Ok(string) => {
match toml::from_str::<Self>(&string) {
Ok(object) => Ok(object),
Err(error) => Err(Error::TomlDeserializeError(error))
}
},
Err(error) => Err(Error::IoError(error))
}
}
fn delete(path: PathBuf) -> Result<(), Error> {
match Quest::load(path.clone()) {
Ok(_) => {
if let Err(error) = fs::remove_file(path) {
return Err(Error::IoError(error));
}
Ok(())
},
Err(error) => Err(error)
}
}
fn save(&self, path: PathBuf) -> Result<(), Error> {
let filename = format!("{}.toml", self.id);
let mut full_path = path;
full_path.push(filename);
let str = match toml::to_string_pretty(&self) {
Ok(string) => string,
Err(error) => {
return Err(Error::TomlSerializeError(error));
}
};
let mut file = match fs::File::create(full_path) {
Ok(f) => f,
Err(error) => {
return Err(Error::IoError(error));
}
};
if let Err(error) = file.write_all(str.as_bytes()) {
return Err(Error::IoError(error));
}
Ok(())
}
}