The score summary now splits the way N1MM's does. `ContestLog` keeps a tally per band, and per kind of row where the contest has kinds, and the score window reads those instead of adding the rows up itself. Three things were wrong with the old sum: - The band rows counted a multiplier as one whatever the band. WAE weights it by band — `ScoreRow.AddContact` adds four on 3.5, three on 7 and two on 14, 21 and 28 — so the band rows did not add up to the total. - The band rows counted contacts left out of the claimed score. - There was no split by kind. `CWAE.LogInfo` and `ScoreClass.Description` give WAE a `Q/QTC` column and a row per band and kind, so contacts, traffic sent and traffic received are read apart. The Cabrillo writer now pads the record name to seven characters, which is what `ConvertCabrilloStructStdToString` does and why: `X-QSO:` is six characters and a space, so every record name puts the frequency in the same column. Nonemm wrote five, and the `X-QSO:` lines added last commit did not line up with the rest. WAE's own layouts follow `CWAE.CabrilloString`: three spaces after the sent serial rather than the one every other column gets, and the transmitter column only for a multi-operator entry. `QtcTraffic.ToSend` no longer offers a contact marked as a dupe, which is what `DBSupport.QTCRecordsetCount` leaves out with `Trim(ContactType) = ''`. Checked by running the program against a WAE SSB log of six contacts and a series of ten received: the band rows read 4, 3, 2 and 2 and add up to the 11 in the total row. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015NZkFxHde1iifAQemFTHxf
193 lines
6.8 KiB
C#
193 lines
6.8 KiB
C#
using Nonemm.Contests.Rules;
|
|
using Nonemm.Core;
|
|
|
|
namespace Nonemm.Contests.Tests;
|
|
|
|
public class WaeTests
|
|
{
|
|
private static readonly Wae Cw = new(ModeCategory.Cw);
|
|
private static readonly Wae Rtty = new(ModeCategory.Digital);
|
|
|
|
private static ContestLog LogFor(Contest contest, StationInfo me) =>
|
|
new(contest, me, TestLog.CountryFile);
|
|
|
|
private static Qso On(string call, double kilohertz, Mode? mode = null) =>
|
|
TestLog.Contact(call, kilohertz: kilohertz, mode: mode ?? Modes.Cw, exchange: WaeQtc.Contact);
|
|
|
|
[Fact]
|
|
public void EveryContactOnAContestBandIsOnePoint()
|
|
{
|
|
ContestLog log = LogFor(Cw, TestLog.Germany);
|
|
Assert.Equal(1, log.Judge(On("JA1XYZ", 14_025)).Points);
|
|
}
|
|
|
|
/// WAE does not run on the WARC bands.
|
|
[Fact]
|
|
public void AContactOnAWarcBandScoresNothing()
|
|
{
|
|
ContestLog log = LogFor(Cw, TestLog.Germany);
|
|
Assert.Equal(0, log.Judge(On("JA1XYZ", 18_080)).Points);
|
|
}
|
|
|
|
[Fact]
|
|
public void EuropeDoesNotWorkEuropeOnCw()
|
|
{
|
|
ContestLog log = LogFor(Cw, TestLog.Germany);
|
|
Verdict verdict = log.Judge(On("IK2XYZ", 14_025));
|
|
|
|
Assert.Equal(0, verdict.Points);
|
|
Assert.Empty(verdict.NewMultipliers);
|
|
}
|
|
|
|
[Fact]
|
|
public void OnRttyEverybodyWorksEverybody()
|
|
{
|
|
ContestLog log = LogFor(Rtty, TestLog.Germany);
|
|
Verdict verdict = log.Judge(On("IK2XYZ", 14_080, Modes.Rtty));
|
|
|
|
Assert.Equal(1, verdict.Points);
|
|
Assert.Single(verdict.NewMultipliers);
|
|
}
|
|
|
|
/// A multiplier is worth four on 80 metres, three on 40 and two higher up.
|
|
[Theory]
|
|
[InlineData(3_530, 4)]
|
|
[InlineData(7_030, 3)]
|
|
[InlineData(14_030, 2)]
|
|
[InlineData(21_030, 2)]
|
|
[InlineData(28_030, 2)]
|
|
public void AMultiplierIsWorthMoreOnTheLowBands(double kilohertz, int weight)
|
|
{
|
|
ContestLog log = LogFor(Cw, TestLog.Germany);
|
|
Multiplier multiplier = Assert.Single(log.Judge(On("JA1XYZ", kilohertz)).NewMultipliers);
|
|
|
|
Assert.Equal(weight, multiplier.Weight);
|
|
Assert.Equal("JA1", multiplier.Value);
|
|
}
|
|
|
|
[Fact]
|
|
public void TheWeightGoesIntoTheScore()
|
|
{
|
|
ContestLog log = LogFor(Cw, TestLog.Germany);
|
|
log.Add(On("JA1XYZ", 3_530));
|
|
|
|
Assert.Equal(1, log.Tally.Points);
|
|
Assert.Equal(4, log.Tally.TotalMultipliers);
|
|
Assert.Equal(4, log.TotalScore);
|
|
}
|
|
|
|
/// The countries with call areas count each area separately.
|
|
[Theory]
|
|
[InlineData("K1ABC", "K1")]
|
|
[InlineData("W6XYZ", "K6")]
|
|
[InlineData("JA1XYZ", "JA1")]
|
|
[InlineData("PY2ABC", "PY2")]
|
|
public void ACallAreaIsAMultiplierOfItsOwn(string call, string expected)
|
|
{
|
|
ContestLog log = LogFor(Cw, TestLog.Germany);
|
|
Multiplier multiplier = Assert.Single(log.Judge(On(call, 14_025)).NewMultipliers);
|
|
|
|
Assert.Equal(expected, multiplier.Value);
|
|
}
|
|
|
|
/// Asiatic Russia goes by the call area digit whatever the prefix on the
|
|
/// air, so RM0W and UA0AB are the same multiplier.
|
|
[Theory]
|
|
[InlineData("RM0W")]
|
|
[InlineData("UA0AB")]
|
|
public void AsiaticRussiaCountsByCallArea(string call)
|
|
{
|
|
ContestLog log = LogFor(Cw, TestLog.Germany);
|
|
Multiplier multiplier = Assert.Single(log.Judge(On(call, 14_025)).NewMultipliers);
|
|
|
|
Assert.Equal("UA0", multiplier.Value);
|
|
}
|
|
|
|
/// A callsign the country file cannot place still counts, with an empty
|
|
/// value, so the log scores the same here as in N1MM. All the unplaceable
|
|
/// calls worked on a band share the one multiplier between them.
|
|
[Fact]
|
|
public void ACallWithNoCountryCountsOncePerBand()
|
|
{
|
|
ContestLog log = LogFor(Cw, TestLog.Germany);
|
|
Assert.Equal("", Assert.Single(log.Judge(On("D1M", 14_025)).NewMultipliers).Value);
|
|
log.Add(On("D1M", 14_025));
|
|
Assert.Empty(log.Judge(On("D2X", 14_025)).NewMultipliers);
|
|
}
|
|
|
|
/// N1MM's score window gives contacts, traffic sent and traffic received a
|
|
/// row of their own on every band, and the multipliers in a band row carry
|
|
/// that band's weight: four on 80, three on 40, two on 20, 15 and 10.
|
|
[Fact]
|
|
public void TheScoreSplitsByBandAndByKindOfRow()
|
|
{
|
|
ContestLog log = LogFor(Cw, TestLog.Germany);
|
|
log.Add(On("JA1XYZ", 3_525));
|
|
log.Add(On("K1ABC", 14_025));
|
|
log.Add(new WaeQtc(
|
|
Callsign.Parse("JA1XYZ"), IsSent: false, 1, 10, "1435", Callsign.Parse("W1AW"), 42)
|
|
.ApplyTo(On("JA1XYZ", 3_525)));
|
|
|
|
Assert.Equal(4, log.Rows[new ScoreKey("80M", WaeQtc.Contact)].TotalMultipliers);
|
|
Assert.Equal(1, log.Rows[new ScoreKey("80M", WaeQtc.Contact)].Points);
|
|
Assert.Equal(2, log.Rows[new ScoreKey("20M", WaeQtc.Contact)].TotalMultipliers);
|
|
|
|
ScoreTally traffic = log.Rows[new ScoreKey("80M", WaeQtc.Received)];
|
|
Assert.Equal(1, traffic.Qsos);
|
|
Assert.Equal(1, traffic.Points);
|
|
Assert.Equal(0, traffic.TotalMultipliers);
|
|
|
|
Assert.Equal(log.Tally.Points, log.Rows.Values.Sum(r => r.Points));
|
|
Assert.Equal(log.Tally.TotalMultipliers, log.Rows.Values.Sum(r => r.TotalMultipliers));
|
|
}
|
|
|
|
[Fact]
|
|
public void AQtcIsAPointAndNothingElse()
|
|
{
|
|
ContestLog log = LogFor(Rtty, TestLog.Germany);
|
|
Qso qtc = new WaeQtc(
|
|
Callsign.Parse("JA1XYZ"), IsSent: true, 1, 10, "1435", Callsign.Parse("DL9XYZ"), 42)
|
|
.ApplyTo(On("JA1XYZ", 14_080, Modes.Rtty));
|
|
|
|
Verdict verdict = log.Judge(qtc);
|
|
Assert.Equal(1, verdict.Points);
|
|
Assert.Empty(verdict.NewMultipliers);
|
|
}
|
|
|
|
/// The station is worked once and then reported to ten times over; those
|
|
/// rows must not read as dupes of the contact.
|
|
[Fact]
|
|
public void QtcTrafficWithAStationAlreadyWorkedIsNotADupe()
|
|
{
|
|
ContestLog log = LogFor(Rtty, TestLog.Germany);
|
|
log.Add(On("JA1XYZ", 14_080, Modes.Rtty));
|
|
Qso qtc = new WaeQtc(
|
|
Callsign.Parse("JA1XYZ"), IsSent: true, 1, 10, "1435", Callsign.Parse("DL9XYZ"), 42)
|
|
.ApplyTo(On("JA1XYZ", 14_080, Modes.Rtty));
|
|
|
|
Assert.False(log.Judge(qtc).IsDupe);
|
|
log.Add(qtc);
|
|
Assert.Equal(2, log.Tally.Points);
|
|
Assert.Equal(2, log.Tally.TotalMultipliers);
|
|
}
|
|
|
|
[Fact]
|
|
public void AQtcGoesIntoTheLogTheWayN1mmKeepsIt()
|
|
{
|
|
WaeQtc qtc = new(
|
|
Callsign.Parse("H2X"), IsSent: true, 9, 10, "0107", Callsign.Parse("OH1SIC"), 7);
|
|
Qso row = qtc.ApplyTo(On("H2X", 14_099, Modes.Rtty));
|
|
|
|
Assert.Equal("SQTC", row.Exchange1);
|
|
Assert.Equal("9/10", row.MiscText);
|
|
Assert.Equal("0107", row.SentReport);
|
|
Assert.Equal("OH1SIC", row.ReceivedReport);
|
|
Assert.Equal(7, row.SentNumber);
|
|
Assert.Equal(qtc, WaeQtc.From(row));
|
|
}
|
|
|
|
[Fact]
|
|
public void AnOrdinaryContactIsNotAQtc() =>
|
|
Assert.Null(WaeQtc.From(On("JA1XYZ", 14_025)));
|
|
}
|