//====Modificado metodos: CreateDataColumnList y CreateDataConversionList===
//====Micho@26/5==mvarela@adme.com.uy=======================================
unit uGNLSumConector;

interface

uses
  Math, Classes, xMatDefs, uSimplex, uGlobs, uFechas, uEstados,
  uActores, uFichasLPD, uNodos,
  uGeneradores,
  uSuministroCombustible,
  uGNLSumIntermedio,
  uCosa,
  uFuentesAleatorias,
  uconstantesSimSEE, SysUtils;

type

  { TGNLFichaSumConector }

  TGNLFichaSumConector = class(TGNLFichaSumIntermedio)
  public
{
      T_ToP: NInt; // [dias] Tiempo de Take or Pay.
      V_ToP: NReal; // [unidad e Volumen] Volumen comprometido por el contrato Take Or Pay
      P_ToP: NReal; // [U$] Precio por Unidad de Volumen de combustible dentro del comprometido por Take or Pay
      P_ExtraToP: NReal; // [U$] Precio por Unidad de Volumen de combustible consumido por encima del volumen comprometido por Take or Pay
}


    (**************************************************************************)
    (*               A T R I B U T O S   P E R S I S T E N T E S              *)
    (**************************************************************************)

    fuenteSendoutMax:      TFuenteAleatoria; //Sendout maximo para el firme
    borneSendoutMax:       string;
    fuenteSendoutMaxInter: TFuenteAleatoria;
    //Sendout máximo por encima del sendout anterior
    borneSendoutMaxInter:  string;

    (**************************************************************************)

    nroBorneSendoutMax: integer;
    nroBorneSendoutMaxInter: integer;


    constructor Create(capa: integer; fecha: TFecha; periodicidad: TPeriodicidad; nombrecombustible: string; indicePreciosPorCombustible: TFuenteAleatoria; bornePreciosPorCombustible: string; fuenteSendoutMax: TFuenteAleatoria; borneSendoutMax: string; fuenteSendoutMaxInter: TFuenteAleatoria; borneSendoutMaxInter: string; indicePreciosPorCombustibleMayorSO: TFuenteAleatoria; bornePreciosPorCombustibleMayorSO: string; CanonFijo: TFuenteAleatoria; borneCanonFijo: string; CuentaCorriente: string);

     
    constructor Create_ReadFromText(f: TArchiTexto); override;
    procedure WriteToText(f: TArchiTexto); override;
    

    function infoAd_: string; override;
    procedure Free; override;

    



  published

    






  end;

type

  { TGNLSumConector }

  TGNLSumConector = class(TGNLSumIntermedio)

  {
  Esta clase representará posibles suministros de combustible intermedio, suministros de
  combustibles simples, que ademas de conocer a su proveedor conocen a sus clientes
  }
  private
    SendOutMaxXPoste: TDAofNReal; //Consumo por poste del generador
    SendOutMaxXPosteInter: TDAofNReal; //Maximo sendout por poste en el interrumpible
  public


    constructor Create(capa: integer; nombre: string; nombreCombustible: string; nacimiento, muerte: TFecha; lpdUnidades, lpd: TFichasLPD; cli: TSuministroCombustible); virtual;

     
    constructor Create_ReadFromText(f: TArchiTexto); override;
    procedure WriteToText(f: TArchiTexto); override;
    

    function get_ires_volumen: NInt; override;
    function get_precio_combustible: NReal; override;
    function get_combustible: TCombustibleSGE; override;

    class function TipoFichaLPD: TClaseDeFichaLPD; virtual; abstract;
    procedure Free; override;
    class function DescClase: string; override;

    procedure PrepararMemoria(globs: TGlobs); override;
    procedure RegistrarParametrosDinamicos; override;

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

    procedure Sim_Cronica_Inicio; override;

    procedure opt_nvers(var ivar, ivae, ires: integer); 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 optx_nvxs(var ixr, ixd, iauxr, iauxd: integer); override;

    // imprime tabla de delta costo futuro de la variable de estado..
    procedure opt_PrintResultados_Encab(var fsal: textfile); override;
    procedure opt_PrintResultados(var fsal: textfile); override;

    procedure PubliVars; override;
    procedure AfterInstantiation; override;
  end;

procedure AlInicio;
procedure AlFinal;
procedure TGNLSumConector_cambioFichaPD(Actor: TCosa);

implementation
//------------------------------
// Métodos de TFichaSuministroCombustible_TakeOrPay
//==============================
constructor TGNLFichaSumConector.Create(capa: integer; fecha: TFecha; periodicidad: TPeriodicidad; nombrecombustible: string;
  //                          a: NInt;
  indicePreciosPorCombustible: TFuenteAleatoria; bornePreciosPorCombustible: string; fuenteSendoutMax: TFuenteAleatoria; borneSendoutMax: string; fuenteSendoutMaxInter: TFuenteAleatoria; borneSendoutMaxInter: string; indicePreciosPorCombustibleMayorSO: TFuenteAleatoria; bornePreciosPorCombustibleMayorSO: string; CanonFijo: TFuenteAleatoria; borneCanonFijo: string; CuentaCorriente: string);

begin
  inherited Create(capa, fecha, periodicidad, nombrecombustible,
    indicePreciosPorCombustible, bornePreciosPorCombustible
    , indicePreciosPorCombustibleMayorSO,
    bornePreciosPorCombustibleMayorSO, CanonFijo, borneCanonFijo, CuentaCorriente);
  self.fuenteSendoutMax := fuenteSendoutMax;
  self.borneSendoutMax := borneSendoutMax;
  self.fuenteSendoutMaxInter := fuenteSendoutMaxInter;
  self.borneSendoutMaxInter := borneSendoutMaxInter;

end;

 
constructor TGNLFichaSumConector.Create_ReadFromText(f: TArchiTexto);
begin
  inherited Create_ReadFromText(f);
  f.IniciarLecturaRetrasada;
  f.rdReferencia('fuenteSendoutMax', TCosa(fuenteSendoutMax), self);
  f.rd('borneSendoutMax', borneSendoutMax);
  f.rdReferencia('fuenteSendoutMaxInter', TCosa(fuenteSendoutMaxInter), self);
  f.rd('borneSendoutMaxInter', borneSendoutMaxInter);

  f.EjecutarLectura;
end;

procedure TGNLFichaSumConector.WriteToText(f: TArchiTexto);
begin
  inherited WriteToText(f);
  f.wrReferencia('fuenteSendoutMax', fuenteSendoutMax);
  f.wr('borneSendoutMax', borneSendoutMax);
  f.wrReferencia('fuenteSendoutMaxInter', fuenteSendoutMaxInter);
  f.wr('borneSendoutMaxInter', borneSendoutMaxInter);
end;


function TGNLFichaSumConector.infoAd_: string;
begin
  Result := inherited  infoAd_;
  //  result:= 'atrib1= ' + IntToStr(atrib1);
{
           'V_ToP= ' + FloatToStrF(V_ToP, ffGeneral, 10, 1) + ' ' + combustible.Unidades + ', ' +
           'P_ToP= ' + FloatToStrF(P_ToP, ffGeneral, 10, 1) + ' USD/' + combustible.Unidades + ', ' +
           'P_ExtraToP= ' + FloatToStrF(P_ExtraToP, ffGeneral, 10, 2) + ' USD/' +combustible.Unidades+', ';
}
end;

procedure TGNLFichaSumConector.Free;
begin
  inherited Free;
end;












//------------------------------
// Métodos de TSuministroCombustible_TakeOrPay
//==============================

constructor TGNLSumConector.Create(capa: integer; nombre: string; nombreCombustible: string; nacimiento, muerte: TFecha; lpdUnidades, lpd: TFichasLPD;
  //        VDisp_ToP_Ini : NReal; NDisc:NInt;
  cli: TSuministroCombustible);
begin
  //  inherited Create(nombre, nombreCombustible, nacimiento, muerte, lpdUnidades, lpd, VDisp_ToP_Ini, NDisc, cli);
  inherited Create(capa, nombre, nombreCombustible, nacimiento, muerte, lpdUnidades, lpd, cli);
end;

{
procedure TGNLSumContector.setCliente(cli: TSuministroCombustible);
begin
  inherited setCliente(cli);
end;
}

 
constructor TGNLSumConector.Create_ReadFromText(f: TArchiTexto);
begin
  inherited Create_ReadFromText(f);
  f.EjecutarLectura;
  pa := nil;
end;

procedure TGNLSumConector.WriteToText(f: TArchiTexto);
begin
  inherited WriteToText(f);
  //  f.wr('VDisp_ToP', VDisp_ToP_Ini);
  //  f.wr('NDisc', NDisc);
end;




procedure TGNLSumConector.PrepararMemoria(globs: TGlobs);
begin
  inherited prepararMemoria(globs);
  setlength(SendOutMaxXPoste, globs.NPostes);
  setlength(SendOutMaxXPosteInter, globs.NPostes);
end;


function TGNLSumConector.get_ires_volumen: NInt;
begin
  Result := self.ires;
end;

function TGNLSumConector.get_precio_combustible: NReal;
begin
{
  if (VConsumido_ToP > 0) and (VConsumido_Extra_Top = 0) then
     result := dCFdV
  else
    if (VConsumido_ToP > 0) and (VConsumido_Extra_Top > 0) then
        result := pa.P_ExtraToP
    else
      if (VConsumido_ToP = 0) and (VConsumido_Extra_Top > 0) then
         result := (dCFdV * VConsumido_ToP +  pa.P_ExtraToP * VConsumido_Extra_Top) / (VConsumido_ToP + VConsumido_Extra_Top)
}
  Result := cliente.get_precio_combustible;   // Decio O (CERO ).???? RCH.
end;



function TGNLSumConector.get_combustible: TCombustibleSGE;
begin
  Result := cliente.combustible;
end;

procedure TGNLSumConector.RegistrarParametrosDinamicos;
var
  i: integer;
  ficha: TGNLFichaSumConector;
begin
  inherited registrarParametrosDinamicos;
  lpd.expandirFichas(globs);
  lpd.RegistrarFichasAActualizar(Self, globs.ActualizadorLPD, @pA, nil,
    TGNLSumConector_cambioFichaPD);
  for i := 0 to lpd.Count - 1 do
  begin
    ficha := TGNLFichaSumConector(lpd[i]);
    if ficha.fuenteSendoutMax <> nil then
      ficha.nroBorneSendoutMax := ficha.fuenteSendoutMax.IdBorne(ficha.borneSendoutMax);
    if ficha.fuenteSendoutMaxInter <> nil then
      ficha.nroBorneSendoutMaxInter :=
        ficha.fuenteSendoutMaxInter.IdBorne(ficha.borneSendoutMaxInter);
  end;
end;

procedure TGNLSumConector.Free;
begin
  inherited Free;
end;

class function TGNLSumConector.DescClase: string;
begin
  Result := 'Interconector de Suministros de Combustibles';
end;



procedure TGNLSumConector.SorteosDelPaso(sortear: boolean);
var
  fecha_ToP_ant: TDateTime;  //Fecha del ultimo embarque recibido (anterior al paso)
  fecha_ToP_sig: TDateTime;  //Fecha del siguiente embarque
  i, cntDias: integer;
  ficha: TGNLFichaSumIntermedio;
begin
{
  //Calculamos cuando fué el último embarque (más reciente) para la fecha de inicio del paso.
  //Esto puede dar la fecha de vigencia de la ficha (cuando comienza a reguir una ficha entra combustible)
  //o una fecha posterior tal que es múltiplo de T_ToP
  cntDias :=  Trunc(globs.FechaInicioDelpaso.dt) - Trunc(pa.Fecha.dt);
//  cntDias :=  cntDias mod  pa.T_ToP;
  cntDias :=  0;
  fecha_ToP_ant := globs.FechaInicioDelpaso.dt  - cntDias;

  //Calculamos la siguiente fecha de ingreso de TakeOrPay y la hacemos igual a la fecha anterior + T dias
  //Si hay un cambio de ficha antes de esa fecha, colocamos como fecha del proximo ingreso la proxima fecha de vigencia
//  fecha_ToP_sig := fecha_ToP_ant + pa.T_ToP;
  fecha_ToP_sig := fecha_ToP_ant;

  //Las Fechas de TOP corresponden a la hora 00:00:00

//  V_ToP_sig := pa.V_ToP;

 //Ahora debemos detectar si hay una ficha que comienza a regir en el paso de simulación.
 //En este caso, en el paso no se actualiza el volumen, se consume todo lo que resta
 //y el volumen se actualizará al final del paso de tiempo
 for i:= 0 to lpd.Count - 1 do
  begin
    ficha:= TGNLFichaSumIntermedio(lpd[i]);
    if (ficha.fecha.dt > globs.FechaInicioDelpaso.dt) and (ficha.fecha.dt < globs.FechaFinDelpaso.dt) then
      if (fecha_ToP_sig > ficha.fecha.dt) then
        begin
           fecha_ToP_sig := ficha.fecha.dt;
//           V_ToP_sig := ficha.V_ToP;
        end;
  end;


  //Ahora determinamos la fase en función de cuando ingreso el cargamento anterior y cuando ingresa el siguiente
  // no utilizo globs.FechaInicioDelpaso.dt porque tiene una hora menos!!!!!
  {if (globs.FechaInicioDelpaso.dt <= fecha_ToP_sig)
     and( TFecha.Create_OffsetDT(globs.FechaInicioDelpaso, globs.HorasDelPaso).dt >= fecha_ToP_sig) then
                   //Atención: se pone globs.FechaFinDelPaso.dt > fecha_ToP_sig pues en caso de la igualdad
                   //se toma en el inicio del siguiente paso.
    fase:= 1     //En este paso de simulación ingresa un volumen T_ToP del contrato
  else
    fase:= 0;     //En este paso de simulación no ingresa combustible
   }
  //Si estamos en la fase 1, debemos actualizar el volumen disponible al final del paso
  //y el volumen restante lo ponemos como perdido
  //Si estamos en la fase 0, significa que tenemos un contrato vigente y estamos a la espera de un cargamento ToP

end;


procedure TGNLSumConector.PrepararPaso_ps;
begin
end;

procedure TGNLSumConector.opt_nvers(var ivar, ivae, ires: integer);
begin
  //si no hay combustible no va al simplex
  if (self.cliente.get_VolCombustibleDisponible = 0) then
    exit;
  inherited opt_nvers(ivar, ivae, ires);
end;

procedure TGNLSumConector.opt_cargue(s: TSimplex);
begin
  //si no hay combustible no va al simplex
  if (self.cliente.get_VolCombustibleDisponible = 0) then
    exit;
  inherited opt_cargue(s);
{$IFDEF SPXCONLOG}
  spx_NombrarVariables(s);
{$ENDIF}
end;

procedure TGNLSumConector.Sim_Cronica_Inicio;
begin
  inherited Sim_Cronica_Inicio;
end;

procedure TGNLSumConector.opt_fijarRestriccionesDeCaja(s: TSimplex);
var
  iposte: integer;
begin
  //si no hay combustible no va al simplex
  if (self.cliente.get_VolCombustibleDisponible = 0) then
    exit;

  inherited opt_fijarRestriccionesDeCaja(s);
  //  s.FijarRestriccionIgualdad(ires);

  //Agregamos la restricción de caja que dice que el sendout max es el dado por la bornera
  if TGNLFichaSumConector(pa).fuenteSendoutMax <> nil then
  begin
    if self.restricciones_postizadas then
    begin
      for iposte := 0 to CantVCons() - 1 do
      begin
        SendOutMaxXPoste[iposte] :=
          TGNLFichaSumConector(pa).fuenteSendoutMax.bornera[TGNLFichaSumConector(
          pa).nroBorneSendoutMax] * globs.DurPos[iposte];
        s.cota_sup_set(ivar + iposte, SendOutMaxXPoste[iposte]);
      end;
    end
    else //si las restricciones no son postizadas
    begin
      SendOutMaxXPoste[0] := TGNLFichaSumConector(
        pa).fuenteSendoutMax.bornera[TGNLFichaSumConector(pa).nroBorneSendoutMax] *
        globs.HorasDelPaso;
      s.cota_sup_set(ivar, TGNLFichaSumConector(
        pa).fuenteSendoutMax.bornera[TGNLFichaSumConector(pa).nroBorneSendoutMax] *
        globs.HorasDelPaso);
    end;
  end;


  //Agregamos la restricción de caja que dice que el sendout max del interrumpible es el dado por la bornera
  if TGNLFichaSumConector(pa).fuenteSendoutMaxInter <> nil then
  begin
    if self.restricciones_postizadas then
    begin
      for iposte := 0 to CantVCons() - 1 do
      begin
        SendOutMaxXPosteInter[iposte] :=
          TGNLFichaSumConector(pa).fuenteSendoutMaxInter.bornera[TGNLFichaSumConector(
          pa).nroBorneSendoutMaxInter] * globs.DurPos[iposte];
        s.cota_sup_set(ivar + CantVCons() + iposte,
          SendOutMaxXPosteInter[iposte]);
      end;
    end
    else //si las restricciones no son postizadas
    begin
      SendOutMaxXPosteInter[0] :=
        TGNLFichaSumConector(pa).fuenteSendoutMaxInter.bornera[TGNLFichaSumConector(
        pa).nroBorneSendoutMaxInter] * globs.HorasDelPaso;
      s.cota_sup_set(ivar + CantVCons(), TGNLFichaSumConector(
        pa).fuenteSendoutMaxInter.bornera[TGNLFichaSumConector(
        pa).nroBorneSendoutMaxInter] * globs.HorasDelPaso);

    end;
  end;

end;

procedure TGNLSumConector.opt_leerSolucion(s: TSimplex);
begin
  inherited opt_leerSolucion(s);
end;

function TGNLSumConector.getNombreVar(ivar: integer; var nombre: string): boolean;
begin
  Result := inherited getNombreVar(ivar, nombre) or False;
end;

function TGNLSumConector.getNombreRes(ires: integer; var nombre: string): boolean;
begin
  Result := inherited getNombreRes(ires, nombre);
end;


procedure TGNLSumConector.PubliVars;
begin
  inherited PubliVars;

  PublicarVariableVR('Caudal_Max', '[' + cliente.combustible.Unidades +
    ']', 6, 1, SendOutMaxXPoste, True, True);
  //  PublicarVariableNR('CV_combustible','[USD/'+ unidades +']',6,1,self.dCFdV, true);
{
  PublicarVariableNR('V_Consumido_ToP', '['+unidades+']', 6, 1, self.VConsumido_ToP);
  PublicarVariableNR('V_Consumid_Extra_ToP', '['+unidades+']', 6, 1, self.VConsumido_Extra_Top);
  PublicarVariableNR('V_Sobrante_ToP', '['+unidades+']', 6, 1, self.VSobrante_ToP);
  PublicarVariableNR('V Disponible_ToP', '['+unidades+']', 6, 1, self.X_VDisp_ToP);
 }
  {  PublicarVariableNI('Fase', '-', fase, true);}
end;

procedure TGNLSumConector.AfterInstantiation;
begin
  inherited AfterInstantiation;
  pa := nil;
end;


{
function TGNLSumConector.varsPSimRes3PorDefecto: TStringList;
var
  res: TStringList;
begin
  res:= inherited varsPSimRes3PorDefecto;

  res.Add('Costo_Directo_Paso');
  res.Add('CV_combustible');
  res.Add('V_Consumido_ToP');
  res.Add('V_Consumido_Extra_ToP');
  res.Add('V_Sobrante_ToP');
  res.Add('V_Disponible_ToP');
  res.Add('Fase');

  result:= res;
end;
}

procedure TGNLSumConector.optx_nvxs(var ixr, ixd, iauxr, iauxd: integer);
begin
  self.ixr := ixr;
end;



procedure TGNLSumConector.opt_PrintResultados_Encab(var fsal: textfile);
begin
  //  write( fsal, #9, FloatToStrF( X_VDisp_ToP,ffgeneral, 6,3 ));
end;

procedure TGNLSumConector.opt_PrintResultados(var fsal: textfile);
begin
  //  write( fsal, #9, FloatToStrF( dCFdV, ffgeneral, 6,3 ) );
end;

{
// imprime volumenes de combustible despachados, h_actual, cv_agua_Dec
procedure TGNLSumConector.Sim_PrintResultados_Encab(var fsal: textfile; kencab: integer );
begin

  if kencab = 0 then
  begin
    Write(fsal, #9,  Nombre, #9, Nombre, #9, Nombre, #9, Nombre,#9, Nombre,#9, Nombre,#9, Nombre);
  end
  else if kencab = 1 then
  begin
    write(fsal, #9, '[VConsumido_ToP]', #9, '[VConsumido_Extra_Top]', #9, '[VDisponible_ToP]', #9, '[VSobrante_ToP]', #9, '[CostoVariableCombustible]', #9, '[CostoDirectoDelPaso]', #9, '[Fase]');
  end
  else if kencab = 2 then
  begin
    write(fsal, #9, '[1VConsumido_ToP]', #9, '[1VConsumido_Extra_Top]', #9, '[1VDisponible_ToP]', #9, '[1VSobrante_ToP]', #9, '[1CostoVariableCombustible]', #9, '[1CostoDirectoDelPaso]', #9, '[1Fase]');
  end
  else
  begin
    write(fsal, #9, '[2VConsumido_ToP]', #9, '[2VConsumido_Extra_Top]', #9, '[2VDisponible_ToP]', #9, '[2VSobrante_ToP]', #9, '[2CostoVariableCombustible]', #9, '[2CostoDirectoDelPaso]', #9, '[2Fase]');
  end;
end;

procedure TGNLSumConector.Sim_PrintResultados(var fsal: textfile);

begin
//   write( fsal, #9, FloatToStrF(VConsumido_ToP, formatoReales, 6, 1));
//  write( fsal, #9, FloatToStrF(VConsumido_Extra_Top, formatoReales, 6, 1));
  write( fsal, #9, FloatToStrF(X_VDisp_ToP, formatoReales, 6, 1));
//  write( fsal, #9, FloatToStrF(VSobrante_ToP, formatoReales, 6, 1));
  write( fsal, #9, FloatToStrF(dCFdV, formatoReales, 6, 1 ) );
  write( fsal, #9, FloatToStrF(CostoDirectoDelPaso, formatoReales, 6, 1 ) );
  write( fsal, #9, IntToStr(fase));

end;
}

procedure TGNLSumConector_cambioFichaPD(Actor: TCosa);
begin
end;

procedure AlInicio;
begin
  registrarClaseDeCosa(TGNLSumConector.ClassName, TGNLSumConector);
  registrarClaseDeCosa(TGNLFichaSumConector.ClassName, TGNLFichaSumConector);
end;

procedure AlFinal;
begin
end;

end.
