using Nonemm.Core; namespace Nonemm.Contests.Rules; /// The BARTG RTTY contest. Every contact is one point. The multipliers are the /// countries and the US and Canadian call areas once per band, and the /// continents once in the contest; the score is the points times the countries /// and areas together, times the continents. /// /// The exchange is a report, a serial number and the time the exchange was /// sent. The time this station sends is stamped into the `MiscText` column as /// the message goes out, which is the column N1MM keeps it in. /// /// The rules are N1MM's `CBARTGSpring`, the March HF contest the station has /// logs of. N1MM's September sprint is a class of its own with a shorter /// exchange, and both of N1MM's names for these two contests open a log here /// with the rules below. public sealed class BartgSprint : Contest { public string Name => "BARTGRTTYS"; public string DisplayName => "BARTG RTTY Sprint"; public string CabrilloName => "BARTG-SPRINT"; public IReadOnlyList ExchangeFieldsFor(StationInfo me) => [ new ExchangeField("Snt", ExchangeSlot.SentReport, ExchangeFieldKind.Report, IsRequired: false), new ExchangeField("SentNr", ExchangeSlot.SentNumber, ExchangeFieldKind.Number, IsRequired: false), new ExchangeField("Rcv", ExchangeSlot.ReceivedReport, ExchangeFieldKind.Report), new ExchangeField("RcvNr", ExchangeSlot.SerialNumber, ExchangeFieldKind.Number), new ExchangeField("Time", ExchangeSlot.Exchange1, ExchangeFieldKind.Text) { Width = 4 }, ]; /// The time this station sent goes in the `MiscText` column, as it does in /// N1MM. public bool StampsSentTime => true; public IReadOnlyList MultiplierNamesFor(StationInfo me) => ["Countries", "Areas", "Continents"]; public DupeScope DupeScope => DupeScope.PerBand; public bool HasSerialNumbers => true; public IReadOnlyList Modes => [ModeCategory.Digital]; public string SentExchangeFor(StationInfo me) => "001"; public int PointsFor(QsoContext qso) => 1; public IReadOnlyList MultipliersFor(QsoContext qso) { string band = qso.Band?.Name ?? ""; List found = []; if (qso.CountryPrefix.Length > 0) { found.Add(new Multiplier(1, qso.CountryPrefix, band)); } string area = qso.Qso.Section.Trim().ToUpperInvariant(); if (area.Length > 0) { found.Add(new Multiplier(2, area, band)); } if (qso.Continent.Length > 0) { found.Add(new Multiplier(3, qso.Continent, "")); } return found; } public int TotalScore(ScoreTally tally, ContestEntry entry) => tally.Points * (tally.MultiplierCount(1) + tally.MultiplierCount(2)) * Math.Max(1, tally.MultiplierCount(3)); public CabrilloExchange CabrilloExchange(Qso qso, StationInfo me, ContestEntry entry) => new( [ new CabrilloField(me.Callsign, 10), new CabrilloField(qso.SentReport, 3), new CabrilloField($"{qso.SentNumber:0000}", 4), new CabrilloField(SentTime(qso), 4), ], [ new CabrilloField(qso.Call.Text, 10), new CabrilloField(qso.ReceivedReport, 3), new CabrilloField($"{qso.ReceivedNumber:0000}", 4), new CabrilloField(FourDigits(qso.Exchange1), 4), ]); /// The time this station sent, and the time of the contact for a contact /// logged before that was filled in. N1MM writes the same two. private static string SentTime(Qso qso) => qso.MiscText.Trim().Length > 0 ? FourDigits(qso.MiscText) : qso.TimestampUtc.ToString("HHmm"); /// `905` is written `0905`, which is what N1MM writes for a time typed /// without its leading zero. private static string FourDigits(string time) => int.TryParse(time.Trim(), out int minutes) ? $"{minutes:0000}" : time.Trim(); }