void CRUELredistribute() { list ll = LISTinit(), q; int j = 0, i = 0; while( i < 12 ) { if( STACKempty( cardStack[i] ) ) i++; else LISTaddEnd( ll, STACKpop( &cardStack[i] ) ); } i = 0; while( !LISTempty( ll ) ) { if( j >= 4 ) { j = 0; i++; } q = LISTgetNterm( ll, 3 - j ); if( q ) { STACKpush( &cardStack[i], LISTgetVal( q ) ); LISTremove(q); } j++; } LISTdestroy(ll); movedSinceDist = 0; lastSugest = ACTIONcreate(-1,-1,-1); }
trecho newTrecho(char tipo, int dist) { trecho t; AUTOMALLOC(t); t->tipo = tipo; t->distancia = dist; t->checkpoint_ranking = LISTinit(); return t; }
list readTrechos(FILE* in) { char tipo; int dist; list resp = LISTinit(); while(!feof(in)) { do tipo = fgetc(in); while(tipo == '\n'); fscanf(in, "%d", &dist); LISTaddEnd(resp, newTrecho(tipo, dist)); } return resp; }
void CRUELstart() { int i, j, k; list ll = LISTinit(), q; /* inicializa as 4 pilhas de naipes */ for( i = 0; i < 4; i++ ) { suitStack[i] = STACKinit( 13 ); LISTaddStart( ll, CARDcreate( i, 1 ) ); } /* aleatoriza a ordem das 4 pilhas de naipes */ for( i = 0; i < 4; i++ ) { k = rand() % (4 - i); q = LISTgetNterm( ll, k ); STACKpush( &suitStack[i], LISTgetVal(q) ); suitPosition[ CARDsuit(LISTgetVal(q)) ] = i; LISTremove(q); } /* inicializa as 12 pilhas de cartas */ for( i = 0; i < 12; i++ ) cardStack[i] = STACKinit( 26 ); /* coloca as 48 cartas na lista ligada */ for( j = 0; j < 4; j++ ) { for( i = 2; i <= 13; i++ ) { LISTaddStart( ll, CARDcreate( j, i ) ); } } /* preechemos as 12 pilhas de cartas linearmente, mas com cartas escolhidas aleatoriamente */ for( i = 0; i < 12; i++ ) { for( j = 0; j < 4; j++ ) { k = rand() % (48 - (4 * i + j) ); q = LISTgetNterm( ll, k ); STACKpush( &cardStack[i], LISTgetVal(q) ); LISTremove(q); } } LISTdestroy(ll); /* Selecionar uma carta aleatoria. Como funciona: Coloca-se todas as cartas numa LL. Sempre que precisar de uma carta aleatoria, fazer k = rand() % TOTAL_DE_CARTAS_NA_LL e pegar a k-esima carta da LL, removendo-a da lista. */ cardLeft = 48; movedSinceDist = 0; lastSugest = ACTIONcreate(-1,-1,-1); }
/*Inicializa o gerenciador de entidades.*/ void inicializaEntidades() { nextID = 1; entityList = LISTinit(); garbageList = LISTinit(); }
/* O grande main incomming. Se vira ae champz. */ int main(int argc, char **argv) { int i; int ciclo; FILE* in; int num_ciclistas; ciclista* ciclistas; pthread_t* ciclistas_threads; pthread_attr_t ciclista_attr; srand((unsigned int) time(NULL)); if(argc != 2) { fprintf(stderr, "Uso: %s arquivo\n", argv[0]); return 1; } in = fopen(argv[1], "r"); if(in == NULL) { fprintf(stderr, "Erro: Arquivo '%s' não pode ser lido.\n", argv[1]); return 2; } fscanf(in, "%d", &num_ciclistas); /* m */ fscanf(in, "%d", &largura_estrada); /* n */ do modo_simula = fgetc(in); while(modo_simula == '\n'); fscanf(in, "%d", &tamanho_estrada); /* d */ trechos = readTrechos(in); fclose(in); #ifdef DEBUG printf("num_ciclistas (m) = %d\n", num_ciclistas); printf("largura_estrada (n) = %d\n", largura_estrada); printf("modo_simula = %c\n", modo_simula); printf("tamanho_estrada (d) = %d\n", tamanho_estrada); LISTdump(trechos, dumpTrecho); assert(largura_estrada >= 2); assert(modo_simula == 'U' || modo_simula == 'A'); #endif AUTOMALLOCV(ciclistas, num_ciclistas); AUTOMALLOCV(ciclistas_threads, num_ciclistas); AUTOMALLOCV(estrada, tamanho_estrada); for(i = 0; i < tamanho_estrada; ++i) { /* Inicializa o vetor estrada. */ estrada[i].ciclistas = LISTinit(); pthread_mutex_init(&estrada[i].mutex, NULL); } ciclistas_terminaram = LISTinit(); pthread_mutex_init(&terminar_mutex, NULL); modo_simula = modo_simula == 'A'; /* 0 se uniforme, 1 se diferente */ for(i = 0; i < num_ciclistas; ++i) { ciclistas[i] = newCiclista(i); AUTOMALLOCV(ciclistas[i]->tempo, num_ciclistas); } for(i = 0; i < num_ciclistas; ++i) printf("%s [%.2lf; %.2lf; %.2lf]\n", ciclistas[i]->nome, ciclistas[i]->vel_descida, ciclistas[i]->vel_plano, ciclistas[i]->vel_subida); pthread_attr_init(&ciclista_attr); pthread_attr_setdetachstate(&ciclista_attr, PTHREAD_CREATE_DETACHED); for(i = 0; i < num_ciclistas; ++i) { int rc = pthread_create(&ciclistas_threads[i], &ciclista_attr, CiclistaThread, (void *) ciclistas[i]); assert(0 == rc); } ciclo = 0; /* Enquanto alguém não terminou a corrida. */ while(LISTsize(ciclistas_terminaram) < num_ciclistas) { /* Manda todo mundo correr. */ for(i = 0; i < num_ciclistas; ++i) sem_post(&ciclistas[i]->continua_ciclo); /* Espera todo mundo que ainda não terminou a corrida acabar o ciclo. */ for(i = 0; i < num_ciclistas; ++i) if(ciclistas[i]->km < tamanho_estrada) sem_wait(&ciclistas[i]->terminou_ciclo); /* Acabamos de realizar um ciclo. */ ++ciclo; /* Passou 1 minuto? */ if(ciclo % (60 / CICLO_TIME) == 0) { printf("Minuto %d:\n", ciclo / (60 / CICLO_TIME)); for(i = 0; i < tamanho_estrada; ++i) { printf("\tKM %.3d: ", i); LISTdump(estrada[i].ciclistas, dumpCiclista); puts(""); } puts(""); } } /* Calcular pontuação dos ciclistas */ { /* Itera por todos os trechos, e distribui pontuação dos checkpoints. */ litem p; int i; trecho t; litem x; int pos; for(p = trechos->first; p; p = p->next) { t = (trecho) p->val; /* Pega o primeiro, segundo e terceiro. For conveniente que trata caso de menos de 3 ciclistas. */ for(pos = 0, x = t->checkpoint_ranking->first; pos < 6 && x; ++pos, x = x->next) { if(t->tipo == 'P') ((ciclista) x->val)->ponto_verde += notas_posicao[pos]; else if(t->tipo == 'S') ((ciclista) x->val)->ponto_branco_vermelho += notas_posicao[pos]; } } i = 1; for(p = trechos->first; p; p = p->next) { printf("Ordem de chegada no trecho %d da corrida:\n", i); t = (trecho) p->val; for(x = t->checkpoint_ranking->first; x!=NULL; x = x->next) { ciclista c1 = ((ciclista) x->val); printf("\t%s - Tempo: %d:%.2d:%.2d\n", c1->nome, c1->tempo[i-1] / 3600, (c1->tempo[i-1] % 3600) / 60, c1->tempo[i-1] % 60 ); } ++i; puts(""); } } puts(""); quickSortCiclistaAmarelo(ciclistas, num_ciclistas); puts("Ranking da Camisa Amarela:"); for(i = 0; i < num_ciclistas; ++i) printf("Pos %.2d: %s - Tempo: %d:%.2d:%.2d\n", i, ciclistas[i]->nome, ciclistas[i]->tempo_gasto_total / 3600, (ciclistas[i]->tempo_gasto_total % 3600) / 60, ciclistas[i]->tempo_gasto_total % 60); puts(""); quickSortCiclistaVerde(ciclistas, num_ciclistas); puts("Ranking da Camisa Verde:"); for(i = 0; i < num_ciclistas; ++i) printf("Pos %.2d: %s - Pontos: %d\n", i, ciclistas[i]->nome, ciclistas[i]->ponto_verde); puts(""); quickSortCiclistaBrancoVermelho(ciclistas, num_ciclistas); puts("Ranking da Camisa Branco com Bolas Vermelhas:"); for(i = 0; i < num_ciclistas; ++i) printf("Pos %.2d: %s - Pontos: %d\n", i, ciclistas[i]->nome, ciclistas[i]->ponto_verde); LISTdestroy(ciclistas_terminaram); pthread_mutex_destroy(&terminar_mutex); /* for trecho in trechos free */ LISTcallback(trechos, destroyTrecho); LISTdestroy(trechos); for(i = 0; i < num_ciclistas; ++i) { free(ciclistas[i]->tempo); destroyCiclista(ciclistas[i]); } free(ciclistas); pthread_attr_destroy(&ciclista_attr); free(ciclistas_threads); for(i = 0; i < tamanho_estrada; ++i) { LISTdestroy(estrada[i].ciclistas); pthread_mutex_destroy(&estrada[i].mutex); } free(estrada); return 0; }