Write what N1MM needs before it will open a log

Checked by opening a log this program wrote in N1MM 1.0.11031. Three things it
rejected:

- a log naming a contest with no row in the Contest table throws "No current
  row" in Contest.FromRow, so the definition row is written whenever a contest
  is opened;
- an empty overlay category is answered with "Invalid Overlay Category:", so an
  entry with no overlay now says "N/A", and the dialog offers N1MM's list;
- the sent exchange omits the report, which is what N1MM's own contest dialog
  asks for.

With those three fixed N1MM opens the log and shows the contacts.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Erik
2026-08-27 11:15:48 +00:00
co-authored by Claude Opus 5
parent 2834f63c8e
commit d96cbe146b
17 changed files with 196 additions and 15 deletions
+51
View File
@@ -0,0 +1,51 @@
using Nonemm.Contests;
using Nonemm.Core;
using Nonemm.Storage;
namespace Nonemm.Session;
/// Turns a contest's rules into the definition row N1MM keeps in the `Contest`
/// table, which it reads when it opens a log.
public static class ContestDefinitions
{
public static ContestDefinition For(Contest contest)
{
IReadOnlyList<string> mults = contest.MultiplierNames;
return new ContestDefinition
{
Name = contest.Name,
DisplayName = contest.DisplayName,
CabrilloName = contest.CabrilloName,
Mode = ModeOf(contest),
DupeType = DupeTypeOf(contest.DupeScope),
Multiplier1Name = NameAt(mults, 0),
Multiplier2Name = NameAt(mults, 1),
Multiplier3Name = NameAt(mults, 2),
};
}
private static string ModeOf(Contest contest)
{
if (contest.Modes.Count != 1)
{
return "BOTH";
}
return contest.Modes[0] switch
{
ModeCategory.Cw => "CW",
ModeCategory.Phone => "SSB",
_ => "RTTY",
};
}
private static int DupeTypeOf(DupeScope scope) => scope switch
{
DupeScope.Once => 1,
DupeScope.PerBandAndMode => 3,
DupeScope.Never => 4,
_ => 2,
};
private static string NameAt(IReadOnlyList<string> names, int at) =>
at < names.Count ? names[at] : "N/A";
}