unit uArbol;


interface

uses
  Classes, SysUtils,
  usalasdejuego,
  ucosa, xmatdefs, ufechas, Dialogs,
  uConstantesSimSEE,
  uauxiliares;

type
  TBifurcacion = class
  private
    fTipoBif: string;
  public
    property Tipobifurcacion: string read fTipoBif write fTipoBif;
    constructor Create();
  end;


  TRama = class;
  ptRama = ^ TRama;
  ptNodo = ^TNodo;

  TNodo = class
    Nombre: string;
    Fecha: TDateTime;
    NodoPadre: ptNodo;
    ramas: TList; {Lista de Ramas}

    TipoBifurcacion: TBifurcacion; // Accion o Involuntaria }

    flg_Hoja: boolean; {Extremos del arbol o nodos sin mas bifurcaciones}
    Grado: integer;
    flg_Optimizado: boolean;

    constructor Create(Nombre: string; Fecha: TDateTime; NodoPadre: ptNodo;
      TipoBifurcacion: TBifurcacion; Hoja: boolean; Grado: integer);
    constructor Create_Clone(x: ptNodo);
    procedure agregar_rama(Rama: TRama);
  end;


  TRama = class
  private
    fnombre: string;
    fcapas: TDAOfNInt; { Lista de capas }
    fProbCapas: NReal;
    FNodo: ptNodo;
  public
    property capas: TDAOfNInt read fcapas write fcapas;
    property Nombre: string read fnombre write fnombre;
    property ProbCapas: NReal read fProbCapas write fProbCapas;
    property Nodo: ptNodo read fNodo write fNodo;
    constructor Create(Nombre: string; capas: TDAOfNInt; Prob: NReal; Nodo: ptNodo);
    constructor Create_Clone(x: ptRama);
  end;

  TGrafo = class
  public
    Nodo: ptNodo;
  end;

  TArbolEscenarios = class
  private
    fNombre: string;
    fSala: TSalaDeJuego;
    fRaiz: ptNodo;
    fFecha_iniopt: TFecha;
    fFecha_finopt: TFecha;
    fFecha_inisim: TFecha;
    fFecha_finsim: TFecha;
    fNodos: TList;
    fRamas: TList;
    fMaxGrado: integer;
    //fCF: TMatOfNReal;

  public

    property Nombre: string read fNombre write fNombre;
    property Sala: TSalaDeJuego read fSala write fSala;
    property Raiz: ptNodo read fRaiz write fRaiz;
    property Fecha_Iniopt: TFecha read fFecha_iniopt write fFecha_iniopt;
    property Fecha_Finopt: TFecha read fFecha_finopt write fFecha_finopt;
    property Fecha_Inisim: TFecha read fFecha_inisim write fFecha_inisim;
    property Fecha_Finsim: TFecha read fFecha_finsim write fFecha_finsim;
    property Nodos: TList read fNodos write fNodos;
    property Ramas: TList read fRamas write fRamas;
    property MaxGrado: integer read fMaxGrado write fMaxGrado;
    //property CF : TMatOfNReal read fCF write fCF;


    constructor create_init();
    constructor create_init_from_file(f: string);
    procedure insertar_nodo(Origen, Nodo: ptNodo);
    procedure eliminar_nodo();
    procedure recorrer_optimizando(Nodo: ptNodo);
    procedure mostrar(nodo: ptNodo);
    function Nodo_a_optmizar(Nodo: ptNodo): boolean;
    procedure recorrer_simulando();
    procedure optimizar_nodo(nodo: ptNodo);

  end;

procedure optimizarnodorama(nodo: ptNodo; rama: ptRama);


implementation

constructor TBifurcacion.Create();
begin
  inherited Create;
end;

constructor TRama.Create(Nombre: string; capas: TDAOfNInt; Prob: NReal; Nodo: ptNodo);
begin
  inherited Create;
  New(fNodo);
  fnombre := Nombre;
  setlength(fcapas, length(capas));
  vcopy(fcapas, capas);
  fProbCapas := Prob;
  fNodo := Nodo;
end;

constructor TRama.Create_Clone(x: ptRama);
begin

end;

constructor TNodo.Create(Nombre: string; Fecha: TDateTime; NodoPadre: ptNodo;
  TipoBifurcacion: TBifurcacion; Hoja: boolean; Grado: integer);
begin
  inherited Create;
  ramas := TList.Create;
  Self.Nombre := Nombre;
  self.Fecha := Fecha;
  flg_Hoja := Hoja;
  self.TipoBifurcacion := TipoBifurcacion;
  self.NodoPadre := NodoPadre;
  flg_Optimizado := Hoja; // Si es una hoja ya está optimizada.
end;


constructor TNodo.Create_Clone(x: ptNodo);
begin
  inherited Create;

end;

procedure TNodo.agregar_rama(Rama: TRama);
begin
  Ramas.Add(Rama);
end;

constructor TArbolEscenarios.create_init();
begin

end;

constructor TArbolEscenarios.create_init_from_file( f: string);
var
  Raiz, Fin: TNodo;
  RamaPrincipal: TRama;
  BifIni, BifFin: TBifurcacion;
begin
  inherited Create;

  if fSala <> nil then
  begin
    fSala.Free;
    fsala := nil;
  end;

  try
    fsala := TSalaDeJuego.cargarSala(0, f, '__principal__', True);
  except
    on E: Exception do
    begin
      ShowMessage('CargarSala, Error:' + #13 + E.Message);
      raise;
    end;

  end;
  New(Raiz);
  New(Fin);
  New(RamaPrincipal);
  fFecha_iniopt := fsala.globs.fechaIniOpt;
  fFecha_finopt := fsala.globs.fechaFinOpt;
  fFecha_inisim := fsala.globs.fechaInisim;
  fFecha_finsim := fsala.globs.fechaFinsim;
  fNodos := TList.Create;
  fRamas := TList.Create;
  BifIni := TBifurcacion.Create;
  BifIni.fTipoBif := 'Inicial';
  BifFin := TBifurcacion.Create;
  BifFin.fTipoBif := 'Final';

  fNombre := 'AEsc_' + fSala.archiSala_;

  Raiz^ := TNodo.Create('Raiz', fSala.globs.fechaIniOpt, nil, BifIni, False, 0);
  Fin^ := TNodo.Create('Fin', fSala.globs.fechaFinOpt, Raiz, BifFin, True, 1);
  RamaPrincipal^ := TRama.Create('Rama_principal',
    fSala.EscenarioActivo.capasActivas, 1, Fin);
  Raiz^.agregar_rama(RamaPrincipal);

  fMaxGrado := 1;
  fRamas.Add(RamaPrincipal^);
  fNodos.Add(Raiz^);
  fNodos.Add(Fin^);
  fRaiz := Raiz;
end;

procedure TArbolEscenarios.insertar_nodo(Origen, Nodo: ptNodo);
var
  i, j: integer;
  Nodaux, Nodofin: ptNodo;
  ram, ramaux: ptRama;
  lscapas: TDAOfNInt;
begin
  New(Nodaux);
  Nodaux^ := Origen^;
  if Nodo^.Fecha.EsMayorQue(Raiz^.Fecha) = -1 then
  begin
    writeln('La fecha del nodo debe ser mayor que la de optimizacion');
    exit;
  end
  else
  begin
    for i := 0 to Nodaux^.ramas.Count - 1 do
    begin
      New(ram);
      New(nodofin);
      ram := Nodaux^.ramas[i];
      nodofin^ := ram^.Nodo^;
      setlength(lscapas, length(ram^.capas));
      vcopy(lscapas, ram^.capas);
      if Nodo^.Fecha.EsMayorQue(ram^.Nodo^.Fecha) = 1 then
        insertar_nodo(ram^.Nodo, Nodo)
      else
      begin
        for j := 0 to Nodo^.ramas.Count - 1 do
        begin
          New(ramaux);
          ramaux := Nodo^.ramas[j];
          ramaux^.Nodo := nodofin;
          setlength(ramaux^.fcapas, length(lscapas));
          vcopy(ramaux^.fcapas, lscapas);
          Nodo^.ramas[j] := ramaux;
        end;
        ram^.Nodo := Nodo;
        Nodo^.fNodoPadre := Nodaux;

      end;

    end;

  end;
end;

function TArbolEscenarios.Nodo_a_optmizar(Nodo: ptNodo): boolean;
var
  nodoaux: ptNodo;
  ramaaux: ptRama;
  i: integer;
begin
  Result := True;

  for i := 0 to Nodo^.ramas.Count - 1 do
  begin
    New(nodoaux);
    New(ramaaux);
    ramaaux := Nodo^.ramas[i];
    nodoaux^ := ramaaux^.Nodo^;
    Result := Result and ((nodoaux^.Optimizado) and not (Nodo^.Optimizado));
  end;

end;

procedure TArbolEscenarios.optimizar_nodo(nodo: ptNodo);
var
  ramaaux: ptRama;
  i: integer;
  parametros, dondeEstaba, nombre_sala, nombre_monitores, nombre_escenario,
  nombre: string;
  ExitCode: dword;
  apl: string;
  params: array of string;

begin
  for i := 0 to Nodo^.ramas.Count - 1 do
  begin
    New(ramaaux);
    ramaaux := Nodo^.ramas[i];
    writeln('Optimizando Nodo: ', nodo^.Nombre, ' y rama: ', ramaaux^.Nombre);

    getdir(3, dondeEstaba);
    ChDir(getDir_Bin);
    sala.globs.fechaIniOpt := Tfecha.Create_Str('06/07/2013');
    sala.globs.fechaFinOpt := Tfecha.Create_Str('27/07/2013');
    nombre_escenario := 'Esc_' + nodo^.Nombre + '_' + ramaaux^.Nombre;
    sala.Escenarios.AppendEscenario(nombre_escenario);

    nombre := 'Sala_' + nodo^.Nombre + '_' + ramaaux^.Nombre + '.ese';
    sala.WriteToArchi('C:\simsee\tmp_rundir\' + nombre);
    nombre_sala := sala.archiSala_;
    parametros := 'sala="' + nombre_sala + '" monitores="' +
      nombre_monitores + '" escenario="' + nombre_escenario + '"' + #0;

    apl := 'C:\simsee\bin\cmdopt.exe';
    if fileexists(apl) then
    begin
      setlength(params, 3);
      params[0] := 'sala=' + nombre_sala;
      params[1] := 'monitores=' + nombre_monitores;
      params[2] := 'escenario=' + nombre_escenario;

      if not RunChildAndWAIT(apl, params) then
        raise Exception.Create('no puede correr la cmdopt');
    end
    else
      writeln(); //MessageBox('No se encuentra la aplicación: ','OK',1);

    ChDir(dondeEstaba);
    writeln('------------------------------------------------------------------------');
    writeln();
  end;

end;

procedure TArbolEscenarios.mostrar(nodo: ptNodo);
var
  ramaaux: ptRama;
  i: integer;
begin
  if Nodo <> nil then

  begin
    writeln(nodo^.Nombre, ' : ', nodo^.Optimizado);
    for i := 0 to Nodo^.ramas.Count - 1 do
    begin
      New(ramaaux);
      ramaaux := Nodo^.ramas[i];
      mostrar(ramaaux^.Nodo);
    end;
  end;

end;

procedure TArbolEscenarios.eliminar_nodo();
begin

end;


procedure TArbolEscenarios.recorrer_optimizando(Nodo: ptNodo);
var
  ramaaux: ptRama;
  i: integer;
begin
  mostrar(raiz);
  if nodo = nil then
    exit;
  if Nodo^.Optimizado then
    recorrer_optimizando(Nodo^.NodoPadre)
  else
  if Nodo_a_optmizar(Nodo) then
  begin
    optimizar_nodo(Nodo);
    Nodo^.Optimizado := True;
    recorrer_optimizando(Nodo^.NodoPadre);
  end
  else
  begin
    for i := 0 to Nodo^.ramas.Count - 1 do
    begin
      New(ramaaux);
      ramaaux := Nodo^.ramas[i];
      if not (ramaaux^.Nodo.Optimizado) then
        recorrer_optimizando(ramaaux^.Nodo);
    end;
  end;

end;

procedure TArbolEscenarios.recorrer_simulando();
begin

end;

procedure optimizarnodorama(nodo: ptNodo; rama: ptRama);
begin
  writeln(nodo^.Nombre, ' y ', rama^.Nombre);
end;


end.
