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 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 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 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 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 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 AReceiverBarIsAsWideAsTheModeItIsIn() { VfoMarker vfo = VfoMarker.Centred( Frequency.FromKilohertz(14_025), Frequency.FromHertz(500), VfoRole.Receive); Assert.Equal(14_024_750, vfo.Low.Hertz); Assert.Equal(14_025_250, vfo.High.Hertz); } }