Add the session, radio control, bandmap and cluster
Nonemm.Session holds what the operator is typing, what the log says about it and what happens on Enter, with no UI toolkit behind it. Nonemm.Rig talks to hamlib's rigctld and reconnects on its own. Nonemm.Spotting reads DX cluster lines into a bandmap that drops spots after an hour. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
61
tests/Nonemm.Spotting.Tests/BandmapTests.cs
Normal file
61
tests/Nonemm.Spotting.Tests/BandmapTests.cs
Normal file
@@ -0,0 +1,61 @@
|
||||
using Nonemm.Core;
|
||||
|
||||
namespace Nonemm.Spotting.Tests;
|
||||
|
||||
public class BandmapTests
|
||||
{
|
||||
private static readonly DateTime Now = new(2026, 5, 30, 12, 0, 0, DateTimeKind.Utc);
|
||||
|
||||
private static Spot At(string call, double kilohertz, DateTime? at = null) =>
|
||||
new(Callsign.Parse(call), Frequency.FromKilohertz(kilohertz), at ?? Now, SpotSource.Cluster);
|
||||
|
||||
[Fact]
|
||||
public void SpotsComeBackInFrequencyOrder()
|
||||
{
|
||||
Bandmap map = new();
|
||||
map.Add(At("DL1ABC", 14_100));
|
||||
map.Add(At("JA1XYZ", 14_010));
|
||||
Assert.Equal(["JA1XYZ", "DL1ABC"], map.On(Bands.Band20M).Select(s => s.Call.Text));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AStationThatMovesKeepsOneEntryOnItsBand()
|
||||
{
|
||||
Bandmap map = new();
|
||||
map.Add(At("DL1ABC", 14_010));
|
||||
map.Add(At("DL1ABC", 14_020));
|
||||
Spot only = Assert.Single(map.On(Bands.Band20M));
|
||||
Assert.Equal(14_020_000, only.Frequency.Hertz);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TheSameStationOnAnotherBandIsASeparateEntry()
|
||||
{
|
||||
Bandmap map = new();
|
||||
map.Add(At("DL1ABC", 14_010));
|
||||
map.Add(At("DL1ABC", 7_010));
|
||||
Assert.Equal(2, map.All().Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SpotsOlderThanAnHourAreDropped()
|
||||
{
|
||||
Bandmap map = new();
|
||||
map.Add(At("DL1ABC", 14_010, Now.AddHours(-2)));
|
||||
map.Add(At("JA1XYZ", 14_020, Now.AddMinutes(-5)));
|
||||
map.DropOlderThan(Now);
|
||||
Assert.Equal("JA1XYZ", Assert.Single(map.All()).Call.Text);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TheNearestSpotInsideTheWindowIsFound()
|
||||
{
|
||||
Bandmap map = new();
|
||||
map.Add(At("DL1ABC", 14_010));
|
||||
map.Add(At("JA1XYZ", 14_050));
|
||||
Assert.Equal(
|
||||
"DL1ABC",
|
||||
map.Near(Frequency.FromKilohertz(14_010.2), Frequency.FromKilohertz(0.5))?.Call.Text);
|
||||
Assert.Null(map.Near(Frequency.FromKilohertz(14_030), Frequency.FromKilohertz(0.5)));
|
||||
}
|
||||
}
|
||||
26
tests/Nonemm.Spotting.Tests/Nonemm.Spotting.Tests.csproj
Normal file
26
tests/Nonemm.Spotting.Tests/Nonemm.Spotting.Tests.csproj
Normal file
@@ -0,0 +1,26 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.4" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
|
||||
<PackageReference Include="xunit" Version="2.9.3" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.4" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="Xunit" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Nonemm.Spotting\Nonemm.Spotting.csproj" />
|
||||
<ProjectReference Include="..\..\src\Nonemm.Core\Nonemm.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
34
tests/Nonemm.Spotting.Tests/SpotLineTests.cs
Normal file
34
tests/Nonemm.Spotting.Tests/SpotLineTests.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using Nonemm.Core;
|
||||
|
||||
namespace Nonemm.Spotting.Tests;
|
||||
|
||||
public class SpotLineTests
|
||||
{
|
||||
private static readonly DateTime Now = new(2026, 5, 30, 12, 40, 0, DateTimeKind.Utc);
|
||||
|
||||
[Fact]
|
||||
public void ANodeSpotIsReadIntoItsParts()
|
||||
{
|
||||
Spot? spot = SpotLine.Parse(
|
||||
"DX de W3LPL: 14025.0 DL1ABC CW 20 dB 25 WPM CQ 1234Z",
|
||||
Now);
|
||||
|
||||
Assert.NotNull(spot);
|
||||
Assert.Equal("DL1ABC", spot.Call.Text);
|
||||
Assert.Equal(14_025_000, spot.Frequency.Hertz);
|
||||
Assert.Equal("W3LPL", spot.Spotter);
|
||||
Assert.Equal(new DateTime(2026, 5, 30, 12, 34, 0, DateTimeKind.Utc), spot.AtUtc);
|
||||
Assert.DoesNotContain("1234Z", spot.Comment);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void OtherTrafficIsNotASpot() =>
|
||||
Assert.Null(SpotLine.Parse("WWV de VE7CC <18Z> : SFI=142, A=7, K=2", Now));
|
||||
|
||||
[Fact]
|
||||
public void ASpotTimedAfterNowCameInYesterday()
|
||||
{
|
||||
Spot? spot = SpotLine.Parse("DX de W3LPL: 14025.0 DL1ABC CQ 2350Z", Now);
|
||||
Assert.Equal(new DateTime(2026, 5, 29, 23, 50, 0, DateTimeKind.Utc), spot?.AtUtc);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user