Move ZoomLevel into skirmish_states

Introduce Structure and Unit traits with enum wrappers.
Replace old zoom helper with ZoomLevel methods.
Update imports, BoardState, CellWidget, and CLI to use new locations.
This commit is contained in:
2026-04-20 12:17:56 +02:00
parent a04264c08b
commit 06a439ff88
20 changed files with 242 additions and 140 deletions
-2
View File
@@ -1,9 +1,7 @@
pub mod block_title; pub mod block_title;
mod cells_area; mod cells_area;
mod main_menu_option; mod main_menu_option;
mod zoom_level;
pub use block_title::{block_single_title_helper, block_title_helper}; pub use block_title::{block_single_title_helper, block_title_helper};
pub use cells_area::cells_area_helper; pub use cells_area::cells_area_helper;
pub use main_menu_option::main_menu_option_helper; pub use main_menu_option::main_menu_option_helper;
pub use zoom_level::{CellSizes, cell_size_helper};
-17
View File
@@ -1,17 +0,0 @@
use crate::app::states::ZoomLevel;
pub enum CellSizes {
Width,
Height,
}
pub fn cell_size_helper(cell_size: CellSizes, zoom_level: ZoomLevel) -> usize {
match (cell_size, zoom_level) {
(CellSizes::Width, ZoomLevel::ZoomedIn) => 13,
(CellSizes::Width, ZoomLevel::Default) => 9,
(CellSizes::Width, ZoomLevel::ZoomedOut) => 5,
(CellSizes::Height, ZoomLevel::ZoomedIn) => 7,
(CellSizes::Height, ZoomLevel::Default) => 5,
(CellSizes::Height, ZoomLevel::ZoomedOut) => 3,
}
}
+1 -4
View File
@@ -1,10 +1,7 @@
use crate::app::{ use crate::app::{
App, App,
keybindings::{Action, common_keybindings, event_to_action}, keybindings::{Action, common_keybindings, event_to_action},
states::{ states::skirmish_states::{BoardState, MoveFocusedCell, ZoomLevel},
ZoomLevel,
skirmish_states::{BoardState, MoveFocusedCell},
},
}; };
use ratatui::crossterm::event::KeyEvent; use ratatui::crossterm::event::KeyEvent;
+1 -1
View File
@@ -9,5 +9,5 @@ pub use main_menu::MainMenuState;
pub use perk_decks::{PerkDecks, PerkDecksState}; pub use perk_decks::{PerkDecks, PerkDecksState};
pub use settings::SettingsState; pub use settings::SettingsState;
pub use skills_config::SkillsConfigState; pub use skills_config::SkillsConfigState;
pub use skirmish::{CellStructure, GameMode, Players, SkirmishState, Units, ZoomLevel}; pub use skirmish::{GameMode, Players, SkirmishState};
pub use skirmish_states::{FocusedCell, Offset}; pub use skirmish_states::{FocusedCell, Offset};
+1 -24
View File
@@ -1,8 +1,4 @@
use crate::app::states::skirmish_states::{ use crate::app::states::skirmish_states::BoardState;
BoardState,
structures::{BaseBuilding, Stone, Tunnel},
units::MinerUnit,
};
use clap::ValueEnum; use clap::ValueEnum;
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
@@ -18,27 +14,8 @@ pub enum GameMode {
FrontLines, FrontLines,
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, ValueEnum)]
pub enum ZoomLevel {
ZoomedIn,
Default,
ZoomedOut,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Players { pub enum Players {
Player, Player,
Enemy, Enemy,
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CellStructure {
Base(BaseBuilding),
Tunnel(Tunnel),
Stone(Stone),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Units {
Miner(MinerUnit),
}
+13 -13
View File
@@ -1,11 +1,11 @@
use crate::app::{ use crate::app::{
helpers::{CellSizes, cell_size_helper, cells_area_helper}, helpers::cells_area_helper,
states::{ states::{
CellStructure, FocusedCell, Offset, Players, Units, ZoomLevel, FocusedCell, Offset, Players,
skirmish_states::{ skirmish_states::{
MoveFocusedCell, CellSizes, MoveFocusedCell, ZoomLevel,
structures::{BaseBuilding, Stone}, structures::{BaseBuilding, Stone, Structures},
units::MinerUnit, units::{MinerUnit, Units},
}, },
}, },
widgets::CellWidget, widgets::CellWidget,
@@ -36,8 +36,8 @@ impl BoardState {
pub fn new(area: &Rect, map_width: usize, map_height: usize, zoom_level: ZoomLevel) -> Self { pub fn new(area: &Rect, map_width: usize, map_height: usize, zoom_level: ZoomLevel) -> Self {
let cells_area: Rect = cells_area_helper(area); let cells_area: Rect = cells_area_helper(area);
let cell_width: usize = cell_size_helper(CellSizes::Width, zoom_level); let cell_width: usize = zoom_level.get_cell_size(CellSizes::Width);
let cell_height: usize = cell_size_helper(CellSizes::Height, zoom_level); let cell_height: usize = zoom_level.get_cell_size(CellSizes::Height);
let cols: usize = (cells_area.width / cell_width as u16) as usize; let cols: usize = (cells_area.width / cell_width as u16) as usize;
let rows: usize = (cells_area.height / cell_height as u16) as usize; let rows: usize = (cells_area.height / cell_height as u16) as usize;
@@ -67,12 +67,12 @@ impl BoardState {
let player_base: bool = row == player_base_coords.0 && col == player_base_coords.1; let player_base: bool = row == player_base_coords.0 && col == player_base_coords.1;
let enemy_base: bool = row == enemy_base_coords.0 && col == enemy_base_coords.1; let enemy_base: bool = row == enemy_base_coords.0 && col == enemy_base_coords.1;
let structure: CellStructure = if player_base { let structure: Structures = if player_base {
CellStructure::Base(BaseBuilding::new(Players::Player)) Structures::Base(BaseBuilding::new(Players::Player))
} else if enemy_base { } else if enemy_base {
CellStructure::Base(BaseBuilding::new(Players::Enemy)) Structures::Base(BaseBuilding::new(Players::Enemy))
} else { } else {
CellStructure::Stone(Stone::new()) Structures::Stone(Stone::new())
}; };
let unit: Option<Units> = if player_base { let unit: Option<Units> = if player_base {
@@ -227,8 +227,8 @@ impl BoardState {
pub fn change_zoom(&mut self, new_zoom_level: ZoomLevel) { pub fn change_zoom(&mut self, new_zoom_level: ZoomLevel) {
self.zoom_level = new_zoom_level; self.zoom_level = new_zoom_level;
self.cell_width = cell_size_helper(CellSizes::Width, self.zoom_level); self.cell_width = new_zoom_level.get_cell_size(CellSizes::Width);
self.cell_height = cell_size_helper(CellSizes::Height, self.zoom_level); self.cell_height = new_zoom_level.get_cell_size(CellSizes::Height);
self.cols = (self.cells_area.width / self.cell_width as u16) as usize; self.cols = (self.cells_area.width / self.cell_width as u16) as usize;
self.rows = (self.cells_area.height / self.cell_height as u16) as usize; self.rows = (self.cells_area.height / self.cell_height as u16) as usize;
+2
View File
@@ -3,7 +3,9 @@ mod focused_cell;
mod offset; mod offset;
pub mod structures; pub mod structures;
pub mod units; pub mod units;
pub mod zoom_level;
pub use board::BoardState; pub use board::BoardState;
pub use focused_cell::{FocusedCell, MoveFocusedCell}; pub use focused_cell::{FocusedCell, MoveFocusedCell};
pub use offset::Offset; pub use offset::Offset;
pub use zoom_level::{CellSizes, ZoomLevel};
@@ -1,34 +1,50 @@
use crate::app::states::{Players, skirmish_states::structures::Structure};
use ratatui::style::Color; use ratatui::style::Color;
use crate::app::states::Players;
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct BaseBuilding { pub struct BaseBuilding {
durability: u16,
stress: u8,
owner: Players, owner: Players,
level: u8, level: u8,
} }
impl BaseBuilding { impl BaseBuilding {
pub fn new(owner: Players) -> Self { pub fn new(owner: Players) -> Self {
Self { owner, level: b'1' } Self {
} durability: 1500,
stress: 0,
pub fn get_tag(&self) -> char { owner,
'B' level: b'1',
}
pub fn get_color(&self) -> Color {
match self.owner {
Players::Player => Color::LightBlue,
Players::Enemy => Color::LightRed,
} }
} }
pub fn get_owner(&self) -> Players { pub fn get_owner(&self) -> Players {
self.owner self.owner
} }
}
pub fn get_level(&self) -> char { impl Structure for BaseBuilding {
fn get_tag(&self) -> char {
'B'
}
fn get_color(&self) -> Color {
match self.owner {
Players::Player => Color::LightBlue,
Players::Enemy => Color::LightRed,
}
}
fn get_level(&self) -> char {
self.level as char self.level as char
} }
fn get_durability(&self) -> u16 {
self.durability
}
fn get_stress(&self) -> u8 {
self.stress
}
} }
@@ -1,7 +1,11 @@
mod base; mod base;
mod stone; mod stone;
mod structures_enum;
mod structures_trait;
mod tunnel; mod tunnel;
pub use base::BaseBuilding; pub use base::BaseBuilding;
pub use stone::Stone; pub use stone::Stone;
pub use structures_enum::Structures;
pub use structures_trait::Structure;
pub use tunnel::Tunnel; pub use tunnel::Tunnel;
@@ -1,20 +1,39 @@
use crate::app::states::skirmish_states::structures::Structure;
use ratatui::style::Color; use ratatui::style::Color;
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Stone { pub struct Stone {
durability: u16, durability: u16,
stress: u8,
} }
impl Stone { impl Stone {
pub fn new() -> Self { pub fn new() -> Self {
Self { durability: 1000 } Self {
durability: 1000,
stress: 0,
}
}
} }
pub fn get_tag(&self) -> char { impl Structure for Stone {
fn get_tag(&self) -> char {
' ' ' '
} }
pub fn get_color(&self) -> Color { fn get_color(&self) -> Color {
Color::White Color::White
} }
fn get_level(&self) -> char {
' '
}
fn get_durability(&self) -> u16 {
self.durability
}
fn get_stress(&self) -> u8 {
self.stress
}
} }
@@ -0,0 +1,35 @@
use crate::app::states::skirmish_states::structures::{BaseBuilding, Stone, Structure, Tunnel};
use ratatui::style::Color;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Structures {
Base(BaseBuilding),
Tunnel(Tunnel),
Stone(Stone),
}
impl Structures {
pub fn get_color(&self) -> Color {
match self {
Structures::Base(b) => b.get_color(),
Structures::Tunnel(t) => t.get_color(),
Structures::Stone(s) => s.get_color(),
}
}
pub fn get_tag(&self) -> char {
match self {
Structures::Base(b) => b.get_tag(),
Structures::Tunnel(t) => t.get_tag(),
Structures::Stone(s) => s.get_tag(),
}
}
pub fn get_level(&self) -> char {
match self {
Structures::Base(b) => b.get_level(),
Structures::Tunnel(t) => t.get_level(),
Structures::Stone(s) => s.get_level(),
}
}
}
@@ -0,0 +1,9 @@
use ratatui::style::Color;
pub trait Structure {
fn get_tag(&self) -> char;
fn get_color(&self) -> Color;
fn get_level(&self) -> char;
fn get_stress(&self) -> u8;
fn get_durability(&self) -> u16;
}
@@ -1,3 +1,4 @@
use crate::app::states::skirmish_states::structures::Structure;
use ratatui::style::Color; use ratatui::style::Color;
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -19,20 +20,26 @@ impl Tunnel {
lamp: false, lamp: false,
} }
} }
}
pub fn get_tag(&self) -> char { impl Structure for Tunnel {
fn get_tag(&self) -> char {
'T' 'T'
} }
pub fn get_color(&self) -> Color { fn get_color(&self) -> Color {
Color::Gray Color::Gray
} }
pub fn get_durability(&self) -> u16 { fn get_level(&self) -> char {
' '
}
fn get_durability(&self) -> u16 {
self.durability self.durability
} }
pub fn get_stress(&self) -> u8 { fn get_stress(&self) -> u8 {
self.stress self.stress
} }
} }
@@ -1,4 +1,4 @@
use crate::app::states::Players; use crate::app::states::{Players, skirmish_states::units::Unit};
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct MinerUnit { pub struct MinerUnit {
@@ -9,8 +9,14 @@ impl MinerUnit {
pub fn new(owner: Players) -> Self { pub fn new(owner: Players) -> Self {
Self { owner } Self { owner }
} }
}
pub fn get_tag(self) -> char { impl Unit for MinerUnit {
fn get_owner(&self) -> Players {
self.owner
}
fn get_tag(&self) -> char {
'M' 'M'
} }
} }
@@ -1,3 +1,7 @@
mod miner; mod miner;
mod units_enum;
mod units_trait;
pub use miner::MinerUnit; pub use miner::MinerUnit;
pub use units_enum::Units;
pub use units_trait::{OptionalUnit, Unit};
@@ -0,0 +1,20 @@
use crate::app::states::skirmish_states::units::{MinerUnit, OptionalUnit, Unit};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Units {
Miner(MinerUnit),
}
impl Units {
pub fn get_tag(&self) -> char {
match self {
Units::Miner(m) => m.get_tag(),
}
}
}
impl OptionalUnit for Option<Units> {
fn try_get_tag(&self) -> char {
self.map_or(' ', |u| u.get_tag())
}
}
@@ -0,0 +1,10 @@
use crate::app::states::Players;
pub trait Unit {
fn get_owner(&self) -> Players;
fn get_tag(&self) -> char;
}
pub trait OptionalUnit {
fn try_get_tag(&self) -> char;
}
@@ -0,0 +1,50 @@
use clap::ValueEnum;
use ratatui::text::Line;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, ValueEnum)]
pub enum ZoomLevel {
ZoomedIn,
Default,
ZoomedOut,
}
pub enum CellSizes {
Width,
Height,
}
impl ZoomLevel {
pub fn get_cell_size(&self, cell_size: CellSizes) -> usize {
match (cell_size, self) {
(CellSizes::Width, ZoomLevel::ZoomedIn) => 13,
(CellSizes::Width, ZoomLevel::Default) => 9,
(CellSizes::Width, ZoomLevel::ZoomedOut) => 5,
(CellSizes::Height, ZoomLevel::ZoomedIn) => 7,
(CellSizes::Height, ZoomLevel::Default) => 5,
(CellSizes::Height, ZoomLevel::ZoomedOut) => 3,
}
}
pub fn get_cell_text_area(
&self,
tag: char,
structure_level: char,
unit: char,
) -> Vec<Line<'_>> {
match self {
ZoomLevel::ZoomedIn => vec![
Line::from(format!(" {} {} ", structure_level, unit)),
Line::from(format!(" ")),
Line::from(format!(" {} ", tag)),
Line::from(format!(" ")),
Line::from(format!(" ")),
],
ZoomLevel::Default => vec![
Line::from(format!(" {} {} ", structure_level, unit)),
Line::from(format!(" {} ", tag)),
Line::from(format!(" ")),
],
ZoomLevel::ZoomedOut => vec![Line::from(format!(" {} ", tag))],
}
}
}
+20 -55
View File
@@ -1,4 +1,8 @@
use crate::app::states::{CellStructure, Units, ZoomLevel, skirmish_states::structures::Stone}; use crate::app::states::skirmish_states::{
ZoomLevel,
structures::{Stone, Structures},
units::{OptionalUnit, Units},
};
use ratatui::{ use ratatui::{
buffer::Buffer, buffer::Buffer,
layout::{Alignment, Rect}, layout::{Alignment, Rect},
@@ -13,7 +17,7 @@ pub struct CellWidget {
col: usize, col: usize,
selected: bool, selected: bool,
zoom_level: ZoomLevel, zoom_level: ZoomLevel,
structure: CellStructure, structure: Structures,
marked: bool, marked: bool,
unit: Option<Units>, unit: Option<Units>,
} }
@@ -24,7 +28,7 @@ impl CellWidget {
col: usize, col: usize,
zoom_level: ZoomLevel, zoom_level: ZoomLevel,
selected: bool, selected: bool,
structure: CellStructure, structure: Structures,
unit: Option<Units>, unit: Option<Units>,
) -> Self { ) -> Self {
Self { Self {
@@ -48,7 +52,7 @@ impl CellWidget {
self self
} }
pub fn set_structure(&mut self, sctructure: CellStructure) -> &mut Self { pub fn set_structure(&mut self, sctructure: Structures) -> &mut Self {
self.structure = sctructure; self.structure = sctructure;
self self
} }
@@ -75,7 +79,7 @@ impl CellWidget {
} }
fn display_coords(&self) -> Span<'_> { fn display_coords(&self) -> Span<'_> {
if self.selected || self.structure != CellStructure::Stone(Stone::new()) || self.marked { if self.selected || self.structure != Structures::Stone(Stone::new()) || self.marked {
format!("{}{}", self.col_to_letters(), self.row).green() format!("{}{}", self.col_to_letters(), self.row).green()
} else { } else {
"".to_span() "".to_span()
@@ -84,61 +88,22 @@ impl CellWidget {
fn fg_color(&self) -> Color { fn fg_color(&self) -> Color {
if self.marked && self.selected { if self.marked && self.selected {
return Color::Magenta; Color::Magenta
} else if self.marked && !self.selected { } else if self.marked && !self.selected {
return Color::LightMagenta; Color::LightMagenta
} else if self.selected && !self.marked { } else if !self.marked && self.selected {
return Color::LightYellow; Color::LightYellow
} } else {
self.structure.get_color()
match self.structure {
CellStructure::Base(base) => base.get_color(),
CellStructure::Tunnel(tunnel) => tunnel.get_color(),
CellStructure::Stone(stone) => stone.get_color(),
} }
} }
fn get_text_area(&self) -> Vec<Line<'_>> { fn get_text_area(&self) -> Vec<Line<'_>> {
let tag: char = match self.structure { self.zoom_level.get_cell_text_area(
CellStructure::Base(base) => base.get_tag(), self.structure.get_tag(),
CellStructure::Tunnel(tunnel) => tunnel.get_tag(), self.structure.get_level(),
CellStructure::Stone(stone) => stone.get_tag(), self.unit.try_get_tag(),
}; )
let b_level: char = match self.structure {
CellStructure::Base(base) => base.get_level(),
_ => ' ',
};
let unit: char = match self.unit {
Some(unit) => match unit {
Units::Miner(miner) => miner.get_tag(),
// _ => ' ',
},
None => ' ',
};
let mut text_area: Vec<Line<'_>> = Vec::new();
match self.zoom_level {
ZoomLevel::ZoomedIn => {
text_area.push(Line::from(format!(" {} {} ", b_level, unit)));
text_area.push(Line::from(format!(" ")));
text_area.push(Line::from(format!(" {} ", tag)));
text_area.push(Line::from(format!(" ")));
text_area.push(Line::from(format!(" ")));
}
ZoomLevel::Default => {
text_area.push(Line::from(format!(" {} {} ", b_level, unit)));
text_area.push(Line::from(format!(" {} ", tag)));
text_area.push(Line::from(format!(" ")));
}
ZoomLevel::ZoomedOut => {
text_area.push(Line::from(format!(" {} ", tag)));
}
}
text_area
} }
fn get_block(&self) -> Block<'_> { fn get_block(&self) -> Block<'_> {
+1 -1
View File
@@ -1,5 +1,5 @@
use crate::app::{ use crate::app::{
states::{GameMode, PerkDecks, ZoomLevel}, states::{GameMode, PerkDecks, skirmish_states::ZoomLevel},
threads::Soundtrack, threads::Soundtrack,
view::View, view::View,
}; };