using Nonemm.Contests.Multipliers; using Nonemm.Core; using Nonemm.Core.Country; namespace Nonemm.Contests.Rules; /// The CQ 160 metre contest, CW and phone. One band, so nothing is counted per /// band: the multipliers are the states, provinces and countries worked, and /// the points are 2 inside your own country, 5 on your own continent and 10 /// from another. /// /// A US or Canadian station sends a state or province, which N1MM keeps in the /// section column; everyone else sends a CQ zone, which it keeps in the /// exchange column. public sealed class CqOneSixty : Contest { private readonly ModeCategory mode; public CqOneSixty(ModeCategory mode) => this.mode = mode; public string Name => mode == ModeCategory.Cw ? "CQ160CW" : "CQ160SSB"; public string DisplayName => $"CQ World-Wide 160 Metre {ModeLabel()}"; public string CabrilloName => mode == ModeCategory.Cw ? "CQ-160-CW" : "CQ-160-SSB"; /// One box takes the state, province or CQ zone the other station sends, /// as N1MM has it. public IReadOnlyList ExchangeFieldsFor(StationInfo me) => [ new ExchangeField("Snt", ExchangeSlot.SentReport, ExchangeFieldKind.Report, IsRequired: false), new ExchangeField("Rcv", ExchangeSlot.ReceivedReport, ExchangeFieldKind.Report), new ExchangeField("Exch", ExchangeSlot.Exchange1, ExchangeFieldKind.Text) { Width = 6 }, ]; /// A number is a CQ zone and stays in the exchange column; anything else /// is a state or province and goes in the section column as well. public Qso FromExchange1(Qso qso, string typed) => int.TryParse(typed, out _) ? qso with { Section = "" } : qso with { Section = typed.Trim().ToUpperInvariant() }; public IReadOnlyList MultiplierNamesFor(StationInfo me) => ["States", "Countries"]; public DupeScope DupeScope => DupeScope.Once; public bool HasSerialNumbers => false; public IReadOnlyList Modes => [mode]; public string SentExchangeFor(StationInfo me) => IsUsOrCanadian(me.CountryPrefix) ? me.State.Length > 0 ? me.State : me.Province : me.CqZone.ToString(); public int PointsFor(QsoContext qso) => qso.IsSameCountry ? 2 : qso.IsSameContinent ? 5 : 10; public IReadOnlyList MultipliersFor(QsoContext qso) { List found = []; string area = StatesAndProvinces.ArrlDxArea(qso.Qso.Section); if (StatesAndProvinces.ArrlDxMultipliers.Contains(area)) { found.Add(new Multiplier(1, area, "")); } if (qso.CountryPrefix.Length > 0) { found.Add(new Multiplier(2, qso.CountryPrefix, "")); } return found; } 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(SentExchangeFor(me), 6), ], [ new CabrilloField(qso.Call.Text, 13), new CabrilloField(qso.ReceivedReport, 3), new CabrilloField(qso.Section.Length > 0 ? qso.Section : qso.Exchange1, 6), ]); private static bool IsUsOrCanadian(string countryPrefix) => countryPrefix is "K" or "VE"; private string ModeLabel() => mode == ModeCategory.Cw ? "CW" : "SSB"; }