summaryrefslogtreecommitdiffstats
path: root/src/fleet/schedule.rs
diff options
context:
space:
mode:
authorJon Santmyer <jon@jonsantmyer.com>2026-05-21 07:58:47 -0400
committerJon Santmyer <jon@jonsantmyer.com>2026-05-21 07:58:47 -0400
commit14ca7b5fc15eb2618b46bde0cac85e37ebc9ebd9 (patch)
tree6c4864880bc54778122f1c0e4fa195c16cc064db /src/fleet/schedule.rs
parenta0a3b3974cab754c10a1517d82762b99482970ce (diff)
downloadsystemic4x-14ca7b5fc15eb2618b46bde0cac85e37ebc9ebd9.tar.gz
systemic4x-14ca7b5fc15eb2618b46bde0cac85e37ebc9ebd9.tar.bz2
systemic4x-14ca7b5fc15eb2618b46bde0cac85e37ebc9ebd9.zip
tacmap back as canvas. begin work on fleet scheduling
Diffstat (limited to 'src/fleet/schedule.rs')
-rw-r--r--src/fleet/schedule.rs190
1 files changed, 190 insertions, 0 deletions
diff --git a/src/fleet/schedule.rs b/src/fleet/schedule.rs
new file mode 100644
index 0000000..c0e275b
--- /dev/null
+++ b/src/fleet/schedule.rs
@@ -0,0 +1,190 @@
+use std::collections::{BinaryHeap, HashMap, VecDeque};
+use std::ops::Range;
+use std::sync::RwLock;
+
+use crate::fleet::{Fleet, FleetId, FleetsManager};
+use crate::timeman::Second;
+use crate::solar_system::{Kilometers, SolarSystem};
+
+pub trait ScheduleCommand
+{
+ //Remaining time interval for this command.
+ fn time_range(&self, time: &Range<Second>) -> Range<Second>;
+
+ fn tick(
+ &self,
+ star_systems: &[SolarSystem],
+ fleet: &mut Fleet,
+ time: &Range<Second>)
+ -> Result<(), Second>;
+}
+
+pub struct Schedule
+{
+ commands: Vec<Box<dyn ScheduleCommand>>,
+ groups: Vec<Range<usize>>,
+ start_time: Second
+}
+
+pub struct ScheduleManager
+{
+ schedules: HashMap<FleetId, Schedule>
+}
+
+impl Schedule
+{
+ pub fn new()
+ -> Self {
+ Self {
+ commands: vec![],
+ groups: vec![],
+ start_time: 0
+ }
+ }
+
+ pub fn commands(&self) -> &[Box<dyn ScheduleCommand>] { &self.commands }
+
+ pub fn top(&self) -> Option<&Box<dyn ScheduleCommand>> { self.commands.first() }
+ pub fn top_mut(&mut self) -> Option<&mut Box<dyn ScheduleCommand>> { self.commands.first_mut() }
+
+ pub fn pop(&mut self) -> Option<Box<dyn ScheduleCommand>> { self.commands.pop() }
+
+ pub fn add_command<T: ScheduleCommand + 'static>(
+ &mut self,
+ command: T)
+ {
+ self.commands.push(Box::new(command));
+ }
+
+ pub(crate) fn tick(
+ &mut self,
+ star_systems: &[SolarSystem],
+ fleet: &mut Fleet,
+ time: &Range<Second>)
+ -> Result<(), Second>
+ {
+ while let Some(command) = self.top() {
+ if command.time_range(time).end > time.start {
+ self.pop();
+ continue;
+ }
+
+ return command.tick(star_systems, fleet, time);
+ };
+ Ok(())
+ }
+} // impl Schedule
+
+impl ScheduleManager
+{
+ pub fn new() -> Self
+ {
+ Self {
+ schedules: HashMap::new()
+ }
+ }
+
+ pub fn schedules_mut(
+ &mut self)
+ -> std::collections::hash_map::IterMut<'_, FleetId, Schedule>
+ {
+ self.schedules.iter_mut()
+ }
+
+ pub fn schedules(
+ &self)
+ -> std::collections::hash_map::Iter<'_, FleetId, Schedule>
+ {
+ self.schedules.iter()
+ }
+
+ pub fn add_command_to_schedule
+ <T: ScheduleCommand + 'static>(
+ &mut self,
+ id: FleetId,
+ command: T)
+ {
+ if let Some(schedule) = self.schedules.get_mut(&id) {
+ schedule.add_command(command);
+ }
+ }
+
+ pub fn schedule_mut(
+ &mut self,
+ id: FleetId)
+ -> Option<&mut Schedule>
+ {
+ self.schedules.get_mut(&id)
+ }
+
+ pub fn schedule(
+ &self,
+ id: FleetId)
+ -> Option<&Schedule>
+ {
+ self.schedules.get(&id)
+ }
+
+ pub fn remove_schedule(
+ &mut self,
+ id: FleetId)
+ {
+ self.schedules.remove_entry(&id);
+ }
+
+ fn next_schedule_tick(
+ &self,
+ time: &Range<Second>)
+ -> Option<(FleetId, Second)> {
+ let mut least_cmd: Option<(FleetId, Second)> = None;
+ for (id, schedule) in self.schedules.iter() {
+ let top_cmd = match schedule.top() {
+ Some(cmd) => cmd.time_range(time).end,
+ None => { continue; }
+ };
+
+ if let Some(least_val) = least_cmd {
+ if least_val.1 > top_cmd {
+ least_cmd = Some((*id, top_cmd));
+ }
+ }else{
+ least_cmd = Some((*id, top_cmd));
+ }
+ }
+ least_cmd
+ }
+
+ pub fn subtick(
+ &mut self,
+ fleets_man: &mut FleetsManager,
+ star_systems: &[SolarSystem],
+ time: &Range<Second>)
+ -> Result<(), Second>
+ {
+ let mut last_time = time.start;
+ while let Some((fleet_id, fleet_tick)) = self.next_schedule_tick(time) {
+ if fleet_tick > time.end {
+ break;
+ }
+ let fleet = match fleets_man.fleet_mut(fleet_id) {
+ Some(v) => v,
+ None => {
+ self.remove_schedule(fleet_id);
+ continue;
+ }
+ };
+
+ let schedule = self.schedules.get_mut(&fleet_id).unwrap();
+ let tick_range = last_time..fleet_tick;
+ let schedule_tick_interrupt = schedule.tick(
+ star_systems, fleet, &tick_range);
+
+ if schedule_tick_interrupt.is_err() {
+ return schedule_tick_interrupt;
+ }
+
+ last_time = fleet_tick;
+ };
+ Ok(())
+ }
+}