Add the YOTA and OK/OM DX contests
Both are in the station's log and neither could be opened. The rules are written from the published ones and checked by replaying the log. YOTA scores a contact by the age the other operator sends: 13 points down to 10 for anyone 25 or under, whatever the continent, and 1 point or 3 for everyone else. Every age worked on a band is a multiplier. The 2024, 2025 and 2026 logs come out to the contact. OK/OM DX is the first contest whose exchange differs by the other station's country: a county from OK and OM stations, a serial number from everyone else, in the two columns N1MM keeps them in, and `SkipsField` walks the entry window past the box that does not apply. Points depend on which side the operator is on, and Czechia and Slovakia count as the two countries they are. The 2023 log comes out to the contact. The Cabrillo exchange now gets the entry, because YOTA sends an age that only the contest setup knows. Two differences are left in the log, both from the .udc files the operator used: their YOTA file only lists ages 7 to 25, so a younger operator scored as an adult, and one OK/OM log was made with the file for stations outside OK and OM while signing an OM call. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RoGtneMQaz4M9w7Kk49AVD
This commit is contained in:
75
tests/Nonemm.Contests.Tests/OkOmDxTests.cs
Normal file
75
tests/Nonemm.Contests.Tests/OkOmDxTests.cs
Normal file
@@ -0,0 +1,75 @@
|
||||
using Nonemm.Contests.Rules;
|
||||
using Nonemm.Core;
|
||||
using Nonemm.Core.Country;
|
||||
|
||||
namespace Nonemm.Contests.Tests;
|
||||
|
||||
public class OkOmDxTests
|
||||
{
|
||||
private static readonly Contest Ssb = new OkOmDx(ModeCategory.Phone);
|
||||
|
||||
private static ContestLog LogFor(StationInfo me) => new(Ssb, me, TestLog.CountryFile);
|
||||
|
||||
private static Qso FromOkOm(string call, string county, double kilohertz = 14_025) =>
|
||||
TestLog.Contact(call, kilohertz, mode: Modes.Usb, section: county);
|
||||
|
||||
private static Qso FromDx(string call, string number, double kilohertz = 14_025) =>
|
||||
TestLog.Contact(call, kilohertz, mode: Modes.Usb, exchange: number);
|
||||
|
||||
[Theory]
|
||||
[InlineData("OM3XYZ", 2)]
|
||||
[InlineData("OK1XYZ", 3)]
|
||||
public void AtHomeCzechiaAndSlovakiaAreTwoCountries(string call, int expected) =>
|
||||
Assert.Equal(expected, LogFor(TestLog.Slovakia).Judge(FromOkOm(call, "NOV")).Points);
|
||||
|
||||
[Theory]
|
||||
[InlineData("IK2XYZ", 3)]
|
||||
[InlineData("JA1XYZ", 5)]
|
||||
public void TheRestOfTheWorldIsScoredByContinent(string call, int expected) =>
|
||||
Assert.Equal(expected, LogFor(TestLog.Slovakia).Judge(FromDx(call, "014")).Points);
|
||||
|
||||
[Theory]
|
||||
[InlineData("OM3XYZ", 10)]
|
||||
[InlineData("DL9XYZ", 1)]
|
||||
[InlineData("IK2XYZ", 3)]
|
||||
[InlineData("JA1XYZ", 5)]
|
||||
public void AStationOutsideScoresTenForAnOkOmContact(string call, int expected) =>
|
||||
Assert.Equal(expected, LogFor(TestLog.Germany).Judge(FromOkOm(call, "NOV")).Points);
|
||||
|
||||
[Fact]
|
||||
public void CountriesAndCountiesBothCountOncePerBand()
|
||||
{
|
||||
ContestLog log = LogFor(TestLog.Slovakia);
|
||||
Assert.Equal(
|
||||
[1, 2],
|
||||
log.Judge(FromOkOm("OM3XYZ", "NOV")).NewMultipliers.Select(m => m.Index).ToList());
|
||||
log.Add(FromOkOm("OM3XYZ", "NOV"));
|
||||
Assert.Empty(log.Judge(FromOkOm("OM4XYZ", "NOV")).NewMultipliers);
|
||||
Assert.Single(log.Judge(FromOkOm("OM4XYZ", "PAR")).NewMultipliers);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AStationOutsideOkOmBringsItsCountryAndNoCounty() =>
|
||||
Assert.Equal(
|
||||
[1],
|
||||
LogFor(TestLog.Slovakia).Judge(FromDx("IK2XYZ", "014")).NewMultipliers
|
||||
.Select(m => m.Index)
|
||||
.ToList());
|
||||
|
||||
/// The entry window walks the county box for an OK or OM station and the
|
||||
/// serial box for everyone else.
|
||||
[Fact]
|
||||
public void OnlyOneOfTheTwoBoxesIsWalked()
|
||||
{
|
||||
IReadOnlyList<ExchangeField> fields = Ssb.ExchangeFieldsFor(TestLog.Slovakia);
|
||||
CountryLookup? okom = TestLog.CountryFile.Find("OM3XYZ");
|
||||
CountryLookup? dx = TestLog.CountryFile.Find("IK2XYZ");
|
||||
|
||||
Assert.Equal(
|
||||
[ExchangeSlot.ReceivedReport, ExchangeSlot.Exchange1],
|
||||
fields.Where(f => !Ssb.SkipsField(f, dx)).Select(f => f.Slot).ToList());
|
||||
Assert.Equal(
|
||||
[ExchangeSlot.ReceivedReport, ExchangeSlot.Section],
|
||||
fields.Where(f => !Ssb.SkipsField(f, okom)).Select(f => f.Slot).ToList());
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,10 @@ public static class TestLog
|
||||
PY,PP;
|
||||
Asiatic Russia: 17: 30: AS: 55.88: -84.10: -7.0: UA9:
|
||||
RM8,RM9,RM0,UA8,UA9,UA0,R8,R9,R0;
|
||||
Slovak Republic: 15: 28: EU: 48.67: -19.50: -1.0: OM:
|
||||
OM;
|
||||
Czech Republic: 15: 28: EU: 49.80: -15.47: -1.0: OK:
|
||||
OK,OL;
|
||||
""";
|
||||
|
||||
public static readonly CountryFile CountryFile = CountryFile.Parse(Countries);
|
||||
@@ -46,6 +50,16 @@ public static class TestLog
|
||||
ArrlSection = "CT",
|
||||
};
|
||||
|
||||
public static readonly StationInfo Slovakia = new()
|
||||
{
|
||||
Callsign = "OM5M",
|
||||
CqZone = 15,
|
||||
ItuZone = 28,
|
||||
Continent = "EU",
|
||||
CountryPrefix = "OM",
|
||||
County = "BRA",
|
||||
};
|
||||
|
||||
public static Qso Contact(
|
||||
string call,
|
||||
double kilohertz = 14_025,
|
||||
|
||||
49
tests/Nonemm.Contests.Tests/YotaTests.cs
Normal file
49
tests/Nonemm.Contests.Tests/YotaTests.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using Nonemm.Contests.Rules;
|
||||
using Nonemm.Core;
|
||||
|
||||
namespace Nonemm.Contests.Tests;
|
||||
|
||||
public class YotaTests
|
||||
{
|
||||
private static ContestLog LogFor(StationInfo me) => new(new Yota(), me, TestLog.CountryFile);
|
||||
|
||||
private static Qso Contact(string call, string age, double kilohertz = 14_025, Mode? mode = null) =>
|
||||
TestLog.Contact(call, kilohertz, mode: mode, exchange: age);
|
||||
|
||||
[Theory]
|
||||
[InlineData("9", 13)]
|
||||
[InlineData("12", 13)]
|
||||
[InlineData("13", 12)]
|
||||
[InlineData("16", 12)]
|
||||
[InlineData("17", 11)]
|
||||
[InlineData("21", 11)]
|
||||
[InlineData("22", 10)]
|
||||
[InlineData("25", 10)]
|
||||
[InlineData("26", 1)]
|
||||
public void AYoungOperatorIsWorthMore(string age, int expected) =>
|
||||
Assert.Equal(expected, LogFor(TestLog.Germany).Judge(Contact("IK2XYZ", age)).Points);
|
||||
|
||||
/// The age pays the same from anywhere; only the contacts with everyone
|
||||
/// else are scored by continent.
|
||||
[Fact]
|
||||
public void AgeBeatsTheContinent()
|
||||
{
|
||||
ContestLog log = LogFor(TestLog.Germany);
|
||||
Assert.Equal(13, log.Judge(Contact("JA1XYZ", "11")).Points);
|
||||
Assert.Equal(3, log.Judge(Contact("JA1XYZ", "44")).Points);
|
||||
Assert.Equal(1, log.Judge(Contact("IK2XYZ", "44")).Points);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AnAgeCountsOncePerBandWhateverTheMode()
|
||||
{
|
||||
ContestLog log = LogFor(TestLog.Germany);
|
||||
log.Add(Contact("IK2XYZ", "19"));
|
||||
Assert.Empty(log.Judge(Contact("DL9XYZ", "19", mode: Modes.Usb)).NewMultipliers);
|
||||
Assert.Single(log.Judge(Contact("DL9XYZ", "19", 7_025)).NewMultipliers);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AnExchangeThatIsNoAgeBringsNoMultiplier() =>
|
||||
Assert.Empty(LogFor(TestLog.Germany).Judge(Contact("IK2XYZ", "")).NewMultipliers);
|
||||
}
|
||||
Reference in New Issue
Block a user