SOBandChangeTimerDuration and MOBandChangeTimerDuration say how long a station has to stay on a band it has just moved to. Both were read by nothing: N1MM counts them down in its info window, which this program does not have. The countdown now stands in the entry window's status bar, next to the contacts and multipliers, ticking with the clock that is already there. BandChangeRules.StayLeft works it out from the log, starting the stay at the minute after the contact that changed band, which is where N1MM starts it. Which contests show it is decided at runtime rather than by a list: the rules come from the contest for the entry's own category, so a file that asks for no stay, or asks for one only of single-op entries while the station is entered multi-op, shows nothing at all. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RoGtneMQaz4M9w7Kk49AVD
102 lines
3.7 KiB
C#
102 lines
3.7 KiB
C#
using Nonemm.Core;
|
|
|
|
namespace Nonemm.Contests.Tests;
|
|
|
|
/// The `…BandChange…` settings: what counts as a change, and over what stretch
|
|
/// of time the changes are counted.
|
|
public class BandChangeRulesTests
|
|
{
|
|
private static readonly DateTime Start = new(2026, 5, 30, 12, 0, 0, DateTimeKind.Utc);
|
|
|
|
private static Qso At(int minutes, double kilohertz, Mode? mode = null, int seconds = 0) =>
|
|
TestLog.Contact("OM3XYZ", kilohertz, mode: mode) with
|
|
{
|
|
TimestampUtc = Start.AddMinutes(minutes).AddSeconds(seconds),
|
|
};
|
|
|
|
[Fact]
|
|
public void EachMoveToAnotherBandIsOneChange() =>
|
|
Assert.Equal(
|
|
2,
|
|
new BandChangeRules(8).CountedIn(
|
|
[At(0, 14_025), At(5, 7_040), At(10, 7_045), At(15, 14_030)],
|
|
Start.AddMinutes(20)));
|
|
|
|
/// The count is per clock hour unless the file says otherwise, so a change
|
|
/// made in the hour before does not count against this one.
|
|
[Fact]
|
|
public void ChangesMadeInAnEarlierHourAreNotCounted() =>
|
|
Assert.Equal(
|
|
1,
|
|
new BandChangeRules(8).CountedIn(
|
|
[At(0, 14_025), At(5, 7_040), At(65, 14_025)],
|
|
Start.AddMinutes(70)));
|
|
|
|
[Fact]
|
|
public void CountingPerContestKeepsEveryChange() =>
|
|
Assert.Equal(
|
|
2,
|
|
new BandChangeRules(8, PerContest: true).CountedIn(
|
|
[At(0, 14_025), At(5, 7_040), At(65, 14_025)],
|
|
Start.AddMinutes(70)));
|
|
|
|
/// `CountBandChangesPerPeriod` counts the hour up to now rather than the
|
|
/// clock hour.
|
|
[Fact]
|
|
public void CountingPerPeriodLooksBackAnHour() =>
|
|
Assert.Equal(
|
|
1,
|
|
new BandChangeRules(8, PerPeriod: true).CountedIn(
|
|
[At(0, 14_025), At(5, 7_040), At(65, 14_025)],
|
|
Start.AddMinutes(70)));
|
|
|
|
/// `CountBandOrModeChange` counts a move to another mode on the same band.
|
|
[Fact]
|
|
public void ModeChangesCountWhenTheContestSaysSo() =>
|
|
Assert.Equal(
|
|
1,
|
|
new BandChangeRules(8, CountsModeChanges: true).CountedIn(
|
|
[At(0, 14_025), At(5, 14_250, Modes.Usb)],
|
|
Start.AddMinutes(10)));
|
|
|
|
/// The stay runs from the minute after the contact that changed band, so a
|
|
/// change at 12:05:40 with a ten-minute stay has five minutes left at
|
|
/// 12:11. N1MM starts it the same way.
|
|
[Fact]
|
|
public void TheStayCountsDownFromTheMinuteAfterTheChange()
|
|
{
|
|
BandChangeRules rules = new(8, MinimumStay: TimeSpan.FromMinutes(10));
|
|
|
|
Assert.Equal(
|
|
TimeSpan.FromMinutes(5),
|
|
rules.StayLeft([At(0, 14_025), At(5, 7_040, seconds: 40)], Start.AddMinutes(11)));
|
|
}
|
|
|
|
[Fact]
|
|
public void TheStayIsUpOnceTheTimeHasPassed() =>
|
|
Assert.Equal(
|
|
TimeSpan.Zero,
|
|
new BandChangeRules(8, MinimumStay: TimeSpan.FromMinutes(10)).StayLeft(
|
|
[At(0, 14_025), At(5, 7_040)],
|
|
Start.AddMinutes(30)));
|
|
|
|
/// A log that has stayed on one band has nothing to count down.
|
|
[Fact]
|
|
public void NothingCountsDownUntilTheStationChangesBand() =>
|
|
Assert.Equal(
|
|
TimeSpan.Zero,
|
|
new BandChangeRules(8, MinimumStay: TimeSpan.FromMinutes(10)).StayLeft(
|
|
[At(0, 14_025), At(5, 14_030)],
|
|
Start.AddMinutes(6)));
|
|
|
|
[Fact]
|
|
public void AContestThatAsksForNoStayHasNoTimer()
|
|
{
|
|
Assert.False(new BandChangeRules(8).HasStayTimer);
|
|
Assert.True(new BandChangeRules(8, MinimumStay: TimeSpan.FromMinutes(10)).HasStayTimer);
|
|
}
|
|
|
|
[Fact]
|
|
public void AContestWithNoLimitCountsNothing() => Assert.False(BandChangeRules.None.IsCounted);
|
|
}
|