2119 lines
56 KiB
C++
2119 lines
56 KiB
C++
#include "stdafx.h"
|
|
#ifdef OLIVIA_COMPILA
|
|
//olivia
|
|
#include "olv_reco_thr.h"
|
|
#include "olv_thr.h"
|
|
#include "olv_limp.h"
|
|
#include "olv.h"
|
|
#include "olv_reco.h"
|
|
#include "olv_geom.h"
|
|
#include "olv_csv.h"
|
|
#include "olv_sens_ws.h"
|
|
#include "math.h"
|
|
#include <iostream>
|
|
#include <sstream>
|
|
#include <string>
|
|
//utiles
|
|
#include "b_file.h"
|
|
#include "Fdbf.h"
|
|
#include "ManagerDbfGdataTable.h"
|
|
using namespace std;
|
|
/**
|
|
* @file olv_limp_thr.h
|
|
* Archivo de implementaciones del thread de control de la utilidad de recogida de residuos del programa Olivia.
|
|
*/
|
|
Colv_reco_thr::Colv_reco_thr(Colv_reco *olv_reco) : Colv_limp_thr(olv_reco)
|
|
{
|
|
this->olv_reco = olv_reco;
|
|
}
|
|
|
|
Colv_reco_thr::~Colv_reco_thr(void)
|
|
{
|
|
//destruye los subthreads
|
|
if(subthrs)
|
|
{
|
|
for(int i=0;i<n_subthr;i++)
|
|
{
|
|
if(subthrs[i])
|
|
delete subthrs[i];
|
|
}
|
|
free(subthrs);
|
|
subthrs=NULL;
|
|
}
|
|
if(olv_limp->tramos)
|
|
delete [] olv_limp->tramos;
|
|
}
|
|
//*************************************************************************************
|
|
void Colv_reco_thr::inicia_th()
|
|
{
|
|
inicia(OLV_MILIS_COLA,&cola_proc,-1,"reco_thr");
|
|
olvlog(LOG_TODO,"olv_limp_t","Thread de recogida reco_thr arrancado");
|
|
borra_temp_files();
|
|
pirate=FALSE;
|
|
}
|
|
//*************************************************************************************
|
|
/**
|
|
* Cola de procesos en la que itera el thr cuando es recogida. Override de limpieza, así que se implementan\n
|
|
* solo los eventos que tienen sentido en recogida y son diferentes que en limpieza
|
|
*/
|
|
void Colv_reco_thr::cola_proc(int evento, OlvAsync_cola<Param_olv_limp_thr> *clase,Param_olv_limp_thr *e)
|
|
{
|
|
BOOL bien=TRUE;
|
|
BOOL hecho=FALSE;
|
|
|
|
Colv_reco_thr *this_i=static_cast<Colv_reco_thr *>(clase);
|
|
switch (evento)
|
|
{
|
|
case OLV_LIMP_EV_RELL_DAT:
|
|
{
|
|
hecho=TRUE;
|
|
bien=this_i->rellena_datos();
|
|
if(bien && (this_i->olv->modo_ejec<OLV_EJEC_DEBUG_NOSIGUE) && !this_i->pirate)//sigue
|
|
{
|
|
//if(this_i->olv_reco->info_sens.url==" " || this_i->olv_reco->info_sens.url[0]==0)
|
|
this_i->encola(OLV_LIMP_EV_UNE_AMB_NW,NULL,FALSE);
|
|
/*else
|
|
this_i->encola(OLV_RECO_EV_SENS,NULL,FALSE);*/
|
|
}
|
|
break;
|
|
}
|
|
case OLV_RECO_EV_SENS:
|
|
{
|
|
//esta tarea lanza varios subthreads para realizar las peticiones de carga a los
|
|
//sensores(les encola la tarea pide_info_sensores_sub),
|
|
//y estos cuando acaban le encolan al padre (el que los ha lanzado)
|
|
//la tarea de dist_conj_fin
|
|
hecho=TRUE;
|
|
bien=this_i->pide_info_sens();
|
|
break;
|
|
}
|
|
case OLV_RECO_EV_SENS_SUB:
|
|
{
|
|
//aquí entran los subthreads para hacer los cálculos de ángulos, cuando acaban
|
|
//encolan al padre la tarea de fin
|
|
int ithr;
|
|
hecho=TRUE;
|
|
if(e!=NULL)
|
|
ithr=e->id_e;
|
|
this_i->pide_info_sens_sub(ithr);
|
|
break;
|
|
}
|
|
case OLV_RECO_EV_SENS_FIN:
|
|
{
|
|
//aquí entra el padre cuando van acabando los subthreads
|
|
//si han terminado todos encola la siguiente tarea
|
|
int i;
|
|
int nno;
|
|
hecho=TRUE;
|
|
this_i->n_subthr_fin++;
|
|
nno=0;
|
|
if(this_i->n_subthr_fin==this_i->n_subthr)
|
|
{
|
|
this_i->n_subthr_fin=0;
|
|
for(i=0;i<this_i->n_subthr;i++)
|
|
{
|
|
if(this_i->subthrs[i]->prog_subthr<0)
|
|
break;
|
|
nno+=(int)this_i->subthrs[i]->prog_subthr;
|
|
}
|
|
if(i<this_i->n_subthr)
|
|
{
|
|
bien=FALSE;
|
|
this_i->pon_mi_msg("Errores en la conexión con la base de datos de los sensores");
|
|
break;
|
|
}
|
|
bien=this_i->pide_info_sens_fin(nno);
|
|
if(bien && (this_i->olv->modo_ejec<OLV_EJEC_DEBUG_NOSIGUE) && !this_i->pirate)//sigue
|
|
this_i->encola(OLV_LIMP_EV_UNE_AMB_NW,NULL,FALSE);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
if(!bien)
|
|
{
|
|
this_i->pon_mi_progre(OLV_TAREA_FIN_NOK,0);
|
|
}
|
|
if(!hecho)
|
|
Colv_limp_thr::cola_proc(evento, clase,e);
|
|
}
|
|
//*************************************************************************************
|
|
/**
|
|
* Rellena la información asociada de la red navegable y los datos de limpieza
|
|
*/
|
|
BOOL Colv_reco_thr::rellena_datos()
|
|
{
|
|
int icampu,icampkg,ia,uds_,icampcap,icampid,icampoid, capa_, idd;
|
|
char nfile[MAX_PATH];
|
|
Cb_file f;
|
|
Fdbf dbf;
|
|
char *uds, *kg, *capa, *id;
|
|
double kg_,auxi;
|
|
BOOL ret=TRUE;
|
|
|
|
olvlog(LOG_TODO,"olv_limp_t","Rellenando matriz de info asociada a ámbitos");
|
|
pon_mi_progre(OLV_TAREA_IMP, (int) (OliviaDef::GeneralDef::ProgrMax*2/3));
|
|
|
|
uds=kg=capa=id=0;
|
|
|
|
//lee dbf del shp
|
|
strcpy_s(nfile,MAX_PATH,olv->paths.path_data);
|
|
//cambiaext(nfile,".shp",".dbf");
|
|
strcpy((Cdir_manager::extension_archivo(nfile)),"dbf");
|
|
|
|
if(!f.abre(nfile,1) || !dbf.lee(&f))
|
|
{
|
|
pon_mi_msg("Error al abrir %s",nfile);
|
|
ret=FALSE;
|
|
goto fin;
|
|
}
|
|
|
|
//busca el campo de unidades
|
|
icampu=dbf.findCol(olv_reco->camps_r.campo_uds);
|
|
if(icampu==-1)
|
|
{
|
|
sprintf_s(err_str,OLV_MAX_ERR,"No encontrado campo %s en\n%s",olv_reco->camps_r.campo_uds,nfile);
|
|
ret=FALSE;
|
|
goto fin;
|
|
}
|
|
icampoid=dbf.findCol(OLV_NOMB_OID);
|
|
icampkg=icampcap=icampid=-1;
|
|
//busca el campo de kgrec, si es el caso
|
|
//si es 0 los kg por defecto, se lee el campo de kg, si es negativo, se lee el campo de capacidad porque o bien están
|
|
//llenos o bien se lee la info de los sensores, pero tiene densidad
|
|
if(olv_reco->kg_reco_def==0)
|
|
{
|
|
icampkg=dbf.findCol(olv_reco->camps_r.campo_kgcont);
|
|
if(icampkg==-1)
|
|
{
|
|
sprintf_s(err_str,OLV_MAX_ERR,"No encontrado campo %s en\n%s",olv_reco->camps_r.campo_kgcont,nfile);
|
|
ret=FALSE;
|
|
goto fin;
|
|
}
|
|
}
|
|
else if(olv_reco->kg_reco_def<=0)//busca el campo de capacidad, si es el caso
|
|
{
|
|
icampcap=dbf.findCol(olv_reco->camps_r.campo_capa);
|
|
if(icampcap==-1)
|
|
{
|
|
sprintf_s(err_str,OLV_MAX_ERR,"No encontrado campo %s en\n%s",olv_reco->camps_r.campo_capa,nfile);
|
|
ret=FALSE;
|
|
goto fin;
|
|
}
|
|
if(olv_reco->info_sens.camps.id[0])//es el caso de los sensores
|
|
{
|
|
icampid=dbf.findCol(olv_reco->info_sens.camps.id);
|
|
if(icampid==-1)
|
|
{
|
|
sprintf_s(err_str,OLV_MAX_ERR,"No encontrado campo %s en\n%s",olv_reco->info_sens.camps.id,nfile);
|
|
ret=FALSE;
|
|
goto fin;
|
|
}
|
|
}
|
|
}
|
|
|
|
idd =dbf.leeNexRow();
|
|
ia=0;
|
|
while(idd == 1)
|
|
{
|
|
///////////////////////////////
|
|
uds_=1;
|
|
uds_=dbf.getI(icampu);
|
|
if(uds_<0 || uds_>50)
|
|
{
|
|
uds_=1;//pone por def
|
|
olvlog(LOG_TODO,"olv_limp_t","Cuidado, info asociada %ld, puesto unidades por defecto a 1",ia+1);
|
|
}
|
|
olv_limp->iaso[ia].inf_r.uds=uds_;
|
|
|
|
///////////////////////////////
|
|
if(icampkg>-1)
|
|
{
|
|
kg_=dbf.getI(icampkg);
|
|
/*//por si viene con notación científica
|
|
stringstream ss(kg);
|
|
ss >> kg_;
|
|
if (ss.fail()) {kg_=0;}
|
|
/////////////////////////////////
|
|
//kg_=atof(dd);*/
|
|
if(kg_<0 || kg_>10000)
|
|
{
|
|
kg_=50;//pone por def
|
|
olvlog(LOG_TODO,"olv_limp_t","Cuidado, info asociada %ld, puesto kg por defecto a 50",ia+1);
|
|
}
|
|
uds_=1; //pone las uds a 1 para no multiplicar: en caso de que venga el campo de carga ya está multiplicado
|
|
}
|
|
else if(icampcap>-1)
|
|
{
|
|
capa_=dbf.getI(icampcap);
|
|
if(capa_<0 || capa_>100000)
|
|
{
|
|
capa_=3000;//pone por def
|
|
olvlog(LOG_TODO,"olv_limp_t","Cuidado, info asociada %ld, puesto capacidad por defecto a 3000 l",ia+1);
|
|
}
|
|
kg_=capa_*olv_reco->dens_frac/1000; //en kg /1000 para pasar de m3 a l
|
|
}
|
|
else
|
|
kg_=olv_reco->kg_reco_def;
|
|
olv_limp->iaso[ia].inf_r.kg=kg_*uds_;//pone la carga total como la carga por el número de contenedores
|
|
|
|
///////////////////////////////
|
|
|
|
if(icampid>=0)
|
|
{
|
|
olv_limp->iaso[ia].inf_r.id = (char*)malloc(dbf.getSize(icampid)+1);
|
|
if(!olv_limp->iaso[ia].inf_r.id)
|
|
break;
|
|
|
|
olv_limp->iaso[ia].inf_r.id[0]=0;
|
|
if(dbf.getType(icampid)==DBF_TYPE_DATA_STR)
|
|
{
|
|
strcpy(olv_limp->iaso[ia].inf_r.id,dbf.getStr(icampid));
|
|
}
|
|
else
|
|
{
|
|
auxi=dbf.getD(icampid);
|
|
if(auxi==(double)(int)auxi)
|
|
{
|
|
sprintf(olv_limp->iaso[ia].inf_r.id,"%ld",(int)auxi);
|
|
}
|
|
else
|
|
{
|
|
sprintf(olv_limp->iaso[ia].inf_r.id,"%lf",auxi);
|
|
}
|
|
}
|
|
}
|
|
|
|
if(icampoid>=0)
|
|
olv_limp->iaso[ia].oid = dbf.getI(icampoid);
|
|
|
|
//olvlog(LOG_TODO,"olv_limp_t","Rellena %0d %3.1f %ld %04d",ia, kg_,uds_,olv_limp->iaso[ia].oid);
|
|
|
|
///////////////////////////////
|
|
//avisa de progreso
|
|
if((ia%100==0) || (ia==(olv_limp->n_amb-1)))
|
|
{
|
|
pon_mi_progre(OLV_TAREA_IMP, (int) (OliviaDef::GeneralDef::ProgrMax*
|
|
((1.0*(ia+1)/olv_limp->n_amb)/3)+2/3));
|
|
olvlog(LOG_TODO,"olv_limp_t","Rellenando info asociada a ámbitos, %ld de %ld",
|
|
ia+1,olv_limp->n_amb);
|
|
}
|
|
|
|
ia++;
|
|
idd =dbf.leeNexRow();
|
|
}
|
|
if(ia<olv_limp->n_amb)
|
|
{
|
|
sprintf_s(err_str,OLV_MAX_ERR,"Error al leer información asociada %ld en\n%s",ia,nfile);
|
|
ret=FALSE;
|
|
goto fin;
|
|
}
|
|
|
|
olvlog(LOG_TODO,"olv_limp_t","Finaliza Matriz de info asociada a ámbitos");
|
|
|
|
fin:
|
|
if(!ret)
|
|
olvlog(LOG_TODO,"olv_limp_t","Fallos en Matriz de info asociada a ámbitos");
|
|
|
|
olvlog(LOG_TODO,"olv_limp_t","Giro límite %lf",olv_limp->ang_lim);
|
|
|
|
return ret;
|
|
}
|
|
//*************************************************************************************
|
|
/**
|
|
* Para la conexión a la lectura de sensores
|
|
*/
|
|
BOOL Colv_reco_thr::pide_info_sens()
|
|
{
|
|
olvlog(LOG_TODO,"olv_limp_t","Leyendo info de los sensores");
|
|
pon_mi_progre(OLV_TAREA_SENS, 0);
|
|
|
|
//Inicia el array donde se guarda la info de carga
|
|
olv_reco->info_carg = (int *)malloc(olv_limp->n_amb*sizeof(int));
|
|
if(!olv_reco->info_carg)
|
|
{
|
|
sprintf_s(err_str,OLV_MAX_ERR,"Error, sin memoria para info de carga");
|
|
return FALSE;
|
|
}
|
|
|
|
//lanza los threads
|
|
lanza_subthrs(OLV_RECO_EV_SENS_SUB);
|
|
|
|
return TRUE;
|
|
}
|
|
//*************************************************************************************
|
|
/**
|
|
* Rellena los valores de los sensores de cada contenedor
|
|
* El thread entra aquí cuando los subthreads que realizan la tarea realmente han finalizado
|
|
*/
|
|
BOOL Colv_reco_thr::pide_info_sens_fin(int nno)
|
|
{
|
|
class AddColPorc : public IAddColDbf
|
|
{
|
|
public:
|
|
Colv_reco *olv_reco;
|
|
AddColPorc(Colv_reco *rr)
|
|
{
|
|
this->olv_reco=rr;
|
|
}
|
|
virtual void setData(int i, void *data)
|
|
{
|
|
if(data)
|
|
{
|
|
memcpy(data,(void*)&olv_reco->info_carg[i],sizeof(int));
|
|
}
|
|
|
|
};
|
|
};
|
|
AddColPorc dataDbf(olv_reco);
|
|
ManagerDbfGdataTable dbfmgr;
|
|
char path_dbf[MAX_PATH];
|
|
////////////////
|
|
//para los threads
|
|
para_subthrs();
|
|
|
|
//guarda la info al shp
|
|
strcpy_s(path_dbf,MAX_PATH,olv_limp->olv->paths.path_data);
|
|
//cambiaext(path_dbf,".shp",".dbf");
|
|
strcpy((Cdir_manager::extension_archivo(path_dbf)),"dbf");
|
|
if(!dbfmgr.AddCol(path_dbf,"PORC_RECO",GdataTable::Tint,&dataDbf))
|
|
//if(!olv_limp->olv->olv_sh->add_col_dbf(path_dbf,olv_limp->n_amb,TIPO_IA_INT,(char*)olv_reco->info_carg,"PORC_RECO",err_str,OLV_MAX_ERR))
|
|
{
|
|
free(olv_reco->info_carg);
|
|
olv_reco->info_carg=NULL;
|
|
return FALSE;
|
|
}
|
|
|
|
olvlog(LOG_TODO,"olv_limp_t","FIN %ld peticiones de carga a sensores",
|
|
olv_limp->n_amb);
|
|
|
|
free(olv_reco->info_carg);
|
|
olv_reco->info_carg=NULL;
|
|
return TRUE;
|
|
}
|
|
//*************************************************************************************
|
|
/**
|
|
* Rellena los valores de los sensores, es la parte de cálculos que
|
|
* realizan los subthreads. 'ithr' indica qué thread es, para calcular qué ámbitos le tocan.
|
|
*/
|
|
void Colv_reco_thr::pide_info_sens_sub(int ithr)
|
|
{
|
|
int na_ini,na_fin,na_desp,na,nno;
|
|
int KK, seg;
|
|
Param_olv_limp_thr pp;
|
|
Colv_sens_ws sens;
|
|
double carg;
|
|
BOOL mal=FALSE;
|
|
|
|
const int SZ_CAMP =32;
|
|
const int SZ_SENTEN =1024;
|
|
char nfile[MAX_PATH];
|
|
|
|
strcpy_s(nfile,MAX_PATH,olv->paths.path_data);
|
|
//cambiaext(nfile,".shp",".dbf");
|
|
strcpy((Cdir_manager::extension_archivo(nfile)),"dbf");
|
|
|
|
////////////////
|
|
pp.id_e=OLV_TAREA_SENS;//manda de parámetro la tarea de la que es el progreso
|
|
KK=olv_limp->tipo_ambit;
|
|
na_desp = (int)ceil(1.0*(olv_limp->n_amb)/n_subthr);
|
|
na_ini= min(ithr*na_desp, olv_limp->n_amb);
|
|
na_fin = min((ithr+1)*na_desp,olv_limp->n_amb);
|
|
nno=0;
|
|
////////////////
|
|
|
|
olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Ambs %04d a %04d", ithr,na_ini, na_fin);
|
|
|
|
seg = GetTickCount();
|
|
|
|
/////////////////////////////////////
|
|
//Conecta con el servicio
|
|
sens.inicia(&olv_reco->info_sens);
|
|
/////////////////////////////////////
|
|
|
|
/////////////////////////////////////
|
|
//Bucle por cada ámbito de los que le tocan a este thread para pedir su carga
|
|
/////////////////////////////////////
|
|
for(na=na_ini;na<na_fin && !pirate; na++)
|
|
{
|
|
carg=0;
|
|
|
|
if(!olv_limp->iaso[na].inf_r.id || strlen(olv_limp->iaso[na].inf_r.id)==0)
|
|
{
|
|
olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Error en la petición de carga de contenedor %ld, no hay ID",
|
|
ithr,na);
|
|
carg=100;
|
|
olv_reco->info_carg[na]=(int) carg;
|
|
continue;
|
|
}
|
|
|
|
/////////////////////////////////////
|
|
//Tiene el id en info2
|
|
carg = sens.dame_porc_cont_i(olv_limp->iaso[na].inf_r.id);
|
|
if(carg==0)
|
|
{
|
|
olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Error en la petición de carga de contenedor %s: %s",ithr,
|
|
olv_limp->iaso[na].inf_r.id,sens.err_str);
|
|
carg=100;
|
|
}
|
|
olv_reco->info_carg[na]=(int) carg;
|
|
|
|
/////////////////////////////////////
|
|
//Pone la carga recibida
|
|
if(carg>=olv_reco->info_sens.porc_lim)//Si la carga supera el valor límite, la pone
|
|
olv_limp->iaso[na].inf_r.kg *= carg/100; //info1 contiene antes los kg del contenedor si estuviera lleno
|
|
else
|
|
{
|
|
olv_limp->iaso[na].flgs |= OLV_LIMP_FLG_AMB_NO; //lo marca para no recogerlo
|
|
nno++;
|
|
}
|
|
|
|
//avisa de progreso
|
|
if(((na-na_ini)%50==0) || ((na-na_ini)==(na_desp-1)))
|
|
{
|
|
olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Pidiendo info de carga a sensores %ld de %ld", ithr,
|
|
(na-na_ini+1),na_desp);
|
|
//avisa de progreso
|
|
prog_subthr=(1.0*(na-na_ini+1)/na_desp);
|
|
thr_padre->encola(OLV_LIMP_EV_SUBTHR_PROG,&pp,FALSE);
|
|
}
|
|
}
|
|
|
|
if(mal)
|
|
{
|
|
olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Error al pedir info de carga a sensores");
|
|
prog_subthr=-1;//para avisar al padre de que ha habido un error
|
|
|
|
}
|
|
else
|
|
{
|
|
olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Fin peticiones de carga a sensores, %.3f seg", ithr, 1.0*(GetTickCount()-seg)/1000);
|
|
prog_subthr=nno;
|
|
}
|
|
thr_padre->encola(OLV_RECO_EV_SENS_FIN,NULL,FALSE);
|
|
|
|
/////////////////////////////////////
|
|
}
|
|
//*************************************************************************************
|
|
/**
|
|
* Añade a la red de conjunciones en qué conjunción está la planta y la instalación
|
|
*/
|
|
BOOL Colv_reco_thr::pon_nodos_planta(double pt[3])
|
|
{
|
|
double pt_[3];
|
|
memcpy(pt_,pt,3*sizeof(double));
|
|
|
|
if(!Colv_limp_thr::pon_nodos_planta(pt))//es la instalación olv_limp->coor_instal
|
|
return FALSE;
|
|
|
|
if(Colv_geom::pto_equals(pt_, olv_reco->coor_plant))
|
|
{
|
|
memcpy(olv_reco->coor_plant,pt,3*sizeof(double));
|
|
}
|
|
else
|
|
{
|
|
if(!Colv_limp_thr::pon_nodos_planta(olv_reco->coor_plant))
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
//*************************************************************************************
|
|
/**
|
|
* Apunta en qué nodos está la planta y la instalación
|
|
*/
|
|
BOOL Colv_reco_thr::busca_conjs_planta(double pt[3], int *nod)
|
|
{
|
|
double pt_[3];
|
|
memcpy(pt_,pt,3*sizeof(double));
|
|
|
|
if(!Colv_limp_thr::busca_conjs_planta(pt,nod))//es la instalación olv_limp->coor_instal, olv_limp->nod_instal
|
|
return FALSE;
|
|
|
|
if(Colv_geom::pto_equals(pt_, olv_reco->coor_plant))
|
|
{
|
|
olv_reco->nod_plant=*nod;
|
|
}
|
|
else
|
|
{
|
|
if(!Colv_limp_thr::busca_conjs_planta(olv_reco->coor_plant,&olv_reco->nod_plant))
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
//*************************************************************************************
|
|
double Colv_reco_thr::dame_cost_jornada()
|
|
{
|
|
return olv_limp->t_conv-olv_reco->t_sal*2-olv_limp->t_desc;
|
|
}
|
|
//*************************************************************************************
|
|
/**
|
|
* Calcula el coste de los ámbitos a la planta e instalación
|
|
*/
|
|
BOOL Colv_reco_thr::calcula_cost_plant()
|
|
{
|
|
int ic,ia,ka,nais, KK, ref_ia;
|
|
Djkt_nodo *costes_nodos;
|
|
BOOL mal=FALSE;
|
|
|
|
//Inicia el array de orden /secuencia
|
|
olv_reco->ord_sec_plan=(Secu_amb*)malloc(sizeof(Secu_amb)*2);
|
|
if(!olv_reco->ord_sec_plan)
|
|
{
|
|
pon_mi_msg("Error, sin memoria para matriz de orden y secuencia");
|
|
return FALSE;
|
|
}
|
|
memset(olv_reco->ord_sec_plan,0,sizeof(Secu_amb)*2);
|
|
olvlog(LOG_TODO,"olv_limp_t","Calculando coste a planta e instalación");
|
|
|
|
costes_nodos=NULL;
|
|
if(olv_reco->nod_plant==olv_reco->nod_instal)
|
|
KK=1;
|
|
else
|
|
KK=2;
|
|
for(int k=0;k<KK;k++)
|
|
{
|
|
if(k==OLV_PLANT)//plant
|
|
ic=olv_reco->nod_plant;
|
|
else if(k==OLV_INSTAL)//instal
|
|
ic=olv_reco->nod_instal;
|
|
|
|
if(!Colv_geom::dijkstra_ang_inv_ok(olv_limp->cost_conj, olv_limp->ang_conj, olv_limp->conjs.n,
|
|
ic, &costes_nodos, &visto_ang))
|
|
{
|
|
mal=TRUE;
|
|
break;
|
|
}
|
|
|
|
olv_reco->ord_sec_plan[k].ctnod[0]=costes_nodos;
|
|
olv_reco->ord_sec_plan[k].ctnod[1]=NULL;
|
|
|
|
costes_nodos=NULL;
|
|
|
|
//revisa si está aislado de algún ámbito
|
|
nais=0;
|
|
for(ia=0;ia<olv_limp->n_amb;ia++)
|
|
{
|
|
ref_ia=olv_limp->carto.get(ia).entity()->ref;
|
|
if(olv_limp->iaso[ref_ia].flgs & OLV_LIMP_FLG_AMB_NO)
|
|
continue;
|
|
for(ka=0;ka<olv_limp->tipo_ambit;ka++)
|
|
{
|
|
if(olv_reco->ord_sec_plan[k].ctnod[0][olv_limp->iaso[ref_ia].inod[ka]].dis>=MAYUSCULO)
|
|
{
|
|
nais++;
|
|
}
|
|
}
|
|
}
|
|
if(nais)
|
|
{
|
|
mal=TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(mal)
|
|
{
|
|
pon_mi_msg("Error al calcular costes de ámbitos a instalación");
|
|
return FALSE;
|
|
}
|
|
|
|
if(KK==1)
|
|
{
|
|
olv_reco->ord_sec_plan[OLV_PLANT].ctnod[0]=olv_reco->ord_sec_plan[OLV_INSTAL].ctnod[0];
|
|
olv_reco->ord_sec_plan[OLV_PLANT].ctnod[1]=olv_reco->ord_sec_plan[OLV_INSTAL].ctnod[1];
|
|
}
|
|
|
|
////////////////////
|
|
//inicializa array
|
|
olv_reco->ptos_vaci=(short*)malloc(olv_limp->n_amb*sizeof(short));
|
|
if(!olv_reco->ptos_vaci)
|
|
return FALSE;
|
|
memset(olv_reco->ptos_vaci,0,olv_limp->n_amb*sizeof(short));
|
|
|
|
return TRUE;
|
|
}
|
|
//*************************************************************************************
|
|
/**
|
|
* Calcula el coste de desplazamiento de ir de ir por todos los ambitos sec desde ini hasta fin
|
|
*/
|
|
double Colv_reco_thr::dame_coste( Secu_amb * sec, int ini, int fin, Info_sec *s, BOOL ind_abs)
|
|
{
|
|
double d=0;
|
|
int ind_cost, ind_cost1;
|
|
int fin_old=fin;
|
|
int id_ambf, ref_ambf;
|
|
int id_ambf1;
|
|
double capac_v=olv_reco->kg_max, cap_act=0,cap_h, cap_t;
|
|
int nv_p, i, sel;//numero de veces por ir a planta
|
|
double coste;
|
|
double cap_g, dd;
|
|
cap_t=cap_act;
|
|
|
|
while(ini<fin)
|
|
{
|
|
id_ambf=s->iamb[sec[fin].iamb];
|
|
id_ambf1=s->iamb[sec[fin-1].iamb];
|
|
|
|
ref_ambf = olv_limp->carto.get(id_ambf).entity()->ref;
|
|
|
|
|
|
if (ind_abs)
|
|
ind_cost=id_ambf;
|
|
else
|
|
ind_cost=sec[fin].iamb;
|
|
|
|
cap_t+=olv_reco->iaso[ref_ambf].inf_r.kg;//suma a la carga la basura del ambito
|
|
d+=olv_limp->cost_amb[id_ambf][id_ambf];//suma el coste del ambito
|
|
d+=olv_limp->arch_dj.dame_dis(id_ambf1, 0, id_ambf,sec[fin].entrada);
|
|
|
|
fin--;
|
|
}
|
|
|
|
|
|
if (ind_abs)
|
|
ind_cost=s->iamb[sec[ini].iamb];
|
|
else
|
|
ind_cost=sec[ini].iamb;
|
|
id_ambf=s->iamb[sec[ini].iamb];
|
|
d+=olv_reco->cost_amb[id_ambf][id_ambf];//suma el coste de hacer el primer ambito
|
|
|
|
if(ini==0)//si ini es 0 falta sumar el coste de la planta a el primer ambito
|
|
{
|
|
d+=olv_limp->arch_dj.dame_dis(olv_limp->arch_dj.id_instal, 0, s->iamb[sec[ini].iamb],0);
|
|
d+=olv_reco->t_sal; //suma el coste de la salida
|
|
}
|
|
|
|
cap_t+=olv_limp->iaso[olv_limp->carto.get(id_ambf).entity()->ref].inf_r.kg;//suma a la carga total la basura del primer ambito
|
|
|
|
nv_p=(int)(cap_t/capac_v +1);//numero de veces que se tendra que ir a planta
|
|
cap_h=nv_p*capac_v-cap_t;//carga con la que se puede jugar (holgura) capacidad desaprovechada
|
|
if(cap_h>=capac_v)
|
|
{
|
|
cap_h-=capac_v;
|
|
nv_p--;
|
|
}
|
|
|
|
cap_t+=olv_reco->iaso[olv_limp->carto.get(ind_cost).entity()->ref].inf_r.kg;
|
|
//suma coste de ir a planta
|
|
|
|
if (ind_abs)
|
|
ind_cost=s->iamb[sec[fin_old].iamb];
|
|
else
|
|
ind_cost=sec[fin_old].iamb;
|
|
id_ambf=s->iamb[sec[fin_old].iamb];//id del ultimo ambito
|
|
|
|
nv_p--;//se descuenta uno porque se tiene que terminar en planta
|
|
d+=olv_reco->ord_sec_plan[OLV_PLANT].ctnod[0][olv_reco->iaso[olv_limp->carto.get(id_ambf).entity()->ref].inod[0]].dis;//suma el coste de ir del ultimo ambito a la planta
|
|
d+=olv_reco->t_descarg;//suma el coste de descargar
|
|
d+=olv_reco->ord_sec_plan[OLV_INSTAL].ctnod[0][olv_reco->nod_plant].dis;//suma el coste de ir de planta a instalacion
|
|
d+=olv_reco->t_sal;//suma el coste de la llegada
|
|
|
|
int iold=-1;
|
|
BOOL errores=FALSE;
|
|
double cos_tray=d;
|
|
int veces_plan=nv_p;
|
|
BOOL salir=FALSE;
|
|
double cap_ult_cont;
|
|
while (!salir)
|
|
{
|
|
salir=TRUE;
|
|
cap_h=(1+veces_plan)*capac_v-cap_t;
|
|
nv_p=veces_plan;
|
|
coste=MAYUSCULO;
|
|
cap_g=0;
|
|
sel=-1;
|
|
d=cos_tray;
|
|
cap_act=0;
|
|
int isel_old=-1;
|
|
double cap_old;
|
|
i=ini;
|
|
|
|
while(nv_p>0 && i<=fin_old)
|
|
{
|
|
if (ind_abs)
|
|
ind_cost=s->iamb[sec[i].iamb];
|
|
else
|
|
ind_cost=sec[i].iamb;
|
|
id_ambf=s->iamb[sec[i].iamb];//id del ambito iesimo de la secuen
|
|
ref_ambf = olv_limp->carto.get(id_ambf).entity()->ref;
|
|
cap_old=cap_act;
|
|
cap_act+=olv_reco->iaso[ref_ambf].inf_r.kg;//suma capacidad del ambito de la secuencia iesima
|
|
cap_ult_cont=olv_reco->iaso[ref_ambf].inf_r.kg;
|
|
i++;
|
|
if(i>fin_old)
|
|
{
|
|
if(cap_act<capac_v)
|
|
break;
|
|
}
|
|
id_ambf1=s->iamb[sec[i].iamb];//id del ambito iesimo+1 de la secuen
|
|
if (ind_abs)
|
|
ind_cost1=s->iamb[sec[i].iamb];
|
|
else
|
|
ind_cost1=sec[i].iamb;
|
|
if((capac_v-cap_act)>cap_h)
|
|
{
|
|
//calcula si el siguiente entra
|
|
|
|
if((cap_act+olv_reco->iaso[olv_limp->carto.get(id_ambf1).entity()->ref].inf_r.kg)>capac_v)
|
|
{
|
|
nv_p++;
|
|
cap_h=cap_h+capac_v;
|
|
}
|
|
else
|
|
continue;
|
|
}
|
|
if(cap_act-capac_v<=0)
|
|
{
|
|
//prueba candidato
|
|
//calcula el coste de ir a planta desde el i-1 y de planta a el i y se le resta el coste de ir del i-1 al i
|
|
dd=olv_reco->ord_sec_plan[OLV_PLANT].ctnod[0][olv_reco->iaso[ref_ambf].inod[0]].dis;//coste del i-1 a planta
|
|
dd+=olv_limp->arch_dj.dame_dis(olv_limp->arch_dj.id_plan,0,id_ambf1, 0);
|
|
dd-=olv_limp->arch_dj.dame_dis(id_ambf,0,id_ambf1, 0);
|
|
|
|
dd+=olv_reco->t_descarg;//suma el coste de descargar
|
|
if(dd>=MAYUSCULO)
|
|
errores=TRUE;//existen errores
|
|
if(coste>dd)
|
|
{
|
|
sel=i;
|
|
coste=dd;
|
|
cap_g=capac_v-cap_act;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//pone candidato
|
|
//suma coste de ir a la planta y el de volver de ella
|
|
if(coste>=MAYUSCULO)
|
|
{
|
|
if(errores)
|
|
olvlog(LOG_TODO,"olv_limp_t","No conseguido candidato para ir a descargar");//algo va mal
|
|
//pone una vuelta mas a planta en el i-1;
|
|
salir=FALSE;
|
|
veces_plan++;
|
|
if(cap_ult_cont>capac_v)
|
|
{
|
|
olvlog(LOG_TODO,"olv_limp_t","Capacidad de contenedor %ld mas grande que la del vehiculo ", i);//algo va mal
|
|
return MAYUSCULO;
|
|
}
|
|
break;
|
|
//calcula coste
|
|
|
|
}
|
|
cap_act=0;
|
|
cap_h-=cap_g;
|
|
iold=i;
|
|
isel_old=sel;
|
|
i=sel;
|
|
d+=coste;
|
|
cap_g=0;
|
|
coste=MAYUSCULO;
|
|
sel=-1;
|
|
nv_p--;
|
|
|
|
}
|
|
}
|
|
}
|
|
return d;
|
|
}
|
|
//*************************************************************************************
|
|
/**
|
|
* Rellena los tiempos de desplazamiento
|
|
*/
|
|
void Colv_reco_thr::pon_t_desp(Info_sec *s, Secu_amb *sec)
|
|
{
|
|
if((olv_limp->nod_instal>=0) && (s->namb>1))
|
|
{
|
|
s->t_despl[0]=olv_limp->arch_dj.dame_dis(olv_limp->arch_dj.id_instal,0 ,s->iamb[sec[0].iamb],sec[0].entrada);
|
|
s->t_despl[1]=olv_limp->ord_sec_plan[OLV_PLANT].ctnod[0][olv_reco->nod_instal].dis;
|
|
|
|
}
|
|
}
|
|
//*************************************************************************************
|
|
/**
|
|
* Calcula el coste de desplazamiento de ir por todos los ambitos sec desde ini hasta fin, e indica en qué puntos se va a vaciar
|
|
*/
|
|
double Colv_reco_thr::dame_coste_pon_viajes( Secu_amb * sec, int ini, int fin, Info_sec *s, int *nvac)
|
|
{
|
|
double d=0;
|
|
int ind_cost, ind_cost1;
|
|
int fin_old=fin;
|
|
int id_ambf, ref_ambf;
|
|
int id_ambf1;
|
|
double capac_v=olv_reco->kg_max, cap_act=0,cap_h, cap_t;
|
|
int nv_p, i, sel;//numero de veces por ir a planta
|
|
double coste;
|
|
double cap_g, dd;
|
|
cap_t=cap_act;
|
|
|
|
BOOL ind_abs=TRUE;
|
|
|
|
while(ini<fin)
|
|
{
|
|
id_ambf=s->iamb[sec[fin].iamb];
|
|
id_ambf1=s->iamb[sec[fin-1].iamb];
|
|
|
|
|
|
if (ind_abs)
|
|
ind_cost=id_ambf;
|
|
else
|
|
ind_cost=sec[fin].iamb;
|
|
ref_ambf = olv_limp->carto.get(id_ambf).entity()->ref;
|
|
|
|
cap_t+=olv_reco->iaso[ref_ambf].inf_r.kg;//suma a la carga la basura del ambito
|
|
d+=olv_limp->cost_amb[id_ambf][id_ambf];//suma el coste del ambito
|
|
d+=olv_limp->arch_dj.dame_dis(id_ambf1, 0, id_ambf,sec[fin].entrada);
|
|
fin--;
|
|
}
|
|
if (ind_abs)
|
|
ind_cost=s->iamb[sec[ini].iamb];
|
|
else
|
|
ind_cost=sec[ini].iamb;
|
|
id_ambf=s->iamb[sec[ini].iamb];
|
|
d+=olv_reco->cost_amb[id_ambf][id_ambf];//suma el coste de hacer el primer ambito
|
|
|
|
if(ini==0)//si ini es 0 falta sumar el coste de la planta a el primer ambito
|
|
{
|
|
d+=olv_limp->arch_dj.dame_dis(olv_limp->arch_dj.id_instal, 0, s->iamb[sec[ini].iamb],0);
|
|
d+=olv_reco->t_sal;//suma el coste de la salida
|
|
}
|
|
|
|
cap_t+=olv_limp->iaso[olv_limp->carto.get(id_ambf).entity()->ref].inf_r.kg;//suma a la carga total la basura del primer ambito
|
|
|
|
//////////////////
|
|
//lo almacena
|
|
s->dis_med=(float)cap_t;
|
|
//////////////////
|
|
|
|
nv_p=(int)(cap_t/capac_v +1);//numero de veces que se tendra que ir a planta
|
|
cap_h=nv_p*capac_v-cap_t;//carga con la que se puede jugar (holgura) capacidad desaprovechada
|
|
if(cap_h>=capac_v)
|
|
{
|
|
cap_h-=capac_v;
|
|
nv_p--;
|
|
}
|
|
|
|
cap_t+=olv_reco->iaso[olv_limp->carto.get(ind_cost).entity()->ref].inf_r.kg;
|
|
|
|
//suma coste de ir a planta
|
|
if (ind_abs)
|
|
ind_cost=s->iamb[sec[fin_old].iamb];
|
|
else
|
|
ind_cost=sec[fin_old].iamb;
|
|
id_ambf=s->iamb[sec[fin_old].iamb];//id del ultimo ambito
|
|
|
|
nv_p--;//se descuenta uno porque se tiene que terminar en planta
|
|
d+=olv_reco->ord_sec_plan[OLV_PLANT].ctnod[0][olv_reco->iaso[olv_limp->carto.get(id_ambf).entity()->ref].inod[0]].dis;//suma el coste de ir del ultimo ambito a la planta
|
|
d+=olv_reco->ord_sec_plan[OLV_INSTAL].ctnod[0][olv_reco->nod_plant].dis;//suma el coste de ir de planta a instalacion
|
|
d+=olv_reco->t_sal;//suma el coste de la llegada
|
|
d+=olv_reco->t_descarg;//suma el coste de descargar
|
|
///////////////////////////
|
|
coste=MAYUSCULO;
|
|
|
|
int iold=-1;
|
|
BOOL errores=FALSE;
|
|
double cos_tray=d;
|
|
int veces_plan=nv_p;
|
|
BOOL salir=FALSE;
|
|
double cap_ult_cont;
|
|
while (!salir)
|
|
{
|
|
salir=TRUE;
|
|
cap_h=(1+veces_plan)*capac_v-cap_t;
|
|
nv_p=veces_plan;
|
|
coste=MAYUSCULO;
|
|
cap_g=0;
|
|
sel=-1;
|
|
d=cos_tray;
|
|
cap_act=0;
|
|
int isel_old=-1;
|
|
double cap_old;
|
|
i=ini;
|
|
//borra marcas------------
|
|
for(int ii=0; ii<fin_old-1; ii++)
|
|
{
|
|
id_ambf=s->iamb[sec[ii].iamb];
|
|
olv_reco->ptos_vaci[id_ambf]=0;
|
|
}
|
|
while(nv_p>0 && i<=fin_old)
|
|
{
|
|
if (ind_abs)
|
|
ind_cost=s->iamb[sec[i].iamb];
|
|
else
|
|
ind_cost=sec[i].iamb;
|
|
id_ambf=s->iamb[sec[i].iamb];//id del ambito iesimo de la secuen
|
|
ref_ambf = olv_limp->carto.get(id_ambf).entity()->ref;
|
|
cap_old=cap_act;
|
|
cap_act+=olv_reco->iaso[ref_ambf].inf_r.kg;//suma capacidad del ambito de la secuencia iesima
|
|
cap_ult_cont=olv_reco->iaso[ref_ambf].inf_r.kg;
|
|
i++;
|
|
if(i>fin_old)
|
|
{
|
|
if(cap_act<capac_v)
|
|
break;
|
|
}
|
|
id_ambf1=s->iamb[sec[i].iamb];//id del ambito iesimo+1 de la secuen
|
|
if (ind_abs)
|
|
ind_cost1=s->iamb[sec[i].iamb];
|
|
else
|
|
ind_cost1=sec[i].iamb;
|
|
if((capac_v-cap_act)>cap_h)
|
|
{
|
|
//calcula si el siguiente entra
|
|
|
|
if((cap_act+olv_reco->iaso[olv_limp->carto.get(id_ambf1).entity()->ref].inf_r.kg)>capac_v)
|
|
{
|
|
nv_p++;
|
|
cap_h=cap_h+capac_v;
|
|
}
|
|
else
|
|
continue;
|
|
}
|
|
if(cap_act-capac_v<=0)
|
|
{
|
|
|
|
//prueba candidato
|
|
//calcula el coste de ir a planta desde el i-1 y de planta a el i y se le resta el coste de ir del i-1 al i
|
|
dd=olv_reco->ord_sec_plan[OLV_PLANT].ctnod[0][olv_reco->iaso[ref_ambf].inod[0]].dis;//coste del i-1 a planta
|
|
|
|
dd+=olv_limp->arch_dj.dame_dis(olv_limp->arch_dj.id_plan,0,s->iamb[sec[i].iamb],0);
|
|
dd-=olv_limp->arch_dj.dame_dis(id_ambf, 0, s->iamb[sec[i].iamb],0);
|
|
|
|
dd+=olv_reco->t_descarg;//suma el coste de descargar
|
|
if(dd>=MAYUSCULO)
|
|
errores=TRUE;//existen errores
|
|
if(sel==-1
|
|
|| (coste>dd))
|
|
{
|
|
sel=i;
|
|
coste=dd;
|
|
cap_g=capac_v-cap_act;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//suma coste de ir a la planta y el de volver de ella
|
|
if(coste>=MAYUSCULO)
|
|
{
|
|
if(errores)
|
|
olvlog(LOG_TODO,"olv_limp_t","No conseguido candidato para ir a descargar");//algo va mal
|
|
//pone una vuelta mas a planta en el i-1;
|
|
salir=FALSE;
|
|
veces_plan++;
|
|
if(cap_ult_cont>capac_v)
|
|
{
|
|
olvlog(LOG_TODO,"olv_limp_t","Capacidad de contenedor %ld mas grande que la del vehiculo ", i);//algo va mal
|
|
return MAYUSCULO;
|
|
}
|
|
break;
|
|
//calcula coste
|
|
|
|
}
|
|
cap_act=0;
|
|
cap_h-=cap_g;
|
|
iold=i;
|
|
isel_old=sel;
|
|
i=sel;
|
|
///////////////
|
|
//pone candidato
|
|
olv_reco->ptos_vaci[s->iamb[sec[i-1].iamb]]=(short)OLV_IDA_PLANT;
|
|
///////////////
|
|
d+=coste;
|
|
cap_g=0;
|
|
coste=MAYUSCULO;
|
|
sel=-1;
|
|
nv_p--;
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
//Cuenta el número de veces que va a vaciar
|
|
sel=0;
|
|
for(i=0;i<s->namb;i++)
|
|
{
|
|
if(olv_reco->ptos_vaci[s->iamb[sec[i].iamb]])
|
|
sel++;
|
|
}
|
|
id_ambf=s->iamb[sec[fin_old].iamb];//id del ultimo ambito
|
|
olv_reco->ptos_vaci[id_ambf]=(short)OLV_IDA_PLANT_ULT; //indica que en el último se va a planta
|
|
|
|
*nvac=sel;
|
|
|
|
return d;
|
|
}
|
|
//*************************************************************************************
|
|
/**
|
|
* Lanza sub-threads
|
|
*/
|
|
void Colv_reco_thr::lanza_subthrs(int tar, int nthr_def/*=-1*/)
|
|
{
|
|
char nomb[32];
|
|
Param_olv_limp_thr pp;
|
|
int nn;
|
|
if((nthr_def>0) && (nthr_def<n_subthr))
|
|
nn=nthr_def;
|
|
else
|
|
nn=n_subthr;
|
|
//Arranca los subthreads
|
|
for(int i=0;i<nn;i++)
|
|
{
|
|
if(!subthrs[i])
|
|
subthrs[i]=new Colv_reco_thr(olv_reco);
|
|
sprintf_s(nomb,32,"limp_subth_%ld",i);
|
|
pp.id_e=i;
|
|
subthrs[i]->n_subthr = nn;
|
|
subthrs[i]->thr_padre=this;
|
|
subthrs[i]->pirate=FALSE;
|
|
subthrs[i]->inicia(OLV_MILIS_COLA,&cola_proc,-1,nomb);
|
|
subthrs[i]->encola(tar,&pp,FALSE);
|
|
}
|
|
|
|
//fuerza fin para que avance olivia
|
|
for(int i=nn;i<n_subthr;i++)
|
|
{
|
|
if(!subthrs[i])
|
|
subthrs[i]=new Colv_limp_thr(olv_limp);
|
|
subthrs[i]->prog_subthr = 0;
|
|
}
|
|
for(int i=0;i<n_subthr-nn;i++)
|
|
encola(tar+1,NULL,FALSE); //encola la tarea de fin
|
|
}
|
|
//*************************************************************************************
|
|
/**
|
|
* Devuelve la planificación del sector iésimo, que realiza el thread 'ithr'
|
|
*/
|
|
void Colv_reco_thr::planifica_sub_1(int ithr, Matrix2d<float> &cost_amb)
|
|
{
|
|
Info_sec *s;
|
|
Info_amb_sec *aa;
|
|
int i,iaux,is_ini,is_fin,is_desp,is,jmin,nvac;
|
|
|
|
BOOL log_debug=FALSE;
|
|
BOOL sal,sig;
|
|
Djkt_nodo *costes_nodos;
|
|
int nsecu,KK,ic_aux,ss;
|
|
int nsecu2;
|
|
Secu_amb *secu_ambi=NULL;
|
|
Param_olv_limp_thr pp;
|
|
Djkt_nodo *buf_aux=NULL;
|
|
int msecu1, msecu2;
|
|
|
|
int *secu, *secu2;
|
|
costes_nodos=NULL;
|
|
msecu2 = msecu1 = olv_limp->conjs.n;
|
|
secu=(int *)malloc(olv_limp->conjs.n*sizeof(int));
|
|
if(!secu)
|
|
{
|
|
sal=TRUE;
|
|
goto fin;
|
|
}
|
|
memset(secu,0,olv_limp->conjs.n*sizeof(int));
|
|
secu2=(int *)malloc(olv_limp->conjs.n*sizeof(int));
|
|
if(!secu2)
|
|
{
|
|
sal=TRUE;
|
|
goto fin;
|
|
}
|
|
memset(secu2,0,olv_limp->conjs.n*sizeof(int));
|
|
nsecu2=0;
|
|
//////////////////////////
|
|
pp.id_e=OLV_TAREA_PLANIF;//manda de parámetro la tarea de la que es el progreso
|
|
ic_aux=0;
|
|
KK=olv_limp->tipo_ambit;
|
|
sal=sig=FALSE;
|
|
jmin=0;
|
|
prog_subthr=0;
|
|
//cost_amb=olv_limp->cost_amb;
|
|
aa=olv_limp->amb_sec;
|
|
iaux=-1;
|
|
|
|
////////////////////////////////////////////////////
|
|
//mira a ver cuántos sectores le tocan a este thread
|
|
if(olv_limp->nsec<n_subthr)
|
|
{
|
|
//hay menos sectores que threads, o le toca uno o ninguno
|
|
if(ithr<olv_limp->nsec)
|
|
{
|
|
//solo hace un sector, el ithr-esimo
|
|
is_ini=ithr;
|
|
is_fin=ithr+1;
|
|
}
|
|
else
|
|
{
|
|
//no hace ningún sector, no hace falta
|
|
is_ini=0;
|
|
is_fin=0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//hay más sectores que threads, le tocan más de uno
|
|
is_desp=(int)ceil(1.0*(olv_limp->nsec)/n_subthr);
|
|
is_ini= min(ithr*is_desp, olv_limp->nsec);
|
|
is_fin=min((ithr+1)*is_desp,olv_limp->nsec);
|
|
}
|
|
//////////////////////////
|
|
if(is_fin==is_ini)
|
|
olvlog(LOG_TODO,"olv_limp_t","Subthr %02d, No Planifica ningún sector", ithr);
|
|
else if(is_fin-is_ini-1==0)
|
|
olvlog(LOG_TODO,"olv_limp_t","Subthr %02d, Planifica sector %02d", ithr,is_ini);
|
|
else
|
|
olvlog(LOG_TODO,"olv_limp_t","Subthr %02d, Planifica sectores %02d a %02d", ithr,is_ini, is_fin-1);
|
|
|
|
buf_aux=olv_limp->arch_dj.dame_buf_nodos();
|
|
if(!buf_aux)
|
|
{
|
|
olvlog(LOG_TODO,"olv_limp_t","Error en planifica_sub 1 th: %ld sin memo para buffer", ithr);
|
|
sal=TRUE;
|
|
}
|
|
//////////////////////////
|
|
//bucle en todos los sectores que le tocan al thread
|
|
for(is=is_ini;is<is_fin && !pirate && !sal;is++)
|
|
{
|
|
s = &olv_limp->sec[is];
|
|
if(s->namb<=0)
|
|
continue;
|
|
s->cost_despl_aux=0;
|
|
sig=FALSE;
|
|
|
|
//busca el ámbito inicial de la planificiación
|
|
secu_ambi=planifica_sect(s,olv_limp->ang_conj,OLV_LIMP_FACT_PERM);
|
|
if(!secu_ambi)
|
|
{
|
|
olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Imposible planificar sector %02d",ithr,is);
|
|
sal=TRUE;
|
|
continue;
|
|
}
|
|
if(esta_repe(secu_ambi, s->namb))
|
|
{
|
|
olvlog(LOG_TODO,"olv_limp_t","Esta repe despues de planifica sec");
|
|
sal=TRUE;
|
|
continue;
|
|
}
|
|
nvac=0;
|
|
s->cost_despl_aux=(float)dame_coste_pon_viajes(secu_ambi,0,s->namb-1,s,&nvac);
|
|
|
|
if(s->cost_despl_aux==0)
|
|
{
|
|
olvlog(LOG_TODO,"olv_limp_t","Error al calcular viajes");
|
|
sal=TRUE;
|
|
continue;
|
|
}
|
|
olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Sector %02d, va a vaciar %ld veces",ithr,is,nvac);
|
|
|
|
///////////////////////////////////////////
|
|
//Añade la ruta de la instalación al primer punto
|
|
double cc = 0, cc1 = 0;
|
|
olv_limp->arch_dj.get_b(s->iamb[secu_ambi[0].iamb],secu_ambi[0].entrada, buf_aux);
|
|
cc+=Colv_geom::ruta_dj_inv_ok(
|
|
olv_reco->nod_instal,//id conjuncion inicial
|
|
&secu2[0], //puntero a secuencia
|
|
buf_aux, //nodos djktra conj final
|
|
olv_limp->conjs.n,
|
|
&nsecu2);
|
|
cc += olv_limp->t_sal;
|
|
if(!genera_planif_vaci(is,0, nsecu2, secu2,OLV_IDA_INST))
|
|
sal=TRUE;
|
|
///////////////////////////////////////////
|
|
|
|
|
|
secu[0]=olv_limp->iaso[olv_limp->carto.get(s->iamb[secu_ambi[0].iamb]).entity()->ref].inod[secu_ambi[0].entrada];
|
|
aa[s->iamb[secu_ambi[0].iamb]].iseq=0;
|
|
//olv_limp->t_conv
|
|
ss=1;
|
|
int iam_ped;
|
|
int iam_ent;
|
|
for (i=1; i<s->namb; i++)
|
|
{
|
|
///////////////////////////////////////////
|
|
//Comprueba si hay que ir a vaciar
|
|
if(olv_reco->ptos_vaci[s->iamb[secu_ambi[i-1].iamb]]==(short)OLV_IDA_PLANT)
|
|
{
|
|
//de i-1 a planta
|
|
cc+=Colv_geom::ruta_dj_inv_ok(
|
|
olv_limp->iaso[olv_limp->carto.get(s->iamb[secu_ambi[i-1].iamb]).entity()->ref].inod[(secu_ambi[i-1].entrada+1)%2],
|
|
&secu2[0], //puntero a secuencia
|
|
olv_reco->ord_sec_plan[OLV_PLANT].ctnod[0], //nodos djktra conj final
|
|
olv_limp->conjs.n,
|
|
&nsecu2);
|
|
cc += olv_reco->t_descarg;
|
|
if(!genera_planif_vaci(is,0, nsecu2, secu2,OLV_IDA_PLANT))
|
|
{
|
|
sal=TRUE;
|
|
break;
|
|
}
|
|
//de planta a i
|
|
olv_limp->arch_dj.get_b(s->iamb[secu_ambi[i].iamb],secu_ambi[i].entrada, buf_aux);
|
|
iam_ped=s->iamb[secu_ambi[i].iamb];
|
|
iam_ent=secu_ambi[i].entrada;
|
|
cc+=Colv_geom::ruta_dj_inv_ok(
|
|
olv_reco->nod_plant,
|
|
&secu2[0], //puntero a secuencia
|
|
buf_aux, //nodos djktra conj final
|
|
olv_limp->conjs.n,
|
|
&nsecu2);
|
|
|
|
if(!genera_planif_vaci(is,0, nsecu2, secu2,OLV_VUELTA_PLANT))
|
|
{
|
|
sal=TRUE;
|
|
break;
|
|
}
|
|
|
|
}
|
|
else
|
|
iam_ped=iam_ent=-1;
|
|
if(i==s->namb)
|
|
continue;
|
|
///////////////////////////////////////////
|
|
|
|
if(iam_ped!=s->iamb[secu_ambi[i].iamb] || iam_ent!=secu_ambi[i].entrada)
|
|
olv_limp->arch_dj.get_b(s->iamb[secu_ambi[i].iamb],secu_ambi[i].entrada, buf_aux);
|
|
Colv_geom::ruta_dj_inv_ok(
|
|
olv_limp->iaso[olv_limp->carto.get(s->iamb[secu_ambi[i-1].iamb]).entity()->ref].inod[(secu_ambi[i-1].entrada+1)%2],//id conjuncion inicial
|
|
&secu[ss], //puntero a secuencia
|
|
buf_aux, //nodos djktra conj final
|
|
olv_limp->conjs.n,
|
|
&nsecu);
|
|
ss+=nsecu;
|
|
|
|
//almacena el coste acumulado
|
|
aa[s->iamb[secu_ambi[i].iamb]].iseq=i;
|
|
|
|
//////////////////
|
|
if((i%50)==0 || (i==s->namb-1))
|
|
{
|
|
//avisa de progreso
|
|
olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Planificando sector %02d, amb %ld de %ld", ithr,is,
|
|
(i+1),(s->namb));
|
|
prog_subthr=(1.0*(i+1)/(s->namb))*((is+1)/(is_fin-is_ini)); //porque son varios sectores
|
|
thr_padre->encola(OLV_LIMP_EV_SUBTHR_PROG,&pp,FALSE);
|
|
}
|
|
/////////////////
|
|
|
|
}
|
|
if(olv_limp->tipo_ambit==OLV_AMB_LIN)//añade el coste del último ámbito si es lineal
|
|
{
|
|
secu[ss++]=olv_limp->iaso[olv_limp->carto.get(s->iamb[secu_ambi[s->namb-1].iamb]).entity()->ref].inod[(secu_ambi[s->namb-1].entrada+1)%2];
|
|
}
|
|
|
|
///////////////////////////////////////////
|
|
//Añade la ruta del último punto a descargar
|
|
cc+=Colv_geom::ruta_dj_inv_ok(
|
|
olv_limp->iaso[olv_limp->carto.get(s->iamb[secu_ambi[s->namb-1].iamb]).entity()->ref].inod[(secu_ambi[s->namb-1].entrada+1)%2],
|
|
&secu2[0], //puntero a secuencia
|
|
olv_reco->ord_sec_plan[OLV_PLANT].ctnod[0], //nodos djktra conj final
|
|
olv_limp->conjs.n,
|
|
&nsecu2);
|
|
cc += olv_reco->t_descarg;
|
|
if(!genera_planif_vaci(is,0, nsecu2, secu2,OLV_IDA_PLANT))
|
|
{
|
|
sal=TRUE;
|
|
break;
|
|
}
|
|
if(olv_reco->nod_instal!=olv_reco->nod_plant)
|
|
{
|
|
//de descargar a la instalación
|
|
cc+=Colv_geom::ruta_dj_inv_ok(
|
|
olv_reco->nod_plant,
|
|
&secu2[0], //puntero a secuencia
|
|
olv_reco->ord_sec_plan[OLV_INSTAL].ctnod[0], //nodos djktra conj final
|
|
olv_limp->conjs.n,
|
|
&nsecu2);
|
|
if(!genera_planif_vaci(is,0, nsecu2, secu2,OLV_VUELTA_INST))
|
|
{
|
|
sal=TRUE;
|
|
break;
|
|
}
|
|
}
|
|
cc += olv_limp->t_sal; //suma el tiempo tanto si va a instala como si no
|
|
///////////////////////////////////////////
|
|
|
|
if(esta_repe(secu_ambi, s->namb, FALSE))
|
|
olvlog(LOG_TODO,"olv_limp_t","Esta repe despues de planificar");
|
|
|
|
olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Planificando sector %02d, coste total %lf",ithr,is,s->cost_despl_aux);
|
|
|
|
if(!pirate && !sal)
|
|
{
|
|
//////////////////////////////////
|
|
//genera la ruta y los puntos de control
|
|
if(!genera_planif(is,s->cost_despl_aux/*-cc*/, ss, secu,OLV_PLAN_RECO))
|
|
sal=TRUE;
|
|
//olv_limp->sec[is].cost_ac = s->cost_despl_aux;
|
|
olv_limp->sec[is].cost_ac=(float)(olv_limp->plan[is].elem[olv_limp->plan[is].nelem-1].coste+cc);
|
|
}
|
|
//////////////////////////////////
|
|
if( secu_ambi)
|
|
{
|
|
free(secu_ambi);
|
|
secu_ambi=NULL;
|
|
}
|
|
}
|
|
free(secu);
|
|
free(secu2);
|
|
fin:
|
|
//Ha terminado, encola al padre
|
|
olv_limp->arch_dj.libera_buf(buf_aux);
|
|
if(sal)
|
|
{
|
|
prog_subthr=-1;//para avisar al padre de que ha habido un error
|
|
}
|
|
thr_padre->encola(OLV_LIMP_EV_PLANIFICA_FIN,NULL,FALSE);
|
|
}
|
|
//*************************************************************************************
|
|
/**
|
|
* Pone en la ruta en qué contenedores corresponden los puntos de control
|
|
*/
|
|
void Colv_reco_thr::pon_ptos_ctrl(Info_planif *pp, int npt_ctrl, double cost_ctrl)
|
|
{
|
|
double cost_acum, cost_viajes;
|
|
int i, ipc, iviaje;
|
|
///////////////////////////////////////////////////////////////
|
|
//Inicializa el array de puntos de control
|
|
pp->pts_ctrl=(Info_planif_ctrl*)malloc((olv_limp->npts_ctrl-2+1)*sizeof(Info_planif_ctrl));
|
|
if(!pp->pts_ctrl)
|
|
return;
|
|
memset(pp->pts_ctrl,0,(olv_limp->npts_ctrl-2+1)*sizeof(Info_planif_ctrl));
|
|
ipc=0;
|
|
|
|
/////////////////////////////
|
|
cost_acum=cost_viajes=0;
|
|
iviaje=1;//la primera ida será en el viaje 1 (ida desde inst,ida a planta)
|
|
for(i=0;i<pp->nelem;i++)
|
|
{
|
|
/////////////////////////////
|
|
cost_acum=pp->elem[i].coste+cost_viajes;
|
|
|
|
//mira si toca punto de control
|
|
if((cost_acum-ipc*(cost_ctrl/*+olv_limp->t_desc*/))>(cost_ctrl+1))
|
|
{
|
|
if(ipc<npt_ctrl)
|
|
{
|
|
//añade como punto de control
|
|
pp->pts_ctrl[ipc].ipt=i-1;
|
|
ipc++;
|
|
}
|
|
else
|
|
ipc=ipc;
|
|
}
|
|
|
|
if(pp->elem[i].tp==OLV_PLAN_TIP_AMB)
|
|
{
|
|
if(olv_reco->ptos_vaci[olv_limp->iaso[pp->elem[i].refe].iamb]==(short)OLV_IDA_PLANT)
|
|
{
|
|
cost_viajes+=pp->planif_insta[iviaje].elem[pp->planif_insta[iviaje].nelem-1].coste;//ida
|
|
iviaje++;
|
|
cost_viajes+=olv_reco->t_descarg;
|
|
cost_viajes+=pp->planif_insta[iviaje].elem[pp->planif_insta[iviaje].nelem-1].coste;//vuelta
|
|
iviaje++;
|
|
}
|
|
}
|
|
}
|
|
|
|
for(i=0;i<npt_ctrl;i++)
|
|
{
|
|
if(pp->pts_ctrl[i].ipt<0)
|
|
pp->pts_ctrl[i].ipt=pp->nelem-1;
|
|
}
|
|
}
|
|
//*************************************************************************************
|
|
/**
|
|
* Dada la secuencia de las conjunciones que sigue la ruta para ir a vaciar, genera el obg
|
|
*/
|
|
BOOL Colv_reco_thr::genera_planif_vaci(int is, int ini, int fin, int *secu, int tip_viaje)
|
|
{
|
|
int i,nvaciados;
|
|
Info_planif *pp,*pp_insta;
|
|
Info_sec *ss;
|
|
|
|
ss=&olv_limp->sec[is];
|
|
pp=&olv_limp->plan[is];
|
|
pp_insta = pp->planif_insta;
|
|
nvaciados=0;
|
|
if(!pp_insta)
|
|
{
|
|
nvaciados=1;//siempre está el último, que va a vaciar
|
|
for(i=0;i<ss->namb;i++)
|
|
{
|
|
if(olv_reco->ptos_vaci[ss->iamb[i]]==(short)OLV_IDA_PLANT)
|
|
nvaciados++;//por cada vez que va a descargar
|
|
}
|
|
}
|
|
if(!genera_planif_instala(is, nvaciados, ini, fin, secu, tip_viaje))
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
//*************************************************************************************
|
|
/**
|
|
* Añade una línea al listado csv con el viaje a vaciar y vuelta
|
|
*/
|
|
BOOL Colv_reco_thr::genera_list_fila_vaci(Colv_csv *cc, char *fila0, int ielem, int isec, int secu, double tt, double *t0,BOOL is_fin)
|
|
{
|
|
int h,m,seg,i,iplan;
|
|
Info_planif *pp;
|
|
double cost_despl,ltot,kgac;
|
|
int iamb, iamb2;
|
|
|
|
iamb=olv_limp->iaso[ielem].iamb;
|
|
if(iamb<0)
|
|
iamb=olv_limp->iaso[ielem].refe2;
|
|
|
|
if(iamb<0 || !olv_reco->ptos_vaci[iamb])
|
|
return TRUE;//no es punto en el que se va a vaciar
|
|
|
|
if(!is_fin && (olv_reco->ptos_vaci[iamb]!=(short)OLV_IDA_PLANT))
|
|
return TRUE;//no es punto en el que se va a vaciar
|
|
|
|
//busca la ruta de este punto en el que se va a vaciar
|
|
if(!olv_limp->plan[isec].planif_insta || !olv_limp->plan[isec].ninsta)
|
|
return FALSE;
|
|
|
|
for(i=0;i<olv_limp->plan[isec].ninsta;i++)
|
|
{
|
|
if(olv_limp->plan[isec].planif_insta[i].elem[0].refe==ielem)
|
|
break;
|
|
}
|
|
if(i>=olv_limp->plan[isec].ninsta)
|
|
return FALSE;
|
|
|
|
iplan=i;
|
|
|
|
//ha encontrado la planificación, coge el tiempo de desplazamiento
|
|
pp = &olv_limp->plan[isec].planif_insta[i];
|
|
if(!pp->nelem)
|
|
return FALSE;
|
|
cost_despl = pp->elem[pp->nelem-1].coste;
|
|
ltot=pp->m[OLV_DESP];
|
|
|
|
//////////////////
|
|
//pone el tiempo acumulado anterior, en el que se inicia este vaciado, aprovecha y lo guarda aquí
|
|
pp->t[OLV_TTO]=tt;
|
|
//////////////////
|
|
|
|
//////////////////
|
|
//Calcula los kg acumulados
|
|
kgac=0;
|
|
for(i=0;i<olv_limp->plan[isec].nelem;i++)
|
|
{
|
|
if(olv_limp->plan[isec].elem[i].tp!=OLV_PLAN_TIP_AMB)
|
|
continue;
|
|
iamb2=olv_limp->iaso[olv_limp->plan[isec].elem[i].refe].refe2;
|
|
kgac+=olv_limp->iaso[iamb2].inf_r.kg;
|
|
if(olv_limp->plan[isec].elem[i].refe==ielem)
|
|
break;
|
|
}
|
|
if(i>=olv_limp->plan[isec].nelem)
|
|
return FALSE;
|
|
|
|
//le resta los kg acumulados en el viaje anterior
|
|
i=iplan;
|
|
while((i-2)>0)//dos antes está la anterior planif a vaciar, si la hubiera
|
|
{
|
|
kgac-=olv_limp->plan[isec].planif_insta[i-2].m[OLV_TTO];//aprovecha y lo guarda aquí
|
|
i-=2;
|
|
}
|
|
pp->m[OLV_TTO]=kgac;
|
|
//////////////////
|
|
|
|
dame_h_m_s(tt, &h, &m, &seg);
|
|
sprintf_s(fila0,256,"%02d;%04d;%s;%.1f;%s;%.1f;%02d:%02d:%02d;\r\n",isec+1,secu,"",kgac,"Ida a descargar",ltot,h,m,seg);
|
|
if(!cc->escribe(fila0))
|
|
{
|
|
return FALSE;
|
|
}
|
|
*t0 += cost_despl + olv_reco->t_descarg;
|
|
tt += cost_despl + olv_reco->t_descarg;
|
|
|
|
if (is_fin)
|
|
*t0 = tt;
|
|
|
|
if(olv_reco->ptos_vaci[iamb]!=(short)OLV_IDA_PLANT)
|
|
return TRUE;
|
|
|
|
//escribe la vuelta de la descarga
|
|
if((iplan+1)>=olv_limp->plan[isec].ninsta)
|
|
return TRUE;
|
|
pp = &olv_limp->plan[isec].planif_insta[iplan+1];
|
|
if(!pp->nelem)
|
|
return FALSE;
|
|
cost_despl = pp->elem[pp->nelem-1].coste;
|
|
ltot=pp->m[OLV_DESP];
|
|
|
|
//////////////////
|
|
//pone el tiempo acumulado
|
|
pp->t[OLV_TTO]=tt;
|
|
//////////////////
|
|
|
|
*t0+=cost_despl;
|
|
tt+=cost_despl;
|
|
dame_h_m_s(tt, &h, &m, &seg);
|
|
sprintf_s(fila0,256,"%02d;%04d;%s;%s;%s;%.1f;%02d:%02d:%02d;\r\n",isec+1,secu,"","","Vuelta de descargar",ltot,h,m,seg);
|
|
if(!cc->escribe(fila0))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//reinicia, para que no vuelva a entrar
|
|
olv_reco->ptos_vaci[iamb]=0;
|
|
|
|
|
|
return TRUE;
|
|
}
|
|
//*************************************************************************************
|
|
/**
|
|
* Quita al tiempo total el del último desplazamiento y la última descarga, solo para reco
|
|
*/
|
|
void Colv_reco_thr::quita_t_ult_desc(int s, double *t)
|
|
{
|
|
int tt=(int)*t;
|
|
if(olv_limp->plan[s].ninsta>2 && olv_limp->plan[s].planif_insta[olv_limp->plan[s].ninsta-2].nelem>0) //quita el tiempo de desplazamiento de la instalación a la planta
|
|
tt-=(int)olv_limp->plan[s].planif_insta[olv_limp->plan[s].ninsta-2].elem[olv_limp->plan[s].planif_insta[olv_limp->plan[s].ninsta-2].nelem-1].coste;
|
|
tt-=olv_reco->t_descarg;
|
|
*t=tt;
|
|
}
|
|
//*************************************************************************************
|
|
/**
|
|
* Añade una columna de observación al listado si es contenedores
|
|
*/
|
|
void Colv_reco_thr::dame_observ_cont(int iamb, char *observ)
|
|
{
|
|
int i=olv_limp->iaso[iamb].iamb;
|
|
if(i<0)
|
|
i=olv_limp->iaso[iamb].refe2;
|
|
sprintf_s(observ,32,"%ld",olv_limp->iaso[i].inf_r.uds);
|
|
}
|
|
//*************************************************************************************
|
|
/**
|
|
* Añade las columnas de información a la ruta, tiempos, longitudes, y demás
|
|
*/
|
|
BOOL Colv_reco_thr::guarda_cols_ruta(char *path_shp)
|
|
{
|
|
char *info;
|
|
char path_dbf[MAX_PATH];
|
|
double tt;
|
|
int h,m,s,j;
|
|
int nsec, i, isec_novac,p;
|
|
ManagerDbfGdataTable dbfmgr;
|
|
GdataTable db;
|
|
|
|
//cuenta el número de sectores no vacíos
|
|
nsec=0;
|
|
for(i=0;i<olv_limp->nsec;i++)
|
|
{
|
|
if(olv_limp->sec[i].namb!=0)
|
|
nsec++;
|
|
}
|
|
|
|
/////////////////////////////////////
|
|
|
|
if(!Colv_limp_thr::guarda_cols_ruta(path_shp))
|
|
return FALSE;
|
|
|
|
strcpy_s(path_dbf,MAX_PATH,path_shp);
|
|
//cambiaext(path_dbf,".shp",".dbf");
|
|
strcpy((Cdir_manager::extension_archivo(path_dbf)),"dbf");
|
|
|
|
info = (char *)malloc(nsec* OLV_SHP_SZ_CAMP_SZ);
|
|
if(!info)
|
|
{
|
|
return FALSE;
|
|
}
|
|
memset(info,0,nsec* OLV_SHP_SZ_CAMP_SZ);
|
|
AddColsDbf dataDbf(info);
|
|
if (!dbfmgr.LeeDbf(path_dbf, &db))
|
|
{
|
|
free(info);
|
|
return FALSE;
|
|
}
|
|
|
|
//elimina col M_DESP
|
|
if (!dbfmgr.DelCol(NULL, "M_DESP"))
|
|
{
|
|
free(info);
|
|
return FALSE;
|
|
}
|
|
|
|
//renombra T_DESP por T_RUTA
|
|
if (!db.rename(db.getInd("T_DESP"),"T_RUTA"))
|
|
{
|
|
free(info);
|
|
return FALSE;
|
|
}
|
|
|
|
//sustituye col m total
|
|
isec_novac = 0;
|
|
for (i = 0; i < olv_limp->nsec; i++)
|
|
{
|
|
if (olv_limp->sec[i].namb == 0)
|
|
continue;
|
|
|
|
tt = 0;
|
|
for(p=0;p<olv_limp->plan[i].ninsta;p++)
|
|
{
|
|
tt += olv_limp->plan[i].planif_insta[p].m[OLV_DESP];
|
|
}
|
|
|
|
tt += olv_limp->plan[i].m[OLV_DESP] + olv_limp->plan[i].m[OLV_TTO];
|
|
//para guardar en número
|
|
((double*)info)[isec_novac] = tt;
|
|
|
|
isec_novac++;
|
|
}
|
|
if (!dbfmgr.AddCol(NULL, "M_TOTAL", GdataTable::Tdouble, &dataDbf))
|
|
{
|
|
free(info);
|
|
return FALSE;
|
|
}
|
|
memset(info, 0, nsec * OLV_SHP_SZ_CAMP_SZ);
|
|
|
|
//sustituye la columna de uds de tratamiento porque hay contenedores que son varias unidades
|
|
isec_novac=0;
|
|
for(i=0;i<nsec;i++)
|
|
{
|
|
if(olv_limp->sec[i].namb==0)
|
|
continue;
|
|
tt=0;
|
|
for(j=0;j<olv_limp->sec[i].namb;j++)
|
|
tt+=olv_limp->iaso[olv_limp->sec[i].iamb[j]].inf_r.uds;
|
|
//para guardar en número
|
|
((int*)info)[isec_novac] = tt;
|
|
isec_novac++;
|
|
}
|
|
if(!dbfmgr.AddCol(NULL,"UDS_TRAT",GdataTable::Tint,&dataDbf))
|
|
{
|
|
free(info);
|
|
return FALSE;
|
|
}
|
|
memset(info,0,nsec* OLV_SHP_SZ_CAMP_SZ);
|
|
|
|
//Kg recogidos
|
|
isec_novac=0;
|
|
for(i=0;i<olv_limp->nsec;i++)
|
|
{
|
|
if(olv_limp->sec[i].namb==0)
|
|
continue;
|
|
tt=olv_limp->sec[i].dis_med;
|
|
//para guardar en número
|
|
((double*)info)[isec_novac] = tt;
|
|
isec_novac++;
|
|
}
|
|
if(!dbfmgr.AddCol(NULL,"KG_TOT_REC",GdataTable::Tdouble,&dataDbf))
|
|
{
|
|
free(info);
|
|
return FALSE;
|
|
}
|
|
memset(info,0,nsec* OLV_SHP_SZ_CAMP_SZ);
|
|
|
|
//número de descargas
|
|
isec_novac=0;
|
|
for(i=0;i<olv_limp->nsec;i++)
|
|
{
|
|
if(olv_limp->sec[i].namb==0)
|
|
continue;
|
|
tt=(olv_limp->plan[i].ninsta-1)/2;
|
|
//para guardar en número
|
|
((int*)info)[isec_novac] = tt;
|
|
isec_novac++;
|
|
}
|
|
if(!dbfmgr.AddCol(NULL,"N_DESCARG",GdataTable::Tint,&dataDbf))
|
|
{
|
|
free(info);
|
|
return FALSE;
|
|
}
|
|
memset(info,0,nsec* OLV_SHP_SZ_CAMP_SZ);
|
|
|
|
//rellena la info de duración de los desplazamientos a descargar
|
|
isec_novac=0;
|
|
for(i=0;i<olv_limp->nsec;i++)
|
|
{
|
|
tt=0;
|
|
if(olv_limp->sec[i].namb==0)
|
|
continue;
|
|
for(p=1;p<olv_limp->plan[i].ninsta;p++)
|
|
{
|
|
if(olv_limp->plan[i].planif_insta[p].nelem==0)
|
|
continue;
|
|
if (olv_limp->plan[i].planif_insta[p].ninsta == OLV_IDA_PLANT || olv_limp->plan[i].planif_insta[p].ninsta == OLV_VUELTA_PLANT)
|
|
tt+=olv_limp->plan[i].planif_insta[p].elem[olv_limp->plan[i].planif_insta[p].nelem-1].coste;
|
|
}
|
|
dame_h_m_s(tt, &h, &m, &s);
|
|
sprintf_s(&info[isec_novac*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%02d:%02d:%02d h",h,m,s);
|
|
isec_novac++;
|
|
}
|
|
if(!dbfmgr.AddCol(NULL,"T_DESCARG",GdataTable::Tstring,&dataDbf,OLV_SHP_SZ_CAMP_CHAR))
|
|
{
|
|
free(info);
|
|
return FALSE;
|
|
}
|
|
memset(info,0,nsec* OLV_SHP_SZ_CAMP_SZ);
|
|
|
|
//añade col m descarg
|
|
isec_novac = 0;
|
|
for (i = 0; i < olv_limp->nsec; i++)
|
|
{
|
|
if (olv_limp->sec[i].namb == 0)
|
|
continue;
|
|
tt = 0;
|
|
for (p = 0; p < olv_limp->plan[i].ninsta; p++)
|
|
{
|
|
if (olv_limp->plan[i].planif_insta[p].ninsta == OLV_IDA_PLANT || olv_limp->plan[i].planif_insta[p].ninsta == OLV_VUELTA_PLANT)
|
|
tt += olv_limp->plan[i].planif_insta[p].m[OLV_DESP];
|
|
}
|
|
//para guardar en número
|
|
((double*)info)[isec_novac] = tt;
|
|
|
|
isec_novac++;
|
|
}
|
|
if (!dbfmgr.AddCol(NULL, "M_DESCARG", GdataTable::Tdouble, &dataDbf))
|
|
{
|
|
free(info);
|
|
return FALSE;
|
|
}
|
|
memset(info, 0, nsec * OLV_SHP_SZ_CAMP_SZ);
|
|
|
|
free(info);
|
|
|
|
if (!dbfmgr.grabaDbf(path_dbf, &db))
|
|
{
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
//*************************************************************************************
|
|
/**
|
|
* Añade las columnas de información a la ruta, tiempos, longitudes, y demás
|
|
*/
|
|
BOOL Colv_reco_thr::guarda_cols_insta(char *path_shp)
|
|
{
|
|
char *info;
|
|
char path_dbf[MAX_PATH];
|
|
double tt;
|
|
//int h;
|
|
int insta, ninsta_parc,ninsta,ninsta_novac;
|
|
ManagerDbfGdataTable dbfmgr;
|
|
GdataTable db;
|
|
|
|
/////////////////////////////////////
|
|
|
|
if(!Colv_limp_thr::guarda_cols_insta(path_shp))
|
|
return FALSE;
|
|
|
|
//cuenta el número de instalaciones
|
|
ninsta=0;
|
|
for(int i=0;i<olv_limp->nsec;i++)
|
|
{
|
|
for(insta=0;insta<olv_limp->plan[i].ninsta;insta++)
|
|
{
|
|
if(olv_limp->plan[i].planif_insta[insta].nelem!=0)
|
|
ninsta++;
|
|
}
|
|
}
|
|
|
|
//añade una columna a la ruta de tiempo de ruta
|
|
strcpy_s(path_dbf,MAX_PATH,path_shp);
|
|
//cambiaext(path_dbf,".shp",".dbf");
|
|
strcpy((Cdir_manager::extension_archivo(path_dbf)),"dbf");
|
|
|
|
info = (char *)malloc(ninsta* OLV_SHP_SZ_CAMP_SZ);
|
|
if(!info)
|
|
{
|
|
return FALSE;
|
|
}
|
|
memset(info,0,ninsta* OLV_SHP_SZ_CAMP_SZ);
|
|
AddColsDbf dataDbf(info);
|
|
if (!dbfmgr.LeeDbf(path_dbf, &db))
|
|
{
|
|
free(info);
|
|
return FALSE;
|
|
}
|
|
|
|
//kg descargados
|
|
ninsta_parc=0;
|
|
for(int i=0;i<olv_limp->nsec;i++)
|
|
{
|
|
ninsta_novac=0;
|
|
for(insta=0;insta<olv_limp->plan[i].ninsta;insta++)
|
|
{
|
|
if(olv_limp->plan[i].planif_insta[insta].nelem==0)
|
|
continue;
|
|
|
|
if(olv_limp->plan[i].planif_insta[insta].ninsta==OLV_IDA_PLANT)
|
|
tt=olv_limp->plan[i].planif_insta[insta].m[OLV_TTO];
|
|
else
|
|
tt=0;
|
|
|
|
((double*)info)[insta + ninsta_parc] = tt;
|
|
ninsta_novac++;
|
|
}
|
|
ninsta_parc+=ninsta_novac;
|
|
}
|
|
if(!dbfmgr.AddCol(NULL,"KG_DESCARG",GdataTable::Tdouble,&dataDbf))
|
|
{
|
|
free(info);
|
|
return FALSE;
|
|
}
|
|
memset(info,0,ninsta* OLV_SHP_SZ_CAMP_SZ);
|
|
|
|
//num de trayecto a descargar
|
|
ninsta_parc=0;
|
|
tt=0;
|
|
int tt2=0;
|
|
for(int i=0;i<olv_limp->nsec;i++)
|
|
{
|
|
ninsta_novac=0;
|
|
tt=1;
|
|
for(insta=0;insta<olv_limp->plan[i].ninsta;insta++)
|
|
{
|
|
if(olv_limp->plan[i].planif_insta[insta].nelem==0)
|
|
continue;
|
|
|
|
if(olv_limp->plan[i].planif_insta[insta].ninsta==OLV_VUELTA_PLANT)
|
|
tt++;
|
|
|
|
((int*)info)[insta + ninsta_parc] = tt;
|
|
ninsta_novac++;
|
|
}
|
|
ninsta_parc+=ninsta_novac;
|
|
}
|
|
if(!dbfmgr.AddCol(NULL,"VIAJE",GdataTable::Tint,&dataDbf))
|
|
{
|
|
free(info);
|
|
return FALSE;
|
|
}
|
|
memset(info,0,ninsta* OLV_SHP_SZ_CAMP_SZ);
|
|
|
|
free(info);
|
|
|
|
if (!dbfmgr.grabaDbf(path_dbf, &db))
|
|
{
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
//*************************************************************************************
|
|
/**
|
|
* Comprueba si en este elemento se va a descargar y en ese caso no se cuenta el desplazamiento hasta el siguiente
|
|
*/
|
|
BOOL Colv_reco_thr::comprueba_descarg(int iamb)
|
|
{
|
|
return (olv_reco->ptos_vaci[iamb]==(short)OLV_IDA_PLANT);
|
|
}
|
|
//*************************************************************************************
|
|
/**
|
|
* Añade las columnas de información a la ruta, tiempos, longitudes, y demás
|
|
*/
|
|
BOOL Colv_reco_thr::guarda_cols_ruta_tram(char *path_shp)
|
|
{
|
|
char *info;
|
|
char path_dbf[MAX_PATH];
|
|
double tt;
|
|
int i, it,ntram,nt,nt_parc;
|
|
Info_planif *pinsta;
|
|
ManagerDbfGdataTable dbfmgr;
|
|
GdataTable db;
|
|
|
|
if(!Colv_limp_thr::guarda_cols_ruta_tram(path_shp))
|
|
return FALSE;
|
|
|
|
//añade
|
|
|
|
//cuenta el número de sectores no vacíos
|
|
ntram=0;
|
|
for(i=0;i<olv_limp->nsec;i++)
|
|
{
|
|
if(olv_limp->sec[i].namb==0)
|
|
continue;
|
|
ntram+=(int)olv_limp->tramos[i].size();
|
|
}
|
|
|
|
//añade una columna a la ruta de tiempo de ruta
|
|
strcpy_s(path_dbf,MAX_PATH,path_shp);
|
|
//cambiaext(path_dbf,".shp",".dbf");
|
|
strcpy((Cdir_manager::extension_archivo(path_dbf)),"dbf");
|
|
|
|
info = (char *)malloc(ntram* OLV_SHP_SZ_CAMP_SZ);
|
|
if(!info)
|
|
{
|
|
return FALSE;
|
|
}
|
|
memset(info,0,ntram* OLV_SHP_SZ_CAMP_SZ);
|
|
AddColsDbf dataDbf(info);
|
|
if (!dbfmgr.LeeDbf(path_dbf, &db))
|
|
{
|
|
free(info);
|
|
return FALSE;
|
|
}
|
|
|
|
//M_RUTA
|
|
nt_parc=0;
|
|
for(i=0;i<olv_limp->nsec;i++)
|
|
{
|
|
if(olv_limp->sec[i].namb==0)
|
|
continue;
|
|
nt=(int)olv_limp->tramos[i].size();
|
|
|
|
for(it=0;it<nt;it++)
|
|
{
|
|
pinsta=olv_limp->plan[i].planif_insta;
|
|
tt=olv_limp->tramos[i][it].long_tr;
|
|
//como es solo ruta le quita las instalaciones
|
|
tt -= (pinsta[olv_limp->tramos[i][it].iins[0]].m[OLV_DESP] + pinsta[olv_limp->tramos[i][it].iins[1]].m[OLV_DESP]);
|
|
if (olv_limp->tramos[i][it].iins[1] > (olv_limp->tramos[i][it].iins[0] + 1)) //si la planta y la instala no son las mismas
|
|
tt -= pinsta[olv_limp->tramos[i][it].iins[1] - 1].m[OLV_DESP];
|
|
|
|
((double*)info)[nt_parc + it] = tt;
|
|
}
|
|
nt_parc+=nt;
|
|
}
|
|
if(!dbfmgr.AddCol(NULL,"M_RUTA",GdataTable::Tdouble,&dataDbf))
|
|
{
|
|
free(info);
|
|
return FALSE;
|
|
}
|
|
memset(info,0,ntram* OLV_SHP_SZ_CAMP_SZ);
|
|
|
|
//N_AMB
|
|
nt_parc=0;
|
|
for(i=0;i<olv_limp->nsec;i++)
|
|
{
|
|
if(olv_limp->sec[i].namb==0)
|
|
continue;
|
|
nt=(int)olv_limp->tramos[i].size();
|
|
for(it=0;it<nt;it++)
|
|
{
|
|
tt=olv_limp->tramos[i][it].namb;
|
|
((int*)info)[nt_parc + it] = tt;
|
|
}
|
|
nt_parc+=nt;
|
|
}
|
|
if(!dbfmgr.AddCol(NULL,"N_AMB",GdataTable::Tint,&dataDbf))
|
|
{
|
|
free(info);
|
|
return FALSE;
|
|
}
|
|
memset(info,0,ntram* OLV_SHP_SZ_CAMP_SZ);
|
|
|
|
//UDS_TTO
|
|
nt_parc=0;
|
|
for(i=0;i<olv_limp->nsec;i++)
|
|
{
|
|
if(olv_limp->sec[i].namb==0)
|
|
continue;
|
|
nt=(int)olv_limp->tramos[i].size();
|
|
for(it=0;it<nt;it++)
|
|
{
|
|
tt=olv_limp->tramos[i][it].ncont;
|
|
((int*)info)[nt_parc + it] = tt;
|
|
}
|
|
nt_parc+=nt;
|
|
}
|
|
if(!dbfmgr.AddCol(NULL,"UDS_TRAT",GdataTable::Tint,&dataDbf))
|
|
{
|
|
free(info);
|
|
return FALSE;
|
|
}
|
|
memset(info,0,ntram* OLV_SHP_SZ_CAMP_SZ);
|
|
|
|
//KG_RECO
|
|
nt_parc=0;
|
|
for(i=0;i<olv_limp->nsec;i++)
|
|
{
|
|
if(olv_limp->sec[i].namb==0)
|
|
continue;
|
|
nt=(int)olv_limp->tramos[i].size();
|
|
for(it=0;it<nt;it++)
|
|
{
|
|
tt=olv_limp->plan[i].planif_insta[2*it+1].m[OLV_TTO];
|
|
((double*)info)[nt_parc + it] = tt;
|
|
}
|
|
nt_parc+=nt;
|
|
}
|
|
if(!dbfmgr.AddCol(NULL,"KG_TOT_REC",GdataTable::Tdouble,&dataDbf))
|
|
{
|
|
free(info);
|
|
return FALSE;
|
|
}
|
|
memset(info,0,ntram* OLV_SHP_SZ_CAMP_SZ);
|
|
free(info);
|
|
|
|
if (!dbfmgr.grabaDbf(path_dbf, &db))
|
|
{
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
//*************************************************************************************
|
|
/**
|
|
* Rellena la info de los tramos
|
|
*/
|
|
void Colv_reco_thr::rellena_tramos()
|
|
{
|
|
Info_planif *pp;
|
|
Info_tramos *tramo;
|
|
int ie,it,nt;
|
|
|
|
Colv_limp_thr::rellena_tramos();
|
|
|
|
for(int is=0;is<olv_limp->nsec;is++)
|
|
{
|
|
pp=&olv_limp->plan[is];
|
|
nt=(int)olv_limp->tramos[is].size();
|
|
for(it=0;it<nt;it++)
|
|
{
|
|
tramo = &olv_limp->tramos[is][it];
|
|
tramo->ncont=0;
|
|
for(ie=tramo->ie[0]; ie<=tramo->ie[1];ie++)
|
|
{
|
|
if (pp->elem[ie].tp != OLV_PLAN_TIP_AMB)
|
|
continue;
|
|
tramo->ncont+=olv_limp->iaso[olv_limp->iaso[pp->elem[ie].refe].refe2].inf_r.uds;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//*************************************************************************************
|
|
/**
|
|
* Como los viajes a instalaciones están ordenados, y los tramos también
|
|
* le corresponde a cada tramo it el viaje it y el it+1, excepto al último, que le pueden
|
|
* corresponder 3 viajes si la instalación y la descarga no son en el mismo sitio
|
|
* Además, actualiza el tiempo de los tramos
|
|
*/
|
|
int Colv_reco_thr::rellena_insta_tramos()
|
|
{
|
|
int it, nt, nins,ii;
|
|
Info_planif *pinsta;
|
|
Info_tramos *tramo;
|
|
|
|
Colv_limp_thr::rellena_insta_tramos();
|
|
|
|
ii=0; //para saber si hace algún tramo o no
|
|
for(int is=0;is<olv_limp->nsec;is++)
|
|
{
|
|
nt=(int)olv_limp->tramos[is].size();
|
|
nins = olv_limp->plan[is].ninsta;
|
|
if(!nins)
|
|
continue;
|
|
if(olv_limp->plan[is].planif_insta[nins-1].nelem==0)
|
|
nins--; //es porque la descarga y planta son la misma
|
|
pinsta = olv_limp->plan[is].planif_insta;
|
|
for(it=0;it<nt;it++)
|
|
{
|
|
tramo = &olv_limp->tramos[is][it];
|
|
|
|
if (it == 0)//primer tramo, le suma el tiempo de llegar
|
|
tramo->t_ini -= olv_limp->t_sal;
|
|
tramo->t_fin += olv_reco->t_descarg;
|
|
if(it == (nt-1))
|
|
tramo->t_fin += olv_limp->t_sal;
|
|
|
|
tramo->t_total_tr = (float)(tramo->t_fin - tramo->t_ini);
|
|
}
|
|
ii++;
|
|
}
|
|
return ii;
|
|
}
|
|
//*************************************************************************************
|
|
#endif |