From 6d4ce034a6ecb4e09c32628d187eec450fbae01f Mon Sep 17 00:00:00 2001 From: Pedro Folloni Pesserl <fpesserl7@gmail.com> Date: Thu, 2 Feb 2023 02:14:45 -0300 Subject: [PATCH] finish simulation --- t1/libconjunto.c | 7 +- t1/makefile | 2 +- t1/mundo.c | 272 +++++++++++++++++++++++++++++++---------------- 3 files changed, 187 insertions(+), 94 deletions(-) diff --git a/t1/libconjunto.c b/t1/libconjunto.c index 7e16126..daf98e3 100644 --- a/t1/libconjunto.c +++ b/t1/libconjunto.c @@ -207,9 +207,10 @@ void imprime_cjt(conjunto_t *c) { } int i; - for (i = 0; i < cardinalidade_cjt(c)-1; i++) - printf("%d ", c->v[i]); - printf("%d\n", c->v[cardinalidade_cjt(c)-1]); + printf("%d", c->v[0]); + for (i = 1; i < cardinalidade_cjt(c); i++) + printf(" %d", c->v[i]); + printf("\n"); } void inicia_iterador_cjt(conjunto_t *c) { diff --git a/t1/makefile b/t1/makefile index f0015ca..5cbc273 100644 --- a/t1/makefile +++ b/t1/makefile @@ -1,6 +1,6 @@ # Makefile de exemplo (Manual do GNU Make) -CFLAGS = -Wall -std=c90 -g # flags de compilacao +CFLAGS = -Wall -std=c90 -g# flags de compilacao LDFLAGS = -lm CC = gcc diff --git a/t1/mundo.c b/t1/mundo.c index 9694d5d..f089556 100644 --- a/t1/mundo.c +++ b/t1/mundo.c @@ -6,10 +6,10 @@ #include "libfila.h" #include "liblef.h" -#define MEM_ERROR_EXIT \ - do { \ - printf("Erro: não foi possÃvel alocar memória."); \ - exit(1); \ +#define MEM_ERROR_EXIT \ + do { \ + fprintf(stderr, "Erro: não foi possÃvel alocar memória."); \ + exit(1); \ } while(0) #define CHEGADA 0 @@ -44,6 +44,7 @@ typedef struct { int n_locais; heroi_t *herois; local_t *locais; + conjunto_t **missoes; } mundo_t; /* retorna um inteiro aleatório entre a e b (inclusive) */ @@ -151,8 +152,14 @@ mundo_t *cria_mundo(lef_t *lista_de_eventos) { adiciona_ordem_lef(lista_de_eventos, &evento_chegada_heroi); } - /* para cada missao, cria evento e insere na lef */ + /* cria vetor de missões */ + if ( !(m->missoes = malloc(m->n_missoes * sizeof(conjunto_t*))) ) { + MEM_ERROR_EXIT; + } + /* preenche vetor de missões, inicialmente com NULL; + * para cada missao, cria evento e insere na lef */ for (i = 0; i < m->n_missoes; i++) { + m->missoes[i] = NULL; evento_t evento_missao = { aleat(0, m->fim_do_mundo), MISSAO, i, 0 }; adiciona_ordem_lef(lista_de_eventos, &evento_missao); } @@ -176,103 +183,188 @@ int velocidade_heroi(heroi_t heroi) { return 100 - max(0, heroi.idade - 40); } +conjunto_t *escolhe_menor_equipe(conjunto_t *missao, int id_missao, mundo_t *m, local_t *local_encontrado) { + conjunto_t *menor; + if ( !(menor = cria_cjt(cardinalidade_cjt(m->cj_habilidades))) ) + MEM_ERROR_EXIT; + conjunto_t *uniao_old; + conjunto_t *uniao; + int i, j, id_heroi_atual; + + for (i = 0; i < m->n_locais; i++) { + if (vazio_cjt(m->locais[i].publico)) continue; + + /* copia o conjunto de habilidades do primeiro herói do local atual */ + inicia_iterador_cjt(m->locais[i].publico); + incrementa_iterador_cjt(m->locais[i].publico, &id_heroi_atual); + if ( !(uniao = copia_cjt(m->herois[id_heroi_atual].habilidades_do_heroi)) ) + MEM_ERROR_EXIT; + + /* faz a união entre os conjuntos de habilidades de todos os heróis do local atual */ + for (j = 1; j < cardinalidade_cjt(m->locais[i].publico); j++) { + uniao_old = uniao; + incrementa_iterador_cjt(m->locais[i].publico, &id_heroi_atual); + uniao = uniao_cjt(uniao, m->herois[id_heroi_atual].habilidades_do_heroi); + uniao_old = destroi_cjt(uniao_old); + } + + printf("%6d:MISSAO %4d HAB_EQL %d:", m->tempo_atual, id_missao, m->locais[i].id); + imprime_cjt(uniao); + + /* compara se o conjunto construÃdo contém a missao e é menor que o achado anteriormente */ + if (contido_cjt(missao, uniao)) { + if (vazio_cjt(menor) || cardinalidade_cjt(uniao) < cardinalidade_cjt(menor)) { + menor = destroi_cjt(menor); + if ( !(menor = copia_cjt(uniao)) ) + MEM_ERROR_EXIT; + *local_encontrado = m->locais[i]; + } + } + uniao = destroi_cjt(uniao); + } + + return menor; +} + +void trata_evento_chegada(int id_heroi, int id_local, mundo_t *m, lef_t *lista_de_eventos) { + printf("%6d:CHEGA HEROI %2d Local %d (%2d/%2d), ", + m->tempo_atual, + id_heroi, + id_local, + cardinalidade_cjt(m->locais[id_local].publico), + m->locais[id_local].lotacao_max); + + if (local_lotado(id_local, m)) { + if (heroi_tem_paciencia(id_heroi, id_local, m)) { + insere_fila(m->locais[id_local].fila, id_heroi); + printf("FILA %d\n", tamanho_fila(m->locais[id_local].fila)); + return; + } + printf("DESISTE\n"); + evento_t saida = { m->tempo_atual, SAIDA, id_heroi, id_local }; + adiciona_ordem_lef(lista_de_eventos, &saida); + return; + } + + printf("ENTRA\n"); + insere_cjt(m->locais[id_local].publico, id_heroi); + int t_permanencia_local = max(1, m->herois[id_heroi].paciencia/10 + aleat(-2,6)); + evento_t saida = { m->tempo_atual + t_permanencia_local, SAIDA, id_heroi, id_local }; + adiciona_ordem_lef(lista_de_eventos, &saida); + return; +} + int main() { - srand(time(0)); + /* srand(time(0)); */ + srand(0); lef_t *lista_de_eventos; if ( !(lista_de_eventos = cria_lef()) ) MEM_ERROR_EXIT; - mundo_t *mundo; - mundo = cria_mundo(lista_de_eventos); - printf("inicializou o mundo!\n"); - printf("tamanho do mundo: %d\n", mundo->tamanho_mundo); - printf("conjunto de habilidades do mundo:\n"); - imprime_cjt(mundo->cj_habilidades); + mundo_t *mundo = cria_mundo(lista_de_eventos); - /* int i = 0; */ - /* nodo_lef_t *exemplo = lista_de_eventos->Primeiro; */ - /* printf("eventos alocados na lef:\n"); */ - /* while (exemplo) { */ - /* printf("tempo do evento %d: %d\n", i, exemplo->evento->tempo); */ - /* printf(" tipo do evento %d: ", i); */ - /* switch (exemplo->evento->tipo) { */ - /* case CHEGADA: */ - /* printf("CHEGADA\n"); */ - /* break; */ - /* case SAIDA: */ - /* printf("SAIDA\n"); */ - /* break; */ - /* case MISSAO: */ - /* printf("MISSAO\n"); */ - /* break; */ - /* case FIM: */ - /* printf("FIM\n"); */ - /* break; */ - /* default: */ - /* printf("deu alguma coisa muito louca aqui\n"); */ - /* break; */ - /* } */ - /* i++; */ - /* exemplo = exemplo->prox; */ - /* } */ - - /* ciclo da simulação */ evento_t *evento_atual; - evento_atual = obtem_primeiro_lef(lista_de_eventos); - mundo->tempo_atual = evento_atual->tempo; - /* trata o evento e atualiza estado do sistema */ - - /* TODO: criar função wrapper para tratar os eventos e poder criar variaveis temporarias */ - - switch (evento_atual->tipo) { - case CHEGADA: - evento_t saida; - int id_heroi = evento_atual->dado1; - int id_local = evento_atual->dado2; - if (local_lotado(id_local, mundo)) { - if (heroi_tem_paciencia(id_heroi, id_local, mundo)) { - insere_fila(mundo->locais[id_local].fila, id_heroi); + /* ciclo da simulação */ + while ( lista_de_eventos && (evento_atual = obtem_primeiro_lef(lista_de_eventos)) ) { + mundo->tempo_atual = evento_atual->tempo; + + /* trata o evento e atualiza estado do sistema */ + int id_heroi, id_local, id_missao, i; + switch (evento_atual->tipo) { + case CHEGADA: + trata_evento_chegada(evento_atual->dado1, evento_atual->dado2, mundo, lista_de_eventos); + break; + + case SAIDA: ; + id_heroi = evento_atual->dado1; + id_local = evento_atual->dado2; + printf("%6d:SAIDA HEROI %2d Local %d (%2d/%2d)", + mundo->tempo_atual, + id_heroi, + id_local, + cardinalidade_cjt(mundo->locais[id_local].publico), + mundo->locais[id_local].lotacao_max); + + if (pertence_cjt(mundo->locais[id_local].publico, id_heroi)) { + retira_cjt(mundo->locais[id_local].publico, id_heroi); + if (!vazia_fila(mundo->locais[id_local].fila)) { + int id_heroi_fila; + retira_fila(mundo->locais[id_local].fila, &id_heroi_fila); + printf(", REMOVE FILA HEROI %d", id_heroi_fila); + evento_t chegada_heroi_fila = { mundo->tempo_atual, CHEGADA, id_heroi_fila, id_local }; + adiciona_inicio_lef(lista_de_eventos, &chegada_heroi_fila); + } + } + printf("\n"); + + int id_local_destino = aleat(0, mundo->n_locais-1); + int t_deslocamento = distancia(mundo->locais[id_local], mundo->locais[id_local_destino]) / velocidade_heroi(mundo->herois[id_heroi]); + evento_t chegada_heroi = { mundo->tempo_atual + t_deslocamento/15, CHEGADA, id_heroi, id_local_destino }; + adiciona_ordem_lef(lista_de_eventos, &chegada_heroi); + break; + + case MISSAO: ; + id_missao = evento_atual->dado1; + local_t local_encontrado; + conjunto_t *missao; + if (mundo->missoes[id_missao] == NULL) + if ( !(mundo->missoes[id_missao] = cria_subcjt_cjt(mundo->cj_habilidades, aleat(3, 6))) ) + MEM_ERROR_EXIT; + + missao = mundo->missoes[id_missao]; + printf("%6d:MISSAO %4d HAB_REQ ", mundo->tempo_atual, id_missao); + imprime_cjt(missao); + + conjunto_t *equipe_escolhida = escolhe_menor_equipe(missao, id_missao, mundo, &local_encontrado); + + printf("%6d:MISSAO %4d ", mundo->tempo_atual, id_missao); + if (vazio_cjt(equipe_escolhida)) { + printf("IMPOSSIVEL\n"); + evento_t nova_tentativa = { aleat(mundo->tempo_atual, mundo->fim_do_mundo), MISSAO, id_missao, 0 }; + adiciona_ordem_lef(lista_de_eventos, &nova_tentativa); } else { - saida = { mundo->tempo_atual, SAIDA, id_heroi, id_local }; - adiciona_ordem_lef(lista_de_eventos, &saida); + printf("HER_EQS %d:", local_encontrado.id); + imprime_cjt(local_encontrado.publico); + + int id_heroi_encontrado; + inicia_iterador_cjt(local_encontrado.publico); + for (i = 0; i < cardinalidade_cjt(local_encontrado.publico); i++) { + incrementa_iterador_cjt(local_encontrado.publico, &id_heroi_encontrado); + (mundo->herois[id_heroi_encontrado].exp)++; + } + missao = destroi_cjt(missao); + mundo->missoes[id_missao] = NULL; } - } else { - insere_cjt(mundo->locais[id_local].publico, id_heroi); - int t_permanencia_local = max(1, mundo->herois[id_heroi].paciencia/10 + aleat(-2,6)); - saida = { mundo->tempo_atual + t_permanencia_local, SAIDA, id_heroi, id_local }; - adiciona_ordem_lef(lista_de_eventos, &saida); - } - break; - - case SAIDA: - evento_t chegada_heroi, chegada_heroi_fila; - int id_heroi = evento_atual->dado1; - int id_local = evento_atual->dado2; - if (pertence_cjt(mundo->locais[id_local].publico, id_heroi)) { - retira_cjt (mundo->locais[id_local].publico, id_heroi); - if (!vazia_fila(mundo->locais[id_local].fila)) { - int id_heroi_fila; - retira_fila(mundo->locais[id_local].fila, &id_heroi_fila); - chegada_heroi_fila = { mundo->tempo_atual, CHEGADA, id_heroi_fila, id_local }; - adiciona_inicio_lef(lista_de_eventos, &chegada_heroi_fila); + equipe_escolhida = destroi_cjt(equipe_escolhida); + break; + + case FIM: + printf("%6d:FIM\n", mundo->tempo_atual); + for (i = 0; i < mundo->n_herois; i++) { + printf("HEROI %2d EXPERIENCIA %2d\n", mundo->herois[i].id, mundo->herois[i].exp); + mundo->herois[i].habilidades_do_heroi = destroi_cjt(mundo->herois[i].habilidades_do_heroi); } - } - int id_local_destino = aleat(0, mundo->n_locais-1); - int t_deslocamento = distancia(mundo->locais[id_local], mundo->locais[id_local_destino]) / velocidade_heroi(mundo->herois[id_heroi]); - chegada_heroi = { mundo->tempo_atual + t_deslocamento/15, CHEGADA, id_heroi, id_local_destino }; - adiciona_ordem_lef(lista_de_eventos, &chegada_heroi); - break; - - case MISSAO: - break; - case FIM: - - lista_de_eventos = destroi_lef(lista_de_eventos); - break; - } - /* agenda os novos eventos na lista_de_eventos; */ + for (i = 0; i < mundo->n_locais; i++) { + mundo->locais[i].publico = destroi_cjt(mundo->locais[i].publico); + mundo->locais[i].fila = destroi_fila(mundo->locais[i].fila); + } + + free(mundo->herois); + free(mundo->locais); + for (i = 0; i < mundo->n_missoes; i++) + if (mundo->missoes[i] != NULL) + mundo->missoes[i] = destroi_cjt(mundo->missoes[i]); + free(mundo->missoes); + mundo->cj_habilidades = destroi_cjt(mundo->cj_habilidades); + free(mundo); + lista_de_eventos = destroi_lef(lista_de_eventos); + break; + } + + free(evento_atual); + } return 0; } -- GitLab