unit uAcumuladorVars;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, xMatDefs, uExcelFile, uAuxiliares, uParseSimRes, ComCtrls,
  uverdoc;

type
  TAcumuladorVars = class(TForm)
    LBDisponibles: TListBox;
    LBSeleccionadas: TListBox;
    BAddRemove: TButton;
    BGenerar: TButton;
    PB: TProgressBar;
    BAyuda: TButton;
    LVarsDisp: TLabel;
    LVarsSelec: TLabel;
    procedure LBDisponiblesClick(Sender: TObject);
    procedure LBSeleccionadasClick(Sender: TObject);
    procedure BAddRemoveClick(Sender: TObject);
    procedure BGenerarClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure BAyudaClick(Sender: TObject);
  private
    archivo: String;

    //Fecha de inicio y fin de la simulacion
    FechaIni, FechaFin : TDateTime;

    //Números de actores, cronicas, pasos, postes y variables
    nActores, nCronicas, nPasos, nPostes, nVars : Integer;

    //durPos
    durPos: TDAofNReal;

    //Los encabezados con los nombres de los actores y las variables
    actores, vars: TStringList;

    //Carga las lineas del comienzo, inicializa nPasos, nCronicas y nVars, y calcula
    //filasPrimerPaso
    procedure leerDatosSimulacion;

    //Separa s en nomActor y nomVar para identificarlo en las columnas
    procedure SplitNomVar(const s : String; var nomActor, nomVar : String);
    //Junta nomActor y nomVar en s para ponerlo en la lista de variables
    procedure JoinNomVar(const nomActor, nomVar : String ; var s : String);

    //retorna el indice de columna en el archivo original del string actVar
    function indiceActVar(const actVar: String) : Integer;

    function indicesColsSeleccionadas : TDAofNInt;

    procedure sumarVars;
  public
    Constructor Create(owner : TComponent ; nArch: String); reintroduce;
    class function filtrosDeArchivos: String;
  end;

var
  AcumuladorVars: TAcumuladorVars;

implementation

uses uconstantesSimSEE;

{$R *.dfm}

Constructor TAcumuladorVars.Create(owner : TComponent ; nArch: String);
begin
  inherited Create(owner);
  archivo:= nArch;
  Self.Caption:= 'Acumulador de Variables - ' + nArch;
end;

class function TAcumuladorVars.filtrosDeArchivos: String;
begin
  result:= 'Archivos de Resultado de Simulación (simres_*.xlt)|simres_*.xlt';
end;

procedure TAcumuladorVars.FormCreate(Sender: TObject);
begin
  leerDatosSimulacion;
end;

function SortByIndiceActVar(Item1, Item2: Pointer) : Integer;
var
  i1, i2 : Integer;
begin
  i1:= AcumuladorVars.indiceActVar(String(Item1));
  i2:= AcumuladorVars.indiceActVar(String(Item2));
  if i1 < i2 then
    result:= -1
  else if i1 = i2 then
    result:= 0
  else result:= 1;
end;

procedure TAcumuladorVars.BAddRemoveClick(Sender: TObject);
var
  index: Integer;
begin
  if BAddRemove.Caption = '->' then
  begin
    index:= LBDisponibles.ItemIndex;
    if index >= 0 then
    begin
      LBSeleccionadas.Items.Add(LBDisponibles.Items[index]);
      LBDisponibles.Items.Delete(index);
      if LBDisponibles.Count <> 0 then
        LBDisponibles.ItemIndex:= index;
      LBSeleccionadas.ItemIndex:= -1;
    end;
  end
  else
  begin
    index:= LBSeleccionadas.ItemIndex;
    if index >= 0 then
    begin
      LBDisponibles.Items.Add(LBSeleccionadas.Items[index]);
      LBSeleccionadas.Items.Delete(index);
      if LBSeleccionadas.Count <> 0 then
        LBSeleccionadas.ItemIndex:= index;
      LBDisponibles.ItemIndex:= -1;
    end;
  end;
end;

procedure TAcumuladorVars.BAyudaClick(Sender: TObject);
begin
  verdoc( 'procesador-resultados-AcumuladorVars', 'Ayuda del Acumulador de Variables');
end;

procedure TAcumuladorVars.BGenerarClick(Sender: TObject);
begin
  if LBSeleccionadas.Count <> 0 then
  begin
    LBDisponibles.Enabled:= false;
    LBSeleccionadas.Enabled:= false;
    BAddRemove.Enabled:= false;
    sumarVars;
    LBDisponibles.Enabled:= true;
    LBSeleccionadas.Enabled:= true;
    BAddRemove.Enabled:= true;
  end
  else
    ShowMessage('No selecciono ninguna variable!')
end;

procedure TAcumuladorVars.leerDatosSimulacion;
var
  entrada: TextFile;
  i: Integer;
  linea: String;
begin
  try
    AssignFile(entrada, archivo);
    Reset(entrada);

    //Inicio simulación:
    Readln(entrada, linea);

    //FechaIni FechaFin
    Readln(entrada, linea);
    nextPal(linea); FechaIni:= StrToDateTime(NextPal(linea));
    NextPal(linea); FechaFin:= StrToDateTime(NextPal(linea));
    //NActores
    Readln(entrada, linea);
    NextPal(linea);
    nActores:= NextInt(linea);
    //NCronicas
    Readln(entrada, linea);
    NextPal(linea);
    nCronicas:= NextInt(linea);
    //NPasos
    Readln(entrada, linea);
    NextPal(linea);
    nPasos:= NextInt(linea);
    //NPostes
    Readln(entrada, linea);
    NextPal(linea);
    nPostes:= NextInt(linea);
    SetLength(durPos, nPostes);
    //Durpos
    Readln(entrada, linea);
    NextPal(linea);
    for i:= 0 to nPostes - 1 do
      durPos[i]:= NextFloat(linea);
    readln(entrada, linea);

    //Cronica RandSeed
    Readln(entrada, linea);

    //Actores
    Readln(entrada, linea);
    actores:= TStringList.Create;
    //Como los -
    actores.Add(NextPal(linea)); actores.Add(NextPal(linea));

    nVars:= 0;
    while linea <> '' do
    begin
      inc(nVars);
      actores.Add(nextTab(linea));
    end;

    vars:= TStringList.Create;
    vars.Capacity:= actores.Count;

    readln(entrada, linea);
    //Paso	FechaInicioDelPaso
    vars.Add(NextPal(linea)); vars.Add(NextPal(linea));
    while linea <> '' do
      vars.Add(nextTab(linea));

    for i:= 2 to actores.Count - 1 do
    begin
      JoinNomVar(actores[i], vars[i], linea);
      LBDisponibles.Items.Add(linea);
    end;
  finally
    CloseFile(entrada);
  end;
end;

procedure TAcumuladorVars.SplitNomVar(const s : String; var nomActor, nomVar : String);
var
  posComa: Integer;
begin
  posComa:= Pos(', ', s);
  nomActor:= Copy(s, 0, posComa -1);
  nomVar:= Copy(s, posComa + 2, Length(s) - posComa + 2);
end;

procedure TAcumuladorVars.JoinNomVar(const nomActor, nomVar : String ; var s : String);
begin
  s:= nomActor + ', ' + nomVar;
end;

function TAcumuladorVars.indiceActVar(const actVar: String) : Integer;
var
  nomAct, nomVar: String;
  res, i: Integer;
begin
  res:= 0; //Para sacar el warning
  SplitNomVar(actVar, nomAct, nomVar);
  for i:= 0 to actores.Count - 1 do
    if (actores[i] = nomAct) and (vars[i] = nomVar) then
    begin
      res:= i;
      break;
    end;
  result:= res;
end;

function TAcumuladorVars.indicesColsSeleccionadas : TDAofNInt;
var
  res: TDAofNInt;
  i: Integer;
begin
  SetLength(res, LBSeleccionadas.Items.Count);
  for i:= 0 to high(res) do
    res[i]:= indiceActVar(LBSeleccionadas.Items[i]);
  QuickSort_Creciente(res);
  result:= res;
end;

procedure TAcumuladorVars.sumarVars;
var
  entrada, salida: TextFile;

  iPaso, iCronica, ivar, icol: Integer;
  colsSeleccionadas: TDAofNInt;
  fila: TDAofNReal;
  matrRes: array of TDAofNReal;

  invNCronicas, invNPasos: NReal;
  promPaso: NReal;
  promediosPorCronica, promediosPorPaso : TDAofNReal;
  linea: String;
begin
  try
    AssignFile(entrada, archivo);
    Reset(entrada);
    try
      AssignFile(salida, 'sumaVars.xlt');
      Rewrite(salida);

      PB.Position:= 1;
      PB.Max:= nCronicas;
      PB.Step:= 1;

      colsSeleccionadas:= indicesColsSeleccionadas;
      SetLength(matrRes, nPasos);
      for iPaso:= 0 to nPasos -1 do
      begin
        SetLength(matrRes[iPaso], nCronicas);
        fila:= matrRes[iPaso];
        for iCronica := 0 to high(fila) do
          fila[iCronica]:= 0;
      end;

      //Leo las 11 lineas hasta el primer paso
      readln(entrada, linea); readln(entrada, linea); readln(entrada, linea);
      readln(entrada, linea); readln(entrada, linea); readln(entrada, linea);
      readln(entrada, linea); readln(entrada, linea); readln(entrada, linea);
      readln(entrada, linea); readln(entrada, linea);

      for iCronica:= 0 to nCronicas - 1 do
      begin
        for iPaso:= 0 to nPasos - 1 do
        begin
          readln(entrada, linea);
          icol:= 0;
          for ivar:= 0 to high(colsSeleccionadas) do
          begin
            while icol < colsSeleccionadas[ivar] do
            begin
              inc(icol);
              NextPal(linea);
            end;
            matrRes[iPaso][iCronica]:= matrRes[iPaso][iCronica] + NextFloat(linea);
            inc(icol);
          end;
        end;
        //leo 4 lineas que no se usan
        if not EoF(entrada) then readln(entrada, linea);
        if not EoF(entrada) then readln(entrada, linea);
        if not EoF(entrada) then readln(entrada, linea);
        if not EoF(entrada) then readln(entrada, linea);
        PB.StepIt;
        Application.ProcessMessages;
      end;

      SetLength(promediosPorPaso, nPasos);
{      for iPaso:= 0 to high(promediosPorPaso) do
        promediosPorPaso[iPaso]:= 0;}
      SetLength(promediosPorCronica, nCronicas);
      for iCronica:= 0 to high(promediosPorCronica) do
        promediosPorCronica[iCronica]:= 0;

      invNCronicas:= 1 / nCronicas;
      for iPaso:= 0 to high(promediosPorPaso) do
      begin
        fila:= matrRes[ipaso];
        promPaso:= 0;
        for iCronica:= 0 to high(promediosPorCronica) do
        begin
          promPaso:= promPaso + fila[iCronica];
          promediosPorCronica[iCronica]:= promediosPorCronica[iCronica] + fila[iCronica];
        end;
        promediosPorPaso[iPaso]:= promPaso * invNCronicas;
      end;

      invNPasos:= 1 / nPasos;
      for iCronica:= 0 to high(promediosPorCronica) do
        promediosPorCronica[iCronica]:= promediosPorCronica[iCronica] * invNPasos;

      write(salida, 'Paso\Cronica' + #9);
      for iCronica:= 1 to nCronicas do
        Write(salida, IntToStr(iCronica) + #9);
      writeln(salida, 'Promedio_del_Paso');

      for iPaso:= 0 to nPasos - 1 do
      begin
        Write(salida, IntToStr(iPaso + 1) + #9);
        fila:= matrRes[iPaso];
        for iCronica := 0 to high(fila) do
          Write(salida, FloatToStr(fila[iCronica]) + #9);
        writeln(salida, FloatToStr(promediosPorPaso[iPaso]));
      end;
      write(salida, 'Promedio_de_la_Cronica' + #9);
      for iCronica:= 0 to high(promediosPorCronica) do
        write(salida, FloatToStr(promediosPorCronica[iCronica]) + #9);

    finally
      CloseFile(salida);
    end;
  finally
    CloseFile(entrada);
  end;
end;

procedure TAcumuladorVars.LBDisponiblesClick(Sender: TObject);
begin
  BAddRemove.Caption:= '->';
end;

procedure TAcumuladorVars.LBSeleccionadasClick(Sender: TObject);
begin
  BAddRemove.Caption:= '<-'
end;

end.
