feat: Quest loading
- Added config::Config::load_quests() - Added quest::error::QuestError error type - Updated documentation
This commit is contained in:
parent
4e3c137f8b
commit
a5eac1b64f
5 changed files with 130 additions and 10 deletions
|
|
@ -1,4 +1,4 @@
|
|||
//! Module for handling user accounts
|
||||
//! User accounts
|
||||
|
||||
use serde::{ Serialize, Deserialize };
|
||||
|
||||
|
|
@ -10,11 +10,11 @@ fn default_id() -> String {
|
|||
#[derive(Serialize, Deserialize)]
|
||||
pub struct Account {
|
||||
|
||||
/// User id, specific to used service
|
||||
/// User identifier, specific to used service
|
||||
#[serde(default = "default_id")]
|
||||
pub id: String,
|
||||
|
||||
/// User balance,
|
||||
/// User balance
|
||||
#[serde(default)]
|
||||
pub balance: u32,
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
//! Module for handling configuration
|
||||
//! Configuration file that handles (de-)serializing other components
|
||||
|
||||
use std::path::PathBuf;
|
||||
use std::{fs::{self, DirEntry},path::PathBuf};
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::quest::{Quest,error::QuestError};
|
||||
|
||||
/// Struct for containing paths to other (de-)serializable things
|
||||
#[derive(Deserialize)]
|
||||
pub struct Config {
|
||||
|
|
@ -30,10 +32,35 @@ impl Default for Config {
|
|||
}
|
||||
}
|
||||
|
||||
fn handle_quest_entry(quest_entry: DirEntry) -> Result<Quest, QuestError>{
|
||||
let filetype = quest_entry.file_type();
|
||||
if let Err(error) = filetype {
|
||||
return Err(QuestError::IoError(error));
|
||||
}
|
||||
|
||||
let path = quest_entry.path();
|
||||
|
||||
let filetype = filetype.unwrap();
|
||||
if !filetype.is_file() {
|
||||
return Err(QuestError::IsNotAFile(path));
|
||||
}
|
||||
|
||||
Quest::load(path)
|
||||
}
|
||||
|
||||
impl Config {
|
||||
/// Deserialize config from TOML
|
||||
/// Logs all errors and returns default config if that happens
|
||||
///
|
||||
/// # Examples
|
||||
/// ```rust
|
||||
/// use squad_quest::config::Config;
|
||||
///
|
||||
/// let path = "cfg/config.toml".into();
|
||||
/// let config = Config::load(path);
|
||||
/// ```
|
||||
pub fn load(path: PathBuf) -> Self {
|
||||
match std::fs::read_to_string(path) {
|
||||
match fs::read_to_string(path) {
|
||||
Ok(string) => {
|
||||
match toml::from_str::<Config>(&string) {
|
||||
Ok(conf) => {
|
||||
|
|
@ -52,4 +79,51 @@ impl Config {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Load [Vec]<[Quest]> from quests folder.
|
||||
/// Also logs errors and counts successfully loaded quests.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```rust
|
||||
/// use squad_quest::{config::Config, quest::Quest};
|
||||
///
|
||||
///
|
||||
/// let path = "cfg/config.toml".into();
|
||||
/// let config = Config::load(path);
|
||||
/// let quests = config.load_quests();
|
||||
///
|
||||
/// for quest in quests {
|
||||
/// println!("Quest #{} {}", quest.id, quest.name);
|
||||
/// }
|
||||
/// ```
|
||||
pub fn load_quests(&self) -> Vec<Quest> {
|
||||
let mut out_vec = Vec::new();
|
||||
|
||||
match fs::read_dir(&self.quests_path) {
|
||||
Ok(iter) => {
|
||||
for entry in iter {
|
||||
match entry {
|
||||
Ok(quest_entry) => {
|
||||
match handle_quest_entry(quest_entry) {
|
||||
Ok(quest) => out_vec.push(quest),
|
||||
Err(error) => {
|
||||
eprintln!("Error on loading single quest: {error}");
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(error) => {
|
||||
eprintln!("Error on loading single quest: {error}");
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(error) => {
|
||||
eprintln!("Error on loading quests: {error}");
|
||||
}
|
||||
}
|
||||
|
||||
println!("Loaded {} quests successfully", out_vec.len());
|
||||
|
||||
out_vec
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
//! Module for handling map, which is a graph of rooms
|
||||
|
||||
//! Map, a.k.a. a graph of rooms
|
||||
#![allow(dead_code)]
|
||||
struct Map;
|
||||
|
||||
/// Graph for room nodes
|
||||
pub struct Map;
|
||||
|
|
|
|||
25
src/quest/error.rs
Normal file
25
src/quest/error.rs
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
//! Module for handling quest loading errors
|
||||
|
||||
use std::{fmt, path::PathBuf};
|
||||
|
||||
/// Error raised when trying to parse quest file
|
||||
#[derive(Debug)]
|
||||
#[non_exhaustive]
|
||||
pub enum QuestError {
|
||||
/// Given path is not a file
|
||||
IsNotAFile(PathBuf),
|
||||
/// std::io::Error happenned when loading
|
||||
IoError(std::io::Error),
|
||||
/// toml::de::Error happened when loading
|
||||
TomlError(toml::de::Error)
|
||||
}
|
||||
|
||||
impl fmt::Display for QuestError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
QuestError::IsNotAFile(path) => write!(f, "{:?} is not a file", path),
|
||||
QuestError::IoError(error) => write!(f, "io error: {error}"),
|
||||
QuestError::TomlError(error) => write!(f, "parse error: {error}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,11 @@
|
|||
//! Module for handling text-based quests and user answers
|
||||
//! Text-based quests and user solutions for them
|
||||
|
||||
pub mod error;
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
use serde::{ Serialize, Deserialize };
|
||||
use error::QuestError;
|
||||
|
||||
/// Difficulty of the quest
|
||||
#[derive(Serialize, Deserialize)]
|
||||
|
|
@ -60,3 +65,18 @@ pub struct Quest {
|
|||
#[serde(default = "default_answer")]
|
||||
pub answer: String,
|
||||
}
|
||||
|
||||
impl Quest {
|
||||
/// Parse quest TOML or return error
|
||||
pub fn load(path: PathBuf) -> Result<Self, QuestError> {
|
||||
match std::fs::read_to_string(path) {
|
||||
Ok(string) => {
|
||||
match toml::from_str::<Quest>(&string) {
|
||||
Ok(quest) => Ok(quest),
|
||||
Err(error) => Err(QuestError::TomlError(error))
|
||||
}
|
||||
},
|
||||
Err(error) => Err(QuestError::IoError(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue