diff --git a/src/ProfHeat.AUI/ViewModels/DataVisualizerViewModel.cs b/src/ProfHeat.AUI/ViewModels/DataVisualizerViewModel.cs index 787390a..0e2aa9b 100644 --- a/src/ProfHeat.AUI/ViewModels/DataVisualizerViewModel.cs +++ b/src/ProfHeat.AUI/ViewModels/DataVisualizerViewModel.cs @@ -16,8 +16,10 @@ using LiveChartsCore.Defaults; using LiveChartsCore.Drawing; using LiveChartsCore.SkiaSharpView; +using LiveChartsCore.SkiaSharpView.Painting; using ProfHeat.Core.Interfaces; using ProfHeat.Core.Models; +using SkiaSharp; namespace ProfHeat.AUI.ViewModels; @@ -25,7 +27,7 @@ public partial class DataVisualizerViewModel : BaseViewModel { #region Fields // Instances of managers. - private readonly IResultDataManager _ResultDataManager; + private readonly IResultDataManager _resultDataManager; // Observable properties. [ObservableProperty, NotifyCanExecuteChangedFor(nameof(ExportResultsCommand))] @@ -53,13 +55,23 @@ public string SelectedPeriod public ObservableCollection ProducedHeat => GetLineSeries(result => result.ProducedHeat); public ObservableCollection GasConsumption => GetLineSeries(result => result.GasConsumption); public ObservableCollection ElectricityProduced => GetLineSeries(result => result.ElectricityProduced); - public static Axis[] XAxes => [new DateTimeAxis(TimeSpan.FromHours(1), date => date.ToString("yy MMM dd',' HH'h'"))]; + public static DrawMarginFrame DrawMarginFrame => new() { Stroke = new SolidColorPaint(SKColors.White, 1) }; + public static Axis[] XAxes => + [new DateTimeAxis(TimeSpan.FromHours(1), date => date.ToString("yy MMM dd',' HH'h'")) + { LabelsPaint = new SolidColorPaint(SKColors.White) }]; + public static Axis[] CostsYAxis { get; } = GetYAxis("DKK / MWh(th)"); + public static Axis[] CO2EmissionsYAxis { get; } = GetYAxis("kg / MWh(th)"); + public static Axis[] ProducedHeatYAxis { get; } = GetYAxis("MW"); + public static Axis[] GasConsumptionYAxis { get; } = GetYAxis("MWh(gas) / MWh(th)"); + public static Axis[] ElectricityProducedYAxis { get; } = GetYAxis("MW"); + public SolidColorPaint LegendTextPaint { get; } = new() { Color = SKColors.White }; + #endregion #region Constructor public DataVisualizerViewModel(IResultDataManager resultDataManager, List results) { - _ResultDataManager = resultDataManager; + _resultDataManager = resultDataManager; SelectedPeriod = Periods[0]; Results = results; } @@ -77,7 +89,7 @@ public async Task ImportResults(string filePath = null!) if (!string.IsNullOrEmpty(filePath)) { Results.Clear(); - Results.AddRange(_ResultDataManager.LoadResultData(filePath)); + Results.AddRange(_resultDataManager.LoadResultData(filePath)); OnPropertyChanged(nameof(Results)); OnPropertyChanged(nameof(Costs)); @@ -105,7 +117,7 @@ public async Task ExportResults(string filePath = null!) if (!string.IsNullOrEmpty(filePath)) { - _ResultDataManager.SaveResultData(Results, filePath!); + _resultDataManager.SaveResultData(Results, filePath!); } } catch (Exception exception) @@ -133,5 +145,13 @@ private ObservableCollection GetLineSeries(Func + [new Axis + { + Name = metric, + NamePaint = new SolidColorPaint(SKColors.White), + LabelsPaint = new SolidColorPaint(SKColors.White) + }]; #endregion } diff --git a/src/ProfHeat.AUI/ViewModels/MainWindowViewModel.cs b/src/ProfHeat.AUI/ViewModels/MainWindowViewModel.cs index 63c0cca..5212c13 100644 --- a/src/ProfHeat.AUI/ViewModels/MainWindowViewModel.cs +++ b/src/ProfHeat.AUI/ViewModels/MainWindowViewModel.cs @@ -18,7 +18,7 @@ namespace ProfHeat.AUI.ViewModels; -public class MainWindowViewModel : BaseViewModel +public partial class MainWindowViewModel : BaseViewModel { #region Fields // Instances of managers. @@ -27,12 +27,16 @@ public class MainWindowViewModel : BaseViewModel Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Data", "HeatingGrid.config") // Path to HeatingGrid.config. ); private readonly ISourceDataManager _sourceDataManager = new SourceDataManager(new CsvRepository()); - private readonly IResultDataManager _ResultDataManager = new ResultDataManager(new CsvRepository()); + private readonly IResultDataManager _resultDataManager = new ResultDataManager(new CsvRepository()); private readonly IOptimizer _optimizer = new Optimizer(); // List of optimization results. private readonly List _results = []; + // Observable properties. + [ObservableProperty] + private int _selectedTabIndex = 0; // Sets Optimizer tab as default. + // ViewModels for the tabs. public OptimizerViewModel Optimizer { get; } public DataVisualizerViewModel DataVisualizer { get; } @@ -41,8 +45,12 @@ public class MainWindowViewModel : BaseViewModel #region Constructor public MainWindowViewModel() { - Optimizer = new OptimizerViewModel(_assetManager, _sourceDataManager, _optimizer, _results); - DataVisualizer = new DataVisualizerViewModel(_ResultDataManager, _results); + Optimizer = new OptimizerViewModel(_assetManager, _sourceDataManager, _optimizer, _results, ChangeTab); + DataVisualizer = new DataVisualizerViewModel(_resultDataManager, _results); } #endregion + + #region Helper Methods + private void ChangeTab(int tabIndex) => SelectedTabIndex = tabIndex; + #endregion } diff --git a/src/ProfHeat.AUI/ViewModels/OptimizerViewModel.cs b/src/ProfHeat.AUI/ViewModels/OptimizerViewModel.cs index b22e97e..5a1875b 100644 --- a/src/ProfHeat.AUI/ViewModels/OptimizerViewModel.cs +++ b/src/ProfHeat.AUI/ViewModels/OptimizerViewModel.cs @@ -28,6 +28,7 @@ public partial class OptimizerViewModel : BaseViewModel private readonly HeatingGrid _grid; private readonly List _marketConditions = []; private readonly List _results; + private readonly Action _changeTab; // Observable properties. public ObservableCollection CheckBoxItems { get; } @@ -36,11 +37,12 @@ public partial class OptimizerViewModel : BaseViewModel #endregion #region Constructor - public OptimizerViewModel(IAssetManager assetManager, ISourceDataManager sourceDataManager, IOptimizer optimizer, List results) + public OptimizerViewModel(IAssetManager assetManager, ISourceDataManager sourceDataManager, IOptimizer optimizer, List results, Action changeTab) { _sourceDataManager = sourceDataManager; _optimizer = optimizer; _results = results; + _changeTab = changeTab; _grid = assetManager.LoadAssets(); // initialize CheckBoxItems for UI. @@ -101,6 +103,7 @@ public void Optimize() { _results.Clear(); _results.AddRange(optimizationResults); + _changeTab?.Invoke(1); // Changes tab to Data Visualizer. } } catch (Exception exception) diff --git a/src/ProfHeat.AUI/Views/DataVisualizerView.axaml b/src/ProfHeat.AUI/Views/DataVisualizerView.axaml index 49c62cb..b061c78 100644 --- a/src/ProfHeat.AUI/Views/DataVisualizerView.axaml +++ b/src/ProfHeat.AUI/Views/DataVisualizerView.axaml @@ -9,7 +9,7 @@ x:Class="ProfHeat.AUI.Views.DataVisualizerView" x:DataType="vm:DataVisualizerViewModel" xmlns:lvc="using:LiveChartsCore.SkiaSharpView.Avalonia"> - + @@ -40,28 +40,53 @@ + YAxes="{Binding CostsYAxis}" + LegendPosition="Bottom" + LegendTextPaint="{Binding LegendTextPaint}" + ZoomMode="ZoomX" + DrawMarginFrame="{Binding DrawMarginFrame}"/> + YAxes="{Binding CO2EmissionsYAxis}" + LegendPosition="Bottom" + LegendTextPaint="{Binding LegendTextPaint}" + ZoomMode="ZoomX" + DrawMarginFrame="{Binding DrawMarginFrame}"/> + YAxes="{Binding ProducedHeatYAxis}" + LegendPosition="Bottom" + LegendTextPaint="{Binding LegendTextPaint}" + ZoomMode="ZoomX" + DrawMarginFrame="{Binding DrawMarginFrame}"/> + YAxes="{Binding GasConsumptionYAxis}" + LegendPosition="Bottom" + LegendTextPaint="{Binding LegendTextPaint}" + ZoomMode="ZoomX" + DrawMarginFrame="{Binding DrawMarginFrame}"/> + YAxes="{Binding ElectricityProducedYAxis}" + LegendPosition="Bottom" + LegendTextPaint="{Binding LegendTextPaint}" + ZoomMode="ZoomX" + DrawMarginFrame="{Binding DrawMarginFrame}"/> diff --git a/src/ProfHeat.AUI/Views/MainWindow.axaml b/src/ProfHeat.AUI/Views/MainWindow.axaml index b70afc6..dccefc4 100644 --- a/src/ProfHeat.AUI/Views/MainWindow.axaml +++ b/src/ProfHeat.AUI/Views/MainWindow.axaml @@ -38,7 +38,8 @@ IsAddTabButtonVisible="False" CanDragTabs="False" CanReorderTabs="False" - AllowDropTabs="False"> + AllowDropTabs="False" + SelectedIndex="{Binding SelectedTabIndex}"> diff --git a/tests/ProfHeat.AUI.Tests/ViewModels/OptimizerViewModelTests.cs b/tests/ProfHeat.AUI.Tests/ViewModels/OptimizerViewModelTests.cs index 4feeda2..0501280 100644 --- a/tests/ProfHeat.AUI.Tests/ViewModels/OptimizerViewModelTests.cs +++ b/tests/ProfHeat.AUI.Tests/ViewModels/OptimizerViewModelTests.cs @@ -24,11 +24,12 @@ public class OptimizerViewModelTests private readonly Mock _mockAssetManager = new(); private readonly Mock _mockSourceDataManager = new(); private readonly Mock _mockOptimizer = new(); + private readonly Mock> _mockChangeTab = new(); private readonly List _marketConditions = [new( new DateTime(2023, 02, 08, 0, 0, 0, DateTimeKind.Unspecified), new DateTime(2023, 02, 08, 1, 0, 0, DateTimeKind.Unspecified), 10.111, 10.111)]; - private readonly HeatingGrid _grid = new ("test", "/test.svg", 1000, [new ("Gas Boiler", "/Assets/Images/GasBoiler.svg", 5, 500, 215, 1.01, 0)]); + private readonly HeatingGrid _grid = new("test", "/test.svg", 1000, [new("Gas Boiler", "/Assets/Images/GasBoiler.svg", 5, 500, 215, 1.01, 0)]); private readonly List _results = []; private readonly OptimizerViewModel _viewModel; private const string _filePath = "testFile.csv"; @@ -36,7 +37,7 @@ public class OptimizerViewModelTests public OptimizerViewModelTests() { _ = _mockAssetManager.Setup(x => x.LoadAssets()).Returns(_grid); - _viewModel = new OptimizerViewModel(_mockAssetManager.Object, _mockSourceDataManager.Object, _mockOptimizer.Object, _results); + _viewModel = new OptimizerViewModel(_mockAssetManager.Object, _mockSourceDataManager.Object, _mockOptimizer.Object, _results, _mockChangeTab.Object); } [Fact] @@ -83,5 +84,6 @@ public void OptimizeCommand_Executes() // Assert _mockOptimizer.Verify(sourceDataManager => sourceDataManager.Optimize(selectedUnits, It.IsAny>()), Times.Once()); Assert.NotEmpty(_results); + _mockChangeTab.Verify(changeTab => changeTab.Invoke(1), Times.Once()); } } diff --git a/tests/ProfHeat.Core.Tests/RepositoryTests/XmlRepositoryTests.cs b/tests/ProfHeat.Core.Tests/RepositoryTests/XmlRepositoryTests.cs index 3f796df..9f097bd 100644 --- a/tests/ProfHeat.Core.Tests/RepositoryTests/XmlRepositoryTests.cs +++ b/tests/ProfHeat.Core.Tests/RepositoryTests/XmlRepositoryTests.cs @@ -90,7 +90,7 @@ public void Save_Test() repository.Save(data, _filePath); // Assert - Assert.Equal(_testFile.Replace(" ",""), File.ReadAllText(_filePath).Replace(" ", "")); + Assert.Equal(_testFile.Replace(" ", ""), File.ReadAllText(_filePath).Replace(" ", "")); } [Fact]