use crate::timer::{TimerFixed,Realtime,Paused,Unpaused}; use crate::integer::Time; #[derive(Clone,Debug)] pub enum FlagReason{ Anticheat, StyleChange, Clock, Pause, Flying, Gravity, Timescale, TimeTravel, Teleport, } impl ToString for FlagReason{ fn to_string(&self)->String{ match self{ FlagReason::Anticheat=>"Passed through anticheat zone.", FlagReason::StyleChange=>"Changed style.", FlagReason::Clock=>"Incorrect clock. (This can be caused by internet hiccups)", FlagReason::Pause=>"Pausing is not allowed in this style.", FlagReason::Flying=>"Flying is not allowed in this style.", FlagReason::Gravity=>"Gravity modification is not allowed in this style.", FlagReason::Timescale=>"Timescale is not allowed in this style.", FlagReason::TimeTravel=>"Time travel is not allowed in this style.", FlagReason::Teleport=>"Illegal teleport.", }.to_owned() } } #[derive(Debug)] pub enum Error{ NotStarted, AlreadyStarted, AlreadyFinished, } impl std::fmt::Display for Error{ fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{ write!(f,"{self:?}") } } impl std::error::Error for Error{} #[derive(Clone,Debug)] enum RunState{ Created, Started{timer:TimerFixed}, Finished{timer:TimerFixed}, } #[derive(Clone,Debug)] pub struct Run{ state:RunState, flagged:Option, } impl Run{ pub fn new()->Self{ Self{ state:RunState::Created, flagged:None, } } pub fn time(&self,time:Time)->Time{ match &self.state{ RunState::Created=>Time::ZERO, RunState::Started{timer}=>timer.time(time), RunState::Finished{timer}=>timer.time(time), } } pub fn start(&mut self,time:Time)->Result<(),Error>{ match &self.state{ RunState::Created=>{ self.state=RunState::Started{ timer:TimerFixed::new(time,Time::ZERO), }; Ok(()) }, RunState::Started{..}=>Err(Error::AlreadyStarted), RunState::Finished{..}=>Err(Error::AlreadyFinished), } } pub fn finish(&mut self,time:Time)->Result<(),Error>{ //this uses Copy match &self.state{ RunState::Created=>Err(Error::NotStarted), RunState::Started{timer}=>{ self.state=RunState::Finished{ timer:timer.into_paused(time), }; Ok(()) }, RunState::Finished{..}=>Err(Error::AlreadyFinished), } } pub fn flag(&mut self,flag_reason:FlagReason){ //don't replace the first reason the run was flagged if self.flagged.is_none(){ self.flagged=Some(flag_reason); } } }