unit uListadoProblemasODDFACE;

{$mode delphi}

interface

uses
  SysUtils, Classes, Controls,
  Forms,
  Graphics,
  urosx,
  uDataSetGenerico,
  uvisordetabla,
  StdCtrls,
  uempaquetar,
  uconstantesSimSEE, unotificar, u_editorproblema,
  uoddface_consultar,
  u_updownload, uListadoProblemas;

type

  { TListadoProblemasODDFACE }

  TListadoProblemasODDFACE = class(TListadoProblemas)
  public
    nombrePerfil: string;

    constructor Create(dbconx: TDBrosxCon; AOwner: TComponent;
      Name: string; nombrePerfil: string); reintroduce;
    procedure Editar_onClick(nidRec: string; kFila: integer); override;
    procedure SemaforoRojo_OnClick(nidRec: string; kFila: integer); override;
    procedure SemaforoVerde_OnClick(nidRec: string; kFila: integer); override;
    procedure Lupa_OnClick(nidRec: string; kFila: integer); override;
    procedure clonar_OnClick(nidRec: string; kFila: integer); override;
    procedure Populate; override;
    class function CrearNuevoProblema(dbconx: TDBrosxCon): integer;
    procedure eliminarProblema(nidCarpeta: string); override;
  end;


implementation

uses
  uoddface_prepare;

procedure CrearTabla_Inidviduos(dbcon: TDBrosxCon; nid_Problema: integer);
var
  sql: string;
  tabla: string;

begin
  tabla := 'ofe_individuos_' + IntToStr(nid_problema);

  if dbcon.TipoServidor = CTS_PostgreSQL then
  begin
    sql := 'CREATE TABLE ' + tabla + ' (' + '  nid SERIAL,' +
      '  adn bytea,' + '  dtc timestamp DEFAULT CURRENT_DATE,' +
      '  dtu timestamp DEFAULT CURRENT_DATE,' +
      '  f_VE double precision NOT NULL,' +
      '  f_CVaR double precision NOT NULL,' +
      '  f_VaR double precision NOT NULL,' +
      '  f_Objetivo double precision NOT NULL,' +
      '  f_MIN double precision NOT NULL,' +
      '  f_MAX double precision NOT NULL,' + '  cnt_evaluaciones int NOT NULL,' +
      '  detalle bytea NOT NULL,' + '  UNIQUE ( adn )' + ');';
    dbcon.sql_exec(sql);
    sql := 'CREATE INDEX ' + tabla + '_idx_fo ON ' + tabla + ' ( f_objetivo );';
    dbcon.sql_exec(sql);
  end
  else
  begin
    // atención en mysql el adn se limita a 750 porque sino no se puede definir el índice.
    sql := 'CREATE TABLE `' + tabla + '` (' + '  `nid` int(11) NOT NULL,' +
      '  `adn` varbinary( 750 ) NOT NULL,' + '  `dtc` datetime NOT NULL,' +
      '  `dtu` datetime NOT NULL,' + '  `f_VE` double NOT NULL,' +
      '  `f_CVaR` double NOT NULL,' + '  `f_VaR` double NOT NULL,' +
      '  `f_Objetivo` double NOT NULL,' + '  `f_MIN` double NOT NULL,' +
      '  `f_MAX` double NOT NULL,' + '  `cnt_evaluaciones` int(11) NOT NULL,' +
      '  `detalle` blob NOT NULL,' + '  PRIMARY KEY  (`nid`),' +
      '  UNIQUE KEY `iadn` (`adn`),' + '  KEY `ifo` (`f_objetivo`)' + ');';
    dbcon.sql_exec(sql);
  end;

end;



class function TListadoProblemasODDFACE.CrearNuevoProblema(dbconx:
  TDBrosxCon): integer;
var

  nid_problema: integer;
  sql: string;
  str_nombres, str_valores: string;
begin

  nid_problema := dbconx.sql_nextnid('ofe_problemas');

  AppendToInsertStr(str_nombres, str_valores, 'nid', IntToStr(nid_problema));

  AppendToInsertStr(str_nombres, str_valores, 'usuario', '0');
  AppendToInsertStr(str_nombres, str_valores, 'llave', '0');
  AppendToInsertStr(str_nombres, str_valores, 'dt_creacion', 'now()', False);
  AppendToInsertStr(str_nombres, str_valores, 'tipo', '0');

  AppendToInsertStr(str_nombres, str_valores, 'ro_VE', '1.0');
  AppendToInsertStr(str_nombres, str_valores, 'ro_VaR', '0.0');
  AppendToInsertStr(str_nombres, str_valores, 'ro_CVaR', '0.0');

  AppendToInsertStr(str_nombres, str_valores, 'N_CronicasPorVez', '100');
  AppendToInsertStr(str_nombres, str_valores, 'N_DiscretizacionesHistograma', '100');
  AppendToInsertStr(str_nombres, str_valores, 'semilla_madre', '31');

  AppendToInsertStr(str_nombres, str_valores, 'ro_GA', '0.95');
  AppendToInsertStr(str_nombres, str_valores, 'ro_EG', '0.00');
  AppendToInsertStr(str_nombres, str_valores, 'ro_MJ', '0.05');

  AppendToInsertStr(str_nombres, str_valores, 'GA_prob_premio_exito', '0.05');
  AppendToInsertStr(str_nombres, str_valores, 'GA_prob_mutacion', '0.01');
  AppendToInsertStr(str_nombres, str_valores, 'descripcion', '');

  AppendToInsertStr(str_nombres, str_valores, 'grupo', IntToStr(
    dbconx.usuario_grupo));


  sql := 'INSERT INTO ofe_problemas ( ' + str_nombres + ' ) VALUES ( ' +
    str_valores + ' ) ';

  dbconx.sql_exec(sql);

  CrearTabla_Inidviduos(dbconx, nid_Problema);

  Result := nid_problema;
end;




procedure TListadoProblemasODDFACE.eliminarProblema(nidCarpeta: string);
var
  pathCarpeta: string;
  sql: string;
begin

  pathCarpeta := dbcon.sql_func('SELECT path FROM ofe_carpetas WHERE nid = ' +
    nidCarpeta);


  if dbcon.tipoServidor = CTS_MySQL then
    sql := 'DELETE ofe_archivos_bloques FROM ofe_archivos_bloques '
      + ' LEFT JOIN ofe_archivos ON ofe_archivos_bloques.nid_archivo = ofe_archivos.nid '
      + ' WHERE ofe_archivos.nid_carpeta = ' + nidCarpeta
  else
    sql := 'DELETE FROM ofe_archivos_bloques USING ofe_archivos '
      + ' WHERE ofe_archivos_bloques.nid_archivo = ofe_archivos.nid AND ofe_archivos.nid_carpeta='
      +
      nidCarpeta;


  if not dbcon.sql_exec(sql) then
    raise Exception.Create(dbcon.UltimoError);

  sql := 'DELETE FROM ofe_archivos WHERE nid_carpeta = ' + nidCarpeta;
  if not dbcon.sql_exec(sql) then
    raise Exception.Create(dbcon.UltimoError);

  sql := 'DELETE FROM ofe_carpetas WHERE nid = ' + nidCarpeta;
  if not dbcon.sql_exec(sql) then
    raise Exception.Create(dbcon.UltimoError);

  sql := 'DROP TABLE IF EXISTS ofe_individuos_' + nidCarpeta;
  dbcon.sql_exec(sql);
  //      raise Exception.Create( urosx.UltimoError );



  sql := 'DELETE FROM ofe_PIG_tecnologias WHERE nid_problema = ' + nidCarpeta;
  if not dbcon.sql_exec(sql) then
    raise Exception.Create(dbcon.UltimoError);

  sql := 'DELETE FROM ofe_PAM_ordenes WHERE nid_problema = ' + nidCarpeta;
  if not dbcon.sql_exec(sql) then
    raise Exception.Create(dbcon.UltimoError);

  sql := 'DELETE FROM ofe_RedCEGH_data WHERE nid_problema = ' + nidCarpeta;
  if not dbcon.sql_exec(sql) then
    raise Exception.Create(dbcon.UltimoError);

  sql := 'DELETE FROM ofe_OptimA WHERE nid_problema = ' + nidCarpeta;
  if not dbcon.sql_exec(sql) then
    raise Exception.Create(dbcon.UltimoError);

  sql := 'DELETE FROM ofe_problemas WHERE nid = ' + nidCarpeta;
  if not dbcon.sql_exec(sql) then
    raise Exception.Create(dbcon.UltimoError);
end;


procedure TListadoProblemasODDFACE.Populate;
var
  k: integer;
  snid: string;
  ds: TResultadoQuery;
  r: TDataRecord;
  estado: integer;

begin
  flg_populate := False;
  ds := dbcon.sql_Query(
    'SELECT nid, dt_creacion, tipo, descripcion,  estado FROM ofe_problemas WHERE grupo=' +
    IntToStr(dbcon.usuario_grupo) + ' ORDER BY nid DESC');
  if ds = nil then
    raise Exception.Create(dbcon.ultimoError);

  ClearRedim(ds.nrows + 1, 7);
  // fila encabezado
  wrTexto('', 0, 0, 'NID');
  wrTexto('', 0, 1, 'dt_creacion');
  wrTexto('', 0, 2, 'tipo');
  wrTexto('', 0, 3, 'Descripcion');

  AlinearCelda(0, 0, CAH_Izquierda, CAV_Centro);
  AlinearCelda(0, 1, CAH_Izquierda, CAV_Centro);
  AlinearCelda(0, 2, CAH_Izquierda, CAV_Centro);
  AlinearCelda(0, 3, CAH_Izquierda, CAV_Centro);


  Self.SetBgColorFila(0, clNavy);
  Self.SetFontColorFila(0, clYellow);

  Self.SetBgColorCelda(0, 0, clNavy);
  Self.SetBgColorCelda(0, 1, clNavy);

  k := 1;
  ds.First;
  r := ds.getFilaActiva;
  while not ds.EOF do
  begin
    snid := r.GetByIdAsString(0);
    estado := r.GetByNameAsInt('estado');
    wrTexto('', k, 0, r.GetByNameAsString('nid'));
    wrTexto('', k, 1, r.GetByNameAsString('dt_creacion'));
    wrTexto('', k, 2, r.GetByNameAsString('tipo'));
    wrTexto('', k, 3, r.GetByNameAsString('descripcion'));
    AlinearCelda(k, 0, CAH_Izquierda, CAV_Centro);
    AlinearCelda(k, 1, CAH_Izquierda, CAV_Centro);
    AlinearCelda(k, 2, CAH_Izquierda, CAV_Centro);
    AlinearCelda(k, 3, CAH_Izquierda, CAV_Centro);

    // ahora la botonera en la última columna

    wrBotonera(snid, k, 4,
      [
      //  iid_fdownload,
      iid_Editar, iid_borrar, iid_clonar],
      [
      //  hintPorDefecto(iid_fdownload),
      hintPorDefecto(iid_Editar), hintPorDefecto(iid_Borrar),
      hintPorDefecto(iid_clonar)]);


    if (estado <= 0) then
      wrBotonera(snid, k, 5, [iid_SemaforoRojo, iid_Lupa], ['Activar', 'Consultar'])
    else
      wrBotonera(snid, k, 5, [iid_SemaforoVerde, iid_Lupa],
        ['Desactivar', 'Consultar']);


    if (k mod 2) = 0 then
      if estado <= 0 then
        SetBgColorFila(k, clFondoFilaPar_Inactiva)
      else
        SetBgColorFila(k, clFondoFilaPar_Activa)
    else
    if estado <= 0 then
      SetBgColorFila(k, clFondoFilaImpar_Inactiva)
    else
      SetBgColorFila(k, clFondoFilaImpar_Activa);

    Inc(k);
    ds.Next;
    r := ds.getFilaActiva;
  end;
  reposicionar;
end;


constructor TListadoProblemasODDFACE.Create(dbconx: TDBrosxCon;
  AOwner: TComponent; Name: string; nombrePerfil: string);
begin
  inherited Create(dbconx, AOwner, Name);
  self.nombrePerfil := nombrePerfil;
end;

procedure TListadoProblemasODDFACE.Editar_onClick(nidRec: string; kFila: integer);
var
  ufp: TForm_EditorProblema;
  res: integer;

begin

  ufp := TForm_EditorProblema.Create(self, dbcon);

  ufp.LoadRec(StrToInt(nidRec));
  res := ufp.ShowModal;
  if res > 0 then
  begin
    flg_populate := True;
    invalidate;
  end;
  ufp.Free;

end;


procedure TListadoProblemasODDFACE.SemaforoRojo_OnClick(nidRec: string; kFila: integer);
var
  sql: string;
begin
  sql := 'UPDATE ofe_problemas SET estado = 1 - estado  WHERE nid = ' + nidRec;
  dbcon.sql_exec(sql);
  flg_populate := True;
  invalidate;
end;

procedure TListadoProblemasODDFACE.SemaforoVerde_OnClick(nidRec: string; kFila: integer);
var
  sql: string;
begin
  sql := 'UPDATE ofe_problemas SET estado = - estado WHERE nid = ' + nidRec;
  dbcon.sql_exec(sql);
  flg_populate := True;
  invalidate;
end;

procedure TListadoProblemasODDFACE.Lupa_OnClick(nidRec: string; kFila: integer);
var
  fc: TConsultar;
begin
  fc := TConsultar.Create(self, dbcon, nombrePerfil);
  fc.eFrom.Text := 'ofe_individuos_' + nidRec;
  fc.nidProblema := StrToInt(nidRec);
  fc.ShowModal;
  fc.Free;
end;


procedure TListadoProblemasODDFACE.clonar_OnClick(nidRec: string; kFila: integer);
var
  nid_problema_destino, nid_problema_origen: integer;
  sql: string;

  tabla_individuos: string;
  k_individuo: integer;
  max_nid_usado, nid_individuo: integer;

begin
  nid_problema_origen := StrToInt(nidRec);
  nid_problema_destino := dbcon.clonar_rec('ofe_problemas', nid_problema_origen,
    -1, 'estado=0, dt_creacion=now()');

  // cada problema tiene una carpeta con el mismo nid del problema.
  dbcon.clonar_rec('ofe_carpetas', nid_problema_origen, nid_problema_destino, '');

{
  // Clonamos los archivos que pudiera tener la carpeta
  dbcon.clonar_hijas('ofe_carpetas', 'ofe_archivos', 'nid_carpeta',
    nid_problema_origen, nid_problema_destino);
 }
  dbcon.clonar_hijas_y_nietas(
    // 'ofe_carpetas',
    'ofe_archivos', 'ofe_archivos_bloques', 'nid_carpeta', 'nid_archivo',
    nid_problema_origen, nid_problema_destino);


  // Clonamos los PIGs
  dbcon.clonar_hijas(
    //'ofe_problemas',
    'ofe_PIG_tecnologias', 'nid_problema',
    nid_problema_origen, nid_problema_destino);

  // Clonamos los PAMs
  dbcon.clonar_hijas(
    //'ofe_problemas',
    'ofe_PAM_ordenes', 'nid_problema',
    nid_problema_origen, nid_problema_destino);

  // Clonamos los RedCEGH s
  dbcon.clonar_hijas(
    //'ofe_problemas',
    'ofe_RedCEGH_data', 'nid_problema',
    nid_problema_origen, nid_problema_destino);

  // Clonamos los OptimA s
  dbcon.clonar_hijas(
    //'ofe_problemas',
    'ofe_OptimA', 'nid_problema',
    nid_problema_origen, nid_problema_destino);

  // creamos la tabla par el historial de evaluaciones
  CrearTabla_Inidviduos(dbcon, nid_Problema_destino);
  tabla_individuos := 'ofe_individuos_' + IntToStr(nid_problema_destino);

  if dbcon.TipoServidor = CTS_PostgreSQL then
  begin
    sql := 'INSERT INTO ' + tabla_individuos +
      ' (f_ve, f_cvar, f_var, f_objetivo, f_min, f_max, cnt_evaluaciones, detalle, adn ) '
      + ' SELECT  0,0,0,0,0,0,-1,'''', adn FROM ofe_individuos_' +
      IntToStr(nid_problema_origen) + ' ORDER BY f_Objetivo LIMIT 100 ';
    dbcon.sql_exec(sql);

    // Esto lo hago por las dudas, porque si como secuencia se usa la que corresponde
    // a la de Postgres no sería necesario.
    max_nid_usado:= dbcon.funcI('SELECT max(nid) FROM '+tabla_individuos );
    for k_individuo := 1 to 100 do
    begin
      nid_individuo := dbcon.sql_nextnid(tabla_individuos);
      if nid_individuo > max_nid_usado then break;
    end;

  end
  else
  begin
    // Como en MySql no hay SERIAL en el nid
    for k_Individuo := 1 to 100 do
    begin
      nid_individuo := dbcon.sql_nextnid(tabla_individuos);
// writeln( 'k_individuo: ', k_individuo, ', nid_individuo: ', nid_individuo );
      sql := 'INSERT INTO ofe_individuos_' + IntToStr(
        nid_problema_destino) +
        ' (f_ve, f_cvar, f_var, f_objetivo, f_min, f_max, cnt_evaluaciones, detalle, adn, nid ) '
        +
        ' SELECT  0,0,0,0,0,0,-1,'''', adn, ' + IntToStr(
        nid_individuo) + ' FROM ofe_individuos_' + IntToStr(
        nid_problema_origen) + ' ORDER BY f_Objetivo LIMIT '+ IntToStr( k_individuo-1)+',1 ';
      dbcon.sql_exec(sql);
    end;

  end;

  Editar_onClick(IntToStr(nid_problema_destino), 0);
end;

end.




