M1: pure normalization engine + default seed
Infrastructure-free normalization engine in Core dispatching on MeterMode: - Cumulative/Generation counters: register deltas, first-reading baseline (Haus 411, Auto 3755), meter swaps (water …861→2 reconciles to 12 via boundary registers OR an explicit amount override), counter resets, anomaly-guarded decreases. - RuntimeCounter: Δhours × rate (fixed/empirical). - ConsumableBalance: tank level-Δ + deliveries → consumption, cm→litre calibration; delivery-only rows before the first dipstick emit nothing. - DirectDelta, and Virtual meters via a small safe arithmetic evaluator (Netz Einsparung = Haus − Netz, Eigenverbrauch = Erzeugung − Einsparung) — data-driven, not hardcoded. - DatabaseSeeder: default energy types, cost categories, base settings (idempotent). 24 Core unit tests + 4 integration tests green. Claude-Session: https://claude.ai/code/session_01WujdMtMJPbxDpDnMeK22rr
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
using MeterVault.Core.Domain;
|
||||
|
||||
namespace MeterVault.Core.Tests;
|
||||
|
||||
/// <summary>Terse builders for readings/events/configs in normalizer tests.</summary>
|
||||
internal static class TestData
|
||||
{
|
||||
public static DateTimeOffset Month(int year, int month) =>
|
||||
new(new DateTime(year, month, 1, 0, 0, 0, DateTimeKind.Utc));
|
||||
|
||||
public static Reading Reading(int meterId, DateTimeOffset time, double value) => new()
|
||||
{
|
||||
MeterId = meterId,
|
||||
Time = time,
|
||||
Value = value,
|
||||
Quality = ReadingQuality.Imported,
|
||||
};
|
||||
|
||||
public static MeterEvent Swap(int meterId, DateTimeOffset time, double? prevValue = null,
|
||||
double? newValue = null, double? amount = null) => new()
|
||||
{
|
||||
MeterId = meterId,
|
||||
Time = time,
|
||||
EventType = MeterEventType.MeterSwap,
|
||||
PrevValue = prevValue,
|
||||
NewValue = newValue,
|
||||
Amount = amount,
|
||||
};
|
||||
|
||||
public static MeterEvent Reset(int meterId, DateTimeOffset time, double? newValue = 0) => new()
|
||||
{
|
||||
MeterId = meterId,
|
||||
Time = time,
|
||||
EventType = MeterEventType.CounterReset,
|
||||
NewValue = newValue,
|
||||
};
|
||||
|
||||
public static MeterEvent Delivery(int meterId, DateTimeOffset time, double litres) => new()
|
||||
{
|
||||
MeterId = meterId,
|
||||
Time = time,
|
||||
EventType = MeterEventType.Delivery,
|
||||
Amount = litres,
|
||||
Unit = "L",
|
||||
};
|
||||
|
||||
public static MeterEvent TankLevelCm(int meterId, DateTimeOffset time, double cm) => new()
|
||||
{
|
||||
MeterId = meterId,
|
||||
Time = time,
|
||||
EventType = MeterEventType.TankLevel,
|
||||
Amount = cm,
|
||||
Unit = "cm",
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user