From fefea7ed2d149f92ffdff95a6c197b55b5098ebb Mon Sep 17 00:00:00 2001 From: Loong Date: Sat, 25 Nov 2023 03:35:27 +0800 Subject: [PATCH] refactor: rename `TaskList` to `TaskConfig` and add methods The `TaskList` struct is renamed to `TaskConfig` because it may not only contain a list of tasks. It may also contain other information in the future. --- maa-cli/src/config/task/mod.rs | 286 ++++++++++++++++++--------------- maa-cli/src/run/fight.rs | 16 +- maa-cli/src/run/mod.rs | 26 +-- 3 files changed, 177 insertions(+), 151 deletions(-) diff --git a/maa-cli/src/config/task/mod.rs b/maa-cli/src/config/task/mod.rs index c706c13c..1c72870a 100644 --- a/maa-cli/src/config/task/mod.rs +++ b/maa-cli/src/config/task/mod.rs @@ -14,9 +14,26 @@ use serde::Deserialize; #[serde(deny_unknown_fields)] pub struct TaskVariant { #[serde(default)] - pub condition: Condition, + condition: Condition, #[serde(default)] - pub params: Value, + params: Value, +} + +impl TaskVariant { + // This constructor seems to be useless, + // because predefined task always active and ask params from user. + // Variant is only used in user-defined tasks. + // pub fn new(condition: Condition, params: Value) -> Self { + // Self { condition, params } + // } + + pub fn is_active(&self) -> bool { + self.condition.is_active() + } + + pub fn params(&self) -> &Value { + &self.params + } } pub fn default_variants() -> Vec { @@ -68,26 +85,26 @@ impl Task { } pub fn is_active(&self) -> bool { - for variant in &self.variants { - if variant.condition.is_active() { + for variant in self.variants.iter() { + if variant.is_active() { return true; } } false } - pub fn get_type(&self) -> &TaskOrUnknown { + pub fn task_type(&self) -> &TaskOrUnknown { &self.task_type } - pub fn get_params(&self) -> Value { + pub fn params(&self) -> Value { let mut params = self.params.clone(); match self.strategy { // Merge params from the first active variant Strategy::First => { for variant in &self.variants { - if variant.condition.is_active() { - params.merge_mut(&variant.params); + if variant.is_active() { + params.merge_mut(variant.params()); break; } } @@ -95,8 +112,8 @@ impl Task { // Merge params from all active variants Strategy::Merge => { for variant in &self.variants { - if variant.condition.is_active() { - params.merge_mut(&variant.params); + if variant.is_active() { + params.merge_mut(variant.params()); } } } @@ -105,14 +122,26 @@ impl Task { } } -#[cfg_attr(test, derive(PartialEq))] #[derive(Deserialize, Debug)] -#[serde(deny_unknown_fields)] -pub struct TaskList { - pub tasks: Vec, +pub struct TaskConfig { + tasks: Vec, +} + +impl TaskConfig { + pub fn new() -> Self { + Self { tasks: Vec::new() } + } + + pub fn push(&mut self, task: Task) { + self.tasks.push(task); + } + + pub fn tasks(&self) -> &Vec { + &self.tasks + } } -impl super::FromFile for TaskList {} +impl super::FromFile for TaskConfig {} #[cfg(test)] mod tests { @@ -190,7 +219,7 @@ mod tests { Strategy::default(), vec![] ) - .get_type(), + .task_type(), &TaskType::StartUp.into() ); } @@ -207,7 +236,7 @@ mod tests { params: object!(), }] ) - .get_params(), + .params(), object!("a" => 1) ); assert_eq!( @@ -220,7 +249,7 @@ mod tests { params: object!("b" => 2), }] ) - .get_params(), + .params(), object!("a" => 1, "b" => 2) ); assert_eq!( @@ -233,7 +262,7 @@ mod tests { params: object!("a" => 1), }] ) - .get_params(), + .params(), object!("a" => 1) ); assert_eq!( @@ -246,7 +275,7 @@ mod tests { params: object!("a" => 2), }] ) - .get_params(), + .params(), object!("a" => 2) ); assert_eq!( @@ -265,7 +294,7 @@ mod tests { }, ] ) - .get_params(), + .params(), object!("a" => 2) ); assert_eq!( @@ -284,7 +313,7 @@ mod tests { }, ] ) - .get_params(), + .params(), object!("a" => 3) ); assert_eq!( @@ -303,7 +332,7 @@ mod tests { }, ] ) - .get_params(), + .params(), object!("a" => 2), ); assert_eq!( @@ -322,7 +351,7 @@ mod tests { }, ] ) - .get_params(), + .params(), object!("a" => 2, "b" => 4), ); assert_eq!( @@ -341,7 +370,7 @@ mod tests { }, ] ) - .get_params(), + .params(), object!("a" => 3, "b" => 4, "c" => 5), ); } @@ -354,105 +383,6 @@ mod tests { use chrono::{NaiveDateTime, NaiveTime, TimeZone, Weekday}; - fn example_tasks() -> TaskList { - TaskList { - tasks: vec![ - Task::new( - TaskType::StartUp, - object!( - "client_type" => "Official", - "start_game_enabled" => BoolInput::new( - Some(true), - Some("start the game"), - ), - ), - Strategy::default(), - vec![TaskVariant { - condition: Condition::Always, - params: object!(), - }], - ), - Task::new( - TaskType::Fight, - object!(), - Strategy::Merge, - vec![ - TaskVariant { - condition: Condition::Weekday { - weekdays: vec![Weekday::Sun], - }, - params: object!("expiring_medicine" => 5), - }, - TaskVariant { - condition: Condition::Always, - params: object!( - "stage" => Input { - default: Some("1-7".to_string()), - description: Some("a stage to fight".to_string()) - } - ), - }, - TaskVariant { - condition: Condition::Weekday { - weekdays: vec![Weekday::Tue, Weekday::Thu, Weekday::Sat], - }, - params: object!("stage" => "CE-6"), - }, - TaskVariant { - condition: Condition::DateTime { - start: Some(naive_local_datetime(2023, 8, 1, 16, 0, 0)), - end: Some(naive_local_datetime(2023, 8, 21, 3, 59, 59)), - }, - params: object!( - "stage" => Select { - alternatives: vec![ - "SL-6".to_string(), - "SL-7".to_string(), - "SL-8".to_string(), - ], - description: Some("a stage to fight in summer event".to_string()), - } - ), - }, - ], - ), - Task::new( - TaskType::Mall, - object!( - "shopping" => true, - "credit_fight" => true, - "buy_first" => [ - "招聘许可", - "龙门币", - ], - "blacklist" => [ - "碳", - "家具", - "加急许可", - ], - ), - Strategy::default(), - vec![TaskVariant { - condition: Condition::Time { - start: Some(NaiveTime::from_hms_opt(16, 0, 0).unwrap()), - end: None, - }, - params: object!(), - }], - ), - Task::new( - TaskType::CloseDown, - object!(), - Strategy::default(), - vec![TaskVariant { - condition: Condition::Always, - params: object!(), - }], - ), - ], - } - } - fn naive_local_datetime(y: i32, m: u32, d: u32, h: u32, mi: u32, s: u32) -> NaiveDateTime { chrono::Local .with_ymd_and_hms(y, m, d, h, mi, s) @@ -460,31 +390,127 @@ mod tests { .naive_local() } + fn example_task_config() -> TaskConfig { + let mut task_list = TaskConfig::new(); + + task_list.push(Task::new( + TaskType::StartUp, + object!( + "client_type" => "Official", + "start_game_enabled" => BoolInput::new( + Some(true), + Some("start the game"), + ), + ), + Strategy::default(), + default_variants(), + )); + + task_list.push(Task::new( + TaskType::Fight, + object!(), + Strategy::Merge, + vec![ + TaskVariant { + condition: Condition::Weekday { + weekdays: vec![Weekday::Sun], + }, + params: object!("expiring_medicine" => 5), + }, + TaskVariant { + condition: Condition::Always, + params: object!( + "stage" => Input { + default: Some("1-7".to_string()), + description: Some("a stage to fight".to_string()) + } + ), + }, + TaskVariant { + condition: Condition::Weekday { + weekdays: vec![Weekday::Tue, Weekday::Thu, Weekday::Sat], + }, + params: object!("stage" => "CE-6"), + }, + TaskVariant { + condition: Condition::DateTime { + start: Some(naive_local_datetime(2023, 8, 1, 16, 0, 0)), + end: Some(naive_local_datetime(2023, 8, 21, 3, 59, 59)), + }, + params: object!( + "stage" => Select { + alternatives: vec![ + "SL-6".to_string(), + "SL-7".to_string(), + "SL-8".to_string(), + ], + description: Some("a stage to fight in summer event".to_string()), + } + ), + }, + ], + )); + + task_list.push(Task::new( + TaskType::Mall, + object!( + "shopping" => true, + "credit_fight" => true, + "buy_first" => [ + "招聘许可", + "龙门币", + ], + "blacklist" => [ + "碳", + "家具", + "加急许可", + ], + ), + Strategy::default(), + vec![TaskVariant { + condition: Condition::Time { + start: Some(NaiveTime::from_hms_opt(16, 0, 0).unwrap()), + end: None, + }, + params: object!(), + }], + )); + + task_list.push(Task::new( + TaskType::CloseDown, + object!(), + Strategy::default(), + default_variants(), + )); + + task_list + } + #[test] fn json() { - let tasks: TaskList = serde_json::from_reader( + let tasks: TaskConfig = serde_json::from_reader( std::fs::File::open("../config_examples/tasks/daily.json").unwrap(), ) .unwrap(); - assert_eq!(tasks, example_tasks()); + assert_eq!(tasks.tasks(), example_task_config().tasks()) } #[test] fn toml() { - let tasks: TaskList = toml::from_str( + let tasks: TaskConfig = toml::from_str( &std::fs::read_to_string("../config_examples/tasks/daily.toml").unwrap(), ) .unwrap(); - assert_eq!(tasks, example_tasks()) + assert_eq!(tasks.tasks(), example_task_config().tasks()) } #[test] fn yaml() { - let tasks: TaskList = serde_yaml::from_reader( + let tasks: TaskConfig = serde_yaml::from_reader( std::fs::File::open("../config_examples/tasks/daily.yml").unwrap(), ) .unwrap(); - assert_eq!(tasks, example_tasks()) + assert_eq!(tasks.tasks(), example_task_config().tasks()) } } } diff --git a/maa-cli/src/run/fight.rs b/maa-cli/src/run/fight.rs index e1ec9b8f..d53e0068 100644 --- a/maa-cli/src/run/fight.rs +++ b/maa-cli/src/run/fight.rs @@ -1,6 +1,7 @@ use crate::{ config::task::{ - default_variants, task_type::TaskType, value::input::Input, Strategy, Task, TaskList, Value, + default_variants, task_type::TaskType, value::input::Input, Strategy, Task, TaskConfig, + Value, }, dirs::Dirs, object, @@ -16,9 +17,10 @@ pub fn fight( startup: bool, closedown: bool, ) -> Result<()> { - let mut task_list: Vec = Vec::new(); + let mut task_config = TaskConfig::new(); + if startup { - task_list.push(Task::new( + task_config.push(Task::new( TaskType::StartUp, Value::default(), Strategy::default(), @@ -29,7 +31,7 @@ pub fn fight( let stage: Input = Input::new(Some("1-7".to_string()), Some("a stage to fight")); let medicine: Input = Input::new(Some(0), Some("medicine to use")); - task_list.push(Task::new( + task_config.push(Task::new( TaskType::Fight, object!( "stage" => stage, @@ -40,7 +42,7 @@ pub fn fight( )); if closedown { - task_list.push(Task::new( + task_config.push(Task::new( TaskType::CloseDown, Value::default(), Strategy::default(), @@ -48,7 +50,5 @@ pub fn fight( )); } - let task = TaskList { tasks: task_list }; - - run(dirs, task, addr, user_resource, batch, false) + run(dirs, task_config, addr, user_resource, batch, false) } diff --git a/maa-cli/src/run/mod.rs b/maa-cli/src/run/mod.rs index f1470c14..a9b666df 100644 --- a/maa-cli/src/run/mod.rs +++ b/maa-cli/src/run/mod.rs @@ -9,7 +9,7 @@ use crate::{ task::{ task_type::{TaskOrUnknown, TaskType}, value::input::enable_batch_mode, - TaskList, + TaskConfig, }, Error as ConfigError, FindFile, }, @@ -25,19 +25,19 @@ use anyhow::{anyhow, bail, Context, Result}; use maa_sys::Assistant; pub enum CLITask { - TaskList(TaskList), - TaskName(String), + TaskConfig(TaskConfig), + TaskFile(String), } -impl From for CLITask { - fn from(task_list: TaskList) -> Self { - Self::TaskList(task_list) +impl From for CLITask { + fn from(task_list: TaskConfig) -> Self { + Self::TaskConfig(task_list) } } impl From for CLITask { fn from(task_name: String) -> Self { - Self::TaskName(task_name) + Self::TaskFile(task_name) } } @@ -147,11 +147,11 @@ pub fn run( // Load task from tasks/.(toml|yaml|json) let task_list = match task.into() { - CLITask::TaskList(task_list) => task_list, - CLITask::TaskName(task_name) => { + CLITask::TaskConfig(task_list) => task_list, + CLITask::TaskFile(task_name) => { let task_file = config_dir.join("tasks").join(&task_name); debug!("Finding task file:", task_file.display()); - TaskList::find_file(&task_file).with_context(|| { + TaskConfig::find_file(&task_file).with_context(|| { format!( "Failed to find task file {} in {}", task_name, @@ -170,11 +170,11 @@ pub fn run( let mut client_resource: Option<&str> = None; - for task in task_list.tasks { + for task in task_list.tasks() { if task.is_active() { - let task_type = task.get_type(); + let task_type = task.task_type(); - let mut params = task.get_params(); + let mut params = task.params(); params.init().context("Failed to init task params!")?; match task_type {