From 8cd0f1af3653bc44c1449aa60c87088bacfab069 Mon Sep 17 00:00:00 2001 From: ntr Date: Mon, 29 Jul 2019 00:11:46 +1000 Subject: [PATCH] team setting and postgres constraint --- client/assets/styles/styles.less | 6 +-- client/src/actions.jsx | 6 ++- client/src/components/team.footer.jsx | 31 +++++------ client/src/components/team.jsx | 29 +++++------ client/src/reducers.jsx | 4 +- client/src/socket.jsx | 15 +++++- .../20180916221309_constructs_table.js | 52 ++++++++++++++++--- server/src/account.rs | 44 +++++++--------- server/src/rpc.rs | 7 ++- server/src/warden.rs | 2 + 10 files changed, 121 insertions(+), 75 deletions(-) diff --git a/client/assets/styles/styles.less b/client/assets/styles/styles.less index fbe20c70..5b607603 100644 --- a/client/assets/styles/styles.less +++ b/client/assets/styles/styles.less @@ -102,7 +102,7 @@ nav h2 { nav hr { margin: 1em 0; - border-color: whitesmoke; + border-color: #444; } nav button { @@ -120,12 +120,12 @@ nav button.active { } nav button[disabled], nav button[disabled]:hover { - color: #333333; + color: #333; text-decoration: none; } nav button:hover { - color: #888; + color: whitesmoke; text-decoration: underline; } diff --git a/client/src/actions.jsx b/client/src/actions.jsx index 96ba0ef5..d47e552f 100644 --- a/client/src/actions.jsx +++ b/client/src/actions.jsx @@ -31,9 +31,11 @@ export const setShowLog = value => ({ type: 'SET_SHOW_LOG', value }); export const setShowNav = value => ({ type: 'SET_SHOW_NAV', value }); export const setSkip = value => ({ type: 'SET_SKIP', value }); export const setShop = value => ({ type: 'SET_SHOP', value }); -export const setTeam = value => ({ type: 'SET_SELECTED_CONSTRUCTS', value: Array.from(value) }); -export const setVboxHighlight = value => ({ type: 'SET_VBOX_HIGHLIGHT', value }); +export const setTeam = value => ({ type: 'SET_TEAM', value: Array.from(value) }); +export const setTeamSelect = value => ({ type: 'SET_TEAM_SELECT', value: Array.from(value) }); + +export const setVboxHighlight = value => ({ type: 'SET_VBOX_HIGHLIGHT', value }); export const setVboxSelected = value => ({ type: 'SET_VBOX_SELECTED', value }); export const setWs = value => ({ type: 'SET_WS', value }); diff --git a/client/src/components/team.footer.jsx b/client/src/components/team.footer.jsx index 7b28dd9e..db3bb077 100644 --- a/client/src/components/team.footer.jsx +++ b/client/src/components/team.footer.jsx @@ -5,26 +5,29 @@ const actions = require('./../actions'); const addState = connect( function receiveState(state) { - const { team, showNav } = state; + const { + teamSelect, + showNav, + ws, + } = state; + + function sendAccountSetTeam() { + return ws.sendAccountSetTeam(teamSelect); + } return { - team, + sendAccountSetTeam, + teamSelect, showNav, }; }, function receiveDispatch(dispatch) { - function navToList() { - dispatch(actions.setGame(null)); - dispatch(actions.setInstance(null)); - return dispatch(actions.setNav('list')); - } function setShowNav(v) { return dispatch(actions.setShowNav(v)); } return { - navToList, setShowNav, }; } @@ -33,20 +36,18 @@ const addState = connect( function TeamFooter(args) { const { showNav, - team, - navToList, + teamSelect, + sendAccountSetTeam, setShowNav, } = args; - if (!team) return false; - return ( ); diff --git a/client/src/components/team.jsx b/client/src/components/team.jsx index 749aebac..fa44db67 100644 --- a/client/src/components/team.jsx +++ b/client/src/components/team.jsx @@ -8,11 +8,9 @@ const { stringSort } = require('./../utils'); const SpawnButton = require('./spawn.button'); const { ConstructAvatar } = require('./construct'); -const idSort = stringSort('id'); - const addState = connect( function receiveState(state) { - const { ws, constructs, team } = state; + const { ws, constructs, teamSelect } = state; function sendConstructSpawn(name) { return ws.sendMtxConstructSpawn(name); @@ -20,27 +18,26 @@ const addState = connect( return { constructs, - team, + teamSelect, sendConstructSpawn, }; }, - function receiveDispatch(dispatch) { function setTeam(constructIds) { - localStorage.setItem('team', JSON.stringify(constructIds)); - dispatch(actions.setTeam(constructIds)); + dispatch(actions.setTeamSelect(constructIds)); } return { setTeam, }; } + ); function Team(args) { const { constructs, - team, + teamSelect, setTeam, sendConstructSpawn, } = args; @@ -51,27 +48,25 @@ function Team(args) { // so much for dumb components function selectConstruct(id) { // remove - const i = team.findIndex(sid => sid === id); + const i = teamSelect.findIndex(sid => sid === id); if (i > -1) { - team[i] = null; - return setTeam(team); + teamSelect[i] = null; + return setTeam(teamSelect); } // window insert - const insert = team.findIndex(j => j === null); + const insert = teamSelect.findIndex(j => j === null); if (insert === -1) return setTeam([id, null, null]); - team[insert] = id; - return setTeam(team); + teamSelect[insert] = id; + return setTeam(teamSelect); } const constructPanels = constructs.map(construct => { - const colour = team.indexOf(construct.id); + const colour = teamSelect.indexOf(construct.id); const selected = colour > -1; const borderColour = selected ? COLOURS[colour] : '#000000'; - - // return (
{ - return knex.schema.createTable('constructs', table => { + await knex.schema.createTable('constructs', table => { table.uuid('id').primary(); table.timestamps(true, true); table.uuid('account').notNullable() table.foreign('account') - .references('id') - .inTable('accounts') - .onDelete('CASCADE'); + .references('id') + .inTable('accounts') + .onDelete('CASCADE'); table.binary('data').notNullable(); table.boolean('team') - .notNullable() - .defaultTo(false); + .notNullable() + .defaultTo(false); }); + + await knex.raw(team_size_trigger); + + return true; }; -exports.down = async () => {}; \ No newline at end of file +exports.down = async () => {}; diff --git a/server/src/account.rs b/server/src/account.rs index a42a3974..cb1f74b9 100644 --- a/server/src/account.rs +++ b/server/src/account.rs @@ -175,12 +175,12 @@ pub fn debit(tx: &mut Transaction, id: Uuid, debit: i64) -> Result Result Result) -> Result, Error> { +// there is a trigger constraint on the table that enforces +// exactly 3 constructs in a team +pub fn set_team(tx: &mut Transaction, account: &Account, ids: Vec) -> Result, Error> { let query = " UPDATE constructs - SET team = false + SET team = + CASE + WHEN id = ANY($2) THEN true + ELSE false + END WHERE account = $1; "; - let updated = tx + let _updated = tx .execute(query, &[&account.id, &ids])?; - if updated > 3 { - warn!("team members >3 account={:?} count={:?}", account, updated); - } - - let query = " - UPDATE constructs - SET team = true - WHERE account = $1 - AND id in $2 - RETURNING data; - "; - - let updated = tx - .execute(query, &[&account.id, &ids])?; - - if updated != 3 { - return Err(format_err!("could not create team of 3 account={:?} updated={:?}", account, updated)); - } - account_team(tx, account) } diff --git a/server/src/rpc.rs b/server/src/rpc.rs index 286e0dbe..898e53fb 100644 --- a/server/src/rpc.rs +++ b/server/src/rpc.rs @@ -6,6 +6,7 @@ use uuid::Uuid; use failure::Error; use failure::err_msg; +use account; use pg::{Db}; use construct::{Construct}; use game::{Game, game_state, game_skill, game_ready}; @@ -54,6 +55,7 @@ enum RpcRequest { AccountState {}, AccountShop {}, AccountConstructs {}, + AccountSetTeam { ids: Vec }, InstancePvp {}, InstancePractice {}, @@ -100,11 +102,12 @@ pub fn receive(data: Vec, db: &Db, begin: Instant, account: &Option RpcRequest::AccountConstructs {} => Ok(RpcMessage::AccountConstructs(account_constructs(&mut tx, &account)?)), + RpcRequest::AccountSetTeam { ids } => + Ok(RpcMessage::AccountConstructs(account::set_team(&mut tx, &account, ids)?)), + // RpcRequest::AccountShop {} => // Ok(RpcMessage::AccountShop(mtx::account_shop(&mut tx, &account)?)), - - // RpcRequest::ConstructDelete" => handle_construct_delete(data, &mut tx, account), RpcRequest::GameState { id } => diff --git a/server/src/warden.rs b/server/src/warden.rs index 38430a54..c37cf024 100644 --- a/server/src/warden.rs +++ b/server/src/warden.rs @@ -83,6 +83,8 @@ impl Warden { let db = self.pool.get()?; let tx = db.transaction()?; + info!("received pair={:?}", pair); + Ok(()) }