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) -> Range; fn tick( &self, star_systems: &[SolarSystem], fleet: &mut Fleet, time: &Range) -> Result<(), Second>; } pub struct Schedule { commands: Vec>, groups: Vec>, start_time: Second } pub struct ScheduleManager { schedules: HashMap } impl Schedule { pub fn new() -> Self { Self { commands: vec![], groups: vec![], start_time: 0 } } pub fn commands(&self) -> &[Box] { &self.commands } pub fn top(&self) -> Option<&Box> { self.commands.first() } pub fn top_mut(&mut self) -> Option<&mut Box> { self.commands.first_mut() } pub fn pop(&mut self) -> Option> { self.commands.pop() } pub fn add_command( &mut self, command: T) { self.commands.push(Box::new(command)); } pub(crate) fn tick( &mut self, star_systems: &[SolarSystem], fleet: &mut Fleet, time: &Range) -> 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 ( &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) -> 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) -> 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(()) } }