Separate battery status from player-facing text
Co-Authored-By: Codex <noreply@openai.com>
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
//! Player-facing labels for battery configuration snapshots.
|
||||
use crate::sim::battery::{BatteryStatus, RadarRole, SamMode};
|
||||
|
||||
pub fn radar_role_name(role: RadarRole) -> &'static str {
|
||||
match role {
|
||||
RadarRole::Multifunction => "многофункциональная",
|
||||
RadarRole::Search => "обзорная",
|
||||
RadarRole::Engagement => "сопровождения",
|
||||
RadarRole::Height => "мачтовая",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn status(status: BatteryStatus) -> String {
|
||||
match status {
|
||||
BatteryStatus::Radar { index, role, emitting, operational } => format!(
|
||||
"№{} РЛС: {}, излучение {}, {}", index + 1, radar_role_name(role),
|
||||
if emitting { "вкл" } else { "выкл" },
|
||||
if operational { "работает" } else { "нет связи или РЛС не работает" }
|
||||
),
|
||||
BatteryStatus::Launcher { index, kind, mode, linked } => format!(
|
||||
"№{} {}: {}{}", index + 1, kind.name(), mode.key(),
|
||||
if mode == SamMode::LauncherOnly {
|
||||
if linked { ", РЛС связана" } else { ", нет связанной РЛС сопровождения" }
|
||||
} else { "" }
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::sim::SamKind;
|
||||
|
||||
#[test]
|
||||
fn renders_battery_status_in_existing_format() {
|
||||
assert_eq!(status(BatteryStatus::Radar { index: 0, role: RadarRole::Search, emitting: false, operational: false }), "№1 РЛС: обзорная, излучение выкл, нет связи или РЛС не работает");
|
||||
assert_eq!(status(BatteryStatus::Radar { index: 1, role: RadarRole::Engagement, emitting: true, operational: true }), "№2 РЛС: сопровождения, излучение вкл, работает");
|
||||
assert_eq!(status(BatteryStatus::Launcher { index: 2, kind: SamKind::S400, mode: SamMode::LauncherOnly, linked: true }), "№3 С-400: launcher, РЛС связана");
|
||||
assert_eq!(status(BatteryStatus::Launcher { index: 3, kind: SamKind::S500, mode: SamMode::LauncherOnly, linked: false }), "№4 С-500: launcher, нет связанной РЛС сопровождения");
|
||||
assert_eq!(status(BatteryStatus::Launcher { index: 4, kind: SamKind::S400, mode: SamMode::Integrated, linked: false }), "№5 С-400: integrated");
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,7 @@ use horizon_mod_sdk::{
|
||||
ui::{self, ButtonWidget, ItemWidget, ListWidget, Screen, Widget},
|
||||
};
|
||||
|
||||
mod battery_view;
|
||||
mod cinema;
|
||||
mod capabilities;
|
||||
mod engines;
|
||||
@@ -2301,7 +2302,7 @@ impl Mod for AirDef {
|
||||
["deploy", kind] => Some(self.deploy_configured(kind)?),
|
||||
["battery"] => {
|
||||
let status = self.sim.battery_status();
|
||||
for line in &status { say(line); }
|
||||
for entry in status { say(&battery_view::status(entry)); }
|
||||
Some("/airdef battery <номер> integrated|launcher; /airdef radar <номер> on|off|multi|search|engagement|height".into())
|
||||
}
|
||||
["battery", n, mode] => {
|
||||
|
||||
@@ -2330,7 +2330,7 @@ impl AirDef {
|
||||
let k = sam.kind;
|
||||
lines.push((format!("{} №{}", k.name(), n + 1), CYAN));
|
||||
if k == SamKind::Radar {
|
||||
lines.push((format!("Роль РЛС: {}", sam.radar_role.name()), WHITE));
|
||||
lines.push((format!("Роль РЛС: {}", crate::battery_view::radar_role_name(sam.radar_role)), WHITE));
|
||||
} else if sam.mode == sim::battery::SamMode::LauncherOnly {
|
||||
lines.push(("Отдельная пусковая: внешняя РЛС сопровождения".into(), WHITE));
|
||||
}
|
||||
|
||||
@@ -33,9 +33,6 @@ impl RadarRole {
|
||||
pub fn from_key(key: &str) -> Option<Self> {
|
||||
match key { "multi" => Some(Self::Multifunction), "search" => Some(Self::Search), "engagement" => Some(Self::Engagement), "height" => Some(Self::Height), _ => None }
|
||||
}
|
||||
pub fn name(self) -> &'static str {
|
||||
match self { Self::Multifunction => "многофункциональная", Self::Search => "обзорная", Self::Engagement => "сопровождения", Self::Height => "мачтовая" }
|
||||
}
|
||||
pub fn authorizes(self) -> bool { matches!(self, Self::Multifunction | Self::Engagement) }
|
||||
pub(super) fn reach_factor(self) -> f64 { match self { Self::Multifunction => 1.0, Self::Search => 1.15, Self::Engagement => 0.8, Self::Height => 1.05 } }
|
||||
}
|
||||
@@ -68,15 +65,22 @@ impl Sam {
|
||||
}
|
||||
}
|
||||
|
||||
/// A snapshot of the relevant configuration, independent of its presentation.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum BatteryStatus {
|
||||
Radar { index: usize, role: RadarRole, emitting: bool, operational: bool },
|
||||
Launcher { index: usize, kind: SamKind, mode: SamMode, linked: bool },
|
||||
}
|
||||
|
||||
impl Sim {
|
||||
/// Current configurations and whether a launcher has an operational radar link.
|
||||
pub fn battery_status(&self) -> Vec<String> {
|
||||
self.sams.iter().enumerate().filter_map(|(i, sam)| {
|
||||
pub fn battery_status(&self) -> Vec<BatteryStatus> {
|
||||
self.sams.iter().enumerate().filter_map(|(index, sam)| {
|
||||
if sam.kind == SamKind::Radar {
|
||||
Some(format!("№{} РЛС: {}, излучение {}, {}", i + 1, sam.radar_role.name(), if sam.radar_on { "вкл" } else { "выкл" }, if sam.radar_up() && sam.link_range() > 0.0 { "работает" } else { "нет связи или РЛС не работает" }))
|
||||
Some(BatteryStatus::Radar { index, role: sam.radar_role, emitting: sam.radar_on, operational: sam.radar_up() && sam.link_range() > 0.0 })
|
||||
} else if matches!(sam.kind, SamKind::S400 | SamKind::S500) {
|
||||
let linked = self.sams.iter().any(|r| r.kind == SamKind::Radar && r.radar_role.authorizes() && r.radar_up() && r.link_range() > 0.0 && sam.link_range() > 0.0 && r.pos.distance(sam.pos) <= r.link_range().min(sam.link_range()));
|
||||
Some(format!("№{} {}: {}{}", i + 1, sam.kind.name(), sam.mode.key(), if sam.mode == SamMode::LauncherOnly { if linked { ", РЛС связана" } else { ", нет связанной РЛС сопровождения" } } else { "" }))
|
||||
Some(BatteryStatus::Launcher { index, kind: sam.kind, mode: sam.mode, linked })
|
||||
} else { None }
|
||||
}).collect()
|
||||
}
|
||||
@@ -87,6 +91,27 @@ mod tests {
|
||||
use super::*;
|
||||
use super::super::{sight, why};
|
||||
|
||||
#[test]
|
||||
fn status_reports_real_radar_links_and_preserves_indices() {
|
||||
let mut sim = Sim::new(1);
|
||||
sim.sams.push(Sam::new(1, SamKind::Pantsir, DVec3::ZERO, 0.0));
|
||||
let mut radar = Sam::new(2, SamKind::Radar, DVec3::ZERO, 0.0);
|
||||
radar.radar_role = RadarRole::Engagement;
|
||||
sim.sams.push(radar);
|
||||
let mut launcher = Sam::new(3, SamKind::S400, DVec3::new(10.0, 0.0, 0.0), 0.0);
|
||||
launcher.set_mode(SamMode::LauncherOnly);
|
||||
sim.sams.push(launcher);
|
||||
assert_eq!(sim.battery_status(), vec![
|
||||
BatteryStatus::Radar { index: 1, role: RadarRole::Engagement, emitting: true, operational: true },
|
||||
BatteryStatus::Launcher { index: 2, kind: SamKind::S400, mode: SamMode::LauncherOnly, linked: true },
|
||||
]);
|
||||
sim.sams[1].radar_on = false;
|
||||
assert_eq!(sim.battery_status(), vec![
|
||||
BatteryStatus::Radar { index: 1, role: RadarRole::Engagement, emitting: false, operational: false },
|
||||
BatteryStatus::Launcher { index: 2, kind: SamKind::S400, mode: SamMode::LauncherOnly, linked: false },
|
||||
]);
|
||||
}
|
||||
|
||||
fn track(now: u64) -> Track {
|
||||
Track { id: 42, kind: DroneKind::Kh101, pos: DVec3::new(0.0, 100.0, -200.0), vel: DVec3::ZERO, tick: now, own_tick: now, ttl: 400, hits: 3, locked: false }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user