Act on the .udc session, off-time and band-change settings
Four settings were read by nothing. MultipleSessions = 0000/30 runs the contest in half-hour sessions from 00:00 UTC. The session is part of the dupe key, so a station worked in an earlier one may be worked again, and ResetMultsEverySession and ResetSNEverySession start the multipliers and the serial numbers over. DupeQSOMinutesAgo is the other way back to a station: after so many minutes rather than in the next session. The log holds the time of the last contact per dupe key instead of only the key, and the setting's IgnoreBand and ThisMode decide the scope, because a file that uses it turns DupeType off. MinimumOffTime drives the time on and time off the score summary now shows under the score, and beside them are the band changes made against the allowance for a contest that limits them. N1MM's countdown for the minutes you have to stay on a new band needs its info window and is not here. UdcFile.Flag now takes 1 and 0 as well as True and False, which is what these settings are written as and what N1MM reads. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RoGtneMQaz4M9w7Kk49AVD
This commit is contained in:
66
src/Nonemm.Contests/Udc/UdcSessions.cs
Normal file
66
src/Nonemm.Contests/Udc/UdcSessions.cs
Normal file
@@ -0,0 +1,66 @@
|
||||
using System.Globalization;
|
||||
|
||||
namespace Nonemm.Contests.Udc;
|
||||
|
||||
/// `MultipleSessions = 0000/30`: the contest runs in sessions, the first one
|
||||
/// starting at 00:00 UTC and each lasting 30 minutes. A station worked in an
|
||||
/// earlier session may be worked again, and `ResetMultsEverySession` and
|
||||
/// `ResetSNEverySession` say whether the multipliers and the serial numbers
|
||||
/// start over as well.
|
||||
///
|
||||
/// N1MM writes the length as minutes up to two digits and as hours and minutes
|
||||
/// above that: `30` is half an hour, `200` is two hours. The shortest session
|
||||
/// N1MM takes is ten minutes.
|
||||
public sealed class UdcSessions
|
||||
{
|
||||
private static readonly TimeSpan Shortest = TimeSpan.FromMinutes(10);
|
||||
|
||||
private readonly TimeSpan start;
|
||||
private readonly TimeSpan length;
|
||||
|
||||
public UdcSessions(UdcFile file)
|
||||
{
|
||||
ResetsMultipliers = file.Flag("ResetMultsEverySession", false);
|
||||
ResetsSerialNumbers = file.Flag("ResetSNEverySession", false);
|
||||
string[] parts = file.Text("MultipleSessions").Split('/', StringSplitOptions.TrimEntries);
|
||||
if (parts.Length != 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
TimeSpan? first = HoursAndMinutes(parts[0]);
|
||||
TimeSpan? each = HoursAndMinutes(parts[1]);
|
||||
if (first is null || each is null || each < Shortest)
|
||||
{
|
||||
return;
|
||||
}
|
||||
start = first.Value;
|
||||
length = each.Value;
|
||||
IsDefined = true;
|
||||
}
|
||||
|
||||
public bool IsDefined { get; }
|
||||
|
||||
public bool ResetsMultipliers { get; }
|
||||
|
||||
public bool ResetsSerialNumbers { get; }
|
||||
|
||||
/// Which session a contact belongs to. The sessions are counted off a
|
||||
/// fixed date so that two days of a contest never share a number, which is
|
||||
/// what N1MM's own stepping from the start time gives. Every contact is in
|
||||
/// session 0 for a contest without sessions.
|
||||
public int SessionOf(DateTime utc) =>
|
||||
IsDefined ? (int)((utc - (DateTime.UnixEpoch + start)).Ticks / length.Ticks) : 0;
|
||||
|
||||
/// `30` is thirty minutes, `200` two hours, `0000` midnight. A value that
|
||||
/// is not a number at all leaves the setting off.
|
||||
private static TimeSpan? HoursAndMinutes(string value)
|
||||
{
|
||||
if (!int.TryParse(value, NumberStyles.None, CultureInfo.InvariantCulture, out int number))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return value.Length > 2
|
||||
? TimeSpan.FromMinutes((number / 100 * 60) + (number % 100))
|
||||
: TimeSpan.FromMinutes(number);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user