Write N1MM's own Contest table rows for the built-in contests
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -153,7 +153,7 @@ public sealed partial class AppSession
|
||||
scoreSent = DateTime.UtcNow;
|
||||
ContestInstance instance = Logging.Instance;
|
||||
StationInfo me = Settings.Station.ToStationInfo();
|
||||
IReadOnlyList<string> multiplierNames = N1mmMultiplierNames.For(Logging.Contest, me);
|
||||
IReadOnlyList<string> multiplierNames = N1mmContestRows.MultiplierNames(Logging.Contest, me);
|
||||
List<ScoreReportRow> rows = ScoreBreakdown.For(Logging.Log.Qsos, Logging.Contest)
|
||||
.Select(r => new ScoreReportRow(r.Band, r.Mode, r.Qsos, r.Multipliers, r.Points))
|
||||
.ToList();
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
using Nonemm.Core;
|
||||
|
||||
namespace Nonemm.Contests;
|
||||
|
||||
/// What N1MM keeps in its `Contest` table for one contest. `Multipliers` are
|
||||
/// the internal names such as `ZN` and `Sect`, without the `N/A` entries.
|
||||
public sealed record N1mmContestRow(
|
||||
string DisplayName,
|
||||
string CabrilloName,
|
||||
string Mode,
|
||||
int DupeType,
|
||||
IReadOnlyList<string> Multipliers,
|
||||
int Period,
|
||||
int PointsPerContact,
|
||||
string CabrilloVersion);
|
||||
|
||||
/// The `Contest` table rows of the built-in contests, taken from a log N1MM
|
||||
/// wrote. N1MM reads this table when it opens a log, so a log written here
|
||||
/// carries N1MM's values rather than ones derived from our rules. The score
|
||||
/// broadcast names its multiplier types from the same rows.
|
||||
public static class N1mmContestRows
|
||||
{
|
||||
private static readonly Dictionary<string, N1mmContestRow> Known =
|
||||
new(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
["CQWWCW"] = new("CQ WorldWide CW", "CQ-WW-CW", "CW", 2, ["ZN", "CountryPrefix"], 2, 3, "3.0"),
|
||||
["CQWWSSB"] = new("CQ WorldWide SSB", "CQ-WW-SSB", "SSB", 2, ["ZN", "CountryPrefix"], 2, 3, "3.0"),
|
||||
["CQWWRTTY"] = new("CQ WorldWide RTTY", "CQ-WW-RTTY", "RTTY", 2, ["ZN", "CountryPrefix", "Sect"], 2, 3, "3.0"),
|
||||
["CQWPXCW"] = new("CQ WPX CW", "CQ-WPX-CW", "CW", 2, ["WPXPrefix"], 2, 2, "3.0"),
|
||||
["CQWPXSSB"] = new("CQ WPX SSB", "CQ-WPX-SSB", "SSB", 2, ["WPXPrefix"], 2, 2, "3.0"),
|
||||
["CQWPXRTTY"] = new("CQ WPX RTTY", "CQ-WPX-RTTY", "RTTY", 2, ["WPXPrefix"], 2, 2, "3.0"),
|
||||
["ARRLDXCW"] = new("ARRL DX CW", "ARRL-DX-CW", "CW", 2, ["Sect"], 2, 3, "3.0"),
|
||||
["ARRLDXSSB"] = new("ARRL DX SSB", "ARRL-DX-SSB", "SSB", 2, ["Sect"], 2, 3, "3.0"),
|
||||
["IARU"] = new("Internatl Amateur Radio Union HF Contest", "IARU-HF", "Both", 3, ["ZN", "HQ"], 2, 1, "3.0"),
|
||||
["SSCW"] = new("ARRL Sweepstakes CW (November)", "ARRL-SS-CW", "CW", 1, ["Sect"], 2, 2, "3.0"),
|
||||
["SSSSB"] = new("ARRL Sweepstakes SSB (November)", "ARRL-SS-SSB", "SSB", 1, ["Sect"], 2, 2, "3.0"),
|
||||
["WAECW"] = new("Worked All Europe - WAE CW", "DARC-WAEDC-CW", "CW", 3, ["CountryPrefix"], 1, 1, "3.0"),
|
||||
["WAESSB"] = new("Worked All Europe - WAE SSB", "DARC-WAEDC-SSB", "SSB", 3, ["CountryPrefix"], 1, 1, "3.0"),
|
||||
["WAERTTY"] = new("Worked All Europe - WAE RTTY", "DARC-WAEDC-RTTY", "RTTY", 3, ["CountryPrefix"], 1, 1, "3.0"),
|
||||
["ARRLRTTY"] = new("ARRL RTTY Roundup (January)", "ARRL-RTTY", "RTTY", 2, ["Sect", "CountryPrefix"], 1, 1, "3.0"),
|
||||
["NAQPCW"] = new("North American QSO Parties - CW", "NAQP-CW", "CW", 2, ["Sect", "NA"], 1, 1, "3.0"),
|
||||
["NAQPSSB"] = new("North American QSO Parties - SSB", "NAQP-SSB", "SSB", 2, ["Sect", "NA"], 1, 1, "3.0"),
|
||||
["NAQPRTTY"] = new("North American QSO Parties - RTTY", "NAQP-RTTY", "RTTY", 2, ["Sect", "NA"], 1, 1, "3.0"),
|
||||
["OKOMDX"] = new("Czech and Slovak Republics DX", "OK-OM-DX", "CW", 2, ["Sect"], 1, 1, "3.0"),
|
||||
["YOTA"] = new("YOTA Contest", "YOTA", "BOTH", 3, ["Exchange"], 2, 0, "3.0"),
|
||||
["IOTA"] = new("RSGB Islands On The Air Contest", "RSGB-IOTA", "Both", 3, ["Sect"], 1, 1, "3.0"),
|
||||
["EUDXC"] = new("EU DX Contest (not UDC)", "EUDXC", "Both", 3, ["Sect", "CountryPrefix"], 1, 1, "3.0"),
|
||||
["CQ160CW"] = new("CQ World-Wide 160 Meter DX Contest - CW", "CQ-160-CW", "CW", 1, ["StateProvince", "CountryPrefix"], 2, 1, "3.0"),
|
||||
["CQ160SSB"] = new("CQ World-Wide 160 Meter DX Contest - Phone", "CQ-160-SSB", "SSB", 1, ["StateProvince", "CountryPrefix"], 2, 1, "3.0"),
|
||||
["XERTTY"] = new("Mexico RTTY Contest", "XE-RTTY", "RTTY", 2, ["Countryprefix", "Sect"], 1, 1, "3.0"),
|
||||
["REFCW"] = new("French REF DX contest - CW", "REF-CW", "CW", 2, ["Sect", "CountryPrefix"], 1, 1, "3.0"),
|
||||
["REFSSB"] = new("French REF DX contest - SSB", "REF-SSB", "SSB", 2, ["Sect", "CountryPrefix"], 1, 1, "3.0"),
|
||||
["UKRAINDX"] = new("UKRAINIAN DX", "UKRAINIAN-DX", "BOTH", 3, ["CountryPrefix", "Sect"], 1, 1, "3.0"),
|
||||
["BARTGRTTYS"] = new("BARTG RTTY Sprint contest (January)", "BARTG-SPRINT", "RTTY", 2, ["CountryPrefix", "Sect", "Continent"], 2, 1, "3.0"),
|
||||
["ARRL10M"] = new("ARRL 10 Meter Contest", "ARRL-10", "Both", 3, ["StateProvince", "CountryPrefix"], 2, 1, "3.0"),
|
||||
["RUSDXRTTY"] = new("Russian DX RTTY", "RADIO-WW-RTTY", "RTTY", 2, ["CountryPrefix", "Sect"], 1, 1, "3.0"),
|
||||
["RDAC"] = new("Russian District Award Contest", "RDAC", "Both", 3, ["CountryPrefix", "Sect"], 1, 1, "3.0"),
|
||||
["YOHFDX"] = new("Romanian Amateur Radio Federation - YO DX HF", "YO-DX-HF", "Both", 3, ["CountryPrefix", "Sect"], 1, 1, "3.0"),
|
||||
["OCEANIACW"] = new("Oceania DX CW", "Oceania-DX-CW", "CW", 2, ["WPXPrefix"], 2, 2, "3.0"),
|
||||
["OCEANIASSB"] = new("Oceania DX SSB", "Oceania-DX-SSB", "SSB", 2, ["WPXPrefix"], 2, 2, "3.0"),
|
||||
["FDREG1"] = new("Internatl Amateur Radio Union, Region 1 Field Day", "FIELDDAY-REGION-1", "Both", 2, ["CountryPrefix"], 1, 1, "3.0"),
|
||||
["SARTGRTTY"] = new("Scandinavian Amateur Radio, WorldWide RTTY", "SARTG-RTTY", "RTTY", 2, ["CountryPrefix", "Sect"], 2, 1, "3.0"),
|
||||
["ALLASIACW"] = new("All Asian DX contest CW", "AADX-CW", "CW", 2, ["WPXPrefix"], 2, 1, "3.0"),
|
||||
["ALLASIASSB"] = new("All Asian DX contest SSB", "AADX-SSB", "SSB", 2, ["WPXPrefix"], 2, 1, "3.0"),
|
||||
["DX"] = new("General Logging", "DX", "Both", 3, ["CountryPrefix"], 32000, 1, "3.0"),
|
||||
};
|
||||
|
||||
public static N1mmContestRow? Find(string name) =>
|
||||
Known.TryGetValue(name, out N1mmContestRow? row) ? row : null;
|
||||
|
||||
/// A contest not in the table gets the names its rules give.
|
||||
public static IReadOnlyList<string> MultiplierNames(Contest contest, StationInfo me) =>
|
||||
Find(contest.Name)?.Multipliers ?? contest.MultiplierNamesFor(me);
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
using Nonemm.Core;
|
||||
|
||||
namespace Nonemm.Contests;
|
||||
|
||||
/// The multiplier names N1MM keeps in the `Contest` table, such as `ZN`,
|
||||
/// `CountryPrefix` and `Sect`. The score broadcast names its multiplier types
|
||||
/// from them, and a contest's own `MultiplierNamesFor` holds the names the
|
||||
/// score window shows instead (`Zones`, `Countries`). Taken from a log N1MM
|
||||
/// wrote, without the `N/A` entries.
|
||||
public static class N1mmMultiplierNames
|
||||
{
|
||||
private static readonly Dictionary<string, IReadOnlyList<string>> Known =
|
||||
new(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
["CQWWCW"] = ["ZN", "CountryPrefix"],
|
||||
["CQWWSSB"] = ["ZN", "CountryPrefix"],
|
||||
["CQWWRTTY"] = ["ZN", "CountryPrefix", "Sect"],
|
||||
["CQWPXCW"] = ["WPXPrefix"],
|
||||
["CQWPXSSB"] = ["WPXPrefix"],
|
||||
["CQWPXRTTY"] = ["WPXPrefix"],
|
||||
["ARRLDXCW"] = ["Sect"],
|
||||
["ARRLDXSSB"] = ["Sect"],
|
||||
["IARU"] = ["ZN", "HQ"],
|
||||
["SSCW"] = ["Sect"],
|
||||
["SSSSB"] = ["Sect"],
|
||||
["WAECW"] = ["CountryPrefix"],
|
||||
["WAESSB"] = ["CountryPrefix"],
|
||||
["WAERTTY"] = ["CountryPrefix"],
|
||||
["ARRLRTTY"] = ["Sect", "CountryPrefix"],
|
||||
["NAQPCW"] = ["Sect", "NA"],
|
||||
["NAQPSSB"] = ["Sect", "NA"],
|
||||
["NAQPRTTY"] = ["Sect", "NA"],
|
||||
["OKOMDX"] = ["Sect"],
|
||||
["YOTA"] = ["Exchange"],
|
||||
["IOTA"] = ["Sect"],
|
||||
["EUDXC"] = ["Sect", "CountryPrefix"],
|
||||
["CQ160CW"] = ["StateProvince", "CountryPrefix"],
|
||||
["CQ160SSB"] = ["StateProvince", "CountryPrefix"],
|
||||
["XERTTY"] = ["Countryprefix", "Sect"],
|
||||
["REFCW"] = ["Sect", "CountryPrefix"],
|
||||
["REFSSB"] = ["Sect", "CountryPrefix"],
|
||||
["UKRAINDX"] = ["CountryPrefix", "Sect"],
|
||||
["BARTGRTTYS"] = ["CountryPrefix", "Sect", "Continent"],
|
||||
["ARRL10M"] = ["StateProvince", "CountryPrefix"],
|
||||
["RUSDXRTTY"] = ["CountryPrefix", "Sect"],
|
||||
["RDAC"] = ["CountryPrefix", "Sect"],
|
||||
["YOHFDX"] = ["CountryPrefix", "Sect"],
|
||||
["OCEANIACW"] = ["WPXPrefix"],
|
||||
["OCEANIASSB"] = ["WPXPrefix"],
|
||||
["FDREG1"] = ["CountryPrefix"],
|
||||
["SARTGRTTY"] = ["CountryPrefix", "Sect"],
|
||||
["ALLASIACW"] = ["WPXPrefix"],
|
||||
["ALLASIASSB"] = ["WPXPrefix"],
|
||||
["DX"] = ["CountryPrefix"],
|
||||
};
|
||||
|
||||
/// A contest not in the table gets the names its rules give.
|
||||
public static IReadOnlyList<string> For(Contest contest, StationInfo me) =>
|
||||
Known.TryGetValue(contest.Name, out IReadOnlyList<string>? names)
|
||||
? names
|
||||
: contest.MultiplierNamesFor(me);
|
||||
}
|
||||
@@ -5,12 +5,30 @@ using Nonemm.Storage;
|
||||
namespace Nonemm.Session;
|
||||
|
||||
/// Turns a contest's rules into the definition row N1MM keeps in the `Contest`
|
||||
/// table, which it reads when it opens a log.
|
||||
/// table, which it reads when it opens a log. A built-in contest takes N1MM's
|
||||
/// own row; any other is worked out from its rules.
|
||||
public static class ContestDefinitions
|
||||
{
|
||||
public static ContestDefinition For(Contest contest, StationInfo me)
|
||||
{
|
||||
IReadOnlyList<string> mults = N1mmMultiplierNames.For(contest, me);
|
||||
if (N1mmContestRows.Find(contest.Name) is { } row)
|
||||
{
|
||||
return new ContestDefinition
|
||||
{
|
||||
Name = contest.Name,
|
||||
DisplayName = row.DisplayName,
|
||||
CabrilloName = row.CabrilloName,
|
||||
Mode = row.Mode,
|
||||
DupeType = row.DupeType,
|
||||
Multiplier1Name = NameAt(row.Multipliers, 0),
|
||||
Multiplier2Name = NameAt(row.Multipliers, 1),
|
||||
Multiplier3Name = NameAt(row.Multipliers, 2),
|
||||
Period = row.Period,
|
||||
PointsPerContact = row.PointsPerContact,
|
||||
CabrilloVersion = row.CabrilloVersion,
|
||||
};
|
||||
}
|
||||
IReadOnlyList<string> mults = contest.MultiplierNamesFor(me);
|
||||
return new ContestDefinition
|
||||
{
|
||||
Name = contest.Name,
|
||||
|
||||
Reference in New Issue
Block a user