feat!: Added several fields to Quest struct
- Added field public - Added optional field available_on - Added optional field deadline - Updated tests and CLI to use these fields
This commit is contained in:
parent
96235086d7
commit
78da6dde05
4 changed files with 60 additions and 6 deletions
|
|
@ -1,7 +1,20 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use clap::{Parser,Subcommand,Args,ValueEnum};
|
||||
use serde::Deserialize;
|
||||
use squad_quest::{config::Config,quest::{Quest,QuestDifficulty as LibQuestDifficulty}};
|
||||
use toml::value::Date;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct DateWrapper {
|
||||
date: Date
|
||||
}
|
||||
|
||||
fn parse_date(arg: &str) -> Result<Date,toml::de::Error> {
|
||||
let toml_str = format!("date = {arg}");
|
||||
let wrapper: DateWrapper = toml::from_str(&toml_str)?;
|
||||
Ok(wrapper.date)
|
||||
}
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(version, about, long_about = None)]
|
||||
|
|
@ -76,7 +89,16 @@ struct QuestCreateArgs {
|
|||
/// Visible description of the quest
|
||||
description: String,
|
||||
/// Answer for the quest for admins
|
||||
answer: String
|
||||
answer: String,
|
||||
/// Create quest and make it public immediately
|
||||
#[arg(short,long)]
|
||||
public: bool,
|
||||
/// Make quest available on date (format = YYYY-MM-DD, ex. 2025-12-24)
|
||||
#[arg(short,long,value_parser = parse_date)]
|
||||
available: Option<Date>,
|
||||
/// Quest expiration date (format = YYYY-MM-DD, ex. 2025-12-24)
|
||||
#[arg(short,long,value_parser = parse_date)]
|
||||
deadline: Option<Date>,
|
||||
}
|
||||
|
||||
#[derive(Args)]
|
||||
|
|
@ -97,7 +119,16 @@ struct QuestUpdateArgs {
|
|||
description: Option<String>,
|
||||
/// Answer for the quest for admins
|
||||
#[arg(long)]
|
||||
answer: Option<String>
|
||||
answer: Option<String>,
|
||||
/// Create quest and make it public immediately
|
||||
#[arg(long)]
|
||||
public: Option<bool>,
|
||||
/// Make quest available on date (format = YYYY-MM-DD, ex. 2025-12-24)
|
||||
#[arg(long,value_parser = parse_date)]
|
||||
available: Option<Date>,
|
||||
/// Quest expiration date (format = YYYY-MM-DD, ex. 2025-12-24)
|
||||
#[arg(long,value_parser = parse_date)]
|
||||
deadline: Option<Date>,
|
||||
}
|
||||
|
||||
#[derive(Args)]
|
||||
|
|
@ -141,7 +172,7 @@ fn main() {
|
|||
let next_id = match quests.last() {
|
||||
Some(quest) if quest.id == u16::MAX => {
|
||||
panic!("Error: quest list contains quest with u16::MAX id.");
|
||||
}
|
||||
},
|
||||
Some(quest) => quest.id + 1u16,
|
||||
None => 0u16
|
||||
};
|
||||
|
|
@ -167,6 +198,9 @@ fn main() {
|
|||
name: args.name.clone(),
|
||||
description: args.description.clone(),
|
||||
answer: args.answer.clone(),
|
||||
public: args.public,
|
||||
available_on: args.available.clone(),
|
||||
deadline: args.deadline.clone()
|
||||
};
|
||||
if let Err(error) = quest.save(path) {
|
||||
eprintln!("Error while saving quest: {error}.");
|
||||
|
|
@ -188,7 +222,10 @@ fn main() {
|
|||
reward: args.reward.unwrap_or(quest.reward),
|
||||
name: args.name.clone().unwrap_or(quest.name.clone()),
|
||||
description: args.description.clone().unwrap_or(quest.description.clone()),
|
||||
answer: args.answer.clone().unwrap_or(quest.answer.clone())
|
||||
answer: args.answer.clone().unwrap_or(quest.answer.clone()),
|
||||
public: args.public.unwrap_or(quest.public),
|
||||
available_on: args.available.clone().or(quest.available_on.clone()),
|
||||
deadline: args.deadline.clone().or(quest.deadline.clone())
|
||||
};
|
||||
let path = config.full_quests_path();
|
||||
match quest.save(path) {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ use std::{fs, io::Write, path::PathBuf};
|
|||
|
||||
use serde::{ Serialize, Deserialize };
|
||||
use error::QuestError;
|
||||
use toml::value::Date;
|
||||
|
||||
/// Difficulty of the quest
|
||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
|
||||
|
|
@ -59,6 +60,15 @@ pub struct Quest {
|
|||
|
||||
/// 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 {
|
||||
|
|
@ -69,7 +79,10 @@ impl Default for Quest {
|
|||
reward: u32::default(),
|
||||
name: default_name(),
|
||||
description: default_description(),
|
||||
answer: default_answer()
|
||||
answer: default_answer(),
|
||||
public: false,
|
||||
available_on: None,
|
||||
deadline: None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,10 @@ fn quest_one() {
|
|||
reward: 100,
|
||||
name: "Example easy quest".to_owned(),
|
||||
description: "Answer this quest without any attachments or comments".to_owned(),
|
||||
answer: "Accept the answer if it has no attachments and an empty comment".to_owned()
|
||||
answer: "Accept the answer if it has no attachments and an empty comment".to_owned(),
|
||||
public: false,
|
||||
available_on: None,
|
||||
deadline: None
|
||||
};
|
||||
|
||||
assert_eq!(*quest, expected);
|
||||
|
|
|
|||
|
|
@ -6,3 +6,4 @@ reward = 100
|
|||
name = "Example easy quest"
|
||||
description = "Answer this quest without any attachments or comments"
|
||||
answer = "Accept the answer if it has no attachments and an empty comment"
|
||||
public = false
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue