using System.Collections.Generic;
public class CustomerPowerConsumption : ICloneable
public long Id {get; set;}
public DateTime Date {get; set;}
public double KWhBase {get; set;}
public double KWhBaseUsed {get; set;}
public double KWhRollover {get; set;}
public double KWhRolloverUsed {get; set;}
public double KWhAdminRollover {get; set;}
public double KWhAdminRolloverUsed {get; set;}
public long Consumption {get; set;}
public double KWhRemaining { get => KWhBaseRemaining + KWhRolloverRemaining + KWhAdminRolloverRemaining; }
public double KWhBaseRemaining { get => KWhBase - KWhBaseUsed; }
public double KWhRolloverRemaining { get => KWhRollover - KWhRolloverUsed; }
public double KWhAdminRolloverRemaining { get => KWhAdminRollover - KWhAdminRolloverUsed; }
public override string ToString()
return "Consumption info: " +
"\nDate: " + Date.ToString() +
"\nKwhBase: " + KWhBase +
"\nKWhBaseUsed: " + KWhBaseUsed +
"\nKWhRollover: " + KWhRollover +
"\nKWhRolloverUsed: " + KWhRolloverUsed +
"\nKWhAdminRollover: " + KWhAdminRollover +
"\nKWhAdminRolloverUsed: " + KWhAdminRolloverUsed +
"\nConsumption: " + Consumption + " ----- out of " + (KWhBase + KWhRollover + KWhAdminRolloverUsed) +
"\nKWhRemaining: " + KWhRemaining +
"\nKWhBaseRemaining: " + KWhBaseRemaining +
"\nKWhRolloverRemaining: " + KWhRolloverRemaining +
"\nKWhAdminRolloverRemaining: " + KWhAdminRolloverRemaining +
"\n ============================================= \n\n";
return this.MemberwiseClone();
public class CustomerPowerPackage
public long Id {get; set;}
public double KWhBase {get; set;}
public double KWhRollover {get; set;}
public double KWhAdminRollover {get; set;}
public DateTime Start {get; set;}
public DateTime End {get; set;}
public List<CustomerPowerConsumption> CustomerPowerConsumptions {get; set;} = new List<CustomerPowerConsumption>();
public override string ToString()
return "PowerPackage info: " +
"\nKwhBase: " + KWhBase +
"\nKWhRollover: " + KWhRollover +
"\nKWhAdminRollover: " + KWhAdminRollover +
"\n ============================================= \n\n";
public class ChargingTransaction
public long Id {get; set;}
public DateTime EndDate {get; set;}
public double ConsumedKwh {get; set;}
private static List<ChargingTransaction> _allTransactions = new List<ChargingTransaction>();
private static List<CustomerPowerPackage> _allPowerPackages = new List<CustomerPowerPackage>();
public static void Main()
DateTime startDate = new DateTime(2022,9,01);
CreateRandomTransactions(startDate);
CreateCustomerPowerPackages(startDate, 700, 60, 40);
var powerPackagesJson = JsonSerializer.Serialize(_allPowerPackages);
var transactionsJson = JsonSerializer.Serialize(_allTransactions);
Console.WriteLine("Power packages with consumptions: \n " + powerPackagesJson);
Console.WriteLine("\n\n\nTransactions: \n " + transactionsJson);
Console.WriteLine("\n\n\tCOMPLETED");
private static void CreateRandomTransactions(DateTime date)
while (date <= DateTime.Now)
long randomConsumption = (long)(r.NextDouble() * range);
_allTransactions.Add(new ChargingTransaction
ConsumedKwh = randomConsumption
private static void CreateCustomerPowerPackages(DateTime date, double baseKwh, double rollover, double adminRollover)
while (date <= DateTime.Now)
var previousPowerPackage = _allPowerPackages.FirstOrDefault(cpp => cpp.Start == date.AddMonths(-1));
CustomerPowerPackage createdPowerPackage = new CustomerPowerPackage
KWhAdminRollover = adminRollover,
End = date.AddMonths(1).AddDays(-1),
if (previousPowerPackage is not null)
var lastConsumptionOfPreviousPackage = previousPowerPackage.CustomerPowerConsumptions.OrderByDescending(cpp => cpp.Date).First();
var totalRollover = lastConsumptionOfPreviousPackage.KWhBaseRemaining + lastConsumptionOfPreviousPackage.KWhRolloverRemaining;
var maxRollover = createdPowerPackage.KWhBase * 3;
createdPowerPackage.KWhRollover = maxRollover <= totalRollover ? maxRollover : totalRollover;
createdPowerPackage.KWhAdminRollover = lastConsumptionOfPreviousPackage.KWhAdminRolloverRemaining;
if (lastConsumptionOfPreviousPackage.KWhRemaining < 0)
createdPowerPackage.KWhBase = createdPowerPackage.KWhBase + lastConsumptionOfPreviousPackage.KWhRemaining;
createdPowerPackage.KWhAdminRollover = 0;
createdPowerPackage.KWhRollover = 0;
_allPowerPackages.Add(createdPowerPackage);
createdPowerPackage.CustomerPowerConsumptions.AddRange(CreateListOfPowerConsumptions(createdPowerPackage));
date = date.AddMonths(1);
private static List<CustomerPowerConsumption> CreateListOfPowerConsumptions(CustomerPowerPackage powerPackage)
List<CustomerPowerConsumption> consumptions = new List<CustomerPowerConsumption>();
DateTime date = powerPackage.Start;
while (date <= powerPackage.End)
CustomerPowerConsumption newPowerConsumption = new CustomerPowerConsumption
KWhBase = powerPackage.KWhBase,
KWhRollover = powerPackage.KWhRollover,
KWhAdminRollover = powerPackage.KWhAdminRollover,
KWhAdminRolloverUsed = 0,
var previousPowerConsumption = consumptions.FirstOrDefault(c => c.Date == date.AddDays(-1));
if (previousPowerConsumption is not null)
newPowerConsumption.Consumption = previousPowerConsumption.Consumption;
newPowerConsumption.KWhAdminRolloverUsed = previousPowerConsumption.KWhAdminRolloverUsed;
newPowerConsumption.KWhRolloverUsed = previousPowerConsumption.KWhRolloverUsed;
newPowerConsumption.KWhBaseUsed = previousPowerConsumption.KWhBaseUsed;
newPowerConsumption = CalculateAndUpdatePowerConsumption(newPowerConsumption);
consumptions.Add(newPowerConsumption);
private static CustomerPowerConsumption CalculateAndUpdatePowerConsumption(CustomerPowerConsumption powerConsumption)
double consumed = _allTransactions.Where(t => t.EndDate == powerConsumption.Date).Sum(t => t.ConsumedKwh);
powerConsumption.Consumption = powerConsumption.Consumption + (long)consumed;
powerConsumption.KWhBaseUsed = CalculateConsumedAmount(ref consumed, powerConsumption.KWhBaseUsed, powerConsumption.KWhBaseRemaining, powerConsumption.KWhBase);
powerConsumption.KWhAdminRolloverUsed = CalculateConsumedAmount(ref consumed, powerConsumption.KWhAdminRolloverUsed, powerConsumption.KWhAdminRolloverRemaining, powerConsumption.KWhAdminRollover);
powerConsumption.KWhRolloverUsed = CalculateConsumedAmount(ref consumed, powerConsumption.KWhRolloverUsed, powerConsumption.KWhRolloverRemaining, powerConsumption.KWhRollover);
powerConsumption.KWhBaseUsed = consumed + powerConsumption.KWhBaseUsed;
private static double CalculateConsumedAmount(ref double consumed, double used, double remaining, double baseAmount)
if (consumed > 0 && remaining >= 0)
if (remaining <= consumed)
consumed = consumed - remaining;