Improve game rules configuration screen
This commit is contained in:
parent
c9f643e224
commit
17a4edf417
@ -1,3 +1,6 @@
|
||||
use std::time::Duration;
|
||||
use tui::style::Color;
|
||||
|
||||
pub const TICK_RATE: Duration = Duration::from_millis(250);
|
||||
|
||||
pub const HIGHLIGHT_COLOR: Color = Color::Green;
|
||||
|
@ -14,13 +14,14 @@ use tui::Terminal;
|
||||
|
||||
use cli_player::server::start_server_if_missing;
|
||||
use cli_player::ui_screens::*;
|
||||
use sea_battle_backend::data::GameRules;
|
||||
|
||||
async fn run_app<B: Backend>(terminal: &mut Terminal<B>) -> Result<(), Box<dyn Error>> {
|
||||
// Temporary code
|
||||
let res = select_bot_type::select_bot_type(terminal)?;
|
||||
let res = configure_game_rules::configure_play_rules(GameRules::default(), terminal)?; // select_bot_type::select_bot_type(terminal)?;
|
||||
Err(io::Error::new(
|
||||
ErrorKind::Other,
|
||||
format!("configured rules: {:?}", res),
|
||||
format!("result: {:?}", res),
|
||||
))?;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
extern crate num as num_renamed;
|
||||
|
||||
use std::cmp::max;
|
||||
use std::io;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
@ -64,7 +63,7 @@ pub fn configure_play_rules<B: Backend>(
|
||||
|
||||
// Navigate between fields
|
||||
KeyCode::Up | KeyCode::Left => cursor_pos -= 1,
|
||||
KeyCode::Down | KeyCode::Right => cursor_pos += 1,
|
||||
KeyCode::Down | KeyCode::Right | KeyCode::Tab => cursor_pos += 1,
|
||||
|
||||
// Submit results
|
||||
KeyCode::Enter => {
|
||||
@ -127,9 +126,11 @@ pub fn configure_play_rules<B: Backend>(
|
||||
}
|
||||
|
||||
// Apply new cursor position
|
||||
cursor_pos = max(0, cursor_pos);
|
||||
if let Some(val) = num_renamed::FromPrimitive::from_u64(cursor_pos as u64) {
|
||||
model.curr_field = val;
|
||||
model.curr_field = if cursor_pos < 0 {
|
||||
EditingField::OK
|
||||
} else {
|
||||
num_renamed::FromPrimitive::from_u64(cursor_pos as u64)
|
||||
.unwrap_or(EditingField::MapWidth)
|
||||
}
|
||||
}
|
||||
if last_tick.elapsed() >= TICK_RATE {
|
||||
|
@ -4,14 +4,14 @@ use std::time::{Duration, Instant};
|
||||
use crossterm::event;
|
||||
use crossterm::event::{Event, KeyCode};
|
||||
use tui::backend::Backend;
|
||||
use tui::style::{Color, Modifier, Style};
|
||||
use tui::style::*;
|
||||
use tui::text::*;
|
||||
use tui::widgets::*;
|
||||
use tui::{Frame, Terminal};
|
||||
|
||||
use sea_battle_backend::data::{BotDescription, BotType, PlayConfiguration};
|
||||
|
||||
use crate::constants::TICK_RATE;
|
||||
use crate::constants::{HIGHLIGHT_COLOR, TICK_RATE};
|
||||
use crate::ui_screens::utils::centered_rect_size;
|
||||
use crate::ui_screens::ScreenResult;
|
||||
|
||||
@ -86,7 +86,7 @@ fn ui<B: Backend>(f: &mut Frame<B>, model: &mut SelectPlayModeScreen) {
|
||||
)
|
||||
.highlight_style(
|
||||
Style::default()
|
||||
.fg(Color::Green)
|
||||
.fg(HIGHLIGHT_COLOR)
|
||||
.add_modifier(Modifier::BOLD),
|
||||
)
|
||||
.highlight_symbol(">> ");
|
||||
|
@ -1,14 +1,14 @@
|
||||
use std::io;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
use crate::constants::TICK_RATE;
|
||||
use crate::constants::{HIGHLIGHT_COLOR, TICK_RATE};
|
||||
use crate::ui_screens::utils::centered_rect_size;
|
||||
use crossterm::event;
|
||||
use crossterm::event::{Event, KeyCode};
|
||||
use tui::backend::Backend;
|
||||
use tui::style::{Color, Modifier, Style};
|
||||
use tui::style::*;
|
||||
use tui::text::Text;
|
||||
use tui::widgets::{Block, Borders, List, ListItem, ListState};
|
||||
use tui::widgets::*;
|
||||
use tui::{Frame, Terminal};
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Copy, Clone, Default)]
|
||||
@ -95,7 +95,7 @@ fn ui<B: Backend>(f: &mut Frame<B>, model: &mut SelectPlayModeScreen) {
|
||||
)
|
||||
.highlight_style(
|
||||
Style::default()
|
||||
.fg(Color::Green)
|
||||
.fg(HIGHLIGHT_COLOR)
|
||||
.add_modifier(Modifier::BOLD),
|
||||
)
|
||||
.highlight_symbol(">> ");
|
||||
|
@ -1,5 +1,6 @@
|
||||
use std::fmt::Display;
|
||||
|
||||
use crate::constants::HIGHLIGHT_COLOR;
|
||||
use tui::buffer::Buffer;
|
||||
use tui::layout::Rect;
|
||||
use tui::style::{Color, Style};
|
||||
@ -37,7 +38,7 @@ impl Widget for ButtonWidget {
|
||||
let input = Paragraph::new(label.as_ref()).style(match (self.disabled, self.is_hovered) {
|
||||
(true, _) => Style::default(),
|
||||
(_, false) => Style::default().bg(Color::DarkGray),
|
||||
(_, true) => Style::default().fg(Color::White).bg(Color::Yellow),
|
||||
(_, true) => Style::default().fg(Color::White).bg(HIGHLIGHT_COLOR),
|
||||
});
|
||||
|
||||
input.render(area, buf);
|
||||
|
@ -1,7 +1,8 @@
|
||||
use crate::constants::HIGHLIGHT_COLOR;
|
||||
use std::fmt::Display;
|
||||
use tui::buffer::Buffer;
|
||||
use tui::layout::Rect;
|
||||
use tui::style::{Color, Style};
|
||||
use tui::style::*;
|
||||
use tui::widgets::*;
|
||||
|
||||
pub struct CheckboxWidget {
|
||||
@ -48,7 +49,7 @@ impl Widget for CheckboxWidget {
|
||||
|
||||
let input = Paragraph::new(paragraph.as_ref()).style(match &self.is_editing {
|
||||
false => Style::default(),
|
||||
true => Style::default().fg(Color::Yellow),
|
||||
true => Style::default().fg(HIGHLIGHT_COLOR),
|
||||
});
|
||||
|
||||
input.render(area, buf);
|
||||
|
@ -1,8 +1,9 @@
|
||||
use std::fmt::Display;
|
||||
|
||||
use crate::constants::HIGHLIGHT_COLOR;
|
||||
use tui::buffer::Buffer;
|
||||
use tui::layout::Rect;
|
||||
use tui::style::{Color, Style};
|
||||
use tui::style::*;
|
||||
use tui::text::*;
|
||||
use tui::widgets::{Block, Borders, Paragraph, Widget};
|
||||
|
||||
@ -37,20 +38,25 @@ impl Widget for TextEditorWidget {
|
||||
self.value.to_string(),
|
||||
match &self.input_mode {
|
||||
InputMode::Normal => Style::default(),
|
||||
InputMode::Editing => Style::default().fg(Color::Yellow),
|
||||
InputMode::Editing => Style::default().fg(HIGHLIGHT_COLOR),
|
||||
},
|
||||
);
|
||||
|
||||
let mut spans = vec![span];
|
||||
|
||||
// Add cursor if field is highlighted
|
||||
if self.input_mode == InputMode::Editing {
|
||||
spans.push(Span::styled(" ", Style::default().bg(Color::Yellow)))
|
||||
spans.push(Span::styled(" ", Style::default().bg(HIGHLIGHT_COLOR)))
|
||||
}
|
||||
|
||||
let text = Text::from(Spans::from(spans));
|
||||
let input = Paragraph::new(text).block(
|
||||
Block::default()
|
||||
.borders(Borders::ALL)
|
||||
.border_style(match self.input_mode {
|
||||
InputMode::Normal => Style::default(),
|
||||
InputMode::Editing => Style::default().fg(HIGHLIGHT_COLOR),
|
||||
})
|
||||
.title(self.label.as_ref()),
|
||||
);
|
||||
|
||||
|
@ -91,18 +91,28 @@ impl GameRules {
|
||||
|
||||
let mut errors = vec![];
|
||||
|
||||
if self.map_width < config.min_map_width || self.map_width > config.max_map_width {
|
||||
errors.push("Map width is outside bounds!");
|
||||
if self.map_width < config.min_map_width {
|
||||
errors.push("Map width is too small!");
|
||||
}
|
||||
|
||||
if self.map_height < config.min_map_height || self.map_height > config.max_map_height {
|
||||
errors.push("Map height is outside bounds!");
|
||||
if self.map_width > config.max_map_width {
|
||||
errors.push("Map width is too big!");
|
||||
}
|
||||
|
||||
if self.boats_list().len() < config.min_boats_number
|
||||
|| self.boats_list().len() > config.max_boats_number
|
||||
{
|
||||
errors.push("The number of boats is invalid!");
|
||||
if self.map_height < config.min_map_height {
|
||||
errors.push("Map height is too small!");
|
||||
}
|
||||
|
||||
if self.map_height > config.max_map_height {
|
||||
errors.push("Map height is too big!");
|
||||
}
|
||||
|
||||
if self.boats_list().len() < config.min_boats_number {
|
||||
errors.push("There is not enough boats!");
|
||||
}
|
||||
|
||||
if self.boats_list().len() > config.max_boats_number {
|
||||
errors.push("There are too many boats!");
|
||||
}
|
||||
|
||||
for boat in self.boats_list() {
|
||||
|
Loading…
Reference in New Issue
Block a user