//
// 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);
}