diff --git a/Documentation/.gitignore b/Documentation/.gitignore index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..35c54365425cc42faf84a2139dd7c4c6b18111c3 100644 --- a/Documentation/.gitignore +++ b/Documentation/.gitignore @@ -0,0 +1,20 @@ +# Created by https://www.toptal.com/developers/gitignore/api/venv +# Edit at https://www.toptal.com/developers/gitignore?templates=venv + +### venv ### +# Virtualenv +# http://iamzed.com/2009/05/07/a-primer-on-virtualenv/ +.Python +[Bb]in +[Ii]nclude +[Ll]ib +[Ll]ib64 +[Ll]ocal +[Ss]cripts +pyvenv.cfg +.venv +pip-selfcheck.json + +# End of https://www.toptal.com/developers/gitignore/api/venv + +/site diff --git a/Documentation/README.md b/Documentation/README.md new file mode 100644 index 0000000000000000000000000000000000000000..7752eb4e068a58bf16deff28600ad9e56c835a4f --- /dev/null +++ b/Documentation/README.md @@ -0,0 +1,216 @@ +# projet_isc_l431 - documentation + +Ce repo git contient la documentation pour le projet réalisé dans le cadre du cours d'ateliers logiciels. + +Ce repo contient également un fichier de configuration [MkDocs](https://www.mkdocs.org) permettant de facilement visualiser la documentation (en local). + + +## Installation du repo + +Cloner le projet : + +``` +git clone ssh://git@ssh.hesge.ch:10572/in-code-we-trust/documentation.git +``` + +Créer et activer l'environnement virtuel : + +``` +python -m venv .venv +source .venv/bin/activate +``` + +Installer les dépendances : + +``` +python -m pip install -r requirements.txt +``` + + +## Structure de la documentation + +Les fichiers de documentation utilisent le format markdown (`.md`) et se trouvent dans le dossier `docs`. + +Le dossier `docs/img` contient les différentes images utilisées dans la documentation. + +Le fichier `mkdocs.yml` est le fichier de configuration MkDocs. + +> Tous les autres fichiers pouvant servir à la documentation mais qui ne sont ni pas des images ou `.md` doivent se +trouver dans un dossier et/ou à la racine du repo. + + +## MkDocs + +L'utilisation de MkDocs permet de consulter facilement la documentation du projet. + +Son utilisation n'est pas indispensable si consulter les fichiers `.md` est suffisant pour vous, néanmoins son +installation est vivement recommandée afin de générer un site statique permettant de parcourir et consulter simplement +la documentation. + + +### Utilisation + +*Pensez à bien activer l'environnement virtuel au préalable.* + +À la racine du projet, la commande suivante permet de visualiser la documentation : + +``` +mkdocs serve +``` + +Ouvrir un navigateur à l'adresse `http://127.0.0.1:8000/` affiche le site généré, permettant de consulter la +documentation. + +Si nécessaire, il est possible de changer le port utilisé à l'aide du paramètre `-a` : + +``` +mkdocs serve -a "127.0.0.1:9876" +``` + +L'exemple ci-dessus rend le site accessible en `http://127.0.0.1:9876`. + +### Générer le site + +Il est possible de générer le site avec la commande suivante : + +``` +mkdocs build +``` + +Cette commande produit un dossier `site` contenant la documentation sous forme d'un site web. Il est ensuite possible +d'héberger ce dossier afin de la rendre accessible à tout le monde. + + +## Écrire la documentation + +### Enrichir la documentation + +[Material for MkDocs](https://squidfunk.github.io/mkdocs-material/reference/) met à disposition de nombreuses extensions +offrant de nombreuses fonctionnalités pour enrichir la documentation. N'hésitez pas à y jetter un oeil afin de voir ce +qui est disponible. + + +### Ajouter une page + +Si vous souhaitez ajouter une page, pour par exemple expliquer une nouvelle fonctionnalité, il suffit simplement de +créer un fichier `<my_file>.md` dans le dossier correspondant (ex: `backend/<my_file>.md` pour une fonctionnalité du +serveur). + +Il faut ensuite ajouter le fichier dans la navigation définie dans la configuration de +[mkdocs](https://gitedu.hesge.ch/in-code-we-trust/documentation/-/blob/main/mkdocs.yml). + + +L'ajout se fait de la manière suivante : + +```yml +nav: + # ... + - Backend: + - Introduction: + - backend/index.md + - Gestion des données: + - Modèles: 'backend/models.md' + - Migrations: 'backend/migrations.md' + - Sérialisation: 'backend/serialization.md' + - <Nom de section>: 'backend/<my_file>.md' # Le chemin vers le nouveau fichier + - Fonctionnement: + - REST framework: 'backend/rest_framework.md' + # ... +``` + +*Remplacer respectivement `<Nom de section>` et `<my_file>` avec un nom de section et le nom du fichier de votre page.* + + +## Déploiement de la documentation avec Docker + +Actuellement, le déploiement de la documentation sur le serveur distant s'effectue à l'aide de docker compose. + + +### Prérequis + +Il est impératif que ce serveur puisse accéder au projet git en SSH. + +*Les clefs SSH expireront le 8 juillet 2023.* + + +Le serveur doit pouvoir créer une image docker et lancer un container à partir de cette image. + + +### Marche à suivre + +Se connecter au serveur [wetty](https://silentpc.ciuj-kune.org/wetty). + +- Pour le premier déploiement, exécuter les commandes suivantes : + +``` +git clone ssh://git@ssh.hesge.ch:10572/in-code-we-trust/documentation.git +cd documentation +python -m pip install -r requirements.txt +mkdocs build +``` + +Note: Le fichier `check-container.bash` permet de vérifier qu'un conteneur de notre image est existant. Dans le cas +contraire il va exécuter le fichier `setup-prod.bash` avec le paramètre `-f`, forçant le déploiement de notre +*container*. + +Se rendre ensuite sur la page des Stacks du [portainer](https://silentpc.ciuj-kune.org/portainer/#!/2/docker/stacks) + +1. Cliquer sur le bouton `+ Add stack` +2. Donner un nom à la stack : `icwt` +3. Sélectionner l'option `Upload` +4. Cliquer sur le bouton `Select file` et sélectionner le fichier `docker-compose.yml` +5. En bas de page, cliquer sur le bouton `Deploy the stack` + +La documentation est ensuite accessible [ici](http://silentpc.ciuj-kune.org:2100/). + +### Bind mount + +Le dossier `site/`, généré par la commande `mkdocs build` est monté sur le conteneur docker à l'aide du fichier +`docker-compose.yml`. + +En cas de modification de la documentation il suffit d'effectuer la commande `mkdocs build` pour que le containeur soit +automatiquement mis à jour. + + +### Automatisation + +Les scripts `setup-prod.bash` et `check-container.bash` permettent de mettre à jour automatiquement la documentation. + +Pour cela, il faut impérativement les rendre exécutables : + +``` +chmod +x setup-prod.bash +chmod +x check-container.bash +``` + +Il est possible d'exécuter régulièrement le fichier `setup-prod.bash` à l'aide de crontab : + +``` +crontab -e +0 3 * * * ~/documentation/setup-prod.bash +``` + +*Le fichier sera exécuté automatiquement tous les jours à 3H du matin.* + + +Actuellement, le crontab sur le serveur est définit ainsi : + +``` +PATH=$PATH:/home/incode/.local/bin:/usr/bin +0 * * * * ~/documentation/setup-prod.bash >> ~/crontab_logs/doc_setup.log 2>&1 +7 * * * * ~/documentation/check-container.bash >> ~/crontab_logs/doc_check.log 2>&1 +15 * * * * ~/documentation/setup-prod.bash >> ~/crontab_logs/doc_setup.log 2>&1 +22 * * * * ~/documentation/check-container.bash >> ~/crontab_logs/doc_check.log 2>&1 +30 * * * * ~/documentation/setup-prod.bash >> ~/crontab_logs/doc_setup.log 2>&1 +37 * * * * ~/documentation/check-container.bash >> ~/crontab_logs/doc_check.log 2>&1 +45 * * * * ~/documentation/setup-prod.bash >> ~/crontab_logs/doc_setup.log 2>&1 +52 * * * * ~/documentation/check-container.bash >> ~/crontab_logs/doc_check.log 2>&1 +``` + +- La ligne `PATH=$PATH:/home/incode/.local/bin` nous assure que la commande mkdocs soit trouvée afin d'être correctement +exécutée. + +- Les `>> ~/crontab_logs/<name>.log` permettent de rediriger la sortie des commandes dans un fichier. + +- Les `2>&1` vont rediriger la sortie d'erreur (`stderr`) dans la sortie standard (`stdout`), ce qui permet de garder une +trace des erreurs lors de l'exécution des commandes. diff --git a/Documentation/docs/api/get_user_info.md b/Documentation/docs/api/get_user_info.md new file mode 100644 index 0000000000000000000000000000000000000000..873d278e210c982ace51473d788b66698662b6e8 --- /dev/null +++ b/Documentation/docs/api/get_user_info.md @@ -0,0 +1 @@ +# GET /api/v1/users/:username \ No newline at end of file diff --git a/Documentation/docs/api/index.md b/Documentation/docs/api/index.md new file mode 100644 index 0000000000000000000000000000000000000000..89e60e937cffdd5f11ba721fc8fd2243fa057517 --- /dev/null +++ b/Documentation/docs/api/index.md @@ -0,0 +1 @@ +# Explication de l'API \ No newline at end of file diff --git a/Documentation/docs/api/user_connect.md b/Documentation/docs/api/user_connect.md new file mode 100644 index 0000000000000000000000000000000000000000..b0f8f34f71d24532d97b8315670ccbca26582a44 --- /dev/null +++ b/Documentation/docs/api/user_connect.md @@ -0,0 +1 @@ +# POST /api/v1/guests/users/:username \ No newline at end of file diff --git a/Documentation/docs/api/user_create.md b/Documentation/docs/api/user_create.md new file mode 100644 index 0000000000000000000000000000000000000000..fe08d872d8652ed6dd06e6141a848c92aba3d97b --- /dev/null +++ b/Documentation/docs/api/user_create.md @@ -0,0 +1 @@ +# POST /api/v1/guests/user \ No newline at end of file diff --git a/Documentation/docs/frontend/angular.md b/Documentation/docs/frontend/angular.md new file mode 100644 index 0000000000000000000000000000000000000000..42970c4225297211a6fc50a4d37d9575c093e4e9 --- /dev/null +++ b/Documentation/docs/frontend/angular.md @@ -0,0 +1 @@ +# Angular \ No newline at end of file diff --git a/Documentation/docs/frontend/babylonjs.md b/Documentation/docs/frontend/babylonjs.md new file mode 100644 index 0000000000000000000000000000000000000000..35df3f0f5985256083085009ee2d5fa1ef67b49d --- /dev/null +++ b/Documentation/docs/frontend/babylonjs.md @@ -0,0 +1,2 @@ +# Babylon JS + diff --git a/Documentation/docs/frontend/firebase.md b/Documentation/docs/frontend/firebase.md new file mode 100644 index 0000000000000000000000000000000000000000..c5f58944c42d7ee8c76f2d1b437e8da11b563832 --- /dev/null +++ b/Documentation/docs/frontend/firebase.md @@ -0,0 +1,26 @@ +# Firebase + + +## Envoi des données à Firebase +Toutes les méthodes utiles pour envoyer et recevoir des données à Firebase sont dans le fichier *meshprocess/src/app/project.service.ts*. Les méthodes qu'on a dans ce fichier nous est utiles a chaque fois qu'on souhaite actualiser la base de données ou bien envoyer un fichier pour le bon fonctionnement de nos pages ionic. +Sachant que nos images ou les informations à propos de chaque projet et process doivent être stocké pour un meilleur rendu. + +## Représentation de chaque projet +Notre base de données Firebase est représenté comme suit: + + +On peut voir ici que la structure dans la base de données est la même que dans notre code. À chaque ajout de projet un id unique est créer dans la base données avec les attributs du projet. Dans notre exemple ci-dessus, ce sera le projet qui contiendra tous les process qui ne vont pas être associé à des projets en particulier. Ce "projet"(qui n'est pas vraiment un au final), ne va pas être afficher sur notre page car ce n'est pas un projet en soit. + +À chaque ajout de process dans un projet, il y aura également un id unique par process. + +## Stockage des données **obj** de notre process + +Les données **obj** vont être stockées dans l'attribut *dataObj* de chaque process. On aura tout le contenu du fichier *.obj* qui va être récupérer à partir de notre backend Django. + +## Stockage des images + +Dans notre application web, on va devoir stocké une image pour chaque projet et chaque process. Grâce à Firebase on peut les stockés et pouvoir les récupérer facilement avec des lien qui seront stockés dans les attributs des projets et process dans la base de données. + + + +Les images de chaque projet sont stockés dans le dossier *Images*. Et les images de tous les process de chaque projet sont stockés dans les dossier nommé à partir de leur id. diff --git a/Documentation/docs/frontend/functionning.md b/Documentation/docs/frontend/functionning.md new file mode 100644 index 0000000000000000000000000000000000000000..4a9adfb9e9a760b5bb75d7009f2b740443946843 --- /dev/null +++ b/Documentation/docs/frontend/functionning.md @@ -0,0 +1,53 @@ +# Fonctionnement + +## Structure du frontend + +Lorsqu'on accède à l'application, on va tomber sur la page suivante(/home-project): + + +On aura la possibilité d'ajouter différents projets, les supprimer ou bien modifier les process associé au projet. On aura également le bouton en haut à gauche *PROCESS* qui permettra d'importer des process sans créer un projet. Cet page est modifiable dans les fichiers du projet ionic, dans le répertoire *meshprocess/src/app/home-project*. +Chaque page ionic est structuré de cette façon: + + +### Modification du comportement de la page +Comme pour une page html normal, on peut modifier le design de la page dans le **html** et le **scss**. La logique de notre page, se situe dans le fichier typescript qui dans l'exemple ici: *home-project-page.ts* + + +### Structure d'un projet +Dans ce même dossier ici dans notre page contenant les projets, on a également le fichier *project-model.ts*, qui va contenir ici la classe pour représenter la structure qu'un projet peut avoir: + + Cela nous est utile pour pouvoir accéder aux attributs d'un projet plus facilement. + +### Structure d'un process +La structure d'un process est lui également situé dans un fichier en particulier *meshprocess/src/app/dashboard/process-model.ts*: + + + + +## Visualisation des process + +### Structure de la page +La page pour visualiser les process de chaque projet est représenter comme ci-dessous: + + +Sur cet page on pourra comme pour les projets ajouter un nouveaux process. + +### Ajout d'un process + +La particularité est qu'on devra communiquer avec notre backend Django pour pouvoir faire la conversion d'un fichier step à importer. Dans notre cas le fichier step sera converti et le backend nous enverra un *json* contenant le contenu du fichier *obj*. Le contenu de ce *json* va être stocké dans l'attribut *dataObj* de chaque process et permettra de l'afficher dans babylonjs + +### Affichage d'un objet 3d + +Pour afficher le process on utilise la librairie *babylonjs*. *babylonjs* nous permet directement de générer l'aperçu 3d d'une pièce directement à partir du contenu du fichier *obj*. Et puisque dans notre cas, on a directement les données *obj*. On pourra a chaque fois qu'on voudra afficher une pièce en particulier, le générer rapidement. + +### Image de chaque process + +À chaque ajout d'un nouveau process, la pièce est directement visualisable sur le côté droit de la page. Grâce à la librairie *babylonjs*, on récupère directement une image de la pièce lors de sa génération, et c'est cette image la qui sera stocké dans notre *Firebase*. + +### Rendu de la visualisation d'une pièce + +Lors qu'on voudra visualiser une pièce, plusieurs informations seront disponibles pour voir les différentes particularités de la pièce: + + + +Ici on a utiliser les GUI de babylonjs pour pouvoir visualiser la pièce de manière optimale pour l'utilisateur. diff --git a/Documentation/docs/frontend/img/dashboard-page.png b/Documentation/docs/frontend/img/dashboard-page.png new file mode 100644 index 0000000000000000000000000000000000000000..40d3d74574eb67959c0fa80d0e412010ab18d8a0 Binary files /dev/null and b/Documentation/docs/frontend/img/dashboard-page.png differ diff --git a/Documentation/docs/frontend/img/home-project-page.png b/Documentation/docs/frontend/img/home-project-page.png new file mode 100644 index 0000000000000000000000000000000000000000..a0f65c4018aae4b2118674a4120e60e3d39dca6c Binary files /dev/null and b/Documentation/docs/frontend/img/home-project-page.png differ diff --git a/Documentation/docs/frontend/img/img-storage.png b/Documentation/docs/frontend/img/img-storage.png new file mode 100644 index 0000000000000000000000000000000000000000..5e77d0c35e627bc8c87add157c0b2e8ca069bb72 Binary files /dev/null and b/Documentation/docs/frontend/img/img-storage.png differ diff --git a/Documentation/docs/frontend/img/page-structure.png b/Documentation/docs/frontend/img/page-structure.png new file mode 100644 index 0000000000000000000000000000000000000000..7a887db4be48d035f298a41c3f084d81034047b8 Binary files /dev/null and b/Documentation/docs/frontend/img/page-structure.png differ diff --git a/Documentation/docs/frontend/img/process-structure.png b/Documentation/docs/frontend/img/process-structure.png new file mode 100644 index 0000000000000000000000000000000000000000..f567f7d77024eafb36e0f274aa4874fe56d1e840 Binary files /dev/null and b/Documentation/docs/frontend/img/process-structure.png differ diff --git a/Documentation/docs/frontend/img/projet-structure.png b/Documentation/docs/frontend/img/projet-structure.png new file mode 100644 index 0000000000000000000000000000000000000000..8729c9edf5590b8f0209596dfa06c1b32b1f5fc9 Binary files /dev/null and b/Documentation/docs/frontend/img/projet-structure.png differ diff --git a/Documentation/docs/frontend/img/structure-database.png b/Documentation/docs/frontend/img/structure-database.png new file mode 100644 index 0000000000000000000000000000000000000000..59a971fae33088e0140122553ed3b7cb5d0cc1db Binary files /dev/null and b/Documentation/docs/frontend/img/structure-database.png differ diff --git a/Documentation/docs/frontend/img/visu-babylon.png b/Documentation/docs/frontend/img/visu-babylon.png new file mode 100644 index 0000000000000000000000000000000000000000..36e523744630fa78943b34670088668cc32fbde7 Binary files /dev/null and b/Documentation/docs/frontend/img/visu-babylon.png differ diff --git a/Documentation/docs/frontend/index.md b/Documentation/docs/frontend/index.md new file mode 100644 index 0000000000000000000000000000000000000000..23c5c0a0d9a2fc698ae38d420b0d24b0de09a592 --- /dev/null +++ b/Documentation/docs/frontend/index.md @@ -0,0 +1,12 @@ +# Frontend + +Cette page contient la documentation concernant la partie frontend du projet. + +Le framework [Ionic](https://ionicframework.com/), avec [Angular](https://angular.io/) et +[Tailwind CSS](https://tailwindcss.com/) est utilisé pour le frontend du projet. + + +## Installation + +La marche à suivre pour l'installation et la mise en place du projet est disponible sur le +[gitlab](https://gitedu.hesge.ch/in-code-we-trust/frontend/-/blob/main/README.md#installation). diff --git a/Documentation/docs/frontend/ionic.md b/Documentation/docs/frontend/ionic.md new file mode 100644 index 0000000000000000000000000000000000000000..773c40a36d9d631462e8d298bd11afa95ef9a69f --- /dev/null +++ b/Documentation/docs/frontend/ionic.md @@ -0,0 +1,10 @@ +# Ionic + +## Création d'un nouvel élément ionic + +Dans *ionic* on peut créer un nouvel élement facilement(page, service, component, etc...). Il suffit d'exécuter la commande suivante: +```bash +ionic generate +``` + +Puis il faut juste choisir l'élément à génerer dans le projet ionic et les fichiers nécessaires seront créé automatiquement en conséquence. diff --git a/Documentation/docs/frontend/tailwindcss.md b/Documentation/docs/frontend/tailwindcss.md new file mode 100644 index 0000000000000000000000000000000000000000..acac9ef88333312d0907a1fe0062f773ea8ecf2b --- /dev/null +++ b/Documentation/docs/frontend/tailwindcss.md @@ -0,0 +1 @@ +# Tailwind CSS \ No newline at end of file diff --git a/Documentation/docs/img/favicon.ico b/Documentation/docs/img/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..e3ab04fe9357c737a04227c9df89c26ae8b2eef1 Binary files /dev/null and b/Documentation/docs/img/favicon.ico differ diff --git a/Documentation/docs/index.md b/Documentation/docs/index.md new file mode 100644 index 0000000000000000000000000000000000000000..1aa8fb2934ade6eb8190d0c8905795efa8990922 --- /dev/null +++ b/Documentation/docs/index.md @@ -0,0 +1,35 @@ +--- +hide: + - navigation +--- + + +# Introduction + +Dans ce projet, on a conçu et implémenter une application de jeu de quiz en utilisant une architecture RESTful et des sockets. L'application permet à différents utilisateurs de se connecter, de jouer et de gérer les questions et les utilisateurs. + + + +# Ressources + +L'application comprend trois types d'utilisateurs : les invités, les joueurs et les administrateurs. Chaque utilisateur est identifié par un nom d'utilisateur unique et un mot de passe. Les questions du quiz sont également des ressources importantes de l'application, comprenant la question elle-même, les réponses proposées et la catégorie associée. + + + +# Actions possibles en fonction du type d'utilisateur + +Les invités peuvent créer un compte, qui sera automatiquement un compte de type joueur. Ils pourront également se connécter à leur compte respectif. Les administrateurs, quant à eux, ont des privilèges plus étendus. Ils peuvent lister, créer, mettre à jour et supprimer des questions et des utilisateurs. + + + +# Déroulement d'une partie + +La partie commence lorsque trois joueurs sont connectés via socket.io avec un token JWT valide. À chaque partie, une question est tirée au hasard et présentée simultanément aux trois joueurs. Chaque joueur doit choisir parmi les réponses proposées. Une fois qu'un joueur a répondu, le serveur vérifie la réponse et attribue des points en fonction de la réponse donnée. + +Après chaque question, le serveur passe à la question suivante jusqu'à ce que dix questions aient été posées. Une fois la partie terminée(10 questions passées), le serveur affiche un classement des joueurs en fonction de leurs points. Le serveur se réinitialise alors et revient à l'étape d'attente des joueurs pour commencer une nouvelle partie. + + + +# Conclusion + +Ce projet vous a permis de développer une application de jeu de quiz avec des fonctionnalités de connexion, de jeu et de gestion des questions et des utilisateurs. Vous avez utilisé une architecture RESTful et des sockets pour permettre une expérience de jeu en temps réel. Vous avez également implémenté différents rôles d'utilisateurs avec des privilèges spécifiques. Avec cette application, les joueurs pourront s'affronter dans des parties de quiz passionnantes et les administrateurs pourront gérer les questions et les utilisateurs de manière efficace. \ No newline at end of file diff --git a/Documentation/docs/javascripts/mathjax.js b/Documentation/docs/javascripts/mathjax.js new file mode 100644 index 0000000000000000000000000000000000000000..bd77d8cd96521e9afee09275b58df09171d44bd0 --- /dev/null +++ b/Documentation/docs/javascripts/mathjax.js @@ -0,0 +1,17 @@ +// https://squidfunk.github.io/mkdocs-material/reference/mathjax/#configuration +window.MathJax = { + tex: { + inlineMath: [["\\(", "\\)"]], + displayMath: [["\\[", "\\]"]], + processEscapes: true, + processEnvironments: true + }, + options: { + ignoreHtmlClass: ".*|", + processHtmlClass: "arithmatex" + } +}; + +document$.subscribe(() => { + MathJax.typesetPromise() +}) \ No newline at end of file diff --git a/Documentation/docs/theory/advanced_algorithms.md b/Documentation/docs/theory/advanced_algorithms.md new file mode 100644 index 0000000000000000000000000000000000000000..3ada0cacafe659533ac190e9813a9b2bdf97259c --- /dev/null +++ b/Documentation/docs/theory/advanced_algorithms.md @@ -0,0 +1,37 @@ +# ISC_L411 - Algorithmes avancés + +## Parcours de graphes + +### Parcours en profondeur (Depth-First Search ou DFS) + +Principe : + +- Parcours un sommet non-visité jusqu'à un cul-de-sac + - Chaque sommet parcouru est noté comme *visité* +- Si bloqué, retourne en arrière jusqu'au dernier sommet avec un chemin possible +- Se termine une fois tous les sommets visités + +<figure markdown> + { width="500"} + <figcaption>L'ordre des noeuds visités avec un parcours en profondeur</figcaption> +</figure> + +### Parcours en largeur (Breadth-First Search ou BFS) + +Principe : + +- Commence à la racine et note sa profondeur à 0 +- Parcours les voisins et note leur profondeur à 1 +- Pour chaque noeuds de profondeur 1, parcours les voisins et note leur profondeur à 2 +- Se termine une fois tous les sommets parcourus. + + +!!! note + Indiquer la profondeur des noeuds permet de connaître leur distance par rapport au + noeud racine. Ceci permet de visualiser la profondeur au sein d'un graphe. + + +<figure markdown> + { width="500"} + <figcaption>L'ordre des noeuds visités avec un parcours en largeur</figcaption> +</figure> \ No newline at end of file diff --git a/Documentation/docs/theory/algorithmic_geometry.md b/Documentation/docs/theory/algorithmic_geometry.md new file mode 100644 index 0000000000000000000000000000000000000000..e78b0404c436144642ea8e3f6c68ee57e7c03f46 --- /dev/null +++ b/Documentation/docs/theory/algorithmic_geometry.md @@ -0,0 +1,90 @@ +# ISC_L412 - Géométrie algorithmique + +!!! warning "Attention" + Les informations se trouvant sur cette page sont incomplètes, peuvent contenir des erreurs et/ou nécessitent une + meilleure mise en page. + +## Les normales + +## Vecteurs + +## Modèle de données de stockage des maillages + +### Tableaux de sommets + +Il est possible de représenter des maillages à l'aide d'un tableaux de sommets : + +<figure markdown> +  + <figcaption>Tableaux de sommets</figcaption> +</figure> + +### Half-Edge + +Une autre représentation possible est via la structure de données *Half-Edge*. + +Cette structure est composé de 3 éléments principaux : + +- **Sommet** (vertex) : représente un point +- **Face** : une surface fermée dans le maillage +- **Demi-arête** (half-edge) + - Correspond à un bord orienté du maillage + - Est associé à un sommet initial, une face qui la contient et une demi-arête opposée + +<figure markdown> + { width="600" } + <figcaption>Diagramme d'un mesh</figcaption> +</figure> + +<figure markdown> +  + <figcaption>Représentation half-edge</figcaption> +</figure> + +Cette représentation offre une grande libertée de traitements possibles sur des maillages. + +## Éclairage Phong + +Le modèle d'illumination de Phong permet de calculer de manière crédible la lumière réfléchie par un point étudié. + +<figure markdown> +  + <figcaption>Visualisation de l'équation Phong</figcaption> +</figure> + +Ce modèle est séparé en 3 composantes : + +- lumière **ambiante** +- lumière **diffuse** +- lumière **spéculaire** + +### Lumière ambiante + +Lorsqu’un point n’est pas directement éclairé par une source, il apparaitra complètement noir. + +La lumière ambiante est supposée égale en tout point de l'espace + +### Lumière diffuse + +Représente l'intensité qui repart en tenant compte de l'inclinaison avec laquelle la lumière incidente arrive sur la +surface, mais en supposant que l'intensité est la même quelle que soit la direction que prend le rayon réfléchi. + +Ainsi, les surfaces rugueuse créées des ombres douces. + + +### Lumière spéculaire + +La spécularité traduit l’aspect « brillant » de l’objet. + +La réflexion spéculaire provient de la réflexion des rayons lumineux sur l’objet. + +Ainsi, les surfaces lisses créées des reflets brillants. + + +## Ombrage de Gouraud (interpolation) + +## Indicateurs de qualités + +## Ressources + +- [Half-Edge Data Structures](https://jerryyin.info/geometry-processing-algorithms/half-edge/) \ No newline at end of file diff --git a/Documentation/docs/theory/img/Phong_components.png b/Documentation/docs/theory/img/Phong_components.png new file mode 100644 index 0000000000000000000000000000000000000000..57dd7fa94137f7136b4b180979782d91b176041c Binary files /dev/null and b/Documentation/docs/theory/img/Phong_components.png differ diff --git a/Documentation/docs/theory/img/bft.png b/Documentation/docs/theory/img/bft.png new file mode 100644 index 0000000000000000000000000000000000000000..f2647e579b983593b610823d95ed18b382538977 Binary files /dev/null and b/Documentation/docs/theory/img/bft.png differ diff --git a/Documentation/docs/theory/img/dihedral.png b/Documentation/docs/theory/img/dihedral.png new file mode 100644 index 0000000000000000000000000000000000000000..5d7b2a70aeac0a5a085b5cb35ba1a2283defffa2 Binary files /dev/null and b/Documentation/docs/theory/img/dihedral.png differ diff --git a/Documentation/docs/theory/img/dpf.png b/Documentation/docs/theory/img/dpf.png new file mode 100644 index 0000000000000000000000000000000000000000..44635d98a7a2bd8e0e6333b65a71e157a253a113 Binary files /dev/null and b/Documentation/docs/theory/img/dpf.png differ diff --git a/Documentation/docs/theory/img/half-edge.png b/Documentation/docs/theory/img/half-edge.png new file mode 100644 index 0000000000000000000000000000000000000000..65fa6b146ea309329903693afd4d53e81791105e Binary files /dev/null and b/Documentation/docs/theory/img/half-edge.png differ diff --git a/Documentation/docs/theory/img/mesh.png b/Documentation/docs/theory/img/mesh.png new file mode 100644 index 0000000000000000000000000000000000000000..d728f3779810639374cb855addc910d7782ca5a4 Binary files /dev/null and b/Documentation/docs/theory/img/mesh.png differ diff --git a/Documentation/docs/theory/img/records.png b/Documentation/docs/theory/img/records.png new file mode 100644 index 0000000000000000000000000000000000000000..d4b6eeacaffaf42cfd40b7e9ae43f617de0a3bc2 Binary files /dev/null and b/Documentation/docs/theory/img/records.png differ diff --git a/Documentation/docs/theory/indicators-and-others.md b/Documentation/docs/theory/indicators-and-others.md new file mode 100644 index 0000000000000000000000000000000000000000..3c32f145852cb2e6d55ba96739fa4b14f63256e7 --- /dev/null +++ b/Documentation/docs/theory/indicators-and-others.md @@ -0,0 +1,225 @@ +# Indicateurs de qualité + +!!! warning "Attention" + Les informations se trouvant sur cette page sont incomplètes, peuvent contenir des erreurs et/ou nécessitent une + meilleure mise en page. + +Quality checks summary : + +1. Aspect Ratio should not go beyond 5 +2. Warp angle should not be more than 45° +3. Jacobian should not be less than 0.5 +4. Tet collapse should be greater than 0.1 + +## Element Quality +>"The Element Quality is based on the ratio of the volume to the sum of the square of the edge lengths for 2D quad/tri elements, or the square root of the cube of the sum of the square of the edge lengths for 3D elements. + +>The Element Quality is a composite quality metric that ranges between 0 and 1. + +>A value of 1 indicates a perfect cube or square while a value of 0 indicates that the element has a zero or negative volume." + +[source](https://featips.com/2022/11/21/ansys-mesh-metrics-explained/) + +$Element Quality (2D) = C \times \frac{area}{\sum edge \space length^2 }$, namely: +$Element Quality (2D) = 4\sqrt 3 \times \frac{area}{a^2 + b^2 + c^2 }$, namely: + +$Element Quality (2D) = 6.928 \times \frac{area}{a^2 + b^2 + c^2 }$ + +For 3D elements, the formula is: +$Element Quality (3D) = C \times \frac{volume}{(\sqrt{\sum edge \space length^2) ^3 }}$ + +## Dihedral angle between two faces + +The dihedral angle between two faces is the value: + +$\pi \pm arccos<\vec{n_1}, \vec{n_2}>$ + +depending on the configuration of the two faces with respect to $\vec{n_i}$, the normals of the faces under interest. + + + +## Tet collapse +$Tet Collapse = min \space of(\frac{h}{\sqrt{A} \times 1.24})$ +_1662385923.png) +(from page 593 of Pascal Jean Frey, Paul L. George - Mesh Generation_ Application to Finite Elements (2000, Hermès Science)) + +[source from skill lync](https://skill-lync.com/blogs/technical-blogs/cfd-how-to-solve-tet-collapses-in-tetra-unstructured-mesh) + + +## Aire des triangles + +!!! quote "Objectif" + Mesurez l'aire de chaque triangle dans le maillage. Des triangles trop petits ou trop grands peuvent indiquer un + maillage de mauvaise qualité. + +Cet indicateur mesure la taille de chaque triangle du maillage. Les triangles trop petits peuvent causer des problèmes +de précision, tandis que les triangles trop grands peuvent causer des problèmes de performances. Un maillage de bonne +qualité aura des triangles de tailles similaires. + +## Qualité de l'arête + +!!! quote "Objectif" + Évaluez la longueur des arêtes du maillage. Les arêtes trop courtes ou trop longues peuvent entraîner une mauvaise + qualité. + +There are different indicators that can be used to measure the quality of edges in a mesh. + +Here are a few examples: + +- Aspect Ratio. See below. + +- various measures of angles (minimum or maximum) + +- Maximum Angle: Largest angle between adjacent edges of the element is reported. + +- Minimum Angle: Smallest angle between adjacent edges of the element is reported. + +## Taux de régularité + +!!! quote "Objectif" + Calculez le pourcentage de triangles ayant un rapport d'aspect proche de 1. Un taux élevé de régularité indique un + maillage de meilleure qualité. + +*Aussi appelé rapport d'aspect.* + +The aspect ratio is a measure of the quality that is used in mesh generation and measures the ratio of the longest edge to the shortest edge of a simplex. The closer the aspect ratio is to 1, the better the simplex is. + +The ratio of the longest edge to the shortest edge of a simplex is another measure of aspect ratio. In fact, it is a common way to define aspect ratio for triangles. The longer the longest edge is relative to the shortest edge, the larger the aspect ratio. This can be expressed mathematically as: + +$$AR = \frac{l_{max}}{l_{min}}$$ + +where $l_{max}$ is the length of the longest edge and $l_{min}$ is the length of the shortest edge. This definition is specific to triangles and is not applicable to other types of simplices like tetrahedra. + +The aspect ratio defined in terms of the inscribed radius and the longest edge, as described earlier, is a more general definition that can be applied to simplices of any dimension. It is also related to the ratio of the circumradius to the inradius, which is another measure of shape quality for simplices. + +REFERENCE PLEASE??????? + +The aspect ratio of a given simplex K is defined by $Q_K = \alpha_2 \frac{h_{max}}{\rho_K}$, where K is a simplex, $h_{max}$ is the element diameter, aka its longest edge. $\rho_K$ is the radius of the inscribed circle, and $\alpha_2$ is a normalization factor that depends on the dimension of the simplex. For a triangle, $\alpha_2 = \frac{\sqrt{3}}{6}$. + +The aspect ratio is a measure of the quality of the simplex. The closer the aspect ratio is to 1, the better the simplex is. + +In two dimensions, a triangle is a simplex + +A simplex is always considered a connected and closed set, meaning that all the points in the simplex are connected to each other by straight line segments, and the simplex includes all of its boundary points. + +## Angle minimal et maximal + +!!! quote "Objectif" + Évaluez les angles minimaux et maximaux de chaque triangle. Les angles trop aigus ou trop obtus peuvent réduire la + qualité du maillage. + +Maximum and minimum interior angles are evaluated independently for triangles and quadrilaterals. + +Cet indicateur mesure l'angle formé par les côtés de chaque triangle du maillage. Les angles trop petits peuvent causer +des problèmes de précision, tandis que les angles trop grands peuvent causer des problèmes de stabilité numérique. Un +maillage de bonne qualité aura des angles de triangle qui sont proches de 60 degrés. + +## Distribution des sommets + +!!! quote "Objectif" + Analysez la répartition des sommets dans le maillage. Une répartition uniforme des sommets est généralement + souhaitable pour un maillage de bonne qualité. + +### Histogramme de la densité de sommets + +On peut diviser le domaine du maillage en petites zones et compter le nombre de sommets dans chaque zone. Ensuite, on +peut représenter ces données sous forme d'un histogramme de la densité de sommets. Un histogramme uniforme indique une +répartition uniforme des sommets dans le maillage. Un histogramme non uniforme indique une mauvaise répartition des +sommets dans le maillage. + +### Voronoi diagram + +This is a way to partition space into regions based on the proximity to a set of points, such as the vertices in a mesh. +The Voronoi diagram can be used to analyze the distribution of vertices by calculating the areas of the Voronoi polygons +associated with each vertex. A well-distributed mesh would have Voronoi polygons with similar areas, while a poorly +distributed mesh would have large variations in the Voronoi polygon areas. + +### Vertex quality index + +The formula for calculating the vertex quality index is: + +$$ +\frac{1}{N}\sum_{i=1}^{N} \sqrt{(x_i - \bar{x})^2 + (y_i - \bar{y})^2 + (z_i - \bar{z})^2} +$$ + + +where $N$ is the total number of vertices in the mesh, $(x_i, y_i, z_i)$ are the coordinates of the $i$-th vertex, and $(\bar{x}, \bar{y}, \bar{z})$ are the coordinates of the center of gravity of the mesh. + +## Ratio de la taille des éléments voisins + +!!! quote "Objectif" + Évaluez le rapport entre la taille des éléments voisins dans le maillage. Des ratios trop élevés ou trop faibles + peuvent indiquer une mauvaise qualité de maillage. + +The ratio of neighboring element sizes is an important measure of the quality of a mesh. It evaluates the ratio between the sizes of neighboring elements, such as triangles or quadrilaterals, in the mesh. A ratio that is too high or too low can indicate poor mesh quality and distortion in the shape of the object. + +The ratio of neighboring element sizes can be calculated by computing the ratio of the maximum size to the minimum size for each element. This can be done by dividing the maximum size of the neighboring elements by the minimum size of the neighboring elements. + +## Connectivité des sommets + +!!! quote "Objectif" + Analysez la connectivité des sommets dans le maillage. Un nombre élevé de sommets connectés à un seul sommet peut + indiquer une mauvaise qualité. + +The connectivity of the vertices in a mesh refers to the number of edges that connect a vertex to other vertices. This metric measures how well the mesh is connected and can indicate the presence of isolated or poorly connected vertices. + +## Cohérence des normales + +!!! quote "Objectif" + Vérifiez que les normales des faces adjacentes sont cohérentes et pointent dans la même direction générale. Les + inversions de normales peuvent causer des problèmes de rendu et d'ombrage + +The coherence of normals refers to the consistency of the direction of the surface normal vectors across adjacent faces in a mesh. In computer graphics, surface normals are used to determine how light interacts with the surface, and inconsistent normals can cause visual artifacts in the rendering. + +## Surface's normal vectors + +"Cohérence des normales", "angle entre les normales", and "divergence des normales" are all measures of the quality of a mesh's surface. However, they each focus on different aspects of the surface's normal vectors: + +### Cohérence des normales + +This measure checks that the normal vectors of adjacent faces are consistent and pointing in the same general direction. +Inconsistencies in normal vectors can cause rendering and shading issues. + +### Angle entre les normales + +This measure calculates the angle between the normal vectors of adjacent faces. A small angle indicates a smooth surface, +while a large angle can indicate a discontinuity or sharp edge in the surface. + +### Divergence des normales + +This measure checks for abrupt changes in the normal vectors across the surface of the mesh. High divergence can +indicate surface irregularities or singularities. + +### Résumé + +While "cohérence des normales" and "angle entre les normales" focus on the direction and angle of the normal vectors +respectively, "divergence des normales" looks for abrupt changes in the normal vectors across the surface of the mesh. + +## Normales de sommet pondérées + +!!! quote "Objectif" + Calculez les normales de sommet pondérées en fonction de l'aire des faces adjacentes. Des normales de sommet + pondérées incohérentes peuvent indiquer des problèmes de qualité du maillage. + +Weighted vertex normals are commonly used in computer graphics to produce smooth shading on curved surfaces. Each vertex normal is the average of the surface normals of all adjacent faces, weighted by the area of each face. This weighting ensures that larger faces have a greater influence on the final normal, resulting in a smoother transition between adjacent faces. + +The calculation of weighted vertex normals is straightforward, but if the mesh has poor quality (such as non-manifold edges or self-intersections), the resulting normals may be inconsistent and lead to visual artifacts in the rendered image. + +To calculate the weighted vertex normal for a vertex V, you can follow these steps: + +- Find all adjacent faces to vertex V. +- Calculate the surface normal for each adjacent face. +- Weight each surface normal by the area of its corresponding face. +- Sum the weighted surface normals. +- Normalize the sum to obtain the final vertex normal. +- Inconsistent weighted vertex normals can result from problems in the mesh geometry, such as non-manifold edges or self-intersections. + - These problems can cause faces to have overlapping or contradictory normals, leading to visual artifacts such as shading seams or incorrect lighting. Therefore, ensuring consistent and accurate weighted vertex normals is an important aspect of mesh quality assessment. + +## Gradient des normales + +!!! quote "Objectif" + Évaluez le gradient des normales des sommets voisins. Un gradient faible des normales indique un maillage plus lisse. + +The "gradient of normals" is a measure of how much the normals of neighboring vertices change in direction and magnitude. This can be computed by taking the difference between the normal vectors of neighboring vertices and computing the magnitude of the resulting vector. A low gradient of normals indicates a smoother mesh, where the normals change gradually from one vertex to another, while a high gradient of normals indicates that the mesh has abrupt changes in surface orientation. This can cause shading and rendering problems. + +The gradient of normals is an important quality metric in computer graphics and is used to evaluate the smoothness of a mesh. It is commonly used in applications such as 3D modeling, animation, and virtual reality. diff --git a/Documentation/docs/theory/optimization.md b/Documentation/docs/theory/optimization.md new file mode 100644 index 0000000000000000000000000000000000000000..e63d1d12fdfbe8e62d4d85722888a275dcb645f3 --- /dev/null +++ b/Documentation/docs/theory/optimization.md @@ -0,0 +1,10 @@ +# Optimisation + +## Mesures choisies + +Les mesures suivantes ont été choisies pour déterminer la qualité d'un mesh : + +- le taux de régularité (aspect ratio) +- l'asymétrie (skewness), calculée par l'écart d'angle normalisé +- l'angle minimum/maximum + diff --git a/Documentation/docs/theory/other.md b/Documentation/docs/theory/other.md new file mode 100644 index 0000000000000000000000000000000000000000..3cca0f641af850764f46a8fe0775413153923fbc --- /dev/null +++ b/Documentation/docs/theory/other.md @@ -0,0 +1,100 @@ +# Autre mesures de qualité + +!!! warning "Attention" + Les informations se trouvant sur cette page sont incomplètes, peuvent contenir des erreurs et/ou nécessitent une + meilleure mise en page. + +## Skewness + +Skewness is the deviation between the optimal cell size to the existing cell size. The range of skewness is between 0 +(ideal) to 1 (worst). Highly skewed cells are not preferred due to the poor accuracy they cause within the interpolated +regions. + +Il existe 2 méthodes pour calculer le niveau de *skewness*. + +### Angular Measure + +Calculation of Skewness for Triangular/Quadrilateral Elements + +The warp angle is a measure of the quality that is used in mesh generation and measures the angle between the normals of two adjacent faces. The closer the warp angle is to 0, the better the mesh is. + +For a triangle, the warp angle is defined as the angle between the normals of the two adjacent faces. + +Skew of triangular elements is calculated by finding the minimum angle between the vector from each node to the opposing mid-side, and the vector between the two adjacent mid-sides at each node of the element. + +The warp angle is a measure of the quality of the mesh. The closer the warp angle is to 0, the better the mesh is. + +Skewness= 90-min(Θ1, Θ2….. Θ6) + +where Θ1, Θ2….. Θ6 are the angles between the vectors from each node to the opposing mid-side, and the vector between the two adjacent mid-sides at each node of the element. + +For Equilateral Triangle, Θ1, Θ2….. Θ6 = 90 degree + +Hence, Skewness = 0 degree + +### Normalized angle deviation + +Calculation of Skewness for Triangular/Quadrilateral Elements + +$skewness = max[\frac{\theta_{max} - \theta_e}{180-\theta_e}, \frac{\theta_e - \theta_{min}}{\theta_e}]$ + +In the normalized angle deviation method, skewness is defined (in general) as "maximum of ratio of Angular deviation from Ideal element. + +θmax = Largest Angle in the face or cell + +θmin = Smallest Angle in the face or cell + +θe = Angle for an equi-angular face or cell + +where, θe = 60 ̊ for Equilateral Triangle and 90 ̊ for Square + +## Qualité de l'angle dièdre + +!!! quote "Objectif" + Calculez l'angle dièdre entre les faces adjacentes. Les angles dièdres trop petits ou trop grands peuvent indiquer des problèmes de qualité. + +The dihedral angle is the angle formed by the intersection of two adjacent faces in a 3D mesh. + + + +Angle between two half-planes (α, β, pale blue) in a third plane (red) which cuts the line of intersection at right angles. + +Cet indicateur mesure l'angle formé entre deux triangles adjacents. Les angles dièdres trop grands ou trop petits +peuvent causer des problèmes de stabilité numérique et de déformation. Un maillage de bonne qualité aura des angles +dièdres proches de 180 degrés. + +## Angle entre les normales + +!!! quote "Objectif" + Calculez l'angle entre les normales des faces adjacentes. Un angle faible entre les normales adjacentes indique une surface lisse, tandis qu'un angle important indique une discontinuité ou une arête vive. + +## Angle entre les normales de sommet et la normale de la face + +!!! quote "Objectif" + Mesurez l'angle entre les normales de sommet et la normale de la face associée. Un angle faible indique que les + normales de sommet et les normales de face sont bien alignées. + +## Écart-type des angles de normales + +!!! quote "Objectif" + Calculez l'écart-type des angles entre les normales des faces adjacentes. Un écart-type faible indique un maillage + lisse et régulier, tandis qu'un écart-type élevé peut indiquer des problèmes de qualité. + +Non-orthogonality is the angle between the vector connecting two adjacent cell centers and the normal of the face shared +by these cells. The range of non-orthogonality is between 0 (ideal) and 90 (worst). 0 indicates the mesh being +orthogonal. Two perfect hexes aligned with each other have non-orthogonality equal to 0. + +## Length (min) + +Minimum element lengths are calculated using one of two methods. + +The shortest edge of the element. This method is used for non-tetrahedral 3D elements. + +The shortest distance from a corner node to its opposing edge (or face, in the case of tetra elements); referred to as +"minimal normalized height". + +## Warpage + +Amount by which an element, or in the case of solid elements, an element face, deviates from being planar. Since three points define a plane, this check only applies to quads. The quad is divided into two trias along its diagonal, and the angle between the trias’ normals is measured. + +Warpage of up to five degrees is generally acceptable. diff --git a/Documentation/docs/theory/quality_threshold.md b/Documentation/docs/theory/quality_threshold.md new file mode 100644 index 0000000000000000000000000000000000000000..f4979f8c7366f1822d355627c0fafc23118b1cda --- /dev/null +++ b/Documentation/docs/theory/quality_threshold.md @@ -0,0 +1,57 @@ +### Rappel +Quality checks summary : + +1. Aspect Ratio should not go beyond 5 +2. Warp angle should not be more than 45° +3. Jacobian should not be less than 0.5 +4. Tet collapse should be greater than 0.1 + +### Table Summarised ANSYS Style + +This table is summarised and based on the ANSYS Mesh Metrics Explained article + +| Indicateur | Valeurs sans warning| Valeurs idéales | Valeurs qui peuvent causer des erreurs | +|------------|---------|-------- | -----------------| +| Angle maximal (maximum corner angle) | 20° - 165° | 60° | 179.9° | +| Skewness | 0 - 0.75 | 0 | - | +| aspect ratio | 1 - 20 | 1 | 1e6 | +| wraping factor | 0 - 5 | 0 | 7 | + + + +Parallel deviation and warping factor brick don't apply to our project as we deal with triangles and tetrahedrons only. + +### Table Summarised GB 33582 Style + +This table is based on the standard GB/T 33582-2017 General principles of structural finite element analysis for mechanical products + +| Indicateur | 2D triangles | 3D tetrahedrons | +|------------|---------|-------- | +| Angle maximal (maximum corner angle) | 20° - 120° | 20° - 120° | +| Skewness | <= 60° | <=60° | +| aspect ratio | 1 - 5 | 1 - 5 | +| wraping factor | - | - | +| Tet collapse | - | 0.1 - 1 | + +Remarque: Tet collapse is not applicable to 2D triangles. The ideal value of tet collapse is 1. The higher the value the better the quality of the tetrahedron. + + +## Valeurs acceptables in more details +[Source: ANSYS Mesh Metrics Explained](https://featips.com/2022/11/21/ansys-mesh-metrics-explained/) +### skewness and cell quality +| value of skewness | cell quality | +|-------------------|--------------| +| 0.0 - 0.25 | excellent | +| 0.25 - 0.5 | good | +| 0.5 - 0.75 | fair | +| 0.75 - 0.9 | poor | +| 0.9 - <1.0 | very poor | +| 1.0 | degenerate | +| >1.0 | invalid | + + + +### Warping factor + + +This factor measures if the shell is on the same plane or not. If 0 then yes, if not 0 then warped. The bigger the value of warping factor the more warped the shell is. The highest acceptable value is 5. There would be calculation errors if the value is higher than 7. diff --git a/Documentation/docs/theory/references.md b/Documentation/docs/theory/references.md new file mode 100644 index 0000000000000000000000000000000000000000..48f25b5030e6bf434b8b804811d494a1f5fb2c20 --- /dev/null +++ b/Documentation/docs/theory/references.md @@ -0,0 +1,10 @@ +# Ressources + +- [What is a mesh?](https://www.simscale.com/docs/simwiki/preprocessing/what-is-a-mesh/) +- [Mesh quality](https://www.simscale.com/docs/simulation-setup/meshing/mesh-quality/) +- [Determining mesh quality](https://resources.system-analysis.cadence.com/blog/msa2022-determining-mesh-quality-and-accuracy-parameters) +- Mesh Generation: Application to Finite Elements, by Pascal Jean Frey, Paul L. George +- [Aspect Ratio](https://docs.salome-platform.org/8/gui/SMESH/aspect_ratio.html) +- [Element Quality Check](https://www.youtube.com/embed/_No2IKmMSXM) +- [Mesh quality parameters](https://www.engmorph.com/mesh-quality-parameters) +- [ANSYS Mesh Metrics Explained](https://featips.com/2022/11/21/ansys-mesh-metrics-explained/) diff --git a/Documentation/example_doc/file_management.md b/Documentation/example_doc/file_management.md new file mode 100644 index 0000000000000000000000000000000000000000..e381c031bf8ed1e47e88a8694b20e62ae8a052b4 --- /dev/null +++ b/Documentation/example_doc/file_management.md @@ -0,0 +1,100 @@ +# Gestion des fichiers + +Cette section explique comment le projet gère les fichiers reçus par des requêtes. + +Dans le fichier `actc/settings.py`, la variable +[MEDIA_ROOT](https://docs.djangoproject.com/en/4.1/ref/settings/#media-url) permet de définir le chemin où les fichiers +sont stockés : + +```python +MEDIA_ROOT = BASE_DIR / 'media/' # (1)! +``` + +1. `BASE_DIR` représente le premier dossier `actc/` qui contient le projet + +Dans le cas de notre projet, les fichiers seront ainsi stockés dans `actc/media/`. + + +## Verification du format + +Notre projet doit convertir des fichiers dans divers formats. Avant d'effectuer ces conversions il est nécessaire de +vérifier le format des fichiers que le serveur reçoit des utilisateurs. + +La vérification du fichier s'effectue à l'aide de la librairie `python-magic`. + +```python linenums="1" title="actc/converter.py" hl_lines="9" +import magic +from django.core.files.uploadedfile import UploadedFile + +def file_mime_type_verification( + file: UploadedFile, + expected_mime_type: str = 'text/plain' +) -> bool: + + mime_type: str = magic.from_buffer(file.read(), mime=True) # (1)! + if mime_type != expected_mime_type: + return False + + return True +``` + +1. L'utilisation de `file.read()` et de `magic.from_buffer()` nous évite de créer localement le fichier reçu pour la +vérification de son *mime type*. + +La méthode ci-dessus permet de déterminer le type du fichier passé en paramètre et de stocker le résultat dans la +variable "mime_type". Si le *mime type* du fichier correspond bien au type attendu (par défaut `text/plain`) on retourne +vrai sinon faux. + + +## Sauvegarde et suppression + +La sauvegarde de fichier s'effectue à l'aide de la classe `DefaultStorage` de +[Django](https://docs.djangoproject.com/en/4.1/topics/files/#storage-objects) avec la méthode `save()`. + +Cette méthode prends 2 paramètres : le nom du fichier et un objet `File`. Les fichiers reçus par une requête POST sont +de type `UploadedFile`. + +Pour éviter d'écraser des fichiers existants, chaque fichier doit être nommé en générant un +[UUID](https://docs.python.org/3/library/uuid.html)[^1] aléatoire. + +[^1]: Universally unique identifier + +```python linenums="1" title="Exemple de sauvegarde de fichier" +import uuid +from django.core.files.storage import default_storage + +def saveFile(file: UploadedFile) -> None: + filename = str(uuid.uuid4()) + default_storage.save(filename, file) +``` + +!!! note + + Dans le cadre de ce projet, la création de certains fichiers s'effectue au travers de librairies externes à Django. + Faites bien attention à définir correctement le chemin où le fichier doit être créé (généralement dans le dossier + `media/`). + +Pour supprimer un fichier, il suffit d'utiliser la méthode `delete()` : + +```python +default_storage.delete(filename) +``` + + +## Récupérer un fichier sauvegardé + +La classe [FileSystemStorage](https://docs.djangoproject.com/en/4.1/ref/files/storage/#the-filesystemstorage-class) +permet de récupérer le chemin du dossier qui stocke les fichiers sauvegardés. Ce chemin est stocké dans l'attribut +`location`. + +En combinant cette attribut avec la classe [PurePath](https://docs.python.org/3.8/library/pathlib.html#pathlib.PurePath) +de la librairie `pathlib` il est possible de reconstruire le chemin complet d'un fichier sauvegardé. + +```python linenums="1" hl_lines="5" +from pathlib import PurePath +from django.core.files.storage import FileSystemStorage + +storage = FileSystemStorage() +filepath = str(PurePath(storage.location, 'my-file-name')) +# /path/to/project/actc/media/my-file-name +``` diff --git a/Documentation/example_doc/index.md b/Documentation/example_doc/index.md new file mode 100644 index 0000000000000000000000000000000000000000..475a636b934b3988c339d78fd02a36990c1f0f38 --- /dev/null +++ b/Documentation/example_doc/index.md @@ -0,0 +1,90 @@ +# Backend + +Cette page contient la documentation concernant la partie backend du projet. + +Le framework [Django](https://www.djangoproject.com/) est utilisé pour le backend du projet. + + +## Installation + +La marche à suivre pour l'installation et la mise en place du projet est disponible sur le +[gitlab](https://gitedu.hesge.ch/in-code-we-trust/backend/-/blob/main/README.md#installation). + + +## Projet vs application + +Dans le cadre du framework Django, il est important de faire la différence entre les termes *projets* et *applications*. + +Un projet contient plusieurs applications, une application peut être utilisée dans plusieurs projets. + + +### Ajouter une application au projet + +Pour qu'un projet puisse utiliser une application, il faut ajouter sa *classe de configuration* dans la liste +`INSTALLED_APPS` se trouvant dans le fichier `actc/settings.py`. + +- La *classe de configuration* se trouve dans le fichier `<app_name>/apps.py` + +```python title="actc/settings.py" +INSTALLED_APPS = [ + 'mesh_process.apps.MeshProcessConfig', # notre application + # les autres applications... +] +``` + + +## Structure du projet + +Le premier dossier `actc` représente notre projet Django. Tous les chemins indiqués dans cette documentation commencent +à la racine de ce dernier.[^1] + +Ce dossier contient des sous-dossiers représentant diverses applications : + +- [mesh_process/](mesh_process) : Conversion des données paramétriques CAO[^2] en données maillées + +[^1]: Lorsqu'un nom de fichier est mentionné sans chemin cela signifie que ce dernier se trouve à la racine du dépôt +git, c'est-à-dire dans le dossier parent du (premier) dossier `actc` + +[^2]: Conception assistée par ordinateur (en anglais, *computer aided design* ou *CAD*). + + +## Dépendances du projet + +Notre projet nécessite diverses dépendances pour fonctionner. Ces dépendances sont définies dans les fichiers +[environment.yml](https://gitedu.hesge.ch/in-code-we-trust/backend/-/blob/main/environment.yml), +[requirements.txt](https://gitedu.hesge.ch/in-code-we-trust/backend/-/blob/main/requirements.txt) et +[additionnal-requirements.txt](https://gitedu.hesge.ch/in-code-we-trust/backend/-/blob/main/additionnal-requirements.txt). + +Cette section liste les dépendances principales du projet, c'est-à-dire celles qui sont directement utilisées dans le +code. + + +### Environnement conda + +Lors de l'installation de notre environnement conda, les dépendances suivantes sont installées : + +```yaml title="environment.yml" hl_lines="4" +# ... +dependencies: + - python=3.9 + - pythonocc-core=7.7.0 + - libmagic=5.39 # Cette dépendance n'est pas disponible sur Windows. +``` + +La dépendance principale du projet est [pythonocc-core](https://anaconda.org/conda-forge/pythonocc-core). N'étant pas +disponible sur [PyPI](https://pypi.org/) elle nous contraint à utiliser conda afin d'être installée. + +!!! note + `libmagic` est ajoutée lors de la création de l'environnement conda afin d'assurer le fonctionnement de + `python-magic` qui en a besoin mais qui ne l'installera pas automatiquement. + +!!! tip "Astuce" + Si vous souhaitez connaître l'arbre des dépendances des paquets installées, vous pouvez utiliser + [pipdeptree](https://pypi.org/project/pipdeptree/). + + +## Références + +* [Django documentation](https://docs.djangoproject.com/en/4.1/) +* [Open CASCADE Technology - STEP Translator](https://dev.opencascade.org/doc/overview/html/occt_user_guides__step.html#occt_step_2_3) +* [pythonocc-core Extend](https://github.com/tpaviot/pythonocc-core/blob/master/src/Extend/DataExchange.py) diff --git a/Documentation/example_doc/logging.md b/Documentation/example_doc/logging.md new file mode 100644 index 0000000000000000000000000000000000000000..58a8285fff486a5d22b5d70cfa56b9e42d7cb75b --- /dev/null +++ b/Documentation/example_doc/logging.md @@ -0,0 +1,214 @@ +# Logging + +Django utilise et étend le module [logging](https://docs.python.org/3/library/logging.html#module-logging) de python. + +Ce document n'explique que les points essentiels pour notre projet. Pour les explications détaillées, redirigez-vous +vers les liens en [références](#references). + + +## Log level + +Chaque message d'un log possède un niveau qui définit le degré de gravité du message : + +* **DEBUG**: information système de bas niveau à des fins de débogage. +* **INFO**: information système générale. +* **WARNING**: information décrivant la présence d’un problème mineur. +* **ERROR**: information décrivant la présence d’un problème majeur. +* **CRITICAL**: information décrivant la présence d’un problème critique. + + +## Configuration + +La configuration du logger se fait exclusivement dans le fichier +[actc/settings.py](https://gitedu.hesge.ch/in-code-we-trust/backend/-/blob/main/actc/actc/settings.py). + + +### loggers + +Le projet définit les *loggers* suivant : + +```python hl_lines="3 8 13 18" +# ... +'loggers': { + 'django': { + 'handlers': ['actc'], + 'level': 'INFO', + 'propagate': False, + }, + 'mesh_process': { + 'handlers': ['actc', 'mesh_process'], + 'level': 'INFO', + 'propagate': False, + }, + 'mesh_process.step_translator': { + 'handlers': ['conversion_file'], + 'level': 'INFO', + 'propagate': True, + }, + 'mesh_process.quality': { + 'handlers': ['mesh_quality'], + 'level': 'DEBUG', + 'propagate': True, + }, +}, +# ... +``` + +* `django` : Envoie les messages de niveau `INFO` à l'*handler* `actc`. +* `mesh_process` : Envoie les messages de niveau `INFO` aux *handlers* `actc` et `mesh_process`. +* `mesh_process.step_translator` : Envoie les messages de niveau `INFO` à l'*handler* `conversion_file`. +* `mesh_process.quality` : Envoie les messages de niveau `DEBUG` à l'*handler* `mesh_quality`. + + +Puisque l'attribue `propagate` de `mesh_process.step_translator` et `mesh_process.quality` est `True`, les messages sont +égalements transmis au logger `mesh_process`. + + +### handlers + +Le projet définit les *handlers* suivant : + +```python hl_lines="3 11 17 23" +# ... +'handlers': { + 'actc': { + 'level': 'DEBUG' if DEBUG else 'WARNING', + 'class': 'logging.handlers.RotatingFileHandler', + 'filename': BASE_DIR / 'logs' / 'actc.log', + 'formatter': 'verbose', + 'maxBytes': 1048576, # 1 MB + 'backupCount': 3 + }, + 'mesh_process': { + 'level': 'INFO', + 'class': 'logging.FileHandler', + 'filename': BASE_DIR / 'logs' / 'mesh_process.log', + 'formatter': 'verbose' + }, + 'conversion_file': { + 'level': 'INFO', + 'class': 'logging.FileHandler', + 'filename': BASE_DIR / 'logs' / 'conversion.log', + 'formatter': 'simple' + }, + 'mesh_quality': { + 'level': 'DEBUG' if DEBUG else 'WARNING', + 'class': 'logging.FileHandler', + 'filename': BASE_DIR / 'logs' / 'quality.log', + 'formatter': 'simple', + }, +}, +# ... +``` + +Les 3 handlers du projet créent un fichier de log pour enregistrer les différents messages détectés. + +!!! info "actc" + + En production, cet *handler* gère des messages d'un niveau plus élevé qu'en développement (DEBUG). + + Il s'agit de l'*handler* qui crée le fichier de log principal du projet, il sera ainsi le plus volumineux. La classe + `logging.handlers.RotatingFileHandler` est donc utilisée afin de définir une taille de fichier maximal et un nombre de + fichier de *backup*. + +!!! info "mesh_process" + + Il s'agit de l'*handler* qui crée le fichier de log principal de l'application *mesh process*. Il traite les + messages de niveau `INFO` ou supérieur. + +!!! info "conversion_file" + + Il s'agit de l'*handler* qui crée le fichier de log enregistrant les événements des conversions de fichiers. Cet + *handler* sert principalement à enregistrer les conversions effectuées, ainsi il traite les messages de niveau `INFO` et + supérieur en utilisant un format simple. + +!!! info "mesh_quality" + + Il s'agit de l'*handler* qui crée le fichier de log enregistrant les événements qui mesurent la qualité d'un *mesh*. + + +### formatters + +Le projet définit les *formatters* suivant : + +```python hl_lines="3 7" +# ... +'formatters': { + 'verbose': { + 'format': '[{levelname}] {asctime} {name} {module} {message}', + 'style': '{', + }, + 'simple': { + 'format': '[{levelname}] {asctime} {message}', + 'style': '{', + }, +}, +# ... +``` + +Le *formatter* `verbose` ajoute simplement le nom du fichier et le module qui a produit le message. + + +### filters + +Le projet n'utilise pas de *filters* pour le traitement des logs. + + +### Time zone + +L'heure des messages indiqué dans les logs va dépendre de la *time zone* définie. + +```python +TIME_ZONE = 'Europe/Zurich' +``` + +## Utilisation + +Pour crée un message de log, il faut ajouter les lignes suivantes en haut du fichier : + +```python +import logging + +logger = logging.getLogger(__name__) +``` + +Il est ensuite possible de faire `logger.<log_level>(<message>)` afin de créer votre message. + +Exemple : + +```python +logger.info(f"STEP to STL conversion has successfully created the file '{output_filename}'." ) +``` + +produira le message suivant : + +```log +[INFO] 2023-03-21 13:49:42,875 STEP to STL conversion has successfully created the file '0d686ff9-9ea9-44cc-8e59-124c90b97fea.stl'. +``` + +## Stockage + +Les logs sont stockées dans le dossier [logs](https://gitedu.hesge.ch/in-code-we-trust/backend/-/tree/main/actc/logs) : + +* **actc.log** (niveau: `DEBUG` en développement, `WARNING` en production) + +Le fichier qui stocke les événements globaux du projet *ACTC*. + +* **mesh_process.log** (niveau: `WARNING`) + +Le fichier qui stocke les événements globaux de l'application *mesh process*. + +* **conversion.log** (niveau: `INFO`) + +Le fichier qui stocke les événements des conversions effectuées par l'application *mesh process*. + +* **quality.log** (niveau: `DEBUG` en développement, `WARNING` en production) + +Le fichier qui stocke les événements des analyses de qualités des meshs effectuées par l'application *mesh process*. + +## Références + +* [Django logging overview](https://docs.djangoproject.com/en/4.1/topics/logging/) +* [Django logging reference](https://docs.djangoproject.com/en/4.1/ref/logging/) +* [Django - How to configure and use logging](https://docs.djangoproject.com/en/4.1/howto/logging/#logging-how-to) +* [logging - Logging facility for Python](https://docs.python.org/3/library/logging.html#module-logging) diff --git a/Documentation/example_doc/mesh_process.md b/Documentation/example_doc/mesh_process.md new file mode 100644 index 0000000000000000000000000000000000000000..604bf9e70ac8b275257abb60bd894c1c4d3145c9 --- /dev/null +++ b/Documentation/example_doc/mesh_process.md @@ -0,0 +1,273 @@ +# App: mesh_process + +L'application **mesh_process** est responsable de la conversion et l'optimisation des fichiers STEP. + +## Formats de fichiers + +Le but de notre application est de produire, à partir d'un fichier STEP, un format de fichier permettant d'afficher des +composants 3D sur un navigateur web. + +Pour ce faire, il faut effectuer diverses conversions dans des formats de fichiers différents. + +### Fichier STEP + +Les fichiers STEP (`.stp`, `.step`, `.stpnc`, `.p21`, `.210`) ou +[ISO 10303-21](https://en.wikipedia.org/wiki/ISO_10303-21) sont les fichiers d'entrées de notre conversion. + +Il s'agit de fichier ayant une structure ASCII, un exemple de leur contenu est disponible sur +[wikipedia](https://en.wikipedia.org/wiki/ISO_10303-21#Example). + + +### Fichier STL + +Les fichiers [STL](https://en.wikipedia.org/wiki/STL_(file_format)) (`.stl`) sont des fichiers ayant soit une structure +ASCII, soit une structure binaire. + + +### Fichier OBJ + +Les fichiers OBJ (`.obj`), aussi appelé [Wavefront .obj file](https://en.wikipedia.org/wiki/Wavefront_.obj_file), sont +les fichiers de sorties de notre conversion. + + +## Processus de conversion + +La conversion des fichiers STEP se déroule ainsi : + +1. fichier STEP :material-arrow-right: fichier STL +2. fichier STL :material-arrow-right: fichier OBJ + +!!! info + La conversion de STEP à STL s'effectue à l'aide d'open CASCADE + + +## Prérequis + +Lorsque le serveur reçoit un fichier STEP à une URL définit, ce dernier va effectuer une conversion dans le format +définit par l'URL. + +Actuellement 2 URLs de conversions sont disponibles : + +* `mesh-process/convert/step/to/stl` qui retourne un fichier STL +* `mesh-process/convert/step/to/obj` qui retourne un fichier OBJ + +!!! warning "Attention" + + Les 2 URLs doivent recevoir une requête POST ayant un formulaire contenant un fichier STEP + + +### Classe de formulaire + +Nous devons définir une classe (`forms.Form`) dans `mesh_process/forms.py` qui correspond au formulaire attendu par le +serveur pour pouvoire effectuer les différentes conversions. Cela permet d'assurer qu'une URL reçoit un formulaire +valide pour le traitement à effectuer. + +Pour nos conversions, nous devons créer une classe qui doit posséder un attribut `FileField` qui représente le fichier +à convertir. + +```python linenums="1" title="mesh_process/forms.py" +from django import forms + +class UploadFileForm(forms.Form): + file = forms.FileField() +``` +*Pour plus d'information sur le fonctionnement, voir la* +*[documentation de Django](https://docs.djangoproject.com/en/4.1/topics/http/file-uploads/#basic-file-uploads).* + + +### Mise en place des vues + +Les vues sont crées via des méthodes dans le fichier `mesh_process/views.py`. + +Cette vue ne doit effectuer la conversion que lorsque le serveur reçoit une requête POST avec un formulaire valide +(qui contient le fichier à convertir). + +```python linenums="1" title="mesh_process/views.py" +from mesh_process.forms import UploadFileForm +from mesh_process.step_translator import convert_step_to_stl + +def step_to_obj(request): + if request.method != 'POST': + # Bad request method, return response with HTTP 400 code... + + form = UploadFileForm(request.POST, request.FILES) + + if not form.is_valid(): + # Form invalid, return response with HTTP 400 code... + + converted_file_path = convert_step_to_obj(request.FILES['file']) + if converted_file_pathis None: + # Conversion failed, return reponse with HTTP 500 code... + + return upload_file(converted_file_path) +``` + +Il faut ensuite définir les URL des vues dans le fichier `mesh_process/urls.py` + +```python title="mesh_process/urls.py" +urlpatterns = [ + # ... + path('convert/step/to/stl', views.step_to_stl, name='step_to_stl'), + path('convert/step/to/obj', views.step_to_obj, name='step_to_obj'), + # ... +] +``` + + +## Conversion STEP à STL + +### Lecture du STEP + +La lecture du fichier STEP permet de récupérer une "forme" (*shape*) qui peut être convertie en fichier STL. + +La méthode suivante effectue la lecture du fichier STEP : + +```python title="mesh_process/step_translator.py" +read_step(input_file: str, verbose: bool = True): + """Translate a STEP file to a shape. + + Args: + input_file (str): Path to the STEP file. + verbose (bool, optional): When True, displays information messages. Defaults to True. + + Raises: + FileNotFoundError: The input_file doesn't exist. + AssertionError: An error has occurred while reading the file + + Returns: + A shape corresponding to the STEP file + """ +``` + +Pour que cette lecture fonctionne, il est primordiale d'effectuer les opérations suivantes : + +* Charger le fichier STEP : + +```python +step_reader = STEPControl_Reader() +status = step_reader.ReadFile(input_file) +``` + +!!! warning "Attention" + + Pour éviter un crash du serveur, il ne faut poursuivre le traitement que si `status` correspond à + [IFSelect_RetDone](https://dev.opencascade.org/doc/occt-7.6.0/refman/html/_i_f_select___return_status_8hxx.html). + +* Effectuer la traduction (*translation*) du fichier STEP : + +```python +step_reader.TransferRoot() +``` + +* Récupérer la *shape* du résultat de la traduction : + +```python +shape = step_reader.Shape() +return shape +``` + +### Écriture du fichier STL + +Une fois la *shape* du fichier STEP récupéré, il est possible de créer le fichier `.stl` pour finaliser la conversion. + +La méthode suivante effectue l'écriture du fichier `.stl` : + +```python title="mesh_process/step_translator.py" +def write_stl_from_step(step_shape, output_file: str, ascii_mode: bool = True, + linear_deflection=0.9, angular_deflection=0.5, isRelative=False, isInParallel=True): + """Create a STL file from a STEP shape. + + Args: + step_shape: The shape used to create the STL file. + output_file (str): The STL filepath. + ascii_mode (bool, optional): Set the writer mode (True for ASCII, False for binary). Defaults to True. + linear_deflection (float, optional): Defaults to 0.9. + angular_deflection (float, optional): Defaults to 0.5. + isRelative (bool, optional): Defaults to False. + isInParallel (bool, optional): Defaults to True. + + Raises: + AssertionError: The write failed + """ +``` + +Pour que cette écriture fonctionne, il est primordiale d'effectuer les opérations suivantes : + +* La forme doit être explicitement maillée + +```python +mesh = BRepMesh_IncrementalMesh(step_shape, linear_deflection, isRelative, angular_deflection, isInParallel) +mesh.Perform() +``` + +* Définir le mode d'écriture + +```python +stl_writer = StlAPI_Writer() +stl_writer.SetASCIIMode(ascii_mode) +``` + +* Effectuer la conversion + +```python +stl_writer.Write(step_shape, output_file) +``` + +La méthode produit un fichier `.stl` au chemin défini par `output_file`. + + +## Conversion STL à OBJ + +TODO + + +## Upload des fichiers + + +### Envoi via JSON + +À la fin de la conversion du fichier, le serveur doit l'envoyer à l'utilisateur sous la forme d'une `HttpResponse` qui +contient une `JsonResponse`. + +```python title="mesh_process/views.py" linenums="1" hl_lines="9" +def upload_file(file_path: str, quality_before=None, quality_after=None): + # ... + with open(file_path, "r") as file: + data = { + "obj_content": file.read(), + # ... + } + response = JsonResponse(data) + return HttpResponse(response, content_type="application/json") +``` + +Le code ci-dessus crée un objet json qui contient le contenu de notre fichier converti. Le format json nous permet de +transmettre d'autres données au client tel que l'analyse de qualité du fichier. + + +### Envoi direct du fichier + +!!! warning "Obsolète" + + Bien que le code ci-dessous fonctionne, cette manière de faire est obsolète lors des conversions de fichiers depuis + l'ajout des indicateurs de qualité dans la version [2.0.0](https://gitedu.hesge.ch/in-code-we-trust/backend/-/tree/v2.0.0?ref_type=tags) du projet. + + Nous préférons envoyé du json au client qui permet de joindre d'autres informations en plus du fichier. + +À la fin de la conversion du fichier, le serveur doit l'envoyer à l'utilisateur sous la forme d'une `HttpResponse`. + +```python title="mesh_process/views.py" linenums="1" hl_lines="4" +def upload_file(file_path): + with open(file_path, 'rb') as file: # (1)! + response = HttpResponse(file.read(), content_type='text/plain') + content = 'attachment; filename=' + os.path.basename(file_path) + response['Content-Disposition'] = content + return response +``` + +1. Le fichier doit être ouvert en mode binaire (`b`) + + On ajoute ensuite le contenu du fichier dans la réponse avec `file.read()` + +Le `content` définit l'en-tête de la réponse et spécifie que le fichier doit être téléchargé (`attachment;`), `basename` +permet de renvoyer le nom de fichier à partir du répertoire complet. diff --git a/Documentation/example_doc/migrations.md b/Documentation/example_doc/migrations.md new file mode 100644 index 0000000000000000000000000000000000000000..412ca6a14540650f068e25d3fe0f536e6a518241 --- /dev/null +++ b/Documentation/example_doc/migrations.md @@ -0,0 +1,13 @@ +# Migration + +La commande suivante permet de créer les migrations pour l'application `mesh_process` : + +```text +python manage.py makemigrations mesh_process +``` + +Il est ensuite possible de créer les tables dans la base de données : + +```text +python manage.py migrate +``` diff --git a/Documentation/example_doc/models.md b/Documentation/example_doc/models.md new file mode 100644 index 0000000000000000000000000000000000000000..6eeafdcff2c6f90228ba327c269f821e9d43519a --- /dev/null +++ b/Documentation/example_doc/models.md @@ -0,0 +1,24 @@ +# Modèles + +Les modèles permettent de représenter les objets que l'on stocke dans la base de données. +Ils sont défininis dans le fichier `mesh_process/models`. + +Voici un exemple de création de modèles : + +```python linenums="1" +from django.db import models + + +class Question(models.Model): + question_text = models.CharField(max_length=200) + pub_date = models.DateTimeField('date published') + + +class Choice(models.Model): + question = models.ForeignKey(Question, on_delete=models.CASCADE) + choice_text = models.CharField(max_length=200) + votes = models.IntegerField(default=0) + +``` + +TODO: expliquer les points essentiels, éventuellement créer une section qui présente les configurations particulières. diff --git a/Documentation/example_doc/prod_config.md b/Documentation/example_doc/prod_config.md new file mode 100644 index 0000000000000000000000000000000000000000..14ca17c34fd27181a02d2168a4f53526dc0384ba --- /dev/null +++ b/Documentation/example_doc/prod_config.md @@ -0,0 +1,127 @@ +# Configuration + +Le déploiement du serveur se fait à l'aide d'une image Docker. Cette page explique les points clefs permettant la +création de cette image. + + +## L'environnement conda + +La création de cette environnement s'effectue à partir du fichier +[environment.yml](https://gitedu.hesge.ch/in-code-we-trust/backend/-/blob/main/environment.yml) : + +```yaml linenums="1" title="environment.yml" +name: pyoccenv +channels: + - conda-forge +dependencies: + - python=3.9 + - pythonocc-core=7.7.0 + - libmagic=5.39 # (1)! +``` + +1. Il est nécessaire que cette librairie soit installée lors de la création de l'environnement conda car elle est + manquante dans l'image `continuumio/miniconda3` et car elle n'est pas installée directement par le package python + `python-magic` qui en a besoin. + + +## Dockerfile + +La création de l'image est effectuée à l'aide du fichier +[Dockerfile](https://gitedu.hesge.ch/in-code-we-trust/backend/-/blob/main/Dockerfile) suivant : + +```Dockerfile linenums="1" title="Dockerfile" +# syntax=docker/dockerfile:1 +FROM continuumio/miniconda3 + +# Copy the Django project, install the environement and dependencies (1) +COPY . /srv/ +RUN conda init bash && \ + . /root/.bashrc && \ + conda env create -f /srv/environment.yml && \ + conda clean -afy && \ + conda activate pyoccenv && \ + python -m pip install -r /srv/requirements.txt + +# Start the server +WORKDIR /srv/actc +CMD conda init bash && \ + . /root/.bashrc && \ + conda activate pyoccenv && \ + python manage.py runserver 0.0.0.0:2000 + +EXPOSE 2000 +``` + +1. Le fichier `environment.yml` est utilisé pour créer l'environnement virtuel conda. + + Le fichier `requirements.txt` est utilisé pour installer les diverses dépendances python du projet. + + La commande `conda clean -afy` permet de réduire considérablement la taille de l'image Docker (~1,3 Go en moins). + +!!! note + Il est possible de copier sereinement l'intégralité du répertoire (avec `COPY .`) sans risque grâce au fichier + [.dockerignore](https://gitedu.hesge.ch/in-code-we-trust/backend/-/blob/main/.dockerignore) qui exclus les fichiers + et répertoires indésirables à notre image. + + +Il est important de préciser que pour pouvoir activer l'environnement virtuel conda, il faut initialiser le terminal +avec `conda init bash`. Hors pour que ce changement soit effectuée, il faut relancer le terminal. + +Lancer plusieurs fois la commande `RUN` de docker ne semble malheureusement pas permettre de relancer le terminal, pire +cela semble même "annuler" l'initialisation du terminal. + +Ainsi, les 2 points ci-dessus font que nous devons : + +- Utiliser qu'une seule commande `RUN` lors de la création de l'environnement et le démarrage du serveur. +- Utiliser `&& \` pour exécuter plusieurs commandes à la suite et sur une ligne différente. +- Utiliser la commande [dot](https://pubs.opengroup.org/onlinepubs/009695399/utilities/dot.html) pour relancer le +terminal avec `. /root.bashrc` + + +## Déploiement + +Se rendre sur le serveur [wetty](https://silentpc.ciuj-kune.org/wetty) et cloner le projet + +```bash +git clone ssh://git@ssh.hesge.ch:10572/in-code-we-trust/backend.git +cd backend +``` + + +### Variables d'environnement + +Les variables d'environnements sont créés automatiquement à partir d'un fichier `.env` et de +[python-dotenv](https://github.com/theskumar/python-dotenv). + +1. Créer une copie du fichier `.env.example` dans un nouveau fichier `.env`. + +2. Créer une clef de sécurité secrète. Pour cela il faut ouvrir une console interactive python et exécuter le code +suivant : + + ```python + import secrets + print(secrets.token_urlsafe(40)) + ``` + +3. Dans le fichier `.env`, remplacer la valeur de la variable `DJANGO_SECRET_KEY` par la clef générée précédemment. + +4. Modifiez ensuite la valeur de la variable `DJANGO_ENABLE_SECURITY` par `'yes'`. + + +### Création de l'image + +Depuis la racine du projet `backend`, la commande suivante permet de créer l'image : + +```text +docker build -t icwt-django . +``` + + +### Démarrer le container + +Une fois l'image créé, il est possible de démarer un *container* à partir de cette dernière à l'aide de la commande +suivante : + +```text +docker run -d -p 2000:2000 icwt-django +``` diff --git a/Documentation/example_doc/rest_framework.md b/Documentation/example_doc/rest_framework.md new file mode 100644 index 0000000000000000000000000000000000000000..80a24808f04d5ee5ddb29ebb1d0b2fedfa8cae98 --- /dev/null +++ b/Documentation/example_doc/rest_framework.md @@ -0,0 +1,49 @@ +# REST framework + +Dans le cadre de notre projet, l'utilisation de base des vues de Django est limitée étant donné que la partie frontend +du projet est gérée par une autre technologie (Ionic/Angular). + +Ainsi, une API REST est mise en place à l'aide du [Django REST framework](https://www.django-rest-framework.org/) + + +## Configuration + +Il faut ajouter `rest_framework` dans la liste `INSTALLED_APPS` se trouvant dans le fichier `actc/settings.py` : + +```python title="actc/settings.py" +INSTALLED_APPS = [ + # ... + 'rest_framework', +] +``` + +La mise en place des routes API s'effectue dans le fichier `actc/urls.py` : + +```python linenums="1" hl_lines="4-6 9" title="actc/urls.py" +from rest_framework import routers +from mesh_process import views + +router = routers.DefaultRouter() # (1) +router.register(r'vector3D', views.Vector3DViewSet) # (2) +router.register(r'vertex', views.VertexViewSet) + +urlpatterns = [ + path('', include(router.urls)), # (3) + # ... +] +``` + +1. Initialise le routeur + +2. Ajoute un `ModelViewSet` au routeur + + Il s'agit des différentes classes définies dans le fichier `mesh_process/views.py` + +3. Crée un routage automatique de notre API + + +## Endpoints + +TODO: tableau récapitulatif des différents *endpoints* de l'application + +note: faire le tableau dans un autre fichier serait peut-être plus judicieux diff --git a/Documentation/example_doc/serialization.md b/Documentation/example_doc/serialization.md new file mode 100644 index 0000000000000000000000000000000000000000..586ed368426c0fae3889c4201660ae68f1acf2b3 --- /dev/null +++ b/Documentation/example_doc/serialization.md @@ -0,0 +1,26 @@ +# Sérialisation + +La sérialisation nous permet de transformer nos différents modèles en instance JSON afin de pouvoir les transférer et +utiliser facilement. + +Notre sérialisation est configurée dans le fichier `mesh_process/serializers.py` : + +```python +from mesh_process.models import Vector3D, Vertex +from rest_framework import serializers + + +class Vector3DSerializer(serializers.HyperlinkedModelSerializer): + class Meta: + model = Vector3D + fields = ['x', 'y', 'z'] + + +class VertexSerializer(serializers.HyperlinkedModelSerializer): + class Meta: + model = Vertex + fields = ['position3D'] + +``` + +TODO: n'expliquer que les points essentiels diff --git a/Documentation/example_doc/view_management.md b/Documentation/example_doc/view_management.md new file mode 100644 index 0000000000000000000000000000000000000000..b59e85401b346242e000dbbe75e206face3816ff --- /dev/null +++ b/Documentation/example_doc/view_management.md @@ -0,0 +1,51 @@ +# Gestion des vues et URLs + +Le fichier `views.py`, se trouvant dans chaque dossier d'application, représente les différentes vues d'une application. + +Le fichier `actc/urls.py` configure toutes les vues du projet et des applications qui le compose. + + +## Création des vues + +Le code ci-dessous représente la vue la plus simple possible : + +```python linenums="1" +from django.http import HttpResponse + + +def index(request): + return HttpResponse("Hello, world. You're at the app index.") +``` + + +## Configuration des URLS + +Pour qu'une vue puisse être appelée, il est nécessaire que chaque application ait un fichier nommé `urls.py` qui contient un code similaire à ceci : + +```python linenums="1" +from django.urls import path + +from . import views + +urlpatterns = [ + path('', views.index, name='index'), +] +``` + +Le fichier `actc/urls.py` de notre projet doit ensuite inclure les URLS de chaque application. + + +```python linenums="1" title="actc/urls.py" hl_lines="8" +from django.contrib import admin +from django.urls import include, path + +# ... + +urlpatterns = [ + # ... + path('mesh-process/', include('mesh_process.urls')), + path('admin/', admin.site.urls), + # ... +] +``` + diff --git a/Documentation/mkdocs.yml b/Documentation/mkdocs.yml new file mode 100644 index 0000000000000000000000000000000000000000..3d51c732d5e74c422cfdcead3ed71459d79ef775 --- /dev/null +++ b/Documentation/mkdocs.yml @@ -0,0 +1,151 @@ +site_name: In Code We Trust +repo_url: https://gitedu.hesge.ch/in-code-we-trust/documentation +repo_name: GitLab +edit_uri: blob/main/docs +theme: + name: material + logo: img/favicon.ico + favicon: img/favicon.ico + language: fr + icon: + admonition: + note: octicons/tag-16 + abstract: octicons/checklist-16 + info: octicons/info-16 + tip: octicons/squirrel-16 + success: octicons/check-16 + question: octicons/question-16 + warning: octicons/alert-16 + failure: octicons/x-circle-16 + danger: octicons/zap-16 + bug: octicons/bug-16 + example: octicons/beaker-16 + quote: octicons/quote-16 + palette: + # Palette toggle for light mode + - scheme: default + primary: grey + accent: light blue + toggle: + icon: material/brightness-7 + name: Switch to dark mode + + # Palette toggle for dark mode + - scheme: slate + primary: deep purple + accent: teal + toggle: + icon: material/brightness-4 + name: Switch to light mode + features: + - navigation.indexes + - navigation.tabs + - navigation.sections + - navigation.top + - navigation.footer + - header.autohide + - content.code.copy + - content.code.annotate +nav: + - But: index.md + - API: + - Introduction: + - api/index.md + - Invités: + - POST /api/v1/guests/users: 'api/user_create.md' + - POST /api/v1/guests/users/:username: 'api/user_connect.md' + - Joueurs: + - GET /api/v1/users/:username: 'api/get_user_info.md' + - Administrateurs: + - Gestion d'utilisateurs: + - GET /api/v1/admins/:admin/:admin: 'api/view_management.md' + - GET /api/v1/admins/:admin/users: api/prod_config.md + - POST /api/v1/admins/:admin/users: api/file_management.md + - PUT /api/v1/admins/:admin/users/:username: api/file_management.md + - DELETE /api/v1/admins/:admin/users/:username: api/file_management.md + - Gestion des questions: + - GET /api/v1/admins/:admin/questions: api/prod_config.md + - POST /api/v1/admins/:admin/questions: api/file_management.md + - PUT /api/v1/admins/:admin/questions/:question_id: api/file_management.md + - DELETE /api/v1/admins/:admin/questions/:question_id: api/file_management.md + - Explication de l'implémentation: + - Introduction: + - frontend/index.md + - Framework: + - frontend/ionic.md + - frontend/angular.md + - frontend/tailwindcss.md + - frontend/babylonjs.md + - Base de données: + - frontend/firebase.md + - Application: + - frontend/functionning.md + - Répartition du travail: + - Cours: + - Algorithmes avancés: theory/advanced_algorithms.md + - Géométrie algorithmique: theory/algorithmic_geometry.md + - Optimisation: + - Indicateurs de qualité: theory/indicators-and-others.md + - Autre mesures: theory/other.md + - Optimisation: theory/optimization.md + - Quality Threshold: theory/quality_threshold.md + - Références: theory/references.md + - Informations supplémentaires: + - Problèmes éventuels: + - Algorithmes avancés: theory/advanced_algorithms.md + - Géométrie algorithmique: theory/algorithmic_geometry.md + - Code provenant d'internet: + - Indicateurs de qualité: theory/indicators-and-others.md + - Autre mesures: theory/other.md + - Optimisation: theory/optimization.md + - Quality Threshold: theory/quality_threshold.md + - Références: theory/references.md + - Implémentation du projet: + - Algorithmes avancés: theory/advanced_algorithms.md + - Géométrie algorithmique: theory/algorithmic_geometry.md + - Procédure d'installation / d'utilisation: + - Problèmes éventuels: + - Algorithmes avancés: theory/advanced_algorithms.md + - Géométrie algorithmique: theory/algorithmic_geometry.md + - Code provenant d'internet: + - Indicateurs de qualité: theory/indicators-and-others.md + - Autre mesures: theory/other.md + - Optimisation: theory/optimization.md + - Quality Threshold: theory/quality_threshold.md + - Références: theory/references.md +copyright: Copyright © 2023 In Code We Trust +markdown_extensions: + - toc: + permalink: true + - pymdownx.arithmatex: + generic: true + - pymdownx.highlight: + anchor_linenums: true + line_spans: __span + pygments_lang_class: true + - attr_list + - pymdownx.emoji: + emoji_index: !!python/name:materialx.emoji.twemoji + emoji_generator: !!python/name:materialx.emoji.to_svg + - pymdownx.inlinehilite + - pymdownx.snippets + - pymdownx.superfences + - pymdownx.details + - pymdownx.caret + - pymdownx.tilde + - admonition + - tables + - footnotes + - md_in_html +plugins: + - git-revision-date-localized: + enable_creation_date: true + type: datetime + locale: fr + - search: + lang: fr + - glightbox +extra_javascript: + - javascripts/mathjax.js + - https://polyfill.io/v3/polyfill.min.js?features=es6 + - https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js diff --git a/Documentation/requirements.txt b/Documentation/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..802670cf5ab5bb30fab8b6bbebce792fe9756e8e --- /dev/null +++ b/Documentation/requirements.txt @@ -0,0 +1,31 @@ +Babel==2.12.1 +certifi==2022.12.7 +charset-normalizer==3.1.0 +click==8.1.3 +colorama==0.4.6 +ghp-import==2.1.0 +gitdb==4.0.10 +GitPython==3.1.31 +idna==3.4 +Jinja2==3.1.2 +Markdown==3.3.7 +MarkupSafe==2.1.2 +mergedeep==1.3.4 +mkdocs==1.4.2 +mkdocs-git-revision-date-localized-plugin==1.2.0 +mkdocs-glightbox==0.3.3 +mkdocs-material==9.1.4 +mkdocs-material-extensions==1.1.1 +packaging==23.0 +Pygments==2.14.0 +pymdown-extensions==9.10 +python-dateutil==2.8.2 +pytz==2023.2 +PyYAML==6.0 +pyyaml_env_tag==0.1 +regex==2023.3.23 +requests==2.28.2 +six==1.16.0 +smmap==5.0.0 +urllib3==1.26.15 +watchdog==3.0.0