Check boats layout before accepting it

This commit is contained in:
Pierre HUBERT 2022-09-15 19:56:11 +02:00
parent d3d5feda4f
commit 8fac31e97b
5 changed files with 78 additions and 11 deletions

View File

@ -9,7 +9,7 @@ use crate::human_player_ws::{ClientMessage, ServerMessage};
#[derive(Debug, Eq, PartialEq)] #[derive(Debug, Eq, PartialEq)]
pub enum ClientEndResult { pub enum ClientEndResult {
Finished, Finished,
InvalidLayout, InvalidBoatsLayout,
} }
pub async fn run_client( pub async fn run_client(
@ -117,7 +117,7 @@ pub async fn run_client(
} }
ServerMessage::RejectedBoatsLayout { errors } => { ServerMessage::RejectedBoatsLayout { errors } => {
log::warn!("Rejected boat layout: {:?}", errors); log::warn!("Rejected boat layout: {:?}", errors);
return Ok(ClientEndResult::InvalidLayout); return Ok(ClientEndResult::InvalidBoatsLayout);
} }
} }
} }

View File

@ -216,7 +216,8 @@ impl BoatsLayout {
true true
} }
pub fn errors(&self, rules: &GameRules) -> Vec<&str> { /// Check if this boats layout is valid or not
pub fn errors(&self, rules: &GameRules) -> Vec<&'static str> {
let mut errors = vec![]; let mut errors = vec![];
// Check the number of boats // Check the number of boats
@ -272,12 +273,6 @@ impl BoatsLayout {
pub fn number_of_boats(&self) -> usize { pub fn number_of_boats(&self) -> usize {
self.0.len() self.0.len()
} }
/// Check for layout invalid configuration
pub fn layouts_errors(&self, _rules: &GameRules) -> Vec<&'static str> {
//TODO : implement
vec![]
}
} }
#[cfg(test)] #[cfg(test)]

View File

@ -44,6 +44,21 @@ impl GameRules {
.collect() .collect()
} }
/// Remove last boat
pub fn pop_boat(&mut self) -> usize {
let list = self.boats_list();
self.set_boats_list(&list[0..list.len() - 1]);
*list.last().unwrap()
}
/// Add a boat to the list of boats
pub fn add_boat(&mut self, len: usize) {
let mut list = self.boats_list();
list.push(len);
self.set_boats_list(&list[0..list.len() - 1]);
}
/// Check game rules errors
pub fn get_errors(&self) -> Vec<&str> { pub fn get_errors(&self) -> Vec<&str> {
let config = PlayConfiguration::default(); let config = PlayConfiguration::default();

View File

@ -208,9 +208,9 @@ impl Handler<SetBoatsLayout> for Game {
let player_index = self.player_id_by_uuid(msg.0); let player_index = self.player_id_by_uuid(msg.0);
let errors = msg.1.layouts_errors(&self.rules); let errors = msg.1.errors(&self.rules);
if !errors.is_empty() { if !errors.is_empty() {
log::error!("Got invalid boats layou!"); log::error!("Got invalid boats layout!");
self.players[player_index].rejected_boats_layout(errors); self.players[player_index].rejected_boats_layout(errors);
self.players[player_index].query_boats_layout(&self.rules); self.players[player_index].query_boats_layout(&self.rules);
return; return;

View File

@ -95,3 +95,60 @@ async fn full_game_no_touching_boats() {
}) })
.await; .await;
} }
#[tokio::test]
async fn invalid_boats_layout_number_of_boats() {
let _ = env_logger::builder().is_test(true).try_init();
let local_set = task::LocalSet::new();
local_set
.run_until(async move {
let mut rules = GameRules::random_players_rules();
rules.boats_can_touch = false;
task::spawn_local(start_server(Args::for_test(
TestPort::FullGameTouchingBoats,
)));
wait_for_port(TestPort::FullGameTouchingBoats.port()).await;
let mut rules_modified = rules.clone();
rules_modified.pop_boat();
let layout = BoatsLayout::gen_random_for_rules(&rules_modified).unwrap();
let res =
bot_client::run_client(&TestPort::FullGameTouchingBoats.as_url(), &rules, layout)
.await
.unwrap();
assert_eq!(res, ClientEndResult::InvalidBoatsLayout);
})
.await;
}
#[tokio::test]
async fn invalid_boats_layout_len_of_a_boat() {
let _ = env_logger::builder().is_test(true).try_init();
let local_set = task::LocalSet::new();
local_set
.run_until(async move {
let mut rules = GameRules::random_players_rules();
rules.boats_can_touch = false;
task::spawn_local(start_server(Args::for_test(
TestPort::FullGameTouchingBoats,
)));
wait_for_port(TestPort::FullGameTouchingBoats.port()).await;
let mut rules_modified = rules.clone();
let previous = rules_modified.pop_boat();
rules_modified.add_boat(previous - 1);
let layout = BoatsLayout::gen_random_for_rules(&rules_modified).unwrap();
let res =
bot_client::run_client(&TestPort::FullGameTouchingBoats.as_url(), &rules, layout)
.await
.unwrap();
assert_eq!(res, ClientEndResult::InvalidBoatsLayout);
})
.await;
}