From 9ae5078c84a0aeb26b4575778c57891bc2832c80 Mon Sep 17 00:00:00 2001 From: ericek111 Date: Fri, 28 Aug 2026 00:02:47 +0000 Subject: [PATCH] Take WAE QTC traffic down MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ctrl+Z opens the QTC window for the station being worked, which is the key N1MM puts it on, and the window is laid out the way N1MM lays it out: the header, ten lines of time, callsign and serial number, an Agn and a Cfm button beside each, Clear, Close and Cancel underneath, and the same colours — green for a line that will be saved, red for one still empty, yellow for one that cannot be read. Enter and Tab move forward and space moves within a line, so a line can be walked while listening to it. Sending, the lines are filled from the log and cannot be edited: the contacts not reported to anybody yet, oldest first, never the station being worked, and never past the ten any station may have. The rule for what has been reported is N1MM's — a contact counts as reported when a QTC row carries its call and the serial we sent it — so the pair is kept in the row the way N1MM keeps it. Which way traffic goes is not the operator's choice on CW and SSB: Europe receives and the rest of the world sends. On RTTY it goes both ways, and there the window carries a switch. That is the one piece of the workflow that is ours rather than N1MM's, which toggles a QTC mode outside the window instead. Nothing here transmits. N1MM sends the lines on CW and RTTY and plays recorded voice messages on SSB; we have no QTC message templates, no voice keyer and no digital window, so Agn, Cfm and RX Ready move the cursor and the operator sends by hand. Running it caught what the tests could not: focus set in the constructor does not stick, so the first thing typed into a freshly opened window was dropped and every field after it took the value of the one before. Co-Authored-By: Claude Opus 5 --- README.md | 18 +- docs/unfinished.md | 13 +- om5m.s3db-shm | Bin 32768 -> 0 bytes om5m.s3db-wal | 0 src/Nonemm.App/AppSession.cs | 10 +- src/Nonemm.App/Windows/EntryWindow.axaml.cs | 48 +++ src/Nonemm.App/Windows/QtcWindow.axaml | 29 ++ src/Nonemm.App/Windows/QtcWindow.axaml.cs | 372 ++++++++++++++++++ src/Nonemm.Contests/Rules/WaeQtc.cs | 13 +- src/Nonemm.Session/QtcTraffic.cs | 184 +++++++++ tests/Nonemm.Session.Tests/QtcTrafficTests.cs | 210 ++++++++++ 11 files changed, 886 insertions(+), 11 deletions(-) delete mode 100644 om5m.s3db-shm delete mode 100644 om5m.s3db-wal create mode 100644 src/Nonemm.App/Windows/QtcWindow.axaml create mode 100644 src/Nonemm.App/Windows/QtcWindow.axaml.cs create mode 100644 src/Nonemm.Session/QtcTraffic.cs create mode 100644 tests/Nonemm.Session.Tests/QtcTrafficTests.cs diff --git a/README.md b/README.md index 3a61fef..abf1569 100644 --- a/README.md +++ b/README.md @@ -279,8 +279,22 @@ number columns, and the series such as `9/10` goes in the misc text column. A log written by either program therefore opens in the other with its QTCs intact, and a QTC row is written to the Cabrillo file as a `QTC:` record. -**Entering QTCs while operating is not there yet.** The rules, the scoring and -the file formats are; the window for taking traffic down is next. +**Ctrl+Z** opens the QTC window for the station being worked, which is the key +N1MM uses. The window is laid out the same way: the header, ten lines of time, +callsign and serial number, an Agn and a Cfm button beside each, and Clear, +Close and Cancel underneath. Green is a line that will be saved, red one that is +still empty, yellow one that cannot be read. Enter and Tab move forward, space +moves within a line. + +Receiving, the lines are typed as they arrive. Sending, they are filled from the +log — the contacts not reported to anybody yet, oldest first, never the station +being worked, and never more than the ten any station may have — and cannot be +edited. On CW and SSB the direction is fixed by the rules; on RTTY traffic goes +both ways and the window has a switch. + +Nothing in the window transmits. On CW the operator sends from the entry window, +on SSB by voice, and RTTY has no digital window yet, so Agn, Cfm and RX Ready +move the cursor rather than putting anything on the air. The scoring was checked against six real WAE logs, and agrees with N1MM on points and on weighted multipliers to the contact. diff --git a/docs/unfinished.md b/docs/unfinished.md index 6544697..42c87e8 100644 --- a/docs/unfinished.md +++ b/docs/unfinished.md @@ -39,10 +39,15 @@ and passed over. Acting on them means holding N1MM's section lists and its rules about which sections are retired, and getting that wrong throws away good data. The file is read without them. -**Entering WAE QTC traffic.** The contest, the QTC rows, the scoring and the -Cabrillo `QTC:` records are in, and a log written by N1MM reads back with its -QTCs. What is missing is the window an operator takes traffic in: today a QTC -can only reach the log by being read from a file N1MM wrote. +**The QTC window does not transmit.** Ctrl+Z opens it and traffic goes into the +log, but N1MM sends the QTC text itself: the lines on CW and RTTY, and recorded +voice messages for QRV, Agn, Cfm and TU on SSB. Here the Agn, Cfm and RX Ready +buttons only move the cursor. What is missing under it is the message templates +for QTC traffic, a voice keyer, and the digital window. + +**N1MM's QTC setup tab is not there.** Field spacing, the CW messages for Agn +and TU, and the settings that skip the Cfm and QRV steps are all N1MM options +this window does not have. **Two WAE numbers do not agree with N1MM, both from 2020 and 2021 logs.** The disagreements are the country file of the day, not the rules: 4U1A counted as diff --git a/om5m.s3db-shm b/om5m.s3db-shm deleted file mode 100644 index fe9ac2845eca6fe6da8a63cd096d9cf9e24ece10..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32768 zcmeIuAr62r3 Changed?.Invoke(this, EventArgs.Empty); - Logging.Logged += (_, qso) => Bandmap.Add(new Spot( - qso.Call, qso.Frequency, qso.TimestampUtc, SpotSource.Log)); + Logging.Logged += (_, qso) => + { + // a WAE QTC row is traffic about a station, not a station on the air + if (contest.IsContact(qso)) + { + Bandmap.Add(new Spot(qso.Call, qso.Frequency, qso.TimestampUtc, SpotSource.Log)); + } + }; Logging.Logged += (_, qso) => _ = network?.SendAsync(qso, Settings.Station.Callsign); Logging.Edited += (_, change) => _ = network?.SendEditAsync( change.Qso, Settings.Station.Callsign, change.OldCall, change.OldTimestampUtc); diff --git a/src/Nonemm.App/Windows/EntryWindow.axaml.cs b/src/Nonemm.App/Windows/EntryWindow.axaml.cs index 71fa740..80e10df 100644 --- a/src/Nonemm.App/Windows/EntryWindow.axaml.cs +++ b/src/Nonemm.App/Windows/EntryWindow.axaml.cs @@ -254,6 +254,10 @@ public sealed partial class EntryWindow : Window e.Handled = true; MoveFocus(forward: !e.KeyModifiers.HasFlag(KeyModifiers.Shift)); break; + case Key.Z when e.KeyModifiers.HasFlag(KeyModifiers.Control): + e.Handled = true; + _ = OpenQtcWindow(); + break; case Key.B when e.KeyModifiers.HasFlag(KeyModifiers.Control): e.Handled = true; ToggleAlternatingCq(); @@ -456,6 +460,50 @@ public sealed partial class EntryWindow : Window } } + /// WAE QTC traffic, on Ctrl+Z as in N1MM. The contact is logged first if it + /// is still in the boxes: the traffic belongs to a station that has been + /// worked. + private async Task OpenQtcWindow() + { + if (Logging is null) + { + return; + } + QtcTraffic traffic = new(Logging); + if (!traffic.IsWaeContest) + { + Status("QTC traffic is a WAE thing"); + return; + } + if (Logging.Entry.Call.Trim().Length > 0 && Logging.Entry.IsComplete) + { + OnEnter(); + } + string typed = Logging.Entry.Call.Trim(); + Callsign station = Callsign.Parse( + typed.Length > 0 ? typed : Logging.Log.Qsos.LastOrDefault()?.Call.Text ?? ""); + QtcDirection direction = traffic.DirectionFor(station, out string why); + if (direction == QtcDirection.None) + { + Status(why); + return; + } + if (direction is QtcDirection.Send && traffic.ToSend(station).Count == 0) + { + Status("nothing left to report to " + station.Text); + return; + } + QtcWindow window = new(session, Logging, station, direction); + bool saved = await window.ShowDialog(this); + Logging.Wipe(); + SyncBoxes(); + boxes[0].Focus(); + Refresh(); + Status(saved + ? $"QTC traffic with {station.Text} logged" + : $"QTC traffic with {station.Text} left alone"); + } + /// Alternating CQ: CQ on this radio, then the other as each message ends. /// N1MM calls it dueling CQs and puts it on the same key. private void ToggleAlternatingCq() diff --git a/src/Nonemm.App/Windows/QtcWindow.axaml b/src/Nonemm.App/Windows/QtcWindow.axaml new file mode 100644 index 0000000..26c9010 --- /dev/null +++ b/src/Nonemm.App/Windows/QtcWindow.axaml @@ -0,0 +1,29 @@ + + + + + + + + + +