Something went wrong. Try again.
Data management tools for playing BattleTech
Something went wrong. Try again.
Java
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138import megamek.client.ui.clientGUI.calculationReport.TextCalculationReport;import megamek.common.loaders.MekSummary;import megamek.common.loaders.MekSummaryCache;import megamek.common.units.Entity;
import java.io.BufferedWriter;import java.io.FileOutputStream;import java.io.OutputStreamWriter;import java.io.PrintWriter;import java.nio.charset.StandardCharsets;
/** * Dump the working of MegaMek's C-bill cost calculation, one object per unit. * * <p>The same bargain as DumpBv: `DumpUnits` already carries the answer, and * an answer alone makes a poor oracle for a reimplementation. A design's cost * is a sum of two dozen terms - the frame, the engine, each actuator, each * weapon, the plate - multiplied by a factor for the kind of machine it is, * and a total that is 40,000 C-bills light says nothing about which term is * wrong. `Entity.getCost` writes its own working into a report as it goes, * and that report says which line. * * java -cp "MegaMek.jar:lib/*" DumpCost.java out.jsonl [unitType ...] * * Must run with MegaMek's install dir as the working directory. */public final class DumpCost {
public static void main(String[] args) throws Exception { if (args.length < 1) { System.err.println("usage: DumpCost <out.jsonl> [unitType ...]"); System.exit(2); } java.util.Set<String> only = new java.util.LinkedHashSet<>(); for (int i = 1; i < args.length; i++) { only.add(args[i].toLowerCase(java.util.Locale.ROOT)); }
long start = System.currentTimeMillis(); MekSummaryCache cache = MekSummaryCache.getInstance(); long deadline = start + 600_000L; while (!cache.isInitialized()) { if (System.currentTimeMillis() > deadline) { System.err.println("units.cache did not initialise within 600s"); System.exit(1); } Thread.sleep(250L); }
int written = 0; int skipped = 0; try (PrintWriter out = new PrintWriter(new BufferedWriter( new OutputStreamWriter(new FileOutputStream(args[0]), StandardCharsets.UTF_8)))) { for (MekSummary ms : cache.getAllMeks()) { String name = ms.getName(); try { if (!only.isEmpty() && !only.contains(ms.getUnitType().toLowerCase(java.util.Locale.ROOT))) { continue; } Entity entity = ms.loadEntity(); if (entity == null) { skipped++; continue; } TextCalculationReport report = new TextCalculationReport(); // `false` is "count the ammunition", which is what // MekSummary.cost records and so what helm is measured // against. double cost = entity.getCost(report, false);
StringBuilder sb = new StringBuilder(1024); sb.append('{'); str(sb, "name"); sb.append(':'); str(sb, name); sb.append(','); str(sb, "unitType"); sb.append(':'); str(sb, ms.getUnitType()); sb.append(','); str(sb, "cost"); sb.append(':'); sb.append(Double.isFinite(cost) ? Double.toString(cost) : "null"); sb.append(','); str(sb, "summaryCost"); sb.append(':'); double summary = ms.getCost(); sb.append(Double.isFinite(summary) ? Double.toString(summary) : "null"); sb.append(','); // What the design's own kind multiplies the sum by, which // the report prints but not always as a line of its own. str(sb, "priceMultiplier"); sb.append(':'); double multiplier = entity.getPriceMultiplier(); sb.append(Double.isFinite(multiplier) ? Double.toString(multiplier) : "null"); sb.append(','); str(sb, "report"); sb.append(':'); str(sb, report.toString()); sb.append('}'); out.println(sb); written++; } catch (Throwable t) { skipped++; System.err.println("skipped " + name + ": " + t); } } }
System.out.printf("dumped %d units in %.1fs (%d skipped) -> %s%n", written, (System.currentTimeMillis() - start) / 1000.0, skipped, args[0]); System.exit(0); }
private static void str(StringBuilder sb, String s) { sb.append('"'); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); switch (c) { case '"' -> sb.append("\\\""); case '\\' -> sb.append("\\\\"); case '\n' -> sb.append("\\n"); case '\r' -> sb.append("\\r"); case '\t' -> sb.append("\\t"); default -> { if (c < 0x20) { sb.append(String.format("\\u%04x", (int) c)); } else { sb.append(c); } } } } sb.append('"'); }}