{Copyright or © or Copr. :

CNRS - Laboratoire Mouvement & Perception
franck.buloup@univmed.fr

This software is a computer program whose purpose is to highly simplify  
the use of ADwinPro realtime systems when you develop experimental
protocols  on life's sciences area.

This software is governed by the CeCILL  license under French law and
abiding by the rules of distribution of free software.  You can  use, 
modify and/ or redistribute the software under the terms of the CeCILL
license as circulated by CEA, CNRS and INRIA at the following URL
"http://www.cecill.info". 

As a counterpart to the access to the source code and  rights to copy,
modify and redistribute granted by the license, users are provided only
with a limited warranty  and the software's author,  the holder of the
economic rights,  and the successive licensors  have only  limited
liability. 

In this respect, the user's attention is drawn to the risks associated
with loading,  using,  modifying and/or developing or reproducing the
software by the user in light of its specific status of free software,
that may mean  that it is complicated to manipulate,  and  that  also
therefore means  that it is reserved for developers  and  experienced
professionals having in-depth computer knowledge. Users are therefore
encouraged to load and test the software's suitability as regards their
requirements in conditions enabling the security of their systems and/or 
data to be ensured and,  more generally, to use and operate it in the 
same conditions as regards security. 

The fact that you are presently reading this means that you have had
knowledge of the CeCILL license and that you accept its terms.}
unit UExecute;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls, xmldom, XMLIntf, msxmldom, XMLDoc, XMLClasses,
  UGlobal, ExtCtrls, ToolWin, OleCtrls, ADWINCONTROLLib_TLB, ActnList,
	ImgList, URecupGeneThread, Contnrs, DocoFastLineSeriesClass, Gauges,
  ActnMan, ActnCtrls, XPStyleActnCtrls, IdBaseComponent, IdComponent,
  IdTCPConnection, IdTCPClient;
type
  TExecuteForm = class(TForm)
    StatusBar1: TStatusBar;
    XMLDoco: TXMLDocument;
    ADwin: TADwin;
    Panel1: TPanel;
    ThreadsTimer: TTimer;
    ImageList1: TImageList;
    ActionList1: TActionList;
    runAction: TAction;
    pauseAction: TAction;
    QuitterAction: TAction;
    ArretAction: TAction;
    Panel2: TPanel;
    BootLabel: TLabel;
    CPUGauge: TGauge;
    MemProgGauge: TGauge;
    MemDataGauge: TGauge;
    TimeLabel: TLabel;
    ActionManager1: TActionManager;
    ActionToolBar1: TActionToolBar;
    TestParamAction: TAction;
    procedure FormShow(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure BootADWinPro;
    procedure ADwinErrorOccur(ASender: TObject;
      const FunctionName: WideString; Code: Integer);
    procedure ThreadsTimerTimer(Sender: TObject);
    procedure FormResize(Sender: TObject);
    procedure runActionExecute(Sender: TObject);
    procedure pauseActionExecute(Sender: TObject);
    procedure QuitterActionExecute(Sender: TObject);
    procedure ArretActionExecute(Sender: TObject);
    //procedure TerminateAfficheThread(Sender: TObject);
    procedure TerminateRecupGeneThread(Sender: TObject);
    procedure TestParamActionExecute(Sender: TObject);
  private
    { Déclarations privées }
    ADWinError : boolean;
    fileName : string;
    numSujet : integer;
		base_TAB_PARAM : integer;
		procedure createIHMForST;
		procedure read_TAB_PARAM;
    procedure init_TAB_PARAM_fromFile;
    procedure setBase_TAB_PARAM(forSessionNum : integer);
    function seekFirstTrialUndone : boolean;
    function runNextTrial : boolean;
	public
		{ Déclarations publiques }
		TAB_PARAM : array of array of array of single;
    DocDOCOMETRE : IXMLROOTType;
    numST : integer;
    numSession : integer;
    sessionList : array of integer;
    mode : string;
    numEssai : integer;
    ASujet : IXMLSUJETType;
    ListeDocoFastLineSeries : TObjectList;
    MemProgMax : integer;
    MemDataMax : integer;
    procedure Delay(microsec : int64);
  end;

var
  ExecuteForm: TExecuteForm;
  RecupGeneThread : TRecupGeneThread;

implementation

uses UGrapheExec, UParamTab;

{$R *.dfm}

procedure TExecuteForm.Delay(microsec : int64);
var Freq,C1,C2,DC : int64;
    dummy : double;
begin
  QueryPerformanceFrequency(Freq);
  QueryPerformanceCounter(C1);
  dummy := 1.0*microsec/1000000.0;
  C2 := C1;
  DC := trunc(dummy*Freq);
  while (C2-C1) < DC do
  begin
    Application.ProcessMessages;
    QueryPerformanceCounter(C2);
  end;
end;

procedure TExecuteForm.BootADWinPro;
var version : integer;
begin
  ADWin.DeviceNo := Link_Address;

  //showmessage('LinkAddress : ' + inttostr(Link_Address) + #13 +
  //            'adBasicVersion : ' + inttostr(adBasicVersion) + #13 +
  //            'SystemType : ' + SystemType);

  BootLabel.Caption := 'L''ADWinPro est prêt';
	version := Adwin.Test_Version;
	if Version <> 0 then
  begin

    if((SystemType = 'ADWINPRO') or (SystemType = 'ADWINGOLD')) then
    begin
      ADWin.Boot('c:\ADWin\ADwin9.btl');
      cpuID := '9';
    end;

    if(SystemType = 'ADWINPRO II') or (SystemType = 'ADWINPRO II Old Cards') then
    begin
      ADWin.Boot('c:\ADWin\ADwin11.btl');
      cpuID := 'B';
    end;

  end;


end;

procedure TExecuteForm.init_TAB_PARAM_fromFile;
var fichierParam : TStringList;
    i,j,nbParam,numParam,indexNumParam : integer;
    S,subS : string;
    paramName : TStringList;
    InfoCanaux : TInfoCanaux;
begin
  if FileExists(rep_manip + ASujet.NOM + '.prm') then
  begin
    //Dans le fichier paramètre il y ts les essais de toutes les sessions
    fichierParam := TStringList.Create;
    fichierParam.LoadFromFile(rep_manip + ASujet.NOM + '.prm');

    //calcul du nbre de param et recup de leur nom
    InfoCanaux := DocDOCOMETRE.RendreListeInfoCanaux;
    paramName := TStringList.Create;
    nbParam := 0;
    S := fichierParam[0];
    repeat
      if pos(';',S) <> 0 then
      begin
        subS := copy(S,1,pos(';',S)-1);
        paramName.Add(subS);
        delete(S,1,pos(';',S));
      end else
      begin
        paramName.Add(S);
        S := '';
      end;
      inc(nbParam);
    until S = '';

    SetLength(TAB_PARAM,fichierParam.Count - 1);
    for i := 1 to fichierParam.Count - 1 do
    begin
      SetLength(TAB_PARAM[i-1],nbParam);
      for j := 0 to nbParam - 1 do SetLength(TAB_PARAM[i-1][j],2);
    end;

    for i := 1 to fichierParam.Count - 1 do
    begin
      S := fichierParam[i];
      numParam := 0;
      repeat
        if pos(';',S) <> 0 then
        begin
          subS := copy(S,1,pos(';',S) - 1);
          delete(S,1,pos(';',S));
        end else
        begin
          subS := S;
          S := ''
        end;
        TAB_PARAM[i-1][numParam][0] := strtofloat(subS);//valeur du param
        indexNumParam := infoCanaux.Nom.IndexOf(paramName[numParam]);
        TAB_PARAM[i-1][numParam][1] := strtoint(infoCanaux.propag[indexNumParam]);//A propager ou non
        inc(numParam);
      until S = '';
    end;
    fichierParam.Free;
    paramName.free;
    InfoCanaux.Free;
  end;
end;

procedure TExecuteForm.setBase_TAB_PARAM(forSessionNum : integer);
var i : integer;
begin
  //calcul de la base et dimensionner TAB_PARAM
  base_TAB_PARAM := 0;
  for i := 0 to forSessionNum - 1
  do base_TAB_PARAM := base_TAB_PARAM + ASujet.SESSIONS[i].ESSAIS.Count;
end;

procedure TExecuteForm.read_TAB_PARAM;
var numEssaiTAB,i : integer;
begin
	if TAB_PARAM <> nil then
	begin
		numEssaiTAB := base_TAB_PARAM + numEssai;

    if numEssaiTAB <= high(TAB_PARAM) then
    begin
      for i := 0 to high(TAB_PARAM[numEssaiTAB]) do//for i := 0 to high(TAB_PARAM[numEssaiTAB]) do
      begin

        //Recup valeur du paramètre si propagation et au dela premier essai
        if TAB_PARAM[numEssaiTAB][i][1] = 1 then
        begin
          if numEssai > 0
          then if  not ADWinError then
               begin
                 ADWin.GetData_Float(200,TAB_PARAM[numEssaiTAB-1][i][0],i+1,1);
                 if(numEssai < DocDOCOMETRE.SESSIONS[numSession].ESSAIS.Count)
                 then ADWin.GetData_Float(200,TAB_PARAM[numEssaiTAB][i][0],i+1,1);
               end;
        end;

        if  not ADWinError then
        begin
          ADwin.SetData_Float(200,TAB_PARAM[numEssaiTAB][i][0],i+1,1)
        end;

      end;
    end else
    begin

      numEssaiTAB := high(TAB_PARAM);

      for i := 0 to high(TAB_PARAM[numEssaiTAB]) do//for i := 0 to high(TAB_PARAM[numEssaiTAB]) do
      begin

        //Recup valeur du paramètre si propagation et au dela premier essai
        if TAB_PARAM[numEssaiTAB][i][1] = 1 then
        begin
          if numEssai > 0
          then if  not ADWinError then
               begin
                 ADWin.GetData_Float(200,TAB_PARAM[numEssaiTAB][i][0],i+1,1);
               end;
        end;

        if  not ADWinError then
        begin
          ADwin.SetData_Float(200,TAB_PARAM[numEssaiTAB][i][0],i+1,1)
        end;

      end;
    end;

  end;
end;

procedure TExecuteForm.FormCreate(Sender: TObject);
var Handle_process : HWND;
    S,STemp : string;
begin
  UGlobal.Readconfig;

  Handle_process := GetCurrentProcess();

  if Level_Appli = 'Idle'
  then SetPriorityClass(Handle_Process,IDLE_PRIORITY_CLASS);
  if Level_Appli = 'Normal'
  then SetPriorityClass(Handle_Process,NORMAL_PRIORITY_CLASS);
  if Level_Appli = 'High'
  then SetPriorityClass(Handle_Process,HIGH_PRIORITY_CLASS);
  if Level_Appli = 'Realtime'
  then SetPriorityClass(Handle_Process,REALTIME_PRIORITY_CLASS);

  Rep_manip := ExtractFilePath(ParamStr(1));
  fileName := ParamStr(1);
  Mode := ParamStr(2);
  if mode = 'TEST' then
  begin
    numST := strtoint(ParamStr(3));
  end;
  if mode = 'EXEC' then
  begin
    numSujet := strtoint(ParamStr(3));
    numSession := 0;
    S := ParamStr(4);
    //Creation de la liste des sessions à executer
    if pos('(',S) > 0 then//Plusieur sessions ds la foulée
    begin
      System.Delete(S,1,1);
      System.Delete(S,length(S),1);
      repeat
        if pos('-',S) <> 0 then
        begin
          STemp := copy(S,1,pos('-',S) - 1);
          delete(S,1,pos('-',S));
        end else
        begin
          STemp := S;
          S := '';
        end;
        setlength(sessionList,high(sessionList)+2);
        sessionList[high(sessionList)] := strtoint(STemp);
      until S = '';
    end else
    begin//une seule session
      setLength(sessionList,1);
      sessionList[0] := strtoint(S);
    end;
  end;
  ADWinError := false;
  BootADWinPro;
	if  not ADWinError then
	begin
		MemProgMax := ADwin.Free_Mem(1);
		MemDataMax := ADwin.Free_Mem(3);
	end;

  TAB_PARAM := nil;
end;

function TExecuteForm.seekFirstTrialUndone : boolean;
var i,indexSession : integer;
begin
  result := true;
  //pour toutes les sessions
  for i := 0 to high(sessionList) do
  begin
    numEssai := -1;
    result := true;
    numSession := i;
    indexSession  := sessionList[i];
    if ASujet.SESSIONS[indexSession].ESSAIS.Count > 0 then
    begin
      repeat
        inc(numEssai);
        if numEssai < ASujet.SESSIONS[indexSession].ESSAIS.Count
        then if ASujet.SESSIONS[indexSession].ESSAIS[numEssai].ETAT = 'NON EFFECTUE'
             then break;
      until numEssai = ASujet.SESSIONS[indexSession].ESSAIS.Count;
    end;

    if (numEssai = -1) or (numEssai = ASujet.SESSIONS[indexSession].ESSAIS.Count) then
    begin
      if numEssai = -1 then
      begin
        showmessage('Aucun essai n''est configuré dans cette session !');
        result := false;
      end;
      if numEssai = ASujet.SESSIONS[indexSession].ESSAIS.Count
      then if high(sessionList) = 0 then
           begin
             showmessage('Tous les essais de cette session ont été effectués !');
             result := false;
           end else
           begin
             if numSession = high(sessionList) then
             begin
               showmessage('Tous les essais de toutes les sessions ont été effectués !');
               result := false;
             end;
           end;
    end else break;
  end;
end;

procedure TExecuteForm.FormShow(Sender: TObject);
var i,nbParam : integer;
begin

  ExecuteForm.Width := executeFormWidth;
  ExecuteForm.Height := executeFormHeight;
  ExecuteForm.Top := executeFormTopPosition;
  ExecuteForm.Left := executeFormLeftPosition;
  if(executeFormMaximized)
  then  ExecuteForm.WindowState := wsMaximized
  else ExecuteForm.WindowState := wsNormal;

  //init objet TXMLDocument
  XMLDoco.LoadFromFile(fileName);
  //lien avec racine IXMLROOTType
  DocDOCOMETRE := GetRoot(XMLDoco);

  ListeDocoFastLineSeries := TObjectList.Create(false);
  //ListeDocoFastLineSeries.OwnsObjects := true;

  Caption := 'DOCoMETRe - Exécution - ' + fileName;
  if mode = 'TEST' then
  begin
    StatusBar1.Panels[0].Text := 'mode Test';
    StatusBar1.Panels[1].Text := DocDOCOMETRE.ST[numST].NOM;
    StatusBar1.Panels[2].Text := 'NA';
		if  not ADWinError then
		begin
			ADwin.Clear_Process(num_process);
			ADwin.Load_Process(Rep_manip + 'BinSources\'+ DocDOCOMETRE.ST[numST].NOM +
																'.t' + cpuID + inttostr(num_process));
		end;
		createIHMForST;

    base_TAB_PARAM := 0;
		numEssai := 0;//-1;//0;
    numSession := -1;
		nbParam := 0;

		for i := 0 to DocDOCOMETRE.CANINT.Count - 1
		do if DocDOCOMETRE.CANINT[i].GENRE = 'PARAMETRE'
			 then inc(nbParam);

		if nbParam > 0 then
		begin
			setLength(TAB_PARAM,1);
			setLength(TAB_PARAM[0],nbParam);
			for i := 0 to nbParam - 1
			do setLength(TAB_PARAM[0][i],2);
			testParamAction.Visible := true;
		end;

	end;

	if mode = 'EXEC' then
	begin
		ASujet := DocDOCOMETRE.SUJETS[numSujet];
		StatusBar1.Panels[0].Text := 'Sujet : ' + ASujet.NOM;
		StatusBar1.Panels[1].Text := 'Session : ' + ASujet.SESSIONS[sessionList[numSession]].NOM +
		' (' + inttostr(ASujet.SESSIONS[sessionList[numSession]].ESSAIS.Count) + ' essais)';

		//positioner sur le premier essai non effectué
    if seekFirstTrialUndone then
    begin

      init_TAB_PARAM_fromFile;
      setBase_TAB_PARAM(sessionList[numSession]);

      StatusBar1.Panels[2].Text := 'Essai n°' + inttostr(numEssai + 1) + ' (' +
      ASujet.SESSIONS[sessionList[numSession]].ESSAIS[numEssai].NOMST + ')';
      //Recup num ST associée
      for i := 0 to DocDOCOMETRE.ST.Count - 1 do
      begin
        numST := i;
        if DocDOCOMETRE.ST[i].NOM = ASujet.SESSIONS[sessionList[numSession]].ESSAIS[numEssai].NOMST
        then break;
      end;
      if  not ADWinError then
      begin
        ADwin.Clear_Process(num_process);
        ADwin.Load_Process(Rep_manip + 'BinSources\'+ DocDOCOMETRE.ST[numST].NOM +
                                '.t' + cpuID + inttostr(num_process));
      end;
      createIHMForST;

      testParamAction.Visible := false;
    end else Application.Terminate;;
    
	end;

end;


procedure TExecuteForm.FormClose(Sender: TObject; var Action: TCloseAction);
var buffer     :   LPTSTR;
    StartupInfo : TStartupInfo;
    ProcessInfo : TProcessInformation;
    LigneDeCmde : TStringList;
    S : string;
		i,j : integer;
		//c1,c2,freq : int64;
		//time : double;
    fichierParam : TStringList;
begin
	{if  not ADWinError then
	begin
		if ADwin.Process_Status(num_process) = 1 then
		begin

			ADwin.Stop_Process(num_process);
			if RecupGeneThread <> nil then
			begin
				QueryPerformanceFrequency(Freq);
				QueryPerformanceCounter(c1);
				c2 := c1;
				repeat
					QueryPerformanceCounter(c2);
					time := (c2-c1)/freq;
					if RecupGeneThread <> nil
					then WaitForSingleObject(RecupGeneThread.Handle,10);
					Application.ProcessMessages;
				until (time > 1.0);
			end;
		end;
	end;  }



  if mode = 'EXEC' then
  begin
    XMLDoco.SaveToFile(XMLDoco.FileName);
    if FileExists(rep_manip + ASujet.NOM + '.prm') then
    begin
      //Sauvegarde du fichier param pour les params propagé
      fichierParam := TStringList.Create;
      fichierParam.LoadFromFile(rep_manip + ASujet.NOM + '.prm');
      for i := 0 to high(TAB_PARAM) do//ASujet.SESSIONS[numSession].ESSAIS.Count - 1 do
      begin

        S := '';
        for j := 0 to high(TAB_PARAM[i])
        do S := S + floattostr(TAB_PARAM[i][j][0]) + ';';
        delete(S,length(S),1);

        fichierParam[i+1] := S;
      end;

      fichierParam.SaveToFile(rep_manip + ASujet.NOM + '.prm');
      fichierParam.Free;
    end;
  end;


	
	for i := 0 to ListeDocoFastLineSeries.Count - 1
	do (ListeDocoFastLineSeries.Items[i] as TDocoFastLineSeries).free;
	ListeDocoFastLineSeries.Free;


  S := '"' + Rep_racine + 'Docometre2.exe" "' + ParamStr(1) + '" ' + ParamStr(2) + ' '
        + ParamStr(3);
  LigneDeCmde := TStringList.Create;
  LigneDeCmde.Add(S);
  LigneDeCmde.SaveToFile(Rep_manip + 'Run.bat');
  LigneDeCmde.free;
  //Execution de Run.bat
  buffer := LPCTSTR(Rep_manip + 'Run.bat');

  FillChar(StartupInfo,Sizeof(StartupInfo),#0);
  StartupInfo.cb := Sizeof(StartupInfo);
  StartupInfo.dwFlags := STARTF_USESHOWWINDOW;
  StartupInfo.wShowWindow := SW_HIDE;
  //StartupInfo.wShowWindow := SW_SHOW;

  CreateProcess(buffer,
                        nil,   { pointer to command line string }
                        nil,   { pointer to process security attributes }
                        nil,   { pointer to thread security attributes }
                        false, { handle inheritance flag }
                        CREATE_NEW_CONSOLE or
                        NORMAL_PRIORITY_CLASS, { creation flags }
                        nil,   { pointer to new environment block }
                        nil,   { pointer to current directory name }
                        StartupInfo,  { pointer to STARTUPINFO }
                        ProcessInfo) ; { pointer to PROCESS_INF }



  saveExecuteMainFormPositions((ExecuteForm.WindowState = wsMaximized),ExecuteForm.left,ExecuteForm.Top, ExecuteForm.Width, ExecuteForm.Height);
  Application.Terminate;
end;

procedure TExecuteForm.ADwinErrorOccur(ASender: TObject;
  const FunctionName: WideString; Code: Integer);
var S : string;
begin
  if (FunctionName <> 'Test_Version') then
  begin
    if recupGeneThread <> nil then
    begin
      S := 'Erreur ADWinPro - Erreur dans la fonction  "' + FunctionName +
           '" avec le message "' + ADWin.Get_Last_Error_Text(Code) + '"';
      showmessage(S);
    end;
    BootLabel.Caption := S;
    ADWinError := true;
  end;
end;

procedure TExecuteForm.createIHMForST;
var i,j : integer;
    AGrapheExecForm : TGrapheExecForm;
    AGraphe : IXMLListeGraphesType;
    NewCourbe : TObject;
begin

  ListeDocoFastLineSeries.Clear;
  repeat
    if Self.MDIChildCount > 0
    then (Self.MDIChildren[0] as TGrapheExecForm).Close;
    Application.ProcessMessages;
  until Self.MDIChildCount = 0;

  for i := 0 to DocDOCOMETRE.ST[numST].GRAPHES.Count - 1 do
  begin
    AGraphe := DocDOCOMETRE.ST[numST].GRAPHES[i];
    AGrapheExecForm := TGrapheExecForm.Create(Application);
    AGrapheExecForm.Caption := 'Graphe n°' + inttostr(i + 1);
    AGrapheExecForm.Name := 'Graphe' + inttostr(i+1);

    AGrapheExecForm.setGraphe(AGraphe.GENRE,AGraphe.TEMPSVISU,
                              (AGraphe.ECHELLEYAUTO = 1),AGraphe.YMIN,AGraphe.YMAX,
                              (AGraphe.ECHELLEXAUTO = 1),AGraphe.XMIN,AGraphe.XMAX);

    for j := 0 to AGraphe.COURBES.Count - 1 do
    begin
      NewCourbe :=
      AGrapheExecForm.addCourbe(AGraphe.COURBES[j].NOMCANALORDO,
                                AGraphe.COURBES[j].NOMCANALABSC,
                                AGraphe.TEMPSVISU,
                                AGraphe.COURBES[j].COLOR);


      ListeDocoFastLineSeries.Add(NewCourbe);

    end;
    
  end;
  
  Tile;

end;

procedure TExecuteForm.FormResize(Sender: TObject);
begin
  Tile;
end;
                                         {
procedure TExecuteForm.TerminateAfficheThread;
begin
  Panel2.Caption := 'affichage terminé';
end;                                    }

procedure TExecuteForm.TerminateRecupGeneThread;
var reRun,fin : boolean;
    i : integer;
begin

	Delay(200000);//200ms de delay
	if  not ADWinError then
	begin
		CPUGauge.Progress := ADwin.Workload(0);
		MemProgGauge.Progress := 100-trunc(100.0*ADwin.Free_Mem(1) / MemProgMax);
		MemDataGauge.Progress :=  100-trunc(100.0*ADwin.Free_Mem(3) / MemDataMax);
	end;
  RecupGeneThread := nil;

  runAction.Enabled := true;
  
  if mode = 'EXEC' then
  begin

    reRun := false;

    if ASujet.SESSIONS[sessionList[numSession]].ESSAIS[numEssai].MODEDEM = 'Automatique'
    then ASujet.SESSIONS[sessionList[numSession]].ESSAIS[numEssai].ETAT := 'EFFECTUE'
    else begin
      if messageDLG('Valider cet essai ?',mtConfirmation,[mbYes,mbNo],0) = mrNo then
      begin
        if messageDLG('Refaire cet essai maintenant ?',mtConfirmation,[mbYes,mbNo],0) = mrYes
        then reRun := true;
      end else ASujet.SESSIONS[sessionList[numSession]].ESSAIS[numEssai].ETAT := 'EFFECTUE';
    end;

    if not reRun then
    begin

      fin := false;
      repeat
        inc(numEssai);
        if numEssai < ASujet.SESSIONS[sessionList[numSession]].ESSAIS.Count then
        begin
          if ASujet.SESSIONS[sessionList[numSession]].ESSAIS[numEssai].ETAT = 'NON EFFECTUE'
          then fin := true;
        end else fin := true;
      until fin;

      if numEssai < ASujet.SESSIONS[sessionList[numSession]].ESSAIS.Count
      then threadsTimer.Enabled := runNextTrial
      else begin

        for i := 0 to ASujet.SESSIONS[sessionList[numSession]].ESSAIS.Count - 1 do
        begin
          numEssai := i;
          if ASujet.SESSIONS[sessionList[numSession]].ESSAIS[numEssai].ETAT = 'NON EFFECTUE'
          then break;
        end;
        if i = ASujet.SESSIONS[sessionList[numSession]].ESSAIS.Count then
        begin

          inc(numEssai);
          read_TAB_PARAM;
          showmessage('Tous les essais de cette session ont été effectués !');

          //Passage à la session suivante si necessaire
          if numSession < high(sessionList) then
          begin
            //inc(numSession);
            numEssai := 0;
            seekFirstTrialUndone;
            setBase_TAB_PARAM(sessionList[numSession]);
            threadsTimer.Enabled := runNextTrial;
          end;

        end else threadsTimer.Enabled := runNextTrial;
      end;

    end else threadsTimer.Enabled := true;

  end;
end;

function TExecuteForm.runNextTrial : boolean;
var i : integer;
    messageString : string;
    reponse : integer;
begin

  result := false;
  //Recup num ST associée
  for i := 0 to DocDOCOMETRE.ST.Count - 1 do
  begin
    numST := i;
    if DocDOCOMETRE.ST[i].NOM = ASujet.SESSIONS[sessionList[numSession]].ESSAIS[numEssai].NOMST
    then break;
  end;

  if  not ADWinError then
  begin
    ADwin.Clear_Process(num_process);
    ADwin.Load_Process(Rep_manip + 'BinSources\'+ DocDOCOMETRE.ST[numST].NOM +
                          '.t' + cpuID + inttostr(num_process));
  end;

  createIHMForST;

  StatusBar1.Panels[1].Text := 'Session : ' + ASujet.SESSIONS[sessionList[numSession]].NOM +
		' (' + inttostr(ASujet.SESSIONS[sessionList[numSession]].ESSAIS.Count) + ' essais)';
  StatusBar1.Panels[2].Text := 'Essai n°' + inttostr(numEssai + 1) + ' (' +
  ASujet.SESSIONS[sessionList[numSession]].ESSAIS[numEssai].NOMST + ')';
  TimeLabel.Caption := 'Temps : 0.000000';
  StatusBar1.Refresh;

  if ASujet.SESSIONS[sessionList[numSession]].ESSAIS[numEssai].MODEDEM = 'Automatique' then
  begin
    if (GetAsyncKeyState(VK_END) AND 1)=1
    then result := false
    else begin
      if (GetAsyncKeyState(VK_PAUSE) AND 1)=1 then
      begin
        messageString := 'En pause... Cliquez sur "OK" pour continuer ou annulez';
        reponse := MessageDlg(messageString, mtInformation,[mbOk,mbCancel], 0);
        if reponse = mrOK
        then result := true
        else result := false;
      end else result := true;
    end;
  end else
  begin
    if messageDLG('Démarrer l''essai ?',mtInformation,[mbYes,mbNo],0) = mrYes
    then result := true;
  end;
end;

procedure TExecuteForm.ThreadsTimerTimer(Sender: TObject);
var ListeCanauxTrsfrtPCKeithley, ListeCanauxTrsfrtKeithleyPC : TStringList;
    i : integer;
    priorityLevel : TThreadPriority;
    continue : boolean;
begin
  threadsTimer.Enabled := false;

  continue := true;

  if mode = 'EXEC'
  then if numEssai >= ASujet.SESSIONS[sessionList[numSession]].ESSAIS.Count
       then continue := false;

  if continue then
  begin
    XMLDoco.SaveToFile(XMLDoco.FileName);

    read_TAB_PARAM;

    for i := 0 to ListeDocoFastLineSeries.Count - 1
    do (ListeDocoFastLineSeries.Items[i] as TDocoFastLineSeries).clearSerie;

    ListeCanauxTrsfrtPCKeithley := TStringList.Create;
    ListeCanauxTrsfrtPCKeithley.CaseSensitive := false;
    ListeCanauxTrsfrtPCKeithley.Sorted := true;
    DocDOCOMETRE.ST[numST].RendreListeCanauxTransfertPCKeithley(ListeCanauxTrsfrtPCKeithley);

    ListeCanauxTrsfrtKeithleyPC := TStringList.Create;
    ListeCanauxTrsfrtKeithleyPC.CaseSensitive := false;
    ListeCanauxTrsfrtKeithleyPC.Sorted := true;
    DocDOCOMETRE.ST[numST].RendreListeCanauxTransfertKeithleyPC(ListeCanauxTrsfrtKeithleyPC);

    //tpIdle, tpLowest, tpLower, tpNormal, tpHigher, tpHighest, tpTimeCritical
    priorityLevel := tpNormal;
    if Level_RecupGene = 'Idle' then priorityLevel := tpIdle;
    if Level_RecupGene = 'Lowest' then priorityLevel := tpLowest;
    if Level_RecupGene = 'Lower' then priorityLevel := tpLower;
    if Level_RecupGene = 'Normal' then priorityLevel := tpNormal;
    if Level_RecupGene = 'Higher' then priorityLevel := tpHigher;
    if Level_RecupGene = 'Highest' then priorityLevel := tpHighest;
    if Level_RecupGene = 'TimeCritical' then priorityLevel := tpTimeCritical;
    RecupGeneThread := TRecupGeneThread.Create(true,priorityLevel,
                                               ListeCanauxTrsfrtKeithleyPC,
                                               ListeCanauxTrsfrtPCKeithley);
    RecupGeneThread.OnTerminate := TerminateRecupGeneThread;
    RecupGeneThread.Resume;

    //Lancer thread affichage
    //AfficheThread := TAfficheThread.Create(true,tpLower);
    //AfficheThread.OnTerminate := TerminateAfficheThread;
    //AfficheThread.Resume;

    //InfoCanaux.Free;
    ListeCanauxTrsfrtKeithleyPC.Free;
    ListeCanauxTrsfrtPCKeithley.Free;

		//Reset Par FPar
		if  not ADWinError then
		begin
			for i := 1 to 80 do Adwin.Set_Par(i,0);
			for i := 1 to 80 do Adwin.Set_FPar(i,0);
		end;

		//Lancer le process adwin
		if  not ADWinError
		then ADwin.Start_Process(num_process);
  end else showmessage('Tous les essais de cette session ont été effectués !');
end;

procedure TExecuteForm.runActionExecute(Sender: TObject);
begin
  runAction.Enabled := false;
  ExecuteForm.Panel2.Color := clLime;
  if not ADWinError
  then threadsTimer.Enabled := true;
end;

procedure TExecuteForm.pauseActionExecute(Sender: TObject);
begin
  //pour faire une pause entre ST qd mode Automatique...
end;

procedure TExecuteForm.QuitterActionExecute(Sender: TObject);
{var i,j : integer;
    fichierParam : TStringList;
    S : string;   }
begin
  ArretActionExecute(Self);

 { if mode = 'EXEC' then
  begin
    XMLDoco.SaveToFile(XMLDoco.FileName);
    if FileExists(rep_manip + ASujet.NOM + '.prm') then
    begin
      //Sauvegarde du fichier param pour les params propagé
      fichierParam := TStringList.Create;
      fichierParam.LoadFromFile(rep_manip + ASujet.NOM + '.prm');
      for i := 0 to ASujet.SESSIONS[numSession].ESSAIS.Count - 1 do
      begin

        S := '';
        for j := 0 to high(TAB_PARAM[i + base_TAB_PARAM])
        do S := S + floattostr(TAB_PARAM[i + base_TAB_PARAM][j][0]) + ';';
        delete(S,length(S),1);

        fichierParam[i+base_TAB_PARAM+1] := S;
      end;

      fichierParam.SaveToFile(rep_manip + ASujet.NOM + '.prm');
      fichierParam.Free;
    end;
  end;    }
  close;
end;

procedure TExecuteForm.ArretActionExecute(Sender: TObject);
var c1,c2,freq : int64;
		time : double;
begin
//  if  not ADWinError then
//	begin
		if ADwin.Process_Status(num_process) = 1 then
		begin
			ADwin.Stop_Process(num_process);
			if RecupGeneThread <> nil then
			begin
				QueryPerformanceFrequency(Freq);
				QueryPerformanceCounter(c1);
				c2 := c1;
				repeat
					QueryPerformanceCounter(c2);
					time := (c2-c1)/freq;
					if RecupGeneThread <> nil
					then WaitForSingleObject(RecupGeneThread.Handle,10);
					Application.ProcessMessages;
				until (time > 1.0);
			end;
		end;
//	end;
end;

procedure TExecuteForm.TestParamActionExecute(Sender: TObject);
var i,j : integer;
begin
	ParamTabForm.ShowModal;

	for i := 1 to ParamTabForm.ValueListEditor.RowCount - 1
	do for j := 0 to DocDOCOMETRE.CANINT.Count - 1
		 do if DocDOCOMETRE.CANINT[j].GENRE = 'PARAMETRE'
				then if DocDOCOMETRE.CANINT[j].FENUMPAR = i
						 then TAB_PARAM[0][i-1][0] := strtofloat(ParamTabForm.ValueListEditor.Values[DocDOCOMETRE.CANINT[j].NOM]);

end;

end.
