Improved chart visual
This commit is contained in:
@@ -8,6 +8,7 @@ namespace BattSim.Models
|
|||||||
public bool DayTariff { get; set; }
|
public bool DayTariff { get; set; }
|
||||||
public double Consumption { get; set; }
|
public double Consumption { get; set; }
|
||||||
public double Production { get; set; }
|
public double Production { get; set; }
|
||||||
|
public double BatteryCharge { get; set; }
|
||||||
|
|
||||||
public EnergyData(){}
|
public EnergyData(){}
|
||||||
public EnergyData(EnergyData other)
|
public EnergyData(EnergyData other)
|
||||||
@@ -16,6 +17,7 @@ namespace BattSim.Models
|
|||||||
DayTariff = other.DayTariff;
|
DayTariff = other.DayTariff;
|
||||||
Consumption = other.Consumption;
|
Consumption = other.Consumption;
|
||||||
Production = other.Production;
|
Production = other.Production;
|
||||||
|
BatteryCharge = other.BatteryCharge;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace BattSim.Models
|
|
||||||
{
|
|
||||||
public class SimulatedBatteryEnergyData : EnergyData
|
|
||||||
{
|
|
||||||
public double BatteryCharge { get; set; }
|
|
||||||
public double SimulatedConsumption { get; set; }
|
|
||||||
public double SimulatedProduction { get; set; }
|
|
||||||
|
|
||||||
public SimulatedBatteryEnergyData(EnergyData energyData) : base(energyData) { }
|
|
||||||
public SimulatedBatteryEnergyData(SimulatedBatteryEnergyData simulatedBatteryEnergyData) : base(simulatedBatteryEnergyData)
|
|
||||||
{
|
|
||||||
BatteryCharge = simulatedBatteryEnergyData.BatteryCharge;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -267,7 +267,7 @@
|
|||||||
|
|
||||||
|
|
||||||
<!-- Chart - Directly on page, full width -->
|
<!-- Chart - Directly on page, full width -->
|
||||||
@if (FluviusDataDaily.Length > 0)
|
@if (FilteredFluviusData.Length > 0)
|
||||||
{
|
{
|
||||||
<div class="chart-container">
|
<div class="chart-container">
|
||||||
<h2>Overzicht: Energie Data & Simulatie</h2>
|
<h2>Overzicht: Energie Data & Simulatie</h2>
|
||||||
@@ -299,7 +299,7 @@
|
|||||||
</RadzenAreaSeries>
|
</RadzenAreaSeries>
|
||||||
|
|
||||||
<!-- Simulated Data -->
|
<!-- Simulated Data -->
|
||||||
@if (SimulationDataDaily.Length > 0)
|
@if (FilteredSimulationData.Length > 0)
|
||||||
{
|
{
|
||||||
<RadzenAreaSeries Smooth=true Data="@FilteredSimulationData" CategoryProperty="Time" Title="Simulated Consumption" ValueProperty="Consumption">
|
<RadzenAreaSeries Smooth=true Data="@FilteredSimulationData" CategoryProperty="Time" Title="Simulated Consumption" ValueProperty="Consumption">
|
||||||
</RadzenAreaSeries>
|
</RadzenAreaSeries>
|
||||||
@@ -323,13 +323,12 @@
|
|||||||
|
|
||||||
@code {
|
@code {
|
||||||
EnergyData[] FluviusDataRaw = [];
|
EnergyData[] FluviusDataRaw = [];
|
||||||
EnergyData[] FluviusDataDaily = [];
|
EnergyData[] SimulationData = [];
|
||||||
|
|
||||||
SimulatedBatteryEnergyData[] SimulationData = [];
|
DataFilter.FilterOption SelectedFilterOption = DataFilter.FilterOption.ALL;
|
||||||
SimulatedBatteryEnergyData[] SimulationDataDaily = [];
|
|
||||||
|
|
||||||
EnergyData[] FilteredFluviusData = [];
|
EnergyData[] FilteredFluviusData = [];
|
||||||
SimulatedBatteryEnergyData[] FilteredSimulationData = [];
|
EnergyData[] FilteredSimulationData = [];
|
||||||
|
|
||||||
EnergyCostCalculator calculator = new();
|
EnergyCostCalculator calculator = new();
|
||||||
double normalCost = 0.0;
|
double normalCost = 0.0;
|
||||||
@@ -406,8 +405,7 @@
|
|||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
|
|
||||||
FluviusDataRaw = await FluviusDataHandler.LoadAndProcessFile(file);
|
FluviusDataRaw = await FluviusDataHandler.LoadAndProcessFile(file);
|
||||||
FluviusDataDaily = FluviusDataHandler.GenerateDailyData(FluviusDataRaw);
|
SetTimePeriod("all");
|
||||||
FilteredFluviusData = FluviusDataDaily;
|
|
||||||
FilteredSimulationData = [];
|
FilteredSimulationData = [];
|
||||||
|
|
||||||
StepData[0].isProcessing = false;
|
StepData[0].isProcessing = false;
|
||||||
@@ -415,7 +413,6 @@
|
|||||||
StepData[1].Completed = false;
|
StepData[1].Completed = false;
|
||||||
StepData[2].Completed = false;
|
StepData[2].Completed = false;
|
||||||
SimulationData = [];
|
SimulationData = [];
|
||||||
SimulationDataDaily = [];
|
|
||||||
|
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
@@ -437,8 +434,7 @@
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
SimulationData = BatterySimulator.SimulateBattery(FluviusDataRaw, BatteryCapacity, Efficiency/100);
|
SimulationData = BatterySimulator.SimulateBattery(FluviusDataRaw, BatteryCapacity, Efficiency/100);
|
||||||
SimulationDataDaily = BatterySimulator.GenerateDailyData(SimulationData);
|
SetTimePeriod("all");
|
||||||
FilteredSimulationData = SimulationDataDaily;
|
|
||||||
|
|
||||||
StepData[1].isProcessing = false;
|
StepData[1].isProcessing = false;
|
||||||
StepData[1].Completed = true;
|
StepData[1].Completed = true;
|
||||||
@@ -465,8 +461,6 @@
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
normalCost = calculator.CalculateCostOfEnergyUsage(FluviusDataRaw);
|
normalCost = calculator.CalculateCostOfEnergyUsage(FluviusDataRaw);
|
||||||
simulatedCost = calculator.CalculateCostOfEnergyUsage(SimulationData);
|
|
||||||
|
|
||||||
StepData[2].isProcessing = false;
|
StepData[2].isProcessing = false;
|
||||||
StepData[2].Completed = true;
|
StepData[2].Completed = true;
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
@@ -481,63 +475,20 @@
|
|||||||
private void SetTimePeriod(string period)
|
private void SetTimePeriod(string period)
|
||||||
{
|
{
|
||||||
_timePeriod = period;
|
_timePeriod = period;
|
||||||
|
var filterOption = period switch {
|
||||||
|
"all" => DataFilter.FilterOption.ALL,
|
||||||
|
"year" => DataFilter.FilterOption.YEAR,
|
||||||
|
"month" => DataFilter.FilterOption.MONTH,
|
||||||
|
"week" => DataFilter.FilterOption.WEEK,
|
||||||
|
"day" => DataFilter.FilterOption.DAY,
|
||||||
|
};
|
||||||
// Filter data based on selected period
|
// Filter data based on selected period
|
||||||
FilteredFluviusData = FilterFluviusDataByPeriod(period);
|
if(FluviusDataRaw.Length > 0) FilteredFluviusData = DataFilter.FilterData(FluviusDataRaw, filterOption);
|
||||||
FilteredSimulationData = FilterSimulationDataByPeriod(period);
|
if(FilteredSimulationData.Length > 0) FilteredSimulationData = DataFilter.FilterData(SimulationData, filterOption);
|
||||||
|
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
private EnergyData[] FilterFluviusDataByPeriod(string period)
|
|
||||||
{
|
|
||||||
if (period == "all" || FluviusDataDaily.Length == 0)
|
|
||||||
return FluviusDataDaily;
|
|
||||||
|
|
||||||
var result = new List<EnergyData>();
|
|
||||||
|
|
||||||
foreach (var item in FluviusDataDaily)
|
|
||||||
{
|
|
||||||
// The Time property is DateTime but for daily data it represents the day
|
|
||||||
var date = DateOnly.FromDateTime(item.Time);
|
|
||||||
bool include = false;
|
|
||||||
switch (period)
|
|
||||||
{
|
|
||||||
case "day": include = true; break; // Show all daily data
|
|
||||||
case "week": include = date.DayOfWeek == DayOfWeek.Monday; break;
|
|
||||||
case "month": include = date.Day == 1; break;
|
|
||||||
case "year": include = date.Month == 1 && date.Day == 1; break;
|
|
||||||
}
|
|
||||||
if (include) result.Add(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result.ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
private SimulatedBatteryEnergyData[] FilterSimulationDataByPeriod(string period)
|
|
||||||
{
|
|
||||||
if (period == "all" || SimulationDataDaily.Length == 0)
|
|
||||||
return SimulationDataDaily;
|
|
||||||
|
|
||||||
var result = new List<SimulatedBatteryEnergyData>();
|
|
||||||
|
|
||||||
foreach (var item in SimulationDataDaily)
|
|
||||||
{
|
|
||||||
var date = DateOnly.FromDateTime(item.Time);
|
|
||||||
bool include = false;
|
|
||||||
switch (period)
|
|
||||||
{
|
|
||||||
case "day": include = true; break;
|
|
||||||
case "week": include = date.DayOfWeek == DayOfWeek.Monday; break;
|
|
||||||
case "month": include = date.Day == 1; break;
|
|
||||||
case "year": include = date.Month == 1 && date.Day == 1; break;
|
|
||||||
}
|
|
||||||
if (include) result.Add(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result.ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
private string FormatObject(object value) {
|
private string FormatObject(object value) {
|
||||||
if(value is double d) return $"{d:0.##} kWh";
|
if(value is double d) return $"{d:0.##} kWh";
|
||||||
if(value is DateTime time) return time.ToString("dd/MM/yyyy");
|
if(value is DateTime time) return time.ToString("dd/MM/yyyy");
|
||||||
|
|||||||
@@ -6,14 +6,14 @@ namespace BattSim.Services
|
|||||||
{
|
{
|
||||||
public static class BatterySimulator
|
public static class BatterySimulator
|
||||||
{
|
{
|
||||||
public static SimulatedBatteryEnergyData[] SimulateBattery(EnergyData[] energyData, double batteryCapacity, double efficiency)
|
public static EnergyData[] SimulateBattery(EnergyData[] energyData, double batteryCapacity, double efficiency)
|
||||||
{
|
{
|
||||||
var results = new List<SimulatedBatteryEnergyData>();
|
var results = new List<EnergyData>();
|
||||||
double batteryCharge = 0;
|
double batteryCharge = 0;
|
||||||
|
|
||||||
foreach (var e in energyData)
|
foreach (var e in energyData)
|
||||||
{
|
{
|
||||||
var simulatedBatteryEnergyData = new SimulatedBatteryEnergyData(e);
|
var simulatedBatteryEnergyData = new EnergyData(e);
|
||||||
// Simulate charging the battery based on production
|
// Simulate charging the battery based on production
|
||||||
double excessProduction = batteryCharge + e.Production - batteryCapacity;
|
double excessProduction = batteryCharge + e.Production - batteryCapacity;
|
||||||
batteryCharge = double.Min(batteryCharge + e.Production, batteryCapacity);
|
batteryCharge = double.Min(batteryCharge + e.Production, batteryCapacity);
|
||||||
@@ -33,30 +33,5 @@ namespace BattSim.Services
|
|||||||
|
|
||||||
return results.ToArray();
|
return results.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SimulatedBatteryEnergyData[] GenerateDailyData(SimulatedBatteryEnergyData[] simulationData)
|
|
||||||
{
|
|
||||||
var simulationDataCopy = (SimulatedBatteryEnergyData[]) simulationData.Clone();
|
|
||||||
var dailySimulationData = new ConcurrentDictionary<DateOnly, SimulatedBatteryEnergyData>();
|
|
||||||
Parallel.ForEach(simulationDataCopy, simulationPoint =>
|
|
||||||
{
|
|
||||||
var date = DateOnly.FromDateTime(simulationPoint.Time);
|
|
||||||
|
|
||||||
// Use AddOrUpdate to avoid double lookup
|
|
||||||
dailySimulationData.AddOrUpdate(
|
|
||||||
date,
|
|
||||||
new SimulatedBatteryEnergyData(simulationPoint), // If key doesn't exist, add this value
|
|
||||||
(_, existing) =>
|
|
||||||
{
|
|
||||||
// If key exists, aggregate the values
|
|
||||||
existing.Consumption += simulationPoint.Consumption;
|
|
||||||
existing.Production += simulationPoint.Production;
|
|
||||||
existing.BatteryCharge = double.Max(existing.BatteryCharge, simulationPoint.BatteryCharge);
|
|
||||||
return existing;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
||||||
return dailySimulationData.Values.ToArray();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
30
Services/DataFilter.cs
Normal file
30
Services/DataFilter.cs
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using BattSim.Models;
|
||||||
|
|
||||||
|
namespace BattSim.Services
|
||||||
|
{
|
||||||
|
public static class DataFilter
|
||||||
|
{
|
||||||
|
public enum FilterOption { ALL, YEAR, MONTH, WEEK, DAY }
|
||||||
|
public static EnergyData[] FilterData(EnergyData[] data, FilterOption filterOption)
|
||||||
|
{
|
||||||
|
var dailyData = data
|
||||||
|
.GroupBy(d=>d.Time.Date)
|
||||||
|
.Select(group=> new EnergyData{
|
||||||
|
Consumption = group.Sum(d => d.Consumption),
|
||||||
|
Production = group.Sum(d => d.Production),
|
||||||
|
BatteryCharge = group.Max(d => d.BatteryCharge),
|
||||||
|
Time = group.First().Time
|
||||||
|
}).ToArray();
|
||||||
|
|
||||||
|
return filterOption switch {
|
||||||
|
FilterOption.DAY => data[(data.Length > 96?data.Length - 96:0)..], // 24 hours * 4 quarters per hour
|
||||||
|
FilterOption.WEEK => data[(data.Length > 672?data.Length - 672:0)..], // 7 days * 24 hours * 4 quarters per hour
|
||||||
|
FilterOption.MONTH => dailyData[(dailyData.Length > 30?dailyData.Length - 30:0)..],
|
||||||
|
FilterOption.YEAR => dailyData[(dailyData.Length > 365?dailyData.Length - 365:0)..],
|
||||||
|
_ => dailyData
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user