#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 #include #include //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;itramos) 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 *clase,Param_olv_limp_thr *e) { BOOL bien=TRUE; BOOL hecho=FALSE; Colv_reco_thr *this_i=static_cast(clase); switch (evento) { case OLV_LIMP_EV_RELL_DAT: { hecho=TRUE; bien=this_i->rellena_datos(); if(bien && (this_i->olv->modo_ejecpirate)//sigue { if(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;in_subthr;i++) { if(this_i->subthrs[i]->prog_subthr<0) break; nno+=(int)this_i->subthrs[i]->prog_subthr; } if(in_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_ejecpirate)//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(ian_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=ithr*na_desp; 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;naiaso[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;knod_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;ian_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;katipo_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(iniiamb[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; } 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_actiamb[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(iniiamb[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 llegada } 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_descarg;//suma el coste de descargar //d+=olv_reco->t_sal;//suma el coste de la llegada /////////////////////////// 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; iiiamb[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_actiamb[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;inamb;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_defn_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;iprog_subthr = 0; } for(int i=0;i &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->nsecnsec) { //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=ithr*is_desp; 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;issec[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 olv_limp->arch_dj.get_b(s->iamb[secu_ambi[0].iamb],secu_ambi[0].entrada, buf_aux); 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); 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 double cc=0, cc1=0; ss=1; int iam_ped; int iam_ent; for (i=1; inamb; 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); 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); 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; } } /////////////////////////////////////////// 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+olv_limp->sec[is].t_despl[0]+olv_limp->sec[is].t_despl[1]); } ////////////////////////////////// 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;inelem;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(ipcpts_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;ipts_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;inamb;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;iplan[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, aprovecha y lo guarda aquí pp->t[OLV_TTO]=tt; ////////////////// ////////////////// //Calcula los kg acumulados kgac=0; for(i=0;iplan[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; ////////////////// *t0+=cost_despl+olv_reco->t_descarg; tt+=cost_despl+olv_reco->t_descarg; 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; } 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; //cuenta el número de sectores no vacíos nsec=0; for(i=0;insec;i++) { if(olv_limp->sec[i].namb!=0) nsec++; } ///////////////////////////////////// if(!Colv_limp_thr::guarda_cols_ruta(path_shp)) return FALSE; //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(nsec* OLV_SHP_SZ_CAMP_SZ); if(!info) { return FALSE; } memset(info,0,nsec* OLV_SHP_SZ_CAMP_SZ); AddColsDbf dataDbf(info); /*//sustituye la info de hora final isec_novac=0; for(i=0;insec;i++) { if(olv_limp->sec[i].namb==0) { continue; } tt=olv_limp->t_ini+ olv_limp->sec[i].cost_ac + olv_limp->t_desc; 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(path_dbf,"H_FIN",GdataTable::Tstring,&dataDbf,OLV_SHP_SZ_CAMP_CHAR)) { free(info); return FALSE; } memset(info,0,nsec* OLV_SHP_SZ_CAMP_SZ);*/ //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;pplan[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(path_dbf, "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;isec[i].namb==0) continue; tt=0; for(j=0;jsec[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(path_dbf,"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;insec;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(path_dbf,"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;insec;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(path_dbf,"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;insec;i++) { tt=0; if(olv_limp->sec[i].namb==0) continue; for(p=1;pplan[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(path_dbf,"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(path_dbf, "M_DESCARG", GdataTable::Tdouble, &dataDbf)) { free(info); return FALSE; } memset(info, 0, nsec * OLV_SHP_SZ_CAMP_SZ); free(info); 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; ///////////////////////////////////// if(!Colv_limp_thr::guarda_cols_insta(path_shp)) return FALSE; //cuenta el número de instalaciones ninsta=0; for(int i=0;insec;i++) { for(insta=0;instaplan[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); //kg descargados ninsta_parc=0; for(int i=0;insec;i++) { ninsta_novac=0; for(insta=0;instaplan[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(path_dbf,"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;insec;i++) { ninsta_novac=0; tt=1; for(insta=0;instaplan[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(path_dbf,"VIAJE",GdataTable::Tint,&dataDbf)) { free(info); return FALSE; } memset(info,0,ninsta* OLV_SHP_SZ_CAMP_SZ); free(info); 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; ManagerDbfGdataTable dbfmgr; 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;insec;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); //M_DESP nt_parc=0; for(i=0;insec;i++) { if(olv_limp->sec[i].namb==0) continue; nt=(int)olv_limp->tramos[i].size(); for(it=0;ittramos[i][it].long_tr; ((double*)info)[nt_parc + it] = tt; } nt_parc+=nt; } if(!dbfmgr.AddCol(path_dbf,"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;insec;i++) { if(olv_limp->sec[i].namb==0) continue; nt=(int)olv_limp->tramos[i].size(); for(it=0;ittramos[i][it].namb; ((int*)info)[nt_parc + it] = tt; } nt_parc+=nt; } if(!dbfmgr.AddCol(path_dbf,"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;insec;i++) { if(olv_limp->sec[i].namb==0) continue; nt=(int)olv_limp->tramos[i].size(); for(it=0;ittramos[i][it].ncont; ((int*)info)[nt_parc + it] = tt; } nt_parc+=nt; } if(!dbfmgr.AddCol(path_dbf,"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;insec;i++) { if(olv_limp->sec[i].namb==0) continue; nt=(int)olv_limp->tramos[i].size(); for(it=0;itplan[i].planif_insta[2*it+1].m[OLV_TTO]; ((double*)info)[nt_parc + it] = tt; } nt_parc+=nt; } if(!dbfmgr.AddCol(path_dbf,"KG_TOT_REC",GdataTable::Tdouble,&dataDbf)) { free(info); return FALSE; } memset(info,0,ntram* OLV_SHP_SZ_CAMP_SZ); return TRUE; } //************************************************************************************* /** * Rellena la info de los tramos */ void Colv_reco_thr::rellena_tramos() { Info_planif *pp; Info_tramos *tramo; int ie,it,nt; for(int is=0;isnsec;is++) { pp=&olv_limp->plan[is]; nt=(int)olv_limp->tramos[is].size(); for(it=0;ittramos[is][it]; tramo->namb=0; tramo->ncont=0; for(ie=tramo->ie[0]; ie<=tramo->ie[1];ie++) { tramo->long_tr+=(float) pp->elem[ie].ltot; if(pp->elem[ie].tp!=OLV_PLAN_TIP_AMB) continue; tramo->namb++; tramo->ncont+=olv_limp->iaso[olv_limp->iaso[pp->elem[ie].refe].refe2].inf_r.uds; } tramo->t_tto_tr = (float)(tramo->ncont*olv_reco->t_tto); if(it==0) tramo->t_ini = (float)(olv_limp->t_ini+pp->planif_insta[0].elem[pp->planif_insta[0].nelem-1].coste); else tramo->t_ini = (float)(pp->planif_insta[2*it].t[OLV_TTO]+pp->planif_insta[2*it].elem[pp->planif_insta[2*it].nelem-1].coste); tramo->t_fin = (float)pp->planif_insta[2*it+1].t[OLV_TTO]; tramo->t_total_tr = (float) (tramo->t_fin-tramo->t_ini); } } } //************************************************************************************* /** * 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; ii=0; //para saber si hace algún tramo o no for(int is=0;isnsec;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;ittramos[is][it]; tramo->iins[0]=2*it; tramo->iins[1]=2*it+1; /////////////////////////////////////// //Actualiza los tiempos del tramo sumando los tiempos del viaje a inst tramo->t_ini -= (float)pinsta[tramo->iins[0]].elem[pinsta[tramo->iins[0]].nelem-1].coste; tramo->t_fin += (float)pinsta[tramo->iins[1]].elem[pinsta[tramo->iins[1]].nelem-1].coste; tramo->t_total_tr=(float) (tramo->t_fin-tramo->t_ini); } //para el último tramo tramo = &olv_limp->tramos[is][it]; tramo->iins[0]=2*it; tramo->iins[1]=nins-1; tramo->t_ini -= (float)pinsta[tramo->iins[0]].elem[pinsta[tramo->iins[0]].nelem-1].coste; //si la instalación no es la misma que la descarga, le suma el tiempo de ir a descargar y el de ir a la instalación BOOL notdesc=TRUE; for(int i=tramo->iins[0]+1;i<=tramo->iins[1];i++) { if(notdesc) { tramo->t_fin += olv_reco->t_descarg; notdesc=FALSE; } tramo->t_fin += (float)pinsta[i].elem[pinsta[i].nelem-1].coste; } tramo->t_total_tr=(float) (tramo->t_fin-tramo->t_ini); ii++; } return ii; } //************************************************************************************* #endif