unit uSimSolar;

{$MODE Delphi}

interface

uses
  Windows, shellapi,
  Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Grids,
  Menus,
  // jpeg,
  ExtCtrls, ComCtrls,
  xmatdefs,
  fddp,
  uhtmlverdoc,
  NucleoT,
  task2,
  VGlbs02,
  Params,
  listas,
  ancestor,
  horrores,
  actores,
  dire02,
  Evals02,
  ActBat04,
  FntVnts,
  fdsol,
  lexemas,
  ofedem02,
  tabp2d,
  fdefs,
  bases,
  fdias02,
  ocurrenx,
  autoesca,
  uSeresVivos,
  fdsol02horaria,
  fdsol_ktcegh,
  fdr01,
  fdrs,
  facpos,
  matpole,
  actpan04,
  demht,
  ufUbicacion, ufCarga, ufPaneles, ufBaterias, ufSimulacion;

const
  archiDatosSintetizador = 'ModeloKT.txt';

type
  TfSimSolar = class(TForm)
    gbResultados: TGroupBox;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    Label5: TLabel;
    eDDDEsperados: TEdit;
    eDDDpne90: TEdit;
    eDDEEsperados: TEdit;
    eDDEpe90: TEdit;
    eBatDeg_med: TEdit;
    Panel2: TPanel;
    lblUbicacionGeografica: TLabel;
    lblCarga: TLabel;
    lblPaneles: TLabel;
    lblBaterias: TLabel;
    lblSimulacion: TLabel;
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Button4: TButton;
    Button5: TButton;
    ProgressBar1: TProgressBar;
    Button6: TButton;
    Button7: TButton;
    MainMenu1: TMainMenu;
    Abrir1: TMenuItem;
    Leer1: TMenuItem;
    Guardar1: TMenuItem;
    Nuevo1: TMenuItem;
    Help1: TMenuItem;
    Contents1: TMenuItem;
    About1: TMenuItem;
    OpenDialog1: TOpenDialog;
    barraDeEstado: TStatusBar;
    lblEnergiaDelDiaMedio: TLabel;
    Button8: TButton;
    Memo1: TMemo;
    procedure FormCreate(Sender: TObject);
    procedure Leer1Click(Sender: TObject);
    procedure Nuevo1Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
    procedure Guardar1Click(Sender: TObject);
    procedure Button5Click(Sender: TObject);
    procedure Button6Click(Sender: TObject);
    procedure Button7Click(Sender: TObject);
    procedure FormCloseQuery(Sender: TObject; var CanClose: boolean);
    procedure Contents1Click(Sender: TObject);
    procedure About1Click(Sender: TObject);
    procedure Button8Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    carpetaDeLaCorrida: string;
    archi: string; // nombre de archivo bajo edición
    xmodificado: boolean; // a true si necesita salvarse
    ultimoAddString: string;

    RW_f: textfile;
    RW_modo: integer;

    // ofrece Guardar con opciones SI NO y CANCELAR
    // Retorna TRUE si se seleccionó CANCELAR indicando que
    // se debe abortar la acción. Si seleccionamos SI guarda y retorna
    // false. Si seleccionamos NO, no guarda y retorna false.
    function Cancelar_GuardarSiNo: boolean;
    procedure ActualizarBarraDeEstado(addString: string);
    procedure setModificado;
    procedure resetModificado;

    procedure ActualizarResumenUbicacion;
    procedure ActualizarResumenCarga;
    procedure ActualizarResumenPaneles;
    procedure ActualizarResumenBaterias;
    procedure ActualizarResumenSimulacion;

    //    procedure rws( var f: textfile; var x: integer; modo: integer );
    procedure rwi(var x: integer);
    procedure rwf(var x: NReal);
    procedure rwb(var x: boolean);

    procedure rwEscenario(modo: integer);
    procedure Ejecutar;

  end;

var
  fSimSolar: TfSimSolar;


implementation



{$R *.lfm}


var

  EDiariaWh: NReal;

  DiasPermitidosDeDeficit, VentanaDeDeficit, VentanaDeExcesos: integer;
  usarModeloCEGHSolar: boolean;

var
  PerfilCDC: TPerfilCDC;
  EstacionalCDC: TEstacionalesCDC;

  Bat_CT: NReal;
  Bat_TN: NReal;
  Bat_ID: NReal;
  Bat_IR: NReal;
  Bat_VN: NReal;
  Bat_rc: NReal; { rendimiento de carga }
  Bat_x1: NReal;
  Bat_y1: NReal;
  Bat_x2: NReal;
  Bat_y2: NReal;

  NPaneles: integer;
  Paneles_PotenciaPicoPorPanel: NReal;
  Paneles_InclinacionDePaneles: NReal;
  Paneles_UsarUnAnguloPorMes: integer;
  Paneles_Angulos: TArrMensual;



  ImpFecha: boolean;
  CapacidadDeBateria, PPCB: NReal;
  NumeroDePanelesDe48W: NReal;
  Latitud, Longitud: NReal;

  DiasDeDeficitResultante, DiasDeExcesoResultante: NReal;

  Quantum: NReal;

  xF: TFuenteDeSol; //Usa la clase abstracta, puede ser FuenteAnilloRuidoso o
  //TFDSol_ktcegh
  xpanel: ActPan04.TPanelSolar;


  Demanda: TDemHT;
  bateria: ActBat04.TBateriaHD;
  e1, e2: Evals02.TEvaluador;
  histoAniosVidaBat: THistograma;
  confianza: NReal;
  contador: integer;
  txt: string;


  auto: boolean;



procedure TfSimSolar.About1Click(Sender: TObject);
begin
  htmlverdoc('creditos');
end;

procedure TfSimSolar.ActualizarBarraDeEstado(addString: string);
var
  s: string;
begin
  s := archi;
  if xmodificado then
    s := s + ' (Modificado)';
  barraDeEstado.SimpleText := s + ' ' + addString;
  ultimoAddString := addString;
end;

procedure TfSimSolar.setModificado;
begin
  xModificado := True;
  ActualizarBarraDeEstado(ultimoAddString);
  self.gbResultados.Visible := False;
end;



procedure TfSimSolar.actualizarResumenUbicacion;
begin
  lblUbicacionGeografica.Caption :=
    'Latitud [º]: ' + FloatToStrF(Latitud, ffFixed, 6, 1) + ', Longitud [º]: ' + FloatToStrF(
    Longitud, ffFixed, 6, 1);
end;

procedure TfSimSolar.ActualizarResumenCarga;
var
  EnergiaDiaria: NReal;
  PromedioFactores: NReal;
  kHora: integer;
  mes: T_Mes;
begin
  EnergiaDiaria := 0;
  for kHora := 0 to 23 do
    EnergiaDiaria := EnergiaDiaria + PerfilCDC[kHora];
  PromedioFactores := 0;
  for mes := Enero to Diciembre do
    PromedioFactores := PromedioFactores + EstacionalCDC[mes];
  PromedioFactores := PromedioFactores / 12.0;
  EnergiaDiaria := EnergiaDiaria * PromedioFactores;
  lblCarga.Caption := 'Consumo medio diario [Wh/día]: ' + FloatToStrF(
    EnergiaDiaria, ffFixed, 6, 2);
end;


procedure TfSimSolar.ActualizarResumenPaneles;
begin

  if Paneles_UsarUnAnguloPorMes = 0 then
    lblPaneles.Caption := 'Paneles: ' + IntToStr(nPaneles) +
      ' x ' + FloatToStrF(Paneles_PotenciaPicoPorPanel, ffFixed,
      6, 1) + 'Wpico, angulo [º]: ' + FloatToStrF(
      Paneles_InclinacionDePaneles, ffFixed, 6, 1)
  else
    lblPaneles.Caption := 'Paneles: ' + IntToStr(nPaneles) +
      ' x ' + FloatToStrF(Paneles_PotenciaPicoPorPanel, ffFixed,
      6, 1) + 'Wpico, angulo [º] Mín: ' + FloatToStrF(
      Minimo(Paneles_Angulos), ffFixed, 6, 1) + ' Máximo: ' + FloatToStrF(
      Maximo(Paneles_Angulos), ffFixed, 6, 1);

end;

procedure TfSimSolar.ActualizarResumenBaterias;
begin
  lblBaterias.Caption := 'Cap.[Ah]: ' + FloatToStrF(CapacidadDeBateria, ffFixed, 6, 1) +
    ' [V]: ' + FloatToStrF(Bat_VN, ffFixed, 6, 1) +
    ' PPCB[p.u.]: ' + FloatToStrF(PPCB, ffFixed, 6, 3);
end;

procedure TfSimSolar.ActualizarResumenSimulacion;
begin
  Self.lblSimulacion.Caption :=
    'Años a simular: ' + IntToStr(periodosTotales) + ', Días Permitidos de Déficit: ' +
    IntToStr(DiasPermitidosDeDeficit) + ',' + #13 + 'Usar Modelo CEGH Solar: ' +
    BoolToStr(usarModeloCEGHSolar, True);
end;

procedure TfSimSolar.resetModificado;
begin
  xModificado := False;
  ActualizarBarraDeEstado(ultimoAddString);

end;

procedure TfSimSolar.Button1Click(Sender: TObject);
var
  fUbicacion: TfUbicacion;
  res: integer;
begin
  fUbicacion := TfUbicacion.Create(Self);
  fUbicacion.SetDatos(Latitud, Longitud);
  res := fUbicacion.ShowModal;
  if res = 1 then
  begin
    fUbicacion.getDatos(Latitud, Longitud);
    actualizarResumenUbicacion;
    SetModificado;
  end;
  fUbicacion.Free;
end;

procedure TfSimSolar.Button2Click(Sender: TObject);
var
  fCarga: TfCarga;
  res: integer;
begin
  fCarga := TfCarga.Create(Self);
  fCarga.SetDatos(PerfilCDC, EstacionalCDC);
  res := fCarga.ShowModal;
  if res = 1 then
  begin
    fCarga.GetDatos(PerfilCDC, EstacionalCDC);
    actualizarResumenCarga;
    SetModificado;
  end;
  fCarga.Free;
end;

procedure TfSimSolar.Button3Click(Sender: TObject);
var
  fPaneles: TfPaneles;
  res: integer;
begin
  fPaneles := TfPaneles.Create(Self);
  fPaneles.SetDatos(
    nPaneles,
    Paneles_PotenciaPicoPorPanel,
    Paneles_InclinacionDePaneles,
    Paneles_UsarUnAnguloPorMes,
    Paneles_Angulos);
  res := fPaneles.ShowModal;
  if res = 1 then
  begin
    fPaneles.GetDatos(
      nPaneles,
      Paneles_PotenciaPicoPorPanel,
      Paneles_InclinacionDePaneles,
      Paneles_UsarUnAnguloPorMes,
      Paneles_Angulos);

    actualizarResumenPaneles;
    SetModificado;
  end;
  fPaneles.Free;
end;

procedure TfSimSolar.Button4Click(Sender: TObject);
var
  fBaterias: TfBaterias;
  res: integer;
begin
  fBaterias := TfBaterias.Create(Self);
  fBaterias.SetDatos(
    CapacidadDeBateria, // Ah @ 100h
    Bat_CT, // coeficiente de variación de la capacidad con la temperatura
    Bat_TN, // temperatura nominal.
    Bat_ID, // [A] corriente máxima de descarga
    Bat_IR, // [A] corriente máxima de recarga
    Bat_VN, // [V] tensión nominal de la batería.
    PPCB, // Profundidad Permitida de uso de Capacidad de la Batería.
    Bat_rc, // rendimiento de carga
    Bat_x1, // profundidad de descarga del punto PC2
    Bat_y1, // número de ciclos del punto PC1
    Bat_x2, // profundidad de descarga del punto PC2
    Bat_y2 // número de ciclos del punto PC2
    );
  res := fBaterias.ShowModal;
  if res = 1 then
  begin
    fBaterias.GetDatos(
      CapacidadDeBateria, // Ah @ 100h
      Bat_CT, // coeficiente de variación de la capacidad con la temperatura
      Bat_TN, // temperatura nominal.
      Bat_ID, // [A] corriente máxima de descarga
      Bat_IR, // [A] corriente máxima de recarga
      Bat_VN, // [V] tensión nominal de la batería.
      PPCB, // Profundidad Permitida de uso de Capacidad de la Batería.
      Bat_rc, // rendimiento de carga
      Bat_x1, // profundidad de descarga del punto PC2
      Bat_y1, // número de ciclos del punto PC1
      Bat_x2, // profundidad de descarga del punto PC2
      Bat_y2 // número de ciclos del punto PC2
      );

    actualizarResumenBaterias;
    SetModificado;
  end;
  fBaterias.Free;
end;


procedure TfSimSolar.Button5Click(Sender: TObject);
begin
  gbResultados.Visible := False;
  Button1.Enabled := False;
  Button2.Enabled := False;
  Button3.Enabled := False;
  Button4.Enabled := False;
  Button5.Enabled := False;
  Button6.Enabled := False;
  self.ProgressBar1.Max := PeriodosTotales;
  randseed := 31;

//RCH OJO;   fddp.FijarSemilla(31);
  Ejecutar;
  gbResultados.Visible := True;
  Button1.Enabled := True;
  Button2.Enabled := True;
  Button3.Enabled := True;
  Button4.Enabled := True;
  Button5.Enabled := True;
  Button6.Enabled := True;
end;

procedure TfSimSolar.Button6Click(Sender: TObject);
var
  fSimulacion: TfSimulacion;
  res: integer;
begin
  fSimulacion := TfSimulacion.Create(Self);
  fSimulacion.SetDatos(PeriodosTotales, DiasPermitidosDeDeficit,
    usarModeloCEGHSolar);
  res := fSimulacion.ShowModal;
  if res = 1 then
  begin
    fSimulacion.GetDatos(PeriodosTotales, DiasPermitidosDeDeficit,
      usarModeloCEGHSolar);
    actualizarResumenSimulacion;
    SetModificado;
  end;
  fSimulacion.Free;
end;

procedure TfSimSolar.Button7Click(Sender: TObject);
begin
  htmlverdoc('');
end;

procedure TfSimSolar.Button8Click(Sender: TObject);
begin
  htmlverdoc('resultados');
end;

function TfSimSolar.Cancelar_GuardarSiNo: boolean;
var
  k: integer;

begin
  k := application.messagebox('Atención!', 'Desea guardar el archivo actual?',
    MB_YESNOCANCEL);
  case k of
    idYes:
    begin
      Self.rwEscenario(1);
      resetModificado;
      Result := False;
    end;
    idNo:
    begin
      Result := False;
    end;
    idCancel:
    begin
      Result := True;
    end;
    else
      Result := True;
  end;

end;


procedure TfSimSolar.Contents1Click(Sender: TObject);
begin
  htmlverdoc('manualdelusuario');
end;


procedure TfSimSolar.FormCloseQuery(Sender: TObject; var CanClose: boolean);
var
  k: integer;

begin
  CanClose := True;
  if not xModificado then
    exit;
  k := application.messagebox(
    'Hay cambios sin guardar. ¿Desea guardar los cambios antes de salir?',
    'Confirmación', MB_YESNOCANCEL);
  case k of
    idYes:
    begin
      if archi = '' then
      begin
        Guardar1Click(self);
        modalresult := 2;
        if archi = '' then  // quiere decir que no guardó
          canclose := False;
      end
      else
        modalresult := 1; // salir y guardar
    end;
    idNo: modalresult := 2; // salir pero no guardar
    idCancel: CanClose := False;
    else
      Canclose := False;
  end;
end;

procedure TfSimSolar.FormCreate(Sender: TObject);
begin
  SysUtils.DecimalSeparator := '.';
  Nuevo1Click(Self);
  self.resetModificado;


  uhtmlverdoc.apphandle := self.Handle;
end;


procedure ImprimirFecha(var alp); far;
begin
  ImpFecha := True;
end;




procedure TfSimSolar.Guardar1Click(Sender: TObject);
begin
  if openDialog1.Execute then
  begin
    archi := opendialog1.FileName;
    self.rwEscenario(1);
    resetModificado;
    carpetaDeLaCorrida := extractFileDir(archi);
    chdir(carpetaDeLaCorrida);
  end;
end;


procedure TfSimSolar.rwf(var x: NReal);
begin
  case RW_modo of
    0: readln(RW_f, x);
    1: writeln(RW_f, x);
  end;
end;


procedure TfSimSolar.rwi(var x: integer);
begin
  case RW_modo of
    0: readln(RW_f, x);
    1: writeln(RW_f, x);
  end;
end;

procedure TfSimSolar.rwb(var x: boolean);
var
  i: integer;
begin
  case RW_modo of
    0:
    begin
      rwi(i);
      x := i <> 0;
    end;
    1:
    begin
      if x then
        i := 1
      else
        i := 0;
      rwi(i);
    end;
  end;
end;

(*
procedure TfSimSolar.rws( var f: textfile; var x: integer; modo: integer );
begin
  case modo of
    0: readln( f, x );
    1: writeln( f, x );
  end;
end;
  *)

procedure TfSimSolar.rwEscenario(modo: integer);
var
  k: integer;
  kmes: T_Mes;

begin
  RW_modo := modo;
  assignfile(RW_f, archi);
  case modo of
    0: reset(RW_f);
    1: rewrite(RW_f);
  end;
  rwf(Latitud);
  rwf(Longitud);
  for k := 0 to 23 do
    rwf(PerfilCDC[k]);

  for kmes := enero to diciembre do
    rwf(EstacionalCDC[kmes]);
  rwf(CapacidadDeBateria);
  rwf(Bat_CT);
  rwf(Bat_TN);
  rwf(Bat_ID);
  rwf(Bat_IR);
  rwf(Bat_VN);
  rwf(PPCB);
  rwf(Bat_rc); { rendimiento de carga }
  rwf(Bat_x1);
  rwf(Bat_y1);
  rwf(Bat_x2);
  rwf(Bat_y2);

  rwi(NPaneles);
  rwf(Paneles_PotenciaPicoPorPanel);
  rwf(Paneles_InclinacionDePaneles);
  rwi(Paneles_UsarUnAnguloPorMes);
  for k := 1 to 12 do
    rwf(NReal(Paneles_Angulos[T_Mes(k - 1)]));

  rwi(PeriodosTotales);
  rwi(DiasPermitidosDeDeficit);


  try
    rwb(usarModeloCEGHSolar);
  except
    usarModeloCEGHSolar := True;
  end;
  closefile(RW_f);
end;

function GetExeDir: string;
var
  s: string;
begin
  s := ParamStr(0);
  s := ExtractFileDir(s);
  Result := s;
end;


procedure ALInicio; far;

label
  FinPrint;

begin

  // LeerEscenario

  VentanaDeDeficit := 2 * DiasPermitidosDeDeficit;
  VentanaDeExcesos := VentanaDeDeficit;

  NumeroDePanelesDe48W := NPaneles * Paneles_PotenciaPicoPorPanel / 48;
  auto := False;


(******
  {$IFDEF PANLOG}
  assign(fbat, 'CapBat.log');
  rewrite(fbat);
  {$ENDIF}
******)

  Latido := NucleoT.Tic_Hora;
  PasoDeTiempo := 3600;

  RandSeed := 31;
  contador := 0;
  //  fdsol_ktcegh.test;

  if usarModeloCEGHSolar then
    xF := TFDSol_ktcegh.Create('Sol', Latitud, Longitud,
      GetExeDir + '\' + archiDatosSintetizador)
  else
    xF := FuenteAnilloRuidoso.Create('Sol', Latitud, Longitud);


  if Paneles_UsarUnAnguloPorMes = 0 then
    xpanel := TPanelSolar.Create('Paneles', NumeroDePanelesDe48W *
      0.36, {  rea en m2 del panel }
      xF, { Fuente de energ¡a solar }
      Paneles_InclinacionDePaneles, NumerodePanelesDe48W * 48)
  else
    xpanel := TPanelSolar.Create('Paneles', NumeroDePanelesDe48W *
      0.36, {  rea en m2 del panel }
      xF, { Fuente de energ¡a solar }
      Paneles_Angulos, NumerodePanelesDe48W * 48);



  Quantum := 0;
  Demanda := TDemHT.Create('Demanda', PerfilCDC, EstacionalCDC,
    1.0 / 1000.0, // para pasarlo a kW
    8);
  Demanda.AcumQ(Quantum);

  Bateria := TBateriaHD.Create('Batería', CapacidadDeBateria, {Ah}
    Bat_TN,  {TN}
    Bat_CT, {CT}
    Bat_IR,  {ImaxR}
    Bat_ID,   {ImaxD}
    Bat_VN,  {VN}
    PPCB, Bat_rc, bat_x1, bat_x2, bat_y1, bat_y2);



  e1 := TEvaluador.Create(8, 8, Deficit, Quantum * VentanaDeDeficit, VentanaDeDeficit);
  e2 := TEvaluador.Create(1, 4, Exceso, 20 * Quantum * VentanaDeExcesos, VentanaDeExcesos);
  histoAniosVidaBat := THistograma.Create(0, 20, 100);

  NucleoT.CadaDia.AgregarProcTarea(@ImprimirFecha, VACIA);



  NucleoT.CadaHora.AgregarProcTarea(@Gestion, VACIA);
  NucleoT.CadaAnio.AgregarProcTarea(@CadaPeriodoDeEvaluacion, VACIA);


  FinPrint: ;

end;

procedure AlFinal; far;
var
  fout: Text;
  k: T_Mes;
  whdia: NReal;
  //  histogs: Text;
begin

  Assign(fout, 'simsolar-sal2.xlt');
  {$I-}
  append(fout);
  {$I+}
  if ioresult <> 0 then
  begin
    rewrite(fout);

    Write(fout, 'Fecha');
    Write(fout, #9, 'CapBat[Ah]');
    Write(fout, #9, 'PPCB[p.u.]');
    Write(fout, #9, 'nP48W[u]');
    Write(fout, #9, 'betaMín[º]');
    Write(fout, #9, 'betaMáx[º]');
    Write(fout, #9, 'ddd-pne90%');
    Write(fout, #9, 'ddd-vm');
    Write(fout, #9, 'ddd-pne10%');
    Write(fout, #9, 'Dem.Prom. [Wh/día]');
    Write(fout, #9, 'dde-pe90%');
    Write(fout, #9, 'dde-vm');
    Write(fout, #9, 'dde-pe10%');
    Write(fout, #9, 'Años de vida de la batería');
    for k := enero to diciembre do
      Write(fout, #9, '[Wh/día] ' + IntToStr(Ord(k) + 1));
    for k := enero to diciembre do
      Write(fout, #9, '[º]' + IntToStr(Ord(k) + 1));
    writeln(fout);
  end;

  Write(fout, DateTimeToStr(now));
  Write(fout, #9, CapacidadDeBateria: 6: 2);
  Write(fout, #9, PPCB: 6: 2);
  Write(fout, #9, NumeroDePanelesDe48W: 6: 2);

  Write(fout, #9, minimo(paneles_Angulos): 6: 2);
  Write(fout, #9, maximo(paneles_Angulos): 6: 2);

  Write(fout, #9, e1.histo.xArea(0.9) / Quantum: 8: 2);
  Write(fout, #9, e1.histo.ValorMedio / Quantum: 8: 2);
  Write(fout, #9, e1.histo.xArea(0.1) / Quantum: 8: 2);
  Write(fout, #9, (Quantum / 3600.0): 12: 2);
  Write(fout, #9, e2.histo.xArea(0.1) / Quantum: 8: 2);
  Write(fout, #9, e2.histo.ValorMedio / Quantum: 8: 2);
  Write(fout, #9, e2.histo.xArea(0.9) / Quantum: 8: 2);
  Write(fout, #9, FloatToStrF(histoAniosVidaBat.ValorMedio, ffFixed, 6, 1));

  whdia := suma(perfilCDC);
  for k := enero to diciembre do
    Write(fout, #9, FloatToStrF((EstacionalCDC[k] * whdia), ffFixed, 12, 2));

  for k := enero to diciembre do
    Write(fout, #9, FloatToStrF(Paneles_Angulos[k], ffFixed, 6, 1));


  writeln(fout, '');
  Close(fout);

  fSimSolar.eDDDEsperados.Text :=
    FloatToStrF(e1.histo.ValorMedio / Quantum, ffFixed, 6, 1);
  fSimSolar.eDDDpne90.Text := FloatToStrF(e1.histo.xArea(0.9) / Quantum, ffFixed, 6, 1);
  fSimSolar.eDDEEsperados.Text :=
    FloatToStrF(e2.histo.ValorMedio / Quantum, ffFixed, 6, 1);
  fSimSolar.eDDEpe90.Text := FloatToStrF(e2.histo.xArea(0.1) / Quantum, ffFixed, 6, 1);
  fSimSolar.eBatDeg_med.Text := FloatToStrF(histoAniosVidaBat.ValorMedio, ffFixed, 6, 1);

{  Assign(histogs, 'histos.txt');
  rewrite(histogs);
  writeln(histogs, 'Dias de Deficit');
  e1.histo.WriteTxt(histogs);
  Writeln(histogs);
  writeln(histogs, 'Dias de Exceso');
  e2.histo.WriteTxt(histogs);
  close(histogs);}

  fSimSolar.lblEnergiaDelDiaMedio.Caption :=
    'Energía del día medio [Wh]:' + FloatToStrF(Quantum / 3600, ffFixed, 6, 1);

  histoAniosVidaBat.Free;
  e2.Free;
  e1.Free;
  Bateria.Free;
  Demanda.Free;
  xpanel.Free;
  xf.Free;
end;


var
  tmpsal: textfile;

procedure Pesca; far;
begin

  DiasDeDeficitResultante := e1.GetValor / Quantum;
  DiasDeExcesoResultante := e2.GetValor / Quantum;
  writeln(tmpsal, DiasDeDeficitResultante, #9, DiasDeExcesoResultante);

  fSimSolar.ProgressBar1.Position := NumeroDePeriodo + 1;
  //  if NumeroDePeriodo+1 < PeriodosTotales then


  e1.evaluar;
  e2.evaluar;

  if Bateria.SumaDegradante >= Bateria.A_Degradante then
  begin
    // hay que cambiar la batería

    histoAniosVidaBat.Anotar(Bateria.NHorasEnSumaDegradante /
      Bateria.SumaDegradante * Bateria.A_Degradante / 365.0 / 24);
    Bateria.LimpiarSumaDegradante;
  end;
  Bateria.Ciclado.Clear;

end;


procedure TfSimSolar.Ejecutar;
begin
  try
    assignfile(tmpsal, 'ddye.xlt');
    rewrite(tmpsal);
    writeln(tmpsal,
      'Déficit y exceso de energía expresados en días equivalentes de energía.');
    writeln(tmpsal, 'Déficit', #9, 'Exceso');

    ImpFecha := False;
    Proc_Arrancar := AlInicio;
    Proc_Pescar := Pesca;
    Proc_Finalizar := Alfinal;

    Simular;

    closefile(tmpsal);


  except
    on E: Exception do
      ShowMessage(E.ClassName + ': ' + E.Message);
  end;
end;

procedure TfSimSolar.Leer1Click(Sender: TObject);
begin
  if openDialog1.Execute then
  begin
    archi := opendialog1.FileName;
    carpetaDeLaCorrida := extractFileDir(archi);
    chdir(carpetaDeLaCorrida);
    Self.rwEscenario(0);
    self.ActualizarResumenUbicacion;
    self.ActualizarResumenCarga;
    self.ActualizarResumenPaneles;
    self.ActualizarResumenBaterias;
    self.ActualizarResumenSimulacion;
    resetModificado;
    Self.gbResultados.Visible := False;
  end;
end;

procedure TfSimSolar.Nuevo1Click(Sender: TObject);
var
  k: integer;
  mes: T_Mes;
begin
  if xmodificado then
    if Cancelar_GuardarSiNo then
      exit;

  Latitud := 31.7;
  Longitud := 56;

  archi := '';
  resetModificado;

  for k := 0 to 23 do
    PerfilCDC[k] := 0;

  PerfilCDC[8] := 3.0;
  PerfilCDC[9] := 3.0;
  PerfilCDC[11] := 13.0;
  PerfilCDC[12] := 73.0;
  PerfilCDC[13] := 13.0;
  PerfilCDC[14] := 13.0;
  PerfilCDC[17] := 10.0;
  PerfilCDC[18] := 19.00;
  PerfilCDC[19] := 9.0;
  PerfilCDC[10] := 9.0;

  EDiariaWh := 0;
  for k := 0 to 23 do
    EDiariaWh := EDiariaWh + PerfilCDC[k];


  for mes := Enero to Marzo do
    EstacionalCDC[mes] := 1.2;

  for mes := Abril to Setiembre do
    EstacionalCDC[mes] := 1.0;

  for mes := Octubre to Diciembre do
    EstacionalCDC[mes] := 1.2;

  // Valores del banco de baterías por defecto
  CapacidadDeBateria := 150.0; // Ah
  Bat_CT := 0.001; // coeficiente de variación de la capacidad con la temperatura
  Bat_TN := 25.0; // temperatura nominal.
  Bat_ID := 30.0; // [A] corriente máxima de descarga
  Bat_IR := 20.0; // [A] corriente máxima de recarga
  Bat_VN := 12.0; // [V] tensión nominal de la batería.
  PPCB := 0.3; // Profundidad Permitida de uso de Capacidad de la Batería.
  Bat_rc := 0.92; // rendimiento de carga
  Bat_x1 := 0.3; // profundidad de descarga del punto PC1
  Bat_y1 := 1200.0; // número de ciclos del punto PC1
  Bat_x2 := 0.5; // profundidad de descarga del punto PC2
  Bat_y2 := 200; // número de ciclos del punto PC2

(* Los puntos PC1 y PC2 definen la característica de vida útil
de la batería en función de la cantidad de ciclos de carga y descarga
que soporta según la profundidad de los ciclos. *)

  NPaneles := 1;
  Paneles_PotenciaPicoPorPanel := 48;
  Paneles_InclinacionDePaneles := 50;
  Paneles_UsarUnAnguloPorMes := 0;
  for k := 1 to 12 do
    Paneles_Angulos[T_Mes(k - 1)] := Paneles_InclinacionDePaneles;


  PeriodosTotales := 100;
  //  inc(PeriodosTotales);
  DiasPermitidosDeDeficit := 10;

  usarModeloCEGHSolar := True;

  setModificado;

  self.ActualizarResumenUbicacion;
  self.ActualizarResumenCarga;
  self.ActualizarResumenPaneles;
  self.ActualizarResumenBaterias;
  self.ActualizarResumenSimulacion;

end;

end.
