diff --git a/rust/cli_player/src/main.rs b/rust/cli_player/src/main.rs index 9e76740..7f44c61 100644 --- a/rust/cli_player/src/main.rs +++ b/rust/cli_player/src/main.rs @@ -1,5 +1,6 @@ use std::error::Error; use std::io; +use std::io::ErrorKind; use crossterm::event::DisableMouseCapture; use crossterm::event::EnableMouseCapture; @@ -22,7 +23,10 @@ async fn run_app(terminal: &mut Terminal) -> Result<(), Box( if let Event::Key(key) = event::read()? { match key.code { + // Quit app KeyCode::Char('q') => return Ok(ConfigureGameRulesResult::Canceled), - KeyCode::Up => cursor_pos -= 1, - KeyCode::Down => cursor_pos += 1, + + // Navigate between fields + KeyCode::Up | KeyCode::Left => cursor_pos -= 1, + KeyCode::Down | KeyCode::Right => cursor_pos += 1, + + // Submit results + KeyCode::Enter => { + if model.curr_field == EditingField::Cancel { + return Ok(ConfigureGameRulesResult::Canceled); + } + + if model.curr_field == EditingField::OK && model.rules.is_valid() { + return Ok(ConfigureGameRulesResult::Ok(model.rules)); + } + } + + KeyCode::Char(' ') => { + if model.curr_field == EditingField::BoatsCanTouch { + model.rules.boats_can_touch = !model.rules.boats_can_touch; + } + + if model.curr_field == EditingField::PlayerContinueOnHit { + model.rules.player_continue_on_hit = + !model.rules.player_continue_on_hit; + } + } + + KeyCode::Backspace => { + if model.curr_field == EditingField::MapWidth { + model.rules.map_width /= 10; + } + + if model.curr_field == EditingField::MapHeight { + model.rules.map_height /= 10; + } + + if model.curr_field == EditingField::BoatsList + && !model.rules.boats_list().is_empty() + { + model.rules.remove_last_boat(); + } + } + + KeyCode::Char(c) if ('0'..='9').contains(&c) => { + let val = c.to_string().parse::().unwrap_or_default(); + + if model.curr_field == EditingField::MapWidth { + model.rules.map_width *= 10; + model.rules.map_width += val; + } + + if model.curr_field == EditingField::MapHeight { + model.rules.map_height *= 10; + model.rules.map_height += val; + } + + if model.curr_field == EditingField::BoatsList { + model.rules.add_boat(val); + } + } + _ => {} } } diff --git a/rust/cli_player/src/ui_widgets/text_editor_widget.rs b/rust/cli_player/src/ui_widgets/text_editor_widget.rs index bfb2089..6759f11 100644 --- a/rust/cli_player/src/ui_widgets/text_editor_widget.rs +++ b/rust/cli_player/src/ui_widgets/text_editor_widget.rs @@ -1,9 +1,12 @@ use std::fmt::Display; + use tui::buffer::Buffer; use tui::layout::Rect; use tui::style::{Color, Style}; +use tui::text::*; use tui::widgets::{Block, Borders, Paragraph, Widget}; +#[derive(Eq, PartialEq)] pub enum InputMode { Normal, Editing, @@ -30,16 +33,26 @@ impl TextEditorWidget { impl Widget for TextEditorWidget { fn render(self, area: Rect, buf: &mut Buffer) { - let input = Paragraph::new(self.value.as_ref()) - .style(match &self.input_mode { + let span = Span::styled( + self.value.to_string(), + match &self.input_mode { InputMode::Normal => Style::default(), InputMode::Editing => Style::default().fg(Color::Yellow), - }) - .block( - Block::default() - .borders(Borders::ALL) - .title(self.label.as_ref()), - ); + }, + ); + + let mut spans = vec![span]; + + if self.input_mode == InputMode::Editing { + spans.push(Span::styled(" ", Style::default().bg(Color::Yellow))) + } + + let text = Text::from(Spans::from(spans)); + let input = Paragraph::new(text).block( + Block::default() + .borders(Borders::ALL) + .title(self.label.as_ref()), + ); input.render(area, buf); } diff --git a/rust/sea_battle_backend/src/data/game_rules.rs b/rust/sea_battle_backend/src/data/game_rules.rs index a05a6e0..2c05615 100644 --- a/rust/sea_battle_backend/src/data/game_rules.rs +++ b/rust/sea_battle_backend/src/data/game_rules.rs @@ -61,6 +61,10 @@ impl GameRules { /// Get the list of boats for this configuration pub fn boats_list(&self) -> Vec { + if self.boats_str.is_empty() { + return vec![]; + } + self.boats_str .split(',') .map(|s| s.parse::().unwrap_or_default()) @@ -78,7 +82,7 @@ impl GameRules { 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]); + self.set_boats_list(&list); } /// Check game rules errors @@ -109,6 +113,11 @@ impl GameRules { errors } + + /// Check out whether these game rules are valid or not + pub fn is_valid(&self) -> bool { + return self.get_errors().is_empty(); + } } #[cfg(test)]