konnektoren_core/commands/
game_command.rs1use super::command::CommandTrait;
4use super::command_type::CommandType;
5use crate::challenges::Timed;
6use crate::commands::error::{CommandError, Result};
7use crate::game::GamePath;
8use crate::game::GameState;
9use crate::game::error::GameError;
10
11#[derive(Debug, Clone, PartialEq)]
13pub enum GameCommand {
14 NextChallenge,
16 PreviousChallenge,
18}
19
20impl CommandTrait for GameCommand {
21 fn execute(&self, state: &mut GameState) -> Result<()> {
31 match self {
32 GameCommand::NextChallenge => Self::next_challenge(state),
33 GameCommand::PreviousChallenge => Self::previous_challenge(state),
34 }
35 }
36
37 fn get_type(&self) -> CommandType {
39 CommandType::Game
40 }
41}
42
43impl GameCommand {
44 pub fn next_challenge(state: &mut GameState) -> Result<()> {
54 let current_game_path: &GamePath = state
55 .game
56 .game_paths
57 .get(state.current_game_path)
58 .ok_or(CommandError::GameError(GameError::GamePathNotFound))?;
59
60 if state.current_challenge_index + 1 >= current_game_path.challenge_ids().len() {
61 return Err(CommandError::GameError(GameError::InvalidGameState(
62 "No more challenges".to_string(),
63 )));
64 }
65 state.current_challenge_index += 1;
66
67 let challenge_config = ¤t_game_path.challenges[state.current_challenge_index];
68 state.challenge = state
69 .game
70 .create_challenge(&challenge_config.id)
71 .map_err(CommandError::GameError)?;
72
73 state.challenge.start();
74 state.current_task_index = 0;
75
76 Ok(())
77 }
78
79 pub fn previous_challenge(state: &mut GameState) -> Result<()> {
89 if state.current_challenge_index == 0 {
90 return Err(CommandError::GameError(GameError::InvalidGameState(
91 "No previous challenges".to_string(),
92 )));
93 }
94
95 state.current_challenge_index -= 1;
96
97 let current_game_path: &GamePath = state
98 .game
99 .game_paths
100 .get(state.current_game_path)
101 .ok_or(CommandError::GameError(GameError::GamePathNotFound))?;
102
103 let challenge_config = ¤t_game_path.challenges[state.current_challenge_index];
104
105 match state.game.create_challenge(&challenge_config.id) {
106 Ok(challenge) => {
107 state.challenge = challenge;
108 state.challenge.start();
109 state.current_task_index = 0;
110 Ok(())
111 }
112 Err(err) => Err(CommandError::GameError(err)),
113 }
114 }
115}
116
117#[cfg(test)]
118mod tests {
119 use super::*;
120 use crate::game::GameState;
121
122 #[test]
123 fn next_challenge() {
124 let mut state = GameState::default();
125 let command = GameCommand::NextChallenge;
126 let result = command.execute(&mut state);
127 assert!(result.is_ok());
128 assert_eq!(state.current_challenge_index, 1);
129 }
130
131 #[test]
132 fn previous_challenge() {
133 let mut state = GameState::default();
134 let command = GameCommand::NextChallenge;
135 let result = command.execute(&mut state);
136 assert!(result.is_ok());
137 assert_eq!(state.current_challenge_index, 1);
138 let command = GameCommand::PreviousChallenge;
139 let result = command.execute(&mut state);
140 assert!(result.is_ok());
141 assert_eq!(state.current_challenge_index, 0);
142 }
143
144 #[test]
145 fn next_challenge_no_more() {
146 let mut state = GameState::default();
147 let command = GameCommand::NextChallenge;
148 command.execute(&mut state).unwrap();
149 command.execute(&mut state).unwrap();
150 command.execute(&mut state).unwrap();
151 command.execute(&mut state).unwrap();
152 command.execute(&mut state).unwrap();
153 command.execute(&mut state).unwrap();
154 command.execute(&mut state).unwrap();
155 assert_eq!(state.current_challenge_index, 7);
156 let result = command.execute(&mut state);
157 assert!(result.is_err());
158
159 if let Err(error) = result {
161 match error {
162 CommandError::GameError(GameError::InvalidGameState(msg)) => {
163 assert_eq!(msg, "No more challenges");
164 }
165 _ => panic!("Unexpected error type: {:?}", error),
166 }
167 }
168 }
169
170 #[test]
171 fn previous_challenge_no_more() {
172 let mut state = GameState::default();
173 let command = GameCommand::PreviousChallenge;
174 let result = command.execute(&mut state);
175 assert!(result.is_err());
176
177 if let Err(error) = result {
179 match error {
180 CommandError::GameError(GameError::InvalidGameState(msg)) => {
181 assert_eq!(msg, "No previous challenges");
182 }
183 _ => panic!("Unexpected error type: {:?}", error),
184 }
185 }
186 }
187
188 #[test]
189 fn test_game_path_not_found() {
190 let mut state = GameState::default();
191 state.current_game_path = 999; let command = GameCommand::NextChallenge;
194 let result = command.execute(&mut state);
195 assert!(result.is_err());
196
197 if let Err(error) = result {
199 match error {
200 CommandError::GameError(GameError::GamePathNotFound) => {}
201 _ => panic!("Unexpected error type: {:?}", error),
202 }
203 }
204 }
205}