no time control for practice

This commit is contained in:
ntr
2019-06-09 17:38:25 +10:00
parent 39501c167a
commit 1070d3482a
8 changed files with 117 additions and 40 deletions
+11 -8
View File
@@ -38,8 +38,8 @@ pub struct Game {
pub resolved: Vec<Resolution>,
pub instance: Option<Uuid>,
time_control: TimeControl,
phase_end: DateTime<Utc>,
phase_start: DateTime<Utc>,
phase_end: Option<DateTime<Utc>>,
}
impl Game {
@@ -54,13 +54,14 @@ impl Game {
resolved: vec![],
instance: None,
time_control: TimeControl::Standard,
phase_end: Utc::now(),
phase_end: None,
phase_start: Utc::now(),
};
}
pub fn set_time_control(&mut self, tc: TimeControl) -> &mut Game {
self.time_control = tc;
self.phase_end = Some(tc.lobby_timeout());
self
}
@@ -159,13 +160,12 @@ impl Game {
fn skill_phase_start(mut self, num_resolutions: usize) -> Game {
let resolution_animation_ms = num_resolutions as i64 * 2500;
let phase_add_time_ms = self.time_control.game_time_seconds() * 1000 + resolution_animation_ms;
self.phase_start = Utc::now()
.checked_add_signed(Duration::milliseconds(resolution_animation_ms))
.expect("could not set phase start");
self.phase_end = Utc::now()
.checked_add_signed(Duration::milliseconds(phase_add_time_ms as i64))
.expect("could not set phase end");
self.phase_end = self.time_control.game_phase_end(resolution_animation_ms);
for player in self.players.iter_mut() {
if player.skills_required() == 0 {
@@ -571,7 +571,10 @@ impl Game {
}
fn phase_timed_out(&self) -> bool {
Utc::now().signed_duration_since(self.phase_end).num_milliseconds() > 0
match self.phase_end {
Some(t) => Utc::now().signed_duration_since(t).num_milliseconds() > 0,
None => false,
}
}
pub fn upkeep(mut self) -> Game {
@@ -1435,7 +1438,7 @@ mod tests {
fn upkeep_test() {
let mut game = create_2v2_test_game();
game.players[0].set_ready(true);
game.phase_end = Utc::now().checked_sub_signed(Duration::seconds(61)).unwrap();
game.phase_end = Some(Utc::now().checked_sub_signed(Duration::seconds(500)).unwrap());
game = game.upkeep();
assert!(game.players[1].warnings == 1);
}
+73 -16
View File
@@ -45,6 +45,7 @@ impl Round {
#[derive(Debug,Clone,Copy,Serialize,Deserialize)]
pub enum TimeControl {
Standard,
Slow,
Practice,
}
@@ -52,21 +53,47 @@ impl TimeControl {
fn vbox_time_seconds(&self) -> i64 {
match self {
TimeControl::Standard => 120,
TimeControl::Practice => 240,
TimeControl::Slow => 240,
TimeControl::Practice => panic!("practice vbox seconds called"),
}
}
pub fn game_time_seconds(&self) -> i64 {
fn game_time_seconds(&self) -> i64 {
match self {
TimeControl::Standard => 60,
TimeControl::Practice => 120,
TimeControl::Slow => 120,
TimeControl::Practice => panic!("practice game seconds called"),
}
}
pub fn vbox_phase_end(&self) -> Option<DateTime<Utc>> {
match self {
TimeControl::Practice => None,
_ => Some(Utc::now()
.checked_add_signed(Duration::seconds(self.vbox_time_seconds()))
.expect("could not set vbox phase end")),
}
}
pub fn lobby_timeout(&self) -> DateTime<Utc> {
Utc::now()
.checked_add_signed(Duration::minutes(5))
.expect("could not set phase end")
}
pub fn game_phase_end(&self, resolution_time_ms: i64) -> Option<DateTime<Utc>> {
match self {
TimeControl::Practice => None,
_ => Some(Utc::now()
.checked_add_signed(Duration::milliseconds(self.vbox_time_seconds() * 1000 + resolution_time_ms))
.expect("could not set game phase end")),
}
}
}
#[derive(Debug,Clone,Serialize,Deserialize)]
pub struct Instance {
id: Uuid,
pub id: Uuid,
pub name: String,
players: Vec<Player>,
@@ -79,7 +106,7 @@ pub struct Instance {
time_control: TimeControl,
phase: InstancePhase,
phase_end: DateTime<Utc>,
phase_end: Option<DateTime<Utc>>,
phase_start: DateTime<Utc>,
}
@@ -97,9 +124,7 @@ impl Instance {
time_control: TimeControl::Standard,
password: None,
phase_start: Utc::now(),
phase_end: Utc::now()
.checked_add_signed(Duration::minutes(5))
.expect("could not set phase end"),
phase_end: Some(TimeControl::Standard.lobby_timeout()),
}
}
@@ -116,12 +141,15 @@ impl Instance {
name: "Global Matchmaking".to_string(),
password: None,
phase_start: Utc::now(),
phase_end: Utc::now(),
phase_end: Some(TimeControl::Standard.lobby_timeout()),
}
}
fn phase_timed_out(&self) -> bool {
Utc::now().signed_duration_since(self.phase_end).num_milliseconds() > 0
match self.phase_end {
Some(t) => Utc::now().signed_duration_since(t).num_milliseconds() > 0,
None => false,
}
}
fn timed_out_players(&self) -> Vec<Uuid> {
@@ -312,9 +340,7 @@ impl Instance {
self.phase = InstancePhase::InProgress;
self.phase_start = Utc::now();
self.phase_end = Utc::now()
.checked_add_signed(Duration::seconds(self.time_control.vbox_time_seconds()))
.expect("could not set phase end");
self.phase_end = self.time_control.vbox_phase_end();
self.players.iter_mut().for_each(|p| {
@@ -336,7 +362,7 @@ impl Instance {
|| self.rounds.len() == self.max_rounds
}
fn finish(&mut self) -> &mut Instance {
pub fn finish(&mut self) -> &mut Instance {
self.phase = InstancePhase::Finished;
self
}
@@ -637,6 +663,37 @@ pub fn instances_need_upkeep(tx: &mut Transaction) -> Result<Vec<Instance>, Erro
return Ok(list);
}
// timed out instances with no time control
pub fn instances_idle(tx: &mut Transaction) -> Result<Vec<Instance>, Error> {
let query = "
SELECT data, id
FROM instances
WHERE finished = false
AND updated_at < now() - interval '1 hour'
FOR UPDATE;
";
let result = tx
.query(query, &[])?;
let mut list = vec![];
for row in result.into_iter() {
let bytes: Vec<u8> = row.get(0);
let id = row.get(1);
match from_slice::<Instance>(&bytes) {
Ok(i) => list.push(i),
Err(_e) => {
instance_delete(tx, id)?;
}
};
}
return Ok(list);
}
pub fn instance_new(params: InstanceLobbyParams, tx: &mut Transaction, account: &Account) -> Result<Instance, Error> {
let mut instance = match params.pve {
true => Instance::new()
@@ -801,7 +858,7 @@ mod tests {
instance.player_ready(a_id).expect("a ready");
instance.player_ready(b_id).expect("b ready");
instance.phase_end = Utc::now().checked_sub_signed(Duration::seconds(61)).unwrap();
instance.phase_end = Some(Utc::now().checked_sub_signed(Duration::seconds(500)).unwrap());
let (mut instance, new_games) = instance.upkeep();
@@ -830,7 +887,7 @@ mod tests {
instance.add_player(player).expect("could not add player");
assert!(!instance.can_start());
instance.phase_end = Utc::now().checked_sub_signed(Duration::minutes(61)).unwrap();
instance.phase_end = Some(Utc::now().checked_sub_signed(Duration::minutes(61)).unwrap());
let (instance, _new_games) = instance.upkeep();
assert!(instance.finished());
+6 -4
View File
@@ -4,7 +4,7 @@ use postgres::transaction::Transaction;
use failure::Error;
use game::{games_need_upkeep, game_update, game_write, game_delete};
use instance::{instances_need_upkeep, instance_update};
use instance::{instances_need_upkeep, instances_idle, instance_update, instance_delete};
use net::{Db};
fn fetch_games(mut tx: Transaction) -> Result<Transaction, Error> {
@@ -25,9 +25,7 @@ fn fetch_games(mut tx: Transaction) -> Result<Transaction, Error> {
}
fn fetch_instances(mut tx: Transaction) -> Result<Transaction, Error> {
let instances = instances_need_upkeep(&mut tx)?;
for mut instance in instances {
for mut instance in instances_need_upkeep(&mut tx)? {
let (instance, new_games) = instance.upkeep();
for game in new_games {
game_write(&mut tx, &game)?;
@@ -35,6 +33,10 @@ fn fetch_instances(mut tx: Transaction) -> Result<Transaction, Error> {
instance_update(&mut tx, instance)?;
}
for mut instance in instances_idle(&mut tx)? {
instance_delete(&mut tx, instance.id)?;
}
Ok(tx)
}