diff --git a/Cargo.lock b/Cargo.lock index a87f7bb..3d80605 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -332,7 +332,7 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "squad-quest" -version = "0.5.0" +version = "0.4.0" dependencies = [ "serde", "toml", @@ -340,7 +340,7 @@ dependencies = [ [[package]] name = "squad-quest-cli" -version = "0.5.0" +version = "0.4.0" dependencies = [ "chrono", "clap", diff --git a/Cargo.toml b/Cargo.toml index ec4ada1..e66a59f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ members = ["cli"] [workspace.package] -version = "0.5.1" +version = "0.4.0" edition = "2024" repository = "https://2ndbeam.ru/git/2ndbeam/squad-quest" license = "MIT" diff --git a/cfg/config.toml b/cfg/config.toml index 0a9e166..1d81f41 100644 --- a/cfg/config.toml +++ b/cfg/config.toml @@ -1,4 +1,10 @@ -quests_path = "quests" -accounts_path = "accounts" -map = "map.toml" -verbose = true +# Default config + +# Path to quests folder relative to config +quests_path = "./quests" + +# Path to accounts folder relative to config +accounts_path = "./accounts" + +# Path to map .toml file relative to config +map = "./map.toml" diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 56fed8f..ca88ec5 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -9,5 +9,5 @@ license.workspace = true chrono = "0.4.42" clap = { version = "4.5.53", features = ["derive"] } serde = { version = "1.0.228", features = ["derive"] } -squad-quest = { version = "0.5.0", path = ".." } +squad-quest = { version = "0.4.0", path = ".." } toml = "0.9.8" diff --git a/cli/src/cli/account.rs b/cli/src/cli/account.rs index bde7393..c6da1ac 100644 --- a/cli/src/cli/account.rs +++ b/cli/src/cli/account.rs @@ -12,8 +12,6 @@ pub enum AccountCommands { Complete(AccountCompleteArgs), /// Delete account Delete(AccountDeleteArgs), - /// Unlock room for account if it has enough balance - Unlock(AccountUnlockArgs), } #[derive(Args)] @@ -57,10 +55,3 @@ pub struct AccountDeleteArgs { pub id: String, } -#[derive(Args)] -pub struct AccountUnlockArgs { - /// Id of the account - pub account: String, - /// Id of the room to unlock - pub room: u16, -} diff --git a/cli/src/cli/mod.rs b/cli/src/cli/mod.rs index db78d60..e44c361 100644 --- a/cli/src/cli/mod.rs +++ b/cli/src/cli/mod.rs @@ -1,6 +1,6 @@ use std::path::PathBuf; -use clap::{Args,Parser,Subcommand}; +use clap::{Parser,Subcommand}; pub mod account; pub mod map; @@ -23,8 +23,6 @@ pub struct Cli { #[derive(Subcommand)] pub enum Objects { - /// Initialize new SquadQuest in current working directory - Init(InitArgs), /// Operations on the quests #[command(subcommand)] Quest(quest::QuestCommands), @@ -36,8 +34,3 @@ pub enum Objects { Map(map::MapCommands), } -#[derive(Args)] -pub struct InitArgs { - #[arg(long,short)] - pub path: Option, -} diff --git a/cli/src/cli/quest.rs b/cli/src/cli/quest.rs index 1ed541c..41a7820 100644 --- a/cli/src/cli/quest.rs +++ b/cli/src/cli/quest.rs @@ -63,8 +63,7 @@ pub struct QuestListArgs { #[derive(Args)] pub struct QuestCreateArgs { - /// Difficulty of the quest - #[arg(value_enum)] + /// Difficulty of the quest #[arg(value_enum)] pub difficulty: QuestDifficulty, /// Reward for the quest pub reward: u32, diff --git a/cli/src/main.rs b/cli/src/main.rs index d120a9d..cd2e5f6 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -1,8 +1,8 @@ -use std::{fs::DirBuilder, path::{Path, PathBuf}}; +use std::path::Path; use clap::Parser; use squad_quest_cli::cli::{Cli,Objects,account::*,map::*,quest::*}; -use squad_quest::{SquadObject, account::Account, config::Config, error::Error, map::{Map, Room}, quest::Quest}; +use squad_quest::{SquadObject, account::Account, config::Config, map::{Map, Room}, quest::Quest}; use toml::value::Date; use chrono::{Datelike, NaiveDate, Utc}; @@ -17,25 +17,19 @@ fn print_quest_long(quest: &Quest) { println!("Answer:\n{}", quest.answer); } -fn do_and_log(result: Result<(),Error>, log: bool, ok_text: String) { - match result { - Ok(_) if log => println!("{ok_text}"), - Err(error) if log => eprintln!("Error: {error}"), - _ => {}, - } -} +fn main() { + let cli = Cli::parse(); -fn load_config_silent(quiet: bool, path: PathBuf) -> Config { - match quiet { - false => Config::load(path.clone()), + let config = match cli.quiet { + false => Config::load(cli.config.clone()), true => { - match Config::try_load(path.clone()) { + match Config::try_load(cli.config.clone()) { Ok(mut config) => { config.verbose = false; config }, Err(_) => { - let path = path.clone().parent().unwrap_or(&Path::new(".")).to_owned(); + let path = cli.config.clone().parent().unwrap_or(&Path::new(".")).to_owned(); Config { verbose: false, path, @@ -44,61 +38,9 @@ fn load_config_silent(quiet: bool, path: PathBuf) -> Config { } } }, - } -} - -fn main() { - let cli = Cli::parse(); - - let config = load_config_silent(cli.quiet, cli.config.clone()); - let map_save = |map: Map, map_path: PathBuf| { map.save(map_path.parent().unwrap_or(Path::new("")).to_owned()) }; + }; match &cli.command { - Objects::Init(args) => { - let path = match args.path.clone() { - Some(path) => path, - None => PathBuf::new(), - }; - - match DirBuilder::new().recursive(true).create(path.clone()) { - Ok(_) if !cli.quiet => println!("Created directory {:?}", path), - Err(error) => { - if !cli.quiet { eprintln!("Error: {error}"); } - return; - }, - _ => {}, - } - - let config = Config { - path: path.clone(), - ..Default::default() - }; - - do_and_log(config.save(path.clone()), !cli.quiet, format!("Created file {:?}/config.toml", path)); - let mut config_path = path.clone(); - config_path.push("config.toml"); - let mut config = load_config_silent(true, config_path); - config.verbose = Config::default().verbose; - - let map = Map::default(); - let map_path = config.full_map_path(); - - do_and_log(map_save(map, map_path.clone()), !cli.quiet, format!("Created file {:?}/map.toml", map_path)); - - let quests_path = config.full_quests_path(); - let accounts_path = config.full_accounts_path(); - - for path in [quests_path, accounts_path] { - match DirBuilder::new().recursive(true).create(path.clone()) { - Ok(_) if !cli.quiet => println!("Created directory {:?}", path), - Err(error) => { - if !cli.quiet { eprintln!("Error: {error}"); } - return; - }, - _ => {}, - } - } - }, Objects::Quest(commands) => { let mut quests = config.load_quests(); let mut path = config.full_quests_path(); @@ -119,19 +61,20 @@ fn main() { Some(quest) => quest.id + 1u16, None => 0u16 }; - - let mut check_path = path.clone(); - check_path.push(format!("{next_id}.toml")); - match std::fs::exists(&check_path) { + + path.push(format!("{next_id}.toml")); + match std::fs::exists(&path) { Ok(exists) => { if exists { - if !cli.quiet { eprintln!("Error: {:?} is not empty.", path); } + if !cli.quiet { + eprintln!("Error: {:?} is not empty.", path); + } return; } }, Err(error) => { if !cli.quiet { - eprintln!("Error: {error}"); + eprintln!("Error while retrieving {:?}: {}.", path, error); } return; } @@ -149,11 +92,17 @@ fn main() { deadline: args.deadline.clone() }; - do_and_log(quest.save(path), !cli.quiet, format!("Created quest #{}.", quest.id)); + match quest.save(path) { + Ok(_) if !cli.quiet => println!("Successfully saved quest #{}", quest.id), + Err(error) if !cli.quiet => eprintln!("Error while saving quest: {error}"), + _ => {}, + } }, QuestCommands::Update(args) => { let Some(quest) = quests.iter().find(|q| q.id == args.id) else { - if !cli.quiet { eprintln!("Error: Quest #{} not found.", args.id); } + if !cli.quiet { + eprintln!("Error: Quest #{} not found.", args.id); + } return; }; let quest = Quest { @@ -170,28 +119,17 @@ fn main() { available_on: args.available.clone().or(quest.available_on.clone()), deadline: args.deadline.clone().or(quest.deadline.clone()) }; - - do_and_log(quest.save(path), !cli.quiet, format!("Updated quest #{}.", quest.id)); + match quest.save(path) { + Ok(_) if !cli.quiet => println!("Updated quest #{}", quest.id), + Err(error) if !cli.quiet => eprintln!("Error while updating quest: {error}"), + _ => {}, + } }, QuestCommands::Delete(args) => { - path.push(format!("{}.toml", args.id)); match Quest::delete(path) { - Ok(_) => { - if !cli.quiet { println!("Deleted quest #{}.", args.id); } - - let mut accounts = config.load_accounts(); - let accounts_path = config.full_accounts_path(); - for account in accounts.iter_mut() { - if let Some(index) = account.quests_completed.iter().position(|qid| *qid == args.id) { - account.quests_completed.remove(index); - do_and_log(account.save(accounts_path.clone()), !cli.quiet, format!("Removed quest #{} from account \"{}\" completed quests", args.id, account.id)); - } - } - }, - Err(error) if !cli.quiet => { - eprintln!("Error: {error}"); - }, - _ => {}, + Ok(_) if !cli.quiet => println!("Successfully deleted quest #{}", args.id), + Err(error) if !cli.quiet => eprintln!("Error deleting quest #{}: {}", args.id, error), + _ => {}, } }, QuestCommands::Daily => { @@ -204,7 +142,12 @@ fn main() { for quest in quests.iter_mut().filter(|q| !q.public && q.available_on.is_some_and(|date| date.le(&toml_today))) { quest.public = true; - do_and_log(quest.save(path.clone()), !cli.quiet, format!("Published quest #{}.", quest.id)); + + match quest.save(path.clone()) { + Ok(_) if !cli.quiet => println!("Published quest #{}", quest.id), + Err(error) if !cli.quiet => eprintln!("Error while publishing quest: {error}"), + _ => {}, + } } }, QuestCommands::Publish(args) => { @@ -215,14 +158,23 @@ fn main() { let not_str = if args.reverse {" not "} else {" "}; if quest.public != args.reverse { - if !cli.quiet { eprintln!("Error: quest #{} is already{}public.", quest.id, not_str); } + if !cli.quiet { + eprintln!("Quest #{} is already{}public", quest.id, not_str); + } return; } quest.public = !args.reverse; - do_and_log(quest.save(path), !cli.quiet, format!("Published quest #{}.", quest.id)); + + match quest.save(path.clone()) { + Ok(_) if !cli.quiet => println!("Published quest #{}", quest.id), + Err(error) if !cli.quiet => eprintln!("Error while publishing quest: {error}"), + _ => {}, + } + }, + None if !cli.quiet => { + eprintln!("Error: couldn't find quest with id {}.", args.id); }, - None if !cli.quiet => eprintln!("Error: quest #{} not found.", args.id), _ => {}, } }, @@ -234,6 +186,7 @@ fn main() { match commands { AccountCommands::List => { + for account in accounts { println!("\"{}\": Balance {}", account.id, account.balance); } @@ -245,16 +198,27 @@ fn main() { }; if let Some(_) = accounts.iter().find(|a| a.id == account.id) { - if !cli.quiet { eprintln!("Error: account \"{}\" exists.", account.id); } + if !cli.quiet { + eprintln!("Error: account {} exists.", account.id); + } return; } - do_and_log(account.save(path), !cli.quiet, format!("Created account \"{}\".", account.id)); + match account.save(path) { + Ok(_) if !cli.quiet => println!("Successfully created account \"{}\"", account.id), + Err(error) if !cli.quiet => eprintln!("Error while saving account: {error}"), + _ => {}, + } }, AccountCommands::Balance(args) => { - let Some(account) = accounts.iter_mut().find(|a| a.id == args.id) else { - if !cli.quiet { eprintln!("Error: account \"{}\" not found.", args.id); } - return; + let account = match accounts.iter_mut().find(|a| a.id == args.id) { + Some(acc) => acc, + None => { + if !cli.quiet { + eprintln!("Could not find account \"{}\"", args.id); + } + return; + } }; match args.action { @@ -269,7 +233,9 @@ fn main() { if args.negative_ok { account.balance = 0u32; } else { - if !cli.quiet { eprintln!("Error: account \"{}\" balance is less than {}.", account.id, args.value); } + if !cli.quiet { + eprintln!("Error: balance ({}) is less than {}.", account.balance, args.value); + } return; } } else { @@ -278,54 +244,54 @@ fn main() { } } - do_and_log(account.save(path), !cli.quiet, format!("Updated balance of account \"{}\".", account.id)); + match account.save(path) { + Ok(_) if !cli.quiet => println!("Successfully updated account \"{}\" balance", account.id), + Err(error) if !cli.quiet => eprintln!("Error while saving account: {error}"), + _ => {}, + } }, AccountCommands::Complete(args) => { - let Some(account) = accounts.iter_mut().find(|a| a.id == args.account) else { - if !cli.quiet { eprintln!("Error: account \"{}\" not found.", args.account); } - return; + let account = match accounts.iter_mut().find(|a| a.id == args.account) { + Some(acc) => acc, + None => { + if !cli.quiet { + eprintln!("Could not find account \"{}\"", args.account); + } + return; + } }; let quests = config.load_quests(); - - let quest = match quests.iter().find(|q| q.id == args.quest) { - Some(quest) => quest, - None => { - if !cli.quiet { eprintln!("Error: quest #{} not found.", args.quest); } - return; - }, - }; - match quest.complete_for_account(account) { - Err(error) if !cli.quiet => println!("Error: {error}"), - Ok(_) => do_and_log(account.save(path), !cli.quiet, format!("Completed quest #{} on account \"{}\".", args.quest, account.id)), + if let None = quests.iter().find(|q| q.id == args.quest) { + if !cli.quiet { + eprintln!("Could not find quest #{}", args.quest); + } + return; + } + + match account.quests_completed.iter().find(|qid| **qid == args.quest) { + Some(_) if !cli.quiet => { + println!("Quest #{} is already completed on account \"{}\"", args.quest, args.account); + }, + None => { + account.quests_completed.push(args.quest); + match account.save(path) { + Ok(_) if !cli.quiet => println!("Successfully completed quest #{} on account \"{}\".", args.quest, account.id), + Err(error) if !cli.quiet => eprintln!("Error while saving account: {error}"), + _ => {}, + } + }, _ => {}, } }, AccountCommands::Delete(args) => { path.push(format!("{}.toml", args.id)); - do_and_log(Account::delete(path), !cli.quiet, format!("Deleted account \"{}\".", args.id)) - }, - AccountCommands::Unlock(args) => { - let Some(account) = accounts.iter_mut().find(|a| a.id == args.account) else { - if !cli.quiet { eprintln!("Error: account \"{}\" not found.", args.account) }; - return; - }; - - let map = match Map::load(config.full_map_path()) { - Ok(map) => map, - Err(error) => { - if !cli.quiet { eprintln!("Error: {error}"); } - return; - } - }; - - if let Err(error) = map.unlock_room_for_account(args.room, account) { - eprintln!("Error: {error}"); - return; + match Account::delete(path) { + Ok(_) if !cli.quiet => println!("Successfully deleted account \"{}\".", args.id), + Err(error) if !cli.quiet => eprintln!("Error while deleting account: {error}"), + _ => {}, } - - do_and_log(account.save(path), !cli.quiet, format!("Unlocked room #{} for account \"{}\"", args.room, args.account)); }, } }, @@ -334,11 +300,12 @@ fn main() { let mut map = match Map::load(map_path.clone()) { Ok(map) => map, Err(error) => { - if !cli.quiet { eprintln!("Error: {error}"); } + if !cli.quiet { + eprintln!("Error while loading map: {error}"); + } return; } }; - match commands { MapCommands::List => { for room in map.room { @@ -354,17 +321,22 @@ fn main() { let room = Room { id: last_id, name: args.name.clone(), - value: args.value, description: args.description.clone(), ..Default::default() }; let r_id = room.id; map.room.push(room); - do_and_log(map_save(map, map_path), !cli.quiet, format!("Created room #{r_id}.")) + match map.save(map_path.parent().unwrap_or(Path::new("")).to_owned()) { + Ok(_) if !cli.quiet => println!("Created room #{}.", r_id), + Err(error) if !cli.quiet => eprintln!("Error while saving map: {error}"), + _ => {}, + } }, MapCommands::Delete(args) => { let Some(room) = map.room.iter().find(|r| r.id == args.id) else { - if !cli.quiet { eprintln!("Error: room #{} not found.", args.id); } + if !cli.quiet { + eprintln!("Error: Room #{} not found", args.id); + } return; }; @@ -379,29 +351,17 @@ fn main() { room.children.remove(idx); } - match map_save(map, map_path) { - Ok(_) => { - if !cli.quiet { println!("Deleted room #{r_id}."); } - - let mut accounts = config.load_accounts(); - let accounts_path = config.full_accounts_path(); - - for account in accounts.iter_mut() { - if let Some(index) = account.rooms_unlocked.iter().position(|rid| *rid == r_id) { - account.rooms_unlocked.remove(index); - do_and_log(account.save(accounts_path.clone()), !cli.quiet, format!("Removed room #{r_id} from account \"{}\" unlocked rooms.", account.id)); - } - } - }, - Err(error) if !cli.quiet => { - eprintln!("Error: {error}"); - }, + match map.save(map_path.parent().unwrap_or(Path::new("")).to_owned()) { + Ok(_) if !cli.quiet => println!("Deleted room #{}.", r_id), + Err(error) if !cli.quiet => eprintln!("Error while saving map: {error}"), _ => {}, } }, MapCommands::Update(args) => { let Some(room) = map.room.iter_mut().find(|r| r.id == args.id) else { - if !cli.quiet { eprintln!("Error: room #{} not found", args.id); } + if !cli.quiet { + eprintln!("Error: Room #{} not found", args.id); + } return; }; @@ -417,7 +377,11 @@ fn main() { room.value = value; } - do_and_log(map_save(map, map_path), !cli.quiet, format!("Updated room #{}.", args.id)) + match map.save(map_path.parent().unwrap_or(Path::new("")).to_owned()) { + Ok(_) if !cli.quiet => println!("Updated room #{}.", args.id), + Err(error) if !cli.quiet => eprintln!("Error while saving map: {error}"), + _ => {}, + } }, MapCommands::Connect(args) | MapCommands::Disconnect(args) => { let connect = match commands { @@ -428,21 +392,28 @@ fn main() { // We iterate twice to make references first->second and second->first for (first, second) in [(args.first, args.second),(args.second, args.first)] { let Some(room) = map.room.iter_mut().find(|r| r.id == first) else { - if !cli.quiet { eprintln!("Error: room #{} not found.", first); } + if !cli.quiet { + eprintln!("Error: Room #{} not found", first); + } return; }; match room.children.iter().position(|id| *id == second) { - Some(_) if connect && !cli.quiet => println!("Room #{} already has reference to #{}.", first, second), + Some(_) if connect && !cli.quiet => println!("Room #{} already has reference to #{}", first, second), None if connect => room.children.push(second), Some(id) if !connect => {room.children.remove(id as usize);}, - None if !connect && !cli.quiet => println!("Room #{} has no reference to #{}.", first, second), + None if !connect && !cli.quiet => println!("Room #{} has no reference to #{}", first, second), _ => {}, } } let connected = if connect { "Connected" } else { "Disconnected" }; - do_and_log(map_save(map, map_path), !cli.quiet, format!("{connected} rooms #{} <-> #{}.", args.first, args.second)); + + match map.save(map_path.parent().unwrap_or(Path::new("")).to_owned()) { + Ok(_) if !cli.quiet => println!("{connected} rooms #{} <-> #{}.", args.first, args.second), + Err(error) if !cli.quiet => eprintln!("Error while saving map: {error}"), + _ => {}, + } }, } } diff --git a/src/config/mod.rs b/src/config/mod.rs index f0b2f94..c805002 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -1,12 +1,12 @@ //! Configuration file that handles (de-)serializing other components -use std::{fs::{self, DirEntry}, io::Write, path::{Path, PathBuf}}; -use serde::{Deserialize, Serialize}; +use std::{fs::{self, DirEntry},path::{Path, PathBuf}}; +use serde::Deserialize; use crate::{SquadObject, account::Account, error::Error, quest::Quest}; /// Struct for containing paths to other (de-)serializable things -#[derive(Serialize, Deserialize)] +#[derive(Deserialize)] #[serde(default)] pub struct Config { /// Path to config directory @@ -112,42 +112,6 @@ impl Config { } } - /// Serialize config into TOML. - /// Config will be saved as `path/config.toml` - /// - /// # Examples - /// ```rust - /// use squad_quest::config::Config; - /// - /// let path = "cfg".into(); - /// - /// let config = Config::default(); - /// - /// if let Err(error) = config.save(path) { - /// // handle error - /// } - /// ``` - pub fn save(&self, path: PathBuf) -> Result<(), Error> { - let mut path = path; - path.push("config.toml"); - - 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(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(()) - } - /// Deserialize config from TOML /// /// # Examples diff --git a/src/error.rs b/src/error.rs index 0804b58..501d6c4 100644 --- a/src/error.rs +++ b/src/error.rs @@ -26,41 +26,3 @@ impl fmt::Display for Error { } } } - -/// Error related to quest logic -#[derive(Debug)] -#[non_exhaustive] -pub enum QuestError { - /// Quest (self.0) is already completed for given account (self.1) - AlreadyCompleted(u16, String), -} - -impl fmt::Display for QuestError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::AlreadyCompleted(quest_id, account_id) => write!(f, "quest #{quest_id} is already completed for account \"{account_id}\""), - } - } -} - -/// Error related to map logic -#[derive(Debug)] -#[non_exhaustive] -pub enum MapError { - /// Room not found in map file - RoomNotFound(u16), - /// Room (self.0) is already unlocked on account (self.1) - RoomAlreadyUnlocked(u16, String), - /// Account (self.1) does not have much money (self.0) - InsufficientFunds(u16, String), -} - -impl fmt::Display for MapError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::RoomNotFound(id) => write!(f, "could not find room #{id}"), - Self::RoomAlreadyUnlocked(room_id, account_id) => write!(f, "room #{room_id} is already unlocked on account \"{account_id}\""), - Self::InsufficientFunds(room_id, account_id) => write!(f, "account \"{account_id}\" does not have enough money to unlock room #{room_id}"), - } - } -} diff --git a/src/map/mod.rs b/src/map/mod.rs index 69ccb68..17e42ce 100644 --- a/src/map/mod.rs +++ b/src/map/mod.rs @@ -4,7 +4,7 @@ use std::{fs, io::Write, path::PathBuf}; use serde::{Deserialize, Serialize}; -use crate::{SquadObject, account::Account, error::{Error, MapError}}; +use crate::{SquadObject, error::Error}; /// THE Graph. Actually, this is a Vec. #[derive(Serialize, Deserialize)] @@ -71,43 +71,7 @@ impl SquadObject for Map { Ok(()) } -} -impl Map { - /// Try to unlock room for account, or return [MapError] - /// - /// # Examples - /// ```rust - /// use squad_quest::{account::Account,map::{Map,Room},error::MapError}; - /// - /// let map = Map { - /// room: vec![Room { id: 0, value: 100, ..Default::default() }], - /// }; - /// - /// let mut account = Account { balance: 100, ..Default::default() }; - /// - /// if let Err(error) = map.unlock_room_for_account(0, &mut account) { - /// // handle error - /// } - /// ``` - pub fn unlock_room_for_account(&self, room_id: u16, account: &mut Account) -> Result<(), MapError> { - let Some(room) = self.room.iter().find(|r| r.id == room_id) else { - return Err(MapError::RoomNotFound(room_id)); - }; - - if let Some(_) = account.rooms_unlocked.iter().find(|rid| **rid == room_id) { - return Err(MapError::RoomAlreadyUnlocked(room_id, account.id.clone())); - } - - if account.balance < room.value { - return Err(MapError::InsufficientFunds(room_id, account.id.clone())); - } - - account.balance -= room.value; - account.rooms_unlocked.push(room_id); - - Ok(()) - } } /// Component of the map diff --git a/src/quest/mod.rs b/src/quest/mod.rs index 669d061..b8d7886 100644 --- a/src/quest/mod.rs +++ b/src/quest/mod.rs @@ -3,7 +3,7 @@ use std::{fs, io::Write, path::PathBuf}; use serde::{ Serialize, Deserialize }; -use crate::{SquadObject, account::Account, error::{Error, QuestError}}; +use crate::{SquadObject, error::Error}; use toml::value::Date; /// Difficulty of the quest @@ -137,32 +137,3 @@ impl SquadObject for Quest { Ok(()) } } - -impl Quest { - /// Complete quest for account and add reward to it's balance. - /// Does nothing and returns [QuestError::AlreadyCompleted] - /// if it is already completed. - /// - /// # Examples - /// - /// ```rust - /// use squad_quest::{account::Account,quest::Quest}; - /// - /// let quest = Quest::default(); - /// let mut account = Account::default(); - /// - /// if let Err(error) = quest.complete_for_account(&mut account) { - /// // handle error - /// } - /// ``` - pub fn complete_for_account(&self, account: &mut Account) -> Result<(),QuestError> { - match account.quests_completed.iter().find(|qid| **qid == self.id) { - Some(_) => Err(QuestError::AlreadyCompleted(self.id, account.id.clone())), - None => { - account.quests_completed.push(self.id); - account.balance += self.reward; - Ok(()) - }, - } - } -}