fix(bandopen): drop the distance ceiling
The detector refused any path over 2400 km, reasoning that past a single hop the bearing test stops meaning anything. That was wrong, and it discarded exactly the openings worth announcing: Nexus flagged a 6 m opening at 5477 km that OpsLog never saw, because the spots were thrown away before any test ran. Multi-hop Es is ordinary on 6 m — 5000 km paths are common, 10000 km happens — and it stays directional: a second hop leaves the sector the first one entered. So the sector test, which is what does the real work here, holds perfectly well at any distance. The ceiling was standing in for a judgement it could not make. The floor stays at 500 km: a short 6 m contact is tropo or ground wave and says nothing about the ionosphere. Both are now pinned by a test.
This commit is contained in:
@@ -182,3 +182,46 @@ func TestBearingArcWrapsAtNorth(t *testing.T) {
|
||||
t.Errorf("bearings on all four quadrants should span nearly the circle, got %d", s)
|
||||
}
|
||||
}
|
||||
|
||||
// Multi-hop must be detected, not thrown away.
|
||||
//
|
||||
// The detector used to cap paths at 2400 km, on the reasoning that past one hop
|
||||
// the bearing test stops meaning anything. Nexus flagged a 6 m opening at
|
||||
// 5477 km that OpsLog never saw: the spots were discarded before any test ran.
|
||||
// Multi-hop Es is directional — a second hop leaves the sector the first one
|
||||
// entered — so distance is not what tells an opening from noise. The sector is.
|
||||
func TestMultiHopOpeningIsDetected(t *testing.T) {
|
||||
d := New(DefaultConfig())
|
||||
base := time.Date(2026, 6, 15, 18, 0, 0, 0, time.UTC)
|
||||
var got *Opening
|
||||
for i, call := range []string{"LU1AA", "PY2BB", "LU3CC", "PY4DD"} {
|
||||
if op := d.Add(Spot{
|
||||
Call: call, Band: "6m",
|
||||
DistKm: 5400 + i*40, // double hop, far past the old ceiling
|
||||
Bearing: +i * 5, // one sector, as a real cloud illuminates
|
||||
At: base.Add(time.Duration(i) * time.Minute),
|
||||
}, 47.0); op != nil {
|
||||
got = op
|
||||
}
|
||||
}
|
||||
if got == nil {
|
||||
t.Fatal("a four-station 5400 km burst in one sector was not reported as an opening")
|
||||
}
|
||||
if got.Band != "6m" {
|
||||
t.Errorf("band = %q, want 6m", got.Band)
|
||||
}
|
||||
}
|
||||
|
||||
// The floor stays: a short path says nothing about the ionosphere.
|
||||
func TestGroundWaveIsStillIgnored(t *testing.T) {
|
||||
d := New(DefaultConfig())
|
||||
base := time.Date(2026, 6, 15, 18, 0, 0, 0, time.UTC)
|
||||
for i, call := range []string{"F1AA", "F2BB", "F3CC", "F4DD"} {
|
||||
if op := d.Add(Spot{
|
||||
Call: call, Band: "6m", DistKm: 120, Bearing: 90,
|
||||
At: base.Add(time.Duration(i) * time.Minute),
|
||||
}, 47.0); op != nil {
|
||||
t.Fatalf("a 120 km burst was reported as an opening: %+v", op)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user