using Nonemm.Core; using Nonemm.Core.Calls; using Nonemm.Core.Country; namespace Nonemm.Contests; /// A QSO together with what the country file says about it, so a contest can /// score by country, zone or continent without looking anything up itself. public sealed record QsoContext(Qso Qso, CountryLookup? Country, StationInfo Me, ContestEntry Entry) { /// The call history file the operator loaded, which a contest can count a /// multiplier from. Empty when there is none. public CallHistory History { get; init; } = CallHistory.Empty; public Band? Band => Qso.Band; public ModeCategory ModeCategory => Qso.Mode.Category; /// What the contact says wins over the country file. The two agree unless /// the operator corrected the country by hand, and then the correction is /// the point. public string Continent => Qso.Continent.Trim().Length > 0 ? Qso.Continent.Trim() : Country?.Continent ?? ""; public string CountryPrefix => Qso.CountryPrefix.Trim().Length > 0 ? Qso.CountryPrefix.Trim() : Country?.Entity.PrimaryPrefix ?? ""; public int CqZone => Country?.CqZone ?? Qso.Zone; public int ItuZone => Country?.ItuZone ?? 0; public bool IsSameCountry => CountryPrefix.Length > 0 && CountryPrefix == Me.CountryPrefix; /// Great-circle kilometres between the two grid squares, and zero when /// either station has no locator. public double DistanceKm => GridSquare.TryParse(Qso.GridSquare, out GridSquare theirs) && GridSquare.TryParse(Me.GridSquare, out GridSquare mine) ? mine.DistanceTo(theirs) : 0.0; public bool IsSameContinent => Continent.Length > 0 && Continent == Me.Continent; }