projet-reseaux-trophiques-equipe-3b / Convertion_jsonTopng / convertion_JSON_MMD.c
convertion_JSON_MMD.c
Raw
//
// 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);
}