unit uActorNodal;

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

interface

uses
  uCosa, uGlobs, uActores, uFechas, unodos, uCosaConNombre, uFichasLPD,
  xMatDefs, Classes, uauxiliares, uFuentesAleatorias;

type

  { TActorNodal }

  TActorNodal = class(TActor)
    // Como Gen. Nodo al que inyecta
    cv_Spot: TDAofNReal; // Costo variable del actor para cada poste = cmg - Multiplicador de lagrange de la restricción de caja de la potencia
    Lambda_P: TDAofNReal; // Multiplicador de Lagrange de la restricción de caja de P
    // Como demanda
    Prioridad_DemSpot: Integer;
    procedure BeforeRead(version, id_hilo: integer); override;

    function ReferenciaAlNodo(nodo: TNodo): boolean; virtual; abstract;
    procedure PrepararMemoria(Catalogo: TCatalogoReferencias; globs: TGlobs); override;
    procedure Free; override;
  end;

  { TActorUniNodal }

  TActorUniNodal = class(TActorNodal)
  public
    P: TDAOfNReal; // Inyectada como generador al nodo
    P_horaria: TDAOfNReal; // Inyectada como generador al nodo horaria

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

    Nodo: TNodo;
    barras_flucar: TDAOfNint;
    codigos_flucar: TDAOfString;
    (**************************************************************************)

    // Participacion  por Servicio de Confiabilidad del Sistema
    ParticipacionSCS:nReal;
    // Participacion en Forzamiento  por Servicio de Confiabilidad del Sistema
    ForzamientoSCS:nReal;

    constructor Create(
      capa: integer; nombre: string; nacimiento, muerte: TFecha;
      lpdUnidades: TFichasLPD; Nodo: TNodo;
      xFuenteIdxP: TFuenteAleatoria; xBorneIdxP: string );

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

    function ReferenciaAlNodo(nodo: TNodo): boolean; override;
    procedure PubliVars; override;
    procedure PrepararMemoria(Catalogo: TCatalogoReferencias; globs: TGlobs); override;

    procedure CalcularPagoServicioDeConfiabilidaddelSist; virtual;

    procedure Free; override;
    {$IFDEF BOSTA}
    procedure AfterInstantiation; override;
    {$ENDIF}
  end;

  { TActorBiNodal }

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

    NodoA, NodoB: TNodo;
    (**************************************************************************)

    // resultados del despacho
    P_NodoA, P_NodoB: TDAOfNReal; //[MW] Potencia inyectada como generador en cada Nodo.


    constructor Create(
      capa: integer; nombre: string; nacimiento, muerte: TFecha;
      lpdUnidades: TFichasLPD; NodoA, NodoB: TNodo;
      xFuenteIdxP: TFuenteAleatoria; xBorneIdxP: string );

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

    function ReferenciaAlNodo(nodo: TNodo): boolean; override;
    procedure PrepararMemoria(Catalogo: TCatalogoReferencias; globs: TGlobs); override;
    procedure Free; override;

  end;

procedure AlInicio;
procedure ALFinal;

implementation

{ TActorNodal }

procedure TActorNodal.BeforeRead(version, id_hilo: integer);
begin
  inherited BeforeRead(version, id_hilo);
  setlength( cv_Spot, 0 );
  setlength( Lambda_P, 0 );
  Prioridad_DemSpot:= 0;
end;

procedure TActorNodal.PrepararMemoria(Catalogo: TCatalogoReferencias;
  globs: TGlobs);
begin
  inherited PrepararMemoria(Catalogo, globs);
  setlength( cv_Spot, globs.NPostes );
  setlength( Lambda_P, globs.NPostes );
end;

procedure TActorNodal.Free;
begin
  if cv_spot <> nil then  setlength( cv_Spot, 0);
  if lambda_P <> nil then setlength( Lambda_P, 0 );
  inherited Free;
end;

//--------------------------
// Métodos de TActorUniNodal
//==========================

constructor TActorUniNodal.Create(capa: integer; nombre: string; nacimiento,
  muerte: TFecha; lpdUnidades: TFichasLPD; Nodo: TNodo;
  xFuenteIdxP: TFuenteAleatoria; xBorneIdxP: string);
begin
  inherited Create(capa, nombre, nacimiento, muerte, lpdUnidades, xFuenteIdxP, xBorneIdxP );
  self.Nodo := Nodo;
  barras_flucar := nil;
  codigos_flucar := nil;
  cv_Spot:= nil;
  Lambda_P:= nil;
end;

function TActorUniNodal.Rec: TCosa_RecLnk;
begin
  Result:=inherited Rec;
  Result.addCampoDef_ref('nodo', TCosa(self.Nodo), Self);
  Result.addCampoDef('barras_flucar', barras_flucar, 49);
  Result.addCampoDef('codigos_flucar', codigos_flucar, 49);
  Result.addCampoDef('Prioridad_DemSpot', Prioridad_DemSpot, 160 );
  Result.addCampoDef('ParticipacionSCS', ParticipacionSCS, 185 );
  Result.addCampoDef('ForzamientoSCS', ForzamientoSCS, 185 );
end;

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

procedure TActorUniNodal.AfterRead(f:TArchiTexto);
begin
  inherited AfterRead(f);
  if f.Version >= 49 then
    clear_vacias(codigos_flucar);
  if f.Version < 185 then
  begin
    ParticipacionSCS:=0;
    ForzamientoSCS:=0;
  end;
  self.Nodo := nil;
end;

function TActorUniNodal.ReferenciaAlNodo(nodo: TNodo): boolean;
begin
  Result := self.nodo = nodo;
end;

procedure TActorUniNodal.PubliVars;
begin
  inherited PubliVars;
  PublicarVariableVR('P', 'MW', 6, 2, P, True, True);
//  PublicarVariableVR('P_horaria', 'MW', 6, 2, P_horaria, True, True);
  PublicarVariableVR('cv_Spot', 'USD/MWh', 12, 4, cv_Spot, True, true);
  PublicarVariableVR('Lambda_P', 'USD/MWh', 12, 4, Lambda_P, True, true);
  PublicarVariableNR( 'ParticipacionSCS', 'USD', 12, 2, ParticipacionSCS, True );
  PublicarVariableNR( 'ForzamientoSCS', 'USD', 12, 2, ForzamientoSCS, True );

end;

procedure TActorUniNodal.PrepararMemoria(Catalogo: TCatalogoReferencias; globs: TGlobs);
begin
  inherited PrepararMemoria(Catalogo, globs);
  setlength(P, globs.NPostes);
  setlength(P_horaria, round(globs.HorasDelPaso));
end;

procedure TActorUniNodal.CalcularPagoServicioDeConfiabilidaddelSist;
var
   iPoste: integer;
   CmgMenosTecho, TechoMenosCV: NReal;
begin
    ParticipacionSCS:= 0;
    ForzamientoSCS:=0;
    for iPoste:= 0 to high( P )  do
    begin
       CmgMenosTecho:= nodo.cmarg[iposte] - globs.TechoDelSpot;
       if  CmgMenosTecho > 0  then
       begin
            TechoMenosCV:= globs.TechoDelSpot - CV_spot[iposte];
            if  TechoMenosCV > 0 then
               ParticipacionSCS:= ParticipacionSCS + P[iposte]* globs.durpos[iposte] *  CmgMenosTecho // al ltriangulito.
            else
            begin
               ParticipacionSCS:= ParticipacionSCS + P[iposte]* globs.durpos[iposte] * ( nodo.cmarg[iposte] - CV_Spot[iposte] );  // al triangulito
               ForzamientoSCS:= ForzamientoSCS + P[iposte]* globs.durpos[iposte] * (-TechoMenosCV) ;  // al rectángulito
            end
       end
    end
end;


procedure TActorUniNodal.Free;
begin
  setlength(P, 0);
  setlength(P_horaria, 0);
  inherited Free;
end;


{$IFDEF BOSTA}
procedure TActorUniNodal.AfterInstantiation;
begin

  inherited AfterInstantiation;
  clear_vacias(codigos_flucar);
  self.Nodo := nil;

end;
{$ENDIF}

//-------------------------
// Métodos de TActorBiNodal
//=========================

constructor TActorBiNodal.Create(capa: integer; nombre: string; nacimiento,
  muerte: TFecha; lpdUnidades: TFichasLPD; NodoA, NodoB: TNodo;
  xFuenteIdxP: TFuenteAleatoria; xBorneIdxP: string);
begin
  inherited Create(capa, nombre, nacimiento, muerte, lpdUnidades, xFuenteIdxP, xBorneIdxP );
  self.NodoA := NodoA;
  self.NodoB := NodoB;
  setlength( cv_Spot, 0 );
  setlength( Lambda_P, 0 );
  Prioridad_DemSpot:=1;
end;

function TActorBiNodal.Rec: TCosa_RecLnk;
begin
  Result:=inherited Rec;
  Result.addCampoDef_ref('nodoA', TCosa(NodoA), Self);
  Result.addCampoDef_ref('nodoB', TCosa(NodoB), Self);
end;

procedure TActorBiNodal.BeforeRead(version, id_hilo: integer);
begin
  inherited BeforeRead(version, id_hilo);
  Prioridad_DemSpot:= 1;
end;

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


function TActorBiNodal.ReferenciaAlNodo(nodo: TNodo): boolean;
begin
  Result := (nodoA = nodo) or (nodoB = nodo);
end;

procedure TActorBiNodal.PrepararMemoria(Catalogo: TCatalogoReferencias; globs: TGlobs);

begin
  inherited prepararMemoria(Catalogo, globs);
  setlength(P_NodoA, globs.NPostes);
  setlength(P_NodoB, globs.NPostes);
  setlength( cv_Spot, globs.NPostes );
  setlength( Lambda_P, globs.NPostes );
end;

procedure TActorBiNodal.Free;
begin
  setlength(P_NodoA, 0);
  setlength(P_NodoB, 0);
  setlength( cv_Spot, 0 );
  setlength( Lambda_P, 0 );
  inherited Free;
end;

procedure AlInicio;
begin
  //  registrarClaseDeCosa(TActorUniNodal.ClassName, TActorUniNodal);
  //  registrarClaseDeCosa(TActorBiNodal.ClassName, TActorBiNodal);
end;

procedure AlFinal;
begin
end;

end.
