konnektoren_core/controller/
challenge_finish_plugin.rs1use super::GameControllerTrait;
2use super::{ControllerPlugin, ControllerPluginError};
3use crate::challenges::{Challenge, ChallengeResult};
4use crate::commands::{ChallengeCommand, Command, CommandType};
5use crate::controller::ControllerError;
6use std::sync::Arc;
7
8pub struct ChallengeFinishPlugin;
9
10impl ChallengeFinishPlugin {
11 fn handle_challenge_finish(
12 game_controller: Arc<dyn GameControllerTrait>,
13 challenge: &Challenge,
14 result: &ChallengeResult,
15 ) -> Result<(), ControllerError> {
16 {
17 let mut game_state = game_controller
18 .game_state()
19 .lock()
20 .map_err(|_| ControllerError::StateLock)?;
21
22 if game_state.challenge.challenge_config.id != challenge.challenge_config.id {
23 return Ok(());
24 }
25
26 game_state.challenge.challenge_result = result.clone();
27 game_state
28 .game
29 .challenge_history
30 .add_challenge(challenge.clone());
31 }
32
33 game_controller.save_game_state()?;
34 Ok(())
35 }
36}
37
38impl ControllerPlugin for ChallengeFinishPlugin {
39 fn name(&self) -> &str {
40 "ChallengeFinishPlugin"
41 }
42
43 fn init(&self) -> Result<(), ControllerPluginError> {
44 Ok(())
45 }
46
47 fn load(
48 &self,
49 game_controller: Arc<dyn GameControllerTrait>,
50 ) -> Result<(), ControllerPluginError> {
51 let game_controller_clone = game_controller.clone();
52 game_controller
53 .command_bus()
54 .subscribe(CommandType::Challenge, move |command| {
55 if let Command::Challenge(ChallengeCommand::Finish(Some(result))) = command {
56 let challenge = match game_controller_clone.game_state().lock() {
57 Ok(state) => state.challenge.clone(),
58 Err(_) => {
59 log::error!("Failed to lock game state in ChallengeFinishPlugin");
60 return;
61 }
62 };
63
64 if let Err(e) = Self::handle_challenge_finish(
65 game_controller_clone.clone(),
66 &challenge,
67 &result,
68 ) {
69 log::error!("Error in challenge finish handler: {:?}", e);
70 }
71 }
72 });
73
74 Ok(())
75 }
76
77 fn unload(
78 &self,
79 _game_controller: Arc<dyn GameControllerTrait>,
80 ) -> Result<(), ControllerPluginError> {
81 Ok(())
82 }
83}
84
85#[cfg(test)]
86mod tests {
87 use super::*;
88 use crate::challenges::{Challenge, ChallengeConfig, ChallengeResult, ChallengeType};
89 use crate::controller::game_controller::MockGameControllerTrait;
90 use std::sync::{Arc, Mutex};
91
92 #[test]
93 fn test_handle_challenge_finish_updates_state_and_saves() {
94 let mut mock_controller = MockGameControllerTrait::new();
95
96 let challenge = Challenge::new(&ChallengeType::default(), &ChallengeConfig::default());
98 let result = ChallengeResult::default();
99
100 let game_state = Mutex::new(crate::game::GameState {
102 challenge: challenge.clone(),
103 ..Default::default()
104 });
105 mock_controller
106 .expect_game_state()
107 .return_const(Arc::new(game_state));
108 mock_controller
109 .expect_save_game_state()
110 .returning(|| Ok(()));
111
112 let res = ChallengeFinishPlugin::handle_challenge_finish(
114 Arc::new(mock_controller),
115 &challenge,
116 &result,
117 );
118 assert!(res.is_ok());
119 }
120}