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