feat: Added interactions with accounts/quests/map
- Bump version to 0.5.0 - Added Quest::complete_for_account public function - Added Map::unlock_room_for_account public function - cli: Added "account unlock" command - cli: "account complete" now uses Quest::complete_for_account - cli: refactored logging
This commit is contained in:
parent
790fa88fe3
commit
f88e010b4f
9 changed files with 231 additions and 138 deletions
38
src/error.rs
38
src/error.rs
|
|
@ -26,3 +26,41 @@ 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}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use std::{fs, io::Write, path::PathBuf};
|
|||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{SquadObject, error::Error};
|
||||
use crate::{SquadObject, account::Account, error::{Error, MapError}};
|
||||
|
||||
/// THE Graph. Actually, this is a Vec.
|
||||
#[derive(Serialize, Deserialize)]
|
||||
|
|
@ -71,7 +71,43 @@ 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
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
use std::{fs, io::Write, path::PathBuf};
|
||||
|
||||
use serde::{ Serialize, Deserialize };
|
||||
use crate::{SquadObject, error::Error};
|
||||
use crate::{SquadObject, account::Account, error::{Error, QuestError}};
|
||||
use toml::value::Date;
|
||||
|
||||
/// Difficulty of the quest
|
||||
|
|
@ -137,3 +137,32 @@ 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(())
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue