Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
[Electron Kiosk Shell](electron-kiosk-shell.md#browser-local-state-breaking-on-first-electron-launch).

### Fixed
- **Simulator output tags estimated launch angles as estimated.** When the
server fills in a launch angle before the sim fan-out, the resolver tagged
it, and the carry built on it, as measured. It now reads the angle's source,
so the simulator badges, `sim_shot` event and `sim_send` log entries match
the data.
- **Doc paths named from the Python package resolve again.** The K-LD7
OPS-bin penalty warning, the cloud client and session-logger comments,
and the two-ray module docstring pointed at flat `docs/*.md` files that
Expand Down
10 changes: 7 additions & 3 deletions src/openflight/sim/resolver.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,18 @@ def resolve_shot(shot: Shot, player_state: PlayerState) -> ResolvedShot:

if shot.launch_angle_vertical is not None:
vla = float(shot.launch_angle_vertical)
provenance["vla"] = "measured"
provenance["vla"] = (
"estimated" if shot.launch_angle_vertical_source == "estimated" else "measured"
)
else:
vla = get_club_physics(shot.club).optimal_launch_deg
provenance["vla"] = "estimated"

if shot.launch_angle_horizontal is not None:
hla = float(shot.launch_angle_horizontal)
provenance["hla"] = "measured"
provenance["hla"] = (
"estimated" if shot.launch_angle_horizontal_source == "estimated" else "measured"
)
else:
hla = 0.0
provenance["hla"] = "estimated"
Expand Down Expand Up @@ -114,7 +118,7 @@ def resolve_shot(shot: Shot, player_state: PlayerState) -> ResolvedShot:
# means launch-angle-informed: the carry model was driven by a measured launch
# angle rather than falling back to club-type defaults. The UI badge reflects
# that distinction, not a claim that carry itself was measured (PR #115 review #6).
provenance["carry"] = "measured" if shot.has_launch_angle else "estimated"
provenance["carry"] = provenance["vla"]

if shot.club_speed_mph is not None and shot.club_speed_mph > 0:
club_speed = float(shot.club_speed_mph)
Expand Down
28 changes: 28 additions & 0 deletions tests/test_sim_resolver.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,3 +122,31 @@ def test_carry_falls_back_to_table_when_nothing_committed():
assert resolve_shot(shot, PlayerState()).carry_yards == pytest.approx(
shot.estimated_carry_yards
)


def test_server_estimated_launch_angles_are_tagged_estimated():
# server._ensure_user_facing_launch_angles fills missing angles before the
# sim fan-out and marks them with source "estimated".
shot = _shot(
launch_angle_vertical=11.0, launch_angle_vertical_source="estimated",
launch_angle_horizontal=0.0, launch_angle_horizontal_source="estimated",
)
r = resolve_shot(shot, PlayerState())
assert r.vla == 11.0
assert r.hla == 0.0
assert r.provenance["vla"] == "estimated"
assert r.provenance["hla"] == "estimated"
assert r.provenance["carry"] == "estimated"


def test_measured_vla_keeps_measured_carry_when_only_hla_is_estimated():
# A vertical angle radar alone gives a measured VLA, and the server fills in
# the neutral 0.0 HLA.
shot = _shot(
launch_angle_vertical=12.0, launch_angle_vertical_source="radar",
launch_angle_horizontal=0.0, launch_angle_horizontal_source="estimated",
)
r = resolve_shot(shot, PlayerState())
assert r.provenance["vla"] == "measured"
assert r.provenance["hla"] == "estimated"
assert r.provenance["carry"] == "measured"
Loading