Add the Broadcast Data dialog and send N1MM's score breakdown

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-24 03:42:19 +00:00
co-authored by Claude Sonnet 5.5
parent ec12fb1d0f
commit 65178b2d89
24 changed files with 1325 additions and 21 deletions
+12 -4
View File
@@ -18,7 +18,7 @@ namespace Nonemm.App;
/// Everything the running program owns: the log store, the contest in progress,
/// the bandmap, the radio and the cluster. The windows read from this and one
/// `Changed` event tells them all to redraw.
public sealed class AppSession : IDisposable
public sealed partial class AppSession : IDisposable
{
/// How often this station tells the others how it is doing. N1MM sends its
/// status on the same sort of interval; every second would read the log
@@ -350,6 +350,7 @@ public sealed class AppSession : IDisposable
Available = new AvailableStations(positions[0], Bandmap);
Save(Settings with { ContestNumber = contestNumber });
ContestChanged?.Invoke(this, EventArgs.Empty);
SendAppInfo();
}
/// A frequency on the band a number was taken on. The message carries a
@@ -412,6 +413,7 @@ public sealed class AppSession : IDisposable
// the socket thread must not touch the log: every other change to it is
// made where the windows read it
link.UpdateArrived += (_, update) => QueueFromNetwork(update);
link.UpdateArrived += (_, update) => ForwardToPrograms(update);
// the resync reads the log rather than being handed it, and another
// station can ask for a rescore when its resync is done
link.Log = new SessionContactLog(this);
@@ -967,13 +969,17 @@ public sealed class AppSession : IDisposable
if (keeping.Count > 0)
{
Bandmap.AddRange(keeping);
SendSpots(keeping);
}
}
/// Whether the station has already been worked, which decides whether a
/// spot is moved about: N1MM leaves a dupe where it is.
private bool IsDupe(Spot spot) =>
Logging is not null && Logging.Log.Judge(new Qso
private bool IsDupe(Spot spot) => JudgeSpot(spot) is { IsDupe: true };
/// What logging the station of a spot would do, or null with no contest open.
private Verdict? JudgeSpot(Spot spot) =>
Logging?.Log.Judge(new Qso
{
Id = "",
TimestampUtc = spot.AtUtc,
@@ -981,7 +987,7 @@ public sealed class AppSession : IDisposable
Frequency = spot.Frequency,
Mode = Position?.Mode ?? Modes.Cw,
ContestName = Logging.Contest.Name,
}) is { IsDupe: true };
});
private void ApplySpotSettings()
{
@@ -1010,6 +1016,8 @@ public sealed class AppSession : IDisposable
DisposeRadios();
cluster?.Dispose();
announcing?.Stop();
broadcasting?.Stop();
data?.Dispose();
network?.Dispose();
link?.Dispose();
alternating?.Dispose();