Changed from daily records to quarter hour records

This commit is contained in:
douwe
2026-04-13 16:14:54 +02:00
parent 9f1fbcdd5a
commit 992b7f02ea
8 changed files with 105 additions and 271 deletions

View File

@@ -1,4 +1,5 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
@@ -13,61 +14,85 @@ namespace BattSim.Services
{
public static async Task<List<EnergyData>> LoadAndProcessData(IBrowserFile file)
{
var energyData = new List<EnergyData>();
await using var stream = file.OpenReadStream();
using var reader = new StreamReader(stream);
var energyData = new ConcurrentBag<EnergyData>(); // Thread-safe collection
await using var stream = file.OpenReadStream(maxAllowedSize: (int)1.0e9);
using var reader = new StreamReader(stream, bufferSize: (int)1.0e6);
// Skip header
await reader.ReadLineAsync();
// Read all lines into memory
var lines = new List<string>();
string line;
while ((line = await reader.ReadLineAsync()) != null)
while ((line = await reader.ReadLineAsync()) is not null)
{
var parts = line.Split(';');
if (parts.Length < 9)
{
Console.WriteLine($"Skipping malformed line: {line}");
continue;
}
lines.Add(line);
}
// Process lines in parallel
Parallel.ForEach(lines, line =>
{
try
{
var date = DateOnly.ParseExact(parts[0].Length == 10 ? parts[0] : "0"+parts[0], "dd/MM/yyyy", CultureInfo.InvariantCulture);
var register = parts[7].Trim();
var volumeStr = parts[8].Trim();
var volume = string.IsNullOrEmpty(volumeStr)
? 0
: double.Parse(volumeStr.Replace(",", "."), CultureInfo.InvariantCulture);
var parts = SplitLine(line);
DateTime time = ParseDateTime(parts[0..2]);
double volume = ParseVolume(parts[8]);
string register = parts[7].Trim();
bool dayTarif = register.Contains("Dag");
var existing = energyData.FirstOrDefault(e => e.Date == date);
if (existing == null)
{
existing = new EnergyData { Date = date };
energyData.Add(existing);
}
// Use ConcurrentBag for thread-safe additions
var entry = new EnergyData { Time = time, DayTarif = dayTarif };
if (register.Contains("Afname"))
entry.Consumption = volume;
else if (register.Contains("Injectie"))
entry.Production = volume;
else
throw new Exception("Unknown volume register");
switch (register)
{
case "Afname Dag":
existing.DayConsumption = volume;
break;
case "Afname Nacht":
existing.NightConsumption = volume;
break;
case "Injectie Dag":
existing.DayProduction = volume;
break;
case "Injectie Nacht":
existing.NightProduction = volume;
break;
}
energyData.Add(entry);
}
catch (Exception ex)
catch (Exception e)
{
Console.WriteLine($"Error parsing line: {line}. Exception: {ex.Message}");
Console.WriteLine($"Error parsing line: {line}. Skipping to next line. Exception: {e}");
}
}
return energyData;
});
// Group by Time and merge entries
var groupedData = energyData
.GroupBy(e => e.Time)
.Select(g =>
{
var first = g.First();
first.Consumption = g.Sum(e => e.Consumption);
first.Production = g.Sum(e => e.Production);
return first;
})
.OrderBy(e => e.Time)
.ToList();
return groupedData;
}
}
private static string[] SplitLine(string line)
{
var parts = line.Split(';');
if (parts.Length < 9)
throw new Exception($"Malformed line (too many parts): {line}");
return parts;
}
private static DateTime ParseDateTime(string[] dateTimeStrings)
{
string dateTimeString = dateTimeStrings[0] + " " + dateTimeStrings[1];
return DateTime.ParseExact(dateTimeString, "dd-MM-yyyy HH:mm:ss", CultureInfo.GetCultureInfo("nl-BE"));
}
private static double ParseVolume(string volumeString)
{
var volumeStr = volumeString.Trim();
return string.IsNullOrEmpty(volumeStr)
? 0
: double.Parse(volumeStr.Replace(",", "."), CultureInfo.InvariantCulture);
}
}
}