Files
Nonemm/src/Nonemm.Contests/Rules/ArrlDx.cs
T
erikbrockoandClaude Opus 5 b5d9f1e21c Name the All Asian multiplier after what it counts
The score window and the stored Contest.Multiplier1Name row both said
"Prefixes" for an Asian entrant, which counts DXCC entities.

Contest.MultiplierNames is now MultiplierNamesFor(StationInfo me), the
same shape as ExchangeFieldsFor. Every other contest returns the same
list it did before; All Asian returns "Countries" from Asia and
"Prefixes" from everywhere else. ContestDefinitions.For takes the
station as well, because that name is written to the log for N1MM.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0157i7PiZyqBkquxS9A6FTdQ
2026-09-10 20:47:51 +00:00

97 lines
3.8 KiB
C#

using Nonemm.Contests.Multipliers;
using Nonemm.Core;
namespace Nonemm.Contests.Rules;
/// ARRL International DX, CW and SSB. W and VE stations work DX and nobody
/// else, so the exchange and the multiplier both depend on which side the
/// operator is on.
///
/// The received power or state goes in the section column, which is where N1MM
/// keeps it, so a log written by either program scores the same in the other.
public sealed class ArrlDx : Contest
{
private readonly ModeCategory mode;
public ArrlDx(ModeCategory mode) => this.mode = mode;
public string Name => mode == ModeCategory.Cw ? "ARRLDXCW" : "ARRLDXSSB";
public string DisplayName => $"ARRL International DX {ModeLabel()}";
public string CabrilloName => mode == ModeCategory.Cw ? "ARRL-DX-CW" : "ARRL-DX-SSB";
/// A W or VE operator copies the power the DX station sends, which goes in
/// the power column; a DX operator copies a state or province, which goes
/// in the section column. Both are where N1MM keeps them.
public IReadOnlyList<ExchangeField> ExchangeFieldsFor(StationInfo me) =>
[
new ExchangeField("Snt", ExchangeSlot.SentReport, ExchangeFieldKind.Report, IsRequired: false),
new ExchangeField("Rcv", ExchangeSlot.ReceivedReport, ExchangeFieldKind.Report),
IsNorthAmericanHome(me)
? new ExchangeField("Pwr", ExchangeSlot.Power, ExchangeFieldKind.Power)
: new ExchangeField("State", ExchangeSlot.Section, ExchangeFieldKind.UsStateOrCanadianProvince),
];
public IReadOnlyList<string> MultiplierNamesFor(StationInfo me) => ["Mults"];
public DupeScope DupeScope => DupeScope.PerBand;
public bool HasSerialNumbers => false;
public IReadOnlyList<ModeCategory> Modes => [mode];
public string SentExchangeFor(StationInfo me) =>
IsNorthAmericanHome(me) ? StateOrProvince(me) : me.Power;
/// Only contacts across the W/VE line count, so a DX station working DX or
/// a W station working W scores nothing.
public int PointsFor(QsoContext qso) =>
IsNorthAmericanHome(qso.Me) == IsNorthAmerican(qso.CountryPrefix) ? 0 : 3;
public IReadOnlyList<Multiplier> MultipliersFor(QsoContext qso)
{
if (PointsFor(qso) == 0)
{
return [];
}
string band = qso.Band?.Name ?? "";
if (IsNorthAmericanHome(qso.Me))
{
return qso.CountryPrefix.Length == 0 ? [] : [new Multiplier(1, qso.CountryPrefix, band)];
}
string received = StatesAndProvinces.ArrlDxArea(qso.Qso.Section);
return StatesAndProvinces.ArrlDxMultipliers.Contains(received)
? [new Multiplier(1, received, band)]
: [];
}
public int TotalScore(ScoreTally tally, ContestEntry entry) => tally.Points * tally.TotalMultipliers;
public CabrilloExchange CabrilloExchange(Qso qso, StationInfo me, ContestEntry entry) =>
new(
[
new CabrilloField(me.Callsign, 13),
new CabrilloField(qso.SentReport, 3),
new CabrilloField(IsNorthAmericanHome(me) ? StateOrProvince(me) : me.Power, 6),
],
[
new CabrilloField(qso.Call.Text, 13),
new CabrilloField(qso.ReceivedReport, 3),
new CabrilloField(IsNorthAmericanHome(me) ? qso.Power : qso.Section, 6),
]);
private static bool IsNorthAmericanHome(StationInfo me) => IsNorthAmerican(me.CountryPrefix);
/// The contest's W/VE side is the 48 states, DC and Canada; KH6 and KL7
/// count as DX for it.
private static bool IsNorthAmerican(string countryPrefix) =>
countryPrefix is "K" or "VE";
private static string StateOrProvince(StationInfo me) =>
me.State.Length > 0 ? me.State : me.Province;
private string ModeLabel() => mode == ModeCategory.Cw ? "CW" : "SSB";
}