Set the bandmap spot timeout separately for CW/digital and phone
CW and digital spots time out after 10 minutes and phone spots after 30 by default, both settings on the telnet Filters tab. The mode comes from the band plan; a frequency it has no boundaries for counts as phone. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1039,7 +1039,11 @@ public sealed partial class AppSession : IDisposable
|
||||
private void ApplySpotSettings()
|
||||
{
|
||||
spotFilter = Settings.SpotFilter.ToFilter(BandPlan, Settings.Station, Countries, Calls, History);
|
||||
Bandmap.Lifetime = TimeSpan.FromMinutes(Math.Max(1, Settings.SpotTimeoutMinutes));
|
||||
Bandmap.LifetimeFor = spot => TimeSpan.FromMinutes(Math.Max(
|
||||
1,
|
||||
BandPlan.ModeAt(spot.Frequency) is ModeCategory.Cw or ModeCategory.Digital
|
||||
? Settings.CwDigitalSpotTimeoutMinutes
|
||||
: Settings.PhoneSpotTimeoutMinutes));
|
||||
foreach (OperatingPosition position in positions)
|
||||
{
|
||||
position.CqLeaveHertz = Settings.CqLeaveHertz;
|
||||
|
||||
@@ -50,8 +50,12 @@ public sealed record Settings
|
||||
/// Which cluster spots reach the bandmap.
|
||||
public StoredSpotFilter SpotFilter { get; init; } = new();
|
||||
|
||||
/// How long a spot stays on the bandmap. N1MM's own default is 60.
|
||||
public int SpotTimeoutMinutes { get; init; } = 60;
|
||||
/// How long a CW or digital spot stays on the bandmap.
|
||||
public int CwDigitalSpotTimeoutMinutes { get; init; } = 10;
|
||||
|
||||
/// How long a phone spot stays on the bandmap. A frequency with no
|
||||
/// boundaries in the band plan counts as phone.
|
||||
public int PhoneSpotTimeoutMinutes { get; init; } = 30;
|
||||
|
||||
/// The width of the slice the bandmap shows, in hertz. Zero is the whole band
|
||||
/// and minus one is the CW, digital or phone part the receiver is in.
|
||||
|
||||
@@ -48,7 +48,8 @@ public sealed partial class TelnetWindow
|
||||
CallAreasBox.Text = string.Join(' ', filter.CallAreas);
|
||||
BlockedSpottersBox.Text = string.Join(' ', filter.BlockedSpotters);
|
||||
BlockedCallsBox.Text = string.Join(' ', filter.BlockedCalls);
|
||||
TimeoutBox.Text = session.Settings.SpotTimeoutMinutes.ToString(CultureInfo.InvariantCulture);
|
||||
TimeoutBox.Text = session.Settings.CwDigitalSpotTimeoutMinutes.ToString(CultureInfo.InvariantCulture);
|
||||
PhoneTimeoutBox.Text = session.Settings.PhoneSpotTimeoutMinutes.ToString(CultureInfo.InvariantCulture);
|
||||
QsySpotBox.Text = session.Settings.QsySpotHertz.ToString(CultureInfo.InvariantCulture);
|
||||
RecentSpotBox.Text = session.Settings.RecentContactSpotMinutes.ToString(CultureInfo.InvariantCulture);
|
||||
CqLeaveBox.Text = session.Settings.CqLeaveHertz.ToString(CultureInfo.InvariantCulture);
|
||||
@@ -74,7 +75,8 @@ public sealed partial class TelnetWindow
|
||||
PreferredSpotters = Words(PreferredSpottersBox.Text),
|
||||
},
|
||||
RandomizeSpots = RandomizeBox.IsChecked == true,
|
||||
SpotTimeoutMinutes = Minutes(TimeoutBox.Text, session.Settings.SpotTimeoutMinutes),
|
||||
CwDigitalSpotTimeoutMinutes = Minutes(TimeoutBox.Text, session.Settings.CwDigitalSpotTimeoutMinutes),
|
||||
PhoneSpotTimeoutMinutes = Minutes(PhoneTimeoutBox.Text, session.Settings.PhoneSpotTimeoutMinutes),
|
||||
QsySpotHertz = Minutes(QsySpotBox.Text, session.Settings.QsySpotHertz),
|
||||
RecentContactSpotMinutes = int.TryParse(RecentSpotBox.Text, out int recent) && recent >= 0
|
||||
? recent
|
||||
|
||||
@@ -120,8 +120,10 @@
|
||||
<TextBox Name="BlockedSpottersBox" />
|
||||
<TextBlock Classes="label" Text="Blacklisted calls" />
|
||||
<TextBox Name="BlockedCallsBox" />
|
||||
<TextBlock Classes="label" Text="Bandmap spot timeout (minutes)" />
|
||||
<TextBlock Classes="label" Text="Bandmap spot timeout for CW and digital (minutes)" />
|
||||
<TextBox Name="TimeoutBox" Width="60" HorizontalAlignment="Left" />
|
||||
<TextBlock Classes="label" Text="Bandmap spot timeout for phone (minutes)" />
|
||||
<TextBox Name="PhoneTimeoutBox" Width="60" HorizontalAlignment="Left" />
|
||||
<TextBlock Classes="label" Text="Spot a call locally when the radio moves more than (Hz)" />
|
||||
<TextBox Name="QsySpotBox" Width="60" HorizontalAlignment="Left" />
|
||||
<TextBlock Classes="label" Text="Go back to search and pounce when the radio moves off the CQ frequency by more than (Hz)" TextWrapping="Wrap" />
|
||||
|
||||
@@ -26,10 +26,14 @@ public sealed class Bandmap
|
||||
this.clock = clock ?? (() => DateTime.UtcNow);
|
||||
}
|
||||
|
||||
/// How long a spot stays on the map. N1MM asks for the same number in
|
||||
/// minutes, on the telnet window's Filters tab.
|
||||
/// How long a spot stays on the map when `LifetimeFor` is not set.
|
||||
public TimeSpan Lifetime { get; set; }
|
||||
|
||||
/// How long a given spot stays on the map, for a different time in each
|
||||
/// mode. N1MM asks for one number in minutes, on the telnet window's
|
||||
/// Filters tab.
|
||||
public Func<Spot, TimeSpan>? LifetimeFor { get; set; }
|
||||
|
||||
public event EventHandler? Changed;
|
||||
|
||||
public void Add(Spot spot)
|
||||
@@ -85,7 +89,8 @@ public sealed class Bandmap
|
||||
lock (guard)
|
||||
{
|
||||
List<string> stale = spots
|
||||
.Where(pair => nowUtc - arrived.GetValueOrDefault(pair.Key, nowUtc) > Lifetime)
|
||||
.Where(pair => nowUtc - arrived.GetValueOrDefault(pair.Key, nowUtc)
|
||||
> (LifetimeFor?.Invoke(pair.Value) ?? Lifetime))
|
||||
.Select(pair => pair.Key)
|
||||
.ToList();
|
||||
foreach (string key in stale)
|
||||
|
||||
@@ -18,6 +18,21 @@ public class BandmapTests
|
||||
Assert.Equal(["JA1XYZ", "DL1ABC"], map.On(Bands.Band20M).Select(s => s.Call.Text));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EachSpotLivesAsLongAsItsOwnLifetime()
|
||||
{
|
||||
Bandmap map = new(clock: () => Now)
|
||||
{
|
||||
LifetimeFor = spot => TimeSpan.FromMinutes(spot.Frequency.Kilohertz < 14_100 ? 10 : 30),
|
||||
};
|
||||
map.Add(At("DL1ABC", 14_025));
|
||||
map.Add(At("JA1XYZ", 14_200));
|
||||
|
||||
map.DropOlderThan(Now.AddMinutes(15));
|
||||
|
||||
Assert.Equal(["JA1XYZ"], map.All().Select(s => s.Call.Text));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AStationThatMovesKeepsOneEntryOnItsBand()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user