The menu tree comes from N1MM's EntryWindow.Designer.cs: File, Edit, View, Tools, Config, Window, with the items under the names N1MM gives them. The window list moved out of View into Window; the call history file moved from Config into File > Import. Ctrl+W, Ctrl+L and Ctrl+M now work, so the keys printed in the menu are real. Two commands that had no menu item before: the CW and SSB function key definitions, and the QTC setup area. The rest of the Edit menu: - Ctrl+N asks for a note and puts it in the comment of the contact in the boxes, or of the last logged contact when nothing is typed. - Edit Current Contact opens the Edit Contact form over what is typed but not logged. Update hands the values back to the entry boxes. - Ctrl+Q and Ctrl+A load a logged contact into the boxes and paint them pale yellow. Enter writes the change back, Esc puts back what was being typed, and stepping forward past the newest contact leaves quick edit. - Ctrl+U raises the received serial, or a numeric exchange box when the contest has no serial. - Ctrl+F shows the call being typed in the log window, then the next contact with that call. RadioPosition is now OperatingPosition: it is the operator at one radio, not a place on a band. Looked at under Xvfb on a 3775-contact log: quick edit back and forward, Esc, the note dialog, find, and Edit Current Contact putting a zone back into the entry boxes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
121 lines
3.9 KiB
C#
121 lines
3.9 KiB
C#
using Nonemm.Contests;
|
|
using Nonemm.Contests.Rules;
|
|
using Nonemm.Core;
|
|
using Nonemm.Core.Calls;
|
|
using Nonemm.Storage;
|
|
|
|
namespace Nonemm.Session.Tests;
|
|
|
|
public class MessageExpanderTests
|
|
{
|
|
private static OperatingPosition Session(CallHistory? history = null, int radioNumber = 1)
|
|
{
|
|
FakeLogStore store = new();
|
|
ContestInstance instance = store.AddContest(new ContestInstance
|
|
{
|
|
ContestNumber = 0,
|
|
ContestName = "CQWW",
|
|
SentExchange = "14",
|
|
});
|
|
return new OperatingPosition(
|
|
new ContestSession(
|
|
store,
|
|
new CqWorldWide(ModeCategory.Cw),
|
|
instance,
|
|
new StationInfo { Callsign = "DL1ABC", CqZone = 14, Name = "Erik", GridSquare = "JN88" },
|
|
null,
|
|
history),
|
|
radioNumber);
|
|
}
|
|
|
|
[Fact]
|
|
public void MyCallAndTheirCallAreFilledIn()
|
|
{
|
|
OperatingPosition session = Session();
|
|
session.Entry.Call = "JA1XYZ";
|
|
Assert.Equal("JA1XYZ DE DL1ABC", MessageExpander.Expand("{CALL} DE {MYCALL}", session));
|
|
}
|
|
|
|
[Fact]
|
|
public void TheSentExchangeComesFromTheContestSetup() =>
|
|
Assert.Equal("599 14", MessageExpander.Expand("{SENTRST} {EXCH}", Session()));
|
|
|
|
[Fact]
|
|
public void HashIsTheSerialNumber() =>
|
|
Assert.Equal("NR 1", MessageExpander.Expand("NR #", Session()));
|
|
|
|
[Fact]
|
|
public void CutNumbersReplaceZeroAndNine() =>
|
|
Assert.Equal("5NN", MessageExpander.Expand("{SENTRSTCUT}", Session()));
|
|
|
|
[Fact]
|
|
public void AMacroThatIsNotKnownDisappears() =>
|
|
Assert.Equal("TU ", MessageExpander.Expand("TU {NOTAMACRO}", Session()));
|
|
|
|
[Fact]
|
|
public void AnUnclosedMacroIsLeftAsTyped() =>
|
|
Assert.Equal("TU {MYCALL", MessageExpander.Expand("TU {MYCALL", Session()));
|
|
|
|
[Fact]
|
|
public void TheSingleCharacterMacrosAreTheirCallMyCallAndTheSerial()
|
|
{
|
|
OperatingPosition session = Session();
|
|
session.Entry.Call = "JA1XYZ";
|
|
|
|
Assert.Equal("JA1XYZ 599 1 DE DL1ABC", MessageExpander.Expand("! 599 # DE *", session));
|
|
}
|
|
|
|
[Fact]
|
|
public void TheirCallFallsBackToTheLastOneLogged()
|
|
{
|
|
OperatingPosition session = Session();
|
|
session.Entry.Call = "JA1XYZ";
|
|
session.Entry.Set(ExchangeSlot.ReceivedReport, "599");
|
|
session.Entry.Set(ExchangeSlot.Zone, "25");
|
|
session.LogContact();
|
|
|
|
Assert.Equal("JA1XYZ JA1XYZ", MessageExpander.Expand("{CALL} {LASTCALL}", session));
|
|
}
|
|
|
|
[Fact]
|
|
public void TheFrequencySendsRForTheDecimalPointOnCw()
|
|
{
|
|
OperatingPosition session = Session();
|
|
session.Tune(Frequency.FromKilohertz(14_025.5));
|
|
|
|
Assert.Equal("14025R5 14026", MessageExpander.Expand("{FREQ} {FREQROUND}", session));
|
|
}
|
|
|
|
[Fact]
|
|
public void TheOtherRadioFillsInTheOtherMacros()
|
|
{
|
|
OperatingPosition here = Session();
|
|
OperatingPosition there = Session(radioNumber: 2);
|
|
there.Tune(Frequency.FromKilohertz(3_525));
|
|
|
|
Assert.Equal("3525R0 3R5 80M", MessageExpander.Expand("{OTHERFREQ} {OTHERMHZ} {OTHERBAND}", here, there));
|
|
}
|
|
|
|
[Fact]
|
|
public void WithOneRadioTheOtherMacrosStandForNothing() =>
|
|
Assert.Equal("", MessageExpander.Expand("{OTHERFREQ}{OTHERMHZ}{OTHERBAND}", Session()));
|
|
|
|
[Fact]
|
|
public void TheNameComesFromTheCallHistoryWhenTheContestHasNoNameBox()
|
|
{
|
|
OperatingPosition session = Session(CallHistory.Parse("!!Order!!,Call,Name\nJA1XYZ,Ken"));
|
|
session.Entry.Call = "JA1XYZ";
|
|
|
|
Assert.Equal("TU Ken GL", MessageExpander.Expand("TU {NAMEANDSPACE}GL", session));
|
|
}
|
|
|
|
[Fact]
|
|
public void MyGridAndTheirsAreDifferentMacros()
|
|
{
|
|
OperatingPosition session = Session(CallHistory.Parse("!!Order!!,Call,LOC1\nJA1XYZ,PM95"));
|
|
session.Entry.Call = "JA1XYZ";
|
|
|
|
Assert.Equal("JN88 PM95", MessageExpander.Expand("{GRID} {GRIDSQUARE}", session));
|
|
}
|
|
}
|