unit ubiomasaembalsable;

{$mode delphi}


interface

uses
  Math,
  SysUtils, Classes, xmatdefs, uGTer, uNodos,
  uglobs,
  usimplex,
  ufichasLPD,
  ufechas,
  ucosa, ucosaConNombre,
  uranddispos,
  uconstantesSimSEE,
  uFuentesAleatorias, uActores, uEstados;

resourcestring
  rsGeneradorBiomasaEmbalsable =
    'Generador de Biomasa Embalsable';


type

  { TFichaBiomasaEmbalsable }

  TFichaBiomasaEmbalsable = class(TFichaLPD)
  public
    fd: NReal;  // factor de disponibilidad fortuita
    PMax: NReal;// MW máximos de una unidad generadora
    PEC: NReal; // [USD/MWh] Pago por Energía Comprometida
    PEE: NReal; // [USD/MWh] Pago por Energía Entregada (o vertida TOP)
    PEX: NREal; // [USD/MWh] Premio por Externalidades.
    TMR: NReal; // Tiempo Medio de Reparción (horas)
    cvea_impuesto: NReal; // [USD/MWh] valor de la energía almacenada
    // si flg_imponer_cvea = true.
    a_PEC, b_PEC, c_PEC, d_PEC: NReal;  // poderadores indexación PEC
    a_PEE, b_PEE, c_PEE, d_PEE: NReal;  // poderadores indexación PEE
    a_PEX, b_PEX, c_PEX, d_PEX: NReal;  // poderadores indexación PEX

    constructor Create(capa: integer; fecha: TFecha; periodicidad: TPeriodicidad;
      fd, TMR: NReal; PMax: NReal; PEC, PEE, PEX, cvea_impuesto: NReal;
      a_PEC, b_PEC, c_PEC, d_PEC: NReal;  // poderadores indexación PEC
      a_PEE, b_PEE, c_PEE, d_PEE: NReal;  // poderadores indexación PEE
      a_PEX, b_PEX, c_PEX, d_PEX: NReal  // poderadores indexación PEX
      );

    function Rec: TCosa_RecLnk; override;
    procedure BeforeRead(version, id_hilo: integer); override;
    procedure AfterRead(f:TArchiTexto); override;

    procedure generarLineaResumen(var archi: TextFile); override;
    function infoAd_: string; override;
    procedure Free; override;

  end;

  { TBiomasaEmbalsable }

  TBiomasaEmbalsable = class(TGTer)
  public
    ECA_DOPTOP: NReal; // Energía comprometida ANUAL
    meses_TOP: integer; // meses máximo que se mantiene el compromiso por energía.
    NPuntos_EA: integer; // Cantidad de puntos de discretización de X_EA
    X_EA_inicial: NReal;  // Valor del estado al inicio.
    ixA_fuente: TFuenteAleatoria;
    ixA_Borne_nombre: string;
    ixB_fuente: TFuenteAleatoria;
    ixB_Borne_nombre: string;
    ixC_fuente: TFuenteAleatoria;
    ixC_Borne_nombre: string;
    ixD_fuente: TFuenteAleatoria;
    ixD_Borne_nombre: string;
    flg_imponer_cvea: boolean;


    ixA_Borne_numero: integer;
    ixB_Borne_numero: integer;
    ixC_Borne_numero: integer;
    ixD_Borne_numero: integer;

    pa: TFichaBiomasaEmbalsable;

    PEC, PEE, PEX: NReal; // USD/MWh indexados.
    cvea_impuesto: NReal; // USD/MWh indexado.

    ecp: NReal; // energía comprometida del paso.
    edp: NReal; // energía despachable del paso. PN * HorasDelPaso
    EA_Max: NReal; // Volumen máximo de energía almacenada;

    // Variable de estado  Energia Almaceanda MWh
    X_EA: NReal;
    Xs_EA: NReal;

    PNominalPorUnidad: NReal; // es pa.PMax salvo que sea sin sorteos
    NMaquinasDisponibles: integer; // maximo de acople
    NMaquinasDespachables: integer; // Para cuantas da la energía del paso

    // -dCF/dX
    cvea: NReal;

    // REsultados del paso
    NMaquinasDespachadas: integer;
    EnergiaVertida_TOP, EnergiaDespachada_DOP: NReal;
    Pagos_TOP: NReal;

    constructor Create(capa: integer; nombre: string; nacimiento, muerte: TFecha;
      lpdUnidades, lpd: TFichasLPD; nodo: TNodo;
  flg_CalcularGradienteDeInversion: boolean; ECA_DOPTOP: NReal;
  meses_TOP: integer; NPuntosEA: integer; X_EA_Inicial: NReal;
  ixA_fuente: TFuenteAleatoria; ixA_Borne_nombre: string;
  ixB_fuente: TFuenteAleatoria; ixB_Borne_nombre: string;
  ixC_fuente: TFuenteAleatoria; ixC_Borne_nombre: string;
  ixD_fuente: TFuenteAleatoria; ixD_Borne_nombre: string;
  imponer_cvea: boolean; TonCO2xMWh: NReal; LowCostMustRun,
  CleanDevelopmentMechanism: boolean; xFuenteIdxP: TFuenteAleatoria;
  xBorneIdxP: string); reintroduce;

    function Rec: TCosa_RecLnk; override;
    procedure BeforeRead(version, id_hilo: integer); override;
    procedure AfterRead(f:TArchiTexto); override;

    procedure PrepararMemoria(Catalogo: TCatalogoReferencias; globs: TGlobs); override;
    procedure RegistrarParametrosDinamicos(CatalogoReferencias: TCatalogoReferencias);
      override;

    function PotenciaFirme: NReal; override;

    function InfoAd_: string; override;
    class function DescClase: string; override;

    procedure PosicionarseEnEstrellita; override;
    procedure ActualizarEstadoGlobal(flg_Xs: boolean); override;

    procedure Sim_Cronica_Inicio; override;
    procedure SorteosDelPaso(sortear: boolean); override;
    procedure PrepararPaso_ps; override;

    procedure EvolucionarEstado; override;

    //      procedure Sim_Cronica_Fin; override;

    procedure opt_nvers(var ivar, ivae, ires: integer); override;
    procedure optx_nvxs(var ixr, ixd, iauxNReal, iauxInt: integer); override;
    procedure optx_RegistrarVariablesDeEstado(adminEstados: TAdminEstados);
      override;

    procedure opt_cargue(s: TSimplex); override;
    procedure opt_fijarRestriccionesDeCaja(s: TSimplex); override;
    procedure opt_leerSolucion(s: TSimplex); override;

    function getNombreVar(ivar: integer; var nombre: string): boolean; override;
    function getNombreRes(ires: integer; var nombre: string): boolean; override;

    procedure Free; override;

    procedure PubliVars; override;
    procedure dump_Variables(var f: TextFile; charIndentacion: char); override;

    class function TipoFichaLPD: TClaseDeFichaLPD; override;

  end;

procedure cambioFichaPD_TBiomasaEmbalsable(actor: TActor);
procedure cambioFichaUnidades_TBiomasaEmbalsable(actor: TActor);

procedure AlInicio;
procedure AlFinal;

implementation


//----------------------------------
// Métodos de TFichaBiomasaEmbalsable
//==================================
constructor TFichaBiomasaEmbalsable.Create(capa: integer; fecha: TFecha;
  periodicidad: TPeriodicidad; fd, TMR: NReal; PMax: NReal;
  PEC, PEE, PEX, cvea_impuesto: NReal; a_PEC, b_PEC, c_PEC, d_PEC: NReal;
  // poderadores indexación PEC
  a_PEE, b_PEE, c_PEE, d_PEE: NReal;  // poderadores indexación PEE
  a_PEX, b_PEX, c_PEX, d_PEX: NReal  // poderadores indexación PEX
  );
begin
  inherited Create(capa, fecha, periodicidad);
  self.fd := fd;
  self.TMR := TMR;
  self.PMax := PMax;
  self.PEC := PEC;
  self.PEE := PEE;
  self.PEX := PEX;
  self.cvea_impuesto := cvea_impuesto;
  self.a_PEC := a_PEC;
  self.b_PEC := b_PEC;
  self.c_PEC := c_PEC;
  self.d_PEC := d_PEC;

  self.a_PEE := a_PEE;
  self.b_PEE := b_PEE;
  self.c_PEE := c_PEE;
  self.d_PEE := d_PEE;

  self.a_PEX := a_PEX;
  self.b_PEX := b_PEX;
  self.c_PEX := c_PEX;
  self.d_PEX := d_PEX;

end;

function TFichaBiomasaEmbalsable.Rec: TCosa_RecLnk;
begin
  Result:=inherited Rec;
  Result.addCampoDef('fd', fd);
  Result.addCampoDef('TMR', TMR);
  Result.addCampoDef('PMax', PMax);
  Result.addCampoDef('PEC', PEC);
  Result.addCampoDef('PEE', PEE);
  Result.addCampoDef('PEX', PEX, 123 );
  Result.addCampoDef('cvea_impuesto', cvea_impuesto, 106 );

  Result.addCampoDef('a_PEC', a_PEC, 123, 0, '1');
  Result.addCampoDef('b_PEC', b_PEC, 123);
  Result.addCampoDef('c_PEC', c_PEC, 123);
  Result.addCampoDef('d_PEC', d_PEC, 123);

  Result.addCampoDef('a_PEE', a_PEE, 123);
  Result.addCampoDef('b_PEE', b_PEE, 123, 0, '1');
  Result.addCampoDef('c_PEE', c_PEE, 123);
  Result.addCampoDef('d_PEE', d_PEE, 123);

  Result.addCampoDef('a_PEX', a_PEX, 123);
  Result.addCampoDef('b_PEX', b_PEX, 123);
  Result.addCampoDef('c_PEX', c_PEX, 123, 0, '1');
  Result.addCampoDef('d_PEX', d_PEX, 123);
end;

procedure TFichaBiomasaEmbalsable.BeforeRead(version, id_hilo: integer);
begin
  inherited BeforeRead(version, id_hilo);
end;

procedure TFichaBiomasaEmbalsable.AfterRead(f:TArchiTexto);
begin
  inherited AfterRead(f);
end;


procedure TFichaBiomasaEmbalsable.generarLineaResumen(var archi: TextFile);
begin
  Write(archi, '-', #9,       //PMín
    FloatToStrF(PMax, formatoReales, 8, 1), #9,  //PMáx
    '-', #9,       //CV_Mín
    FloatToStrF(PEC + PEE, formatoReales, 8, 2), #9,    //CV_Medio
    FloatToStrF(PEE, formatoReales, 8, 2), #9,    //CV_Incremental
    FloatToStrF(fd, formatoReales, 8, 2), #9,  //FDisp
    '-', #9,       //Costo Arranque
    '-', #9,       //Costo Parada
    '-', #9,       //mínNPasosOn
    '-', #9,       //mínNPasosOff
    '-', #9,       //desiciónPasosOnPorCiclo
    '-', #9,       //desiciónPasosOffPorCiclo
    '-', #9,       //costoPorCicloOn
    '-', #9);      //costoPorCicloOff
end;

function TFichaBiomasaEmbalsable.infoAd_: string;
begin
  Result := 'PMáx= ' + FloatToStrF(PMax, ffGeneral, 10, 1) + ' MW, ' +
    'PE= ' + FloatToStrF(PEC + PEE, ffGeneral, 10, 1) + ' USD/MWh, ' +
    'fd= ' + FloatToStrF(fd, ffGeneral, 10, 2) + ' p.u., ' + 'TMR= ' +
    FloatToStrF(TMR, ffGeneral, 10, 1) + ' hs';
end;

procedure TFichaBiomasaEmbalsable.Free;
begin
  inherited Free;
end;


//-----------------------------
// Métodos de TBiomasaEmbalsable
//=============================
procedure TBiomasaEmbalsable.dump_Variables(var f: TextFile; charIndentacion: char);
begin
  inherited dump_Variables(f, charIndentacion);
  writeln(f, charIndentacion, 'PEC[USD/MWh]= ', FloatToStrF(PEC, ffFixed, 10, 3));
  writeln(f, charIndentacion, 'PMAx[MW]= ', FloatToStrF(pa.PMax, ffFixed, 10, 3));
  writeln(f, charIndentacion, 'X_EA= ', X_EA);
  writeln(f);
end;

class function TBiomasaEmbalsable.TipoFichaLPD: TClaseDeFichaLPD;
begin
  Result := TFichaBiomasaEmbalsable;
end;


constructor TBiomasaEmbalsable.Create(capa: integer; nombre: string;
  nacimiento, muerte: TFecha; lpdUnidades, lpd: TFichasLPD; nodo: TNodo;
  flg_CalcularGradienteDeInversion: boolean; ECA_DOPTOP: NReal;
  meses_TOP: integer; NPuntosEA: integer; X_EA_Inicial: NReal;
  ixA_fuente: TFuenteAleatoria; ixA_Borne_nombre: string;
  ixB_fuente: TFuenteAleatoria; ixB_Borne_nombre: string;
  ixC_fuente: TFuenteAleatoria; ixC_Borne_nombre: string;
  ixD_fuente: TFuenteAleatoria; ixD_Borne_nombre: string; imponer_cvea: boolean;
  TonCO2xMWh: NReal; LowCostMustRun, CleanDevelopmentMechanism: boolean;
  xFuenteIdxP: TFuenteAleatoria; xBorneIdxP: string );
begin
  inherited Create(capa, nombre, nacimiento, muerte, lpdUnidades, lpd, nodo,
    flg_CalcularGradienteDeInversion,
    TonCO2xMWh, LowCostMustRun, CleanDevelopmentMechanism,
    xFuenteIdxP, xBorneIdxP );
  P := nil;
  self.ECA_DOPTOP := ECA_DOPTOP;
  self.meses_TOP := meses_TOP;
  self.NPuntos_EA := NPuntos_EA;
  self.X_EA_Inicial := X_EA_Inicial;

  self.ixA_fuente := ixA_fuente;
  self.ixA_Borne_nombre := ixA_Borne_nombre;
  self.ixA_Borne_numero := -1;

  self.ixB_fuente := ixB_fuente;
  self.ixB_Borne_nombre := ixB_Borne_nombre;
  self.ixB_Borne_numero := -1;

  self.ixC_fuente := ixC_fuente;
  self.ixC_Borne_nombre := ixC_Borne_nombre;
  self.ixC_Borne_numero := -1;

  self.ixD_fuente := ixD_fuente;
  self.ixD_Borne_nombre := ixD_Borne_nombre;
  self.ixD_Borne_numero := -1;

  self.flg_imponer_cvea := imponer_cvea;
end;

function TBiomasaEmbalsable.Rec: TCosa_RecLnk;
begin
  Result:=inherited Rec;
  Result.addCampoDef('ECA', ECA_DOPTOP, 0, 123 );
  Result.addCampoDef('ECA_DOPTOP', ECA_DOPTOP, 123 );
  Result.addCampoDef('NPuntos_ECA', NPuntos_EA, 0, 109);
  Result.addCampoDef('meses_TOP', meses_TOP, 109,0, '12');
  Result.addCampoDef('NPuntos_EA', NPuntos_EA, 109 );
  Result.addCampoDef('X_EA_inicial', X_EA_inicial);
  Result.addCampoDef_ref('ixPEC_fuente', TCosa(ixA_fuente), self, 0, 123 );
  Result.addCampoDef('ixPEC_Borne_nombre', ixA_Borne_nombre, 0, 123);
  Result.addCampoDef_ref('ixPEE_fuente', TCosa(ixB_fuente), self, 0, 123);
  Result.addCampoDef('ixPEE_Borne_nombre', ixB_Borne_nombre, 0, 123);
  Result.addCampoDef_ref('ixA_fuente', TCosa(ixA_fuente), self, 123 );
  Result.addCampoDef('ixA_Borne_nombre', ixA_Borne_nombre, 123 );
  Result.addCampoDef_ref('ixB_fuente', TCosa(ixB_fuente), self, 123);
  Result.addCampoDef('ixB_Borne_nombre', ixB_Borne_nombre, 123);
  Result.addCampoDef_ref('ixC_fuente', TCosa(ixC_fuente), self, 123);
  Result.addCampoDef('ixC_Borne_nombre', ixC_Borne_nombre, 123);
  Result.addCampoDef_ref('ixD_fuente', TCosa(ixD_fuente), self, 123);
  Result.addCampoDef('ixD_Borne_nombre', ixD_Borne_nombre, 123);
  Result.addCampoDef('flg_imponer_cvea', flg_imponer_cvea, 106 )
end;

procedure TBiomasaEmbalsable.BeforeRead(version, id_hilo: integer);
begin
  inherited BeforeRead(version, id_hilo);
end;

procedure TBiomasaEmbalsable.AfterRead(f:TArchiTexto);
begin
  inherited AfterRead(f);
  P := nil;
  pa := nil;
  nodo := nil;
  if f.version < 123 then
  begin
    ixC_fuente := nil;
    ixC_Borne_nombre := '';
    ixC_Borne_numero := -1;
    ixD_fuente := nil;
    ixD_Borne_nombre := '';
    ixD_Borne_numero := -1;
  end;
end;

procedure TBiomasaEmbalsable.PrepararMemoria(Catalogo: TCatalogoReferencias;
  globs: TGlobs);
begin
  inherited prepararMemoria(Catalogo, globs);
  if ixA_fuente <> nil then
    ixA_Borne_numero := ixA_fuente.IdBorne(ixA_Borne_nombre);
  if ixB_fuente <> nil then
    ixB_Borne_numero := ixB_fuente.IdBorne(ixB_Borne_nombre);
  if ixC_fuente <> nil then
    ixC_Borne_numero := ixC_fuente.IdBorne(ixC_Borne_nombre);
  if ixD_fuente <> nil then
    ixD_Borne_numero := ixD_fuente.IdBorne(ixD_Borne_nombre);
end;

procedure TBiomasaEmbalsable.RegistrarParametrosDinamicos(
  CatalogoReferencias: TCatalogoReferencias);
begin
  uActores.procCambioFichaUnidades := @cambioFichaUnidades_TBiomasaEmbalsable;
  inherited registrarParametrosDinamicos(CatalogoReferencias);
  uActores.procCambioFichaUnidades := nil;
  lpd.expandirFichas(CatalogoReferencias, globs);
  lpd.RegistrarFichasAActualizar(Self, globs.ActualizadorLPD, @pA,
    nil, @cambioFichaPD_TBiomasaEmbalsable);
end;

function TBiomasaEmbalsable.PotenciaFirme: NReal;
begin
  Result := (paUnidades.nUnidades_Operativas[0]) * pa.PMax * pa.fd;
end;

function TBiomasaEmbalsable.InfoAd_: string;
begin
  Result := '';
end;

class function TBiomasaEmbalsable.DescClase: string;
begin
  Result := rsGeneradorBiomasaEmbalsable;
end;

procedure TBiomasaEmbalsable.PosicionarseEnEstrellita;
begin
  if not flg_imponer_cvea then
    X_EA := globs.CF.xr[ixr]
  else
    X_EA := ECA_DOPTOP / 2.0;
end;

procedure TBiomasaEmbalsable.ActualizarEstadoGlobal(flg_Xs: boolean);
begin
  if not flg_imponer_cvea then
    globs.CF.xr[ixr] := X_EA;
end;

procedure TBiomasaEmbalsable.Sim_Cronica_Inicio;
begin
  inherited Sim_Cronica_Inicio;
  X_EA := X_EA_inicial;
end;

procedure TBiomasaEmbalsable.SorteosDelPaso(sortear: boolean);
begin
  if hayForzamientos or globs.ObligarDisponibilidad_1_ then
  begin
    NMaquinasDisponibles := paUnidades.nUnidades_Operativas[0];
    PNominalPorUnidad := pa.PMax;
  end
  else if sortear then
  begin
    ActualizarProbabilidadesReparacionYRotura_(pa.fd, pa.TMR);
    NMaquinasDisponibles := Sorteos_RepRotUnidades;
    PNominalPorUnidad := pa.PMax;
  end
  else
  begin
    NMaquinasDisponibles := paUnidades.nUnidades_Operativas[0];
    PNominalPorUnidad := pa.PMax * pa.fd;
  end;
end;

procedure TBiomasaEmbalsable.PrepararPaso_ps;
var
  dCFdX_inc, dCFdX_dec: NReal;
  rescod: integer;
  xrpos: NReal;
  dCFdX: NReal;
  actualizador: NReal;
  residuo: NReal;

  procedure addcomp(fuente: TFuenteAleatoria; borne: integer; factor: NReal);
  begin
    if fuente <> nil then
    begin
      actualizador := actualizador + factor * fuente.Bornera[borne];
      residuo := residuo - factor;
    end;
  end;

begin

  // calculamos los valores PEC y PEE en base los precios de la ficha
  // de parámetros dinámicos activa y los valores de las fuentes de
  // indexación de ambos precios.
  residuo := 1;
  actualizador := 0;
  addcomp(ixA_fuente, ixA_Borne_numero, pa.a_PEC);
  addcomp(ixB_fuente, ixB_Borne_numero, pa.b_PEC);
  addcomp(ixC_fuente, ixC_Borne_numero, pa.c_PEC);
  addcomp(ixD_fuente, ixD_Borne_numero, pa.d_PEC);
  actualizador := actualizador + residuo;
  PEC := pa.PEC * actualizador;

  residuo := 1;
  actualizador := 0;
  addcomp(ixA_fuente, ixA_Borne_numero, pa.a_PEE);
  addcomp(ixB_fuente, ixB_Borne_numero, pa.b_PEE);
  addcomp(ixC_fuente, ixC_Borne_numero, pa.c_PEE);
  addcomp(ixD_fuente, ixD_Borne_numero, pa.d_PEE);
  actualizador := actualizador + residuo;
  PEE := pa.PEE * actualizador;
  if flg_imponer_cvea then
    cvea_impuesto := pa.cvea_impuesto * actualizador;


  residuo := 1;
  actualizador := 0;
  addcomp(ixA_fuente, ixA_Borne_numero, pa.a_PEX);
  addcomp(ixB_fuente, ixB_Borne_numero, pa.b_PEX);
  addcomp(ixC_fuente, ixC_Borne_numero, pa.c_PEX);
  addcomp(ixD_fuente, ixD_Borne_numero, pa.d_PEX);
  actualizador := actualizador + residuo;
  PEX := pa.PEX * actualizador;


  if not flg_imponer_cvea then
  begin

    globs.CF.devxr_continuo(ixr, globs.kPaso_Opt + 1, dCFdX_inc,
      dCFdX_dec, rescod, xrpos);

    case rescod of
      -1: dCFdX := dCFdX_inc;
      0: dCFdX := (dCFdX_dec + dCFdX_inc) / 2.0;
      1: dCFdX := dCFdX_dec;
      else
        raise Exception.Create('rescod: ' + IntToStr(rescod) + ' esto no puede pasar.');
    end;


    cvea := -dCFdX * globs.fActPaso;
  end
  else
    cvea := cvea_impuesto;

  if NMaquinasDisponibles = 0 then
    NMaquinasDespachables := 0
  else
  begin
    NMaquinasDespachables := trunc((X_EA + ecp) / edp);
    NMaquinasDespachables := min(NMaquinasDisponibles, NMaquinasDespachables);
  end;

end;


procedure TBiomasaEmbalsable.opt_nvers(var ivar, ivae, ires: integer);
begin
  if NMaquinasDespachables = 0 then
    exit; // si no hay máquinas no juego

  Self.ivar := ivar;
  ivar := ivar + 3; // A, VE, Xs_EA

  self.ivae := ivae;
  Inc(ivae);

  Self.ires := ires;
  Inc(ires);  //   - A* edp -VE -Xs_EA + x_EA + ecp = 0
end;

procedure TBiomasaEmbalsable.optx_nvxs(var ixr, ixd, iauxNReal, iauxInt: integer);
begin
  if not flg_imponer_cvea then
  begin
    Self.ixr := ixr;
    ixr := ixr + 1;
  end;
end;

procedure TBiomasaEmbalsable.optx_RegistrarVariablesDeEstado(
  adminEstados: TAdminEstados);
begin
  if not flg_imponer_cvea then
    adminEstados.Registrar_Continua(ixr, 0, EA_Max, NPuntos_EA, 'EA', 'MWh');
end;

procedure TBiomasaEmbalsable.opt_cargue(s: TSimplex);
var
  inodores: integer;
  iposte: integer;
begin
  if NMaquinasDespachables = 0 then
    exit; // si no hay máquinas no juego

  inodores := nodo.ires;
  for iposte := 0 to globs.NPostes - 1 do
  begin
    // cargamos la potencia en la restricción de balance de potencia del nodo
    s.pon_e(inodores + iposte, ivar, PNominalPorUnidad);
  end;

  // Cargamos la restricción dinámica
  // - edp*A -VE -Xs_EA + x_EA + ecp = 0
  s.pon_e(ires, ivar, -edp);
  s.pon_e(ires, ivar + 1, -1);
  s.pon_e(ires, ivar + 2, -1);
  s.pon_e(ires, s.nc, x_EA + ecp);

  // Ahora agregamos a la función de UTILIDAD (-costo
  s.pon_e(s.nf, ivar, -edp * PEE); // - A * edp  * PEE
  s.pon_e(s.nf, ivar + 1, -PEE); // - VE * PEE
  s.pon_e(s.nf, ivar + 2, cvea);  // - cvea * (X - Xs )

  // s.acum_e(s.nf, s.nc, -cvea * X_EA - PEC * ecp);

end;

procedure TBiomasaEmbalsable.opt_fijarRestriccionesDeCaja(s: TSimplex);
var
  iposte: integer;
  AForzadas: integer;

begin
  if NMaquinasDespachables = 0 then
    exit; // si no hay máquinas no juego


  if (not hayForzamientos) then
  begin
    s.cota_sup_set(ivar, NMaquinasDespachables);
  end
  else
  begin
    AForzadas := trunc(paForzamiento.P[0] / pa.PMax + 0.5);
    s.FijarVariable(ivar, AForzadas);
  end;

  s.set_entera(ivae, ivar, NMaquinasDespachables);

  s.cota_sup_set(ivar + 1, max(0, X_EA + ecp - EA_Max));
  // No puede verter más que lo que le sobra si no despacha nada

  s.cota_sup_set(ivar + 2, EA_Max); // el estado no puede superar ECA

  s.FijarRestriccionIgualdad(ires);
end;

procedure TBiomasaEmbalsable.opt_leerSolucion(s: TSimplex);
var
  iposte: integer;
  m: NReal;
  pagoenergia: NReal;
begin
  Ingreso_PorEnergia_ := 0;
  Ingreso_PorDisponibilidad_ := ecp * PEC;
  Pagos_TOP := Ingreso_PorDisponibilidad_;
  CostoDirectoDelPaso := 0;

  if NMaquinasDespachables = 0 then
  begin
    vclear(P);
    for iposte := 0 to globs.NPostes - 1 do
    begin
      Lambda_P[ iPoste ]:= 0;
      cv_Spot[ iPoste ]:=get_cv_falla; // para que en el ordenamiento quede último, con costo variable igual a la falla;
    end;
    NMaquinasDespachadas := 0;
    EnergiaDespachada_DOP := 0;
    Xs_EA := X_EA + ecp;
    if (Xs_EA > EA_Max) then
    begin
      EnergiaVertida_TOP := (Xs_EA - EA_Max);
      Xs_EA := EA_Max;
      pagoenergia := EnergiaVertida_TOP * PEE;
      Pagos_TOP := Pagos_TOP + pagoenergia;
      costoDirectoDelPaso := costoDirectoDelPaso + pagoenergia;
    end
    else
      EnergiaVertida_TOP := 0;
    exit;
  end;

  NMaquinasDespachadas := trunc(s.xval(ivar) + 0.1);
  EnergiaVertida_TOP := s.xval(ivar + 1);
  Xs_EA := s.xval(ivar + 2);

  P[0] := NMaquinasDespachadas * PNominalPorUnidad;
  EnergiaDespachada_DOP := NMaquinasDespachadas * edp;

  // recuperamos los valores de Potencia despachada
  for iposte := 1 to globs.NPostes - 1 do
  begin
    P[iposte] := P[0];
    Lambda_P[ iPoste ]:= s.xmult( ivar + iposte ) / globs.DurPos[iPoste];
    cv_Spot[iPoste]:= Nodo.cmarg[iposte] - Lambda_P[ iPoste ];
  end;

  pagoenergia := (EnergiaDespachada_DOP + EnergiaVertida_TOP) * PEE;
  Pagos_TOP := Pagos_TOP + pagoenergia;
  costoDirectoDelPaso := costoDirectoDelPaso + pagoenergia;
end;

procedure TBiomasaEmbalsable.EvolucionarEstado;
begin
  X_EA := Xs_EA;
end;


function TBiomasaEmbalsable.getNombreVar(ivar: integer; var nombre: string): boolean;
var
  kvar: integer;
  res: boolean;
begin
  res := True;
  kvar := ivar - self.ivar;
  case kvar of
    0: nombre := self.Nombre + '_Acopladas';
    1: nombre := self.Nombre + '_EnergiaVertida';
    2: nombre := self.Nombre + '_Xs_EA';
    else
      Res := False;
  end;
  Result := res;
end;

function TBiomasaEmbalsable.getNombreRes(ires: integer; var nombre: string): boolean;
begin
  if ires = self.ires then
  begin
    nombre := 'dinamica(EA)';
    Result := True;
  end
  else
    Result := False;

end;

procedure TBiomasaEmbalsable.PubliVars;
begin
  inherited PubliVars;

  PublicarVariableNR('X_EA', 'MW', 6, 1, X_EA, True);
  PublicarVariableNI('NMaquinasDespachadas', 'u', NMaquinasDespachadas, True);
  PublicarVariableNR('EnergiaVertida_TOP', 'MWh', 6, 1, EnergiaVertida_TOP, True);
  PublicarVariableNR('EnergiaDespachada_DOP', 'MWh', 6, 1, EnergiaDespachada_DOP, True);
  PublicarVariableNR('cvea', 'USD/MWh', 6, 3, cvea, True);
  PublicarVariableNR('Pagos_TOP', 'USD', 6, 1, Pagos_TOP, True);

end;

procedure TBiomasaEmbalsable.Free;
begin
  inherited Free;
end;

procedure cambioFichaPD_TBiomasaEmbalsable(actor: TActor);
begin
  with actor as TBiomasaEmbalsable do
  begin
    ecp := ECA_DOPTOP / HorasDelAnio * globs.HorasDelPaso;
    edp := pa.PMax * globs.HorasDelPaso;
    EA_Max := ECA_DOPTOP / 12 * meses_TOP;
  end;
end;

procedure cambioFichaUnidades_TBiomasaEmbalsable(actor: TActor);
begin
end;

procedure AlInicio;
begin
  registrarClaseDeCosa(TBiomasaEmbalsable.ClassName, TBiomasaEmbalsable);
  registrarClaseDeCosa(TFichaBiomasaEmbalsable.ClassName, TFichaBiomasaEmbalsable);
end;

procedure AlFinal;
begin
end;

end.
