Add the Avalonia application and the station network

The entry window types contacts and colours them as they are typed; the log,
check, bandmap, score and packet windows read the same session. Contacts are
shared with the other stations of a multi-operator entry in N1MM's contact
message, so an N1MM station on the same network sees them too.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Erik
2026-08-27 10:56:35 +00:00
parent ffeeb2cdc1
commit 2834f63c8e
45 changed files with 2667 additions and 0 deletions

View File

@@ -0,0 +1,87 @@
using Avalonia.Controls;
using Nonemm.Core;
namespace Nonemm.App.Windows;
/// Contacts, points and multipliers band by band.
public sealed partial class ScoreWindow : RefreshableWindow
{
private readonly AppSession session;
public ScoreWindow(AppSession session)
{
this.session = session;
InitializeComponent();
Refresh();
}
public override void Refresh()
{
Table.Children.Clear();
Table.ColumnDefinitions.Clear();
Table.RowDefinitions.Clear();
if (session.Logging is null)
{
TotalText.Text = "no contest is open";
return;
}
List<Band> bands = session.Logging.Log.Qsos
.Select(q => q.Band)
.OfType<Band>()
.Distinct()
.OrderBy(b => b.MegahertzLabel)
.ToList();
foreach (string _ in new[] { "band", "qsos", "points", "mults" })
{
Table.ColumnDefinitions.Add(new ColumnDefinition(GridLength.Star));
}
AddRow(0, "Band", "QSOs", "Points", "Mults", header: true);
int row = 1;
foreach (Band band in bands)
{
IReadOnlyList<Qso> onBand = session.Logging.Log.Qsos.Where(q => q.Band == band).ToList();
AddRow(
row++,
band.Name,
onBand.Count.ToString(),
onBand.Sum(q => q.Points).ToString(),
onBand.Sum(MultiplierCount).ToString());
}
AddRow(
row,
"Total",
session.Logging.Log.Tally.Qsos.ToString(),
session.Logging.Log.Tally.Points.ToString(),
session.Logging.Log.Tally.TotalMultipliers.ToString(),
header: true);
TotalText.Text = $"Claimed score {session.Logging.Log.TotalScore:N0}";
}
private static int MultiplierCount(Qso qso) =>
(qso.IsMultiplier1 ? 1 : 0) + (qso.IsMultiplier2 ? 1 : 0) + (qso.IsMultiplier3 ? 1 : 0);
private void AddRow(int row, string band, string qsos, string points, string mults, bool header = false)
{
Table.RowDefinitions.Add(new RowDefinition(GridLength.Auto));
string[] cells = [band, qsos, points, mults];
for (int column = 0; column < cells.Length; column++)
{
TextBlock text = new()
{
Text = cells[column],
FontFamily = new Avalonia.Media.FontFamily("monospace"),
FontSize = 13,
Opacity = header ? 1.0 : 0.85,
Margin = new Avalonia.Thickness(0, 2, 8, 2),
};
Grid.SetRow(text, row);
Grid.SetColumn(text, column);
Table.Children.Add(text);
}
}
}