Tell the APRS map which band it is on, and where you are standing
Three things wrong with the window, all reported from the chair in front of it, and all three the same kind of wrong: the map had been handed the aircraft map's furniture and nobody had checked which bits of it were about aircraft. The empty screen said "listening on 1090 MHz" and went on to explain that an aeroplane is placed once an even and an odd position frame have both arrived. That sentence was true of the window it was written for and false of every word in this one. What has to arrive before a mark can be placed is a fact about the signal rather than about the window, so it is now a thing the window is told: an aeroplane still says what an aeroplane needs, a station says that most of them mention where they are every few minutes, and left unsaid the words follow whatever channel the window was given rather than naming 1090 from memory. There was no red flag. The flag is drawn where the receiver was actually told it is, and this section has its own --at that had never been filled in -- but the aircraft section's had, by the same person, about the same aerial, on the same roof. One aerial does not move because the receiver was pointed at a different band, so a position set on either side now serves both, this section's own winning where it has one because two receivers in two places is exactly what a separate setting is for. It says out loud which it used, an inherited position being a convenience right up until somebody has moved and changed only one of them. The flag, the range rings and every distance and bearing all come from the same answer, so all four arrive together. The boxes drew a station's position and never wrote it down. A mark on a map shows where something is; the figures are what gets read out over the air, copied into a log or typed into something else. They are also the only place the doubt shows: a station that blanks its minutes is somewhere inside a two-degree square, the diamond is as definite there as it is anywhere, and only "49.0000N 72.0000W +/-340 km" admits it. Twelve new tests against six deliberately broken builds. One survived, and it is the one that matters: with the drawing code changed back to print aeroplanes at 1090 MHz, every test still passed, because they all read the sentence off the object and none of them read the pixels. That is the reported fault exactly -- a window that holds one sentence and paints another -- and the suite could not see it. It reads the picture now, cropped below the header, whose ticking clock has made a test pass for the wrong reason twice already this session. Full suite 2664 passed. Built as 2026-09-21_02. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016PsWPTweCT6pwxKngvVxcg
This commit is contained in:
parent
2c7b1ba25e
commit
e05b66ec3d
8 changed files with 295 additions and 36 deletions
|
|
@ -1005,3 +1005,126 @@ def test_the_window_says_so_rather_than_failing_when_qt_is_missing(
|
|||
heard = ap.watch(console, ap.AprsOptions(), str(tmp_path))
|
||||
assert heard.stations == 0
|
||||
assert "no window to open" in cap.get()
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Where the aerial is
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def test_the_aerial_position_is_taken_from_the_aircraft_settings_if_unset(
|
||||
tmp_path, monkeypatch):
|
||||
"""One aerial, one roof, one position.
|
||||
|
||||
Which band it is pointed at today does not move it, so somebody who has
|
||||
already told the aircraft side where they are should not have to say it
|
||||
again -- and, having said it once, would reasonably expect the flag.
|
||||
"""
|
||||
from bandsaunter import aircraft
|
||||
|
||||
aircraft.save_options(
|
||||
aircraft.AircraftOptions(location="47.55,-122.30"), tmp_path)
|
||||
monkeypatch.setattr(aircraft, "options_path",
|
||||
lambda directory=None: tmp_path / "aircraft.yaml")
|
||||
assert ap.receiver_at(ap.AprsOptions()) == (47.55, -122.30)
|
||||
|
||||
|
||||
def test_this_sections_own_position_wins_where_it_has_one(tmp_path,
|
||||
monkeypatch):
|
||||
"""Two receivers in two places is a thing that happens, and is exactly
|
||||
what the separate setting is for."""
|
||||
from bandsaunter import aircraft
|
||||
|
||||
aircraft.save_options(
|
||||
aircraft.AircraftOptions(location="47.55,-122.30"), tmp_path)
|
||||
monkeypatch.setattr(aircraft, "options_path",
|
||||
lambda directory=None: tmp_path / "aircraft.yaml")
|
||||
here = ap.receiver_at(ap.AprsOptions(location="51.5,-0.13"))
|
||||
assert here == (51.5, -0.13)
|
||||
|
||||
|
||||
def test_neither_side_knowing_is_no_position_rather_than_a_wrong_one(
|
||||
tmp_path, monkeypatch):
|
||||
from bandsaunter import aircraft
|
||||
|
||||
monkeypatch.setattr(aircraft, "options_path",
|
||||
lambda directory=None: tmp_path / "none.yaml")
|
||||
assert ap.receiver_at(ap.AprsOptions()) is None
|
||||
|
||||
|
||||
def test_the_window_gets_the_position_so_the_flag_is_drawn(tmp_path,
|
||||
monkeypatch):
|
||||
from bandsaunter import aircraft, livemap
|
||||
|
||||
aircraft.save_options(
|
||||
aircraft.AircraftOptions(location="47.55,-122.30"), tmp_path)
|
||||
monkeypatch.setattr(aircraft, "options_path",
|
||||
lambda directory=None: tmp_path / "aircraft.yaml")
|
||||
built = {}
|
||||
monkeypatch.setattr(livemap, "available", lambda: True)
|
||||
monkeypatch.setattr(livemap, "show",
|
||||
lambda sky, title: built.update(home=sky.home,
|
||||
waiting=sky.waiting))
|
||||
monkeypatch.setattr(ap, "open_device", lambda console, opts: Silence(1))
|
||||
console = Console(width=120, force_terminal=False)
|
||||
with console.capture():
|
||||
ap.watch(console, ap.AprsOptions(rate=RATE, log=False, report=False,
|
||||
basemap=False), str(tmp_path))
|
||||
assert built["home"] == (47.55, -122.30)
|
||||
# And the empty picture no longer talks about aeroplanes.
|
||||
assert "1090" not in built["waiting"] and "144.39 MHz" in built["waiting"]
|
||||
assert "aircraft" not in built["waiting"]
|
||||
|
||||
|
||||
def test_it_says_where_the_position_came_from_rather_than_assuming(
|
||||
tmp_path, monkeypatch):
|
||||
"""A position inherited from another section is a convenience right up
|
||||
until somebody has moved and changed only one of them."""
|
||||
from bandsaunter import aircraft, livemap
|
||||
|
||||
aircraft.save_options(
|
||||
aircraft.AircraftOptions(location="47.55,-122.30"), tmp_path)
|
||||
monkeypatch.setattr(aircraft, "options_path",
|
||||
lambda directory=None: tmp_path / "aircraft.yaml")
|
||||
monkeypatch.setattr(livemap, "available", lambda: True)
|
||||
monkeypatch.setattr(livemap, "show", lambda sky, title: None)
|
||||
monkeypatch.setattr(ap, "open_device", lambda console, opts: Silence(1))
|
||||
console = Console(width=120, force_terminal=False)
|
||||
with console.capture() as cap:
|
||||
ap.watch(console, ap.AprsOptions(rate=RATE, log=False, report=False,
|
||||
basemap=False), str(tmp_path))
|
||||
assert "from the aircraft settings" in cap.get()
|
||||
|
||||
|
||||
def test_knowing_nowhere_says_what_that_costs(tmp_path, monkeypatch):
|
||||
from bandsaunter import aircraft
|
||||
|
||||
monkeypatch.setattr(aircraft, "options_path",
|
||||
lambda directory=None: tmp_path / "none.yaml")
|
||||
monkeypatch.setattr(ap, "open_device", lambda console, opts: Silence(2))
|
||||
console = Console(width=120, force_terminal=False)
|
||||
with console.capture() as cap:
|
||||
ap.listen(console, ap.AprsOptions(rate=RATE, log=False,
|
||||
packets_seen=True), str(tmp_path))
|
||||
out = cap.get()
|
||||
assert "no flag" in out and "--at" in out
|
||||
|
||||
|
||||
def test_the_box_gives_the_position_in_figures():
|
||||
"""A mark shows where a station is; a number is what gets written down."""
|
||||
rows = dict((label, value) for label, value, _f
|
||||
in ap.station_lines(station_of()))
|
||||
assert rows["position"] == "49.0583N 72.0292W"
|
||||
|
||||
|
||||
def test_the_box_shows_a_vague_position_as_vague():
|
||||
"""Blanking the minutes is a deliberate act by the operator, and the
|
||||
figures are the only place that shows."""
|
||||
rows = dict((label, value) for label, value, _f
|
||||
in ap.station_lines(station_of("=49 . N/072 . W-vague")))
|
||||
assert "±" in rows["position"]
|
||||
|
||||
|
||||
def test_a_station_that_never_said_where_it_is_has_no_position_row():
|
||||
rows = dict((label, value) for label, value, _f
|
||||
in ap.station_lines(station_of(">Monitoring 146.52")))
|
||||
assert "position" not in rows
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue