(****************************************************
Unidad principal del optimizador-simulador  de SimSEE
****************************************************)
unit uSimSEE;

interface

uses
  LResources,
{$IFDEF WINDOWS}
  Windows,
{$ELSE}
  LMessages,
  LCLType,
{$ENDIF}
  SysUtils, Forms,
  Messages, Classes, Graphics, Controls,
  Dialogs, StdCtrls, Buttons, ExtCtrls, Menus, ComCtrls,
  uglobs,
  uSalasDeJuego,
  uSustituirVariablesPlantilla,
  uCosa, xMatDefs,
  uEstados,
{$IFDEF MONITORES}
  uManejadoresDeMonitores,
  uReferenciaMonitor,
  uEventosOptSim,
{$ENDIF}
{$IFDEF INTERMEDIARIO_DE_COSTO_FUTURO}
  uintermediariocostofuturo,
{$ENDIF}
  uCosaConNombre, uconstantesSimSEE,
  uverdoc, uversiones,
  uInterpreteDeParametros,
  uauxiliares,
  umh_sincrodata,
  // Types,
  uadminestadossobremuestreado;

type

  { TfSimSEE }

  TfSimSEE = class(TForm)
    btAyudaCF_aux: TButton;
    btAyudaTiempo: TButton;
    btCargarCF: TButton;
    btCargarCFBase: TButton;
    btLlenarConUltimoFrame: TButton;
    btOptimizar: TButton;
    btPausarContinuar: TButton;
    btDetenerSim: TButton;
    btImprimirPotenciasFirmes: TButton;
    btImprimirUnidadesDisp: TButton;
    btSeleccionarCFAux: TButton;
    btSimular: TButton;
    Button1: TButton;
    cbEstabilizarInicio: TCheckBox;
    cbFrenarFinAnio: TCheckBox;
    cbFrenarFinCronica: TCheckBox;
    cbFrenarFinPaso: TCheckBox;
    cbObligarDisponibilidad_1_Opt: TCheckBox;
    cbObligarDisponibilidad_1_Sim: TCheckBox;
    cbObligarInicioCronicaIncierto_1_sim: TCheckBox;
    cbOptMuliHilo: TCheckBox;
    cbPlantillasSimRes3: TComboBox;
    cbPublicarSoloVariablesUsadasEnSimRes3: TCheckBox;
    cbResincronizarSemilla_SimInicioCronica: TCheckBox;
    cbSimMuliHilo: TCheckBox;
    cbSortearOpt: TCheckBox;
    cb_cvaPositivoSIM: TCheckBox;
    cb_cvaPositivoOPT: TCheckBox;
    eArchiCFAux: TEdit;
    eMaxNITERSOpt: TEdit;
    eMaxNItersSim: TEdit;
    eNCronicasOpt: TEdit;
    eNCronSim: TEdit;
    eNHilosForzadosOPT: TEdit;
    eNHilosForzadosSIM: TEdit;
    eSemillaAleatoriaOpt: TEdit;
    eSemillaAleatoriaSim: TEdit;
    eTasaDeActualizacion: TEdit;
    eTiempoPausa: TEdit;
    eTiempoRestanteSIM: TEdit;
    eTiempoTotalSIM: TEdit;
    ETOpt: TEdit;
    ETRestanteEstOpt: TEdit;
    GBArchivos: TGroupBox;
    gbControlSimulacion: TGroupBox;
    gbModoEjecucionOPT: TGroupBox;
    gbModoEjecucionSIM: TGroupBox;
    gbParametrosOPT: TGroupBox;
    gbParametrosSIM: TGroupBox;
    gbProgresoOPT: TGroupBox;
    gbProgresoSIM: TGroupBox;
    gb_ResultadosGlobales: TGroupBox;
    lbDetenerAlFinalDe: TLabel;
    lblNCronicasOpt: TLabel;
    lbl_ArchiSala: TLabel;
    lbl_ArchiMonitores: TLabel;
    eArchiSala: TEdit;
    eArchiMonitores: TEdit;
    btSala: TButton;
    btMonitores: TButton;
    GBAlertas: TGroupBox;
    lbl_TiempoRestante: TLabel;
    lbMaxNItersSIM: TLabel;
    lbNCronicasSIM: TLabel;
    lbProgresoSIM: TLabel;
    lbSemillaSIM: TLabel;
    lbTiempoPausa: TLabel;
    lbTiempoRestanteSIM: TLabel;
    lbTiempoTotalSIM: TLabel;
    lMaxNItersOpt: TLabel;
    lSemillaAleatoriaOpt: TLabel;
    lTasaDeActualizacionOpt: TLabel;
    LTOpt: TLabel;
    memoAlertas: TMemo;
    memoResultados: TMemo;
    openDialogCF: TOpenDialog;
    bt_Ayuda: TButton;
    OpenDialog1: TOpenDialog;
    Panel1: TPanel;
    panel_accionesSIM: TPanel;
    panel_accionesOPT: TPanel;
    pcPaneles: TPageControl;
    PBOpt: TProgressBar;
    pbProgresoSIM: TProgressBar;
    rbExcel: TRadioButton;
    rbHtml: TRadioButton;
    tsAuxiliares: TTabSheet;
    tsOptimizacion: TTabSheet;
    tsSimulacion: TTabSheet;
    tsSimRes3: TTabSheet;

    procedure btPausarContinuarClick(Sender: TObject);
    procedure btCargarCFBaseClick(Sender: TObject);
    procedure btLlenarConUltimoFrameClick(Sender: TObject);
    procedure bt_SimMHClick(Sender: TObject);
    procedure CBEscribirOptActoresChange(Sender: TObject);
    procedure cbEstabilizarInicioChange(Sender: TObject);
    procedure cbSimMuliHiloChange(Sender: TObject);
    procedure eArchiMonitoresChange(Sender: TObject);
    procedure EditEnter(Sender: TObject);
    procedure btDetenerSimClick(Sender: TObject);
    procedure eTiempoPausaExit(Sender: TObject);
    procedure btAyudaTiempoClick(Sender: TObject);
    procedure FormCloseQuery(Sender: TObject; var CanClose: boolean);
    procedure eTiempoPausaChange(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure btSalaClick(Sender: TObject);
    procedure btMonitoresClick(Sender: TObject);
    procedure cbSortearOptClick(Sender: TObject);
    procedure btCargarCFClick(Sender: TObject);
    procedure eArchiMonitoresExit(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure btAyudaCF_auxClick(Sender: TObject);
    procedure btSeleccionarCFAuxClick(Sender: TObject);
    procedure btOptimizarClick(Sender: TObject);
    procedure btSimularClick(Sender: TObject);
    procedure btImprimirPotenciasFirmesClick(Sender: TObject);
    procedure btImprimirUnidadesDispClick(Sender: TObject);
    procedure bt_AyudaClick(Sender: TObject);

  private
    sala: TSalaDeJuego;

{$IFDEF MONITORES}
    manejadorMonitores: TManejadoresDeMonitores;
    cambioArchiMonitores: boolean;
{$ENDIF}
    loQueHabia: string;
    cambioArchiSala: boolean;
    pausa, simulacionEnCurso: boolean;
    cntTrayectorias: integer;
    tiempoPausa: integer;
    tiempoIniSim, tiempoTotalDeSimulacion, tiempoIniCronica, tStop: NReal;
    tiempoIniOpt, tiempoTotalDeOptimizacion: NReal;

    function chequearParamsLineaDeComandos: boolean;


    // Funciones auxiliares para Activar/Desactivar los controles.
    procedure ActivarPaneles_Opt_y_Aux;
    procedure activarPanel_Sim;
    procedure activarPanel_SimRes3;
    procedure desactivarTodosLosPaneles;
    procedure desactivarAcciones;
    procedure activarAcciones;

    function validarEditInt(Sender: TEdit; min: integer; max: integer): boolean;

    procedure pausarSim;
    procedure reanudarSim;
  public
    procedure resetCtrl;
{$IFDEF MONITORES}
    //Atiende los mensajes de cerrar una ventana TrazosXY
    procedure WM_CLOSETRAZOSXY(var Message: TMessage); message WM_CLOSETRAZOSXY;
    procedure CargarMonitores(archiMonitores: string);
{$ENDIF}

    // Conecta los procedimientos de NOTIFICACION de la sala con
    // las funciones locales definidas en esta unidad para el propósito
    // de dar seguimiento al avance de la Optimización y de la Simulación.
    procedure EnlazarProcedimientos_OptSim(sala: TSalaDeJuego);

    // carga la sala leyendo el nombre de archivo del formulario
    // además maneja la habilitación de botones y etiquetas.
    procedure CargarSala_(nombre_escenario_activo: string);

    // carga la sala con el nombre pasado por parámetro
    procedure CargarSala(archiSala, nombre_escenario_activo: string);

    procedure call_runOptimizar( multihilo: boolean; llenarConFrameFinal: boolean);
    procedure call_runSimular( multihilo: boolean);

  end;


// Procedimientos para monitoreo de la optimización.
procedure Opt_Inicio;
procedure Opt_InicioCalculosDeEtapa;
procedure Opt_InicioCronicaSorteos;
procedure Opt_PrepararPaso_ps;
procedure Opt_FinCronicaSorteos;
procedure Opt_FinCalculosDeEtapa;
procedure Opt_Fin;

// Procedimientos para monitoreo de la simulación.
procedure Sim_Inicio;
procedure Sim_InicioCronica;
procedure Sim_IniPaso;
procedure Sim_FinPaso;
procedure Sim_FinCronica;
procedure Sim_Fin;

procedure Sim_FinCronica_cnt;
procedure Sim_FinCronica_GUI;

var
  fSimSEE: TfSimSEE;

implementation

{$R *.lfm}

procedure TfSimSEE.resetCtrl;
begin
  cbFrenarFinCronica.Checked := False;
  cbFrenarFinPaso.Checked := False;
  cbFrenarFinAnio.Checked := False;
  reanudarSim;
end;

{$IFDEF MONITORES}
procedure TfSimSEE.WM_CLOSETRAZOSXY(var Message: TMessage);
var
  ref: TReferenciaMonitor;
begin
  ref := TReferenciaMonitor(manejadorMonitores.referenciasMonitores[Message.wParam - 1]);
  manejadorMonitores.quitarMonitor(ref);
end;

{$ENDIF}

function TfSimSEE.chequearParamsLineaDeComandos: boolean;
var
  param: string;
  k, n: integer;
begin
  n := paramCount;
  writeln('ParamCount: ', n);
  for k := 1 to n do
    writeln('ParamStr(' + IntToStr(k) + '): ' + ParamStr(k) + ';');

  if ParamCount >= 1 then
  begin
    param := ParamStr(1);
    if not FileExists(param) then
      raise Exception.Create('El archivo: [' + param + '] no existe.(par1)');

    if (ExtractFileExt(param) = '.ese') then
    begin
      if ParamCount >= 2 then
      begin
        param := ParamStr(2);
        if not FileExists(param) then
          raise Exception.Create('El archivo: [' + param + '] no existe.(par2)');

        if (ExtractFileExt(param) = '.mon') then
        begin
          Result := True;
        end
        else
        begin
          raise Exception.Create(
            'El Archivo De Monitores Indicado No Es Valido (par2): [' + param + ']');
          Result := False;
        end;
      end
      else
        Result := True;
    end
    else
    begin
      raise Exception.Create('El Archivo De Sala Indicado No Es Valido (par1): [' +
        param + ']');
      Result := False;
    end;
  end
  else
  begin
    raise Exception.Create('No Se Indico Ningun Archivo');
    Result := False;
  end;
end;


procedure TfSimSEE.eArchiMonitoresExit(Sender: TObject);
begin
  {$IFDEF MONITORES}
  if (eArchiMonitores.Text = '') and (manejadorMonitores <> nil) then
  begin
    manejadorMonitores.Free;
    manejadorMonitores := TManejadoresDeMonitores.Create(0, self.sala);
  end;
  {$ENDIF}
end;


function TfSimSEE.validarEditInt(Sender: TEdit; min: integer; max: integer): boolean;
var
  valor: integer;
begin
  try
    begin
      if Sender.Text = '' then
      begin
        Sender.Text := '0';
        Result := True;
      end
      else
      begin
        valor := StrToInt(Sender.Text);
        if (valor < min) or (valor > max) then
          raise EConvertError.Create('Fuera de Rango');
        Result := True;
      end;
    end
  except
    on EConvertError do
    begin
      ShowMessage('El valor ingresado debe ser numérico y estar entre ' +
        IntToStr(min) + ' y ' + IntToStr(max));
      Sender.Text := loQueHabia;
      Sender.SetFocus;
      Result := False;
    end
  end;
end;

procedure TfSimSEE.pausarSim;
begin
  pausa := True;
  tiempoPausa := StrToInt(eTiempoPausa.Text);
  btPausarContinuar.Caption := 'Continuar';
  tStop := Now();
end;

procedure TfSimSEE.reanudarSim;
var
  tiempoDetenido: NReal;
begin
  pausa := False;
  btPausarContinuar.Caption := 'Pausar';
  tiempoDetenido := Now() - tStop;
  tiempoIniCronica := tiempoIniCronica + tiempoDetenido;
  tiempoIniSim := tiempoIniSim + tiempoDetenido;
end;

procedure Alerta(const s: string);
begin
  fSimSEE.memoAlertas.Lines.Append(s);
end;

procedure TfSimSEE.EnlazarProcedimientos_OptSim(sala: TSalaDeJuego);
begin
  sala.globs.procNot_opt_InicioOptimizacion := Opt_Inicio;
  sala.globs.procNot_opt_InicioCalculosDeEtapa := Opt_InicioCalculosDeEtapa;
  sala.globs.procNot_opt_InicioCronicaSorteos := Opt_InicioCronicaSorteos;
  sala.globs.procNot_opt_PrepararPaso_ps := Opt_PrepararPaso_ps;
  sala.globs.procNot_opt_FinCronicaSorteos := Opt_FinCronicaSorteos;
  sala.globs.procNot_opt_FinCalculosDeEtapa := Opt_FinCalculosDeEtapa;
  sala.globs.procNot_opt_FinOptimizacion := Opt_Fin;

  sala.globs.procNot_InicioSimulacion := Sim_Inicio;
  sala.globs.procNot_InicioCronica := Sim_InicioCronica;
  sala.globs.procNot_InicioPaso := Sim_IniPaso;
  sala.globs.procNot_FinPaso := Sim_FinPaso;
  sala.globs.procNot_FinCronica := Sim_FinCronica;
  sala.globs.procNot_FinSimulacion := Sim_Fin;

  sala.globs.setProcAlerta(Alerta);
end;

procedure TfSimSEE.CargarSala(archiSala, nombre_escenario_activo: string);
begin
  eTiempoRestanteSIM.Text := '';
  ETRestanteEstOpt.Text := '';
  ETOpt.Text := '';
  eTiempoTotalSIM.Text := '';

  btImprimirPotenciasFirmes.Enabled := False;
  btImprimirUnidadesDisp.Enabled := False;

  if Sala <> nil then
  begin
    Sala.Free;
    sala := nil;
  end;

  try
    sala := uSalasDeJuego.cargarSala(0, archiSala, nombre_escenario_activo, True);
    btImprimirPotenciasFirmes.Enabled := True;
    btImprimirUnidadesDisp.Enabled := True;
  except
    on E: Exception do
    begin
      ShowMessage('CargarSala, Error:' + #13 + E.Message);
      raise;
    end;
  end;

  if ((fileExists(sala.archiCF_bin)) or (fileExists(sala.archiCF_xlt))) then
    btCargarCF.Enabled := True
  else
    btCargarCF.Enabled := False;
end;


{$IFDEF MONITORES}
procedure TfSimSEE.CargarMonitores(archiMonitores: string);
begin
  if manejadorMonitores <> nil then
  begin
    manejadorMonitores.Free;
    manejadorMonitores := nil;
  end;

  try
    manejadorMonitores := TManejadoresDeMonitores.CargarManejadorDeMonitores(
      archiMonitores, True, self.sala);
  except
    on E: Exception do
    begin
      ShowMessage('Se Encontro El Siguiente Error:' + #13 + E.Message);
      //  PostQuitMessage(0);
    end;
  end;
end;

{$ENDIF}

procedure Sim_Inicio;
begin
  fSimSEE.pbProgresoSIM.Min := 0;
  fSimSEE.pbProgresoSIM.Max := fSimSEE.Sala.globs.NCronicasSim_global_;
  fSimSEE.pbProgresoSIM.Position := 0;
  fSimSEE.pbProgresoSIM.Step := 1;
  fSimSEE.eTiempoTotalSIM.Text := '0';
  fSimSEE.simulacionEnCurso := True;
  fSimSEE.tiempoIniSim := now();
  fSimSEE.cntTrayectorias := 0;
{$IFDEF MONITORES}
  try
    fSimSEE.manejadorMonitores.resolverReferenciasMonitores(
      TResolverMonitoresSimulacion);
  except
    on E: EMonitorException do
      ShowMessage('Se Encontraron Los Siguientes Errores:' + #13 +
        e.Message + #13 +
        'La Simulación Continuara Sin Monitorear Los Actores/Variables Sin Resolver.');
  end;
  fSimSEE.manejadorMonitores.notificarEvento(E_Sim_Inicio);
{$ENDIF}

end;

procedure Sim_InicioCronica;
begin
  fSimSEE.tiempoIniCronica := now();
{$IFDEF MONITORES}
  fSimSEE.manejadorMonitores.notificarEvento(E_Sim_InicioCronica);
{$ENDIF}
end;

procedure Sim_IniPaso;
begin

{$IFDEF MONITORES}
  uManejadoresDeMonitores.notifyIniPaso;
{$ENDIF}
end;


procedure Sim_FinPaso;
var
  i, tpausa: integer;
begin
  if fSimSEE.CBFrenarFinPaso.Checked or fSimSEE.pausa then
  begin
    if not fSimSEE.pausa then
      fSimSEE.pausarSim;
    while (fSimSEE.pausa) and (not fSimSEE.Sala.globs.abortarSim) do
    begin
      application.ProcessMessages;
      tpausa := fSimSEE.tiempoPausa;
      if tpausa <> 0 then
      begin
        if tpausa > 100 then
        begin
          for i := 0 to tpausa div 100 do
          begin
            Sleep(100);
            Application.ProcessMessages;
          end;
        end
        else
          Sleep(tpausa);
        fSimSEE.btPausarContinuarClick(fSimSEE.btPausarContinuar);
      end
      else
        sleep(200);
    end;
  end;
{$IFDEF MONITORES}
  fSimSEE.manejadorMonitores.notificarEvento(E_Sim_FinPaso);
{$ENDIF}
  application.ProcessMessages;
end;



procedure Sim_FinCronica;
begin
  Sim_FinCronica_cnt;
  Sim_FinCronica_GUI;

end;

procedure Sim_Fin;
begin

{$IFDEF MONITORES}
  fSimSEE.manejadorMonitores.notificarEvento(E_Sim_Fin);
{$ENDIF}
  fSimSEE.resetCtrl;
  fSimSEE.eTiempoRestanteSIM.Text := '0';
  fSimSEE.simulacionEnCurso := False;
end;

procedure Sim_FinCronica_cnt;
begin
  Inc(fSimSEE.cntTrayectorias);
end;

procedure Sim_FinCronica_GUI;
var
  i, tpausa: integer;
  segsPorCronica: double;

begin
  if fSimSEE.cntTrayectorias < 1 then
    exit; // no va ni una crónica.
  fSimSEE.tiempoTotalDeSimulacion := (now() - fSimSEE.tiempoIniSim) * 24 * 3600;
  segsPorCronica := fSimSEE.tiempoTotalDeSimulacion / fSimSEE.cntTrayectorias;

  fSimSEE.eTiempoRestanteSIM.Text :=
    FloatToStrF(segsPorCronica * (fSimSEE.sala.globs.NTrayectorias_global -
    fSimSEE.cntTrayectorias), ffFixed, 8, 3);
  fSimSEE.eTiempoTotalSIM.Text :=
    FloatToStrF(fSimSEE.tiempoTotalDeSimulacion, ffFixed, 8, 3);

  if fSimSEE.CBFrenarFinCronica.Checked or fSimSEE.pausa then
  begin
    if not fSimSEE.pausa then
      fSimSEE.pausarSim;
    while (fSimSEE.pausa) and (not fSimSEE.Sala.globs.abortarSim) do
    begin
      application.ProcessMessages;
      tpausa := fSimSEE.tiempoPausa;
      if tpausa <> 0 then
      begin
        if tpausa > 100 then
        begin
          for i := 0 to tpausa div 100 do
          begin
            Sleep(100);
            Application.ProcessMessages;
          end;
        end
        else
          Sleep(tpausa);
        fSimSEE.btPausarContinuarClick(fSimSEE.btPausarContinuar);
      end
      else
        sleep(200);
    end;
  end;
  fSimSEE.tiempoIniCronica := now();

//  fSimSEE.pbProgresoSIM.stepit;
  fSimSEE.pbProgresoSIM.Position := fSimSEE.cntTrayectorias;

{$IFDEF MONITORES}
  fSimSEE.manejadorMonitores.notificarEvento(E_Sim_FinCronica);
{$ENDIF}
  Application.ProcessMessages;

end;

procedure Opt_Inicio;
begin

  fSimSEE.PBOpt.Min := 1;
  fSimSEE.PBOpt.Max := fSimSEE.Sala.globs.calcNPasosOpt + 1;
  fSimSEE.PBOpt.Position := 1;
  fSimSEE.PBOpt.Step := 1;

  fSimSEE.pbProgresoSIM.Position := 0;
  fSimSEE.simulacionEnCurso := True;
{$IFDEF MONITORES}
  try
    fSimSEE.manejadorMonitores.resolverReferenciasMonitores(
      TResolverMonitoresOptimizacion);
  except
    on E: EMonitorException do
      ShowMessage('Se Encontraron Los Siguientes Errores:' + #13 +
        e.Message + #13 +
        'La Simulación Continuara Sin Monitorear Los Actores/Variables Sin Resolver.');
  end;
  fSimSEE.manejadorMonitores.notificarEvento(E_Opt_Inicio);
{$ENDIF}

end;

procedure Opt_InicioCalculosDeEtapa;
begin

{$IFDEF MONITORES}
  fSimSEE.manejadorMonitores.notificarEvento(E_Opt_InicioCalculosEtapa);
{$ENDIF}

end;

procedure Opt_InicioCronicaSorteos;
begin

{$IFDEF MONITORES}
  fSimSEE.manejadorMonitores.notificarEvento(E_Opt_InicioCronicaSorteos);
{$ENDIF}

end;

procedure Opt_PrepararPaso_ps;
begin

  {$IFDEF MONITORES}
  fSimSEE.manejadorMonitores.notificarEvento(E_Opt_PrepararPaso_ps);
  {$ENDIF}

end;

procedure Opt_FinCronicaSorteos;
begin

{$IFDEF MONITORES}
  fSimSEE.manejadorMonitores.notificarEvento(E_Opt_FinCronicaSorteos);
{$ENDIF}
end;

procedure mh_Actualizar;
begin
  Sim_FinCronica_GUI;
end;


procedure Opt_FinCalculosDeEtapa;
var
  segsPorEtapa: NReal;
begin

  {$IFDEF MONITORES}
  fSimSEE.manejadorMonitores.notificarEvento(E_Opt_FinCalculosEtapa);
{$ENDIF}
  fSimSEE.PBOpt.stepit;
  fSimSEE.tiempoTotalDeOptimizacion := (now() - fSimSEE.tiempoIniOpt) * 24 * 3600;
  fSimSEE.ETOpt.Text := FloatToStrF(fSimSEE.tiempoTotalDeOptimizacion, ffFixed, 8, 2);
  segsPorEtapa := fSimSEE.tiempoTotalDeOptimizacion /
    (fSimSEE.sala.globs.NPasos - fSimSEE.sala.globs.kPaso_Opt + 1);
  fSimSEE.ETRestanteEstOpt.Text :=
    FloatToStrF(segsPorEtapa * fSimSEE.sala.globs.kPaso_Opt, ffFixed, 8, 2);
  Application.ProcessMessages;
end;

procedure Opt_Fin;
begin
  {$IFDEF MONITORES}
  fSimSEE.manejadorMonitores.notificarEvento(E_Opt_Fin);
  {$ENDIF}
  fSimSEE.simulacionEnCurso := False;
end;

procedure TfSimSEE.btPausarContinuarClick(Sender: TObject);
begin
  if pausa then
    reanudarSim
  else
    pausarSim;
end;

procedure TfSimSEE.btCargarCFBaseClick(Sender: TObject);
begin

  if sala.globs.CF <> nil then
    sala.globs.CF.Free;

(***
rch@201411091951

Esto es para que Vates funcione colgado de un CF de una sala
que se usó para valorizar los recursos.

También puede servir para testear en el caso del proyecto de la
regasificadora el Optimizar con paso Mensual o Quincenal y luego
simular con paso Semanal.

ojo , ahora para probar copiar a mano el CF de la corrida BASE
en la carpeta de la Sala que se cuelga de la base y llamar al CF
CFBase_.bin para que funcione el cargar.

Después vamos a poner en la Sala un indicador de que está COLGADA y que
por tanto no corresponde OPTIMIZAR y tendrá un LINK a la sala BASE y se
colgará de su CF.bin
 ****)

  OpenDialog1.Filter := '';
  OpenDialog1.Filter := 'Archivo CF | *.bin; *.xlt';
  if OpenDialog1.Execute then
  begin
    desactivarAcciones;
    Sala.globs.CF := TAdminEstados_SobreMuestreado.CreateLoadFromArchi_(
      OPenDialog1.filename, sala.globs.fechaIniSim.dt, sala.globs.fechaFinSim.dt,
      sala.globs.HorasDelPaso);
    activarPanel_Sim;
    activarAcciones;
  end;

end;




procedure TfSimSEE.btLlenarConUltimoFrameClick(Sender: TObject);
begin
  call_runOptimizar(False, True);
end;

procedure TfSimSEE.bt_SimMHClick(Sender: TObject);
begin
  call_runSimular(True);
end;

procedure TfSimSEE.CBEscribirOptActoresChange(Sender: TObject);
begin
  //if Self.CBEscribirOptActores.Checked then
  //  self.BOptimizarMultiHilo.Enabled := False
  //else
  //  self.BOptimizarMultiHilo.Enabled := True;
end;

procedure TfSimSEE.cbEstabilizarInicioChange(Sender: TObject);
begin

end;

procedure TfSimSEE.cbSimMuliHiloChange(Sender: TObject);
begin
  gbControlSimulacion.Enabled := not cbSimMuliHilo.Checked;
end;

procedure TfSimSEE.eArchiMonitoresChange(Sender: TObject);
begin

end;

procedure TfSimSEE.EditEnter(Sender: TObject);
begin
  loQueHabia := TEdit(Sender).Text;
end;

procedure TfSimSEE.btDetenerSimClick(Sender: TObject);
begin
  reanudarSim;
  Sala.globs.abortarSim := True;
  //  ETRestanteEst.Text := '0';
end;

procedure TfSimSEE.btOptimizarClick(Sender: TObject);
begin
  if cbOptMuliHilo.Checked then
    call_runOptimizar( True , False)
  else
    call_runOptimizar( False , False);
end;


procedure TfSimSEE.call_runOptimizar(multihilo: boolean; llenarConFrameFinal: boolean);
begin
  desactivarAcciones;
  {$IFDEF MONITORES}
  if manejadorMonitores = nil then
    manejadorMonitores := TManejadoresDeMonitores.Create(0, sala);
  btMonitores.Enabled := False;
{$ENDIF}

  sala.globs.SortearOpt := cbSortearOpt.Checked;
  sala.estabilizarFrameInicial := cbEstabilizarInicio.Checked;
  sala.globs.TasaDeActualizacion := StrToFloat(eTasaDeActualizacion.Text);
  sala.globs.NCronicasOpt := StrToInt(eNCronicasOpt.Text);
  sala.globs.NMAX_ITERACIONESDELPASO_OPT := StrToInt(self.eMaxNITERSOpt.Text);

  sala.globs.ObligarDisponibilidad_1_Sim := cbObligarDisponibilidad_1_Sim.Checked;
  sala.globs.ObligarInicioCronicaIncierto_1_Sim :=
    cbObligarInicioCronicaIncierto_1_sim.Checked;
  sala.globs.ObligarDisponibilidad_1_Opt := cbObligarDisponibilidad_1_Opt.Checked;
  sala.globs.ObligarDisponibilidad_1_ := sala.globs.ObligarDisponibilidad_1_Opt;

  sala.globs.publicarSoloVariablesUsadasEnSimRes3 :=
    cbPublicarSoloVariablesUsadasEnSimRes3.Checked;

  sala.globs.flg_HidroConEmbalse_cvaPositivo := cb_cvaPositivoOPT.Checked;


  EnlazarProcedimientos_OptSim(sala);
  sala.globs.semilla_inicial_opt := StrToInt(eSemillaAleatoriaOpt.Text);

  tiempoIniOpt := now();

  if multihilo then
    runOptimizar(sala, StrToInt(eNHilosForzadosOPT.Text), -1, llenarConFrameFinal)
  else
    runOptimizar(sala, 0, -1, llenarConFrameFinal);


  if sala.globs.EstadoDeLaSala <> CES_OPTIMIZACION_ABORTADA then
  begin
    self.ETOpt.Text := FloatToStrF((now() - tiempoIniOpt) * 24 * 3600, ffFixed, 8, 3);

    if sala.globs.CF <> nil then
      sala.guardarResultadosOpt;

    activarPanel_Sim;
  end;
  btSala.Enabled := True;
{$IFDEF MONITORES}
  btMonitores.Enabled := True;
{$ENDIF}
  activarAcciones;
end;

procedure TfSimSEE.call_runSimular(multihilo: boolean);
begin
  desactivarAcciones;
  tsSimRes3.Visible := False;
{$IFDEF MONITORES}
  if self.eArchiMonitores.Text <> '' then
    CargarMonitores(self.eArchiMonitores.Text);
  if manejadorMonitores = nil then
    manejadorMonitores := TManejadoresDeMonitores.Create(0, sala);
{$ENDIF}
  //desactivarControlesSim;

  EnlazarProcedimientos_OptSim(sala);

  sala.globs.abortarSim := False;
  sala.globs.NCronicasSim_global_ := StrToInt(eNCronSim.Text);
  sala.globs.NEstadosIniciales_global := 1;
  sala.globs.NTrayectorias_global := sala.globs.NCronicasSim_global_;

  sala.globs.semilla_inicial_sim := StrToInt(eSemillaAleatoriaSim.Text);
  sala.globs.ObligarDisponibilidad_1_Sim := cbObligarDisponibilidad_1_Sim.Checked;
  sala.globs.ObligarInicioCronicaIncierto_1_Sim :=
    cbObligarInicioCronicaIncierto_1_sim.Checked;
  sala.globs.ObligarDisponibilidad_1_Opt := cbObligarDisponibilidad_1_Opt.Checked;
  sala.globs.ObligarDisponibilidad_1_ := sala.globs.ObligarDisponibilidad_1_Sim;
  sala.globs.NMAX_ITERACIONESDELPASO_SIM := StrToInt(self.eMaxNItersSim.Text);
  sala.RandSeed_SincronizarAlInicioDeCadaCronica :=
    self.cbResincronizarSemilla_SimInicioCronica.Checked;

  sala.globs.flg_HidroConEmbalse_cvaPositivo := cb_cvaPositivoSIM.Checked;

  if sala.archivoCFAux <> nil then
    sala.archivoCFAux.ArchiRef.set_archi( eArchiCFAux.Text );

  application.ProcessMessages;

  sala.Clear_ResultadosSim;

  if multihilo then
  begin
    {$IFDEF SIM_MULTIHILO_NOTIFICANDO_GUI}
    umh_sincrodata.procActualizarGUI := mh_Actualizar;
    Sala.globs.procNot_FinCronica := Sim_FinCronica_cnt;
    {$ENDIF}
    runSimular(sala, StrToInt(eNHilosForzadosSIM.Text));
  end
  else
    runSimular(sala, 0);


  memoResultados.Lines.Add('CF_VE[MUSD]: ' + FloatToStrF(sala.VE_CF, ffFixed, 12, 2));
  memoResultados.Lines.Add('CF_VaR(5%)[MUSD]: ' + FloatToStrF(
    sala.VaR05_CF, ffFixed, 12, 2));
  memoResultados.Lines.Add('CF_CVaR(5%)[MUSD]: ' + FloatToStrF(
    sala.CVaR05_CF, ffFixed, 12, 2));


  if sala.globs.EstadoDeLaSala = CES_SIMULACION_TERMINADA then
  begin
    //  cbPlantillasSimRes3.Items.AddStrings( sala.listaPlantillasSimRes3.lista_activas );
    cbPlantillasSimRes3.Items := sala.listaPlantillasSimRes3.lista_activas;
    if cbPlantillasSimRes3.Items.Count > 0 then
    begin
      cbPlantillasSimRes3.ItemIndex := 0;
    end;

    activarPanel_SimRes3;
  end
  else
    ShowMessage('Simlación ABORTADA');
  activarAcciones;
end;


procedure TfSimSEE.desactivarTodosLosPaneles;
begin
  tsOptimizacion.Enabled := False;
  tsSimulacion.Enabled := False;
  tsSimRes3.Enabled := False;
  tsAuxiliares.Enabled := False;
end;

procedure TfSimSEE.desactivarAcciones;
begin
  panel_accionesOPT.Enabled := False;
  panel_accionesSIM.Enabled := False;
end;

procedure TfSimSEE.activarAcciones;
begin
  panel_accionesOPT.Enabled := True;
  panel_accionesSIM.Enabled := True;
end;

procedure TfSimSEE.ActivarPaneles_Opt_y_Aux;
begin
  tsOptimizacion.Enabled := True;
  tsSimulacion.Enabled := False;
  tsSimRes3.Enabled := False;
  tsAuxiliares.Enabled := True;
  pcPaneles.TabIndex := 0;
end;


procedure TfSimSEE.activarPanel_Sim;
begin
  tsOptimizacion.Enabled := True;
  tsSimulacion.Enabled := True;
  tsSimRes3.Enabled := False;
  tsAuxiliares.Enabled := True;
  pcPaneles.TabIndex := 1;
end;

procedure TfSimSEE.activarPanel_SimRes3;
begin
  tsOptimizacion.Enabled := True;
  tsSimulacion.Enabled := True;
  tsSimRes3.Enabled := True;
  tsAuxiliares.Enabled := True;
  pcPaneles.TabIndex := 2;
end;


procedure TfSimSEE.eTiempoPausaExit(Sender: TObject);
begin
  validarEditInt(TEdit(Sender), 0, MAXINT);
end;

procedure TfSimSEE.btAyudaTiempoClick(Sender: TObject);
begin
  verdoc( 3826, 'simulador-mspausa');
end;

procedure TfSimSEE.FormCloseQuery(Sender: TObject; var CanClose: boolean);
var
  res: boolean;
begin

  CanClose := True;
  if sala <> nil then
  begin
    if sala.globs.EstadoDeLaSala in [CES_OPTIMIZANDO, CES_SIMULANDO] then
    begin
      pausarSim;
      case sala.globs.EstadoDeLaSala of
        CES_OPTIMIZANDO:
          res := (Application.MessageBox(
            'La Optimización No Ha Terminado. ¿Desea Salir De Todas Formas?',
            'Confirmar Salida', MB_YESNO or MB_ICONEXCLAMATION) = idYes);
        CES_SIMULANDO:
          res := (Application.MessageBox(
            'La Simulación No Ha Terminado. ¿Desea Salir De Todas Formas?',
            'Confirmar Salida', MB_YESNO or MB_ICONEXCLAMATION) = idYes);
        else
          res := False;
      end;
      if res then
      begin
        Sala.globs.abortarSim := True;
        CanClose := False;
        GBArchivos.Visible := False;
        tsOptimizacion.Enabled := True;
        tsSimulacion.Enabled := False;
        tsSimRes3.Enabled := False;
        tsAuxiliares.Enabled := True;
        pcPaneles.TabIndex := 0;
      end
      else
      begin
        CanClose := False;
        reanudarSim;
      end;
    end;
  end
  else
    CanClose := True;
  if CanClose then
  begin
    if Sala <> nil then
    begin
      Sala.Free;
      Sala := nil;
    end;
    {$IFDEF MONITORES}
    if manejadorMonitores <> nil then
    begin
      ManejadorMonitores.Free;
      ManejadorMonitores := nil;
    end;
    {$ENDIF}
  end;
end;

procedure TfSimSEE.btSimularClick(Sender: TObject);
begin
  call_runSimular(cbSimMuliHilo.Checked);
end;

procedure TfSimSEE.Button1Click(Sender: TObject);
var
  sustitutor: TSustituirVariablesPlantilla;
begin
  desactivarAcciones;
  sustitutor := TSustituirVariablesPlantilla.Create(0);
  try
    sustitutor.ejecutarSimRes3(
      cbPlantillasSimRes3.Text, sala,
      sala.EscenarioActivo.nombre,
      StrToInt(eSemillaAleatoriaSim.Text), rbHtml.Checked);
  except
    on e: Exception do
      ShowMessage(e.Message);
  end;
  sustitutor.Free;
  activarAcciones;
end;

procedure TfSimSEE.btSeleccionarCFAuxClick(Sender: TObject);
begin
  if openDialogCF.Execute then
    eArchiCFAux.Text := openDialogCF.FileName;
end;

procedure TfSimSEE.btAyudaCF_auxClick(Sender: TObject);
begin
  verdoc(3826, 'simulador-cfauxiliar', '');
end;

procedure TfSimSEE.bt_AyudaClick(Sender: TObject);
begin
  verdoc(3826, 'simulador-pantallaprincipal', '');
end;

procedure TfSimSEE.btImprimirPotenciasFirmesClick(Sender: TObject);
begin
  if sala <> nil then
    sala.ImprimirPotenciasFirmes
  else
    ShowMessage('Primero debe cargar una sala');
end;

procedure TfSimSEE.btImprimirUnidadesDispClick(Sender: TObject);
begin
  sala.ImprimirUnidadesInstaladas;
end;



procedure TfSimSEE.eTiempoPausaChange(Sender: TObject);
begin
  if TEdit(Sender).Text = '' then
    TEdit(Sender).Text := '0';
end;

procedure TfSimSEE.FormCreate(Sender: TObject);
var
  interpreteDeParametros: TInterpreteParametros;
  nombre_escenario: string;

begin

  ChDir(ExtractFilePath(ParamStr(0)));
  crearDirectorios;
  self.top := 20;
  self.left := 50;

  self.Caption := AnsiToUtf8('SimSEE (v' + uversiones.vSimSEESimulador_ + ')');


  memoAlertas.Lines.add(self.Caption);
  memoAlertas.Lines.add(CONDITIONAL_DEFINES);

  sala := nil;
{$IFDEF MONITORES}
  manejadorMonitores := nil;
{$ENDIF}
{$IFNDEF ESTABILIZAR_FRAMEINICIAL}
  cbEstabilizarInicio.Visible := False;
{$ENDIF}



  cambioArchiSala := True;
  tsOptimizacion.Enabled := False;
  tsSimulacion.Enabled := False;
  tsSimRes3.Enabled := False;
  tsAuxiliares.Enabled := False;
  pcPaneles.TabIndex := 0;
  pcPaneles.Enabled := False;

  interpreteDeParametros := TInterpreteParametros.Create(False);

  eArchiSala.Text := interpreteDeParametros.valStr('sala');
  if eArchiSala.Text = '' then
    OpenDialog1.InitialDir := getDir_Corridas;

  eArchiMonitores.Text := interpreteDeParametros.valStr('monitores');


  nombre_escenario := interpreteDeParametros.valStr('escenario');
  if nombre_escenario = '' then
    nombre_escenario := '__principal__';

  interpreteDeParametros.Free;

  if eArchiSala.Text <> '' then
    CargarSala_(nombre_escenario);

{$IFDEF MONITORES}
  eArchiMonitores.Enabled := True;
  self.btMonitores.Enabled := True;
  if eArchiMonitores.Text <> '' then
    CargarMonitores(eArchiMonitores.Text);
{$ELSE}
  btMonitores.Visible := False;
  eArchiMonitores.Visible := False;
  lbl_ArchiMonitores.Visible := False;
  gbControlSimulacion.Visible := False;
{$ENDIF}
end;

procedure TfSimSEE.CargarSala_(nombre_escenario_activo: string);
var
  carpetaSala: string;
begin
  cambioArchiSala := True;

  try
    carpetaSala := extractFilePath(eArchiSala.Text);
    chdir(carpetaSala);
    CargarSala(eArchiSala.Text, nombre_escenario_activo);
  except
    begin
      MessageDlg('Error cargando la Sala', mtError, [mbOK], 0);
      exit;
    end;
  end;

  memoAlertas.Clear;
  cbSortearOpt.Checked := sala.globs.SortearOpt;
  cbEstabilizarInicio.Checked := sala.estabilizarFrameInicial;
  eNCronicasOpt.Text := IntToStr(sala.globs.NCronicasOpt);
  eMaxNITERSOpt.Text := IntToStr(sala.globs.NMAX_ITERACIONESDELPASO_OPT);
  eNCronSim.Text := IntToStr(sala.globs.NCronicasSim_global_);
  eTasaDeActualizacion.Text :=
    FloatToStrF(sala.globs.TasaDeActualizacion, ffGeneral, 6, 3);
  cbObligarDisponibilidad_1_Sim.Checked := sala.globs.ObligarDisponibilidad_1_Sim;
  cbObligarInicioCronicaIncierto_1_sim.Checked :=
    sala.globs.ObligarInicioCronicaIncierto_1_Sim;
  cbObligarDisponibilidad_1_Opt.Checked := sala.globs.ObligarDisponibilidad_1_Opt;


  eSemillaAleatoriaOpt.Text := IntToStr(sala.globs.semilla_inicial_opt);

  cbPublicarSoloVariablesUsadasEnSimRes3.Checked :=
    sala.globs.publicarSoloVariablesUsadasEnSimRes3;

  eMaxNItersSim.Text := IntToStr(sala.globs.NMAX_ITERACIONESDELPASO_SIM);

  eSemillaAleatoriaSim.Text := IntToStr(sala.globs.semilla_inicial_sim);

  cb_cvaPositivoOPT.Checked := sala.globs.flg_HidroConEmbalse_cvaPositivo;
  cb_cvaPositivoSIM.Checked := sala.globs.flg_HidroConEmbalse_cvaPositivo;


  cbSortearOptClick(Self);

  tsOptimizacion.Enabled := True;
  tsSimulacion.Enabled := False;
  tsSimRes3.Enabled := False;
  tsAuxiliares.Enabled := True;
  pcPaneles.TabIndex := 0;
  pcPaneles.Enabled := True;


  if sala.archivoCFAux <> nil then
    eArchiCFAux.Text := sala.archivoCFAux.ArchiRef.get_archi
  else
    eArchiCFAux.Text := '';
end;


procedure TfSimSEE.btSalaClick(Sender: TObject);
begin
  OpenDialog1.FilterIndex := 1;
  if OpenDialog1.Execute then
  begin
    eArchiSala.Text := OpenDialog1.FileName;

    CargarSala_('__principal__');

    if sala.archivoCFAux <> nil then
      eArchiCFAux.Text := sala.archivoCFAux.ArchiRef.get_archi
    else
      eArchiCFAux.Text := '';


    pbProgresoSIM.Position := 0;
    PBOpt.Position := 0;
    self.Caption := 'SimSEE ' + eArchiSala.Text;
{$IFDEF MONITORES}
    if manejadorMonitores <> nil then
      manejadorMonitores.sala := sala;
{$ENDIF}
  end;
end;

procedure TfSimSEE.btMonitoresClick(Sender: TObject);
begin
{$IFDEF MONITORES}
  OpenDialog1.FilterIndex := 2;
  if OpenDialog1.Execute then
  begin
    eArchiMonitores.Text := OpenDialog1.FileName;
    cambioArchiMonitores := True;
    cargarMonitores(eArchiMonitores.Text);
  end;
{$ELSE}
  ShowMessage('Esta versión del simulador no ha sido compilada con monitores.' +
    'Para habilitarlos recompile los codigos fuente con el conditional' +
    'define MONITORES');
{$ENDIF}
end;

procedure TfSimSEE.cbSortearOptClick(Sender: TObject);
begin
  if cbSortearOpt.Checked then
  begin
    eNCronicasOpt.Enabled := True;
    lblNCronicasOpt.Enabled := True;
  end
  else
  begin
    eNCronicasOpt.Enabled := False;
    lblNCronicasOpt.Enabled := False;
  end;
end;


procedure TfSimSEE.btCargarCFClick(Sender: TObject);
var
  nombreArchi: string;

begin
  desactivarAcciones;

  if FileExists(sala.ArchiCF_bin) then
    nombreArchi := sala.ArchiCF_bin
  else if FileExists(sala.ArchiCF_xlt) then
    nombreArchi := sala.ArchiCF_xlt;

  if sala.CargarCFFrom_archi(True, nombreArchi) then
  begin
    activarPanel_Sim;
    {$IFDEF INTERMEDIARIO_DE_COSTO_FUTURO}
    //    sala.intermediario:=TIntermediarioCostoFuturo.Create( sala.globs.CF ); // creo que tendria que ir aca DV@20180523
    {$ENDIF}
  end;
  activarAcciones;
end;




initialization
{$I uSimSEE.lrs}
end.
