Show the other computers, and apply the ten-minute rule

Three pieces on top of the link:

**The network status window**, on the entry window's Window menu. A row
per station, this computer included the way N1MM shows it: number,
address, operator, band, mode, run, transmit, pass frequency, the last
message type, how long ago it arrived, the counts each way and the echo
round trip. A station that broadcast the wrong version is named under the
table in red — that is the one fault where everything looks connected
and nothing arrives. The box at the bottom sends a line of chat, and
Echo asks every station whether it is there.

**Where this station is** goes out once a second when it has changed.
The frequency, the mode and run have a dozen places they can change from
— the radio moving, a band button, a QSY typed into the callsign box —
so it is read and compared rather than announced from each of them.

**The ten-minute rule.** `BandChangeRules` already counted changes and
the stay on a band, and the entry window already showed the countdown,
but only a user-defined contest carried a rule, so every built-in
contest allowed anything. `ForCategory` gives a multi-operator entry
with one or two transmitters a ten-minute stay, which is N1MM's fallback
in `ContestInstance.BandChangeTimerDuration` for every contest that does
not name its own. Its per-contest table is a few hundred cases in a
decompiled hash switch and is not repeated.

Config ▸ Edit Networked-Computer Names now covers both networks: the
12060 broadcast to other programs and the 12070 link, with the station
number, the port, the version to claim and stations named by address for
a network where a broadcast does not reach.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PdAYHcdRktqKry7nk414TU
This commit is contained in:
2026-09-03 15:26:42 +00:00
co-authored by Claude Opus 5
parent c0e1bc1e1b
commit 6f2f39768c
12 changed files with 588 additions and 3 deletions
+17 -1
View File
@@ -14,7 +14,23 @@
</Grid>
<TextBlock Text="Other stations, one address per line" FontSize="11" Opacity="0.7" Margin="0,6,0,1" />
<TextBox Name="PeersBox" AcceptsReturn="True" Height="90" PlaceholderText="192.168.1.11" />
<CheckBox Name="EnabledBox" Content="Share contacts with the other stations" Margin="0,6,0,0" />
<CheckBox Name="EnabledBox" Content="Broadcast contacts to other programs (port 12060)" Margin="0,6,0,0" />
<TextBlock Text="The other logging computers" FontWeight="Bold" Margin="0,12,0,0" />
<TextBlock TextWrapping="Wrap" FontSize="11" Opacity="0.75"
Text="This is N1MM's own link between the computers of one entry, on port 12070: contacts, edits, deletes and chat, over a connection to each station. Stations are found by broadcast, so nothing has to be listed." />
<Grid ColumnDefinitions="90,8,110,8,*" RowDefinitions="Auto,Auto">
<TextBlock Text="Station number" FontSize="11" Opacity="0.7" Margin="0,6,0,1" />
<TextBox Name="StationNumberBox" Grid.Row="1" />
<TextBlock Grid.Column="2" Text="Port" FontSize="11" Opacity="0.7" Margin="0,6,0,1" />
<TextBox Name="LinkPortBox" Grid.Row="1" Grid.Column="2" />
<TextBlock Grid.Column="4" Text="Version to claim" FontSize="11" Opacity="0.7" Margin="0,6,0,1" />
<TextBox Name="VersionBox" Grid.Row="1" Grid.Column="4" />
</Grid>
<TextBlock TextWrapping="Wrap" FontSize="11" Opacity="0.75"
Text="N1MM turns away a station whose version is not its own, so this has to be the version the N1MM copies beside it are running. Help ▸ About in N1MM says which." />
<TextBlock Text="Stations to reach by address, one per line, as NAME@address" FontSize="11" Opacity="0.7" Margin="0,6,0,1" />
<TextBox Name="LinkPeersBox" AcceptsReturn="True" Height="60" PlaceholderText="RUN-PC@192.168.1.11" />
<CheckBox Name="LinkEnabledBox" Content="Share contacts with the other logging computers (port 12070)" Margin="0,6,0,0" />
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Spacing="6" Margin="0,8,0,0">
<Button Content="Cancel" Click="OnCancel" />
<Button Content="Save" Click="OnSave" IsDefault="True" />
@@ -18,6 +18,11 @@ public sealed partial class NetworkDialog : Window
PortBox.Text = settings.NetworkPort.ToString();
PeersBox.Text = string.Join("\n", settings.NetworkPeers);
EnabledBox.IsChecked = settings.NetworkEnabled;
StationNumberBox.Text = settings.StationNumber.ToString();
LinkPortBox.Text = settings.StationLinkPort.ToString();
VersionBox.Text = settings.StationLinkVersion;
LinkPeersBox.Text = string.Join("\n", settings.StationLinkPeers);
LinkEnabledBox.IsChecked = settings.StationLinkEnabled;
}
@@ -31,7 +36,23 @@ public sealed partial class NetworkDialog : Window
.Where(l => l.Length > 0)
.ToList(),
NetworkEnabled = EnabledBox.IsChecked == true,
StationNumber = int.TryParse(StationNumberBox.Text, out int number)
? Math.Clamp(number, 1, 99)
: settings.StationNumber,
StationLinkPort = int.TryParse(LinkPortBox.Text, out int linkPort)
? linkPort
: settings.StationLinkPort,
StationLinkVersion = (VersionBox.Text ?? "").Trim(),
StationLinkPeers = Lines(LinkPeersBox.Text),
StationLinkEnabled = LinkEnabledBox.IsChecked == true,
});
private static List<string> Lines(string? text) =>
(text ?? "")
.Split('\n', StringSplitOptions.RemoveEmptyEntries)
.Select(l => l.Trim())
.Where(l => l.Length > 0)
.ToList();
private void OnCancel(object? sender, RoutedEventArgs e) => Close(null);
}