Commit db9f5297 authored by Ralf's avatar Ralf
Browse files

more comments

parent 36241923
......@@ -7,45 +7,77 @@ use std::sync::mpsc::{channel, Sender, Receiver};
use input::Event;
/// An EventHandler is a function that handles events.
pub type EventHandler<'a> = Box<FnMut(Event) -> HandlerResult + 'a>;
/// The result of a handler is either: Go on working, or:
/// Quit the current situation
#[must_use]
#[derive(Copy,Clone,Debug,PartialEq,Eq)]
pub enum HandlerResult {
Continue,
QuitLoop,
QuitSituation,
}
pub type EventHandler<'a> = Box<FnMut(Event) -> HandlerResult + 'a>;
/// The result of handling a bunch of events: Shut down the world, a timeout,
/// or quit the current situation.
#[must_use]
#[derive(Copy,Clone,Debug,PartialEq,Eq)]
pub enum EventsResult {
ShuttingDown,
Timeout,
QuitSituation,
}
/// Create a handler that can quit the current situation.
pub fn mk_quitting_handler<'a, F>(f: F) -> EventHandler<'a>
where F: FnMut(Event) -> HandlerResult + 'a
{
Box::new(f)
}
/// Create a handler that *cannot* quit the current situation.
pub fn mk_handler<'a, F>(mut f: F) -> EventHandler<'a>
where F: FnMut(Event) + 'a
{
Box::new(move |ev| { f(ev); HandlerResult::Continue })
}
#[must_use]
#[derive(Copy,Clone,Debug,PartialEq,Eq)]
pub enum EventsResult {
ShuttingDown,
Timeout,
Quit,
/// Stores the states of all our sensors. Notice that the state could be
/// "None", which indictaes "unknown" -- this can happen immediately after
/// startup, before the pins have stabilized.
pub struct SensorStates {
door_locked: Option<bool>,
}
enum EventOrTimer {
Ev(Event),
Timeout(u32),
impl SensorStates {
/// New SensorStates with all states being "unknown".
fn new() -> SensorStates {
SensorStates { door_locked: None }
}
/// Is the door locked right now?
pub fn door_locked(&self) -> Option<bool> {
self.door_locked
}
/// Update the states based on the given event
fn record_state(&mut self, ev: &Event) {
match ev {
&Event::DoorLocked(b) => self.door_locked = Some(b),
_ => {}
}
}
}
pub struct SensorStates {
door_locked: Option<bool>,
/// An Event sender is used by input types to send events to the brain.
#[derive(Clone)]
pub struct EventSender {
sender: Sender<EventOrTimer>,
}
/// An Environment: Keeps track of the current state of sensors, and offers
/// functionality to handle incoming events.
pub struct Environment {
events: Receiver<EventOrTimer>,
sender: Sender<EventOrTimer>,
......@@ -53,39 +85,33 @@ pub struct Environment {
cur_id: u32, // current ID used for timeout events
}
pub struct EventSender {
sender: Sender<EventOrTimer>,
}
macro_rules! handle_events {
( $env:expr, $( $x:expr ),* ) => {
{ $env.handle_events(vec![$( $x, )*] ) }
};
}
macro_rules! handle_events_timeout {
( $env:expr, $d:expr, $( $x:expr ),* ) => {
{ $env.handle_events_timeout($d, vec![$( $x, )*] ) }
};
}
impl Environment {
pub fn new() -> (Environment, EventSender) {
/// Create a new environment
pub fn new() -> Environment {
let (tx, rx) = channel();
(Environment {
Environment {
events: rx,
sender: tx.clone(),
sensors: SensorStates::new(),
cur_id: 0,
},
EventSender { sender: tx })
}
}
/// Return an EventSender matching this Environment
pub fn sender(&self) -> EventSender {
EventSender { sender: self.sender.clone() }
}
/// Handle events with the given handlers, until either the event stream
/// shuts down or a handler reteurns QuitSituation.
pub fn handle_events(&mut self, handlers: Vec<EventHandler>) -> EventsResult {
self.cur_id = u32::wrapping_add(self.cur_id, 1); // make sure we ignore old timeouts
self.handle_events_cur_id(handlers)
}
/// Handle events with the given handlers, until either the time's out,
/// the event stream shuts down, or a handler reteurns QuitSituation.
pub fn handle_events_timeout(&mut self,
d: Duration,
handlers: Vec<EventHandler>)
......@@ -106,6 +132,7 @@ impl Environment {
self.handle_events_cur_id(handlers)
}
/// Handle events, considering Timeout events based on self.cur_id
fn handle_events_cur_id(&mut self, mut handlers: Vec<EventHandler>) -> EventsResult {
for ev in self.events.iter() {
match ev {
......@@ -122,7 +149,7 @@ impl Environment {
for handler in handlers.iter_mut() {
match handler(ev) {
HandlerResult::Continue => {}
HandlerResult::QuitLoop => return EventsResult::Quit,
HandlerResult::QuitSituation => return EventsResult::QuitSituation,
}
}
}
......@@ -131,24 +158,31 @@ impl Environment {
return EventsResult::ShuttingDown;
}
/// Provide access to the sensor data
pub fn sensors(&self) -> &SensorStates {
&self.sensors
}
}
impl SensorStates {
fn new() -> SensorStates {
SensorStates { door_locked: None }
}
/// Type of the MPSC channel, but not visibly so: Either a timeout,
/// or an actual event.
enum EventOrTimer {
Ev(Event),
Timeout(u32),
}
pub fn door_locked(&self) -> Option<bool> {
self.door_locked
}
/// handle_events! is used to pretend that we have a vararg function, it
/// constructs the Vec.
macro_rules! handle_events {
( $env:expr, $( $x:expr ),* ) => {
{ $env.handle_events(vec![$( $x, )*] ) }
};
}
fn record_state(&mut self, ev: &Event) {
match ev {
&Event::DoorLocked(b) => self.door_locked = Some(b),
_ => {}
}
}
/// handle_events_timeout! is used to pretend that we have a vararg function,
/// it constructs the Vec.
macro_rules! handle_events_timeout {
( $env:expr, $d:expr, $( $x:expr ),* ) => {
{ $env.handle_events_timeout($d, vec![$( $x, )*] ) }
};
}
......@@ -43,7 +43,7 @@ impl Situation for UnLocking {
mk_quitting_handler(|ev| {
match ev {
Event::DoorLocked(b) if b == locking => {
HandlerResult::QuitLoop
HandlerResult::QuitSituation
}
_ => HandlerResult::Continue,
}
......@@ -61,7 +61,7 @@ impl Situation for UnLocking {
None /* FIXME: What do do when all attempts failed? */
}
}
EventsResult::Quit =>
EventsResult::QuitSituation =>
None /* FIXME: Which state to go in next? */
})
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment