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:
@@ -0,0 +1,25 @@
|
||||
using Nonemm.Contests;
|
||||
using Nonemm.Core.Calls;
|
||||
|
||||
namespace Nonemm.Session;
|
||||
|
||||
/// One callsign the check window offers, with what the log says about it so it
|
||||
/// is coloured the same as everywhere else.
|
||||
public sealed record CheckCandidate(string Call, PartialMatchQuality Quality, Verdict? Verdict);
|
||||
|
||||
/// Where a column of candidates came from. They stay apart because they answer
|
||||
/// different questions: the log is what this station copied itself, the
|
||||
/// database is a guess about the whole world, and the bandmap is somebody
|
||||
/// else's claim.
|
||||
public enum CheckSource
|
||||
{
|
||||
Log,
|
||||
Database,
|
||||
Bandmap,
|
||||
}
|
||||
|
||||
/// One column of the check window.
|
||||
public sealed record CheckColumn(
|
||||
CheckSource Source,
|
||||
int Held,
|
||||
IReadOnlyList<CheckCandidate> Candidates);
|
||||
@@ -0,0 +1,86 @@
|
||||
using Nonemm.Contests;
|
||||
using Nonemm.Core;
|
||||
using Nonemm.Core.Calls;
|
||||
using Nonemm.Spotting;
|
||||
|
||||
namespace Nonemm.Session;
|
||||
|
||||
/// Answers what the callsign being typed could be, a column per source.
|
||||
public sealed class CheckWindowSources
|
||||
{
|
||||
private readonly LoggingSession session;
|
||||
private readonly CallDatabase database;
|
||||
private readonly Bandmap bandmap;
|
||||
|
||||
public CheckWindowSources(LoggingSession session, CallDatabase database, Bandmap bandmap)
|
||||
{
|
||||
this.session = session;
|
||||
this.database = database;
|
||||
this.bandmap = bandmap;
|
||||
}
|
||||
|
||||
public IReadOnlyList<CheckColumn> Columns(string typed, int limit = 24)
|
||||
{
|
||||
string query = typed.Trim().ToUpperInvariant();
|
||||
return
|
||||
[
|
||||
Column(CheckSource.Log, LoggedCalls(), query, limit),
|
||||
new CheckColumn(
|
||||
CheckSource.Database,
|
||||
database.Count,
|
||||
query.Length < PartialMatching.ShortestUsefulQuery
|
||||
? []
|
||||
: database.Matches(query, limit).Select(Judged).ToList()),
|
||||
Column(CheckSource.Bandmap, SpottedCalls(), query, limit),
|
||||
];
|
||||
}
|
||||
|
||||
private CheckColumn Column(
|
||||
CheckSource source,
|
||||
IReadOnlyList<string> calls,
|
||||
string query,
|
||||
int limit)
|
||||
{
|
||||
if (query.Length < PartialMatching.ShortestUsefulQuery)
|
||||
{
|
||||
return new CheckColumn(source, calls.Count, []);
|
||||
}
|
||||
List<CheckCandidate> found = [];
|
||||
foreach (string call in calls)
|
||||
{
|
||||
PartialMatchQuality? quality = PartialMatching.Judge(query, call);
|
||||
if (quality is not null)
|
||||
{
|
||||
found.Add(Judged(new PartialMatch(call, quality.Value)));
|
||||
}
|
||||
}
|
||||
return new CheckColumn(
|
||||
source,
|
||||
calls.Count,
|
||||
found.OrderBy(c => c.Quality).ThenBy(c => c.Call, StringComparer.Ordinal).Take(limit).ToList());
|
||||
}
|
||||
|
||||
private CheckCandidate Judged(PartialMatch match) =>
|
||||
new(match.Call, match.Quality, VerdictFor(match.Call));
|
||||
|
||||
/// What logging this call on the current band and mode would do.
|
||||
private Verdict? VerdictFor(string call)
|
||||
{
|
||||
Qso candidate = new()
|
||||
{
|
||||
Id = "",
|
||||
TimestampUtc = DateTime.UtcNow,
|
||||
Call = Callsign.Parse(call),
|
||||
Frequency = session.Frequency,
|
||||
Mode = session.Mode,
|
||||
ContestName = session.Contest.Name,
|
||||
};
|
||||
return session.Log.Judge(candidate);
|
||||
}
|
||||
|
||||
private IReadOnlyList<string> LoggedCalls() =>
|
||||
session.Log.Qsos.Select(q => q.Call.Text).Distinct(StringComparer.Ordinal).ToList();
|
||||
|
||||
private IReadOnlyList<string> SpottedCalls() =>
|
||||
bandmap.All().Select(s => s.Call.Text).Distinct(StringComparer.Ordinal).ToList();
|
||||
}
|
||||
@@ -5,6 +5,7 @@
|
||||
<ProjectReference Include="..\Nonemm.Contests\Nonemm.Contests.csproj" />
|
||||
<ProjectReference Include="..\Nonemm.Storage\Nonemm.Storage.csproj" />
|
||||
<ProjectReference Include="..\Nonemm.Formats\Nonemm.Formats.csproj" />
|
||||
<ProjectReference Include="..\Nonemm.Spotting\Nonemm.Spotting.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
|
||||
Reference in New Issue
Block a user