unit ufuenteoperacionmultifuente;

interface

uses
  uFuentesAleatorias, ucosa, uCosaConNombre,
  classes, uparseadorsupersimple, uauxiliares,
  uFichasLPD, xMatDefs, uFechas, SysUtils;

resourcestring
  rsFichaDe = 'Ficha de';
  rsFuenteDeCombinacion = 'Fuente Operación Multi-Fuente';

type

(*+doc TFichaFuenteOperacionMultiFuente
Ficha de parámetros dinámicos de fuente Operación Multi-Fuente.
Permite especificar una expresión para evaluar los bornes de salida.

 y = expr( x1, x2, ..... )


-doc*)

  { TFichaFuenteOperacionMultiFuente }

  TFichaFuenteOperacionMultiFuente = class(TFichaLPD)
  public
    expresion: string;

    constructor Create(capa: integer; fecha: TFecha; periodicidad: TPeriodicidad;
      expresion: string);
     
    function Rec: TCosa_RecLnk; override;

    class function DescClase: string; override;
    function infoAd_: string; override;

    function GetLines: TStrings;
    procedure SetLines( ls: TStrings );
    function GetAsStr: string;
  end;



(*+doc TFuenteOperacionMultiFuente
-doc*)

  { TFuenteOperacionMultiFuente }

  TFuenteOperacionMultiFuente = class(TFuenteAleatoriaConFichas)
  public
    pa: TFichaFuenteOperacionMultiFuente;
    Entradas_Nombres: TStringList;
    Entradas_FuenteBorne: TListaDeCosas;

    constructor Create(
       capa: integer;
       nombre: string;
       lpd: TFichasLPD;
       Salidas_NombreBorne: TStringList;
       Entradas_Nombres: TStringList;
       Entradas_FuenteBorne: TListaDeCosas );

    class function TipoFichaFuente: TClaseDeFichaLPD; override;

    function Rec: TCosa_RecLnk; override;

    class function DescClase: string; override;
    procedure RegistrarParametrosDinamicos( Catalogo: TCatalogoReferencias ); override;
    procedure SorteosDelPaso(xsortear: boolean); override;
    procedure SortearEntradaRB(var aRB: NReal); override;
    procedure ValorEsperadoEntradaRB(var aRB: Nreal); override;
    function referenciaFuente(fuente: TFuenteAleatoria): boolean; override;

    procedure PubliVars; override;
    procedure CambioFichaPD; override;
    destructor destroy; override;
private
    Evaluador: TEvaluadorExpresionesSimples;
    aScript: TExprLst;
    Entradas_PlaceHolder, Salidas_PLaceHolder: array of TVar;
  end;

procedure procCambioFichaOperacionMultiFuente(fuente: TCosa);
procedure AlInicio;
procedure AlFinal;

implementation
uses
  usalasdejuego;

//-----------------------------------
// Métodos de TFichaFuenteOperacionMultiFuente
//===================================

constructor TFichaFuenteOperacionMultiFuente.Create(capa: integer;
  fecha: TFecha; periodicidad: TPeriodicidad; expresion: string);
begin
  inherited Create(capa, fecha, periodicidad);
  self.expresion:= expresion;
end;

function TFichaFuenteOperacionMultiFuente.Rec: TCosa_RecLnk;
begin
  Result:=inherited Rec;
  Result.addCampoDef('expresion', expresion);
end;




class function TFichaFuenteOperacionMultiFuente.DescClase: string;
begin
  Result := rsFichaDe + ' ' + rsFuenteDeCombinacion;
end;

function TFichaFuenteOperacionMultiFuente.infoAd_: string;
begin
  Result := expresion;
end;

function TFichaFuenteOperacionMultiFuente.GetLines: TStrings;
var
  ls: TStringList;
begin
  ls:= TStringList.Create;
  ls.Delimiter:= '|';
  ls.DelimitedText:= expresion;
  result:= ls;
end;

procedure TFichaFuenteOperacionMultiFuente.SetLines(ls: TStrings);
begin
  ls.Delimiter:= '|';
  expresion:= ls.DelimitedText;
end;


function TFichaFuenteOperacionMultiFuente.GetAsStr: string;
var
  slst: TStringList;
  ts, res: string;
  k: integer;
  iPosBarraBarra: integer;

begin
  slst:= TStringList.Create;
  slst.Delimiter:= '|';
  slst.DelimitedText:= expresion;
  res:= '';
  for k:= 0 to slst.count-1 do
  begin
    ts:= trim(  slst[k] );
    iPosBarraBarra := pos('//', ts);
    if iPosBarraBarra > 0 then
      ts := copy(ts, 1, iPosBarraBarra - 1);
    ts:= trim( ts );
    if ts <> '' then
      res:= res + ' '+ ts;
  end;
  result:= res;
  slst.Free;
//  result:= MemoToStr( expresion, '|' );
end;





//------------------------------
// Métodos de TFuenteOperacionMultiFuente
//==============================

constructor TFuenteOperacionMultiFuente.Create(capa: integer; nombre: string;
  lpd: TFichasLPD; Salidas_NombreBorne: TStringList;
  Entradas_Nombres: TStringList; Entradas_FuenteBorne: TListaDeCosas);
begin
  inherited Create(capa, nombre, 0, True, lpd);
  self.Entradas_FuenteBorne:= Entradas_FuenteBorne;
  self.Entradas_Nombres:= Entradas_Nombres;
end;

class function TFuenteOperacionMultiFuente.TipoFichaFuente: TClaseDeFichaLPD;
begin
  Result := TFichaFuenteOperacionMultiFuente;
end;

function TFuenteOperacionMultiFuente.Rec: TCosa_RecLnk;
begin
  Result:=inherited Rec;
  Result.addCampoDef('Entradas_FuenteBorne', TCosa(Entradas_FuenteBorne) );
  result.addCampoDef('Entradas_Nombres', Entradas_Nombres );
end;

class function TFuenteOperacionMultiFuente.DescClase: string;
begin
  Result := rsFuenteDeCombinacion;
end;

procedure TFuenteOperacionMultiFuente.RegistrarParametrosDinamicos(
  Catalogo: TCatalogoReferencias);
begin
  lpd.RegistrarFichasAActualizar(Self, globs.ActualizadorLPD, @pa,
    nil, procCambioFichaOperacionMultiFuente );
end;

procedure TFuenteOperacionMultiFuente.SorteosDelPaso(xsortear: boolean);
var
  i: integer;
  ficha: TFuenteAleatoria_Borne;
begin
  // EVALUACION
  // Fijamos los valores de entrada
    for i := 0 to Entradas_FuenteBorne.Count-1 do
    begin
      ficha:= Entradas_FuenteBorne[i] as TFuenteAleatoria_Borne;
      Entradas_PlaceHolder[i].val.Val_F := ficha.Valor;
    end;

  // Evaluamos
   aScript.evaluar;

  // Leemos valores de salida
   for i:= 0 to high( salidas_PlaceHolder ) do
     bornera[i] := Salidas_PlaceHolder[i].val.Val_F;

end;


procedure TFuenteOperacionMultiFuente.SortearEntradaRB( var aRB: NReal);
begin
   raise Exception.Create( 'Llamada a : TFuenteOperacionMultiFuente.SortearEntradaRB .. NO PERMITIDA!!' );
end;

procedure TFuenteOperacionMultiFuente.ValorEsperadoEntradaRB(var aRB: Nreal);
begin
  raise Exception.Create( 'Llamada a : ValorEsperadoEntradaRB.SortearEntradaRB .. NO PERMITIDA!!' );
end;

function TFuenteOperacionMultiFuente.referenciaFuente(fuente: TFuenteAleatoria): boolean;
var
  i: integer;
  res: boolean;
  ficha: TFuenteAleatoria_Borne;
begin
  res := False;
  for i := 0 to Entradas_FuenteBorne.Count - 1 do
  begin
    ficha:= Entradas_FuenteBorne[i] as TFuenteAleatoria_Borne;
    if (fuente = ficha.fuente) then
    begin
      res := True;
      break;
    end;
  end;
  Result := res;
end;

procedure TFuenteOperacionMultiFuente.PubliVars;
var
  i: integer;
begin
 inherited PubliVars;
 for i:= 0 to NombresDeBornes_Publicados.count-1 do
   PublicarVariableNR( NombresDeBornes_Publicados[i], '-', 15, 15, Bornera[i], True);
end;


procedure TFuenteOperacionMultiFuente.CambioFichaPD;
var
  i: integer;
  ficha: TFuenteAleatoria_Borne;
  ssNombre: string;
  rVal: double;
  s_expresion: string;
begin
  inherited CambioFichaPD;

  // Con cambio fichalpd actualizo ele evaluador
  // y referencia a ls variables dentro de la expresión.

   if evaluador =nil then
   begin
     evaluador := TEvaluadorExpresionesSimples.Create;
     TSalaDeJuego( globs.sala ).AgregarDefinicionesEvaluador(Evaluador);
   end;

  // indexamos las entradas
    setlength( Entradas_PlaceHolder, Entradas_FuenteBorne.count );
    for i := 0 to high( Entradas_PlaceHolder ) do
    begin
      ficha:= Entradas_FuenteBorne[i] as TFuenteAleatoria_Borne;

      // esto es solo para que quede definido el idBorne en la ficha y luego
      // sepa calcular el valor.
      ficha.DarIdBorne( self );

      ssNombre:= self.Entradas_Nombres[i];

      // Asignamos cualquier cosa solo para crear la variable
      if not evaluador.Ejecutar( rval, ssNombre+':= 12.1222' ) then
        raise Exception.Create('TAdminEstados.InicializarFrameFinal, imposible evaluar: '+ssNombre+':= 33.333' );

      // Guardamos la referncia para poder inicializar los datos antes de evaluar
      Entradas_PlaceHolder[i]:= evaluador.FindVar( ssNombre );
    end;

//    s_expresion:= MemoToStr( pa.expresion, '|' ); ;
      s_expresion:= pa.GetAsStr;


    if pos( '"', s_expresion ) = 1 then
     delete( s_expresion, 1, 1 );
    if s_expresion[length( s_expresion ) ] = '"' then
     delete( s_expresion, length( s_expresion ), 1 );

    aScript := evaluador.GetExprLst( s_expresion );
    aScript.evaluar;

    setlength( Salidas_PlaceHolder, NombresDeBornes_Publicados.Count );
    for i:= 0 to high( Salidas_PlaceHolder ) do
    begin
      ssNombre:= NombresDeBornes_Publicados[i];
      Salidas_PLaceHolder[i]:= evaluador.FindVar( ssNombre );
    end;

end;

destructor TFuenteOperacionMultiFuente.destroy;
begin
  Entradas_Nombres.Free;
  Entradas_FuenteBorne.Free;
  setlength( Entradas_PlaceHolder, 0 );
  setlength( Salidas_PLaceHolder, 0 );

  aScript.Free;  // ojo este tiene que hacer Free antes que el Evaluador
  Evaluador.Free;

  inherited destroy;
end;

procedure procCambioFichaOperacionMultiFuente(fuente: TCosa);
begin
  cambioFichaPDFuenteAleatoria(fuente);
  (fuente as TFuenteOperacionMultiFuente).CambioFichaPD;
end;

procedure AlInicio;
begin
  registrarClaseDeCosa(TFuenteOperacionMultiFuente.ClassName, TFuenteOperacionMultiFuente);
  registrarClaseDeCosa(TFichaFuenteOperacionMultiFuente.ClassName, TFichaFuenteOperacionMultiFuente);
end;

procedure AlFinal;
begin
end;

end.
