// // Created by Alban on 26/11/2024. // #include "convertion_JSON_MMD.h" #include "Affichage.h" void Saisie(toutAllegro * toutAllegro1, ALLEGRO_BITMAP * background, char *result, char * phrase) { char input[MAX_INPUT_LENGTH + 1] = {0}; // Tampon pour la saisie int cursor_pos = 0; bool input_complete = false; al_draw_bitmap(background, 0, 0, 0); char truncated_phrase[61] = {0}; // 60 caractères + '\0' char *t = NULL; if (strlen(phrase) > 60) { strncpy(truncated_phrase, phrase, 60); truncated_phrase[61] = '\0'; t = &phrase[60]; } else { strcpy(truncated_phrase, phrase); t = ""; } al_draw_text(toutAllegro1->font_small, COULEUR_PRIMAIRE, SCREEN_WIDTH / 2, 275, ALLEGRO_ALIGN_CENTRE, truncated_phrase); al_draw_text(toutAllegro1->font_small, COULEUR_PRIMAIRE, SCREEN_WIDTH / 2, 300, ALLEGRO_ALIGN_CENTRE, t); al_flip_display(); char c; while (!input_complete) { ALLEGRO_EVENT event; al_wait_for_event(toutAllegro1->eventQueue, &event); switch (event.type) { case ALLEGRO_EVENT_DISPLAY_CLOSE : exit(0); break; case ALLEGRO_EVENT_KEY_CHAR: c = event.keyboard.unichar; if (c >= 32 && c <= 126 && cursor_pos < MAX_INPUT_LENGTH) { // Saisie des caractères imprimables input[cursor_pos++] = c; input[cursor_pos] = '\0'; } else if (c == '\b' && cursor_pos > 0) { // Gestion du backspace input[--cursor_pos] = '\0'; } else if (c == '\r') { // Validation de la saisie avec Entrée if (strlen(input) > 0) { input_complete = true; } break; } // Affichage al_draw_bitmap(background, 0, 0, 0); al_draw_text(toutAllegro1->font_small, COULEUR_PRIMAIRE, SCREEN_WIDTH / 2, 275, ALLEGRO_ALIGN_CENTRE, truncated_phrase); al_draw_text(toutAllegro1->font_small, COULEUR_PRIMAIRE, SCREEN_WIDTH / 2, 300, ALLEGRO_ALIGN_CENTRE, t); al_draw_text(toutAllegro1->font_mid, COULEUR_VERT, SCREEN_WIDTH / 2, 500, ALLEGRO_ALIGN_CENTRE, input); al_flip_display(); } } // Copier la saisie dans le tampon de résultat strncpy(result, input, MAX_INPUT_LENGTH); } void AttendreBouton(toutAllegro * toutAllegro1, ALLEGRO_BITMAP * background, const char *texte, float boutonX, float boutonY, float boutonW, float boutonH) { bool clicked = false; float sourisX; float sourisY; while (!clicked) { ALLEGRO_EVENT event; al_wait_for_event(toutAllegro1->eventQueue, &event); switch (event.type) { case ALLEGRO_EVENT_DISPLAY_CLOSE: exit(0); break; case ALLEGRO_EVENT_MOUSE_BUTTON_DOWN: sourisX = event.mouse.x; sourisY = event.mouse.y; if (sourisX >= boutonX && sourisX <= boutonX + boutonW && sourisY >= boutonY && sourisY <= boutonY + boutonH) { clicked = true; } break; case ALLEGRO_EVENT_KEY_DOWN: if (event.keyboard.keycode == ALLEGRO_KEY_ENTER){ clicked = true; } break; } // Réaffichage avec le texte saisi al_draw_bitmap(background, 0, 0, 0); al_draw_text(toutAllegro1->font_mid, COULEUR_VERT, SCREEN_WIDTH / 2, 500, ALLEGRO_ALIGN_CENTRE, texte); al_flip_display(); } } // Fonction pour lire un fichier JSON char* lireFichier(const char* nomFichier) { FILE* fichier = fopen(nomFichier, "r"); if (!fichier) { perror("Erreur lors de l'ouverture du fichier"); return NULL; } fseek(fichier, 0, SEEK_END); long taille = ftell(fichier); rewind(fichier); char* contenu = (char*)malloc(taille + 1); if (!contenu) { perror("Erreur d'allocation memoire"); fclose(fichier); return NULL; } fread(contenu, 1, taille, fichier); contenu[taille] = '\0'; fclose(fichier); return contenu; } int has_json_extension(const char *filename) { const char *dot = strrchr(filename, '.'); return dot && strcmp(dot, ".json") == 0; } // Fonction pour convertir une chaîne en identifiant Mermaid valide void convertirNom(const char* original, char* resultat) { strcpy(resultat, original); for (int i = 0; resultat[i]; i++) { if (resultat[i] == ' ' || resultat[i] == '\'') { resultat[i] = '_'; } } } // Fonction pour obtenir le nom d'un nœud à partir de son ID const char* trouverNomParId(cJSON* nodes, int id) { cJSON* node; cJSON_ArrayForEach(node, nodes) { cJSON* nodeId = cJSON_GetObjectItem(node, "id"); if (cJSON_IsNumber(nodeId) && nodeId->valueint == id) { return cJSON_GetObjectItem(node, "name")->valuestring; } } return NULL; } // Fonction pour générer le code Mermaid void genererMermaid(const char* contenuJSON, const char* nomFichierMermaid) { cJSON* root = cJSON_Parse(contenuJSON); if (!root) { printf("Erreur de parsing JSON : %s\n", cJSON_GetErrorPtr()); return; } FILE* fichierMermaid = fopen(nomFichierMermaid, "w"); if (!fichierMermaid) { perror("Erreur lors de la creation du fichier Mermaid"); cJSON_Delete(root); return; } fprintf(fichierMermaid, "flowchart TD\n"); cJSON* nodes = cJSON_GetObjectItem(root, "nodes"); cJSON* links = cJSON_GetObjectItem(root, "links"); if (!cJSON_IsArray(nodes) || !cJSON_IsArray(links)) { fprintf(stderr, "Le champ 'nodes' ou 'links' n'est pas un tableau.\n"); cJSON_Delete(root); fclose(fichierMermaid); return; } // Récupération des nœuds pour les définitions cJSON* node; cJSON_ArrayForEach(node, nodes) { cJSON* name = cJSON_GetObjectItem(node, "name"); cJSON* emoji = cJSON_GetObjectItem(node, "emoji"); if (!cJSON_IsString(name) || !cJSON_IsString(emoji)) { fprintf(stderr, "Erreur : nœud invalide.\n"); continue; } char id[100]; convertirNom(name->valuestring, id); fprintf(fichierMermaid, " %s((\"%s %s\"))\n", id, emoji->valuestring, name->valuestring); } fprintf(fichierMermaid, "\n"); // Récupération des liens pour les relations cJSON* link; cJSON_ArrayForEach(link, links) { cJSON* source = cJSON_GetObjectItem(link, "source"); cJSON* target = cJSON_GetObjectItem(link, "target"); cJSON* relation = cJSON_GetObjectItem(link, "relation"); if (!cJSON_IsNumber(source) || !cJSON_IsNumber(target) || !cJSON_IsNumber(relation)) { fprintf(stderr, "Erreur : lien invalide.\n"); continue; } const char* sourceName = trouverNomParId(nodes, source->valueint); const char* targetName = trouverNomParId(nodes, target->valueint); if (sourceName && targetName) { char sourceID[100], targetID[100]; convertirNom(sourceName, sourceID); convertirNom(targetName, targetID); fprintf(fichierMermaid, " %s -->|%d | %s\n", sourceID, relation->valueint, targetID); } } // Création des styles cJSON_ArrayForEach(node, nodes) { cJSON* name = cJSON_GetObjectItem(node, "name"); cJSON* couleur = cJSON_GetObjectItem(node, "couleur"); if (!cJSON_IsString(name) || !cJSON_IsString(couleur)) continue; char id[100]; convertirNom(name->valuestring, id); fprintf(fichierMermaid, " style %s fill:%s,stroke:#333,stroke-width:2px,color:#000;\n", id, couleur->valuestring); } // Libération et fermeture cJSON_Delete(root); fclose(fichierMermaid); } void recupererNomJson(char ** tabNom){ int nbJson = 0; ensure_directory_exists(JSON_DIR); DIR * dir = opendir(JSON_DIR); if (!dir) { perror("Erreur lors de l'ouverture du dossier DATA/json"); } struct dirent *entry; while ((entry = readdir(dir)) != NULL) { if (!has_json_extension(entry->d_name)) { continue; } nbJson ++; strcpy(tabNom[nbJson], entry->d_name); tabNom[nbJson][strlen(tabNom[nbJson]) - 5] = '\0'; printf("%s\n", tabNom[nbJson]); } snprintf(tabNom[0], 10, "%d", nbJson); } void demanderFichierConsole(nom_fichier_extension * nomFichierExtension, char **tabNom){ char nom_mmd[MAX_NAME]; char choix[MAX_NAME]; printf("Quel nom voulez vous donnez au fichier ? \n"); { int g; scanf("%d", &g);// regle un bug bizarre } if (fgets(nom_mmd, sizeof(char) * MAX_NAME, stdin) != NULL) { size_t length = strlen(nom_mmd); if (nom_mmd[length - 1] == '\n') { nom_mmd[length - 1] = '\0'; } } else { printf("Erreur de lecture.\n"); } size_t taille = strlen("MMD/") + strlen(nom_mmd) + strlen(".mmd") + 1; // +1 pour \0 nomFichierExtension->nom_fichier_mmd = (char *) malloc(taille + 1); // free a la fin du main snprintf(nomFichierExtension->nom_fichier_mmd, taille, "MMD/%s.mmd", nom_mmd); // Demander à l'utilisateur de choisir un fichier JSON bool running = true; do { printf("Reseaux disponible :"); for (int i = 0; i < NOMBRE_RESEAU; i++) { printf(" %s", tabNom[i + 1]); (i + 1) < NOMBRE_RESEAU ? printf(",") : printf(" :"); } scanf("%s", choix); for (int i = 0; i < NOMBRE_RESEAU; i++) { if (strcmp(choix, tabNom[i + 1]) == 0) { running = false; } } if (running == true){ printf(" Choix invalide\n"); } } while (running); size_t taille2 = strlen("DATA/json/") + strlen(choix) + strlen(".json "); nomFichierExtension->nom_fichier_json = malloc(sizeof(taille2) + 1); snprintf(nomFichierExtension->nom_fichier_json, taille2, "DATA/json/%s.json", choix); printf(" %s\n", nomFichierExtension->nom_fichier_json); } void demanderFichierAllegro(toutAllegro * toutAllegro1, char ** tabNom, nom_fichier_extension * nomFichierExtension){ toutAllegro1->tabImage[nom_fichier_gris] = al_load_bitmap("DATA/PNG/Menu_Selection00.png"); toutAllegro1->tabImage[nom_fichier_couleur] = al_load_bitmap("DATA/PNG/Menu_Selection01.png"); toutAllegro1->tabImage[choix_reseau_gris] = al_load_bitmap("DATA/PNG/Menu_Selection10.png"); toutAllegro1->tabImage[choix_reseau_couleur] = al_load_bitmap("DATA/PNG/Menu_Selection11.png"); if (!toutAllegro1->tabImage[4] || !toutAllegro1->tabImage[5] || !toutAllegro1->tabImage[6] || !toutAllegro1->tabImage[7]) { fprintf(stderr, "Erreur: Impossible de charger les images.\n"); al_destroy_font(toutAllegro1->font_small); al_destroy_event_queue(toutAllegro1->eventQueue); al_destroy_display(toutAllegro1->display); } // Première saisie char saisie1[MAX_INPUT_LENGTH + 1] = {0}; Saisie(toutAllegro1,toutAllegro1->tabImage[nom_fichier_gris], saisie1, " "); size_t length = strlen(saisie1); if (saisie1[length - 1] == '\n') { saisie1[length - 1] = '\0'; } size_t taille = strlen("MMD/") + strlen(saisie1) + strlen(".mmd ") + 1; // +1 pour \0 nomFichierExtension->nom_fichier_mmd = (char *) malloc(taille + 1); // free a la fin du main snprintf(nomFichierExtension->nom_fichier_mmd, taille, "MMD/%s.mmd", saisie1); // Attendre le clic sur le bouton après la saisie AttendreBouton(toutAllegro1, toutAllegro1->tabImage[nom_fichier_couleur], saisie1, 1360, 834, 315, 103); // Deuxième saisie char saisie2[MAX_INPUT_LENGTH + 1] = {0}; char RDisponible[100] = {0}; char ajout[MAX_NAME] = {0}; strcpy(RDisponible, "Reseau disponible : "); for (int i = 0; i < NOMBRE_RESEAU; i++) { snprintf(ajout, MAX_NAME, "%s%s", tabNom[i + 1], (i + 1) < NOMBRE_RESEAU ? ", " : " :"); strcat(RDisponible, ajout); } strcat(RDisponible, "\0"); char *reseauDisponible = malloc(strlen(RDisponible) + 1* sizeof(char)); strcpy(reseauDisponible, RDisponible); if (!reseauDisponible) { fprintf(stderr, "Erreur : échec de l'allocation mémoire.\n"); exit(EXIT_FAILURE); } bool runnig = true; bool once = true; do { Saisie(toutAllegro1, toutAllegro1->tabImage[choix_reseau_gris], saisie2, reseauDisponible); for (int i = 0; i < NOMBRE_RESEAU; i++) { if (strcmp(saisie2, tabNom[i + 1]) == 0) { runnig = false; break; } } if(runnig == true && once == true){ strcpy(ajout, "\n choix invalide !"); size_t nouvelle_taille = strlen(reseauDisponible) + strlen(ajout) + 1; reseauDisponible = realloc(reseauDisponible, nouvelle_taille); strcat(reseauDisponible, ajout); once = false; } }while(runnig); size_t taille2 = strlen("DATA/json/") + strlen(saisie2) + strlen(".json "); nomFichierExtension->nom_fichier_json = malloc(sizeof(taille2) + 1); snprintf(nomFichierExtension->nom_fichier_json, taille2, "DATA/json/%s.json", saisie2); // Attendre le clic sur le bouton après la deuxième saisie AttendreBouton(toutAllegro1, toutAllegro1->tabImage[choix_reseau_couleur], saisie2, 1360, 834, 315, 103); al_draw_bitmap(toutAllegro1->tabImage[chargement], 0, 0, 0); al_flip_display(); free(reseauDisponible); } void convertion_json_mmd(nom_fichier_extension * nomFichierExtension, toutAllegro * toutAllegro1) { char **tabNom = (char **) malloc(NB_RESEAU_MAX * sizeof(char *)); for (int i = 0; i < NB_RESEAU_MAX; i++) { tabNom[i] = (char *) malloc(LONGUEUR_MAX_NOM_FICHIER * sizeof(char)); } recupererNomJson(tabNom); if (MODE == console) { demanderFichierConsole(nomFichierExtension, tabNom); } else{ demanderFichierAllegro(toutAllegro1, tabNom, nomFichierExtension); } size_t taille = strlen(nomFichierExtension->nom_fichier_mmd) + 1; nomFichierExtension->nom_fichier_png = malloc(taille); // Lire le contenu du fichier JSON char* contenuJSON = lireFichier(nomFichierExtension->nom_fichier_json); if (!contenuJSON) { printf("Erreur : Le fichier %s n'existe pas ou ne peut pas être ouvert.\n", nomFichierExtension->nom_fichier_json); } // Générer le code Mermaid et l'enregistrer dans un fichier genererMermaid(contenuJSON, nomFichierExtension->nom_fichier_mmd); // Libérer la mémoire du contenu JSON free(contenuJSON); printf("Diagramme Mermaid genere dans le fichier : %s\n", nomFichierExtension->nom_fichier_mmd); convertion_mmd_png(nomFichierExtension) ;/// converti un fichier .mmd donne en entree en .png et renvoie son chemin d'acces } void convertionSimulation(){ char* contenuJSON = lireFichier("DATA/json/simulation.json"); if (!contenuJSON) { printf("Erreur : Le fichier %s n'existe pas ou ne peut pas être ouvert.\n","DATA/json/simulation.json"); } // Générer le code Mermaid et l'enregistrer dans un fichier genererMermaid(contenuJSON, "MMD/simulation.mmd"); convertionPNGSimulation(); // Libérer la mémoire du contenu JSON free(contenuJSON); }