rust/hwphysics/src/time.rs
changeset 15775 95402fa4e191
parent 15774 9588bd852202
child 15776 ec85fdf82942
equal deleted inserted replaced
15774:9588bd852202 15775:95402fa4e191
     1 use crate::common::{GearId, Millis};
       
     2 use std::{
       
     3     cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd},
       
     4     collections::BinaryHeap,
       
     5 };
       
     6 
       
     7 pub type EventId = u16;
       
     8 
       
     9 struct TimeEvent {
       
    10     time: Millis,
       
    11     gear_id: GearId,
       
    12     event_id: EventId,
       
    13 }
       
    14 
       
    15 impl PartialOrd for TimeEvent {
       
    16     #[inline]
       
    17     fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
       
    18         self.time.partial_cmp(&other.time)
       
    19     }
       
    20 }
       
    21 
       
    22 impl PartialEq for TimeEvent {
       
    23     #[inline]
       
    24     fn eq(&self, other: &Self) -> bool {
       
    25         self.time.eq(&other.time)
       
    26     }
       
    27 }
       
    28 
       
    29 impl Ord for TimeEvent {
       
    30     #[inline]
       
    31     fn cmp(&self, other: &Self) -> Ordering {
       
    32         self.time.cmp(&other.time)
       
    33     }
       
    34 }
       
    35 
       
    36 impl Eq for TimeEvent {}
       
    37 
       
    38 pub struct OccurredEvents {
       
    39     events: Vec<(GearId, EventId)>,
       
    40 }
       
    41 
       
    42 impl OccurredEvents {
       
    43     fn new() -> Self {
       
    44         Self { events: vec![] }
       
    45     }
       
    46 
       
    47     fn clear(&mut self) {
       
    48         self.events.clear()
       
    49     }
       
    50 }
       
    51 
       
    52 pub struct TimeProcessor {
       
    53     current_event_id: EventId,
       
    54     current_time: Millis,
       
    55     events: BinaryHeap<TimeEvent>,
       
    56     timeouts: OccurredEvents,
       
    57 }
       
    58 
       
    59 impl TimeProcessor {
       
    60     pub fn new() -> Self {
       
    61         Self {
       
    62             current_event_id: 0,
       
    63             current_time: Millis::new(0),
       
    64             events: BinaryHeap::with_capacity(1024),
       
    65             timeouts: OccurredEvents::new(),
       
    66         }
       
    67     }
       
    68 
       
    69     pub fn register(&mut self, gear_id: GearId, timeout: Millis) -> EventId {
       
    70         let event_id = self.current_event_id;
       
    71         self.current_event_id = self.current_event_id.wrapping_add(1);
       
    72         let event = TimeEvent {
       
    73             time: self.current_time + timeout,
       
    74             gear_id,
       
    75             event_id,
       
    76         };
       
    77         self.events.push(event);
       
    78         event_id
       
    79     }
       
    80 
       
    81     fn remove_events<P>(&mut self, predicate: P)
       
    82     where
       
    83         P: Fn(&TimeEvent) -> bool,
       
    84     {
       
    85         let events = self.events.drain().filter(predicate).collect::<Vec<_>>();
       
    86         self.events.extend(events);
       
    87     }
       
    88 
       
    89     pub fn cancel(&mut self, event_id: EventId) {
       
    90         //self.events.retain(|event| event.event_id != event_id)
       
    91         self.remove_events(|event| event.event_id != event_id)
       
    92     }
       
    93 
       
    94     pub fn cancel_all(&mut self, gear_id: GearId) {
       
    95         //self.events.retain(|event| event.gear_id != gear_id)
       
    96         self.remove_events(|event| event.gear_id != gear_id)
       
    97     }
       
    98 
       
    99     pub fn process(&mut self, time_step: Millis) -> &OccurredEvents {
       
   100         self.timeouts.clear();
       
   101         self.current_time = self.current_time + time_step;
       
   102         while self
       
   103             .events
       
   104             .peek()
       
   105             .filter(|e| e.time <= self.current_time)
       
   106             .is_some()
       
   107         {
       
   108             let event = self.events.pop().unwrap();
       
   109             self.timeouts.events.push((event.gear_id, event.event_id))
       
   110         }
       
   111         &self.timeouts
       
   112     }
       
   113 }