{
  Autor: Michael Springwald

  Datum: Donnerstag, 17.12.2015
}

unit uplDataContainer;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, contnrs;

type
  { TPLData }
  TPLData = class
  private
    fabs_pressure: Extended;
    fData: TDate;
    fdelay: Integer;
    fhum_in: Extended;
    fhum_out: Extended;
    frain: Extended;
    ftemp_in: Extended;
    ftemp_out: Extended;
    fTime: TTime;
    fwind_ave: Extended;
    fwind_dir: Extended;
    fwind_gust: Extended;
    procedure SetAbs_Pressure(AValue: Extended);
    procedure SetData(AValue: TDate);
    procedure SetHumIn(AValue: Extended);
    procedure SetHumOut(AValue: Extended);
    procedure SetRain(AValue: Extended);
    procedure SetTempIn(AValue: Extended);
    procedure SetTempOut(AValue: Extended);
    procedure SetTime(AValue: TTime);
    procedure SetWindAve(AValue: Extended);
    procedure SetWindDir(AValue: Extended);
    procedure SetWindGust(AValue: Extended);

  protected

  public
    isChanged:Boolean;
    constructor Create;
    destructor Destroy; override;
  published
    property Data:TDate read fData write SetData;
    property Time:TTime read fTime write SetTime;

    property delay:Integer read fdelay write fdelay;

    property Hum_in:Extended read fhum_in write SetHumIn;
    property Temp_in:Extended read ftemp_in write SetTempIn;
    property Hum_out:Extended read fhum_out write SetHumOut;
    property Temp_out:Extended read ftemp_out write SetTempOut;
    property Abs_pressure:Extended read fabs_pressure write SetAbs_Pressure;
    property Wind_ave:Extended read fwind_ave write SetWindAve;
    property Wind_gust:Extended read fwind_gust write SetWindGust;
    property Wind_dir:Extended read fwind_dir write SetWindDir;
    property Rain:Extended read frain write SetRain;

  end; // TPLData

  { TPLDataContainer }
  TPLDataContainer = class
  private
    fABS_Hum_Out: Extended;
    fABS_pressure: Extended;
    fABS_Temp_Out: Extended;

    fMax_Hum_Out: Extended;
    fMax_pressure: Extended;
    fMax_Temp_In: Extended;
    fMax_Temp_Out: Extended;

    fMin_Hum_Out: Extended;
    fMin_pressure: Extended;
    fMin_Temp_In: Extended;
    fMin_Temp_Out: Extended;

    function GetCount: Integer;
    function GetItem(index: Integer): TPLData;

  protected

  public
    ABS_Temp_Count, ABS_HUM_Count, ABS_Pressure_Count:Integer;
    Items:TObjectList;

    constructor Create;
    destructor Destroy; override;

    function Add():TPLData;

    procedure LoadFromFile(const aFileName:string; const OnlyHour:Boolean = false);

    property Count:Integer read GetCount;
    property Item[index:Integer]:TPLData read GetItem; default;

    property Min_Temp_In:Extended read fMin_Temp_In write fMin_Temp_In;
    property Min_Temp_Out:Extended read fMin_Temp_Out write fMin_Temp_Out;
    property Min_Hum_Out:Extended read fMin_Hum_Out write fMin_Hum_Out;
    property Min_pressure:Extended read fMin_pressure write fMin_pressure;

    property Max_Temp_In:Extended read fMax_Temp_In write fMax_Temp_In;
    property Max_Temp_Out:Extended read fMax_Temp_Out write fMax_Temp_Out;
    property Max_Hum_Out:Extended read fMax_Hum_Out write fMax_Hum_Out;
    property Max_pressure:Extended read fMax_pressure write fMax_pressure;

    property ABS_Temp_Out:Extended read fABS_Temp_Out write fABS_Temp_Out;
    property ABS_Hum_Out:Extended read fABS_Hum_Out write fABS_Hum_Out;
    property ABS_pressure:Extended read fABS_pressure write fABS_pressure;

  published
  end; // TPLDataContainer

implementation

procedure TPLData.SetAbs_Pressure(AValue: Extended);
begin
  if fabs_pressure=AValue then Exit;
  fabs_pressure:=AValue;
end; // TPLData.SetAbs_Pressure

procedure TPLData.SetData(AValue: TDate);
begin
  if fData=AValue then Exit;
  fData:=AValue;
end; // TPLData.SetData

procedure TPLData.SetHumIn(AValue: Extended);
begin
  if fhum_in=AValue then Exit;
  fhum_in:=AValue;
end; // TPLData.SetHumIn

procedure TPLData.SetHumOut(AValue: Extended);
begin
  if fhum_out=AValue then Exit;
  fhum_out:=AValue;
end; // TPLData.SetHumOut

procedure TPLData.SetRain(AValue: Extended);
begin
  if frain=AValue then Exit;
  frain:=AValue;
end; // TPLData.SetRain

procedure TPLData.SetTempIn(AValue: Extended);
begin
  if ftemp_in=AValue then Exit;
  ftemp_in:=AValue;
end; // TPLData.SetTempIn

procedure TPLData.SetTempOut(AValue: Extended);
begin
  if ftemp_out=AValue then Exit;
  ftemp_out:=AValue;
end; // TPLData.SetTempOut

procedure TPLData.SetTime(AValue: TTime);
begin
  if fTime=AValue then Exit;
  fTime:=AValue;
  isChanged:=true;
end; // TPLData.SetTime

procedure TPLData.SetWindAve(AValue: Extended);
begin
  if fwind_ave=AValue then Exit;
  fwind_ave:=AValue;
end; // TPLData.SetWindAve

procedure TPLData.SetWindDir(AValue: Extended);
begin
  if fwind_dir=AValue then Exit;
  fwind_dir:=AValue;
end; // TPLData.SetWindDir

procedure TPLData.SetWindGust(AValue: Extended);
begin
  if fwind_gust=AValue then Exit;
  fwind_gust:=AValue;
end; // TPLData.SetWindGust

constructor TPLData.Create;
begin
  inherited Create;
  isChanged:=False;

  fabs_pressure:=0;
  fdelay:=0;
  fhum_in:=0;
  fhum_out:=0;
  frain:=0;
  ftemp_in:=0;
  ftemp_out:=0;
  fwind_ave:=0;
  fwind_dir:=0;
  fwind_gust:=0;
end; // TPLData.Create

destructor TPLData.Destroy;
begin
  inherited Destroy;
end; // TPLData.Destroy

function TPLDataContainer.GetCount: Integer;
begin
  result:=Items.Count;
end; // TPLDataContainer.GetCount

function TPLDataContainer.GetItem(index: Integer): TPLData;
begin
  result:=items[index] as TPLData
end; // TPLDataContainer.GetItem

{ TPLDataContainer }
constructor TPLDataContainer.Create;
begin
  inherited Create;
  Items:=TObjectList.Create;

  fABS_Hum_Out:=0;
  fABS_pressure:=0;
  fABS_Temp_Out:=0;
  fMax_Temp_Out:=0;
  fMax_Hum_Out:=0;
  fMax_pressure:=0;
  fMax_Temp_Out:=0;
  fMin_Temp_In:=0;
  fMin_Hum_Out:=0;
  fMin_pressure:=0;
  fMin_Temp_Out:=0;

  ABS_Temp_Count:=0;
  ABS_HUM_Count:=0;
  ABS_Pressure_Count:=0;
end; // TPLDataContainer.Create

destructor TPLDataContainer.Destroy;
begin
  Items.Free;
  inherited Destroy;
end; // TPLDataContainer.Destroy

function TPLDataContainer.Add: TPLData;
begin
  result:=item[items.Add(TPLData.Create)];
end; // TPLDataContainer.Add


procedure StringToDataTime(const aValue:String; var aDate:TDate; var aTime:TTime);
var
  str1,str2:String;
  x:Integer;
begin
  x:=pos(' ',aValue);
  str1:=trim(copy(aValue,1,X-1));
  str2:=Copy(aValue,x+1,Length(aValue));

//  writeln('"',str1,'"');

  aDate:=StrToDate(str1,'YYYY-MM-DD','-');
  aTime:=StrToTime(Str2);
end; // StringToDataTime

procedure TPLDataContainer.LoadFromFile(const aFileName: string; const OnlyHour:Boolean = false);
var
  FileName:String;

  ch:char;
  index, Z:integer;
  H,M,S,MS,OldHour:Word;
  str:string;

  fs:TFileStream;
  Data:TPLData;

  TempDate:TDate;
  TempTime:TTime;
  Value:Extended;
begin
  fABS_Hum_Out:=0;
  fABS_pressure:=0;
  fABS_Temp_Out:=0;

  fMax_Hum_Out:=0;
  fMax_pressure:=0;
  fMax_Temp_Out:=0;

  fMin_Hum_Out:=0;
  fMin_pressure:=0;
  fMin_Temp_Out:=0;

  ABS_Temp_Count:=0;
  ABS_HUM_Count:=0;
  ABS_Pressure_Count:=0;
  H:=0; M:=0; S:=0; MS:=0; OldHour:=0; z:=0;
  Items.Clear;
  if FileExists(aFileName) then begin
    fs:=TFileStream.Create(aFileName,fmOpenRead);
    index:=0;
    Data:=Add();
    while true do begin
      if fs.Read(ch,1) > 0 then begin

        if ch in [#13,#10] then begin
          index:=0;
          str:='';
          if (ch = #10) and (not OnlyHour) then begin
            Data:=Add();
          end
        end;

        if ch = ',' then begin
          index:=index+1;
          if (Index <=11) and (str <> '') then begin


            case index of
              1: begin // Datum und Uhrzeit
                StringToDataTime(str,TempDate,TempTime);
                DecodeTime(TempTime,H,M,S,MS);

                if not Data.isChanged then begin
                  Data.Data:=TempDate;
                  Data.Time:=TempTime;
                end;


                if (H <> OldHour) then begin
                  Data.Hum_in:=Data.Hum_in / z;
                  Data.Temp_in:=Data.Temp_in / z;
                  Data.Hum_out:=Data.Hum_out / z;
                  Data.Temp_out:=Data.Temp_out / z;
                  Data.Abs_pressure:=Data.Abs_pressure / z;

                  Min_Temp_In:=Min_Temp_In;
                  Min_Temp_Out:=Min_Temp_Out;
                  Max_Temp_In:=Max_Temp_In;
                  Max_Temp_Out:=Max_Temp_Out;

                  Max_Hum_Out:=Max_Hum_Out;
//                  max_
                  z:=0;
                  if OnlyHour then begin
                    Data:=Add();
                  end;
                end
                else
                  z:=z+1;

                OldHour:=h;
              end;

              2: Data.delay:=StrToInt(str);

              3: begin
                if OnlyHour then
                  Data.hum_in:=Data.hum_in+StrToFloat(str)
                else
                  Data.hum_in:=StrToFloat(str);
              end;

              4: begin
                Value:=StrToFloat(str);
                if OnlyHour then
                  Data.Temp_in:=Data.Temp_in+Value
                else
                  Data.Temp_in:=Value;

                if Value > Max_Temp_in then Max_Temp_in:=Value;
                if (Value < Min_Temp_in) or (Min_Temp_in = 0) then Min_Temp_in:=Value;

              end;

              5: begin
                if OnlyHour then
                  Data.Hum_out:=Data.Hum_out+StrToFloat(str)
                else
                  Data.Hum_out:=StrToFloat(str);

                if Data.Hum_out > Max_Hum_Out then Max_Hum_Out:=Data.Hum_out;
                if (Data.Hum_out < Min_Hum_Out) or (Min_Hum_Out = 0) then Min_Hum_Out:=Data.Hum_out;
                ABS_Hum_Out:=ABS_Hum_Out+Data.Hum_out;
                ABS_HUM_Count:=ABS_HUM_Count+1;
              end;

              6: begin
                Value:=StrToFloat(str);
                if OnlyHour then
                  Data.Temp_out:=Data.Temp_out+Value
                else
                  Data.Temp_out:=Value;

                if Value > Max_Temp_Out then Max_Temp_Out:=Value;
                if (Value < Min_Temp_Out) or (Min_Temp_Out=0) then Min_Temp_Out:=Value;

                ABS_Temp_Out:=ABS_Temp_Out+Data.Temp_out;
                ABS_Temp_Count:=ABS_Temp_Count+1;

              end;

              7: begin
                if OnlyHour then
                  Data.Abs_pressure:=Data.Abs_pressure+StrToFloat(str)
                else
                  Data.Abs_pressure:=StrToFloat(str);

                if Data.Abs_pressure > Max_pressure then Max_pressure:=Data.Abs_pressure;
                if (Data.Abs_pressure < Min_pressure) or (Min_pressure = 0) then Min_pressure:=Data.Abs_pressure;
                ABS_pressure:=ABS_pressure+Data.ABS_pressure;
                ABS_Pressure_Count:=ABS_Pressure_Count+1;


              end;

              8: Data.Wind_ave:=StrToFloat(str);
              9: Data.Wind_gust:=StrToFloat(str);
              10: Data.Wind_dir:=StrToFloat(str);
              11: Data.Rain:=StrToFloat(str);
            end;
          end;
          str:='';
        end
        else
          str:=str+ch;
      end
      else
        break;
    end;
    fs.Free;
  end;
  ABS_Temp_Out:=ABS_Temp_Out/ABS_Temp_Count;
  ABS_Hum_Out:=ABS_Hum_Out/ABS_HUM_Count;
  ABS_pressure:=ABS_pressure/ABS_Pressure_Count;
  Items.Delete(Items.Count-1);

end; // TPLDataContainer.LoadFromFile

end.

