Remove the status bar and the band name, add the 75 and 150 kHz spans, add buttons for the callsign size (saved in the settings), draw the scale in the form's text colour so it shows in the dark theme, mark the carrier on the VFO bar and place a sideband bar on its side of the carrier, and show who spotted a station, when, and the comment when the pointer is on it. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
109 lines
3.5 KiB
C#
109 lines
3.5 KiB
C#
using Nonemm.Core;
|
|
|
|
namespace Nonemm.Spotting.Tests;
|
|
|
|
public class BandmapLayoutTests
|
|
{
|
|
private const double LabelHeight = 10;
|
|
|
|
private static readonly DateTime Now = new(2026, 5, 30, 12, 0, 0, DateTimeKind.Utc);
|
|
|
|
/// 14000 to 14100 kHz over 100 pixels, so one pixel is one kilohertz.
|
|
private static BandmapScale Scale() =>
|
|
new(Frequency.FromKilohertz(14_000), Frequency.FromKilohertz(14_100), 100);
|
|
|
|
private static Spot At(double kilohertz, string call = "DL1ABC") =>
|
|
new(Callsign.Parse(call), Frequency.FromKilohertz(kilohertz), Now, SpotSource.Cluster);
|
|
|
|
[Fact]
|
|
public void ALabelSitsCentredOnItsFrequency()
|
|
{
|
|
IReadOnlyList<BandmapLabel> placed = BandmapLayout.Place([At(14_050)], Scale(), LabelHeight);
|
|
|
|
Assert.Equal(50, placed[0].MarkY);
|
|
Assert.Equal(45, placed[0].LabelY);
|
|
}
|
|
|
|
[Fact]
|
|
public void LabelsComeOutInFrequencyOrder()
|
|
{
|
|
IReadOnlyList<BandmapLabel> placed = BandmapLayout.Place(
|
|
[At(14_080, "JA1XYZ"), At(14_010, "DL1ABC")],
|
|
Scale(),
|
|
LabelHeight);
|
|
|
|
Assert.Equal(["DL1ABC", "JA1XYZ"], placed.Select(l => l.Spot.Call.Text));
|
|
}
|
|
|
|
/// Two stations a hundred hertz apart would have their text on top of each
|
|
/// other, so the lower one moves down and its leader line does the work.
|
|
[Fact]
|
|
public void ALabelThatWouldCoverTheOneAboveIsPushedDown()
|
|
{
|
|
IReadOnlyList<BandmapLabel> placed = BandmapLayout.Place(
|
|
[At(14_050, "DL1ABC"), At(14_050.1, "JA1XYZ")],
|
|
Scale(),
|
|
LabelHeight);
|
|
|
|
Assert.Equal(45, placed[0].LabelY);
|
|
Assert.Equal(55.5, placed[1].LabelY);
|
|
// the leader still points at where the station really is
|
|
Assert.Equal(50.1, placed[1].MarkY, 3);
|
|
}
|
|
|
|
[Fact]
|
|
public void ALabelWithRoomKeepsItsOwnPlace()
|
|
{
|
|
IReadOnlyList<BandmapLabel> placed = BandmapLayout.Place(
|
|
[At(14_010, "DL1ABC"), At(14_090, "JA1XYZ")],
|
|
Scale(),
|
|
LabelHeight);
|
|
|
|
Assert.Equal(5, placed[0].LabelY);
|
|
Assert.Equal(85, placed[1].LabelY);
|
|
}
|
|
|
|
[Fact]
|
|
public void AStationOutsideTheSliceIsNotDrawn() =>
|
|
Assert.Empty(BandmapLayout.Place([At(14_200)], Scale(), LabelHeight));
|
|
|
|
[Fact]
|
|
public void TheTicksStartAtTheFirstRoundFrequencyInTheSlice()
|
|
{
|
|
IReadOnlyList<Frequency> ticks = BandmapLayout.Ticks(
|
|
new BandmapScale(Frequency.FromKilohertz(14_003), Frequency.FromKilohertz(14_012), 100),
|
|
Frequency.FromKilohertz(5));
|
|
|
|
Assert.Equal([14_005_000, 14_010_000], ticks.Select(t => t.Hertz));
|
|
}
|
|
|
|
[Fact]
|
|
public void TheScaleTurnsPixelsBackIntoFrequencies() =>
|
|
Assert.Equal(14_050_000, Scale().At(50).Hertz);
|
|
|
|
[Fact]
|
|
public void ACwReceiverBarIsCentredOnTheCarrier()
|
|
{
|
|
VfoMarker vfo = VfoMarker.For(Frequency.FromKilohertz(14_025), Modes.Cw, VfoRole.Receive);
|
|
|
|
Assert.Equal((14_024_750, 14_025_250), (vfo.Low.Hertz, vfo.High.Hertz));
|
|
Assert.Equal(14_025_000, vfo.Carrier.Hertz);
|
|
}
|
|
|
|
[Fact]
|
|
public void AnUpperSidebandBarStartsAtTheCarrier()
|
|
{
|
|
VfoMarker vfo = VfoMarker.For(Frequency.FromKilohertz(14_200), Modes.Usb, VfoRole.Receive);
|
|
|
|
Assert.Equal((14_200_000, 14_202_700), (vfo.Low.Hertz, vfo.High.Hertz));
|
|
}
|
|
|
|
[Fact]
|
|
public void ALowerSidebandBarEndsAtTheCarrier()
|
|
{
|
|
VfoMarker vfo = VfoMarker.For(Frequency.FromKilohertz(7_100), Modes.Lsb, VfoRole.Receive);
|
|
|
|
Assert.Equal((7_097_300, 7_100_000), (vfo.Low.Hertz, vfo.High.Hertz));
|
|
}
|
|
}
|