unit UnitTest;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, StdCtrls, Buttons, jpeg, Menus;

type
  TTest = class(TObject)
  public
    filename : string; // имя файла
    sek : Integer; // секунд на ответ
    notv : Integer; // номер верного ответа
    vybr : Integer; // выбран пользователем ответ
    vopr : string; // вопрос
    otv : array[1..4] of string; //  для ответов
  end;

  TFormTest = class(TForm)
    Panel0: TPanel;
    Panel00: TPanel;
    Label1: TLabel;
    BitBtn1: TBitBtn;
    BitBtnTestBreak: TBitBtn;
    GroupBox1: TGroupBox;
    GroupBox2: TGroupBox;
    MemoQ: TMemo;
    GroupBox3: TGroupBox;
    Image1: TImage;
    EditFile: TEdit;
    ButtonSelFile: TButton;
    LabelSek: TLabel;
    EditSek: TEdit;
    BitBtn2: TBitBtn;
    ButtonQAdd: TButton;
    ButtonQDel: TButton;
    ButtonQL: TButton;
    ButtonQR: TButton;
    Timer1: TTimer;
    OpenDialog1: TOpenDialog;
    PopupMenu1: TPopupMenu;
    NCopy: TMenuItem;
    NIns: TMenuItem;
    NCut: TMenuItem;
    NDel: TMenuItem;
    N1: TMenuItem;
    NSelAll: TMenuItem;
    TimerLoadFile: TTimer;
    GroupBox5: TGroupBox;
    CheckBoxA1: TCheckBox;
    MemoA1: TMemo;
    MemoA2: TMemo;
    MemoA3: TMemo;
    MemoA4: TMemo;
    CheckBoxA2: TCheckBox;
    CheckBoxA3: TCheckBox;
    CheckBoxA4: TCheckBox;
    procedure FormCreate(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure BitBtn1Click(Sender: TObject);
    procedure BitBtnTestBreakClick(Sender: TObject);
    procedure BitBtn2Click(Sender: TObject);
    procedure ButtonSelFileClick(Sender: TObject);
    procedure ButtonQAddClick(Sender: TObject);
    procedure ButtonQDelClick(Sender: TObject);
    procedure ButtonQLClick(Sender: TObject);
    procedure ButtonQRClick(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure CheckBoxA1Click(Sender: TObject);
    procedure CheckBoxA2Click(Sender: TObject);
    procedure CheckBoxA3Click(Sender: TObject);
    procedure CheckBoxA4Click(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    procedure NCopyClick(Sender: TObject);
    procedure NInsClick(Sender: TObject);
    procedure NCutClick(Sender: TObject);
    procedure NDelClick(Sender: TObject);
    procedure NSelAllClick(Sender: TObject);
    procedure EditFileChange(Sender: TObject);
    procedure TimerLoadFileTimer(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    list : TList; // список всех вопросов теста TTest
    iLs : Integer; // текущий вопрос
    res : String; // результаты тестирования
    nOtv : Integer; // сколько ответов успели дать
    bal : Integer; // балл за тест в процентах
    obTest : Boolean; // обучающее тестирование

    procedure LoadFromMemo(); // Загрузить из memo формата
    procedure SaveToMemo(); // Сохранить в memo формат
    procedure GetTTest(); // получить из TTest текущего
    procedure SetTTest(); // записать в TTest текущий


  end;

var
  FormTest: TFormTest;

implementation

uses
  Unit1;

{$R *.dfm}

procedure TFormTest.LoadFromMemo(); // Загрузить из memo формата
var
  i, n, ls, nA : Integer;
  tt : TTest;
  s, sOld, Q, A : String;
  bQ, bA : boolean;
begin
  // удаляем все из списка
  if list.Count > 0 then
  begin
    for i:=0 to list.Count-1 do
    begin
      tt := list.Items[i];
      tt.Free;
    end;
    list.Clear;
  end;

  Q := '';
  A := '';
  bQ := False;
  bA := False;
  nA := 0;
  sOld := '';
  n:=0;

  if Form1.MemoTest.Lines.Count > 0 then
  begin

    for i:=0 to Form1.MemoTest.Lines.Count-1 do
    begin
      s := Trim( Form1.MemoTest.Lines.Strings[i] );
      ls := Length(s);
      if s <> '' then
      begin
        try
          if s = 'файл:' then
          begin
            Inc(n);
            // если не 1
            if n > 1 then
            begin
              // если ответ еще есть
              if A <> '' then
              begin
                tt.otv[nA] := A;
                A := '';
              end;
              // добавить прошлый в список
              list.Add( tt );
            end;
            tt := TTest.Create;
            tt.filename := '';
            tt.sek := 30;
            tt.notv := 1;
            tt.vybr := -1; // выбран пользователем ответ
            tt.vopr := '';
            tt.otv[1] := '';
            tt.otv[2] := '';
            tt.otv[3] := '';
            tt.otv[4] := '';
            nA := 0;
            bQ := False;
            bA := False;
            Q := '';
            A := '';
          end;

          if sOld = 'файл:' then
          begin
            tt.filename := s;
          end;

          if sOld = 'секунд:' then
          begin
            tt.sek := StrToInt(s);
          end;

          if sOld = 'N ответа:' then
          begin
            tt.notv := StrToInt(s);
          end;

          if s = 'Вопрос:' then
          begin
            bQ := True;
            bA := False;
            Q := '';
            A := '';
          end
          else if s = 'Ответ:' then
          begin
            if bQ then
            begin
              tt.vopr := Q;
            end
            else if bA and (nA > 0) then
            begin
              tt.otv[nA] := A;
            end;
            bQ := False;
            bA := True;
            Q := '';
            A := '';
            Inc(nA);
          end
          else if bQ then
          begin
            if sOld = 'Вопрос:' then Q := Q + s
            else Q := Q + #13#10 + s;
          end
          else if bA then
          begin
            if sOld = 'Ответ:' then A := A + s
            else A := A + #13#10 + s;
          end;


        except
        end;
      end;

      sOld := s;
    end;

    // если ответ еще есть
    if A <> '' then
    begin
      tt.otv[nA] := A;
      A := '';
    end;
    // добавить прошлый в список
    list.Add( tt );

  end;

  if list.Count > 0 then
  begin
    iLs := 0; // текущий вопрос
  end
  else
  begin
    iLs := -1; // текущий вопрос
  end;

end;

procedure TFormTest.SaveToMemo(); // Сохранить в memo формат
var
  i : Integer;
  tt : TTest;
begin
  Form1.MemoTest.Lines.Clear;
  for i:=0 to list.Count-1 do
  begin
    tt := list.Items[i];
    Form1.MemoTest.Lines.Add('файл:');
    Form1.MemoTest.Lines.Add(tt.filename);
    Form1.MemoTest.Lines.Add('секунд:');
    Form1.MemoTest.Lines.Add(IntToStr(tt.sek));
    Form1.MemoTest.Lines.Add('N ответа:');
    Form1.MemoTest.Lines.Add(IntToStr(tt.notv));
    Form1.MemoTest.Lines.Add('Вопрос:');
    Form1.MemoTest.Text := Form1.MemoTest.Text
      + tt.vopr + #13#10;
    Form1.MemoTest.Lines.Add('Ответ:');
    Form1.MemoTest.Text := Form1.MemoTest.Text
      + tt.otv[1] + #13#10;
    Form1.MemoTest.Lines.Add('Ответ:');
    Form1.MemoTest.Text := Form1.MemoTest.Text
      + tt.otv[2] + #13#10;
    Form1.MemoTest.Lines.Add('Ответ:');
    Form1.MemoTest.Text := Form1.MemoTest.Text
      + tt.otv[3] + #13#10;
    Form1.MemoTest.Lines.Add('Ответ:');
    Form1.MemoTest.Text := Form1.MemoTest.Text
      + tt.otv[4] + #13#10;
  end;
end;


procedure TFormTest.GetTTest(); // получить из TTest текущего
var
  tt : TTest;
begin
  GroupBox2.Caption := ' вопрос ';
  MemoQ.Clear;
  MemoA1.Clear;
  MemoA2.Clear;
  MemoA3.Clear;
  MemoA4.Clear;
  EditFile.Text := '';
  EditSek.Text := '';
  CheckBoxA1.Checked := False;
  CheckBoxA2.Checked := False;
  CheckBoxA3.Checked := False;
  CheckBoxA4.Checked := False;

  BitBtn1.Enabled := CheckBoxA1.Checked or CheckBoxA2.Checked
    or CheckBoxA3.Checked or CheckBoxA4.Checked;
  BitBtn2.Enabled := True;  

  if Form1.Editing then
  begin
    BitBtn1.Caption := 'Правильный ответ установлен. К след. вопросу';
  end
  else
  begin
    BitBtn1.Caption := 'Дать ответ и перейти к следующему вопросу';
  end;

  MemoA1.Visible := true;
  CheckBoxA1.Visible := true;
  MemoA2.Visible := true;
  CheckBoxA2.Visible := true;
  MemoA3.Visible := true;
  CheckBoxA3.Visible := true;
  MemoA4.Visible := true;
  CheckBoxA4.Visible := true;
  Timer1.Enabled := False;

  if (iLs > -1) and (iLs < list.Count) then
  begin
    if iLs = 0 then
    begin
      BitBtn2.Enabled := False;
    end;

    if iLs = list.Count-1 then
    begin
      if Form1.Editing then
      begin
        BitBtn1.Caption := 'Правильный ответ установлен.';
      end
      else
      begin
        BitBtn1.Caption := 'Дать ответ и закончить тест!';
      end;
    end;

    // цветом выделим, что есть
    MemoQ.Color := clWhite;
    MemoA1.Color := clWhite;
    MemoA2.Color := clWhite;
    MemoA3.Color := clWhite;
    MemoA4.Color := clWhite;
    CheckBoxA1.Enabled := True;
    CheckBoxA2.Enabled := True;
    CheckBoxA3.Enabled := True;
    CheckBoxA4.Enabled := True;

    GroupBox2.Caption := ' вопрос ' + IntToStr(iLs+1)
      + ' из ' + IntToStr( list.Count) ;
    tt := list.Items[iLs];
    MemoQ.Text := tt.vopr;
    MemoA1.Text := tt.otv[1];
    MemoA2.Text := tt.otv[2];
    MemoA3.Text := tt.otv[3];
    MemoA4.Text := tt.otv[4];

    // для режима выполнения скроем пустые
    if not Form1.Editing then
    begin
      if Trim(tt.otv[1]) = '' then
      begin
        MemoA1.Visible := False;
        CheckBoxA1.Visible := False;
      end;

      if Trim(tt.otv[2]) = '' then
      begin
        MemoA2.Visible := False;
        CheckBoxA2.Visible := False;
      end;

      if Trim(tt.otv[3]) = '' then
      begin
        MemoA3.Visible := False;
        CheckBoxA3.Visible := False;
      end;

      if Trim(tt.otv[4]) = '' then
      begin
        MemoA4.Visible := False;
        CheckBoxA4.Visible := False;
      end;
    end;


    EditSek.Text := ' ' + IntToStr(tt.sek);
    if tt.sek <= 10 then
    begin
      EditSek.Color := clRed;
      EditSek.Font.Color := clWhite;
    end
    else
    begin
      EditSek.Color := clWindow;
      EditSek.Font.Color := clBlue;
    end;

    EditFile.Text := tt.filename;
    // для режима редактирования покажем ответ
    if Form1.Editing then
    begin
      case tt.notv of
        1 : CheckBoxA1.Checked := true;
        2 : CheckBoxA2.Checked := true;
        3 : CheckBoxA3.Checked := true;
        4 : CheckBoxA4.Checked := true;
      end;
    end
    else
    begin
      if tt.sek > 0 then
      begin
        Timer1.Tag := tt.sek;
        if not obTest then Timer1.Enabled := True;
        if tt.sek <= 10 then
        begin
          EditSek.Color := clRed;
          EditSek.Font.Color := clWhite;
        end
        else
        begin
          EditSek.Color := clWindow;
          EditSek.Font.Color := clBlue;
        end;
      end;


    end;
  end
  else
  begin
    // цветом выделим, что ничего нет
    MemoQ.Color := clSilver;
    MemoA1.Color := clSilver;
    MemoA2.Color := clSilver;
    MemoA3.Color := clSilver;
    MemoA4.Color := clSilver;
    BitBtn1.Enabled := False;
    BitBtn2.Enabled := False;
    CheckBoxA1.Enabled := False;
    CheckBoxA2.Enabled := False;
    CheckBoxA3.Enabled := False;
    CheckBoxA4.Enabled := False;

  end;

  BitBtn1.Enabled := CheckBoxA1.Checked or CheckBoxA2.Checked
    or CheckBoxA3.Checked or CheckBoxA4.Checked;


end;

procedure TFormTest.SetTTest(); // записать в TTest текущий
var
  tt : TTest;
begin
  if (iLs > -1) and (iLs < list.Count) then
  begin
    tt := list.Items[iLs];

    if Form1.Editing then
    begin
      tt.vopr := MemoQ.Text;
      tt.otv[1] := MemoA1.Text;
      tt.otv[2] := MemoA2.Text;
      tt.otv[3] := MemoA3.Text;
      tt.otv[4] := MemoA4.Text;

      try
        tt.sek := StrToInt( Trim(EditSek.Text) );
      except
        tt.sek := 0;
      end;

      tt.filename :=  Trim( EditFile.Text );
    end;

    // для режима редактирования запишем ответ
    if Form1.Editing then
    begin
      if CheckBoxA1.Checked then tt.notv := 1
      else if CheckBoxA2.Checked then tt.notv := 2
      else if CheckBoxA3.Checked then tt.notv := 3
      else if CheckBoxA4.Checked then tt.notv := 4
      else tt.notv := -1;
    end
    else // запомним выбор пользователя
    begin
      if CheckBoxA1.Checked then tt.vybr := 1
      else if CheckBoxA2.Checked then tt.vybr := 2
      else if CheckBoxA3.Checked then tt.vybr := 3
      else if CheckBoxA4.Checked then tt.vybr := 4
      else tt.vybr := -1;
    end;   


  end;

end;


procedure TFormTest.FormCreate(Sender: TObject);
begin
  Panel0.Align := alClient;
  obTest := False; // обучающее тестирование

  list := TList.Create; // список всех вопросов теста TTest
end;

procedure TFormTest.FormShow(Sender: TObject);
begin

  GroupBox1.Caption := '' + Form1.ListBoxTests.Items[ Form1.ListBoxTests.ItemIndex]
    + '';
  
  // если не в режиме редактирования
  if not Form1.Editing then
  begin
    // результаты тестирования
    res := ' === ' + FormatDateTime('dd.mm.yyyy hh:nn:ss', Now) + ' === ';
    res := res + #13#10 + 'Тест "'
      + Form1.ListBoxTests.Items[ Form1.ListBoxTests.ItemIndex] + '"';
    nOtv := 0; // сколько ответов успели дать  
    FormTest.WindowState := wsMaximized;
    EditFile.Visible := False;
    ButtonSelFile.Visible := False;
    EditSek.ReadOnly := True;
    MemoQ.ReadOnly := True;
    MemoA1.ReadOnly := True;
    MemoA2.ReadOnly := True;
    MemoA3.ReadOnly := True;
    MemoA4.ReadOnly := True;
    LabelSek.Caption := '- осталоcь секунд на ответ';
    BitBtn1.Caption := 'Дать ответ и перейти к следующему вопросу';
    BitBtn2.Visible := False;
    Label1.Visible := True;
    ButtonQAdd.Visible := False;
    ButtonQDel.Visible := False;
    ButtonQL.Visible := False;
    ButtonQR.Visible := False;
    BitBtnTestBreak.Caption := 'Прервать тест';
  end
  else
  begin
    res := ''; // результаты тестирования
    //FormTest.WindowState := wsNormal;
    FormTest.WindowState := wsMaximized; // так по максимуму больше картинка выйдет
    EditFile.Visible := True;
    ButtonSelFile.Visible := True;
    EditSek.ReadOnly := False;
    MemoQ.ReadOnly := False;
    MemoA1.ReadOnly := False;
    MemoA2.ReadOnly := False;
    MemoA3.ReadOnly := False;
    MemoA4.ReadOnly := False;
    LabelSek.Caption := '- секунд на ответ';
    BitBtn1.Caption := 'Правильный ответ установлен. К след. вопросу';
    BitBtn2.Visible := True;
    Label1.Visible := False;
    ButtonQAdd.Visible := True;
    ButtonQDel.Visible := True;
    ButtonQL.Visible := True;
    ButtonQR.Visible := True;
    BitBtnTestBreak.Caption := 'Закрыть тест';
  end;

  // чуть меньше панель главной сделать
  Panel00.Width := Panel0.Width - 32;
  Panel00.Height := Panel0.Height - 32;
  // если по центру
  Panel00.Left := (Panel0.Width - Panel00.Width) div 2;
  Panel00.Top := (Panel0.Height - Panel00.Height) div 2;

  LoadFromMemo(); // Загрузить из memo формата
  GetTTest(); // получить из TTest текущего




end;

procedure TFormTest.BitBtn1Click(Sender: TObject);
var
  nv, npI, i : Integer;
  np : Real;
  tt : TTest;
begin
  // Дать ответ и перейти к следующему билету
  if not Form1.Editing then
  begin
    nOtv := nOtv + 1; // сколько ответов успели дать
  end;     

  if (iLs > -1) and (iLs < list.Count) then
  begin
    SetTTest(); // записать в TTest текущий
    if iLs < list.Count-1 then
    begin
      iLS := iLs + 1;
      GetTTest(); // получить из TTest текущего
    end
    else
    begin
      // это послений и если не редактирование, то закончить тест
      if not Form1.Editing then
      begin
        // если не в режиме редактирования
        if not Form1.Editing then
        begin
          // результаты тестирования
          res := res + #13#10 + '+++ ТЕСТ ПРОЙДЕН в ' + FormatDateTime('dd.mm.yyyy hh:nn:ss', Now);
          res := res + #13#10 + 'Дано ответов ' + IntToStr( nOtv ) + ' из '
            + IntToStr( list.Count );
          // подсчет результатов
          nv := 0;
          for i:=0 to list.Count-1 do
          begin
            tt := list.Items[i];
            if (tt.notv = tt.vybr) and (tt.vybr >= 1) then Inc(nv);
          end;
          np := nv;
          np := (np / list.Count) * 100;
          npI := Round( np );
          res := res + #13#10 + 'РЕЗУЛЬТАТ: ' + IntToStr(npI) + '%';
          bal := npI; // балл за тест в процентах
        end;
        ModalResult := mrOk;
      end;
    end; 
  end;
  
end;

procedure TFormTest.BitBtnTestBreakClick(Sender: TObject);
var
  nv, npI, i : Integer;
  np : Real;
  tt : TTest;
begin
  // Прервать тест
  // если не в режиме редактирования
  if not Form1.Editing then
  begin
    // результаты тестирования
    res := res + #13#10 + '--- ТЕСТ ПРЕРВАН в ' + FormatDateTime('dd.mm.yyyy hh:nn:ss', Now);
    res := res + #13#10 + 'Дано ответов ' + IntToStr( nOtv ) + ' из '
            + IntToStr( list.Count );
    // подсчет результатов
    nv := 0;
    for i:=0 to list.Count-1 do
    begin
      tt := list.Items[i];
      if (tt.notv = tt.vybr) and (tt.vybr >= 1) then Inc(nv);
    end;
    np := nv;
    np := (np / list.Count) * 100;
    npI := Round( np );
    res := res + #13#10 + 'РЕЗУЛЬТАТ: ' + IntToStr(npI) + '%';
    bal := npI; // балл за тест в процентах
  end;
  ModalResult := mrCancel;
end;

procedure TFormTest.BitBtn2Click(Sender: TObject);
begin
  // Предыдущий вопрос
  if (iLs > -1) and (iLs < list.Count) then
  begin
    SetTTest(); // записать в TTest текущий
    if iLs > 0 then
    begin
      iLS := iLs - 1;
    end;
    GetTTest(); // получить из TTest текущего
  end;



end;

procedure TFormTest.ButtonSelFileClick(Sender: TObject);
var
  f : string;
begin
  // выбрать файл
  f := Trim(EditFile.Text);
  if f = '' then
  begin
    OpenDialog1.FileName := ExtractFilePath( Application.ExeName ) + 'System\Tests\JPG\no.jpg';
  end
  else
  begin
     OpenDialog1.FileName := ExtractFilePath( Application.ExeName ) + 'System\Tests\JPG\'
       + f;
  end;

  if OpenDialog1.Execute then
  begin
    f := ExtractFileName( OpenDialog1.FileName );
    EditFile.Text := f;
  end;

end;

procedure TFormTest.ButtonQAddClick(Sender: TObject);
var
  tt : TTest;
begin
  // + Добавить вопрос

  SetTTest(); // записать в TTest текущий

  tt := TTest.Create;
  tt.filename := '';
  tt.sek := 30;
  tt.notv := -1;
  tt.vybr := -1; // выбран пользователем ответ
  tt.vopr := '';
  tt.otv[1] := '';
  tt.otv[2] := '';
  tt.otv[3] := '';
  tt.otv[4] := '';
  list.Add( tt );
  iLs := list.Count-1;

  GetTTest(); // получить из TTest текущего
  
end;

procedure TFormTest.ButtonQDelClick(Sender: TObject);
begin
  // - Удалить вопрос
  if (iLs > -1) and (iLs < list.Count) then
  begin
    list.Delete( iLs );
    if iLs = list.Count then iLs := list.Count-1;
    GetTTest(); // получить из TTest текущего
  end;
end;

procedure TFormTest.ButtonQLClick(Sender: TObject);
begin
  // < N вопроса
  if (iLs > -1) and (iLs < list.Count) then
  begin
    SetTTest(); // записать в TTest текущий
    if iLs > 0 then
    begin
      list.Exchange(iLs, iLs-1);
      iLs := iLs - 1;
    end;
    GetTTest(); // получить из TTest текущего
  end;
end;

procedure TFormTest.ButtonQRClick(Sender: TObject);
begin
  // > N вопроса
  if (iLs > -1) and (iLs < list.Count) then
  begin
    SetTTest(); // записать в TTest текущий
    if iLs < list.Count-1 then
    begin                                  
      list.Exchange(iLs, iLs+1);
      iLs := iLs + 1;
    end;
    GetTTest(); // получить из TTest текущего
  end;
end;

procedure TFormTest.FormDestroy(Sender: TObject);
begin
  list.Free;
end;

procedure TFormTest.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  if Form1.Editing then SetTTest(); // записать в TTest текущий  
  SaveToMemo(); // Сохранить в memo формат
end;

procedure TFormTest.CheckBoxA1Click(Sender: TObject);
var
  tt : TTest;
begin
  if CheckBoxA1.Checked then
  begin
    CheckBoxA2.Checked := False;
    CheckBoxA3.Checked := False;
    CheckBoxA4.Checked := False;
    // если обучающее тестирование, то цветом ответ
    if obTest and (iLs >= 0) then
    begin
      tt := list.Items[iLs];
      if tt.notv = 1 then MemoA1.Color := RGB(128, 255, 128)
      else MemoA1.Color := RGB(255, 128, 128);
    end;
  end;
  BitBtn1.Enabled := CheckBoxA1.Checked or CheckBoxA2.Checked
    or CheckBoxA3.Checked or CheckBoxA4.Checked;

end;

procedure TFormTest.CheckBoxA2Click(Sender: TObject);
var
  tt : TTest;
begin
  if CheckBoxA2.Checked then
  begin
    CheckBoxA1.Checked := False;
    CheckBoxA3.Checked := False;
    CheckBoxA4.Checked := False;
    // если обучающее тестирование, то цветом ответ
    if obTest and (iLs >= 0) then
    begin
      tt := list.Items[iLs];
      if tt.notv = 2 then MemoA2.Color := RGB(128, 255, 128)
      else MemoA2.Color := RGB(255, 128, 128);
    end;
  end;
  BitBtn1.Enabled := CheckBoxA1.Checked or CheckBoxA2.Checked
    or CheckBoxA3.Checked or CheckBoxA4.Checked;
end;

procedure TFormTest.CheckBoxA3Click(Sender: TObject);
var
  tt : TTest;
begin
  if CheckBoxA3.Checked then
  begin
    CheckBoxA2.Checked := False;
    CheckBoxA1.Checked := False;
    CheckBoxA4.Checked := False;
    // если обучающее тестирование, то цветом ответ
    if obTest and (iLs >= 0) then
    begin
      tt := list.Items[iLs];
      if tt.notv = 3 then MemoA3.Color := RGB(128, 255, 128)
      else MemoA3.Color := RGB(255, 128, 128);
    end;
  end;
  BitBtn1.Enabled := CheckBoxA1.Checked or CheckBoxA2.Checked
    or CheckBoxA3.Checked or CheckBoxA4.Checked;
end;

procedure TFormTest.CheckBoxA4Click(Sender: TObject);
var
  tt : TTest;
begin
  if CheckBoxA4.Checked then
  begin
    CheckBoxA2.Checked := False;
    CheckBoxA3.Checked := False;
    CheckBoxA1.Checked := False;
    // если обучающее тестирование, то цветом ответ
    if obTest and (iLs >= 0) then
    begin
      tt := list.Items[iLs];
      if tt.notv = 4 then MemoA4.Color := RGB(128, 255, 128)
      else MemoA4.Color := RGB(255, 128, 128);
    end;
  end;
  BitBtn1.Enabled := CheckBoxA1.Checked or CheckBoxA2.Checked
    or CheckBoxA3.Checked or CheckBoxA4.Checked;
end;

procedure TFormTest.Timer1Timer(Sender: TObject);
begin
  Timer1.Enabled := False;
  if obTest then Exit;
  
  Timer1.Tag := Timer1.Tag - 1;
  if Timer1.Tag < 0 then Timer1.Tag := 0;
  EditSek.Text := ' ' + IntToStr( Timer1.Tag);
  if Timer1.Tag <= 10 then
  begin
    EditSek.Color := clRed;
    EditSek.Font.Color := clWhite;
  end
  else
  begin
    EditSek.Color := clWindow;
    EditSek.Font.Color := clBlue;
  end;
  if Timer1.Tag = 0 then
  begin
    BitBtn1.Enabled := True;
    BitBtn1Click( self );
  end
  else Timer1.Enabled := True;
end;

procedure TFormTest.NCopyClick(Sender: TObject);
var
  m : TMemo;
begin
  // Копировать
  m := nil;
  if MemoQ.Focused then m := MemoQ
  else if MemoA1.Focused then m := MemoA1
  else if MemoA2.Focused then m := MemoA2
  else if MemoA3.Focused then m := MemoA3
  else if MemoA4.Focused then m := MemoA4;
  if m <> nil then
  begin
    m.CopyToClipboard;
  end;
end;

procedure TFormTest.NInsClick(Sender: TObject);
var
  m : TMemo;
begin
  // Вставить
  if not Form1.Editing then Exit;
  m := nil;
  if MemoQ.Focused then m := MemoQ
  else if MemoA1.Focused then m := MemoA1
  else if MemoA2.Focused then m := MemoA2
  else if MemoA3.Focused then m := MemoA3
  else if MemoA4.Focused then m := MemoA4;
  if m <> nil then
  begin
    m.PasteFromClipboard;
  end;
end;

procedure TFormTest.NCutClick(Sender: TObject);
var
  m : TMemo;
begin
  // вырезать
  if not Form1.Editing then Exit;
  m := nil;
  if MemoQ.Focused then m := MemoQ
  else if MemoA1.Focused then m := MemoA1
  else if MemoA2.Focused then m := MemoA2
  else if MemoA3.Focused then m := MemoA3
  else if MemoA4.Focused then m := MemoA4;
  if m <> nil then
  begin
    m.CutToClipboard;
  end;
end;

procedure TFormTest.NDelClick(Sender: TObject);
var
  m : TMemo;
begin
  // Удалить
  if not Form1.Editing then Exit;
  m := nil;
  if MemoQ.Focused then m := MemoQ
  else if MemoA1.Focused then m := MemoA1
  else if MemoA2.Focused then m := MemoA2
  else if MemoA3.Focused then m := MemoA3
  else if MemoA4.Focused then m := MemoA4;
  if m <> nil then
  begin
    m.SelText := '';
  end;
end;

procedure TFormTest.NSelAllClick(Sender: TObject);
var
  m : TMemo;
begin
  // Выделить всё
  m := nil;
  if MemoQ.Focused then m := MemoQ
  else if MemoA1.Focused then m := MemoA1
  else if MemoA2.Focused then m := MemoA2
  else if MemoA3.Focused then m := MemoA3
  else if MemoA4.Focused then m := MemoA4;
  if m <> nil then
  begin
    m.SelectAll;
  end;
end;

procedure TFormTest.EditFileChange(Sender: TObject);
begin
  // при изменении таймер загрузки включим
  TimerLoadFile.Enabled := False;
  TimerLoadFile.Enabled := True;

end;

procedure TFormTest.TimerLoadFileTimer(Sender: TObject);
var
  fn, fnAll, fnLoad : string;
begin
  TimerLoadFile.Enabled := False;
  // загрузка файла если есть
  fn := Trim(EditFile.Text);
  fnAll := ExtractFilePath( Application.ExeName ) + 'System\Tests\JPG\' + fn;

  // если файл существует
  if (fn = '') then
  begin
    fnLoad := ExtractFilePath( Application.ExeName ) + 'System\Tests\JPG\no.jpg';
  end
  else
  begin
    if FileExists( fnAll ) then
      fnLoad := fnAll
    else
      fnLoad := ExtractFilePath( Application.ExeName ) + 'System\Tests\JPG\no.jpg';
  end;

  Image1.Picture.LoadFromFile( fnLoad );  

end;

end.
