unit uPrintCronVars;

{$MODE Delphi}
{$IFDEF APLICACION_CONSOLA}
{xDEFINE SIMRES3SOLOTEXTO}
{$ENDIF}

interface

uses
{$IFNDEF SIMRES3SOLOTEXTO}
  {$IFNDEF  SVG_CANVAS}
{$IFDEF FP_CANVAS}
  ucoloresbasicos,
{$ELSE}
  Graphics,
{$ENDIF}
  Dialogs,
{$ENDIF}
  uExcelFile,
 {$ENDIF}
  uHistoVarsOps, uPrint, xMatDefs, uAuxiliares, SysUtils,
  uversiones,
  uConstantesSimSEE,
{$IFNDEF SIMRES3SOLOTEXTO}
  uAuxiliaresEscrituraSimRes,
 {$ENDIF}
 Classes;

{$IFDEF SIMRES3SOLOTEXTO}
type
  TExcelFile = record
    idstr: string;
  end; // solo para que compile
{$ENDIF}

type
  TClaseDePrintCronVar = class of TPrintCronVar;

  { TPrintCronVar }

  TPrintCronVar = class
  public
    nombreHoja: string;
    titulo: string;

    titulo_eje1: string;
    digitos_eje1, decimales_eje1: integer;
    minEjeYAuto_eje1, maxEjeYAuto_eje1: boolean;
    minEjeY_eje1, MaxEjeY_eje1: NReal;

    titulo_eje2: string;
    digitos_eje2, decimales_eje2: integer;
    minEjeYAuto_eje2, maxEjeYAuto_eje2: boolean;
    minEjeY_eje2, MaxEjeY_eje2: NReal;

    constructor Create;

    //Retorna false si los parametros no son correctos. En caso de error
    //se agrega una línea por error en errores con la descripcion del problema
    //encontrado
    //Se llama antes de llamar a imprimirse y luego de haber calculado las
    //cronOpers y postOpers
    procedure checkParams(errores: TStringList); virtual;

    // Retonra TRUE si necesita Excel
    function usa_excel: boolean; virtual;

    procedure imprimirse(xls: TExcelFile); virtual; abstract;
    class function tipo: string; virtual; abstract;

    function getNombresCronVars: string; virtual; abstract;
    function referenciaCronVar(cronVar: TCronVar): boolean; virtual; abstract;
    function parametrosAdicionales: string; virtual;
{$IFNDEF SIMRES3SOLOTEXTO}
    //Retorna la lista de colores que se hayan seleccionado especificamente para
    //su grafico
    function getColores: TDAOfTColor; virtual;
{$ENDIF}
    function serialize: string; virtual;

    function cronVarsAImprimir: TDAOfCronVar; virtual; abstract;
  end;

  TPrintCronVar_UniCronVar = class(TPrintCronVar)
  public
    cronVar: TCronVar;
    function getNombresCronVars: string; override;
    function referenciaCronVar(cronVar: TCronVar): boolean; override;
    function serialize: string; override;
    function cronVarsAImprimir: TDAOfCronVar; override;
  end;

  TPrintCronVar_MultiCronVar = class(TPrintCronVar)
  public
    cronVars: TDAOfCronVar;
    function getNombresCronVars: string; override;
    function referenciaCronVar(cronVar: TCronVar): boolean; override;
    procedure Free;
    //      function serialize: string; override;

    function cronVarsAImprimir: TDAOfCronVar; override;
  end;

{$IFNDEF SIMRES3SOLOTEXTO}
  TPrintCronVar_matrizDeDatos = class(TPrintCronVar_UniCronVar)
  private
    //Si no se definieron títulos para todas las columnas agrega las columnas
    //que faltan con título CrónicaN con N el número de columna
    function titulosColsExt: TDAofString;
  public
    Print_promedio: boolean;
    titulosCols: TDAofString;
    chart_Mat: boolean;

    minEjeYAuto_eje1, maxEjeYAuto_eje1: boolean;
    minEjeY_eje1, MaxEjeY_eje1: NReal;

    minEjeYAuto_eje2, maxEjeYAuto_eje2: boolean;
    minEjeY_eje2, MaxEjeY_eje2: NReal;

    constructor Create(cronVar: TCronVar; nombreHoja: string;
      titulo, unidades: string; titulosCols: TDAofString;
      digitos, decimales: integer; Print_promedio: boolean;
      chart_Mat: boolean; minEjeYAuto, maxEjeYAuto: boolean;
      minEjeY, MaxEjeY: NReal);

    procedure imprimirse(xls: TExcelFile); override;
    class function tipo: string; override;
    procedure Free;
    function parametrosAdicionales: string; override;
    function serialize: string; override;
  end;


  { TPrintCronVar_histograma }

  TPrintCronVar_histograma = class(TPrintCronVar_UniCronVar)
  public
    chart_Mat: boolean;
    Print_Todas: boolean;
    Print_promedio: boolean;
    Pre_Ordenar: boolean;
    Print_probAisladas: TDAofNReal;
    TipoImpresion_PE: boolean;

    constructor Create(cronVar: TCronVar; nombreHoja: string;
      titulo, titulo_eje1: string; digitos_eje1, decimales_eje1: integer;
      Print_Todas: boolean; Print_promedio: boolean; Pre_Ordenar: boolean;
      TipoImpresion_PE: boolean; Print_probAisladas: TDAofNReal;
      chart_Mat: boolean; minEjeYAuto_eje1, maxEjeYAuto_eje1: boolean;
      minEjeY_eje1, MaxEjeY_eje1: NReal);
    procedure imprimirse(xls: TExcelFile); override;
    class function tipo: string; override;
    procedure Free;
    function parametrosAdicionales: string; override;
    class function printProbAisladasPorDefecto: TDAofNReal;
    function serialize: string; override;
  end;

{$ENDIF}


  TPrintCronVar_histograma_text = class(TPrintCronVar_UniCronVar)
  public
    Print_Todas: boolean;
    Print_promedio: boolean;
    Pre_Ordenar: boolean;
    TipoImpresion_PE: boolean;
    Print_probAisladas: TDAofNReal;
    constructor Create(cronVar: TCronVar; archi: string;
      titulo, unidades: string; digitos, decimales: integer;
      Print_Todas: boolean; Print_promedio: boolean; Pre_Ordenar: boolean;
      TipoImpresion_PE: boolean; Print_probAisladas: TDAofNReal);


    function usa_excel: boolean; override;
    procedure imprimirse(xls: TExcelFile); override;
    class function tipo: string; override;
    procedure Free;
    function parametrosAdicionales: string; override;
    class function printProbAisladasPorDefecto: TDAofNReal;
    function serialize: string; override;
  end;

{$IFNDEF SIMRES3SOLOTEXTO}
  TPrintCronVar_HistogramaGlobal = class(TPrintCronVar_UniCronVar)
  public
    minX, maxX: NReal;
    nPuntosHistograma: integer;

    constructor Create(cronVar: TCronVar; nombreHoja: string;
      titulo, unidades: string; digitos, decimales: integer;
      minX, maxX: NReal; nPuntosHistograma: integer{;
                         chart_Mat: boolean;
                         minEjeYAuto, maxEjeYAuto: boolean;
                         minEjeY, MaxEjeY: NReal});
    procedure imprimirse(xls: TExcelFile); override;
    class function tipo: string; override;
    procedure Free;
    function serialize: string; override;
  end;

  { TPrintCronVar_compararValoresMultiplesCronVars }

  TPrintCronVar_compararValoresMultiplesCronVars = class(TPrintCronVar_MultiCronVar)
  public
    tipoValorAComparar: TTipoValoresAComparar;
    //Solo aplica si el tipoValorAComparar = ProbabilidadesDeExcedencia
    probExcedencia: NReal;
    ejex: TTipoVariableDelEje;
    cronVarEjex: TCronVar;

    titulo_ejeX: string;

    Pre_Ordenar: boolean;
    ProbExcedencia_Sup: NReal; // borde superior

    graficar: boolean;

    tiposGraficos: TDAOfTTipoGrafico;
    ejes: TDAOfTTipoEje;

    //clDefault hace que elija automático
    colores: TDAOfTColor;

    constructor Create(cronVars: TDAOfCronVar; nombreHoja: string;
      titulo: string; titulo_eje1: string; digitos_eje1, decimales_eje1: integer;
      tipoValorAComparar: TTipoValoresAComparar; probExcedencia: NReal;
      titulo_ejeX: string; ejex: TTipoVariableDelEje; CronVarsEjex: TCronVar;
      Pre_Ordenar: boolean; ProbExcedencia_Sup: NReal; graficar: boolean;
      tiposGraficos: TDAOfTTipoGrafico; ejes: TDAOfTTipoEje; colores: TDAOfTColor;
      minEjeYAuto_eje1, maxEjeYAuto_eje1: boolean; minEjeY_eje1, MaxEjeY_eje1: NReal;
      titulo_eje2: string; digitos_eje2, decimales_eje2: integer;
      minEjeYAuto_eje2, maxEjeYAuto_eje2: boolean; minEjeY_eje2, MaxEjeY_eje2: NReal);

    procedure checkParams(errores: TStringList); override;
    procedure imprimirse(xls: TExcelFile); override;
    class function tipo: string; override;
    procedure Free;
    function parametrosAdicionales: string; override;
    function getColores: TDAOfTColor; override;
    function serialize: string; override;

    function cronVarEjex_nombre: string;
  end;

{$ENDIF}


  { TPrintCronVar_R }

  TPrintCronVar_R = class(TPrintCronVar_MultiCronVar)
  public
    carpeta_destino: string;
    R_archi: string;
    R_script: string;
    cronVars: TDAOfCronVar;

    TipoScript: string; // R, Octave, Matlab.
    flg_quit_al_final: boolean;
    flg_ejecutar: boolean;

    constructor Create(cronVars: TDAOfCronVar; carpeta_destino: string;
      R_Archi: string; R_Script: string; TipoScript: string;
      flg_ejecutar_, flg_quit_al_final_: boolean);

    procedure imprimir_mat(idrunstr: string);

    function usa_excel: boolean; override;
    class function tipo: string; override;
    procedure Free;
    function parametrosAdicionales: string; override;
    function serialize: string; override;

  private
    procedure add_begin_Matlab(script_lst: TStringList);
    procedure add_begin_Octave(script_lst: TStringList);
    procedure add_begin_R(script_lst: TStringList);
    procedure add_end_Matlab(script_lst: TStringList; flg_quit: boolean);
    procedure add_end_Octave(script_lst: TStringList; flg_quit: boolean);
    procedure add_end_R(script_lst: TStringList; flg_quit: boolean);
  end;


implementation

{
uses
  uAuxiliaresEscrituraSimRes;
 }


//------------------------
//Métodos de TPrintCronVar
//========================

constructor TPrintCronVar.Create;
begin
  inherited Create;
  titulo_eje1 := '';
  digitos_eje1 := 12;
  decimales_eje1 := 2;
  minEjeYAuto_eje1 := True;
  maxEjeYAuto_eje1 := True;
  minEjeY_eje1 := 0.0;
  MaxEjeY_eje1 := 100.0;

  titulo_eje2 := '';
  digitos_eje2 := 12;
  decimales_eje2 := 2;
  minEjeYAuto_eje2 := True;
  maxEjeYAuto_eje2 := True;
  minEjeY_eje2 := 0.0;
  MaxEjeY_eje2 := 100.0;

end;

procedure TPrintCronVar.checkParams(errores: TStringList);
begin
  //Nada
end;


// Retonra TRUE si necesita Excel
function TPrintCronVar.usa_excel: boolean;
begin
  Result := True; // por defecto que lo sobreescriban las que precisen otra cosa
end;

function TPrintCronVar.parametrosAdicionales: string;
begin
  Result := '-';
end;

{$IFNDEF SIMRES3SOLOTEXTO}
function TPrintCronVar.getColores: TDAOfTColor;
begin
  Result := nil;
end;

{$ENDIF}

function TPrintCronVar.serialize: string;
begin
  Result := tipo;
end;

//----------------------------------
//Métodos de TPrintCronVarUniCronVar
//==================================

function TPrintCronVar_UniCronVar.getNombresCronVars: string;
begin
  Result := cronVar.nombre;
end;

function TPrintCronVar_UniCronVar.referenciaCronVar(cronVar: TCronVar): boolean;
begin
  Result := self.cronVar = cronVar;
end;

function TPrintCronVar_UniCronVar.serialize: string;
begin
  Result := inherited serialize + #9 + encomille(cronVar.nombre);
end;

function TPrintCronVar_UniCronVar.cronVarsAImprimir: TDAOfCronVar;
var
  res: TDAOfCronVar;
begin
  SetLength(res, 1);
  res[0] := cronVar;
  Result := res;
end;

//------------------------------------
//Métodos de TPrintCronVarMultiCronVar
//====================================

function TPrintCronVar_MultiCronVar.getNombresCronVars: string;
var
  res: string;
  i: integer;
begin
  if Length(cronVars) > 0 then
  begin
    res := cronVars[0].nombre;
    for i := 1 to high(cronVars) do
      res := res + ', ' + cronVars[i].nombre;
  end
  else
    res := '';
  Result := res;
end;

function TPrintCronVar_MultiCronVar.referenciaCronVar(cronVar: TCronVar): boolean;
var
  referencia: boolean;
  i: integer;
begin
  referencia := False;
  for i := 0 to high(cronVars) do
    if cronVars[i] = cronVar then
    begin
      referencia := True;
      break;
    end;
  Result := referencia;
end;

procedure TPrintCronVar_MultiCronVar.Free;
begin
  SetLength(cronVars, 0);
  inherited Free;
end;

function TPrintCronVar_MultiCronVar.cronVarsAImprimir: TDAOfCronVar;
begin
  Result := cronVars;
end;

//--------------------------------------
//Métodos de TPrintCronVar_matrizDeDatos
//======================================

{$IFNDEF SIMRES3SOLOTEXTO}
constructor TPrintCronVar_matrizDeDatos.Create(cronVar: TCronVar;
  nombreHoja: string; titulo, unidades: string; titulosCols: TDAofString;
  digitos, decimales: integer; Print_promedio: boolean; chart_Mat: boolean;
  minEjeYAuto, maxEjeYAuto: boolean; minEjeY, MaxEjeY: NReal);
begin
  inherited Create;
  self.cronVar := cronVar;
  self.nombreHoja := nombreHoja;
  self.titulo := titulo;
  self.titulosCols := titulosCols;
  self.Print_promedio := Print_promedio;
  self.chart_Mat := chart_Mat;

  self.titulo_eje1 := titulo_eje1;
  self.digitos_eje1 := digitos_eje1;
  self.decimales_eje1 := decimales_eje1;
  self.minEjeYAuto_eje1 := minEjeYAuto_eje1;
  self.maxEjeYAuto_eje1 := maxEjeYAuto_eje1;
  self.minEjeY_eje1 := minEjeY_eje1;
  self.MaxEjeY_eje1 := MaxEjeY_eje1;
end;

procedure TPrintCronVar_matrizDeDatos.imprimirse(xls: TExcelFile);
begin
  WriteMatToXLS_SinOrdenar(
    xls, nombreHoja, cronVar.v_,
    titulo, titulo_eje1, titulosColsExt,
    cronVar.nPasos,
    cronVar.nCronicas,
    cronVar.dtIni,
    cronVar.DurPaso_horas / 24,
    decimales_eje1,
    Print_promedio, chart_Mat,
    minEjeYAuto_eje1, maxEjeYAuto_eje1, minEjeY_eje1, MaxEjeY_eje1);
end;

(*
procedure TPrintCronVar_matrizDeDatos.imprimirseYCopiarAWord(xls: TExcelFile;
                                                             wordApp: Variant);
begin
  WriteMatToXLSAndCopyToWord_SinOrdenar(xls, nombreHoja, cronVar.v, titulo, unidades, titulosColsExt, cronVar.nPasos,
                                        cronVar.nCronicas, cronVar.dtIni, cronVar.DurPaso_horas / 24, digitos, decimales,
                                        Print_promedio, chart_Mat,
                                        minEjeYAuto, maxEjeYAuto, minEjeY, MaxEjeY,
                                        wordApp);
end;

*)

class function TPrintCronVar_matrizDeDatos.tipo: string;
begin
  Result := 'matrizDeDatos';
end;

procedure TPrintCronVar_matrizDeDatos.Free;
begin
  SetLength(titulosCols, 0);
  inherited Free;
end;

function TPrintCronVar_matrizDeDatos.parametrosAdicionales: string;
begin
  Result := 'Imprimir Promedio= ' + boolToSiNo(Print_promedio) +
    ', Graficar= ' + boolToSiNo(chart_Mat);
end;

function TPrintCronVar_matrizDeDatos.titulosColsExt: TDAofString;
var
  i: integer;
  res: TDAofString;
  n: integer;
  s: string;
begin
  if cronVar.nCronicas = Length(titulosCols) then
    res := titulosCols
  else
  begin
    n := length(titulosCols);
    SetLength(res, cronVar.nCronicas);

    if (n > cronVar.nCronicas) then
    begin
      s := 'Error, en TPrintCronVar_matrizDeDatos. '#13#10 +
        'De la cronVar: ' + cronVar.nombre + #13#10 +
        'Especificó más titulos de columnas que la cantidad columnas de la matriz.'#13#10 + ' Se ignoran los títulos: '#13#10;
      for i := cronVar.nCronicas to high(titulosCols) do
        s := s + ', ' + titulosCols[i];
      raise Exception.Create(s);

      n := cronVar.nCronicas;
    end;

    for i := 0 to n - 1 do
      res[i] := titulosCols[i];
    for i := n to high(res) do
      res[i] := 'Cron_' + IntToStr(i + 1);
  end;
  Result := res;
end;

function TPrintCronVar_matrizDeDatos.serialize: string;
begin

  Result := inherited serialize + #9 + encomille(nombreHoja) + #9 +
    encomille(titulo) + #9 + encomille(titulo_eje1) + #9 +
    TDAOfStringToStringConTamanio(titulosCols) + #9 + IntToStr(digitos_eje1) +
    #9 + IntToStr(decimales_eje1) + #9 + BoolToStr(Print_promedio, True) +
    #9 + BoolToStr(chart_Mat, True) + #9 + BoolToStr(minEjeYAuto_eje1, True) +
    #9 + BoolToStr(maxEjeYAuto_eje1, True) + #9 +
    FloatToStrF(minEjeY_eje1, ffGeneral, 8, 3) + #9 +
    FloatToStrF(MaxEjeY_eje1, ffGeneral, 8, 3);
end;

//-----------------------------------
//Métodos de TPrintCronVar_histograma
//===================================

constructor TPrintCronVar_histograma.Create(cronVar: TCronVar;
  nombreHoja: string; titulo, titulo_eje1: string;
  digitos_eje1, decimales_eje1: integer; Print_Todas: boolean;
  Print_promedio: boolean; Pre_Ordenar: boolean; TipoImpresion_PE: boolean;
  Print_probAisladas: TDAofNReal; chart_Mat: boolean;
  minEjeYAuto_eje1, maxEjeYAuto_eje1: boolean; minEjeY_eje1, MaxEjeY_eje1: NReal);
begin
  inherited Create;
  self.cronVar := cronVar;
  self.nombreHoja := nombreHoja;
  self.titulo := titulo;
  self.titulo_eje1 := titulo_eje1;
  self.digitos_eje1 := digitos_eje1;
  self.decimales_eje1 := decimales_eje1;
  self.Print_Todas := Print_Todas;
  self.Print_promedio := Print_promedio;
  self.Pre_Ordenar := Pre_Ordenar;
  self.TipoImpresion_PE := TipoImpresion_PE;
  self.Print_probAisladas := Print_probAisladas;
  self.chart_Mat := chart_Mat;
  self.minEjeYAuto_eje1 := minEjeYAuto_eje1;
  self.maxEjeYAuto_eje1 := maxEjeYAuto_eje1;
  self.minEjeY_eje1 := minEjeY_eje1;
  self.MaxEjeY_eje1 := MaxEjeY_eje1;
end;

procedure TPrintCronVar_histograma.imprimirse(xls: TExcelFile);
begin
  WriteMatToXLS(
    xls, nombreHoja, cronVar.v_,
    UTF8TOAnsi(titulo), Titulo_eje1, cronVar.nPasos,
    cronVar.nCronicas, cronVar.dtIni, cronVar.DurPaso_horas / 24.0,
    decimales_eje1,
    Print_Todas, Print_promedio,
    Pre_Ordenar,
    TipoImpresion_PE,
    Print_probAisladas, chart_Mat,
    minEjeYAuto_eje1, maxEjeYAuto_eje1, minEjeY_eje1, MaxEjeY_eje1);
end;


class function TPrintCronVar_histograma.tipo: string;
begin
  Result := 'histograma';
end;

function TPrintCronVar_histograma.parametrosAdicionales: string;
begin
  if length(Print_probAisladas) > 0 then
    Result := 'Imprimir Promedio= ' + boolToSiNo(Print_promedio) +
      ', Graficar= ' + boolToSiNo(chart_Mat) + ', PrintProbsAisladas= ' +
      TDAOfNRealToStringSinTamanio(Print_probAisladas, 4, 3, ', ')
  else
    Result := 'Imprimir Promedio= ' + boolToSiNo(Print_promedio) +
      ', Graficar= ' + boolToSiNo(chart_Mat) + ', PrintProbsAisladas= no';
end;

class function TPrintCronVar_histograma.printProbAisladasPorDefecto: TDAofNReal;
var
  printProbsAisladasPorDefecto: TDAofNReal;
begin
  SetLength(printProbsAisladasPorDefecto, 4);
  printProbsAisladasPorDefecto[0] := 0.1;
  printProbsAisladasPorDefecto[1] := 0.3;
  printProbsAisladasPorDefecto[2] := 0.7;
  printProbsAisladasPorDefecto[3] := 0.9;
  Result := printProbsAisladasPorDefecto;
end;

procedure TPrintCronVar_histograma.Free;
begin
  SetLength(Print_probAisladas, 0);
  inherited Free;
end;


function TPrintCronVar_histograma.serialize: string;
begin
  Result := inherited serialize + #9 + encomille(nombreHoja) + #9 +
    encomille(titulo) + #9 + encomille(titulo_eje1) + #9 +
    IntToStr(digitos_eje1) + #9 + IntToStr(decimales_eje1) + #9 +
    BoolToStr(Print_Todas, True) + #9 + BoolToStr(Print_promedio, True) +
    #9 + BoolToStr(Pre_Ordenar, True) + #9 + BoolToStr(TipoImpresion_PE, True) +
    #9 + TDAOfNRealToTabbedStringConTamanio(Print_probAisladas, 8, 3) +
    #9 + BoolToStr(chart_Mat, True) + #9 + BoolToStr(minEjeYAuto_eje1, True) +
    #9 + BoolToStr(maxEjeYAuto_eje1, True) + #9 +
    FloatToStrF(minEjeY_eje1, ffGeneral, 8, 3) + #9 +
    FloatToStrF(MaxEjeY_eje1, ffGeneral, 8, 3);
end;

{$ENDIF}


//-----------------------------------
//Métodos de TPrintCronVar_histograma_text
//===================================

constructor TPrintCronVar_histograma_text.Create(cronVar: TCronVar;
  archi: string; titulo, unidades: string; digitos, decimales: integer;
  Print_Todas: boolean; Print_promedio: boolean; Pre_Ordenar: boolean;
  TipoImpresion_PE: boolean; Print_probAisladas: TDAofNReal);
begin
  inherited Create;
  self.cronVar := cronVar;
  if pos('.', archi) = 0 then
    archi := archi + '.xlt';
  self.nombreHoja := archi;
  self.titulo := titulo;
  self.titulo_eje1 := titulo_eje1;
  self.digitos_eje1 := digitos_eje1;
  self.decimales_eje1 := decimales_eje1;
  Self.Print_Todas := Print_Todas;
  Self.Print_promedio := Print_Promedio;
  Self.Pre_Ordenar := Pre_Ordenar;
  Self.TipoImpresion_PE := TipoImpresion_PE;
  Self.Print_probAisladas := Print_probAisladas;
end;


function TPrintCronVar_histograma_text.usa_excel: boolean;
begin
  Result := False;
end;

procedure TPrintCronVar_histograma_text.imprimirse(xls: TExcelFile);
begin
  WriteMatToText(
    nombreHoja, xls.idStr,
    cronVar.v_,
    UTF8ToAnsi(titulo), cronVar.nPasos,
    cronVar.nCronicas, cronVar.dtIni, cronVar.DurPaso_horas / 24.0,
    digitos_eje1,
    decimales_eje1,
    Print_Todas, Print_promedio, Pre_Ordenar, TipoImpresion_PE, Print_probAisladas);
end;

class function TPrintCronVar_histograma_text.tipo: string;
begin
  Result := 'histograma_text';
end;

procedure TPrintCronVar_histograma_text.Free;
begin
  SetLength(Print_probAisladas, 0);
  inherited Free;
end;

function TPrintCronVar_histograma_text.parametrosAdicionales: string;
begin
  if length(Print_probAisladas) > 0 then
    Result := 'Imprimir Promedio= ' + boolToSiNo(Print_promedio) +
      ', PrintProbsAisladas= ' + TDAOfNRealToStringSinTamanio(
      Print_probAisladas, 4, 3, ', ')
  else
    Result := 'Imprimir Promedio= ' + boolToSiNo(Print_promedio) +
      ', PrintProbsAisladas= no';
end;

class function TPrintCronVar_histograma_text.printProbAisladasPorDefecto: TDAofNReal;
var
  printProbsAisladasPorDefecto: TDAofNReal;
begin
  SetLength(printProbsAisladasPorDefecto, 4);
  printProbsAisladasPorDefecto[0] := 0.1;
  printProbsAisladasPorDefecto[1] := 0.3;
  printProbsAisladasPorDefecto[2] := 0.7;
  printProbsAisladasPorDefecto[3] := 0.9;
  Result := printProbsAisladasPorDefecto;
end;


function TPrintCronVar_Histograma_text.serialize: string;
begin
  Result := inherited serialize + #9 + encomille(nombreHoja) + #9 +
    encomille(titulo) + #9 + encomille(titulo_eje1) + #9 + IntToStr(digitos_eje1) +
    #9 + IntToStr(decimales_eje1) + #9 + BoolToStr(Print_Todas, True) +
    #9 + BoolToStr(Print_promedio, True) + #9 + BoolToStr(Pre_Ordenar, True) +
    #9 + BoolToStr(TipoImpresion_PE, True) + #9 +
    TDAOfNRealToTabbedStringConTamanio(Print_probAisladas, 8, 3);
end;

{$IFNDEF SIMRES3SOLOTEXTO}

(** métodos de TPrintCronVar_HistogramaGlobal **)
constructor TPrintCronVar_HistogramaGlobal.Create(cronVar: TCronVar;
  nombreHoja: string; titulo, unidades: string; digitos, decimales: integer;
  minX, maxX: NReal; nPuntosHistograma: integer{;
                                                  chart_Mat: boolean;
                                                  minEjeYAuto, maxEjeYAuto: boolean;
                                                  minEjeY, MaxEjeY: NReal});
begin
  inherited Create;
  self.cronVar := cronVar;
  self.nombreHoja := nombreHoja;
  self.titulo := titulo;
  self.titulo_eje1 := titulo_eje1;
  self.digitos_eje1 := digitos_eje1;
  self.decimales_eje1 := decimales_eje1;
  self.minX := minX;
  self.maxX := maxX;
  self.nPuntosHistograma := nPuntosHistograma;
{  self.chart_Mat:= chart_Mat;
  self.minEjeYAuto:= minEjeYAuto;
  self.maxEjeYAuto:= maxEjeYAuto;
  self.minEjeY:= minEjeY;
  self.MaxEjeY:= MaxEjeY;}
end;

procedure TPrintCronVar_HistogramaGlobal.imprimirse(xls: TExcelFile);
begin
  writeHistogramaGlobalToXls(xls, nombreHoja, cronVar.v_, UTF8ToAnsi(titulo),
    titulo_eje1,
    decimales_eje1, minX, maxX, nPuntosHistograma
                             {, chart_Mat, minEjeYAuto,
                             maxEjeYAuto, minEjeY, MaxEjeY});
end;


class function TPrintCronVar_HistogramaGlobal.tipo: string;
begin
  Result := 'HistogramaGlobal';
end;

procedure TPrintCronVar_HistogramaGlobal.Free;
begin
  inherited Free;
end;

function TPrintCronVar_HistogramaGlobal.serialize: string;
begin
  Result := inherited serialize + #9 + encomille(nombreHoja) + #9 +
    encomille(titulo) + #9 + encomille(titulo_eje1) + #9 + IntToStr(digitos_eje1) +
    #9 + IntToStr(decimales_eje1) + #9 + FloatToStr(minX) + #9 +
    FloatToStr(maxX) + #9 + IntToStr(nPuntosHistograma);
end;


//---------------------------------------------------------
//Métodos de TPrintCronVar_compararValoresMultiplesCronVars

//=========================================================

constructor TPrintCronVar_compararValoresMultiplesCronVars.Create(
  cronVars: TDAOfCronVar; nombreHoja: string; titulo: string;
  titulo_eje1: string; digitos_eje1, decimales_eje1: integer;
  tipoValorAComparar: TTipoValoresAComparar; probExcedencia: NReal;
  titulo_ejeX: string; ejex: TTipoVariableDelEje; CronVarsEjex: TCronVar;
  Pre_Ordenar: boolean; ProbExcedencia_Sup: NReal; graficar: boolean;
  tiposGraficos: TDAOfTTipoGrafico; ejes: TDAOfTTipoEje; colores: TDAOfTColor;
  minEjeYAuto_eje1, maxEjeYAuto_eje1: boolean; minEjeY_eje1, MaxEjeY_eje1: NReal;
  titulo_eje2: string; digitos_eje2, decimales_eje2: integer;
  minEjeYAuto_eje2, maxEjeYAuto_eje2: boolean; minEjeY_eje2, MaxEjeY_eje2: NReal);
begin
  inherited Create;
  self.cronVars := cronVars;
  self.nombreHoja := nombreHoja;
  self.titulo := titulo;

  self.titulo_eje1 := Titulo_eje1;
  self.digitos_eje1 := digitos_eje1;
  self.decimales_eje1 := decimales_eje1;
  self.tipoValorAComparar := tipoValorAComparar;
  self.probExcedencia := probExcedencia;

  self.titulo_ejeX := titulo_ejeX;

  self.ejex := ejex;
  self.cronVarEjex := CronVarsEjex;

  self.Pre_Ordenar := Pre_Ordenar;
  self.ProbExcedencia_Sup := ProbExcedencia_Sup; // borde superior

  self.graficar := graficar;
  self.tiposGraficos := tiposGraficos;
  self.ejes := ejes;
  self.colores := colores;
  self.minEjeYAuto_eje1 := minEjeYAuto_eje1;
  self.maxEjeYAuto_eje1 := maxEjeYAuto_eje1;
  self.minEjeY_eje1 := minEjeY_eje1;
  self.MaxEjeY_eje1 := MaxEjeY_eje1;

  self.titulo_eje2 := Titulo_eje2;
  self.digitos_eje2 := digitos_eje2;
  self.decimales_eje2 := decimales_eje2;
  self.minEjeYAuto_eje2 := minEjeYAuto_eje2;
  self.maxEjeYAuto_eje2 := maxEjeYAuto_eje2;
  self.minEjeY_eje2 := minEjeY_eje2;
  self.MaxEjeY_eje2 := MaxEjeY_eje2;

end;

procedure TPrintCronVar_compararValoresMultiplesCronVars.checkParams(
  errores: TStringList);
var
  i, nf, nc: integer;
  i_CronVar_Max_nf, i_CronVar_Max_nc: integer;

begin
  nf := 0;
  nc := 0;
  i_CronVar_Max_nf := 0;
  i_CronVar_Max_nc := 0;

  // primero buscamos los máximos.
  for i := 0 to high(cronVars) do
  begin
    if cronVars[i].nPasos > nf then
    begin
      nf := cronVars[i].nPasos;
      i_CronVar_Max_nf := i;
    end;

    if cronVars[i].nCronicas > nc then
    begin
      nc := cronVars[i].nCronicas;
      i_CronVar_Max_nc := i;
    end;
  end;

  // ahora chequeamos que la dimensión sea 1 o el máximo
  for i := 0 to high(cronVars) do
  begin
    if cronVars[i].v_ = nil then
    begin
      errores.Add('La cronVar "' + cronVars[i].nombre +
        '" no ha sido inicializada.' + ' Asegurese de que "' +
        cronVars[i].nombre +
        '" sea el resultado de al menos una cronOper o una postOper.');
    end
    else
    begin

 (*
     if ((cronVars[i].nPasos <> 1 ) and ( cronVars[i].nPasos <> nf)) then
         errores.Add('La cronVar "' + cronVars[i].nombre + '" tiene distinta cantidad de pasos que la cronVar "' + cronVars[ i_CronVar_Max_nf].nombre + '".' +
                   ' Para poder imprimir debe seleccionar un conjunto de cronVars con la misma dimensión.');

     if (( cronVars[i].nCronicas <> 1) and ( cronVars[i].nCronicas <> nc)) then
        errores.Add('La cronVar "' + cronVars[i].nombre + '" tiene distinta cantidad de crónicas que la cronVar "' + cronVars[ i_CronVar_Max_nc].nombre + '".' +
                  ' Para poder imprimir debe seleccionar un conjunto de cronVars con la misma dimensión.');

 *)
    end;
  end;
end;

procedure TPrintCronVar_compararValoresMultiplesCronVars.imprimirse(xls: TExcelFile);
var
  nombres: TDAofString;
  mats: array of TMatOfNReal;
  nombre_ejex: string;
  mat_ejex: TMatOfNReal;
  i: integer;
begin

  if cronVarEjex <> nil then
  begin
    nombre_ejex := Utf8ToAnsi(cronVarEjex.nombre);
    mat_ejex := cronVarEjex.v_;
  end
  else
  begin
    nombre_ejex := '';
    mat_ejex := nil;
  end;

  SetLength(mats, length(cronVars));
  SetLength(nombres, length(cronVars));

  for i := 0 to high(nombres) do
  begin
    nombres[i] := Utf8ToAnsi(cronVars[i].nombre);
    mats[i] := cronVars[i].v_;
  end;


  WriteValoresToXLS(
    xls, tipoValorAComparar,
    probExcedencia, Pre_Ordenar,
    ProbExcedencia_Sup,
    nombres, mats,
    nombre_ejex, mat_ejex,
    Utf8ToAnsi(nombreHoja), Utf8ToAnsi(titulo),
    cronVars[0].dtIni, cronVars[0].DurPaso_horas / 24.0,
    graficar, tiposGraficos, ejes, colores,

    titulo_eje1,
    digitos_eje1,
    decimales_eje1,
    minEjeYAuto_eje1,
    maxEjeYAuto_eje1,
    minEjeY_eje1,
    MaxEjeY_eje1,

    titulo_eje2,
    digitos_eje2,
    decimales_eje2,
    minEjeYAuto_eje2,
    maxEjeYAuto_eje2,
    minEjeY_eje2,
    MaxEjeY_eje2,

    ejex, titulo_ejeX);

  SetLength(nombres, 0);
  SetLength(mats, 0);
end;


class function TPrintCronVar_compararValoresMultiplesCronVars.tipo: string;
begin
  Result := 'CompararValoresMultiplesCronVars';
end;

procedure TPrintCronVar_compararValoresMultiplesCronVars.Free;
begin
  inherited Free;
end;

function TPrintCronVar_compararValoresMultiplesCronVars.parametrosAdicionales: string;
var
  res: string;
begin
  if tipoValorAComparar = ProbabilidadesDeExcedencia then
    res := 'Valores a Comparar= P.E. ' + FloatToStr(probExcedencia) + '[p.u], '
  else
    res := 'Valores a Comparar= ' + TTipoValoresACompararToString(
      tipoValorAComparar) + ', ';

  if graficar then
  begin
    res := res + 'Graficar= si';
  end
  else
    res := res + 'Graficar= no';
  Result := res;
end;

function TPrintCronVar_compararValoresMultiplesCronVars.getColores: TDAOfTColor;
var
  i, nColoresNoDefault: integer;
  res: TDAOfTColor;
begin
  nColoresNoDefault := 0;
  SetLength(res, length(colores));
  for i := 0 to high(colores) do
  {$IFDEF FP_CANVAS}
    if not colores_iguales(colores[i], clDefault) then
  {$ELSE}
      if colores[i] <> clDefault then
  {$ENDIF}
      begin
        res[nColoresNoDefault] := colores[i];
        nColoresNoDefault := nColoresNoDefault + 1;
      end;

  if nColoresNoDefault <> Length(res) then
    SetLength(res, nColoresNoDefault);
  Result := res;
end;

function TPrintCronVar_compararValoresMultiplesCronVars.serialize: string;
begin
  Result := inherited serialize + #9 +
    TDAOfCronVarTipoGraficoEjeColorToStringConTamanio(cronVars,
    tiposGraficos, ejes, colores) + #9 + encomille(nombreHoja) +
    #9 + encomille(titulo) + #9 + encomille(titulo_eje1) + #9 +
    IntToStr(digitos_eje1) + #9 + IntToStr(decimales_eje1) + #9 +
    encomille(TTipoValoresACompararToString(tipoValorAComparar)) +
    #9 + FloatToStr(probExcedencia) + #9 + encomille(titulo_ejeX) +
    #9 + TEjeToString(ejex) + #9 + encomille(cronVarEjex_nombre) +
    #9 + BoolToStr(Pre_Ordenar) + #9 + FloatToStr(ProbExcedencia_Sup) +
    #9 + BoolToStr(graficar, True) + #9 + BoolToStr(minEjeYAuto_eje1, True) +
    #9 + BoolToStr(maxEjeYAuto_eje1, True) + #9 +
    FloatToStrF(minEjeY_eje1, ffGeneral, 8, 3) + #9 +
    FloatToStrF(MaxEjeY_eje1, ffGeneral, 8, 3) + #9 + encomille(titulo_eje2) +
    #9 + IntToStr(digitos_eje2) + #9 + IntToStr(decimales_eje2) + #9 +
    BoolToStr(minEjeYAuto_eje2, True) + #9 + BoolToStr(maxEjeYAuto_eje2, True) +
    #9 + FloatToStrF(minEjeY_eje2, ffGeneral, 8, 3) + #9 +
    FloatToStrF(MaxEjeY_eje2, ffGeneral, 8, 3);
end;

function TPrintCronVar_compararValoresMultiplesCronVars.cronVarEjex_nombre: string;
begin
  if cronVarEjex <> nil then
    Result := cronVarEjex.nombre
  else
    Result := 'nil';
end;

{$ENDIF}




constructor TPrintCronVar_R.Create(cronVars: TDAOfCronVar;
  carpeta_destino: string; R_Archi: string; R_Script: string;
  TipoScript: string; flg_ejecutar_, flg_quit_al_final_: boolean);
begin
  inherited Create;
  self.carpeta_destino := carpeta_destino;
  self.cronVars := cronVars;
  self.R_archi := R_Archi;
  self.R_Script := R_Script;
  self.TipoScript := TipoScript;
  self.flg_quit_al_final := flg_quit_al_final_;
  self.flg_ejecutar := flg_ejecutar_;
end;

function TPrintCronVar_R.usa_excel: boolean;
begin
  Result := False;
end;


(***************
# Cargar paquete ggplot2
library(ggplot2)


# Supongamos la generación mensual de las máquinas del sistema:
# Los datos van en un dataframe:
datos <- data.frame(mes=rep(1:12,each=3), máquina=rep(c("Quinta", "Sexta", "CTR"), times=12), generación=runif(n=3*12, max=300))
# (Doce meses, tres máquinas, con generaciones aleatorias)


# Gráfica de areas apiladas
ggplot(data=datos) + geom_area(mapping=aes(x=mes, y=generación, group=máquina, fill=máquina), position="stack")



*****************)

procedure TPrintCronVar_R.add_begin_R(script_lst: TStringList);
var
  aCronVar: TCronVar;
  archi: string;
  k: integer;
begin
  script_lst.add('# Inicio R script generado por SimSEE');
  script_lst.add('# Versión SimSEE: ' + vSimSEESimulador_);
  script_lst.add('# Fecha: ' + DateTimeToStr(now()));
  remplazar_letra(carpeta_destino, '\', '/');
  script_lst.add('setwd("' + carpeta_destino + '")');
  for k := 0 to high(cronVars) do
  begin
    aCronVar := cronVars[k];
    archi := aCronVar.nombre;
    remplazar_letra(archi, '\', '/');
    //    script_lst.add(aCronVar.nombre + ' <- read.table( "' + archi +
    //      '.csv",  skip=0, header=TRUE, sep=",", dec="." ) ');
    script_lst.add(aCronVar.nombre + ' <- as.matrix( read.table( "' +
      archi + '.csv",  skip=0, header=FALSE, sep=",", dec="." )) ');
    script_lst.add(aCronVar.nombre + '_def <- read.table( "' + archi +
      '_def.csv",  skip=0, header=FALSE, sep=",", dec="." ) ');
  end;
end;

procedure TPrintCronVar_R.add_begin_Octave(script_lst: TStringList);
var
  aCronVar: TCronVar;
  archi: string;
  k: integer;
begin
  script_lst.add('# Inicio Octave script generado por SimSEE');
  script_lst.add('# Versión SimSEE: ' + vSimSEESimulador_);
  script_lst.add('# Fecha: ' + DateTimeToStr(now()));
  remplazar_letra(carpeta_destino, '\', '/');
  script_lst.add('cd "' + carpeta_destino + '"');
  for k := 0 to high(cronVars) do
  begin
    aCronVar := cronVars[k];
    archi := aCronVar.nombre;
    remplazar_letra(archi, '\', '/');
    script_lst.add(aCronVar.nombre + '= csvread( "' + archi + '.csv" ); ');
    script_lst.add(aCronVar.nombre + '_def= csvread( "' + archi + '_def.csv" ); ');
  end;
end;

procedure TPrintCronVar_R.add_begin_Matlab(script_lst: TStringList);
begin
  // Por ahora ... lo mismo que en Octave.
  add_begin_Octave(script_lst);
end;

procedure TPrintCronVar_R.add_end_R(script_lst: TStringList; flg_quit: boolean);
begin
  // Acá podría ir algo más.

  if flg_quit then
    script_lst.add('q()');
end;

procedure TPrintCronVar_R.add_end_Octave(script_lst: TStringList; flg_quit: boolean);
begin
  // Acá podría ir algo más.

  if flg_quit then
    script_lst.add('exit');
end;

procedure TPrintCronVar_R.add_end_Matlab(script_lst: TStringList; flg_quit: boolean);
begin
  // Acá podría ir algo más.

  if flg_quit then
    script_lst.add('exit');
end;

procedure TPrintCronVar_R.imprimir_mat(idrunstr: string);
var
  k: integer;
  aCronVar: TCronVar;
  archi: string;
  script_lst, result_lst: TStringList;
  kts: integer;
  comando_externo: string;
  paramsLst: TStringList;

begin

  // Atención, esto lo pongo así por ahora
  // Luego veremos si habilitamos que se Lancen las aplicaciones desde
  // El SimRes3. Esto tiene sus complicaciones.
  self.flg_ejecutar := False;
  self.flg_quit_al_final := False;

  setSeparadoresGlobales; // para que escriba en global

  if TipoScript = 'R' then
    kts := 0
  else if TipoScript = 'Octave' then
    kts := 1
  else if TipoScript = 'Matlab' then
    kts := 2
  else
    raise Exception.Create('TPrintCronVar_R, tipo script desconocido: ' + TipoScript);

  if not DirectoryExists(carpeta_destino) then
    mkdir(carpeta_destino);
  for k := 0 to high(cronVars) do
  begin
    aCronVar := cronVars[k];
    archi := carpeta_destino + DirectorySeparator + aCronVar.nombre;
    aCronVar.Write_R_csv(archi, idrunstr);
  end;


  script_lst := TStringList.Create;

  script_lst.add('# ' + idrunstr);
  case kts of
    0: add_begin_R(script_lst);
    1: add_begin_Octave(script_lst);
    2: add_begin_Matlab(script_lst);
  end;

  script_lst.add(self.R_script);

  case kts of
    0: add_end_R(script_lst, flg_quit_al_final);
    1: add_end_Octave(script_lst, flg_quit_al_final);
    2: add_end_Matlab(script_lst, flg_quit_al_final);
  end;

  if kts = 0 then
    archi := carpeta_destino + DirectorySeparator + Self.R_archi + '.R'
  else
    archi := carpeta_destino + DirectorySeparator + Self.R_archi + '.m';

  script_lst.SaveToFile(archi);

  setSeparadoresLocales; // vuelvo a LOCAL


  if flg_ejecutar then
  begin
    paramsLst := TStringList.Create;
    case kts of
      0:
      begin
        paramsLst.add('--no-restore');
        paramsLst.add('--no-save');
        comando_externo := 'C:\Program Files\R\R-3.1.2\bin\x64\Rterm.exe';
      end;
      1:
      begin

      (*
       paramsLst.add( '-f' );
       paramsLst.add( '--no-init-file' );
       paramsLst.add( '--force-gui');
       *)
        paramsLst.add('-x');
        paramsLst.add('--interactive');
        paramsLst.add('--persist');
        comando_externo := 'C:\Octave\Octave-4.0.0\bin\octave.exe';

      end;
      2:
      begin
        paramsLst.add('--interactive');
        paramsLst.add('-x');
        paramsLst.add('--persist');
        comando_externo := 'C:\Octave\Octave-4.0.0\bin\octave.exe';
      end;
    end;


    result_lst := runPipe(comando_externo, paramsLst, script_lst, #10);
    archi := carpeta_destino + DirectorySeparator + Self.R_archi + '.out';
    result_lst.SaveToFile(archi);
    result_lst.Free;
    paramsLst.Free;
  end;
end;

class function TPrintCronVar_R.tipo: string;
begin
  Result := 'Script_R_Octave_Matlab';
end;

procedure TPrintCronVar_R.Free;
begin
  inherited Free;
end;

function TPrintCronVar_R.parametrosAdicionales: string;
begin
  Result := self.carpeta_destino + ', ' + self.R_archi + ', ' + self.R_script;
end;

function TPrintCronVar_R.serialize: string;
var
  k: integer;
  res: string;
begin
  res := inherited serialize;
  res := res + #9 + IntToStr(length(cronVars));
  for k := 0 to high(CronVars) do
    res := res + #9 + encomille(cronVars[k].nombre);
  res := res + #9 + encomille(carpeta_destino) + #9 + encomille(R_archi) +
    #9 + HTTPEncode(R_script);
  res := res + #9 + self.TipoScript + #9 + BoolToStr(flg_ejecutar, True) +
    #9 + BoolToStr(flg_quit_al_final, True);
  Result := res;
end;

end.
