unit VisMcha;

interface

uses
  DesignIntf, DesignEditors, 
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ExtCtrls, stdctrls, ScadaBase, VisMachine;


type

  TVisMcha = class(TVisMachine)
  private
    hasStatusGood: Boolean;
    hasModeVisible: Boolean;
    hasBlokVisible: Boolean;
    tagnameExpanded: string;
  protected
    procedure SetDatColor(idx, value: integer);
  public
    TypeName1: string;
    TypeName2: string;
    procedure Init; override;
    procedure Process; override;
    constructor Create(AOwner: TComponent); override;

    function MakeMachTagname(ending: string): string;
    function MakeDatchikTagname(postfix, ending: string): string;
    function calcDatColor(value, ColorScheme: integer;
      curColor: TColor): TColor;
  end;

  procedure SetMchbDatColorContrasting;

  procedure Register;

implementation
uses
  TagStorage,
  RpVisualGlobal,
  numbers,
  ExtDlgs;

var
  DatColorOff: TColor = clAqua;

procedure SetMchbDatColorContrasting;
begin
  DatColorOff := $00979700;
end;


procedure Register;
begin
  RegisterComponents('Scada', [TVisMcha]);
end;


{ TVisMcha }

constructor TVisMcha.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  TypeName1 := 'MCHA';
  TypeName2 := 'MDTA';

  hasStatusGood := true;
  hasModeVisible := true;
  hasBlokVisible := true;
end;

function TVisMcha.calcDatColor(value, ColorScheme: integer; curColor: TColor): TColor;
//const
//  CL_OFF = $00979700;
begin
  result := clBlack;

  // todo define consts!!!

  // bad status
  if value = 5 then begin
    result := clRed;
    Exit;
  end;

  // Аварийный
  if ColorScheme = 0 then begin
    case value of
    0: result := DatColorOff;
    1: result := clYellow;
    2: result := clRed; //clAqua; - авар.датчик с включенным триггером должен быть красным!
    3: if curColor = clRed then
         result := clYellow
       else
         result := clRed;
    4: result := $00B3FFFF;//clLime;
    end;
  end;

  // Технологический
  if ColorScheme = 1 then begin
    case value of
    0,2: result := DatColorOff;
    1,3: result := clYellow;
    4: result := $00B3FFFF;//clLime;
    end;
  end;

  // aqua-red
  if ColorScheme = 2 then begin
    case value of
    0,2: result := DatColorOff;
    1,3: result := clRed;
    4: result := $00B3FFFF;//clLime;
    end;
  end;


  // Аварийный Триггерный
  if ColorScheme = 3 then begin
    case value of
    0: result := DatColorOff;
    1: result := clYellow;
    2: result := clRed;
    3: if curColor = clRed then
         result := clYellow
       else
         result := clRed;
    4: result := $00B3FFFF;//clLime;
    end;
  end;

  // Технологический Инвертированный
  if ColorScheme = 4 then begin
    case value of
    0:  result := clYellow;
    1..4: result := DatColorOff;
    end
  end;

  // aqua-lime
  if ColorScheme = 5 then begin
    case value of
    0,1: result := DatColorOff;
    2,3: result := clLime;
    4:   result := clBtnFace;
    end
  end;

  // grey-red
  if ColorScheme = 6 then begin
    case value of
    0,1: result := clGray;
    2,3: result := clRed;
    4:   result := clBtnFace;
    end
  end;
end;

// Установка цвета датчика
procedure TVisMcha.SetDatColor(idx, value: integer);
begin
  if (value <> Datchik[idx].valSost) or (value>0) then begin
    Datchik[idx].Shape.Brush.Color := calcDatColor(
          value,
          Datchik[idx].ColorScheme,
          Datchik[idx].Shape.Brush.Color
    );

    Datchik[idx].valSost := value;
  end;
end;


// INIT
procedure TVisMcha.Init;
var
  i: integer;
begin
  inherited;

  LostTags := '';
  tagnameExpanded := expandTagname;

  if OnlyDat then
    IsConnectionBad := false
  else begin
    FTagMctlControl := GetTagIndexWithLost(MakeMachTagname('Control'), LostTags);
    FTagMachSost    := GetTagIndexWithLost(MakeMachTagname('Sost'), LostTags);
    FTagMachBlok    := GetTagIndexWithLost(MakeMachTagname('Blok'), LostTags);
    IsConnectionBad := (FTagMctlControl<0) or (FTagMachSost<0) or (FTagMachBlok<0);
  end;

  for i:=0 to DatCount-1 do with Datchik[i]^ do begin
    TagIdxOutput  := GetTagIndexWithLost(MakeDatchikTagname(TagPostfix, 'Sost'), LostTags);
    TagIdxBlok    := GetTagIndexWithLost(MakeDatchikTagname(TagPostfix, 'Blok'), LostTags);

    IsConnectionBad := (IsConnectionBad) or (TagIdxOutput<0) or (TagIdxBlok<0);
  end;

  if OnlyDat then begin
    try
      ImageObj.Picture.LoadFromFile(VisImagesPath + ImagePic);
    except
      LabelObj.Caption := 'PIC';
    end;
  end;

end;

function TVisMcha.MakeMachTagname(ending: string): string;
begin
  result := format('%s.'+TypeName1+'_%s_%s', [TagPath, tagnameExpanded, ending])
end;

function TVisMcha.MakeDatchikTagname(postfix, ending: string): string;
begin
  result := format('%s.'+TypeName2+'_%s%s_%s', [TagPath, tagnameExpanded, postfix, ending])
end;


// PROCESS HANDLER
procedure TVisMcha.Process;
var
  value, i: integer;
  statusChanged, allgood, mode, blok: boolean;

  function getval(idx: integer): integer;
  begin
    result := GetTagValue(idx);
    allgood := allgood and (result >= 0) and (IsTagStatusGood(idx));
  end;

begin
  allgood := True;
  mode := false;
  blok := false;

  if OnlyDat then begin
    SetImageSost(0);
  end else begin
    value := getval(FTagMachSost);
    SetImageSost(value);
    mode := (getval(FTagMctlControl) and 3) > 0;
    blok := getval(FTagMachBlok) > 0;
  end;

  for i:=0 to DatCount-1 do begin
    SetDatColor(i, getval(Datchik[i].TagIdxOutput));
    blok := blok or (getval(Datchik[i].TagIdxBlok) > 0);
  end;

  if not rvgLogIn then begin
    allgood := true;
    mode := false;
    blok := false;
  end;


  statusChanged := allgood <> hasStatusGood;

  if statusChanged then begin
    if allgood then begin
      FrameModeObj.Brush.Style := bsClear;
      FrameBlokObj.Brush.Style := bsClear;
    end else begin
      FrameModeObj.Pen.Color := clRed;
      FrameBlokObj.Pen.Color := clRed;
      FrameModeObj.Brush.Color := clRed;
      FrameBlokObj.Brush.Color := clRed;
      FrameModeObj.Brush.Style := bsSolid;
      FrameBlokObj.Brush.Style := bsSolid;
    end;
  end;

  if allgood then begin
    if (mode <> hasModeVisible) or (statusChanged) then begin
      if mode then begin
        FrameModeObj.Pen.Color := clAqua;
        FrameModeObj.Pen.Style := psSolid;
      end else begin
        FrameModeObj.Pen.Style := psClear;
      end;
    end;

    if (blok <> hasBlokVisible) or (statusChanged) then begin
      if blok then begin
        FrameBlokObj.Pen.Color := clYellow;
        FrameBlokObj.Pen.Style := psSolid;
      end else begin
        FrameBlokObj.Pen.Style := psClear;
      end;
    end;
  end;

  if (allgood <> hasStatusGood) or (mode <> hasModeVisible) or (blok <> hasBlokVisible) then begin
    hasStatusGood := allgood;
    hasModeVisible := mode;
    hasBlokVisible := blok;
    
    RepaintRect(FrameModeObj);
  end;

  if (blinkingBadStatus) and (not hasStatusGood) then
    Visible := not Visible;

end;








end.
