Files
Nonemm/tests/Nonemm.Contests.Tests/CqWpxTests.cs
ericek111 04568d0ca3 Read the rest of what a .udc file says, and score what N1MM scores
Two pieces of work on the scoring engine.

The .udc reader now takes N1MM's published scoring vocabulary: the full
PointsPerContact condition set, the PointsMultBy family, PowerMult, BonusPoints,
the multiplier sources and the settings that say which stations bring a
multiplier in. MultMult is a weight rather than a switch, as in N1MM's
ComputeScore. The entry categories and the sent exchange reach the rules in a
new ContestEntry, so a contest can score by the power category it is entered in
or by what this station sends.

Then every contest in a real N1MM log was scored again from these rules and
compared with the points and multiplier flags N1MM wrote. That found five bugs:
ARRL DX and IARU read the exchange from the wrong column, a stored " " was read
as a value rather than as empty, CQ WW RTTY's own Canadian area names were not
counted, a maritime mobile scored nothing, and a contact in a mode the contest
does not run scored as if it were in the contest.

docs/n1mm-interop.md has the check and what still differs.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RoGtneMQaz4M9w7Kk49AVD
2026-08-31 08:33:40 +00:00

82 lines
2.8 KiB
C#

using Nonemm.Contests.Rules;
using Nonemm.Core;
namespace Nonemm.Contests.Tests;
public class CqWpxTests
{
private static ContestLog LogFor(StationInfo me, ModeCategory mode = ModeCategory.Cw) =>
new(new CqWpx(mode), me, TestLog.CountryFile);
[Theory]
[InlineData(14_025, 3)]
[InlineData(21_025, 3)]
[InlineData(7_025, 6)]
[InlineData(3_525, 6)]
public void DifferentContinentDoublesBelowFourteenMegahertz(double kilohertz, int expected)
{
ContestLog log = LogFor(TestLog.Germany);
Assert.Equal(expected, log.Judge(TestLog.Contact("JA1XYZ", kilohertz)).Points);
}
[Fact]
public void SameContinentScoresOneOnTheHighBands()
{
ContestLog log = LogFor(TestLog.Germany);
Assert.Equal(1, log.Judge(TestLog.Contact("IK2XYZ")).Points);
Assert.Equal(2, log.Judge(TestLog.Contact("IK2XYZ", 7_025)).Points);
}
[Fact]
public void NorthAmericansScoreDoubleWithinNorthAmerica()
{
ContestLog log = LogFor(TestLog.UnitedStates);
Assert.Equal(2, log.Judge(TestLog.Contact("VE3XYZ")).Points);
Assert.Equal(4, log.Judge(TestLog.Contact("VE3XYZ", 7_025)).Points);
}
[Fact]
public void OwnCountryScoresOneOnEveryBand()
{
ContestLog log = LogFor(TestLog.Germany);
Assert.Equal(1, log.Judge(TestLog.Contact("DL9XYZ")).Points);
Assert.Equal(1, log.Judge(TestLog.Contact("DL9XYZ", 3_525)).Points);
}
[Fact]
public void RttyScoresOwnCountryTwiceOnTheLowBands()
{
ContestLog log = LogFor(TestLog.Germany, ModeCategory.Digital);
Assert.Equal(1, log.Judge(TestLog.Contact("DL9XYZ", mode: Modes.Rtty)).Points);
Assert.Equal(2, log.Judge(TestLog.Contact("DL9XYZ", 3_525, Modes.Rtty)).Points);
}
[Fact]
public void PrefixCountsOnceForTheWholeContest()
{
ContestLog log = LogFor(TestLog.Germany);
log.Add(TestLog.Contact("JA1XYZ"));
Assert.Empty(log.Judge(TestLog.Contact("JA1ZZZ", 7_025)).NewMultipliers);
Assert.Single(log.Judge(TestLog.Contact("JA2ZZZ", 7_025)).NewMultipliers);
}
[Fact]
public void MaritimeMobileBringsNoPrefix()
{
ContestLog log = LogFor(TestLog.Germany);
Assert.Empty(log.Judge(TestLog.Contact("DL1ABC/MM")).NewMultipliers);
}
/// A tuning carrier logged by accident, or any contact in a mode the
/// contest does not run, scores nothing. The prefix still counts, which is
/// what N1MM logs.
[Fact]
public void AContactInAnotherModeScoresNothingAndKeepsItsMultiplier()
{
ContestLog log = new(new CqWpx(ModeCategory.Phone), TestLog.Germany, TestLog.CountryFile);
Verdict verdict = log.Judge(TestLog.Contact("IK2XYZ", mode: Modes.Rtty, number: 5));
Assert.Equal(0, verdict.Points);
Assert.Single(verdict.NewMultipliers);
}
}