diff --git a/client/assets/styles/player.less b/client/assets/styles/player.less
new file mode 100644
index 00000000..3dd302b9
--- /dev/null
+++ b/client/assets/styles/player.less
@@ -0,0 +1,37 @@
+@import 'colours.less';
+
+.player-box {
+ display: grid;
+
+ grid-template-areas:
+ "score"
+ "img"
+ "ctrl";
+
+ &.top {
+ grid-template-areas:
+ "ctrl"
+ "img"
+ "score";
+
+ .img {
+ display: flex;
+ flex-flow: column;
+ justify-content: flex-end;
+ }
+ }
+
+ grid-template-rows: min-content 1fr min-content;
+
+ .score {
+ grid-area: score;
+ }
+
+ .img {
+ grid-area: img;
+ }
+
+ .ctrl {
+ grid-area: ctrl;
+ }
+}
diff --git a/client/index.js b/client/index.js
index 8c76e1ff..d25854c0 100644
--- a/client/index.js
+++ b/client/index.js
@@ -7,6 +7,7 @@ require('./assets/styles/controls.less');
require('./assets/styles/instance.less');
require('./assets/styles/vbox.less');
require('./assets/styles/game.less');
+require('./assets/styles/player.less');
require('./assets/styles/styles.mobile.css');
require('./assets/styles/instance.mobile.css');
diff --git a/client/src/components/game.ctrl.jsx b/client/src/components/game.ctrl.jsx
index 4bf517d6..9fd5b07a 100644
--- a/client/src/components/game.ctrl.jsx
+++ b/client/src/components/game.ctrl.jsx
@@ -3,8 +3,7 @@ const { connect } = require('preact-redux');
const actions = require('../actions');
-// dunno if this is a good idea
-// bashing together instance and game to save having two panels
+const PlayerBox = require('./player.box');
const addState = connect(
function receiveState(state) {
@@ -44,35 +43,6 @@ const addState = connect(
}
);
-function scoreboard(game, player, isOpponent) {
- const text = game.phase === 'Finished'
- ? player.wins > game.rounds / 2 && 'Winner'
- : '';
-
- const classes =`scoreboard ${player.ready ? 'ready' : ''}`;
-
- const body = isOpponent
- ? (
-
- | {player.name} |
- | {player.wins} / {player.losses} |
- | {player.ready ? 'ready' : ''} |
-
- ) : (
-
- | {player.ready ? 'ready' : ''} |
- | {player.wins} / {player.losses} |
- | {player.name} |
-
- );
-
- return (
-
- );
-}
-
function Controls(args) {
const {
account,
@@ -126,9 +96,9 @@ function Controls(args) {
);
diff --git a/client/src/components/instance.ctrl.jsx b/client/src/components/instance.ctrl.jsx
index a431f1d4..47324fa9 100644
--- a/client/src/components/instance.ctrl.jsx
+++ b/client/src/components/instance.ctrl.jsx
@@ -1,6 +1,10 @@
const preact = require('preact');
const { connect } = require('preact-redux');
+const actions = require('../actions');
+
+const PlayerBox = require('./player.box');
+
const addState = connect(
function receiveState(state) {
const {
@@ -23,42 +27,23 @@ const addState = connect(
animating,
};
},
+ function receiveDispatch(dispatch) {
+ function leave() {
+ dispatch(actions.setNav('play'));
+ dispatch(actions.setGame(null));
+ dispatch(actions.setInstance(null));
+ }
+
+ return { leave };
+ }
);
-function scoreboard(instance, player, isOpponent) {
- const text = instance.phase === 'Finished'
- ? player.wins > instance.rounds / 2 && 'Winner'
- : '';
-
- const classes =`scoreboard ${player.ready ? 'ready' : ''}`;
-
- const body = isOpponent
- ? (
-
- | {player.name} |
- | {player.wins} / {player.losses} |
- | {player.ready ? 'ready' : ''} |
-
- ) : (
-
- | {player.ready ? 'ready' : ''} |
- | {player.wins} / {player.losses} |
- | {player.name} |
-
- );
-
- return (
-
- );
-}
-
function Controls(args) {
const {
account,
instance,
sendReady,
+ leave,
} = args;
if (!instance) return false;
@@ -96,9 +81,9 @@ function Controls(args) {
);
diff --git a/client/src/components/player.box.jsx b/client/src/components/player.box.jsx
new file mode 100644
index 00000000..4b626171
--- /dev/null
+++ b/client/src/components/player.box.jsx
@@ -0,0 +1,47 @@
+const preact = require('preact');
+
+function Scoreboard(args) {
+ const {
+ isPlayer,
+ ready,
+ player,
+
+ leave,
+ } = args;
+
+ let scoreText = () => {
+ if (player.score === 'Zero') return '▫▫▫▫';
+ if (player.score === 'One') return '■▫▫▫';
+ if (player.score === 'Two') return '■■▫▫';
+ if (player.score === 'Three') return '■■■▫';
+ if (player.score === 'Adv') return '■■■+';
+ if (player.score === 'Win') return '■■■■';
+ return '';
+ };
+
+ if (!isPlayer) {
+ return (
+
+ );
+ }
+
+ return (
+
+
{scoreText()}
+
+
+ {leave ? : null}
+
+
+ );
+}
+
+module.exports = Scoreboard;
diff --git a/server/src/instance.rs b/server/src/instance.rs
index 6feeb8f1..3061cb10 100644
--- a/server/src/instance.rs
+++ b/server/src/instance.rs
@@ -14,7 +14,7 @@ use chrono::Duration;
use account::Account;
use account;
use events::{EventsTx, Event};
-use player::{Player, player_create};
+use player::{Player, Score, player_create};
use construct::{Construct, construct_get};
use mob::{bot_player, instance_mobs};
use game::{Game, Phase, game_get, game_write};
@@ -318,14 +318,14 @@ impl Instance {
// tennis
for player in self.players.iter() {
- if player.wins >= 4 && player.wins >= player.losses + 2 {
+ if player.score == Score::Win {
self.winner = Some(player.id);
return true;
}
}
// both players afk
- if self.players.iter().all(|p| p.wins == 0) {
+ if self.players.iter().all(|p| p.score == Score::Zero) {
return true;
}
@@ -403,12 +403,25 @@ impl Instance {
None => return Ok(self.finish()),
};
- for player in game.players.iter() {
- let mut player = self.account_player(player.id)?;
- match player.id == winner_id {
- true => player.add_win(),
- false => player.add_loss(),
- };
+ {
+ let loser = self.players.iter()
+ .find(|p| p.id != winner_id)
+ .map(|p| p.score)
+ .unwrap();
+
+ let winner = self.players.iter_mut()
+ .find(|p| p.id == winner_id)
+ .unwrap();
+
+ winner.score = winner.score.add_win(&loser);
+ }
+
+ {
+ let loser = self.players.iter_mut()
+ .find(|p| p.id != winner_id)
+ .unwrap();
+
+ loser.score = loser.score.add_loss();
}
if self.all_games_finished() {
diff --git a/server/src/player.rs b/server/src/player.rs
index 0c123143..8c42743d 100644
--- a/server/src/player.rs
+++ b/server/src/player.rs
@@ -14,6 +14,43 @@ use effect::{Effect};
const DISCARD_COST: u16 = 2;
+#[derive(Debug,Copy,Clone,Serialize,Deserialize,Eq,PartialEq)]
+pub enum Score {
+ Zero,
+ One,
+ Two,
+ Three,
+ Adv,
+
+ Win,
+ Lose,
+}
+
+impl Score {
+ pub fn add_win(self, opp: &Score) -> Score {
+ match self {
+ Score::Zero => Score::One,
+ Score::One => Score::Two,
+ Score::Two => Score::Three,
+ Score::Three => match opp {
+ Score::Adv => Score::Three,
+ Score::Three => Score::Adv,
+ _ => Score::Win,
+ }
+ Score::Adv => Score::Win,
+ _ => panic!("faulty score increment {:?}", self),
+ }
+ }
+
+ pub fn add_loss(self) -> Score {
+ match self {
+ Score::Adv => Score::Three,
+ _ => self,
+ }
+ }
+
+}
+
#[derive(Debug,Clone,Serialize,Deserialize)]
pub struct Player {
pub id: Uuid,
@@ -23,8 +60,7 @@ pub struct Player {
pub bot: bool,
pub ready: bool,
pub warnings: u8,
- pub wins: u8,
- pub losses: u8,
+ pub score: Score,
}
impl Player {
@@ -33,12 +69,11 @@ impl Player {
id: account,
name: name.clone(),
vbox: Vbox::new(),
- wins: 0,
- losses: 0,
constructs,
bot: false,
ready: false,
warnings: 0,
+ score: Score::Zero,
}
}
@@ -64,21 +99,6 @@ impl Player {
self
}
- pub fn add_win(&mut self) -> &mut Player {
- self.wins += 1;
- let win_bonus = 12 + 6 * (self.wins + self.losses);
- self.vbox.balance_add(win_bonus.into());
- self
- }
-
- pub fn add_loss(&mut self) -> &mut Player {
- self.losses += 1;
- let loss_bonus = 12 + 6 * (self.wins + self.losses);
- self.vbox.balance_add(loss_bonus.into());
- self
- }
-
-
pub fn construct_get(&mut self, id: Uuid) -> Result<&mut Construct, Error> {
self.constructs.iter_mut().find(|c| c.id == id).ok_or(err_msg("construct not found"))
}
@@ -336,4 +356,32 @@ mod tests {
assert!(player.constructs.iter().all(|c| c.skills.len() >= 1));
}
+
+ #[test]
+ fn player_score_test() {
+ let player_account = Uuid::new_v4();
+ let constructs = instance_mobs(player_account);
+ let mut player = Player::new(player_account, &"test".to_string(), constructs).set_bot(true);
+
+ player.score = player.score.add_win(&Score::Zero);
+ player.score = player.score.add_win(&Score::Zero);
+ player.score = player.score.add_win(&Score::Zero);
+ assert_eq!(player.score, Score::Three); // 40 / 0
+
+ player.score = player.score.add_loss(); // adv -> deuce
+ assert_eq!(player.score, Score::Three);
+
+ player.score = player.score.add_loss(); // adv -> deuce
+ assert_eq!(player.score, Score::Three);
+
+ player.score = player.score.add_win(&Score::Adv); // opp adv -> stays deuce
+ assert_eq!(player.score, Score::Three);
+
+ player.score = player.score.add_win(&Score::Three);
+ assert_eq!(player.score, Score::Adv);
+
+ player.score = player.score.add_win(&Score::Three);
+ assert_eq!(player.score, Score::Win);
+ }
+
}
\ No newline at end of file
diff --git a/server/src/skill.rs b/server/src/skill.rs
index c587a465..d71ac47e 100644
--- a/server/src/skill.rs
+++ b/server/src/skill.rs
@@ -2113,8 +2113,8 @@ mod tests {
.learn(Skill::HealPlus);
purge(&mut x, &mut y, vec![], Skill::Purge);
- // 2 turns at lvl 1
- assert!(y.effects.iter().any(|e| e.effect == Effect::Purge && e.duration == 2));
+ // current turn + 2 turns at lvl 1
+ assert!(y.effects.iter().any(|e| e.effect == Effect::Purge && e.duration == 3));
assert!(y.disabled(Skill::Heal).is_some());
}
}