using Nonemm.Core; namespace Nonemm.Contests.Rules; /// The JARL All Asian DX contest. It is two contests in one. A station /// outside Asia works Asia only, and counts the WPX prefix of each Asian /// station once per band. An Asian station works everybody except its own /// country, counts countries instead of prefixes, and is paid three times the /// band value for a contact outside Asia. public sealed class AllAsian : Contest { private readonly ModeCategory mode; public AllAsian(ModeCategory mode) => this.mode = mode; public string Name => mode == ModeCategory.Cw ? "ALLASIACW" : "ALLASIASSB"; public string DisplayName => $"All Asian DX {ModeLabel()}"; public string CabrilloName => mode == ModeCategory.Cw ? "AADX-CW" : "AADX-SSB"; public IReadOnlyList ExchangeFieldsFor(StationInfo me) => [ new ExchangeField("Snt", ExchangeSlot.SentReport, ExchangeFieldKind.Report, IsRequired: false), new ExchangeField("Rcv", ExchangeSlot.ReceivedReport, ExchangeFieldKind.Report), new ExchangeField("Age", ExchangeSlot.Exchange1, ExchangeFieldKind.Number) { Width = 3 }, ]; public IReadOnlyList MultiplierNamesFor(StationInfo me) => me.Continent == "AS" ? ["Countries"] : ["Prefixes"]; public DupeScope DupeScope => DupeScope.PerBand; public bool HasSerialNumbers => false; public IReadOnlyList Modes => [mode]; public string SentExchangeFor(StationInfo me) => ""; public int PointsFor(QsoContext qso) { if (!IsWorkable(qso)) { return 0; } bool treble = qso.Me.Continent == "AS" && qso.Continent != "AS" && !qso.Qso.Call.IsMaritimeMobile; return PointsOn(qso.Band) * (treble ? 3 : 1); } public IReadOnlyList MultipliersFor(QsoContext qso) { if (!IsWorkable(qso) || qso.Qso.Call.IsMaritimeMobile) { return []; } string? value = qso.Me.Continent == "AS" ? qso.CountryPrefix : qso.Qso.Call.WpxPrefix(); return string.IsNullOrEmpty(value) ? [] : [new Multiplier(1, value, qso.Band?.Name ?? "")]; } 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(entry.SentExchange, 3), ], [ new CabrilloField(qso.Call.Text, 13), new CabrilloField(qso.ReceivedReport, 3), new CabrilloField(qso.Exchange1, 3), ]); /// An Asian station works anybody outside its own country. Everybody else /// works Asia only, and a maritime mobile is not one of them: a station at /// sea makes a valid contact with an Asian station alone. public bool IsWorkable(QsoContext qso) => qso.Me.Continent == "AS" ? !qso.IsSameCountry : qso.Continent == "AS" && !qso.Qso.Call.IsMaritimeMobile; /// 160 metres is worth 3, 80 and 10 metres 2, and every other band 1. An /// Asian entrant works from the same table and trebles it outside Asia, /// except for a maritime mobile, which pays the Asian rate wherever it is. private static int PointsOn(Band? band) => band?.Name switch { "160M" => 3, "80M" or "10M" => 2, null => 0, _ => 1, }; private string ModeLabel() => mode == ModeCategory.Cw ? "CW" : "SSB"; }