log bad commands

This commit is contained in:
Ilion Beyst 2022-09-15 21:59:03 +02:00
parent ecd378f0d9
commit 36c16aa8c7
3 changed files with 52 additions and 46 deletions

View file

@ -13,6 +13,12 @@ pub enum MatchLogMessage {
GameState(State), GameState(State),
#[serde(rename = "stderr")] #[serde(rename = "stderr")]
StdErr(StdErrMessage), StdErr(StdErrMessage),
#[serde(rename = "bad_command")]
BadCommand {
player_id: u32,
command: String,
error: String,
},
} }
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]

View file

@ -12,7 +12,7 @@ use std::convert::TryInto;
pub use planetwars_rules::config::{Config, Map}; pub use planetwars_rules::config::{Config, Map};
use planetwars_rules::protocol::{self as proto, PlayerAction}; use planetwars_rules::protocol as proto;
use planetwars_rules::serializer as pw_serializer; use planetwars_rules::serializer as pw_serializer;
use planetwars_rules::{PlanetWars, PwConfig}; use planetwars_rules::{PlanetWars, PwConfig};
@ -44,12 +44,8 @@ impl PwMatch {
let player_messages = self.prompt_players().await; let player_messages = self.prompt_players().await;
for (player_id, turn) in player_messages { for (player_id, turn) in player_messages {
let res = self.execute_action(player_id, turn); let player_action = self.execute_action(player_id, turn);
if let Some(err) = action_errors(res) { self.log_player_action(player_id, player_action);
let _info_str = serde_json::to_string(&err).unwrap();
// TODO
// println!("player {}: {}", player_id, info_str);
}
} }
self.match_state.step(); self.match_state.step();
@ -88,18 +84,14 @@ impl PwMatch {
.await .await
} }
fn execute_action( fn execute_action(&mut self, player_num: usize, turn: RequestResult<Vec<u8>>) -> PlayerAction {
&mut self, let data = match turn {
player_num: usize, Err(_timeout) => return PlayerAction::Timeout,
turn: RequestResult<Vec<u8>>,
) -> proto::PlayerAction {
let turn = match turn {
Err(_timeout) => return proto::PlayerAction::Timeout,
Ok(data) => data, Ok(data) => data,
}; };
let action: proto::Action = match serde_json::from_slice(&turn) { let action: proto::Action = match serde_json::from_slice(&data) {
Err(err) => return proto::PlayerAction::ParseError(err.to_string()), Err(error) => return PlayerAction::ParseError { data, error },
Ok(action) => action, Ok(action) => action,
}; };
@ -108,15 +100,51 @@ impl PwMatch {
.into_iter() .into_iter()
.map(|command| { .map(|command| {
let res = self.match_state.execute_command(player_num, &command); let res = self.match_state.execute_command(player_num, &command);
proto::PlayerCommand { PlayerCommand {
command, command,
error: res.err(), error: res.err(),
} }
}) })
.collect(); .collect();
proto::PlayerAction::Commands(commands) PlayerAction::Commands(commands)
} }
fn log_player_action(&mut self, player_id: usize, player_action: PlayerAction) {
match player_action {
PlayerAction::ParseError { data, error } => {
// TODO: can this be handled better?
let command =
String::from_utf8(data).unwrap_or_else(|_| "<invalid utf-8>".to_string());
self.match_ctx.log(MatchLogMessage::BadCommand {
player_id: player_id as u32,
command,
error: error.to_string(),
});
}
// TODO: handle other action types
_ => {}
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PlayerCommand {
pub command: proto::Command,
#[serde(skip_serializing_if = "Option::is_none")]
pub error: Option<proto::CommandError>,
}
/// the action a player performed.
// TODO: can we name this better? Is this a "play"?
pub enum PlayerAction {
Timeout,
ParseError {
data: Vec<u8>,
error: serde_json::Error,
},
Commands(Vec<PlayerCommand>),
} }
fn action_errors(action: PlayerAction) -> Option<PlayerAction> { fn action_errors(action: PlayerAction) -> Option<PlayerAction> {

View file

@ -49,31 +49,3 @@ pub enum CommandError {
OriginDoesNotExist, OriginDoesNotExist,
DestinationDoesNotExist, DestinationDoesNotExist,
} }
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PlayerCommand {
pub command: Command,
#[serde(skip_serializing_if = "Option::is_none")]
pub error: Option<CommandError>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
#[serde(tag = "type", content = "value")]
pub enum PlayerAction {
Timeout,
ParseError(String),
Commands(Vec<PlayerCommand>),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
#[serde(tag = "type", content = "content")]
pub enum ServerMessage {
/// Game state in current turn
GameState(State),
/// The action that was performed
PlayerAction(PlayerAction),
/// The game is over, and this is the concluding state.
FinalState(State),
}