-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
226132f
commit ad1779d
Showing
17 changed files
with
317 additions
and
49 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
#[derive(Clone, Debug)] | ||
pub struct DecayingStats { | ||
pub mean: f64, | ||
pub deviation: f64, | ||
pub decay: f64, | ||
} | ||
|
||
impl DecayingStats { | ||
pub fn record(&mut self, value: f64) { | ||
let delta = self.mean - value; | ||
self.mean = value + self.decay * delta; | ||
self.deviation = self.decay * self.deviation + (1.0 - self.decay) * delta.abs(); | ||
} | ||
|
||
pub fn empty() -> Self { | ||
DecayingStats { | ||
mean: 0.0, | ||
deviation: 4.0, | ||
decay: 0.85, | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
use crate::lag_tracking::{decaying_stats::DecayingStats, stats::Stats}; | ||
|
||
#[derive(Clone, Debug)] | ||
pub struct LagTracker { | ||
pub quota_gain: f64, | ||
pub quota: f64, | ||
pub quota_max: f64, | ||
pub lag_estimator: DecayingStats, | ||
pub uncomp_stats: Stats, | ||
pub lag_stats: Stats, | ||
pub comp_est_sq_err: f64, | ||
pub comp_est_overs: f64, | ||
pub comp_estimate: Option<f64>, | ||
} | ||
|
||
impl LagTracker { | ||
pub fn new(base: usize, inc: usize) -> Self { | ||
let quota_gain = Self::quota_base_inc(base, inc); | ||
|
||
Self { | ||
quota_gain, | ||
quota: quota_gain * 3.0, | ||
quota_max: quota_gain * 7.0, | ||
lag_estimator: DecayingStats::empty(), | ||
uncomp_stats: Stats::default(), | ||
lag_stats: Stats::default(), | ||
comp_est_sq_err: 0.0, | ||
comp_est_overs: 0.0, | ||
comp_estimate: None, | ||
} | ||
} | ||
|
||
fn quota_base_inc(base: usize, inc: usize) -> f64 { | ||
let game_time = base as f64 + inc as f64 * 40.0; | ||
((game_time / 2.5 + 15.0) / 1000.0).min(100.0) | ||
} | ||
|
||
pub fn on_move(&mut self, lag: f64) -> f64 { | ||
let comp = lag.min(self.quota); | ||
let uncomped = lag - comp; | ||
let ce_diff = self.comp_estimate.unwrap_or(1.0) - comp; | ||
let new_quota = (self.quota + self.quota_gain - comp).min(self.quota_max); | ||
|
||
if uncomped != 0.0 || self.uncomp_stats.samples != 0 { | ||
self.uncomp_stats.record(uncomped); | ||
} | ||
|
||
self.lag_stats.record(lag.min(2000.0)); | ||
self.comp_est_sq_err += ce_diff * ce_diff; | ||
self.comp_est_overs += ce_diff.min(0.0); | ||
self.quota = new_quota; | ||
comp | ||
} | ||
|
||
pub fn record_lag(&mut self, lag: f64) { | ||
self.lag_estimator.record(lag); | ||
self.comp_estimate = Some( | ||
0_f64 | ||
.min(self.lag_estimator.mean - 0.8 * self.lag_estimator.deviation) | ||
.min(self.quota_max), | ||
); | ||
} | ||
|
||
pub fn moves(&self) -> usize { | ||
self.lag_stats.samples | ||
} | ||
|
||
pub fn lag_mean(&self) -> Option<f64> { | ||
if self.moves() > 0 { | ||
Some(self.lag_stats.total / self.moves() as f64) | ||
} else { | ||
None | ||
} | ||
} | ||
|
||
pub fn comp_est_std_err(&self) -> Option<f64> { | ||
if self.moves() > 2 { | ||
Some(self.comp_est_sq_err.sqrt() / ((self.moves() - 2) as f64)) | ||
} else { | ||
None | ||
} | ||
} | ||
|
||
pub fn comp_avg(&self) -> Option<f64> { | ||
if self.moves() > 0 { | ||
Some(self.total_comp() / self.moves() as f64) | ||
} else { | ||
None | ||
} | ||
} | ||
|
||
pub fn total_comp(&self) -> f64 { | ||
self.total_lag() - self.total_uncomped() | ||
} | ||
|
||
pub fn total_lag(&self) -> f64 { | ||
self.lag_stats.total | ||
} | ||
|
||
pub fn total_uncomped(&self) -> f64 { | ||
self.uncomp_stats.total | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
use crate::lag_tracking::lag_tracker::LagTracker; | ||
use shared_types::GameId; | ||
use std::{collections::HashMap, sync::RwLock}; | ||
use uuid::Uuid; | ||
|
||
#[derive(Debug)] | ||
pub struct Lags { | ||
trackers: RwLock<HashMap<(Uuid, GameId), LagTracker>>, | ||
} | ||
|
||
impl Lags { | ||
pub fn new() -> Self { | ||
Self { | ||
trackers: RwLock::new(HashMap::new()), | ||
} | ||
} | ||
|
||
pub fn track_lag( | ||
&self, | ||
uuid: Uuid, | ||
game: GameId, | ||
lag: f64, | ||
base: usize, | ||
inc: usize, | ||
) -> Option<f64> { | ||
if let Ok(mut uuids_lags) = self.trackers.write() { | ||
let user_lags = uuids_lags | ||
.entry((uuid, game)) | ||
.or_insert(LagTracker::new(base, inc)); | ||
user_lags.record_lag(lag / 1000.0); | ||
let comp = Some(user_lags.on_move(lag / 1000.0)); | ||
return comp; | ||
} | ||
None | ||
} | ||
|
||
pub fn remove(&self, uuid: Uuid, game: GameId) { | ||
if let Ok(mut trackers) = self.trackers.write() { | ||
trackers.remove(&(uuid, game)); | ||
} | ||
} | ||
} | ||
|
||
impl Default for Lags { | ||
fn default() -> Self { | ||
Self::new() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
pub mod decaying_stats; | ||
pub mod lag_tracker; | ||
pub mod lags; | ||
pub mod stats; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
#[derive(Clone, Debug)] | ||
pub struct Stats { | ||
pub samples: usize, | ||
pub total: f64, | ||
} | ||
|
||
impl Stats { | ||
pub fn new() -> Self { | ||
Stats { | ||
samples: 0, | ||
total: 0.0, | ||
} | ||
} | ||
|
||
pub fn record(&mut self, value: f64) { | ||
self.samples += 1; | ||
self.total += value; | ||
} | ||
} | ||
|
||
impl Default for Stats { | ||
fn default() -> Self { | ||
Self::new() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.