using Nonemm.Core; namespace Nonemm.Contests.Udc; /// One of a user-defined contest's up-to-three multipliers: where its value /// comes from and how often it may be counted. public sealed class UdcMultiplier { private readonly int index; private readonly string source; private readonly UdcMultiplierScope scope; private readonly IReadOnlyList onlyForCountries; public UdcMultiplier( int index, string source, UdcMultiplierScope scope, IReadOnlyList onlyForCountries) { this.index = index; this.source = source; this.scope = scope; this.onlyForCountries = onlyForCountries; } public Multiplier? For(QsoContext qso) { if (scope == UdcMultiplierScope.None) { return null; } if (onlyForCountries.Count > 0 && !onlyForCountries.Contains(qso.CountryPrefix, StringComparer.OrdinalIgnoreCase)) { return null; } string? value = ValueFor(qso); return string.IsNullOrEmpty(value) ? null : new Multiplier(index, value, ScopeKey(qso)); } private string? ValueFor(QsoContext qso) => source.ToUpperInvariant() switch { "COUNTRYPREFIX" => qso.CountryPrefix, "WPXPREFIX" => qso.Qso.Call.WpxPrefix(), "SECTION" or "SECT" => Upper(qso.Qso.Section), "EXCHANGE" or "EXCH" => Upper(qso.Qso.Exchange1), "MISC" or "MISCTEXT" => Upper(qso.Qso.MiscText), "CALLSIGN" => qso.Qso.Call.Text, "CQZONE" or "ZN" => qso.Qso.Zone > 0 ? qso.Qso.Zone.ToString() : null, "GRID" => Truncate(qso.Qso.GridSquare, 4), "SGRID" => Truncate(qso.Qso.GridSquare, 6), "FIELD" => Truncate(qso.Qso.GridSquare, 2), "CONTINENT" => qso.Continent, "FIRSTQSO" => "first", _ => null, }; private string ScopeKey(QsoContext qso) => scope switch { UdcMultiplierScope.PerBand => qso.Band?.Name ?? "", UdcMultiplierScope.PerMode => qso.ModeCategory.ToString(), UdcMultiplierScope.PerBandAndMode => $"{qso.Band?.Name}|{qso.ModeCategory}", _ => "", }; private static string Upper(string text) => text.Trim().ToUpperInvariant(); private static string? Truncate(string text, int length) { string trimmed = text.Trim().ToUpperInvariant(); return trimmed.Length < length ? null : trimmed[..length]; } }