unit Ean;

interface

uses
  Classes, SysUtils, Generics.Collections, Generics.Defaults, DateUtils;

type

  { TEanValue }

  TEanValue = record
    Time: TDateTime;
    ValueIn: Single;
    ValueOut: Single;
    class function Create(Time: TDateTime; ValueIn, ValueOut: Single): TEanValue; static;
    function GetShared: Double;
  end;

  { TEanValues }

  TEanValues = class(TList<TEanValue>)
    function Comparer(constref Left, Right: TEanValue): Integer;
  end;

  TEanKind = (ekSupply, ekConsumption);

  { TEan }

  TEan = class
    Number: string;
    Owner: string;
    Values: TEanValues;
    Kind: TEanKind;
    function GetTotalIn(TimeFrom, TimeTo: TDateTime): Double;
    function GetTotalOut(TimeFrom, TimeTo: TDateTime): Double;
    function GetShared(TimeFrom, TimeTo: TDateTime): Double;
    constructor Create;
    destructor Destroy; override;
  end;

  { TEans }

  TEans = class(TObjectList<TEan>)
    function SearchByNumber(Number: string): TEan;
    procedure LoadToStrings(Strings: TStrings; AllowNone: Boolean = False);
  end;

var
  EanKindText: array[TEanKind] of string;

procedure Translate;


implementation

resourcestring
  SSupply = 'Supply';
  SConsumption = 'Consumption';

procedure Translate;
begin
  EanKindText[ekSupply] := SSupply;
  EanKindText[ekConsumption] := SConsumption;
end;

{ TEanValue }

class function TEanValue.Create(Time: TDateTime; ValueIn, ValueOut: Single
  ): TEanValue;
begin
  Result.Time := Time;
  Result.ValueIn := ValueIn;
  Result.ValueOut := ValueOut;
end;

function TEanValue.GetShared: Double;
begin
  if ValueIn <> 0 then Result := (1 - ValueOut / ValueIn) * 100
    else Result := 0;
end;

{ TEanValues }

function TEanValues.Comparer(constref Left, Right: TEanValue): Integer;
begin
  Result := CompareDateTime(Left.Time, Right.Time);
end;

{ TEan }

function TEan.GetTotalIn(TimeFrom, TimeTo: TDateTime): Double;
var
  I: Integer;
begin
  Result := 0;
  for I := 0 to Values.Count - 1 do
    if (Values[I].Time >= TimeFrom) and (Values[I].Time < TimeTo) then
      Result := Result + Values[I].ValueIn;
end;

function TEan.GetTotalOut(TimeFrom, TimeTo: TDateTime): Double;
var
  I: Integer;
begin
  Result := 0;
  for I := 0 to Values.Count - 1 do
    if (Values[I].Time >= TimeFrom) and (Values[I].Time < TimeTo) then
      Result := Result + Values[I].ValueOut;
end;

function TEan.GetShared(TimeFrom, TimeTo: TDateTime): Double;
var
  TotalIn: Double;
begin
  TotalIn := GetTotalIn(TimeFrom, TimeTo);
  if TotalIn <> 0 then Result := (1 - GetTotalOut(TimeFrom, TimeTo) / TotalIn) * 100
    else Result := 0;
end;

constructor TEan.Create;
begin
  Values := TEanValues.Create;
end;

destructor TEan.Destroy;
begin
  FreeAndNil(Values);
  inherited;
end;

{ TEans }

function TEans.SearchByNumber(Number: string): TEan;
var
  I: Integer;
begin
  I := 0;
  while (I < Count) and (Items[I].Number <> Number) do Inc(I);
  if I < Count then Result := Items[I]
    else Result := nil;
end;

procedure TEans.LoadToStrings(Strings: TStrings; AllowNone: Boolean = False);
var
  I: Integer;
  Shift: Integer;
begin
  if AllowNone then Shift := 1 else Shift := 0;
  Strings.BeginUpdate;
  try
    while Strings.Count > Count + Shift do Strings.Delete(Strings.Count - 1);
    while Strings.Count < Count + Shift do Strings.Add('');
    for I := 0 to Count - 1 do begin
      Strings[I + Shift] := Items[I].Number + ' (' + Items[I].Owner + ')';
      Strings.Objects[I + Shift] := Items[I];
    end;
  finally
    Strings.EndUpdate;
  end;
end;

end.

