no time control for practice
This commit is contained in:
parent
39501c167a
commit
1070d3482a
@ -31,6 +31,8 @@
|
||||
|
||||
mobile info page
|
||||
|
||||
mnml tv
|
||||
|
||||
rework scatter
|
||||
hatred maybe
|
||||
|
||||
|
||||
@ -333,11 +333,11 @@
|
||||
height: 2px;
|
||||
transform-origin: center;
|
||||
background-color: whitesmoke;
|
||||
animation: equipping-skill 2s infinite ease alternate;
|
||||
animation: equipping-skill 2s infinite ease-out alternate;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.equipping::after, .equip-spec::after {
|
||||
.equipping::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: 2px;
|
||||
@ -346,7 +346,7 @@
|
||||
height: 2px;
|
||||
transform-origin: center;
|
||||
background-color: whitesmoke;
|
||||
animation: equipping-skill 2s infinite ease alternate;
|
||||
animation: equipping-skill 2s infinite ease-out alternate;
|
||||
opacity: 0;
|
||||
animation-delay: 0.75s
|
||||
}
|
||||
@ -373,7 +373,16 @@
|
||||
}
|
||||
|
||||
.equip-spec::after {
|
||||
animation-delay: 0;
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: 2px;
|
||||
left: 50%;
|
||||
width: 100%;
|
||||
height: 2px;
|
||||
transform-origin: center;
|
||||
background-color: whitesmoke;
|
||||
animation: equipping-skill 2s infinite ease-out alternate;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.equip .specs figcaption {
|
||||
|
||||
@ -108,7 +108,7 @@ function GameFooter(props) {
|
||||
const now = Date.now();
|
||||
const end = Date.parse(game.phase_end);
|
||||
const timerPct = ((now - zero) / (end - zero) * 100);
|
||||
const displayPct = resolution || game.phase === 'Finish'
|
||||
const displayPct = resolution || game.phase === 'Finish' || !game.phase_end
|
||||
? 0
|
||||
: Math.min(timerPct, 100);
|
||||
|
||||
@ -123,11 +123,13 @@ function GameFooter(props) {
|
||||
background: displayColour,
|
||||
};
|
||||
|
||||
const timer = (
|
||||
<div class="timer-container">
|
||||
<div class="timer" style={timerStyles} > </div>
|
||||
</div>
|
||||
);
|
||||
const timer = game.phase_end
|
||||
? (
|
||||
<div class="timer-container">
|
||||
<div class="timer" style={timerStyles} > </div>
|
||||
</div>
|
||||
)
|
||||
: null;
|
||||
|
||||
return (
|
||||
<footer>
|
||||
|
||||
@ -67,7 +67,7 @@ class InstanceCreateForm extends Component {
|
||||
placeholder="game name"
|
||||
onInput={this.nameInput}
|
||||
/>
|
||||
<label htmlFor="pveSelect">Practice Mode - Bo10, vs CPU, 2x turn time</label>
|
||||
<label htmlFor="pveSelect">Practice Mode - Bo10, vs CPU, no time control</label>
|
||||
<input id="pveSelect"
|
||||
type="checkbox"
|
||||
disabled={disabled}
|
||||
|
||||
@ -94,7 +94,9 @@ function Instance(args) {
|
||||
const zero = Date.parse(instance.phase_start);
|
||||
const now = Date.now();
|
||||
const end = Date.parse(instance.phase_end);
|
||||
const timerPct = ((now - zero) / (end - zero) * 100);
|
||||
const timerPct = instance.phase_end
|
||||
? ((now - zero) / (end - zero) * 100)
|
||||
: 0;
|
||||
|
||||
const displayColour = player.ready
|
||||
? 'forestgreen'
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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());
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user