Something went wrong. Try again.
Data management tools for playing BattleTech
Something went wrong. Try again.
Rust
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110//! `helm wire-check`: what a page would be handed, and what this build says//! the answers are.//!//! The bundle it writes is the input to `crates/helm-wasm/wire.mjs`, which//! scores every design twice - once natively here and once through the wasm//! boundary - and fails on any disagreement.
use crate::inputs::install_and_dump;use crate::options::parse_opts;
/// Write what a browser needs to score the whole library, and what this build/// says the answers are.////// The rules compile twice, natively for the server and to wasm for the page,/// and the whole reason `helm-bv` does no I/O is that both have to agree./// Nothing proved they did: the smoke test crosses the boundary with a handful/// of designs. This writes the bundle that lets `crates/helm-wasm/wire.mjs`/// check every one of them, which is a different claim entirely.////// Three files, all derived and none committed: the catalogue a page loads,/// every design as the text a page would be handed, and this build's answer/// for each, fresh and shot at - because a condition crossing the boundary as/// JSON is its own chance to disagree.pub(crate) fn wire_check(args: &[String]) -> Result<(), String> { let opts = parse_opts(args)?; let (megamek, bridge) = install_and_dump(&opts, "--bridge-dir is required: the catalogue lives there")?; let out = opts .out .ok_or("--out is required: the bundle wire.mjs reads has to go somewhere")?; std::fs::create_dir_all(&out).map_err(|e| format!("{}: {e}", out.display()))?;
let catalogue = helm_bridge::read_catalogue(&bridge.join("equipment.jsonl")).map_err(|e| e.to_string())?; let zip = megamek.join(helm_unitfile::LIBRARY_IN_INSTALL); let file = std::fs::File::open(&zip).map_err(|e| format!("{}: {e}", zip.display()))?; let texts = helm_unitfile::read_zip_text(file).map_err(|e| e.to_string())?;
// The condition every design is also scored in, chosen to touch the parts // of a `Condition` that cross as JSON: plate, frame, a wrecked slot and an // empty magazine. let damaged = helm_bv::Condition { armor: [("CT".to_string(), 3), ("LT".to_string(), 0)] .into_iter() .collect(), structure: [("RT".to_string(), 2)].into_iter().collect(), destroyed: [("Right Arm".to_string(), [4usize].into_iter().collect())] .into_iter() .collect(), empty_ammo: [("Left Torso".to_string(), [1usize].into_iter().collect())] .into_iter() .collect(), // Nothing swapped: what a slot holds is a `.mul`'s business, and this // sweep reads `.mtf` files. loaded: Default::default(), };
let mut designs = String::new(); let mut native = String::new(); let mut written = 0; for (path, text) in &texts { let Ok(unit) = helm_unitfile::parse_mtf(path, text) else { continue; }; let Ok(fresh) = helm_bv::battle_value(&unit, &catalogue) else { // Declined by decision or not yet written: a page will not be // asked about it either. continue; }; let hurt = helm_bv::battle_value_in(&unit, &catalogue, &damaged).ok(); let name = unit.display_name(); designs.push_str(&serde_json::json!({ "name": name, "mtf": text }).to_string()); designs.push('\n'); native.push_str( &serde_json::json!({ "name": name, "fresh": fresh, "damaged": hurt }).to_string(), ); native.push('\n'); written += 1; }
let write = |file: &str, body: &str| -> Result<(), String> { let path = out.join(file); std::fs::write(&path, body).map_err(|e| format!("{}: {e}", path.display())) }; write("designs.jsonl", &designs)?; write("native.jsonl", &native)?; write( "condition.json", &serde_json::json!({ "armor": damaged.armor, "structure": damaged.structure, "destroyed": damaged.destroyed, "emptyAmmo": damaged.empty_ammo, }) .to_string(), )?;
println!( "wrote {} ({written} designs, {:.1} MB)", out.display(), designs.len() as f64 / 1_048_576.0 ); println!( "check it with: node crates/helm-wasm/wire.mjs {} {}", bridge.join("equipment.jsonl").display(), out.display() ); Ok(())}