The window is now a summary table of mults, Qs and totals per band over a sortable spot grid with Call, Freq, Mode, Dir, Mlt, SN, TS, Spotter, Grid, Sun, Pts and a preferred-spotter column. Columns can be hidden, headers sorted, and the list stops re-sorting for six seconds under the mouse. Adds the Mults / Mults & Qs button, a Bands & Modes filter, delete and blacklist from the right-click menu, Alt+A stepping, and QSY to the top spot after logging. Spot gains Snr and IsSkimmer, Bandmap gains Remaining, and AvailableStation carries the path to the station. The menu item no longer has apostrophes. SO2R, SO2V and the other missing pieces are listed in docs/unfinished.md. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
191 lines
6.4 KiB
C#
191 lines
6.4 KiB
C#
using Nonemm.Contests;
|
|
using Nonemm.Contests.Rules;
|
|
using Nonemm.Core;
|
|
using Nonemm.Core.Calls;
|
|
using Nonemm.Core.Country;
|
|
using Nonemm.Spotting;
|
|
using Nonemm.Storage;
|
|
|
|
namespace Nonemm.Session.Tests;
|
|
|
|
public class AvailableStationsTests
|
|
{
|
|
private const string Countries = """
|
|
Germany: 14: 28: EU: 51.00: -10.00: -1.0: DL:
|
|
DL,DK,DJ;
|
|
Japan: 25: 45: AS: 36.40: -138.38: -9.0: JA:
|
|
JA,JH,JR;
|
|
United States: 05: 08: NA: 37.53: 91.67: 5.0: K:
|
|
K,W,N;
|
|
""";
|
|
|
|
private static readonly StationInfo Me = new()
|
|
{
|
|
Callsign = "DL1ABC",
|
|
CqZone = 14,
|
|
ItuZone = 28,
|
|
Continent = "EU",
|
|
CountryPrefix = "DL",
|
|
};
|
|
|
|
private static readonly Frequency On20 = Frequency.FromKilohertz(14_030);
|
|
|
|
private static (OperatingPosition Position, Bandmap Bandmap, AvailableStations Available) Station(
|
|
Contest? contest = null,
|
|
CallHistory? history = null)
|
|
{
|
|
FakeLogStore store = new();
|
|
ContestInstance instance = store.AddContest(new ContestInstance
|
|
{
|
|
ContestNumber = 0,
|
|
ContestName = "CQWW",
|
|
});
|
|
ContestSession session = new(
|
|
store,
|
|
contest ?? new CqWorldWide(ModeCategory.Cw),
|
|
instance,
|
|
Me,
|
|
CountryFile.Parse(Countries),
|
|
history);
|
|
OperatingPosition position = new(session);
|
|
Bandmap bandmap = new();
|
|
return (position, bandmap, new AvailableStations(position, bandmap));
|
|
}
|
|
|
|
private static Spot At(string call, Frequency where) =>
|
|
new(Callsign.Parse(call), where, DateTime.UtcNow, SpotSource.Cluster, "OK1TEST");
|
|
|
|
private static void Work(OperatingPosition position, string call, string zone, Frequency where)
|
|
{
|
|
position.Tune(where);
|
|
position.Entry.Call = call;
|
|
position.Entry.Set(ExchangeSlot.ReceivedReport, "599");
|
|
position.Entry.Set(ExchangeSlot.Zone, zone);
|
|
position.LogContact();
|
|
}
|
|
|
|
/// A mark saying a frequency is busy is not a station to work.
|
|
[Fact]
|
|
public void AMarkIsNotOffered()
|
|
{
|
|
(_, Bandmap bandmap, AvailableStations available) = Station();
|
|
bandmap.Add(Spot.Mark(On20, DateTime.UtcNow));
|
|
|
|
Assert.Empty(available.All());
|
|
}
|
|
|
|
[Fact]
|
|
public void ASpottedStationThatIsANewCountryIsAMultiplier()
|
|
{
|
|
(_, Bandmap bandmap, AvailableStations available) = Station();
|
|
bandmap.Add(At("JA1XYZ", On20));
|
|
|
|
AvailableStation station = Assert.Single(available.All());
|
|
Assert.True(station.IsMultiplier);
|
|
Assert.Equal(Bands.Band20M, station.Band);
|
|
Assert.Equal("JA", station.MultiplierText);
|
|
}
|
|
|
|
/// CQ WW counts the zone the station sends, not the one the country file
|
|
/// guesses, and a spot carries no exchange. So the zone shows only where
|
|
/// the call history file published it.
|
|
[Fact]
|
|
public void TheCallHistoryZoneBringsInTheZoneMultiplier()
|
|
{
|
|
CallHistory history = CallHistory.Parse("""
|
|
!!Order!!,Call,CQZone
|
|
JA1XYZ,25
|
|
""");
|
|
(_, Bandmap bandmap, AvailableStations available) = Station(history: history);
|
|
bandmap.Add(At("JA1XYZ", On20));
|
|
|
|
AvailableStation station = Assert.Single(available.All());
|
|
Assert.Equal("25, JA", station.MultiplierText);
|
|
}
|
|
|
|
[Fact]
|
|
public void AStationAlreadyWorkedOnThatBandIsLeftOut()
|
|
{
|
|
(OperatingPosition position, Bandmap bandmap, AvailableStations available) = Station();
|
|
Work(position, "JA1XYZ", "25", On20);
|
|
bandmap.Add(At("JA1XYZ", On20));
|
|
|
|
Assert.Empty(available.All());
|
|
}
|
|
|
|
[Fact]
|
|
public void TheSameStationOnAnotherBandIsStillWorthWorking()
|
|
{
|
|
(OperatingPosition position, Bandmap bandmap, AvailableStations available) = Station();
|
|
Work(position, "JA1XYZ", "25", On20);
|
|
bandmap.Add(At("JA1XYZ", Frequency.FromKilohertz(7_030)));
|
|
|
|
AvailableStation station = Assert.Single(available.All());
|
|
Assert.Equal(Bands.Band40M, station.Band);
|
|
Assert.True(station.IsMultiplier);
|
|
}
|
|
|
|
[Fact]
|
|
public void AStationThatBringsNoMultiplierIsStillOfferedForItsPoints()
|
|
{
|
|
(OperatingPosition position, Bandmap bandmap, AvailableStations available) = Station();
|
|
Work(position, "JA1XYZ", "25", On20);
|
|
bandmap.Add(At("JA2ABC", On20));
|
|
|
|
AvailableStation station = Assert.Single(available.All());
|
|
Assert.False(station.IsMultiplier);
|
|
Assert.True(station.Verdict.Points > 0);
|
|
}
|
|
|
|
[Fact]
|
|
public void MultipliersComeFirst()
|
|
{
|
|
(OperatingPosition position, Bandmap bandmap, AvailableStations available) = Station();
|
|
Work(position, "JA1XYZ", "25", On20);
|
|
bandmap.Add(At("JA2ABC", Frequency.FromKilohertz(14_010)));
|
|
bandmap.Add(At("W1AW", Frequency.FromKilohertz(14_040)));
|
|
|
|
Assert.Equal(
|
|
["W1AW", "JA2ABC"],
|
|
available.All().Select(s => s.Spot.Call.Text).ToList());
|
|
}
|
|
|
|
/// A spot carries no exchange, so a section contest can only judge a
|
|
/// spotted station where the call history file says what it sends.
|
|
[Fact]
|
|
public void TheCallHistoryFillsTheExchangeOfASpottedStation()
|
|
{
|
|
CallHistory history = CallHistory.Parse("""
|
|
!!Order!!,Call,Sect
|
|
W1AW,CT
|
|
""");
|
|
(_, Bandmap bandmap, AvailableStations available) =
|
|
Station(new Sweepstakes(ModeCategory.Cw), history);
|
|
bandmap.Add(At("W1AW", Frequency.FromKilohertz(14_080)));
|
|
|
|
AvailableStation station = Assert.Single(available.All());
|
|
Assert.True(station.IsMultiplier);
|
|
Assert.Equal("CT", station.MultiplierText);
|
|
}
|
|
|
|
[Fact]
|
|
public void WithNoCallHistoryASpottedStationOfASectionContestIsJustPoints()
|
|
{
|
|
(_, Bandmap bandmap, AvailableStations available) = Station(new Sweepstakes(ModeCategory.Cw));
|
|
bandmap.Add(At("W1AW", Frequency.FromKilohertz(14_080)));
|
|
|
|
AvailableStation station = Assert.Single(available.All());
|
|
Assert.False(station.IsMultiplier);
|
|
}
|
|
|
|
[Fact]
|
|
public void AStationInJapanIsToTheNortheastOfGermany()
|
|
{
|
|
(_, Bandmap bandmap, AvailableStations available) = Station();
|
|
bandmap.Add(At("JA1XYZ", On20));
|
|
|
|
AvailableStation station = Assert.Single(available.All());
|
|
Assert.InRange(station.Heading ?? -1, 1, 89);
|
|
}
|
|
}
|