about to change teams -> player
This commit is contained in:
parent
618f366796
commit
15ae93e70f
@ -67,10 +67,11 @@ class InstanceCreateForm extends Component {
|
||||
<label htmlFor="playerSelect">players</label>
|
||||
<select id="playerSelect"
|
||||
disabled={disabled}
|
||||
value={this.state.players}
|
||||
onChange={this.playersChange}
|
||||
>
|
||||
<option value={1}>pve</option>
|
||||
<option selected value={2}>2</option>
|
||||
<option value={2}>2</option>
|
||||
<option value={4}>4</option>
|
||||
<option value={8}>8</option>
|
||||
<option value={16}>16</option>
|
||||
|
||||
@ -6,6 +6,10 @@ exports.up = async knex => {
|
||||
table.index('id');
|
||||
table.timestamps(true, true);
|
||||
table.binary('data').notNullable();
|
||||
table.boolean('finished')
|
||||
.defaultTo(false)
|
||||
.notNullable()
|
||||
.index();
|
||||
});
|
||||
|
||||
await knex.schema.createTable('instances', async table => {
|
||||
@ -14,7 +18,7 @@ exports.up = async knex => {
|
||||
table.timestamps(true, true);
|
||||
|
||||
table.binary('data').notNullable();
|
||||
table.boolean('finished')
|
||||
table.boolean('open')
|
||||
.defaultTo(false)
|
||||
.notNullable()
|
||||
.index();
|
||||
|
||||
@ -89,6 +89,8 @@ make strike *really* hit first / resolve at same time?
|
||||
* not sure hwo to get sets of player games
|
||||
* set joined_games_$account [game_id]
|
||||
|
||||
* move team -> player
|
||||
|
||||
* chat
|
||||
* notifications
|
||||
* elo + leaderboards
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
use rand::prelude::*;
|
||||
use uuid::Uuid;
|
||||
|
||||
use std::time::Instant;
|
||||
// timekeeping
|
||||
use chrono::prelude::*;
|
||||
use chrono::Duration;
|
||||
|
||||
// Db Commons
|
||||
use serde_cbor::{from_slice, to_vec};
|
||||
@ -22,6 +24,7 @@ pub struct Team {
|
||||
pub player: Option<Uuid>,
|
||||
pub bot: bool,
|
||||
pub cryps: Vec<Cryp>,
|
||||
pub ready: bool,
|
||||
}
|
||||
|
||||
impl Team {
|
||||
@ -31,6 +34,7 @@ impl Team {
|
||||
player: None,
|
||||
cryps: vec![],
|
||||
bot: false,
|
||||
ready: false,
|
||||
};
|
||||
}
|
||||
|
||||
@ -95,6 +99,7 @@ pub struct Game {
|
||||
pub log: Vec<String>,
|
||||
pub instance: Option<Uuid>,
|
||||
pub mode: GameMode,
|
||||
phase_start: DateTime<Utc>,
|
||||
}
|
||||
|
||||
impl Game {
|
||||
@ -110,6 +115,7 @@ impl Game {
|
||||
log: vec![],
|
||||
instance: None,
|
||||
mode: GameMode::Normal,
|
||||
phase_start: Utc::now(),
|
||||
};
|
||||
}
|
||||
|
||||
@ -218,6 +224,7 @@ impl Game {
|
||||
}
|
||||
|
||||
fn skill_phase_start(mut self) -> Game {
|
||||
self.phase_start = Utc::now();
|
||||
self.log.push("<Skill Phase>".to_string());
|
||||
|
||||
if ![Phase::Start, Phase::Resolve].contains(&self.phase) {
|
||||
@ -349,14 +356,15 @@ impl Game {
|
||||
}
|
||||
|
||||
fn skill_phase_finished(&self) -> bool {
|
||||
self.teams.iter()
|
||||
// for every team
|
||||
.all(|t| self.stack.iter()
|
||||
// the number of skills they have cast
|
||||
.filter(|s| s.source_team_id == t.id).collect::<Vec<&Cast>>()
|
||||
// should equal the number required this turn
|
||||
.len() == t.skills_required()
|
||||
)
|
||||
self.teams.iter().all(|t| t.ready)
|
||||
// self.teams.iter()
|
||||
// // for every team
|
||||
// .all(|t| self.stack.iter()
|
||||
// // the number of skills they have cast
|
||||
// .filter(|s| s.source_team_id == t.id).collect::<Vec<&Cast>>()
|
||||
// // should equal the number required this turn
|
||||
// .len() == t.skills_required()
|
||||
// )
|
||||
}
|
||||
|
||||
// requires no input
|
||||
@ -590,75 +598,24 @@ impl Game {
|
||||
self
|
||||
}
|
||||
|
||||
fn phase_timed_out(&self) -> bool {
|
||||
Utc::now().signed_duration_since(self.phase_start).num_seconds() > 30
|
||||
}
|
||||
|
||||
pub fn upkeep(mut self) -> Game {
|
||||
// give teams a ready status
|
||||
// on time out if not enough skills selected
|
||||
// add a warning
|
||||
// on 3 warnings forfeit
|
||||
|
||||
if self.phase == Phase::Skill && self.phase_timed_out() {
|
||||
self = self.resolve_phase_start();
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
pub fn game_skill(params: GameSkillParams, tx: &mut Transaction, account: &Account) -> Result<Game, Error> {
|
||||
let query = "
|
||||
SELECT *
|
||||
FROM games
|
||||
WHERE id = $1
|
||||
";
|
||||
|
||||
let result = tx
|
||||
.query(query, &[¶ms.game_id])?;
|
||||
|
||||
let returned = match result.iter().next() {
|
||||
Some(row) => row,
|
||||
None => return Err(err_msg("game not found")),
|
||||
};
|
||||
|
||||
// tells from_slice to cast into a cryp
|
||||
let game_bytes: Vec<u8> = returned.get("data");
|
||||
let mut game = from_slice::<Game>(&game_bytes)?;
|
||||
|
||||
if game.phase != Phase::Skill {
|
||||
return Err(err_msg("game not in skill phase"))
|
||||
}
|
||||
|
||||
game.add_skill(account.id, params.cryp_id, params.target_cryp_id, params.skill)?;
|
||||
|
||||
if game.skill_phase_finished() {
|
||||
game = game.resolve_phase_start();
|
||||
}
|
||||
|
||||
game_update(tx, &game)?;
|
||||
|
||||
Ok(game)
|
||||
}
|
||||
|
||||
// pub fn game_target(params: GameTargetParams, tx: &mut Transaction, account: &Account) -> Result<Game, Error> {
|
||||
// let query = "
|
||||
// SELECT *
|
||||
// FROM games
|
||||
// WHERE id = $1
|
||||
// ";
|
||||
|
||||
// let result = tx
|
||||
// .query(query, &[¶ms.game_id])?;
|
||||
|
||||
// let returned = match result.iter().next() {
|
||||
// Some(row) => row,
|
||||
// None => return Err(err_msg("game not found")),
|
||||
// };
|
||||
|
||||
// // tells from_slice to cast into a cryp
|
||||
// let game_bytes: Vec<u8> = returned.get("data");
|
||||
// let mut game = from_slice::<Game>(&game_bytes)?;
|
||||
|
||||
// game.add_target(account.id, params.cryp_id, params.skill_id)?;
|
||||
|
||||
// if game.target_phase_finished() {
|
||||
// game.resolve_phase_start();
|
||||
// }
|
||||
|
||||
// game_update(game, tx)?;
|
||||
|
||||
// Ok(game)
|
||||
// }
|
||||
|
||||
pub fn game_write(tx: &mut Transaction, game: &Game) -> Result<(), Error> {
|
||||
let game_bytes = to_vec(&game)?;
|
||||
|
||||
@ -847,7 +804,7 @@ pub fn game_update(tx: &mut Transaction, game: &Game) -> Result<(), Error> {
|
||||
|
||||
let query = "
|
||||
UPDATE games
|
||||
SET data = $1, complete = $2, updated_at = now()
|
||||
SET data = $1, finished = $2, updated_at = now()
|
||||
WHERE id = $3
|
||||
RETURNING id, data;
|
||||
";
|
||||
@ -869,6 +826,34 @@ pub fn game_update(tx: &mut Transaction, game: &Game) -> Result<(), Error> {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
pub fn game_skill(params: GameSkillParams, tx: &mut Transaction, account: &Account) -> Result<Game, Error> {
|
||||
let mut game = game_get(tx, params.game_id)?;
|
||||
|
||||
game.add_skill(account.id, params.cryp_id, params.target_cryp_id, params.skill)?;
|
||||
|
||||
if game.skill_phase_finished() {
|
||||
game = game.resolve_phase_start();
|
||||
}
|
||||
|
||||
game_update(tx, &game)?;
|
||||
|
||||
Ok(game)
|
||||
}
|
||||
|
||||
pub fn game_ready(params: GameSkillParams, tx: &mut Transaction, account: &Account) -> Result<Game, Error> {
|
||||
let mut game = game_get(tx, params.game_id)?;
|
||||
|
||||
game.player_ready(account.id, params.cryp_id, params.target_cryp_id, params.skill)?;
|
||||
|
||||
if game.skill_phase_finished() {
|
||||
game = game.resolve_phase_start();
|
||||
}
|
||||
|
||||
game_update(tx, &game)?;
|
||||
|
||||
Ok(game)
|
||||
}
|
||||
|
||||
// pub fn game_pve_new(cryp_ids: Vec<Uuid>, mode: GameMode, tx: &mut Transaction, account: &Account) -> Result<Game, Error> {
|
||||
// if cryp_ids.len() == 0 {
|
||||
// return Err(err_msg("no cryps selected"));
|
||||
@ -1325,4 +1310,12 @@ mod tests {
|
||||
assert!(game.team_by_id(x_team.id).skills_required() == 2);
|
||||
return;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn upkeep_test() {
|
||||
let mut game = create_2v2_test_game();
|
||||
game.phase_start = Utc::now().checked_sub_signed(Duration::seconds(31)).unwrap();
|
||||
|
||||
println!("{:?}", game.upkeep());
|
||||
}
|
||||
}
|
||||
|
||||
@ -375,7 +375,7 @@ impl Instance {
|
||||
current_round
|
||||
}
|
||||
|
||||
fn current_game(&mut self, player_id: Uuid) -> Option<Uuid> {
|
||||
fn current_game(&self, player_id: Uuid) -> Option<Uuid> {
|
||||
if self.phase == InstancePhase::Lobby {
|
||||
return None;
|
||||
}
|
||||
@ -388,7 +388,10 @@ impl Instance {
|
||||
.all(|p| p.ready);
|
||||
|
||||
match can_start {
|
||||
true => Some(current_round.game_id),
|
||||
true => match current_round.finished {
|
||||
true => None,
|
||||
false => Some(current_round.game_id),
|
||||
},
|
||||
false => None,
|
||||
}
|
||||
}
|
||||
@ -401,37 +404,54 @@ impl Instance {
|
||||
.ok_or(err_msg("account not in instance"))
|
||||
}
|
||||
|
||||
pub fn vbox_action_allowed(&self, account: Uuid) -> Result<(), Error> {
|
||||
if self.phase == InstancePhase::Lobby {
|
||||
return Err(err_msg("game not yet started"));
|
||||
}
|
||||
if self.current_game(account).is_some() {
|
||||
return Err(err_msg("you cannot perform vbox actions while in a game"));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn vbox_discard(mut self, account: Uuid) -> Result<Instance, Error> {
|
||||
self.vbox_action_allowed(account)?;
|
||||
self.account_player(account)?
|
||||
.vbox_discard()?;
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
pub fn vbox_accept(mut self, account: Uuid, group: usize, index: usize) -> Result<Instance, Error> {
|
||||
self.vbox_action_allowed(account)?;
|
||||
self.account_player(account)?
|
||||
.vbox_accept(group, index)?;
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
pub fn vbox_combine(mut self, account: Uuid, indices: Vec<usize>) -> Result<Instance, Error> {
|
||||
self.vbox_action_allowed(account)?;
|
||||
self.account_player(account)?
|
||||
.vbox_combine(indices)?;
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
pub fn vbox_reclaim(mut self, account: Uuid, index: usize) -> Result<Instance, Error> {
|
||||
self.vbox_action_allowed(account)?;
|
||||
self.account_player(account)?
|
||||
.vbox_reclaim(index)?;
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
pub fn vbox_apply(mut self, account: Uuid, index: usize, cryp_id: Uuid) -> Result<Instance, Error> {
|
||||
self.vbox_action_allowed(account)?;
|
||||
self.account_player(account)?
|
||||
.vbox_apply(index, cryp_id)?;
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
pub fn vbox_unequip(mut self, account: Uuid, target: Var, cryp_id: Uuid) -> Result<Instance, Error> {
|
||||
self.vbox_action_allowed(account)?;
|
||||
self.account_player(account)?
|
||||
.vbox_unequip(target, cryp_id)?;
|
||||
Ok(self)
|
||||
@ -541,7 +561,8 @@ pub fn instances_need_upkeep(tx: &mut Transaction) -> Result<Vec<Instance>, Erro
|
||||
let query = "
|
||||
SELECT data, id
|
||||
FROM instances
|
||||
WHERE updated_at < now() - interval '5 seconds';
|
||||
WHERE updated_at < now() - interval '5 seconds'
|
||||
AND id != '00000000-0000-0000-0000-000000000000';
|
||||
";
|
||||
|
||||
let result = tx
|
||||
|
||||
@ -7,7 +7,8 @@ use std::net::{TcpListener, TcpStream};
|
||||
use serde_cbor::{to_vec};
|
||||
|
||||
use std::env;
|
||||
use std::thread::spawn;
|
||||
use std::thread::{spawn, sleep};
|
||||
use std::time::Duration;
|
||||
|
||||
use r2d2::{Pool};
|
||||
use r2d2::{PooledConnection};
|
||||
@ -72,7 +73,16 @@ pub fn start() {
|
||||
let server = TcpListener::bind("0.0.0.0:40000").unwrap();
|
||||
|
||||
let warden_pool = pool.clone();
|
||||
spawn(move || warden(warden_pool));
|
||||
spawn(move || {
|
||||
loop {
|
||||
let db_connection = warden_pool.get().expect("unable to get db connection");
|
||||
if let Err(e) = warden(db_connection) {
|
||||
println!("{:?}", e);
|
||||
}
|
||||
sleep(Duration::new(5, 0));
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
for stream in server.incoming() {
|
||||
let db = pool.clone();
|
||||
|
||||
@ -558,19 +558,19 @@ pub fn vbox_combine(params: VboxCombineParams, tx: &mut Transaction, account: &A
|
||||
}
|
||||
|
||||
pub fn vbox_reclaim(params: VboxReclaimParams, tx: &mut Transaction, account: &Account) -> Result<Instance, Error> {
|
||||
let mut instance = instance_get(tx, params.instance_id)?
|
||||
let instance = instance_get(tx, params.instance_id)?
|
||||
.vbox_reclaim(account.id, params.index)?;
|
||||
return instance_update(tx, instance);
|
||||
}
|
||||
|
||||
pub fn vbox_apply(params: VboxApplyParams, tx: &mut Transaction, account: &Account) -> Result<Instance, Error> {
|
||||
let mut instance = instance_get(tx, params.instance_id)?
|
||||
let instance = instance_get(tx, params.instance_id)?
|
||||
.vbox_apply(account.id, params.index, params.cryp_id)?;
|
||||
return instance_update(tx, instance);
|
||||
}
|
||||
|
||||
pub fn vbox_unequip(params: VboxUnequipParams, tx: &mut Transaction, account: &Account) -> Result<Instance, Error> {
|
||||
let mut instance = instance_get(tx, params.instance_id)?
|
||||
let instance = instance_get(tx, params.instance_id)?
|
||||
.vbox_unequip(account.id, params.target, params.cryp_id)?;
|
||||
return instance_update(tx, instance);
|
||||
}
|
||||
|
||||
@ -11,10 +11,13 @@ use r2d2_postgres::{PostgresConnectionManager};
|
||||
|
||||
use game::{Game, games_need_upkeep, game_update};
|
||||
use instance::{Instance, instances_need_upkeep, instance_update};
|
||||
use net::{Db};
|
||||
|
||||
fn fetch_games(mut tx: Transaction) -> Result<Transaction, Error> {
|
||||
let games = games_need_upkeep(&mut tx)?;
|
||||
|
||||
println!("warden: {:?} games active", games.len());
|
||||
|
||||
for mut game in games {
|
||||
game_update(&mut tx, &game.upkeep())?;
|
||||
}
|
||||
@ -32,16 +35,12 @@ fn fetch_instances(mut tx: Transaction) -> Result<Transaction, Error> {
|
||||
Ok(tx)
|
||||
}
|
||||
|
||||
pub fn warden(pool: Pool<PostgresConnectionManager>) -> Result<(), Error> {
|
||||
loop {
|
||||
let db_connection = pool.get().expect("unable to get db connection");
|
||||
pub fn warden(db: Db) -> Result<(), Error> {
|
||||
fetch_games(db.transaction()?)?
|
||||
.commit()?;
|
||||
|
||||
fetch_games(db_connection.transaction()?)?
|
||||
.commit()?;
|
||||
fetch_instances(db.transaction()?)?
|
||||
.commit()?;
|
||||
|
||||
fetch_instances(db_connection.transaction()?)?
|
||||
.commit()?;
|
||||
|
||||
sleep(Duration::new(1, 0));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user