timer revelations

This commit is contained in:
Quaternions 2024-07-31 13:57:59 -07:00
parent 6a12d213e8
commit 852bbe6dad

@ -1,18 +1,26 @@
use crate::integer::{Time,Ratio64}; use crate::integer::{Time,Ratio64};
//this could be about half as long if I only had pub struct Paused{}
//scaled timers and just used a scale of 1 pub struct Unpaused{}
//but I thought the concept of a timer that could
//only be paused and not scaled was cool
trait TimerState:Copy{ pub trait PauseState{
fn get_time(&self,time:Time)->Time; const IS_PAUSED:bool;
fn set_time(&mut self,time:Time,new_time:Time); }
fn get_offset(&self)->Time; impl PauseState for Paused{
fn set_offset(&mut self,offset:Time); const IS_PAUSED:bool=true;
}
impl PauseState for Unpaused{
const IS_PAUSED:bool=false;
} }
#[derive(Clone,Copy,Debug)] pub struct Realtime{
offset:Time,
}
impl Realtime{
const fn identity()->Self{
Self{offset:Time::ZERO}
}
}
pub struct Scaled{ pub struct Scaled{
scale:Ratio64, scale:Ratio64,
offset:Time, offset:Time,
@ -36,29 +44,12 @@ impl Scaled{
self.set_time(time,new_time); self.set_time(time,new_time);
} }
} }
impl TimerState for Scaled{
fn get_time(&self,time:Time)->Time{
self.scale(time)+self.offset
}
fn set_time(&mut self,time:Time,new_time:Time){
self.offset=new_time-self.scale(time);
}
fn get_offset(&self)->Time{
self.offset
}
fn set_offset(&mut self,offset:Time){
self.offset=offset;
}
}
#[derive(Clone,Copy,Debug)] pub trait TimerState{
pub struct Realtime{ fn get_time(&self,time:Time)->Time;
offset:Time, fn set_time(&mut self,time:Time,new_time:Time);
} fn get_offset(&self)->Time;
impl Realtime{ fn set_offset(&mut self,offset:Time);
const fn identity()->Self{
Self{offset:Time::ZERO}
}
} }
impl TimerState for Realtime{ impl TimerState for Realtime{
fn get_time(&self,time:Time)->Time{ fn get_time(&self,time:Time)->Time{
@ -74,28 +65,33 @@ impl TimerState for Realtime{
self.offset=offset; self.offset=offset;
} }
} }
impl TimerState for Scaled{
#[derive(Clone,Debug)] fn get_time(&self,time:Time)->Time{
pub struct Timer<T>{ self.scale(time)+self.offset
state:T, }
paused:bool, fn set_time(&mut self,time:Time,new_time:Time){
self.offset=new_time-self.scale(time);
}
fn get_offset(&self)->Time{
self.offset
}
fn set_offset(&mut self,offset:Time){
self.offset=offset;
}
} }
impl Timer<Realtime>{ pub struct TimerFixed<T:TimerState,P:PauseState>{
pub fn realtime(time:Time,new_time:Time)->Self{ state:T,
let mut timer=Self{ paused:P,
state:Realtime::identity(), }
paused:false,
}; pub enum Timer{
timer.set_time(time,new_time); Paused(TimerFixed<Realtime,Paused>),
timer Unpaused(TimerFixed<Realtime,Unpaused>),
} }
pub fn realtime_paused(offset:Time)->Self{ pub enum TimerScaled{
Self{ Paused(TimerFixed<Scaled,Paused>),
state:Realtime{offset}, Unpaused(TimerFixed<Scaled,Unpaused>),
paused:true,
}
}
} }
#[derive(Debug)] #[derive(Debug)]
@ -110,100 +106,45 @@ impl std::fmt::Display for Error{
} }
impl std::error::Error for Error{} impl std::error::Error for Error{}
impl Timer<Scaled>{ impl<T:TimerState,P:PauseState> TimerFixed<T,P>{
pub fn new(time:Time,new_time:Time,scale:Ratio64,paused:bool)->Self{
let mut timer=Self{
state:Scaled::with_scale(scale),
paused,
};
timer.set_time(time,new_time);
timer
}
pub fn scaled(time:Time,new_time:Time,scale:Ratio64)->Self{
let mut timer=Self{
state:Scaled::with_scale(scale),
paused:false,
};
timer.set_time(time,new_time);
timer
}
pub fn scaled_paused(time:Time,new_time:Time,scale:Ratio64)->Self{
let mut timer=Self{
state:Scaled::with_scale(scale),
paused:true,
};
timer.set_time(time,new_time);
timer
}
pub const fn get_scale(&self)->Ratio64{
self.state.get_scale()
}
pub fn set_scale(&mut self,time:Time,new_scale:Ratio64){
self.state.set_scale(time,new_scale)
}
}
impl<T:TimerState> Timer<T>{
pub fn time(&self,time:Time)->Time{ pub fn time(&self,time:Time)->Time{
match self.paused{ match P::IS_PAUSED{
true=>self.state.get_offset(), true=>self.state.get_offset(),
false=>self.state.get_time(time), false=>self.state.get_time(time),
} }
} }
pub fn set_time(&mut self,time:Time,new_time:Time){ pub fn set_time(&mut self,time:Time,new_time:Time){
match self.paused{ match P::IS_PAUSED{
true=>self.state.set_offset(new_time), true=>self.state.set_offset(new_time),
false=>self.state.set_time(time,new_time), false=>self.state.set_time(time,new_time),
} }
} }
pub fn pause(&mut self,time:Time)->Result<(),Error>{ pub fn pause(self,time:Time)->Result<TimerFixed<T,Paused>,Error>{
match self.paused{ match P::IS_PAUSED{
true=>Err(Error::AlreadyPaused), true=>Err(Error::AlreadyPaused),
false=>{ false=>{
let new_time=self.time(time); let new_time=self.time(time);
self.state.set_offset(new_time); let mut timer=TimerFixed{
self.paused=true; state:self.state,
Ok(()) paused:Paused{},
};
timer.set_time(time,new_time);
Ok(timer)
}, },
} }
} }
pub fn unpause(&mut self,time:Time)->Result<(),Error>{ pub fn unpause(self,time:Time)->Result<TimerFixed<T,Unpaused>,Error>{
match self.paused{ match P::IS_PAUSED{
true=>{ true=>{
let new_time=self.time(time); let new_time=self.time(time);
self.state.set_time(time,new_time); let mut timer=TimerFixed{
self.paused=false; state:self.state,
Ok(()) paused:Unpaused{},
};
timer.set_time(time,new_time);
Ok(timer)
}, },
false=>Err(Error::AlreadyUnpaused), false=>Err(Error::AlreadyUnpaused),
} }
} }
} }
#[cfg(test)]
mod test{
use super::{Time,Timer,Error};
macro_rules! sec {
($s: expr) => {
Time::from_secs($s)
};
}
#[test]
fn test_timer()->Result<(),Error>{
//create a paused timer that reads 0s
let mut timer=Timer::realtime_paused(sec!(0));
//the paused timer at 1 second should read 0s
assert_eq!(timer.time(sec!(1)),sec!(0));
//unpause it after one second
timer.unpause(sec!(1))?;
//the timer at 6 seconds should read 5s
assert_eq!(timer.time(sec!(6)),sec!(5));
//pause the timer after 11 seconds
timer.pause(sec!(11))?;
//the paused timer at 20 seconds should read 10s
assert_eq!(timer.time(sec!(20)),sec!(10));
Ok(())
}
}