unit uTSumComb;

interface

uses
  uCosa, SysUtils,
  uGlobs, uActores, uFechas, uCosaConNombre,
  uFichasLPD, usimplex, xMatDefs, uauxiliares,
  uActorNodalCombustible,
  unodocombustible,
  uFuentesAleatorias;

resourcestring
  rsSuministroSimpleCombustible = 'Suministro Simple Combustible';


type

  TSuministroCombustible = class(TActorUniNodalCombustible)
  end;

  { TFichaSuministroSimpleCombustible }

  TFichaSuministroSimpleCombustible = class(TFichaLPD)
  public
  (**************************************************************************)
  (*              A T R I B U T O S   P E R S I S T E N T E S               *)
  (**************************************************************************)

    QMax: NReal;   // m3/s
    flg_QMedMax_Activo: boolean; // Activa restricción de QMedMax
    QMedMax: NReal; // m3/s medios del paso MAXIMO.
    precio_por_unidad: NREal; //
    unidades_del_precio: string;
    flg_precio_a_PCS: boolean;
    fd: NReal;
    TMR: NReal;
    fuente_idxPrecioCombustible: TFuenteAleatoria;
    borne_idxPrecioCombustible: string;
  (**************************************************************************)

    kborne_idxPrecioCombustible: integer;

    constructor Create(capa: integer; fecha: TFecha; periodicidad: TPeriodicidad;
      QMax: NReal;
      flg_QMedMax_Activo: boolean;
      QMedMax: NReal;
      Precio_por_unidad: NReal;
      unidades_del_precio: string; flg_precio_a_PCS: boolean;
      xFuente_idxPrecioCombustible: TFuenteAleatoria;
      xBorne_idxPrecioCombustible: string; fd, TMR: NReal);
     
    function Rec: TCosa_RecLnk; override;
    procedure BeforeRead(version, id_hilo: integer); override;
    procedure AfterRead(f:TArchiTexto); override;

    function InfoAd_: string; override;
  end;

  { TSuministroSimpleCombustible }

  TSuministroSimpleCombustible = class(TSuministroCombustible)
  public
    // variables
    pa: TFichaSuministroSimpleCombustible;

    QMaxOperativo: NReal;
    PrecioOperativo_por_Q1h: NReal;
    NMaquinasDisponibles: integer;

    precio_USD_por_Q1h: NReal;

    constructor Create(capa: integer; nombre: string; nacimiento, muerte: TFecha;
      lpdUnidades: TFichasLPD; lpd: TFichasLPD; NodoSumComb: TNodoCombustible;
  xFuenteIdxP: TFuenteAleatoria; xBorneIdxP: string);

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

    procedure PubliVars; override;
    procedure PrepararMemoria(Catalogo: TCatalogoReferencias; globs: TGlobs); override;

    class function DescClase: string; override;

    procedure RegistrarParametrosDinamicos( Catalogo: TCatalogoReferencias ); override;

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

    procedure opt_nvers(var ivar, {%H-}ivae, ires: integer); override;
    procedure opt_cargue(s: TSimplex); override;
    procedure opt_fijarRestriccionesDeCaja(s: TSimplex); override;
    procedure opt_leerSolucion(s: TSimplex); override;

    procedure CambioFichaPD; override;

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

    procedure Free; override;
  end;

procedure AlInicio;
procedure ALFinal;

procedure TSuministroSimpleCombustible_CambioFichaPD( Actor: TCosa );


implementation


procedure TSuministroSimpleCombustible_CambioFichaPD( Actor: TCosa );
begin
  (Actor as TSuministroSimpleCombustible).cambioFichaPD;
end;

procedure TSuministroSimpleCombustible.CambioFichaPD;
begin
   precio_USD_por_Q1h:= NodoComb.combustible.precio_USD_por_MWh_a_PCI(
    pa.precio_por_unidad, pa.unidades_del_precio, pa.flg_precio_a_PCS)
    * NodoComb.combustible.MWh_por_Q1h_;
end;



// Métodos de TFichaSUministroSimpleCombustible

constructor TFichaSuministroSimpleCombustible.Create(capa: integer;
  fecha: TFecha; periodicidad: TPeriodicidad;
  QMax: NReal;
  flg_QMedMax_Activo: boolean;
  QMedMax: NReal;
  Precio_por_unidad: NReal;
  unidades_del_precio: string; flg_precio_a_PCS: boolean;
  xFuente_idxPrecioCombustible: TFuenteAleatoria; xBorne_idxPrecioCombustible: string;
  fd, TMR: NReal);
begin
  inherited Create(capa, fecha, periodicidad);
  self.Qmax := Qmax;
  self.flg_QMedMax_Activo:= flg_QMedMax_Activo;
  self.QMedMax:= QMedMax;
  self.precio_por_unidad := precio_por_unidad;
  self.unidades_del_precio:= unidades_del_precio;
  self.flg_precio_a_PCS:= flg_precio_a_PCS;
  self.fd := fd;
  self.TMR := TMR;
  self.fuente_idxPrecioCombustible := xFuente_idxPrecioCombustible;
  self.borne_idxPrecioCombustible := xBorne_idxPrecioCombustible;
end;

function TFichaSuministroSimpleCombustible.Rec: TCosa_RecLnk;
begin
  Result:=inherited Rec;
  Result.addCampoDef('QMax', QMax);
  Result.addCampoDef('flg_QMedMax_Activo', flg_QMedMax_Activo, 128 );
  Result.addCampoDef('QMedMax', QMedMax, 128 );
  Result.addCampoDef('Precio_por_unidad', Precio_por_unidad);
  Result.addCampoDef('unidades_del_precio', unidades_del_precio );
  Result.addCampoDef('flg_precio_a_PCS', flg_precio_a_PCS );
  Result.addCampoDef('fd', fd);
  Result.addCampoDef('TMR', TMR);
  Result.addCampoDef_ref('fuente_idxPrecioCombustible',  TCosa(fuente_idxPrecioCombustible), self);
  Result.addCampoDef('borne_idxPrecioCombustible', borne_idxPrecioCombustible);
end;

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

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

function TFichaSuministroSimpleCombustible.InfoAd_: string;
begin
  Result := 'QMax: ' + FloatToStr(QMax) + ', Precio['+unidades_del_precio+']: ' + FloatToStr(Precio_por_unidad);
end;


//--------------------------
// Métodos de TSuministroSimpleCombustible
//==========================

constructor TSuministroSimpleCombustible.Create(capa: integer;
  nombre: string; nacimiento, muerte: TFecha; lpdUnidades: TFichasLPD;
  lpd: TFichasLPD; NodoSumComb: TNodoCombustible;
  xFuenteIdxP: TFuenteAleatoria; xBorneIdxP: string );
begin
  inherited Create(capa, nombre, nacimiento, muerte, lpdUnidades, NodoSumComb,
  xFuenteIdxP, xBorneIdxP );
  self.lpd := lpd;
end;

function TSuministroSimpleCombustible.Rec: TCosa_RecLnk;
begin
  Result:=inherited Rec;
  Result.addCampoDef('lpd', TCosa(lpd));
end;

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

procedure TSuministroSimpleCombustible.AfterRead(f:TArchiTexto);
begin
  inherited AfterRead(f);
  lpd.Propietario := self;
end;

 

procedure TSuministroSimpleCombustible.PubliVars;
begin
  inherited PubliVars;
  PublicarVariableNR('Precio Operativo', '[USD/Q1h]', 6, 2, PrecioOperativo_por_Q1h, True);  //verificar unidades

end;

procedure TSuministroSimpleCombustible.PrepararMemoria(
  Catalogo: TCatalogoReferencias; globs: TGlobs);
begin
  inherited PrepararMemoria( Catalogo, globs);
end;

class function TSuministroSimpleCombustible.DescClase: string;
begin
  Result := rsSuministroSimpleCombustible;
end;

procedure TSuministroSimpleCombustible.RegistrarParametrosDinamicos(
  Catalogo: TCatalogoReferencias);
var
  i: integer;
  ficha: TFichaSuministroSimpleCombustible;

begin
  inherited registrarParametrosDinamicos( Catalogo );
  lpd.expandirFichas( Catalogo, globs);
  lpd.RegistrarFichasAActualizar(Self, globs.ActualizadorLPD, @pA, nil, TSuministroSimpleCombustible_CambioFichaPD );

  for i:= 0 to lpd.count - 1 do
  begin
    ficha := lpd[0] as TFichaSuministroSimpleCombustible;
    if ficha.fuente_idxPrecioCombustible <> nil then
      ficha.kborne_idxPrecioCombustible :=
        ficha.fuente_idxPrecioCombustible.IdBorne(ficha.borne_idxPrecioCombustible);
  end;
  pa:= lpd[0] as TFichaSuministroSimpleCombustible;
  CambioFichaPD;
end;


procedure TSuministroSimpleCombustible.SorteosDelPaso(sortear: boolean);
begin
  if hayForzamientos or globs.ObligarDisponibilidad_1_ then
  begin
    NMaquinasDisponibles := paUnidades.nUnidades_Operativas[0];;
    //supongo que nUnidades[0] tiene el total de maquinas de la central
    QMaxOperativo := pa.QMax * NMaquinasDisponibles;
  end
  else if sortear then
  begin
    ActualizarProbabilidadesReparacionYRotura_(pa.fd, pa.TMR);
    NMaquinasDisponibles := Sorteos_RepRotUnidades;
    QMaxOperativo := pa.QMax * NMaquinasDisponibles;
  end
  else
  begin
    NMaquinasDisponibles := paUnidades.nUnidades_Operativas[0];;
    //si no hay que sortear deja todas las maquinas disponibles
    QMaxOperativo := pa.QMax * pa.fd * NMaquinasDisponibles;
    //pero afecta a la potencia disponible por la disponibilidad
  end;

end;

procedure TSuministroSimpleCombustible.PrepararPaso_ps;
begin
  if pa.fuente_idxPrecioCombustible <> nil then
    PrecioOperativo_por_Q1h := precio_USD_por_Q1h * pa.fuente_idxPrecioCombustible.Bornera[
      pa.kborne_idxPrecioCombustible]
  else
    PrecioOperativo_por_Q1h := precio_USD_por_Q1h;
end;

procedure TSuministroSimpleCombustible.opt_nvers(var ivar, ivae, ires: integer);
begin
  self.ivar := ivar;
  Inc(ivar, globs.npostes);
  if pa.flg_QMedMax_Activo then
  begin
   self.ires:= ires;
   inc( ires );
  end;
end;

procedure TSuministroSimpleCombustible.opt_cargue(s: TSimplex);
var
  iresnodo: integer;
  kposte: integer;
begin
  iresnodo := self.NodoComb.ires;
  for kposte := 0 to globs.npostes - 1 do
  begin
    s.pon_e(iresnodo+ kposte, ivar + kposte, 1);

    // cargar funcion objetivo-costo
    s.pon_e(s.nf, ivar + kposte, -PrecioOperativo_por_Q1h * globs.durpos[kposte]);
  end;

  if pa.flg_QMedMax_Activo then
  begin
    for kposte := 0 to globs.npostes - 1 do
        s.pon_e( ires, ivar + kposte, -globs.DurPos[kposte] );
    s.pon_e( ires, s.nc, globs.HorasDelPaso * pa.QMedMax );
  end;

end;

procedure TSuministroSimpleCombustible.opt_fijarRestriccionesDeCaja(s: TSimplex);
var
  kposte: integer;
begin
  for kposte := 0 to globs.npostes - 1 do
    s.cota_sup_set(ivar + kposte, QMaxOperativo);


end;

procedure TSuministroSimpleCombustible.opt_leerSolucion(s: TSimplex);
var
  kposte: integer;
  Consumo: NREal;
begin
  Consumo := 0;
  for kposte := 0 to globs.npostes - 1 do
  begin
    Q[kposte] := s.xval(ivar + kposte);
    Consumo := Consumo + Q[kposte] * globs.DurPos[kposte];
  end;

  CostoDirectoDelPaso := Consumo * PrecioOperativo_por_Q1h;
end;

function TSuministroSimpleCombustible.getNombreVar(ivar: integer; var nombre: string): boolean;
begin
  if (ivar >= self.ivar) and (ivar < self.ivar + globs.NPostes) then
  begin
    nombre := self.Nombre + '_Q[m3/s]' + IntToStr(ivar - self.ivar + 1);
    Result := True;
  end
  else
    Result := False;
end;


procedure TSuministroSimpleCombustible.Free;
begin
  inherited Free;
end;


procedure AlInicio;
begin
  registrarClaseDeCosa(TSuministroSimpleCombustible.ClassName,
    TSuministroSimpleCombustible);
  registrarClaseDeCosa(TFichaSuministroSimpleCombustible.ClassName,
    TFichaSuministroSimpleCombustible);
end;

procedure AlFinal;
begin
end;

end.
