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 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 MultiplierNamesFor(StationInfo me) => ["Mults"]; public DupeScope DupeScope => DupeScope.PerBand; public bool HasSerialNumbers => false; public IReadOnlyList 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 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"; }