Files
pomomon-garden/src/features/phase/mod.rs
2025-11-26 19:59:53 +01:00

162 lines
4.7 KiB
Rust

use crate::features::savegame::messages::SavegameDumpMessage;
use crate::prelude::*;
use components::{SessionTracker, TimerSettings};
use messages::*;
pub mod components;
pub mod messages;
pub mod utils;
pub struct PhasePlugin;
impl Plugin for PhasePlugin {
fn build(&self, app: &mut App) {
app.init_resource::<TimerSettings>();
app.init_resource::<SessionTracker>();
app.insert_resource(CurrentPhase(Phase::Focus {
duration: 25.0 * 60.0,
}));
app.add_message::<PhaseTimerFinishedMessage>();
app.add_systems(OnEnter(AppState::GameScreen), load_rules);
app.add_systems(
Update,
(tick_timer, handle_pause, handle_continue).run_if(in_state(AppState::GameScreen)),
);
#[cfg(debug_assertions)]
app.add_systems(Update, debug_short_phase_duration);
}
}
#[cfg(debug_assertions)]
fn debug_short_phase_duration(
mut phase_res: ResMut<CurrentPhase>,
keys: Res<ButtonInput<KeyCode>>,
) {
if keys.any_pressed([KeyCode::ShiftLeft, KeyCode::ShiftRight])
&& keys.just_pressed(KeyCode::Enter)
{
let phase = &mut phase_res.0;
match phase {
Phase::Focus { duration } | Phase::Break { duration } => {
*duration = 3.0;
println!("Debug: Phase duration set to 3 seconds!");
}
_ => {}
}
}
}
fn load_rules(mut phase_res: ResMut<CurrentPhase>, settings: Res<TimerSettings>) {
let phase = &mut phase_res.0;
let new_phase = match phase {
Phase::Focus { .. } => Some(Phase::Focus {
duration: settings.focus_duration,
}),
Phase::Break { .. } => Some(Phase::Break { duration: 0.0 }),
_ => None,
};
if let Some(p) = new_phase {
*phase = p;
}
}
fn tick_timer(
time: Res<Time>,
mut phase_res: ResMut<CurrentPhase>,
mut finish_writer: MessageWriter<PhaseTimerFinishedMessage>,
mut savegame_messages: MessageWriter<SavegameDumpMessage>,
) {
let delta = time.delta_secs();
let phase = &mut phase_res.0;
match phase {
Phase::Focus { duration } | Phase::Break { duration } => {
*duration -= delta;
if *duration <= 0.0 {
finish_writer.write(PhaseTimerFinishedMessage {
phase: phase.clone(),
});
let completed = phase.clone();
*phase = Phase::Finished {
completed_phase: Box::new(completed),
};
println!("phase ended");
savegame_messages.write(SavegameDumpMessage);
}
}
_ => {}
}
}
fn handle_pause(
mut messages: MessageReader<PhaseTimerPauseMessage>,
mut phase_res: ResMut<CurrentPhase>,
) {
for _ in messages.read() {
let phase = &mut phase_res.0;
match phase {
Phase::Focus { .. } | Phase::Break { .. } => {
let current_state = phase.clone();
*phase = Phase::Paused {
previous_phase: Box::new(current_state),
};
println!("Phase paused");
}
Phase::Paused { previous_phase } => {
*phase = *previous_phase.clone();
println!("Phase resumed");
}
_ => {}
}
}
}
fn handle_continue(
mut messages: MessageReader<NextPhaseMessage>,
mut phase_res: ResMut<CurrentPhase>,
mut session_tracker: ResMut<SessionTracker>,
settings: Res<TimerSettings>,
) {
for _ in messages.read() {
let phase = &mut phase_res.0;
if let Phase::Finished { completed_phase } = phase {
match **completed_phase {
Phase::Focus { .. } => {
session_tracker.completed_focus_phases += 1;
// TODO: add berry grant logic
let is_long_break = session_tracker.completed_focus_phases > 0
&& session_tracker.completed_focus_phases % settings.long_break_interval
== 0;
if is_long_break {
*phase = Phase::Break {
duration: settings.long_break_duration,
};
} else {
*phase = Phase::Break {
duration: settings.short_break_duration,
};
}
}
Phase::Break { .. } => {
*phase = Phase::Focus {
duration: 25.0 * 60.0,
};
}
_ => {}
}
}
}
}