Same style fix applied to the README earlier, extended everywhere: replaced " -- " with commas/colons/periods (picking whichever reads right per occurrence, splitting into two sentences where the clauses were independent), fixed a few user-facing strings along the way (entity list rows, placement/strike toasts, ambiguous-candidate tag, shell picker button label). Left three intentional non-prose uses alone: the "unassigned" dash glyph in firing_panel.py (and its docstring diagram), and ocr.py's dash-variant regex character class, which needs to literally match em/en-dashes in OCR'd text. Also caught and fixed a stale models.py docstring claiming "no solver yet" (solver.py has existed for a while) while touching that paragraph anyway, and a formatting artifact in coord_dialog.py's docstring left by the sed pass (misaligned comma from a since-removed alignment gap). Verified: py_compile across all files, the 9-screenshot OCR regression sweep, and a GTK smoke test exercising the edited toast/placement code paths. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
47 lines
1.4 KiB
Python
47 lines
1.4 KiB
Python
"""Firing-solution math, from High Command's gunnery tables.
|
|
|
|
Distances/bearings reuse the same board-units-are-km convention as
|
|
solver.py. Powder charge controls elevation: more charge, lower arc for
|
|
the same distance, up to MAX_POWDER_CHARGE; min_powder_charge() is the
|
|
least charge that can still reach a given distance at all.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import math
|
|
|
|
from .models import Coord
|
|
|
|
MAX_POWDER_CHARGE = 6
|
|
|
|
|
|
def distance_km_point(a: tuple[float, float], b: tuple[float, float]) -> float:
|
|
return math.hypot(b[0] - a[0], b[1] - a[1])
|
|
|
|
|
|
def bearing_deg_point(a: tuple[float, float], b: tuple[float, float]) -> float:
|
|
"""Compass bearing from a to b: 0 = north (+row), 90 = east (+col),
|
|
matching solver.py's convention, the inverse of
|
|
solver.point_from_bearing_distance()."""
|
|
return math.degrees(math.atan2(b[0] - a[0], b[1] - a[1])) % 360
|
|
|
|
|
|
def distance_km(a: Coord, b: Coord) -> float:
|
|
return distance_km_point(a.as_fraction(), b.as_fraction())
|
|
|
|
|
|
def bearing_deg(a: Coord, b: Coord) -> float:
|
|
return bearing_deg_point(a.as_fraction(), b.as_fraction())
|
|
|
|
|
|
def min_powder_charge(dist_km: float, eps: float = 1e-9) -> int:
|
|
n = dist_km / 5
|
|
rounded = round(n)
|
|
if abs(n - rounded) < eps:
|
|
return max(1, rounded)
|
|
return math.ceil(n)
|
|
|
|
|
|
def elevation_deg(dist_km: float, charges: int) -> float:
|
|
return 12 * dist_km / charges
|