unit uDTSintetizador;

interface

uses
  xMatDefs, Classes, SysUtils, uAuxiliares, matreal;

const
  separator = #9;

type
  //Por cada punto de la función deformante se tiene un arreglo de reales con el valor
  //de la deformación de x perteneciente a [0, 1]
  TDAOfFuncionDeformante = array of TDAofNReal;

  //Datatype para leer el archivo de un sintetizador
  TDTSintetizador = class
  public
    A, B, R, RT: TMatR;

    //Número de variables de estado
    nVE: integer;
    //Número de discretizaciones de las variables de estado
    nDiscsVsE: TDAofNInt;

    // Probabilidad acumulada asignada al punto de discretización
    ProbsVsE: array of TDAofNReal;

    //Los nombres de las variables de estado
    nombreVar: TDAofString;

    //Contiene las functiones deformantes para cada serie
    funcionesDeformantes: array of TDAOfFuncionDeformante;

    //Es la cantidad de salidas que presenta la fuente a los actores
    //Es igual a NombresDeBornes_Publicados.Count
    nBornesSalida: integer;

    durPasoDeSorteoEnHoras: integer;
    // Nombres de los bornes
    NombresDeBornes_Publicados: TStringList;

    EstadoInicial_Real: TDAofNReal;

    constructor Create(nombreArchivo: string);
    procedure Free;
  end;

implementation

constructor TDTSintetizador.Create(nombreArchivo: string);
var
  f: TextFile;
  linea, num: string;
  nPuntosPorPeriodo, nPuntosPorFuncionDeformante, nFuentesRBlancoGaussiano: integer;
  posSeparador, i, j, k: integer;
  normaFilaR: NReal;
  funcionesDeformantesI: TDAOfFuncionDeformante;
  funcionesDeformantesIJ: TDAofNReal;
  //Lee lineas del archivo hasta que llega a una que no este en blanco y la devuelve
  //Borra todos los separadores al final de la linea
  function comerLineasEnBlanco: string;
  begin
    Readln(f, linea);
    linea := trim(linea);
    while not EOF(f) and (linea = '') do
    begin
      Readln(f, linea);
      linea := trim(linea);
    end;
    Result := linea;
  end;


  //Lee separadores del archivo hasta llegar a la cantidad indicada
  //La linea ya debe estar cargada
  procedure comerSeparadores(cantSeparadores: integer; var linea: string);
  var
    iter: integer;
  begin
    for iter := 0 to cantSeparadores - 1 do
    begin
      posSeparador := pos(separator, linea);
      linea := copy(linea, posSeparador + 1, MAXINT);
    end;
  end;

begin
  if FileExists(nombreArchivo) then
  begin
    try
      AssignFile(f, nombreArchivo);
      Reset(f);
      NombresDeBornes_Publicados := TStringList.Create;


      readln(f, linea);

      //Leo la cantidad de series de salida
      readln(f, linea);
      NextPal(linea);
      nBornesSalida := NextInt(linea);

      //Leo la cantidad de puntos por período
      Readln(f, linea);
      NextPal(linea);
      nPuntosPorPeriodo := NextInt(linea);

      //Leo la cantidad de puntos por función deformante
      Readln(f, linea);
      NextPal(linea);
      nPuntosPorFuncionDeformante := NextInt(linea);

      //Leo la duración del paso de sorteo EN HORAS
      Readln(f, linea);
      NextPal(linea);
      durPasoDeSorteoEnHoras := NextInt(linea);

      //Leo las funciones deformantes de las series
      SetLength(funcionesDeformantes, nBornesSalida);
      for i := 0 to nBornesSalida - 1 do
      begin
        linea := comerLineasEnBlanco;//Nombre de la serie
        uauxiliares.Nextpal(linea);
        self.NombresDeBornes_Publicados.Add(uauxiliares.Nextpal(linea));
        Readln(f, linea);//intervalos
        SetLength(funcionesDeformantes[i], nPuntosPorPeriodo);
        funcionesDeformantesI := funcionesDeformantes[i];
        for j := 0 to nPuntosPorPeriodo - 1 do
        begin
          //leo los vectores para cada punto de la función deformante
          Readln(f, linea);

          //saco el paso: y el numero
          comerSeparadores(2, linea);
          SetLength(funcionesDeformantesI[j], nPuntosPorFuncionDeformante);
          funcionesDeformantesIJ := funcionesDeformantesI[j];
          for k := 0 to nPuntosPorFuncionDeformante - 1 do
            funcionesDeformantesIJ[k] := NextFloat(linea);
        end;
      end;//Termino con las series
      linea := comerLineasEnBlanco;

      //Numero de Fuentes De Ruido Blanco Gaussiano
      Readln(f, linea);
      NextPal(linea);
      nFuentesRBlancoGaussiano := NextInt(linea);

      Readln(f, linea); //Aca iría NSS pero ya lo leimos antes
      comerLineasEnBlanco;//Vuelve con Filtro A
      Readln(f, linea); //Nombres de las columnas

      A := TMatR.Create_Init(nBornesSalida, nBornesSalida);
      B := TMatR.Create_Init(nBornesSalida, nFuentesRBlancoGaussiano);

      for i := 1 to nBornesSalida do
      begin
        Readln(f, linea);
        comerSeparadores(3, linea);
        for j := 1 to nBornesSalida - 1 do
        begin
          posSeparador := pos(separator, linea);
          num := copy(linea, 0, posSeparador - 1);
          A.pon_e(i, j, StrToFloat(num));
          comerSeparadores(1, linea);
        end;
        posSeparador := pos(separator, linea);
        num := trim(copy(linea, 0, posSeparador - 1));
        A.pon_e(i, nBornesSalida, StrToFloat(num));

        comerSeparadores(2, linea);

        for j := 1 to nFuentesRBlancoGaussiano do
        begin
          posSeparador := pos(separator, linea);
          num := trim(copy(linea, 0, posSeparador - 1));
          B.pon_e(i, j, StrToFloat(num));
          comerSeparadores(1, linea);
        end;
      end;

      SetLength(EstadoInicial_Real, nBornesSalida);

      linea := comerLineasEnBlanco;
      if not EOF(f) then
      begin
        //nVE
        NextPal(linea);
        nVE := NextInt(linea);
        SetLength(nDiscsVsE, nVE);
        SetLength(nombreVar, nVE);
        R := TMatR.Create_Init(nVe, nBornesSalida);
        // Creavos la matriz de probabilidades
        setlength(ProbsVsE, nVE);

        for i := 1 to nVE do
        begin
          readln(f, linea);
          //ndi
          NextPal(linea);
          nDiscsVsE[i - 1] := NextInt(linea);
          //nombre de la var
          nombreVar[i - 1] := NextPal(linea);
          for j := 1 to nBornesSalida do
          begin
            num := NextPal(linea);
            R.pon_e(i, j, StrToFloat(num));
          end;
          //EstadoInicial
          NextPal(linea);
          EstadoInicial_Real[i - 1] := NextFloat(linea);

          // leemos las probabilidades asignadas
          readln(f, linea);
          nextpal(linea);
          setlength(ProbsVsE[i - 1], nDiscsVsE[i - 1]);
          for  j := 0 to nDiscsVsE[i - 1] - 1 do
            ProbsVsE[i - 1][j] := NextFloat(linea);
        end;
        RT := TMatR.Create_Init(R.nc, R.nf);
        for i := 1 to R.nf do
        begin
          normaFilaR := 1 / R.pm[i].ne2;
          for j := 1 to RT.nf do
            RT.pon_e(j, i, R.e(i, j) * normaFilaR);
        end;
      end
      else
      begin
        nVE := 0;
      end;
    finally
      CloseFile(f);
    end;
  end
  else
    raise Exception.Create('No se encuentra el archivo ' + nombreArchivo);
end;

procedure TDTSintetizador.Free;
var
  i, j: integer;
begin
  for i := 0 to High(funcionesDeformantes) do
    for j := 0 to high(funcionesDeformantes[i]) do
      funcionesDeformantes[i][j] := nil;
  SetLength(nDiscsVsE, 0);
  for i := 0 to high(ProbsVsE) do
    setlength(ProbsVsE[i], 0);
  setlength(ProbsVsE, 0);

  SetLength(nombreVar, 0);
  NombresDeBornes_Publicados.Free;
  A.Free;
  B.Free;
  if R <> nil then
    R.Free;
  if RT <> nil then
    RT.Free;
end;

end.
