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

{$IFDEF FPC}
  {$MODE Delphi}
{$ENDIF}

interface

uses
  SysUtils, Classes, xmatdefs, uGTer, unodos,
  uglobs,
  umipsimplex,
  usimplex,
  ufichasLPD,
  ufechas,
  ucosa,
  uConversions,
  uconstantesSimSEE, uFuentesAleatorias, Math
  {$IFDEF COMBUSTIBLES}
  , uCombustible
  {$ENDIF}  ;

resourcestring
  rsGeneradorTermicoCombinado = 'Generador térmico combinado V2';

type

  { TFichaGTer_combinadoV2 }

  TFichaGTer_combinadoV2 = class(TFichaLPD)
  protected
    


















;

  public
     
    //Atributos para las TurbinaGas
    PMin_TG, PMax_TG: NReal; // [MW] Potencias Mínima y Máxima Por maquina
    disp_TG: NReal; // disponibilidad (fortuita)
    tRepHoras_TG: NReal;
    //Atributos para las TurboVapor
    disp_TV: NReal; // disponibilidad (fortuita)
    tRepHoras_TV: NReal;
    //Atributos para las CicloCombinado
    PMin_CC, PMax_CC: NReal; // [MW] Potencias Mínima y Máxima Por maquina
    factorPotenciaTVdivTG: NReal; //factor de potencia en el que funciona el CC
    indicePreciosPorCombustible: TFuenteAleatoria;
    bornePreciosPorCombustible: string;
    HayRestriccionEmaxPasoDeTiempo: boolean; // indica si se aplica la restricción
    EmaxPasoDeTiempo: NReal; // Energía maxima generable en un paso de tiempo
    disponibleCombustible: array[1..3] of boolean;
    rendimientoPN: array[1..3] of NReal;
    rendimientoMT: array[1..3] of NReal;
    combustible: array[1..3] of TCombustible;
    

    nroBornePreciosPorCombustible: integer;

    constructor Create(fecha: TFecha; periodicidad: TPeriodicidad;
      PMin_TG, PMax_TG: NReal; disp_TG: NReal; tRepHoras_TG: NReal;
      disp_TV: NReal; tRepHoras_TV: NReal; PMin_CC, PMax_CC: NReal;
      factorPotenciaTVdivTG: NReal; indicePreciosPorCombustible: TFuenteAleatoria;
      bornePreciosPorCombustible: string; HayRestriccionEmaxPasoDeTiempo: boolean;
      EmaxPasoDeTiempo: NReal; disponibleCombustible: array of boolean;
      rendimientoPN: array of NReal; rendimientoMT: array of NReal;
      combustible: array of TCombustible);

    constructor Create_ReadFromText(f: TArchiTexto); override;
    procedure WriteToText(f: TArchiTexto); override;
    procedure generarLineaResumen(var archi: TextFile); override;
    function infoAd_: string; override;
    procedure Free; override;

    class function CreateDataColumnList(xClaseDeCosa:TClaseDeCosa; xVersion: Integer=-2): TDataColumnListOfCosa; override;
    class function CreateDataConversionList: TListDataConversion; override;

  published
    


















  end;


  // TGenSencillo es una potencia minima y maxima constante en todos los postes
  // y un costo variable cv [USD/MWh] tambien igual en todos los postes
  // y un costo variable cv_min "hasta el minimo" igual al costo de produccion en USD/MWh cuando
  // la central esta generado en el minimo.

  { TGTer_combinadoV2 }

  TGTer_combinadoV2 = class(TGTer)
  public
    pa: TFichaGTer_combinadoV2;

    NMaquinasDespachadas: TDAOfNInt;
    // cantidad de máquinas despachadas por poste o por paso ( Acople )
    maxNMaquinasDespachadas: integer; // máximo del vector anterior
    costosPorPoste: TDAofNReal;


    c0: NReal; //Costo en USD/h por máquina por estar operando en el mínimo técnico
    cv: NReal; //USD/MWh usado para la optimización del paso.
    cvPN: array[1..3] of NReal;
    cvMT: array[1..3] of NReal;


    PMin: NReal; //MW, mínimo
    PxMax: NReal; // MW, cota sup de P-Pmin

    // resultado de los sorteos de disponibilidad y del mantenimiento programado
    NMaquinasDisponibles: integer;
    PMaxDisponible: NReal;

    //Cuanta potencia despacho en cada hora el generador en promedio
    potMedia_despachada: NReal;

    constructor Create(nombre: string; nacimiento, muerte: TFecha;
      lpdUnidades, lpd: TFichasLPD; nodo: TNodo); override;

    constructor Create_ReadFromText(f: TArchiTexto); override;
    procedure WriteToText(f: TArchiTexto); override;
    procedure PrepararMemoria(globs: TGlobs); override;
    procedure RegistrarParametrosDinamicos; override;

    function PotenciaFirme: NReal; override;

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

    procedure SorteosDelPaso(sortear: boolean); override;
    procedure PrepararPaso_ps; override;
    procedure Sim_Paso_Fin; 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;
{$IFDEF SPXCONLOG}
    procedure spx_NombrarVariables(s: TSimplex); override;
{$ENDIF}
    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;

    class function CreateDataColumnList(xClaseDeCosa: TClaseDeCosa; xVersion: Integer=-2
      ): TDataColumnListOfCosa; override;

    procedure AfterInstantiation; override;

  end;

procedure AlInicio;
procedure AlFinal;

implementation

//------------------------------
// Métodos de TFichaGter_combinadoV2
//==============================
constructor TFichaGTer_combinadoV2.Create(fecha: TFecha;
  periodicidad: TPeriodicidad; PMin_TG, PMax_TG: NReal; disp_TG: NReal;
  tRepHoras_TG: NReal; disp_TV: NReal; tRepHoras_TV: NReal;
  PMin_CC, PMax_CC: NReal; factorPotenciaTVdivTG: NReal;
  indicePreciosPorCombustible: TFuenteAleatoria; bornePreciosPorCombustible: string;
  HayRestriccionEmaxPasoDeTiempo: boolean; EmaxPasoDeTiempo: NReal;
  disponibleCombustible: array of boolean; rendimientoPN: array of NReal;
  rendimientoMT: array of NReal; combustible: array of TCombustible);
begin
  inherited Create(fecha, periodicidad);

  self.PMin_TG := PMin_TG;
  self.PMax_TG := PMax_TG;
  self.disp_TG := disp_TG;
  self.tRepHoras_TG := tRepHoras_TG;

  self.disp_TV := disp_TV;
  self.tRepHoras_TV := tRepHoras_TV;

  self.PMin_CC := PMin_CC;
  self.PMax_CC := PMax_CC;

  self.factorPotenciaTVdivTG := factorPotenciaTVdivTG;

  self.indicePreciosPorCombustible := indicePreciosPorCombustible;
  self.bornePreciosPorCombustible := bornePreciosPorCombustible;
  self.HayRestriccionEmaxPasoDeTiempo := HayRestriccionEmaxPasoDeTiempo;
  self.EmaxPasoDeTiempo := EmaxPasoDeTiempo;

  self.disponibleCombustible := disponibleCombustible;
  self.rendimientoPN := rendimientoPN;
  self.rendimientoMT := rendimientoMT;
  self.combustible := combustible;
end;

constructor TFichaGTer_combinadoV2.Create_ReadFromText(f: TArchiTexto);
var
  i: integer;
begin
  inherited Create_ReadFromText(f);
  f.IniciarLecturaRetrasada;
  f.rd('PMin_TG', PMin_TG);
  f.rd('PMax_TG', PMax_TG);
  f.rd('disp_TG', disp_TG);
  f.rd('tRepHoras_TG', tRepHoras_TG);

  f.rd('disp_TV', disp_TV);
  f.rd('tRepHoras_TV', tRepHoras_TV);

  f.rd('PMin_CC', PMin_CC);
  f.rd('PMax_CC', PMax_CC);

  f.rd('factorPotenciaTVdivTG', factorPotenciaTVdivTG);

  f.rdReferencia('indicePreciosPorCombustible',
    TCosa(indicePreciosPorCombustible), self);
  f.rd('bornePreciosPorCombustible', bornePreciosPorCombustible);
  f.rd('HayRestriccionEmaxPasoDeTiempo', HayRestriccionEmaxPasoDeTiempo);
  f.rd('EmaxPasoDeTiempo', EmaxPasoDeTiempo);

  for i := 1 to 3 do
  begin
    f.rd('disponibleCombustible' + IntToStr(i), disponibleCombustible[i]);
    f.rd('rendimientoPN' + IntToStr(i), rendimientoPN[i]);
    f.rd('rendimientoMT' + IntToStr(i), rendimientoMT[i]);
    f.rdReferencia('combustible' + IntToStr(i), TCosa(combustible[i]), Self);
  end;

  f.EjecutarLectura;
end;

procedure TFichaGTer_combinadoV2.WriteToText(f: TArchiTexto);
var
  i: integer;
begin
  inherited WriteToText(f);
  f.wr('PMin_TG', PMin_TG, uconstantesSimSEE.CF_PRECISION,
    uconstantesSimSEE.CF_DECIMALES);
  f.wr('PMax_TG', PMax_TG, uconstantesSimSEE.CF_PRECISION,
    uconstantesSimSEE.CF_DECIMALES);
  f.wr('disp_TG', disp_TG, uconstantesSimSEE.CF_PRECISION,
    uconstantesSimSEE.CF_DECIMALESPU);
  f.wr('tRepHoras_TG', tRepHoras_TG, uconstantesSimSEE.CF_PRECISION,
    uconstantesSimSEE.CF_DECIMALES);

  f.wr('disp_TV', disp_TV, uconstantesSimSEE.CF_PRECISION,
    uconstantesSimSEE.CF_DECIMALESPU);
  f.wr('tRepHoras_TV', tRepHoras_TV, uconstantesSimSEE.CF_PRECISION,
    uconstantesSimSEE.CF_DECIMALES);

  f.wr('PMin_CC', PMin_CC, uconstantesSimSEE.CF_PRECISION,
    uconstantesSimSEE.CF_DECIMALES);
  f.wr('PMax_CC', PMax_CC, uconstantesSimSEE.CF_PRECISION,
    uconstantesSimSEE.CF_DECIMALES);

  f.wr('factorPotenciaTVdivTG', factorPotenciaTVdivTG,
    uconstantesSimSEE.CF_PRECISION, uconstantesSimSEE.CF_DECIMALES);

  f.wrReferencia('indicePreciosPorCombustible', indicePreciosPorCombustible);
  f.wr('bornePreciosPorCombustible', bornePreciosPorCombustible);
  f.wr('HayRestriccionEmaxPasoDeTiempo', HayRestriccionEmaxPasoDeTiempo);
  f.wr('EmaxPasoDeTiempo', EmaxPasoDeTiempo);

  for i := 1 to 3 do
  begin
    f.wr('disponibleCombustible' + IntToStr(i), disponibleCombustible[i]);
    f.wr('rendimientoPN' + IntToStr(i), rendimientoPN[i]);
    f.wr('rendimientoMT' + IntToStr(i), rendimientoMT[i]);
    f.wrReferencia('combustible' + IntToStr(i), combustible[i]);
  end;

end;

procedure TFichaGTer_combinadoV2.generarLineaResumen(var archi: TextFile);
begin
  Write(archi, FloatToStrF(PMin_TG, formatoReales, 8, 1), #9,
    //PMín_TG
    FloatToStrF(PMax_TG, formatoReales, 8, 1), #9,
    //PMáx_TG
    FloatToStrF(disp_TG, formatoReales, 8, 2), #9,
    //FDisp_TG
    '-', #9,
    //Costo Arranque
    '-', #9,
    //Costo Parada
    '-', #9,
    //mínNPasosOn
    '-', #9,
    //mínNPasosOff
    '-', #9,
    //desiciónPasosOnPorCiclo
    '-', #9,
    //desiciónPasosOffPorCiclo
    '-', #9,
    //costoPorCicloOn
    '-', #9);
  //costoPorCicloOff
end;

function TFichaGTer_combinadoV2.infoAd_: string;
begin
  Result := 'PMín_TG= ' + FloatToStrF(PMin_TG, ffGeneral, 10, 1) +
    ' MW, ' + 'PMáx_TG= ' + FloatToStrF(PMax_TG, ffGeneral, 10, 1) +
    ' MW, ' + 'fDisp_TG= ' + FloatToStrF(disp_TG, ffGeneral, 10, 2) +
    ' p.u., ' + 'tRep_TG= ' + FloatToStrF(tRepHoras_TG, ffGeneral, 10, 1) + 'h';
end;

procedure TFichaGTer_combinadoV2.Free;
begin
  inherited Free;
end;

class function TFichaGTer_combinadoV2.CreateDataColumnList(
  xClaseDeCosa: TClaseDeCosa; xVersion: Integer): TDataColumnListOfCosa;
begin
  



































end;

class function TFichaGTer_combinadoV2.CreateDataConversionList: TListDataConversion;
begin
  Result:=inherited CreateDataConversionList;
  Result.Add(uConversions.VERSION_MIGRACION_PERSISTENCIA,
    ['disponibleCombustible1', 'disponibleCombustible2' , 'disponibleCombustible3'],
    ['disponibleCombustible'], Result.ConversionPrimitivesToOneDynArray());

  Result.Add(uConversions.VERSION_MIGRACION_PERSISTENCIA,
    ['rendimientoPN1', 'rendimientoPN2' , 'rendimientoPN3'],
    ['rendimientoPN'], Result.ConversionPrimitivesToOneDynArray());

  Result.Add(uConversions.VERSION_MIGRACION_PERSISTENCIA,
    ['rendimientoMT1', 'rendimientoMT2' , 'rendimientoMT3'],
    ['rendimientoMT'], Result.ConversionPrimitivesToOneDynArray());

  Result.Add(uConversions.VERSION_MIGRACION_PERSISTENCIA,
    ['combustible1', 'combustible2' , 'combustible3'],
    ['combustible'], Result.ConversionPrimitivesToOneDynArray());
end;

//------------------------
// Métodos de TGTer_CombinadoV2
//========================
procedure TGTer_combinadoV2.dump_Variables(var f: TextFile; charIndentacion: char);
begin
  inherited dump_Variables(f, charIndentacion);
  writeln(f, charIndentacion, 'c0[USD/MWh]= ', FloatToStrF(c0, ffFixed, 10, 3));
  writeln(f, charIndentacion, 'cv[USD/MWh]= ', FloatToStrF(cv, ffFixed, 10, 3));

  writeln(f, charIndentacion, 'PMin[MW]= ', FloatToStrF(PMin, ffFixed, 10, 3));
  writeln(f, charIndentacion, 'PMAx[MW]= ', FloatToStrF(pa.PMax_TG, ffFixed, 10, 3));
  writeln(f, charIndentacion, 'PxMax[MW]= ', FloatToStrF(PxMax, ffFixed, 10, 3));
  writeln(f, charIndentacion, 'PMaxDisponible[MW]= ',
    FloatToStrF(PMaxDisponible, ffFixed, 10, 3));

  writeln(f, charIndentacion, 'NMaquinasDisponibles= ', NMaquinasDisponibles);

  writeln(f, charIndentacion, 'HayRestrEMaxPasoDeTiempo= ',
    pa.hayRestriccionEmaxPasoDeTiempo);
  writeln(f, charIndentacion, 'EMaxPasoDeTiempo[MW/h]= ',
    FloatToStrF(pa.EmaxPasoDeTiempo, ffFixed, 10, 3));

  writeln(f);
end;

class function TGTer_combinadoV2.TipoFichaLPD: TClaseDeFichaLPD;
begin
  Result := TFichaGTer_combinadoV2;
end;

class function TGTer_combinadoV2.CreateDataColumnList(
  xClaseDeCosa: TClaseDeCosa; xVersion: Integer): TDataColumnListOfCosa;
begin
  


end;

procedure TGTer_combinadoV2.AfterInstantiation;
begin
  inherited AfterInstantiation;
    pa := nil;
  nodo := nil;
end;


constructor TGTer_combinadoV2.Create(nombre: string; nacimiento, muerte: TFecha;
  lpdUnidades, lpd: TFichasLPD; nodo: TNodo);
begin
  inherited Create(nombre, nacimiento, muerte, lpdUnidades, lpd, nodo);
end;

constructor TGTer_combinadoV2.Create_ReadFromText(f: TArchiTexto);
begin
  inherited Create_ReadFromText(f);
  pa := nil;
  nodo := nil;
end;

procedure TGTer_combinadoV2.PrepararMemoria(globs: TGlobs);
begin
  inherited prepararMemoria(globs);
  SetLength(costosPorPoste, globs.NPostes);

(* Dimensionamoes estos vectores de tamaño NPostes aune si la central es del tipo
ONOFF Por paso bastaría con dimensión= 1 *)
  SetLength(NMaquinasDespachadas, globs.NPostes);
end;

procedure TGTer_combinadoV2.RegistrarParametrosDinamicos;
var
  i: integer;
  ficha: TFichaGTer_combinadoV2;
begin
  inherited registrarParametrosDinamicos;
  lpd.expandirFichas(globs);
  lpd.RegistrarFichasAActualizar(Self, globs.ActualizadorLPD, @pA, nil);
  for i := 0 to lpd.Count - 1 do
  begin
    ficha := TFichaGTer_combinadoV2(lpd[i]);
    if ficha.indicePreciosPorCombustible <> nil then
      ficha.nroBornePreciosPorCombustible :=
        ficha.indicePreciosPorCombustible.IdBorne(ficha.bornePreciosPorCombustible);
  end;
end;

function TGTer_combinadoV2.PotenciaFirme: NReal;
begin
  Result := (paUnidades.nUnidades[0]) * pa.PMax_TG * pa.disp_TG;
end;

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

class function TGTer_combinadoV2.DescClase: string;
begin
  Result := rsGeneradorTermicoCombinado;
end;

procedure TGTer_combinadoV2.SorteosDelPaso(sortear: boolean);
begin
  if globs.ObligarDisponibilidad_1_ then
  begin
    NMaquinasDisponibles := paUnidades.nUnidades[0];
    PMaxDisponible := pa.PMax_TG * NMaquinasDisponibles;
  end
  else
  if sortear then
  begin
    ActualizarProbabilidadesReparacionYRotura(pa.disp_TG, pa.tRepHoras_TG);
    NMaquinasDisponibles := Sorteos_RepRotUnidades;
    PMaxDisponible := pa.PMax_TG * NMaquinasDisponibles;
  end
  else
  begin
    NMaquinasDisponibles := paUnidades.nUnidades[0];
    PMaxDisponible := pa.PMax_TG * pa.disp_TG * NMaquinasDisponibles;
  end;
end;

procedure TGTer_combinadoV2.PrepararPaso_ps;
var
  i: integer;
begin
  //PMin  := pa.PMIn;
  //PxMax := pa.PMax - pa.PMin;

  //for i:= 1 to 3 do
  //begin

  //    if pa.combustible[i] <> nil then
  //    begin
  //      cvMT[i] := (pa.combustible[i].pa.precio * pa.combustible[i].pa.PCS)
  //              / (pa.rendimientoMT[i] * pa.combustible[i].pa.PCI);

  //      cvPN[i] := (pa.combustible[i].pa.precio * pa.combustible[i].pa.PCS)
  //              / (pa.rendimientoMT[i] * pa.combustible[i].pa.PCI);
  //    end
  //    else
  //    begin
  //      cvMT[i] := math.MaxDouble;
  //      cvPN[i] := math.MaxDouble;
  //    end;
  //end;

  //c0 := Min( Min(cvMT[1],cvMT[1]), cvMT[3] );
  //cv := Min( Min(cvPN[1],cvPN[1]), cvPN[3] );

end;

procedure TGTer_combinadoV2.Sim_Paso_Fin;
var
  iposte: integer;
begin
  if NMaquinasDisponibles > 0 then
  begin
    for iposte := 0 to high(P) do
      potMedia_despachada := potMedia_despachada + P[iposte] * globs.durpos[iposte];
    potMedia_despachada := potMedia_despachada * globs.invHorasDelPaso;
  end
  else
  begin
    potMedia_despachada := 0;
  end;
end;

procedure TGTer_combinadoV2.WriteToText(f: TArchiTexto);
begin
  inherited WriteToText(f);
end;

procedure TGTer_combinadoV2.opt_nvers(var ivar, ivae, ires: integer);
begin
  if NMaquinasDisponibles = 0 then
    exit;
  Self.ivar := ivar;
  ivar := ivar + globs.NPostes * 2;
  Self.ivae := ivae;
  ivae := ivae + globs.NPostes;
  Self.ires := ires;
  ires := ires + globs.NPostes;
  if pA.HayRestriccionEmaxPasoDeTiempo then
    Inc(ires);
end;

procedure TGTer_combinadoV2.opt_cargue(s: TSimplex);
var
  inodores: integer;
  iposte: integer;
  jres: integer;
begin
  if NMaquinasDisponibles = 0 then
    exit; // si no hay máquinas no juego
{$IFDEF SPXCONLOG}
  spx_NombrarVariables(s);
{$ENDIF}
  inodores := nodo.ires;
  // aporte a las restricciones del nodo
  for iposte := 0 to globs.NPostes - 1 do
  begin
    s.pon_e(inodores + iposte, ivar + iposte, 1); // coeficiente de la B[iposte]
    s.pon_e(inodores + iposte, ivar + iposte + globs.NPostes, Pmin); // coef A
  end;

  // restricciones adicionales impuestas por la variable de Acople
  jres := ires;
  for iposte := 0 to globs.NPostes - 1 do
  begin
    s.pon_e(jres, ivar + iposte, -1); // coef B[iposte]
    s.pon_e(jres, ivar + globs.NPostes + iposte, PxMax);
    Inc(jres);
  end;
  //Restriccion a la energía máxima generable en el paso
  if pA.HayRestriccionEmaxPasoDeTiempo then
  begin
    for iposte := 0 to globs.NPostes - 1 do
    begin
      s.pon_e(jres, ivar + iposte, -globs.durpos[iposte]);
      s.pon_e(jres, ivar + globs.NPostes + iposte, -globs.durpos[iposte] * pa.PMin_TG);
    end;
    s.pon_e(jres, s.nc, pa.EmaxPasoDeTiempo);
  end;

  // aportes a la función de utilidad
  for iposte := 0 to globs.NPostes - 1 do
  begin
    s.pon_e(s.nf, ivar + iposte, -cv * globs.DurPos[iposte]);
    s.pon_e(s.nf, ivar + globs.NPostes + iposte, -c0 * globs.DurPos[iposte]);
  end;
end;

procedure TGTer_combinadoV2.opt_fijarRestriccionesDeCaja(s: TSimplex);
var
  iposte: integer;
begin
  if NMaquinasDisponibles = 0 then
    exit;
  (*
    // Restricciones de caja de las B (Esto no es necesario pues las restricciones adicionales
    // obligan que estas se cumplan. Por eso le pongo el 1.1 para dejarle la caja un poco floja
    for iposte:= 0 to globs.NPostes-1 do
      s.cota_sup_set( ivar+iposte, PxMax*NMaquinasDisponibles*1.1 );
  *)

  // Restricciones de caja de las A y las declaramos enteras
  for iposte := 0 to globs.NPostes - 1 do
    s.set_EnteraConAcople(
      ivae + iposte, ivar + globs.NPostes + iposte, NMaquinasDisponibles,
      ivar + iposte, ires + iposte);
end;

procedure TGTer_combinadoV2.opt_leerSolucion(s: TSimplex);
var
  iposte: integer;
  nmaqs: integer;
  m: NReal;

begin

  CostoDirectoDelPaso := 0;

  maxNMaquinasDespachadas := 0;
  if NMaquinasDisponibles = 0 then
  begin
    vclear(P);
    vclear(costosPorPoste);
    vclear(NMaquinasDespachadas);
    exit;
  end;

  for iposte := 0 to globs.NPostes - 1 do
  begin
    nmaqs := trunc(s.xval(ivar + globs.NPostes + iposte) + 0.2);
    NMaquinasDespachadas[iposte] := nmaqs;
    m := s.xval(ivar + iposte);
    P[iposte] := m + nmaqs * PMin;
    CostoDirectoDelPaso := CostoDirectoDelPaso + (m * cv + nmaqs * C0) *
      globs.DurPos[iposte];
    if nmaqs > maxNMaquinasDespachadas then
      maxNMaquinasDespachadas := nmaqs;

    if NMaquinasDespachadas[iposte] > 0 then
      costosPorPoste[iposte] :=
        ((P[iposte] - PMin * NMaquinasDespachadas[iposte]) * cv +
        NMaquinasDespachadas[iposte] * c0) * globs.durpos[iposte]
    else
      costosPorPoste[iposte] := 0;
  end;
end;



{$IFDEF SPXCONLOG}
procedure TGTer_combinadoV2.spx_NombrarVariables(s: TSimplex);
var
  iposte: integer;
begin
  if NMaquinasDisponibles = 0 then
    exit;
  for iposte := 0 to globs.NPostes - 1 do
  begin
    s.set_NombreVar(ivar + iposte, Nombre + '_P[MW]' + IntToStr(iposte + 1));
    s.set_NombreVar(ivar + iposte + globs.NPostes, Nombre + '_A' + IntToStr(iposte + 1));
    s.set_NombreRest(ires + iposte, Nombre + '_res-A' + IntToStr(iposte + 1));
  end;
  if pA.HayRestriccionEmaxPasoDeTiempo then
    s.set_NombreRest(ires + globs.NPostes, Nombre + '_res-EMax');
end;

{$ENDIF}

function TGTer_combinadoV2.getNombreVar(ivar: integer; var nombre: string): boolean;
begin
  if NMaquinasDisponibles = 0 then
    Result := False
  else
  if (ivar >= self.ivar) and (ivar < self.ivar + globs.NPostes) then
  begin
    nombre := self.Nombre + '_P[MW]' + IntToStr(ivar - self.ivar + 1);
    Result := True;
  end
  else if (ivar >= self.ivar + globs.NPostes) and
    (ivar < self.ivar + 2 * globs.NPostes) then
  begin
    nombre := self.Nombre + '_A[MW]' + IntToStr(ivar - (self.ivar + globs.NPostes) + 1);
    Result := True;
  end
  else
    Result := False;
end;

function TGTer_combinadoV2.getNombreRes(ires: integer; var nombre: string): boolean;
begin
  if NMaquinasDisponibles = 0 then
    Result := False
  else
  if (ires >= self.ires) and (ires < self.ires + globs.NPostes) then
  begin
    nombre := self.nombre + '_res-A' + IntToStr(ires - self.ires + 1);
    Result := True;
  end
  else if pa.HayRestriccionEmaxPasoDeTiempo and (ires = self.ires + globs.NPostes) then
  begin
    nombre := self.nombre + '_res-EMax';
    Result := True;
  end
  else
    Result := False;
end;

procedure TGTer_combinadoV2.PubliVars;
begin
  inherited PubliVars;
  PublicarVariableVR('Costo', '[USD]', 6, 1, costosPorPoste, True, False);
  PublicarVariableVI('NMaqsDespachadas', '-', NMaquinasDespachadas, True, False);
  declararVarsPSimResPorDefectoIntercalandoPostes(['P', 'Costo', 'NMaqsDespachadas'],
    globs.NPostes);

  PublicarVariableNI('MaxNMaqsDespachadas', '-', maxNMaquinasDespachadas, False);
  PublicarVariableNR('c0', '[USD/h]', 6, 1, c0, False);
  PublicarVariableNI('NMaqsDisponibles', '-', NMaquinasDisponibles, False);

  PublicarVariableNR('PMaxDisponible', '[MW]', 6, 1, PMaxDisponible, False);
  PublicarVariableNR('PMediaDespachada', '[MW]', 6, 1, potMedia_despachada, False);
end;

procedure TGTer_combinadoV2.Free;
begin
  setlength(NMaquinasDespachadas, 0);
  SetLength(costosPorPoste, 0);
  inherited Free;
end;


procedure AlInicio;
begin
  registrarClaseDeCosa(TGTer_combinadoV2.ClassName, TGTer_combinadoV2);
  registrarClaseDeCosa(TFichaGter_combinadoV2.ClassName, TFichaGter_combinadoV2);
end;

procedure AlFinal;
begin
end;

end.








