konnektoren_core/controller/
game_xp_plugin.rs1use super::{ControllerPlugin, ControllerPluginError, GameControllerTrait};
2use crate::challenges::ChallengeResult;
3use crate::challenges::Performance;
4use crate::commands::{ChallengeCommand, Command, CommandType};
5use crate::controller::ControllerError;
6use std::sync::Arc;
7
8pub struct GameXpPlugin;
9
10impl GameXpPlugin {
11 fn update_game_xp(
12 game_controller: Arc<dyn GameControllerTrait>,
13 challenge_result: &ChallengeResult,
14 ) -> Result<(), ControllerError> {
15 {
16 let mut game_state = game_controller
17 .game_state()
18 .lock()
19 .map_err(|_| ControllerError::StateLock)?;
20
21 game_state.challenge.challenge_result = challenge_result.clone();
22 let performance = game_state.challenge.performance(challenge_result);
23 let xp_reward = performance / 10;
24
25 game_state.game.xp += xp_reward;
26 }
27
28 game_controller.save_game_state()?;
29 Ok(())
30 }
31}
32
33impl ControllerPlugin for GameXpPlugin {
34 fn name(&self) -> &str {
35 "GameXpPlugin"
36 }
37
38 fn init(&self) -> Result<(), ControllerPluginError> {
39 Ok(())
40 }
41
42 fn load(
43 &self,
44 game_controller: Arc<dyn GameControllerTrait>,
45 ) -> Result<(), ControllerPluginError> {
46 let game_controller_clone = game_controller.clone();
47 game_controller
48 .command_bus()
49 .subscribe(CommandType::Challenge, move |command| {
50 if let Command::Challenge(ChallengeCommand::Finish(Some(result))) = command {
51 if let Err(e) = Self::update_game_xp(game_controller_clone.clone(), &result) {
52 log::error!("Error updating game XP: {:?}", e);
53 }
54 }
55 });
56
57 Ok(())
58 }
59
60 fn unload(
61 &self,
62 _game_controller: Arc<dyn GameControllerTrait>,
63 ) -> Result<(), ControllerPluginError> {
64 Ok(())
65 }
66}
67
68#[cfg(test)]
69mod tests {
70 use super::*;
71 use crate::challenges::{Challenge, ChallengeConfig, ChallengeResult, ChallengeType};
72 use crate::controller::game_controller::MockGameControllerTrait;
73 use std::sync::{Arc, Mutex};
74
75 #[test]
76 fn test_update_game_xp_increases_xp() {
77 let mut mock_controller = MockGameControllerTrait::new();
78
79 let mut challenge = Challenge::new(&ChallengeType::default(), &ChallengeConfig::default());
81 challenge.challenge_result = ChallengeResult::default();
82
83 let mut game_state = crate::game::GameState::default();
84 game_state.challenge = challenge.clone();
85 game_state.game.xp = 0;
86
87 let game_state_mutex = Mutex::new(game_state);
88 mock_controller
89 .expect_game_state()
90 .return_const(Arc::new(game_state_mutex));
91 mock_controller
92 .expect_save_game_state()
93 .returning(|| Ok(()));
94
95 let result = ChallengeResult::default();
96 let res = GameXpPlugin::update_game_xp(Arc::new(mock_controller), &result);
97 assert!(res.is_ok());
98 }
100}