Check boats layout before accepting it
This commit is contained in:
		@@ -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);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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)]
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user