Sync scores between players
continuous-integration/drone/push Build is passing Details

main
Clément FRÉVILLE 2 years ago
parent 2fb71a3969
commit 1fc4e10c39

@ -51,6 +51,8 @@ pub enum ServerMessage {
PlayerTurn(usize),
/// Update the current hand of the player
SyncHand(Vec<TileRef>),
/// Update the score of the n-th player.
SyncScore(usize, u32),
/// Informs that a tile has been placed
TilePlaced(Position2dRef, TileRef),
/// Informs that a tile has been removed

@ -6,6 +6,7 @@ use board_shared::deck::RngDeck;
use board_shared::expr::is_valid_guess;
use board_shared::game::Hand;
use board_shared::position::Position2d;
use board_shared::score::calc_score;
use board_shared::tile::Tile;
use futures::channel::mpsc::{UnboundedReceiver, UnboundedSender};
use futures::StreamExt;
@ -189,6 +190,7 @@ impl Room {
.hand
.complete(&mut self.deck)
.ok();
self.on_validated_move(self.active_player, &diff);
self.next_player();
} else {
self.send(
@ -198,6 +200,23 @@ impl Room {
}
}
fn on_validated_move(&mut self, player_id: usize, diff: &[Position2d]) {
let tiles_placed = diff
.iter()
.map(|&pos| {
self.board
.get(pos.x, pos.y)
.expect("A placed tile should not be empty.")
})
.collect::<Vec<Tile>>();
self.players[player_id].score += calc_score(&tiles_placed);
self.broadcast(ServerMessage::SyncScore(
player_id,
self.players[player_id].score,
));
self.validated_board = self.board.clone();
}
fn reset_player_moves(&mut self) {
let diff = self.board.difference(&self.validated_board);
for pos in diff {

@ -7,4 +7,5 @@ pub mod game;
mod lexer;
mod parser;
pub mod position;
pub mod score;
pub mod tile;

@ -0,0 +1,79 @@
use crate::tile::{Operator, Tile};
/// Calculate the score for a given list of tiles.
pub fn calc_score(tiles: &[Tile]) -> u32 {
tiles
.split(|tile| matches!(tile, Tile::Equals))
.map(calc_expression_score)
.sum()
}
fn calc_expression_score(tiles: &[Tile]) -> u32 {
let mut digit_score = 0u32;
let mut multiplier = 1u32;
for token in tiles {
match token {
Tile::Digit(_) => digit_score += 1,
Tile::Operator(op) => {
match op {
Operator::Add | Operator::Subtract => multiplier = 2,
Operator::Multiply => multiplier = 3,
Operator::Divide => digit_score += 10,
};
}
_ => unreachable!(),
}
}
digit_score * multiplier
}
#[cfg(test)]
mod tests {
use crate::tile::Digit;
use super::*;
#[test]
fn only_digits() {
assert_eq!(
calc_score(&[
Tile::Digit(Digit::new(7)),
Tile::Digit(Digit::new(8)),
Tile::Equals,
Tile::Digit(Digit::new(9)),
Tile::Digit(Digit::new(4)),
]),
4
);
}
#[test]
fn calc_individually() {
assert_eq!(
calc_score(&[
Tile::Digit(Digit::new(4)),
Tile::Operator(Operator::Add),
Tile::Digit(Digit::new(5)),
Tile::Equals,
Tile::Digit(Digit::new(3)),
Tile::Operator(Operator::Multiply),
Tile::Digit(Digit::new(3)),
]),
10
);
}
#[test]
fn diviser_add_to_original_sum() {
assert_eq!(
calc_score(&[
Tile::Digit(Digit::new(8)),
Tile::Operator(Operator::Divide),
Tile::Digit(Digit::new(4)),
Tile::Equals,
Tile::Digit(Digit::new(2)),
]),
13
);
}
}
Loading…
Cancel
Save