code review fixes
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using LibreHardwareMonitor.Windows.WinUI.Controls;
|
||||
using LibreHardwareMonitor.Windows.WinUI.ViewModels;
|
||||
using Xunit;
|
||||
|
||||
namespace LibreHardwareMonitor.Windows.WinUI.Tests.Controls;
|
||||
|
||||
public class PlotViewTests
|
||||
{
|
||||
[Fact]
|
||||
public void DecimatePoints_ReturnsOriginalList_WhenPointsCountSmall()
|
||||
{
|
||||
var points = new List<PlotPointViewModel>
|
||||
{
|
||||
new(DateTime.UtcNow, 1.0),
|
||||
new(DateTime.UtcNow.AddSeconds(1), 2.0),
|
||||
new(DateTime.UtcNow.AddSeconds(2), 3.0),
|
||||
};
|
||||
|
||||
var result = PlotView.DecimatePoints(points, 10);
|
||||
|
||||
Assert.Equal(points.Count, result.Count);
|
||||
Assert.Equal(points, result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DecimatePoints_DecimatesAndMaintainsEnvelope_WhenPointsCountLarge()
|
||||
{
|
||||
// 1000 points, decimate to targetWidth = 100
|
||||
var points = new List<PlotPointViewModel>();
|
||||
var baseTime = DateTime.UtcNow;
|
||||
for (int i = 0; i < 1000; i++)
|
||||
{
|
||||
// Create a sine wave with some noise/spikes
|
||||
double val = Math.Sin(i * 0.1);
|
||||
if (i == 505) val = 100.0; // extreme max spike
|
||||
if (i == 510) val = -100.0; // extreme min spike
|
||||
points.Add(new PlotPointViewModel(baseTime.AddSeconds(i), val));
|
||||
}
|
||||
|
||||
var result = PlotView.DecimatePoints(points, 100);
|
||||
|
||||
// Result should be decimated (less than original, but bounds preserved)
|
||||
Assert.True(result.Count < points.Count);
|
||||
Assert.True(result.Count >= 100);
|
||||
|
||||
// Extreme spike values must be preserved in the output
|
||||
Assert.Contains(result, p => p.Value == 100.0);
|
||||
Assert.Contains(result, p => p.Value == -100.0);
|
||||
|
||||
// Rightmost point (latest sample) must be exactly preserved
|
||||
Assert.Equal(points[^1].Timestamp, result[^1].Timestamp);
|
||||
Assert.Equal(points[^1].Value, result[^1].Value);
|
||||
}
|
||||
}
|
||||
@@ -458,7 +458,9 @@ public sealed class PlotView : Grid
|
||||
StrokeLineJoin = PenLineJoin.Round
|
||||
};
|
||||
|
||||
foreach (PlotPointViewModel point in sample.Points)
|
||||
IReadOnlyList<PlotPointViewModel> decimatedPoints = DecimatePoints(sample.Points, (int)Math.Max(100, bounds.Width));
|
||||
|
||||
foreach (PlotPointViewModel point in decimatedPoints)
|
||||
{
|
||||
double x = bounds.Left + (point.Timestamp - minTimestamp).Ticks / (double)rangeTicks * bounds.Width;
|
||||
double y = axis.Bottom - ((point.Value - axis.MinValue) / (axis.MaxValue - axis.MinValue) * axis.Height);
|
||||
@@ -470,6 +472,57 @@ public sealed class PlotView : Grid
|
||||
DrawPointMarker(canvas, line.Points[^1], stroke);
|
||||
}
|
||||
|
||||
internal static IReadOnlyList<PlotPointViewModel> DecimatePoints(IReadOnlyList<PlotPointViewModel> points, int targetWidth)
|
||||
{
|
||||
if (points.Count <= targetWidth * 2)
|
||||
return points;
|
||||
|
||||
List<PlotPointViewModel> result = new();
|
||||
int bucketSize = points.Count / targetWidth;
|
||||
if (bucketSize <= 1)
|
||||
return points;
|
||||
|
||||
for (int i = 0; i < targetWidth; i++)
|
||||
{
|
||||
int start = i * bucketSize;
|
||||
int end = (i == targetWidth - 1) ? points.Count : (i + 1) * bucketSize;
|
||||
if (start >= end)
|
||||
break;
|
||||
|
||||
int minIdx = start;
|
||||
int maxIdx = start;
|
||||
for (int j = start + 1; j < end; j++)
|
||||
{
|
||||
if (points[j].Value < points[minIdx].Value)
|
||||
minIdx = j;
|
||||
if (points[j].Value > points[maxIdx].Value)
|
||||
maxIdx = j;
|
||||
}
|
||||
|
||||
if (minIdx == maxIdx)
|
||||
{
|
||||
result.Add(points[minIdx]);
|
||||
}
|
||||
else if (minIdx < maxIdx)
|
||||
{
|
||||
result.Add(points[minIdx]);
|
||||
result.Add(points[maxIdx]);
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Add(points[maxIdx]);
|
||||
result.Add(points[minIdx]);
|
||||
}
|
||||
}
|
||||
|
||||
if (result.Count > 0 && result[^1].Timestamp != points[^1].Timestamp)
|
||||
{
|
||||
result.Add(points[^1]);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void DrawPlotMessage(Canvas canvas, PlotBounds bounds, string message)
|
||||
{
|
||||
TextBlock label = CreatePlotLabel(message, new SolidColorBrush(GetPlotTextColor()), 13, 600);
|
||||
|
||||
@@ -66,16 +66,25 @@ internal sealed class WindowPlacementService
|
||||
|
||||
public void Maximize()
|
||||
{
|
||||
if (_appWindow.Presenter is OverlappedPresenter presenter)
|
||||
if (_settings.GetValue(_settingPrefix + "Maximized", false) && _appWindow.Presenter is OverlappedPresenter presenter)
|
||||
presenter.Maximize();
|
||||
}
|
||||
|
||||
public void Save()
|
||||
{
|
||||
_settings.SetValue(_settingPrefix + "Location.X", _appWindow.Position.X);
|
||||
_settings.SetValue(_settingPrefix + "Location.Y", _appWindow.Position.Y);
|
||||
_settings.SetValue(_settingPrefix + "Width", _appWindow.Size.Width);
|
||||
_settings.SetValue(_settingPrefix + "Height", _appWindow.Size.Height);
|
||||
if (_appWindow.Presenter is OverlappedPresenter presenter)
|
||||
{
|
||||
bool maximized = presenter.State == OverlappedPresenterState.Maximized;
|
||||
_settings.SetValue(_settingPrefix + "Maximized", maximized);
|
||||
|
||||
if (presenter.State == OverlappedPresenterState.Restored)
|
||||
{
|
||||
_settings.SetValue(_settingPrefix + "Location.X", _appWindow.Position.X);
|
||||
_settings.SetValue(_settingPrefix + "Location.Y", _appWindow.Position.Y);
|
||||
_settings.SetValue(_settingPrefix + "Width", _appWindow.Size.Width);
|
||||
_settings.SetValue(_settingPrefix + "Height", _appWindow.Size.Height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
|
||||
Reference in New Issue
Block a user