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:
87
src/Nonemm.App/Windows/ScoreWindow.axaml.cs
Normal file
87
src/Nonemm.App/Windows/ScoreWindow.axaml.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user