unit umh_worker_sim;

{$mode delphi}

interface

uses
  xMatDefs, Classes, SysUtils, uglobs, usalasdejuego, uEstados, umh_sincrodata,
  syncobjs,
  utrayectorias_xcdpcf;

type

  { TTareaSimRangoCronicas }

  TTareaSimRangoCronicas = class(TTarea_mh)
    kTrayectoriaIni, kTrayectoriaFin: integer;
    //Trayectorias:TTrayectorias;
    constructor Create(nid, kTrayectoriaIni, kTrayectoriaFin:Integer);
  end;

  { TRobotOptRangoEstrellas }

  { TRobotSimRangoCronicas }

  TRobotSimRangoCronicas = class(TWorker_mh)
  private
    sala: TSalaDeJuego;
    procedure copiarVarsTiempoEjecucion( salaMadre_: TSalaDeJuego );
  public
    nTareasCalculadasEstePaso: integer;

    constructor Create(nid: integer; sincroData: TSincroData_mh;
      const salax: TSalaDeJuego);
    destructor destroy; override;
    procedure Execute; override;
    function GetEstadoSala: TEstadoDeLaSala;
  end;


  {$IFDEF SIM_MULTIHILO_NOTIFICANDO_GUI}
// Esto es para poder usar el progress bar del simulador.
var
  CS_SimFinCronica: TCriticalSection;
  mh_SimFinCronica: TProcNotificacion;
{$ENDIF}

implementation
{$IFDEF SIM_MULTIHILO_NOTIFICANDO_GUI}
procedure procSimFinCronica;
begin
  if assigned( mh_SimFinCronica ) then
  begin
    CS_SimFinCronica.enter;
    mh_SimFinCronica;
    CS_SimFinCronica.leave;
  end;
end;
{$ENDIF}

constructor TTareaSimRangoCronicas.Create(nid, kTrayectoriaIni,
  kTrayectoriaFin: Integer);
begin
  inherited Create(nid);
  self.kTrayectoriaIni := kTrayectoriaIni;
  self.kTrayectoriaFin := kTrayectoriaFin;
end;

constructor TRobotSimRangoCronicas.Create(nid: integer; sincroData: TSincroData_mh;
  const salax: TSalaDeJuego);
begin
  inherited Create(nid, sincroData);
  sala := usalasdejuego.cargarSala(nid + 1, salax.archiSala_,
    salax.EscenarioActivo.nombre, True);

  sala.globs.idHilo := nid + 1;
  sala.SalaMadre := salax;

  {$IFDEF VERBOSO}
  writeln('creando robot: ', sala.globs.idHIlo);
  {$ENDIF}

  copiarVarsTiempoEjecucion( salax );
  sala.estabilizarFrameInicial := False;
  nTareasCalculadasEstePaso := 0;

  if salax.globs.CF <> nil then
    sala.globs.CF := salax.globs.CF.CreateParasito
  else
    sala.globs.CF := nil;
  sala.globs.flg_CF_parasito := True; // para que no lo borre en el free
  {$IFDEF VERBOSO}
  writeln('fin creación parásito: ', sala.globs.idHIlo);
  {$ENDIF}

  if salax.CFAux <> nil then
    sala.CFAux := salax.CFAux.CreateParasito;

end;

destructor TRobotSimRangoCronicas.destroy;
begin
  {$IFDEF VERBOSO}
  writeln('Free worker ... ' + IntToStr(self.nid));
  {$ENDIF}
  sala.Free;
  inherited destroy;
end;



procedure TRobotSimRangoCronicas.copiarVarsTiempoEjecucion(
  salaMadre_: TSalaDeJuego);
begin
  sala.globs.NMAX_ITERACIONESDELPASO_OPT :=
    salaMadre_.globs.NMAX_ITERACIONESDELPASO_OPT;
  sala.globs.NMAX_ITERACIONESDELPASO_SIM :=
    salaMadre_.globs.NMAX_ITERACIONESDELPASO_SIM;

  sala.globs.SortearOpt := SalaMadre_.globs.SortearOpt;
  sala.globs.TasaDeActualizacion := SalaMadre_.globs.TasaDeActualizacion;
  sala.globs.NCronicasOpt := SalaMadre_.globs.NCronicasOpt;
  sala.globs.NCronicasSim_global_ := SalaMadre_.globs.NCronicasSim_global_;
  sala.globs.NEstadosIniciales_global := SalaMadre_.globs.NEstadosIniciales_global;
  sala.globs.semilla_inicial_opt := SalaMadre_.globs.semilla_inicial_opt;
  sala.globs.semilla_inicial_sim := SalaMadre_.globs.semilla_inicial_sim;

  sala.globs.ObligarDisponibilidad_1_Sim := salaMadre_.globs.ObligarDisponibilidad_1_Sim;
  sala.globs.ObligarInicioCronicaIncierto_1_Sim :=
    salaMadre_.globs.ObligarInicioCronicaIncierto_1_Sim;
  sala.globs.ObligarDisponibilidad_1_Opt := salaMadre_.globs.ObligarDisponibilidad_1_Opt;

  sala.globs.semillasIniSim:= SalaMadre_.globs.semillasIniSim;
  sala.globs.nubeDePuntos_XEstado := SalaMadre_.globs.nubeDePuntos_XEstado;
  sala.globs.Trayectorias:= SalaMadre_.globs.Trayectorias;
  sala.globs.flg_HidroConEmbalse_cvaPositivo:= SalaMadre_.globs.flg_HidroConEmbalse_cvaPositivo;
  sala.globs.CF_Enganche := SalaMadre_.globs.CF_Enganche;

  {$IFDEF SIM_MULTIHILO_NOTIFICANDO_GUI}
  if assigned( salaMadre_.globs.procNot_FinCronica ) then
     sala.globs.procNot_FinCronica:= procSimFinCronica;
  {$ENDIF}
end;




procedure TRobotSimRangoCronicas.Execute;
var
  pTarea: TTareaSimRangoCronicas;
begin
  nTareasCalculadasEstePaso := 0;
  pTarea := sincrodata_mh.wrk_AsignarTarea(self, nil) as TTareaSimRangoCronicas;
  aTarea := pTarea;
  if pTarea = nil then
  begin
    //   sala.globs.EstadoDeLaSala:= CES_SIMULACION_TERMINADA;
    Terminate;
  end;

  while (sincrodata_mh.Paso > 0) and (not Terminated) do
  begin
    {$IFDEF VERBOSO}
    writeln('Robot: ' + IntToStr(nid) + ' kPaso: ' + IntToStr(
      sincrodata_mh.Paso) + ', kTrayectoriaIni: ' + IntToStr(
      pTarea.kTrayectoriaIni) + ', kTrayectoriaFin: ' + IntToStr(pTarea.kTrayectoriaFin));
    {$ENDIF}

    sala.Simular(nid, True, pTarea.kTrayectoriaIni, pTarea.kTrayectoriaFin);

    Inc(nTareasCalculadasEstePaso);
    pTarea := sincrodata_mh.wrk_AsignarTarea(self, aTarea) as TTareaSimRangoCronicas;
    aTarea := pTarea;
    if aTarea = nil then
    begin
      Terminate;
    end;
  end; //while de los pasos


  // aquí podría ir
  sincrodata_mh.wrk_Finalizado(Self);
end;

function TRobotSimRangoCronicas.GetEstadoSala: TEstadoDeLaSala;
begin
  result:= sala.globs.EstadoDeLaSala;
end;

initialization
{$IFDEF SIM_MULTIHILO_NOTIFICANDO_GUI}
mh_SimFinCronica:= nil;
CS_SimFinCronica:= TCriticalSection.Create;
{$ENDIF}
finalization
  {$IFDEF SIM_MULTIHILO_NOTIFICANDO_GUI}
  CS_SimFinCronica.Free;
  {$ENDIF}
end.
