unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ComCtrls, StdCtrls, ExtCtrls, IniFiles, FormComp, Mask, Spin;

type
  TPerem = record
    Name:string;
    Offset:byte;
  end;

  TLog = record
    PeremsCout:byte;
    Perems:array of TPerem;
    Max,Min:integer;
    Name:string;
    PerName:string;
  end;

  TGraph = record
    CurImg:timage;
    SelCol:array [0..3] of tMaskEdit;
    SelLog:array [0..3] of tcombobox;
    Bit:tbitmap;
   end;

  TAllData = record
    Graphs: array [0..1] of TGraph;
    LogCout:byte;
    LogsFormuls: array of Tformula;
    Logs:array of TLog;

  end;

  TIndex = record
    TimeI :dword;
    TimeS :string;
  end;

  TForm1 = class(TForm)
    OpenDialog1: TOpenDialog;
    ProgressBar1: TProgressBar;
    Image1: TImage;
    Panel1: TPanel;
    Label1: TLabel;
    Button2: TButton;
    Button3: TButton;
    Button4: TButton;
    Button5: TButton;
    TrackBar1: TTrackBar;
    TrackBar2: TTrackBar;
    ComboBox1: TComboBox;
    ComboBox2: TComboBox;
    ComboBox3: TComboBox;
    ComboBox4: TComboBox;
    ComboBox5: TComboBox;
    ComboBox6: TComboBox;
    ComboBox7: TComboBox;
    ComboBox8: TComboBox;
    Splitter1: TSplitter;
    Image2: TImage;
    Image3: TImage;
    MaskEdit2: TMaskEdit;
    ColorDialog1: TColorDialog;
    MaskEdit1: TMaskEdit;
    MaskEdit3: TMaskEdit;
    MaskEdit4: TMaskEdit;
    MaskEdit5: TMaskEdit;
    MaskEdit6: TMaskEdit;
    MaskEdit7: TMaskEdit;
    MaskEdit8: TMaskEdit;
    Timer1: TTimer;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    Label5: TLabel;
    Label6: TLabel;
    Label7: TLabel;
    SpinEdit1: TSpinEdit;
    Label8: TLabel;
    procedure DrawTime;
    procedure reDraw;
    procedure DrawR;
    procedure DrawLine;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure FormResize(Sender: TObject);
    procedure ProgressBar1MouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure ProgressBar1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure ProgressBar1MouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure MaskEdit2Change(Sender: TObject);
    procedure MaskEdit2DblClick(Sender: TObject);
    procedure MaskEdit2KeyPress(Sender: TObject; var Key: Char);
    procedure TrackBar1Change(Sender: TObject);
    procedure Image3MouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure Timer1Timer(Sender: TObject);
    procedure Button4Click(Sender: TObject);
    procedure Button5Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure ComboBox1Change(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure SpinEdit1Change(Sender: TObject);
  private
    MD:boolean;
    Data: TAllData;
    Index:array of TIndex;
    AllValues:array of array of single;
    DeltaInd,CurX:dword;
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.reDraw;
var centerl,max,min,poz,i,j,int:integer; val,lval:real; H,CurInd:dword;
begin

 for i:=0 to 1 do begin
  H:=Data.Graphs[i].Bit.Height;
  poz:=Data.Graphs[i].Bit.Width;
  CurInd:=ProgressBar1.Position;
  Data.Graphs[i].Bit.canvas.fillrect(Data.Graphs[i].Bit.canvas.cliprect);
  while (poz>0) and (CurInd>0) do begin
    int:=round((Index[CurInd].TimeI-Index[CurInd-1].TimeI)*(TrackBar1.Position/10));
    for j:=0 to 3 do
      if Data.Graphs[i].SelLog[j].ItemIndex<Data.LogCout then begin
         Data.Graphs[i].Bit.Canvas.Pen.Color:=Data.Graphs[i].SelCol[j].Color;
         Data.Graphs[i].Bit.Canvas.Pen.Width:=3;
         max:=Data.Logs[Data.Graphs[i].SelLog[j].ItemIndex].Max;
         min:=Data.Logs[Data.Graphs[i].SelLog[j].ItemIndex].Min;
         centerl:=H-round(H/(max-min)*(-min));
         val:=AllValues[CurInd,Data.Graphs[i].SelLog[j].ItemIndex];
         lval:=AllValues[CurInd-1,Data.Graphs[i].SelLog[j].ItemIndex];
         Data.Graphs[i].Bit.Canvas.MoveTo(poz,centerl-round(H/(max-min)*val));
         Data.Graphs[i].Bit.Canvas.LineTo(poz-int,centerl-round(H/(max-min)*lval));
       end;
    CurInd:=CurInd-1;
    poz:=poz-int;
   end;
 end;
DeltaInd:=ProgressBar1.Position-CurInd;
DrawLine;
end;

procedure TForm1.DrawR;
var centerl,max,min,poz,i,j,int:integer; val,lval:real; H,CurInd:dword;
begin
 for i:=0 to 1 do begin
  CurInd:=ProgressBar1.Position;
  int:=round((Index[CurInd+1].TimeI-Index[CurInd].TimeI)*(TrackBar1.Position/10));
  H:=Data.Graphs[i].Bit.Height;
  poz:=Data.Graphs[i].Bit.Width;
  bitblt(Data.Graphs[i].Bit.Canvas.Handle,0,0,Data.Graphs[i].Bit.Width,H,Data.Graphs[i].Bit.Canvas.Handle,Int,0,srccopy);
  Data.Graphs[i].Bit.Canvas.FillRect(Bounds(poz-int,0,int,H));
  for j:=0 to 3 do
    if Data.Graphs[i].SelLog[j].ItemIndex<Data.LogCout then begin
       Data.Graphs[i].Bit.Canvas.Pen.Color:=Data.Graphs[i].SelCol[j].Color;
       Data.Graphs[i].Bit.Canvas.Pen.Width:=3;
       max:=Data.Logs[Data.Graphs[i].SelLog[j].ItemIndex].Max;
       min:=Data.Logs[Data.Graphs[i].SelLog[j].ItemIndex].Min;
       centerl:=H-round(H/(max-min)*(-min));
       val:=AllValues[CurInd-1,Data.Graphs[i].SelLog[j].ItemIndex];
       lval:=AllValues[CurInd,Data.Graphs[i].SelLog[j].ItemIndex];
       Data.Graphs[i].Bit.Canvas.MoveTo(poz-int,centerl-round(H/(max-min)*val));
       Data.Graphs[i].Bit.Canvas.LineTo(poz,centerl-round(H/(max-min)*lval));
     end;
 end;
DrawLine;
end;

procedure TForm1.DrawLine;
var i,j,h,tw,th,poz,curind:dword; max,min,centerl:integer; val:real;
begin
if (length(index)=0) or (DeltaInd = 0) then exit;
  curind:=ProgressBar1.Position-round(DeltaInd/Data.Graphs[0].CurImg.Width*(Data.Graphs[0].CurImg.Width-CurX));
  poz:=Data.Graphs[0].CurImg.Width-round((Index[ProgressBar1.Position].TimeI-Index[curind].TimeI)*(TrackBar1.Position/10));
  Label1.Caption:=Index[curind].TimeS;
for i:=0 to 1 do begin
  Data.Graphs[i].CurImg.Canvas.Font.Height:=SpinEdit1.Value;
  h:=Data.Graphs[i].CurImg.Height;
  bitblt(Data.Graphs[i].CurImg.Canvas.Handle,0,0,Data.Graphs[i].Bit.Width,H,Data.Graphs[i].Bit.Canvas.Handle,0,0,srccopy);
  Data.Graphs[i].CurImg.Canvas.MoveTo(poz,0);
  Data.Graphs[i].CurImg.Canvas.LineTo(poz,h);
  for j:=0 to 3 do
   if Data.Graphs[i].SelLog[j].ItemIndex<Data.LogCout then begin
    Data.Graphs[i].CurImg.Canvas.Font.Color:=Data.Graphs[i].SelCol[j].Color;
    tw:=Data.Graphs[i].CurImg.Canvas.TextWidth('00000');
    th:=Data.Graphs[i].CurImg.Canvas.TextHeight('0');
    Data.Graphs[i].CurImg.Canvas.TextOut(poz+(j-tw*2)+j*tw,0,inttostr(Data.Logs[Data.Graphs[i].SelLog[j].ItemIndex].Max));
    Data.Graphs[i].CurImg.Canvas.TextOut(poz+(j-tw*2)+j*tw,h-th,inttostr(Data.Logs[Data.Graphs[i].SelLog[j].ItemIndex].Min));
   end;
  for j:=0 to 3 do
   if Data.Graphs[i].SelLog[j].ItemIndex<Data.LogCout then begin
    Data.Graphs[i].CurImg.Canvas.Font.Color:=Data.Graphs[i].SelCol[j].Color;
    max:=Data.Logs[Data.Graphs[i].SelLog[j].ItemIndex].Max;
    min:=Data.Logs[Data.Graphs[i].SelLog[j].ItemIndex].Min;
    centerl:=H-round(H/(max-min)*(-min));
    val:=AllValues[CurInd,Data.Graphs[i].SelLog[j].ItemIndex];
    Data.Graphs[i].CurImg.Canvas.TextOut(poz+1,centerl-round(H/(max-min)*val)-th,Data.Logs[Data.Graphs[i].SelLog[j].ItemIndex].PerName+' = '+floattostrf(val,fffixed,7,2));
   end;
 end;
end;



procedure TForm1.FormCreate(Sender: TObject);
var
  IniFile: TIniFile;
  i,j: byte;
  PeremList: TStringList;
  LogNames:tstrings;
begin
  IniFile:= TIniFile.Create(ExtractFilePath(Application.ExeName)+'set.ini');

  PeremList:= TStringList.Create;

  Data.LogCout:= IniFile.ReadInteger('настройки','кол-во_логов',1);
  SetLength(Data.Logs, Data.LogCout);
  SetLength(Data.LogsFormuls, Data.LogCout);
  for i:=0 to Data.LogCout-1 do
    begin
     Data.Logs[i].PeremsCout:= IniFile.ReadInteger('логер_'+inttostr(i),'кол-во_перем',1);
     SetLength(Data.Logs[i].Perems, Data.Logs[i].PeremsCout);
     PeremList.Clear;
     if Data.Logs[i].PeremsCout>0 then
     for j:=0 to Data.Logs[i].PeremsCout-1 do
       begin
         Data.Logs[i].Perems[j].Name:= IniFile.ReadString('логер_'+inttostr(i),'переменная_'+inttostr(j),'p'+inttostr(j));
         Data.Logs[i].Perems[j].Offset:= IniFile.Readinteger('логер_'+inttostr(i),'отступ_пер_'+inttostr(j),$ff);
         PeremList.Add(Data.Logs[i].Perems[j].Name);
       end;
     CodeBuild(Data.LogsFormuls[i],IniFile.ReadString('логер_'+inttostr(i),'формула','0'),PeremList);
     Data.Logs[i].Name:=IniFile.ReadString('логер_'+inttostr(i),'название','датчик'+inttostr(i));
     Data.Logs[i].PerName:=IniFile.ReadString('логер_'+inttostr(i),'Имя_перем','датчик'+inttostr(i));
     Data.Logs[i].Max:= IniFile.ReadInteger('логер_'+inttostr(i),'макс_знач',100);
     Data.Logs[i].Min:= IniFile.ReadInteger('логер_'+inttostr(i),'мин_знач',0);
    end;
  PeremList.Free;
  IniFile.Free;

  Image1.Picture.Bitmap.Canvas.Brush.Color:=clBtnFace;

  for i:=0 to 1 do
    Data.Graphs[i].Bit:=tbitmap.Create;

  Data.Graphs[0].SelLog[0]:=ComboBox1;
  Data.Graphs[0].SelLog[1]:=ComboBox2;
  Data.Graphs[0].SelLog[2]:=ComboBox3;
  Data.Graphs[0].SelLog[3]:=ComboBox4;
  Data.Graphs[1].SelLog[0]:=ComboBox5;
  Data.Graphs[1].SelLog[1]:=ComboBox6;
  Data.Graphs[1].SelLog[2]:=ComboBox7;
  Data.Graphs[1].SelLog[3]:=ComboBox8;
  Data.Graphs[0].SelCol[0]:=MaskEdit1;
  Data.Graphs[0].SelCol[1]:=MaskEdit2;
  Data.Graphs[0].SelCol[2]:=MaskEdit3;
  Data.Graphs[0].SelCol[3]:=MaskEdit4;
  Data.Graphs[1].SelCol[0]:=MaskEdit5;
  Data.Graphs[1].SelCol[1]:=MaskEdit6;
  Data.Graphs[1].SelCol[2]:=MaskEdit7;
  Data.Graphs[1].SelCol[3]:=MaskEdit8;

  data.Graphs[0].CurImg:=Image3;
  data.Graphs[1].CurImg:=Image2;


  LogNames:=Tstringlist.Create;
  for i:=0 to Data.LogCout-1 do
    LogNames.Add(Data.Logs[i].Name);
  LogNames.Add(' ');

  IniFile:= TIniFile.Create(ExtractFilePath(Application.ExeName)+'watchset.ini');

  for i:=0 to 1 do begin
    Data.Graphs[i].CurImg.Canvas.Font.Name:='Arial';
    for j:=0 to 3 do begin
      Data.Graphs[i].SelLog[j].Items:=LogNames;
      Data.Graphs[i].SelLog[j].ItemIndex:=IniFile.ReadInteger('экран_'+inttostr(i),'выбор'+inttostr(j),1);
      Data.Graphs[i].SelCol[j].Text:='$'+inttohex(IniFile.ReadInteger('экран_'+inttostr(i),'цвет'+inttostr(j),$FF),6);
      MaskEdit2Change(Data.Graphs[i].SelCol[j]);
     end;
   end;
  LogNames.Free;

  if IniFile.ReadBool('Окно','Развернуто',false) then
    Form1.WindowState:=wsMaximized;

   SpinEdit1.Value:=IniFile.ReadInteger('Окно','шрифт',11);
//  Image2.Height:=IniFile.ReadInteger('Окно','Сплитер',200);

  IniFile.Free;

end;

procedure TForm1.Button1Click(Sender: TObject);
var
  LogFile:file of byte;
  Buffer: array [0..$6F] of byte;
  t: array [0..3] of byte;
  NowT:dword;
  i,j,k:dword;
begin
  OpenDialog1.Execute;
  Form1.Caption:='Просмотр логов HondaLogger '+OpenDialog1.FileName;
  AssignFile(LogFile, OpenDialog1.FileName);
  Reset(LogFile);
  setlength(index,filesize(logfile) div $74);
  setlength(AllValues,length(index),Data.LogCout);
  ProgressBar1.Max:=high(index);
  Seek(LogFile,0);
  for k:=0 to high(index) do begin
    BlockRead(LogFile,t,4);
    NowT:=t[0]*3600*200+t[1]*60*200+t[2]*200+t[3];
    index[k].TimeI:=NowT;
    index[k].TimeS:=inttostr(t[0])+':'+inttostr(t[1])+':'+inttostr(t[2]);
    BlockRead(LogFile,Buffer,$70);
    for i:=0 to Data.LogCout-1 do
     begin
      for j:=0 to Data.Logs[i].PeremsCout-1 do
        Data.LogsFormuls[i].DS[j]:=Buffer[Data.Logs[i].perems[j].offset];
      AllValues[k,i]:=Data.LogsFormuls[i].proc;
     end;
    ProgressBar1.Position:=k;
   end;
  Index[0].TimeI:=Index[1].TimeI;
  CloseFile(LogFile);
  DrawTime;
  reDraw;
  ProgressBar1.Position:=DeltaInd;
  reDraw;
end;

procedure TForm1.FormResize(Sender: TObject);
var i:integer;
begin
  DrawTime;

for i:=0 to 1 do begin
  Data.Graphs[i].Bit.Height:=Data.Graphs[i].CurImg.Height;
  Data.Graphs[i].Bit.Width:=Data.Graphs[i].CurImg.Width;
  Data.Graphs[i].CurImg.Picture.Bitmap.Height:=Data.Graphs[i].CurImg.Height;
  Data.Graphs[i].CurImg.Picture.Bitmap.Width:=Data.Graphs[i].CurImg.Width;
 end;
 reDraw;
end;

procedure TForm1.DrawTime;
var i:dword;
begin
 if length(index)>0 then begin
  Image1.Picture.Bitmap.Width:=Image1.Width;
  Image1.Picture.Bitmap.Height:=Image1.Height;
  i:=0;
  while i<image1.Width do begin
    Image1.Picture.Bitmap.Canvas.TextOut(i-3,0,'^'+Index[round(ProgressBar1.Max / image1.Width  * i)].TimeS);
    i:=i+50;
   end;
 end;
end;

procedure TForm1.ProgressBar1MouseMove(Sender: TObject; Shift: TShiftState;
  X, Y: Integer);
begin
 if length(index)=0 then exit;
 if x>=0 then begin
   Label1.Caption:=Index[round(ProgressBar1.Max / ProgressBar1.Width * x)].TimeS;
   if MD then  ProgressBar1MouseDown(Sender,MBLeft,Shift,X,Y);
  end;
end;

procedure TForm1.ProgressBar1MouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  MD:=true;
 if length(index)>0 then
  ProgressBar1.Position:=round(ProgressBar1.Max / ProgressBar1.Width * x);
 reDraw;
end;

procedure TForm1.ProgressBar1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  MD:=false;
end;


procedure TForm1.MaskEdit2Change(Sender: TObject);
begin
  TEdit(Sender).Color:=strtoint(TEdit(Sender).Text);
  reDraw;
end;

procedure TForm1.MaskEdit2DblClick(Sender: TObject);
begin
  ColorDialog1.Color:=strtoint(TEdit(Sender).Text);
  ColorDialog1.Execute;
  TEdit(Sender).Text:='$'+inttohex(ColorDialog1.Color,6);
end;

procedure TForm1.MaskEdit2KeyPress(Sender: TObject; var Key: Char);
begin
    if not (key in (['0'..'9']+['a'..'f']+['A'..'F'])) and (ord(key) <> VK_BACK) then
        key := #0;
end;

procedure TForm1.TrackBar1Change(Sender: TObject);
begin
reDraw;
end;

procedure TForm1.Image3MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
CurX:=x;
DrawLine;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
if ProgressBar1.Position < ProgressBar1.Max-1 then begin
  ProgressBar1.Position:=ProgressBar1.Position+1;
  Timer1.Interval:=round((Index[ProgressBar1.Position+1].TimeI-Index[ProgressBar1.Position].TimeI)*(TrackBar2.Position/5));
  Label1.Caption:=Index[ProgressBar1.Position].TimeS;
  DrawR
 end else Timer1.Enabled:=false;
end;

procedure TForm1.Button4Click(Sender: TObject);
begin
 if length(index)>0 then
   Timer1.Enabled:=true;
 Timer1.Interval:=100;
end;

procedure TForm1.Button5Click(Sender: TObject);
begin
 Timer1.Enabled:=false;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
  ProgressBar1.Position:=DeltaInd;
  reDraw;
end;

procedure TForm1.ComboBox1Change(Sender: TObject);
begin
 reDraw;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
var  IniFile: TIniFile; i,j:byte;
begin
  IniFile:= TIniFile.Create(ExtractFilePath(Application.ExeName)+'watchset.ini');

  for i:=0 to 1 do
    for j:=0 to 3 do begin
      IniFile.WriteInteger('экран_'+inttostr(i),'выбор'+inttostr(j),Data.Graphs[i].SelLog[j].ItemIndex);
      IniFile.WriteInteger('экран_'+inttostr(i),'цвет'+inttostr(j),Data.Graphs[i].SelCol[j].Color);
     end;

  if Form1.WindowState=wsMaximized then
    IniFile.WriteBool('Окно','Развернуто',true)
  else
    IniFile.WriteBool('Окно','Развернуто',false);

   IniFile.WriteInteger('Окно','шрифт',SpinEdit1.Value);
//  IniFile.WriteInteger('Окно','Сплитер',Image2.Height);

  IniFile.Free;

end;

procedure TForm1.SpinEdit1Change(Sender: TObject);
begin
DrawLine;
end;

end.
