1. Introduction

La fin du semestre approche, il est temps de montrer tout ce que vous avez appris et de proposer au monde entier votre première application web (webapp) ! L’objectif de ce mini-projet est d’utiliser toutes les compétences acquises lors des TP et TD précédents, afin de réaliser une application du jeu de stratégie Quoridor à peu près jouable (et observable) en multijoueur réseau.

La date de rendu est fixée au 19 avril 2023 (23h55 au plus tard).

Ce projet est à réaliser obligatoirement par groupe de deux (provenant du même demi-groupe de TP) ! Les groupes de trois ne sont autorisés que dans le cas d’un nombre d’étudiants impair.

2. Préparation

2.1. Création de votre bifurcation

Une seule fois par binôme, avant de commencer à travailler sur le projet, suivez rigoureusement les étapes suivantes :

  1. Créez une bifurcation (en anglais, fork) du Projet Quoridor.

  2. Configurez votre nouveau projet GitLab obtenu via la bifurcation de la manière suivante :

    1. Dans le menu Paramètres  Général, allez dans Visibility  Project Features  Permissions" et mettez "Project visibility" à "Private". Ainsi, vous devenez le seul utilisateur autorisé à accéder à votre code source.

    2. Toujours dans "Paramètres → Général", saisissez rigoureusement la description de projet suivante, différente pour chaque groupe de TP — consultez le tableau ci-après.

      Cette étape est très importante car elle nous permet de retrouver vos projets sur le GitLab.
    3. Dans Gestion  Membres, donnez accès à votre projet à votre enseignant de TP, avec le statut "Reporter". Pour savoir quel compte ajouter, consultez le tableau ci-après.

    4. Toujours dans Gestion  Membres, ajoutez l’autre membre de votre binôme de projet, avec le statut "Maintainer".

Si votre groupe de TP est… Vous mettez comme Description Vous ajoutez ce compte enseignant comme Membre de type Reporter

280CMI, 282LAS

projet-dl-2023-280-282

Khawla SAYEB (@ch4pjvse)

281Q

projet-dl-2023-281Q

Erwan BOUSSE (clone) (@bousse-e-clone)

281R

projet-dl-2023-281R

Yasmina DALI YOUCEF (@e22k313w)

284I

projet-dl-2023-284I

Amal TIAB (@tiab-a0)

284J

projet-dl-2023-284J

David JULIEN (@djulien)

285K

projet-dl-2023-285K

Loïc MICHEL (@michel-l-5)

285L

projet-dl-2023-285L

David JULIEN (@djulien)

286M

projet-dl-2023-286M

Amal TIAB (@tiab-a0)

286N

projet-dl-2023-286N

Matthieu Perrin (@mperrin)

289S

projet-dl-2023-289S

Loïc MICHEL (@michel-l-5)

289T

projet-dl-2023-289T

Vincent KOWALSKI (@e164695r)

Ensuite terminez de préparer votre répertoire de travail :

  1. Ouvrez le Terminal et effectuez une commande git clone appropriée pour récupérer votre bifurcation sur votre poste de travail. *Il vous est recommandé d’utiliser l’adresse SSH de votre bifurcation pour faire le clone, si vous avez au préalable configuré votre accès SSH comme expliqué dans le TP GitLab.

  2. Utilisez la commande cd pour vous rendre dans le répertoire créé par votre git clone et faites la commande npm install pour télécharger les dépendances nécessaires.

2.2. Analyse de la structure du projet

Regardez la structure du projet. Le projet est organisé en différents dossiers :

.
├── README.adoc
├── client
│   ├── script.js
│   └── style.css
├── package-lock.json
├── package.json
├── src
│   ├── main
│   │   └── ts
│   │       ├── fence-placement-validation.ts
│   │       ├── fence-placement.ts
│   │       ├── fence.ts
│   │       ├── game-board.ts
│   │       ├── game.ts
│   │       ├── main.ts
│   │       ├── movement-validation.ts
│   │       ├── pawn-movement.ts
│   │       ├── pawn.ts
│   │       ├── position.ts
│   │       ├── server.ts
│   │       ├── square.ts
│   │       └── util.ts
│   └── test
│       └── ts
│           ├── move-validation-test.spec.ts
│           └── position-test.spec.ts
├── tsconfig.json
└── views
    └── index.ejs
  • Le répertoire client contient le code Javascript qui sera exécuté sur le navigateur, ainsi que le style de la page. Vous ne devez pas modifier le contenu de ce dossier.

  • Le répertoire views contient le fichier index.ejs qui définit la page principale de l’application web. Vous n’avez pas besoin de le modifier.

  • Le répertoire src/main/ts contient le code source du serveur.

    • Dans ce dossier, vous allez modifier les fichiers move-validation.ts et fence-placement-validation.ts.

      En aucun cas vous ne devez modifier le contenu des fichiers fence-placement.ts, fence.ts, game-board.ts, game.ts, main.ts, pawn-movements.ts, pawn.ts, position.ts, server.ts, square.ts et util.ts.
  • Le fichier main.ts est le programme principal de création et gestion de la ligne de commandes. Vous ne devez pas modifier le contenu de ce fichier.

  • Le fichier server.ts est le programme principal de création et gestion du serveur web. Vous ne devez pas modifier le contenu de ce fichier.

  • Le répertoire src/test/ts contient les tests unitaires du serveur. Vous allez modifier le contenu de ce dossier.

  • Le répertoire node_modules contient les modules Node.js téléchargés par npm install. Vous ne devez pas modifier le contenu de ce dossier.

  • Le fichier package.json est le fichier de configuration de npm, qui décrit les dépendances ainsi que les commandes exécutables. Vous n’avez pas besoin de le modifier.

  • Le fichier tsconfig.json est le fichier de configuration du compilateur TypeScript. Il est identique à celui que vous avez utilisé en TP. Vous n’avez pas besoin de le modifier.

2.3. Mise à jour du projet (seulement si demandé)

Il est possible que les enseignants aient laissé quelques coquilles dans le projet et que ces coquilles soient corrigées alors que vous aurez déjà commencé à travailler sur le code.

Seulement si un enseignant vous le demande, vous pourrez récupérer les corrections des coquilles à l’aide des commandes suivantes :

# ajoute à votre référentiel local un lien vers le dépôt originel et le nomme `upstream`.
# (pas besoin si déjà fait une première fois sur votre machine)
git remote add upstream https://gitlab.univ-nantes.fr/gl/developpement/projet-2023.git

# récupère les changements des enseignants et les fusionne avec votre bifurcation.
git pull upstream main

# envoie les changements ainsi récupérés sur votre référentiel distant.
git push
  • La première ligne ajoute à votre référentiel local un lien vers le dépôt originel et le nomme upstream.

  • La deuxième ligne récupère les changements et les fusionne avec votre bifurcation.

  • La troisième ligne s’assure que les changements ainsi récupérés sont bien envoyés sur votre référentiel distant.

3. Description du fonctionnement du projet fourni

3.1. Exécution des tests unitaires, exécution de l’application

Le projet utilise l’outil de construction et de gestion de modules npm. Deux principales commandes vous sont fournies, exécutables avec npm :

  • Pour lancer tous les tests unitaires du projet avec Alsatian, exécutez : npm run test.

  • Pout lancer le jeu en ligne de commande, exécutez : npm run command-line.

  • Pour lancer le serveur en mode développement, exécutez: npm run start-server. Puis, une fois le serveur lancé :

Comme vu en TP, il ne faut pas hésiter à lancer ces deux commandes en mode Debug, afin de pouvoir profiter du débogueur ! Pour rappel, nécessite de passer par l’encart NPM Scripts que vous pouvez afficher tout en bas à gauche de VSCode (si besoin, retournez voir les instructions fournies dans le TP sur le test).

Deux commandes optionnelles vous sont également fournies :

  • Pour supprimer le code compilé, exécutez: npm run clean.

  • Pour supprimer les dépendances téléchargées, exécutez: npm run clean-deps.

3.2. Manuel d’utilisation de l’application

Une fois votre application lancée et ouverte dans une ligne de commande, répondez aux questions de l’interface pour déplacer les pions et placer des murs.

3.3. Fonctionnement interne de l’application (contenu avancé, optionnel)

3.3.1. Serveur web

Le programme principal du serveur (server.ts) est chargé de démarrer un mini-serveur web capable de recevoir les différentes requêtes provenant des navigateurs connectés à l’application :

  • GET "/" : distribue le fichier views/index.ejs;

  • GET "/status.js" : génère et distribue l’échiquier en cours au format JSON.

  • POST "/" : reçoit et traite un coup à jouer;

Ces trois traitements correspondent aux différents appels à app.get() et app.post() du programme principal.

3.3.2. Chronologie d’une partie

  1. Lorsqu’un utilisateur se connecte à l’application (adresse "/"), le serveur distribue alors la page html principale composée d’un plateau vierge et d’une zone de saisie permettant à l’utilisateur de remplir le coup à jouer.

  2. Le navigateur internet récupère immédiatement les informations de la partie en cours présentes à l’adresse /status.js et remplit le plateau à l’aide d’un script situé dans le fichier script.js. Ces deux scripts se trouvent dans le dossier client.

  3. Un clic sur le bouton "Envoyer" effectue une requête de type POST au à l’adresse "/" du serveur, contenant les informations du champ de texte associé. Le serveur traite alors la requête afin de jouer le coup demandé.

  4. La page internet du joueur est alors rechargée automatiquement, affichant ainsi le nouvel état de la partie.

4. Travail à réaliser

4.1. Code à écrire

4.1.1. Validation des mouvements et des placements de mur

La version actuelle permet le déplacement libre des pions, sans respecter les règles du jeu. Il est donc possible de déplacer les pions et placer des murs sur n’importe quelle case, ce qui n’est pas correct !

L’objectif principal de votre travail est d’écrire le code nécessaire pour vérifier qu’un mouvement est bien valide (du point de vue des règles du jeu) avant d’être exécuté.

Dans le projet que vous avez récupéré, ce travail a été commencé, mais pour le moment aucun déplacement n’est vérifié. Vous devez mettre en oeuvre la validation des déplacements des pions et le placement des murs.

En interne, le traitement des déplacements se fait de la façon suivante:

  1. Lorsqu’une requête POST arrive, le serveur extrait la valeur du champ envoyé et appelle la fonction processMove() du module server.

  2. La fonction processMove() appelle une autre fonction, parseMoveString(), qui transforme une chaîne de caractères en un déplacement (type Move) entre 2 positions (type Position).

  3. La fonction processMove() appelle ensuite la fonction isMovePossible(), qui fait appel à différentes fonctions de validation spécifiques aux pièces de l’échiquier (une par type de pièce). Le module move-validation contient toutes les fonctions de validation de déplacements.

  4. Si le mouvement est possible, c’est à dire la fonction isMovePossible() retourne true, la fonction processMove() appelle la fonction performMove(), qui effectue le déplacement.

Vous devez donc parcourir le module move-validation et implémenter les fonctions de validation contenant un commentaire de la forme :

// #TODO: Implement this function
Vous serez évalués sur le bon fonctionnement de vos fonctions de validation.

4.1.2. Tests unitaires

Pour vérifier que les fonctions du module move-validation fonctionnent correctement, vous devez écrire des tests unitaires, qui vont vérifier que les fonctions acceptent les mouvements possibles et n’acceptent pas les mouvements impossibles.

Les mouvements sont possibles (ou impossibles) en accord avec les règles du jeu. Comme ces règles sont complexes, vous serez mené à écrire plusieurs tests unitaires pour vérifier les mouvements possibles et impossibles d’un pion ainsi que les placements des murs.

Les tests unitaires du module position ont déjà été implémentés, vous les trouverez dans le fichier ./src/test/ts/position-test.spec.ts.

Vous serez évalués sur le bon fonctionnement de vos tests.

4.1.3. Comment procéder ?

Vous devez procéder par itérations successives, n’essayez pas d’implémenter les fonctions d’un seul trait. Observez le cycle de développement suivant :

  1. Implémentez une fonctionnalité simple.

  2. Écrivez le ou les tests unitaires qui vérifient cette fonctionnalité.

  3. Exécutez les tests pour vérifier que la fonctionnalité marche correctement et la non-régression.

  4. Recommencez avec la fonctionnalité suivante.

4.2. Qualité du code exigée

Il est demandé que votre travail respecte tous les principes de qualité de code étudiés en cours et en TP, ce qui inclut :

  • Nommage approprié de vos fonctions et variables,

  • Usage de commentaire lorsque c’est nécessaire et approprié,

  • Simplification du code lorsque c’est possible.

Vous serez évalués sur la qualité du code que vous aurez produit.

4.3. Utilisation de GitLab et git

Il est demandé que votre développement soit entièrement versionné à l’aide de GitLab et git. Vous devez enregistrer tous les changements que vous réalisez à l’aide de commits et de pushs sur votre référentiel distant, en choisissant à chaque fois des messages de commit appropriés. Vous devez également utiliser git pour collaborer à plusieurs sur votre projet, en partageant le même référentiel distant auprès des deux membres du binôme.

Effectuez des commits et des pushs régulièrement ! Cela vous permet d’éviter de perdre votre travail, et de mieux collaborer en équipe.

Vous serez évalués sur votre usage de git, que ce soit la qualité des messages de commit, la fréquence des commits, et l’équilibre de la répartition des commits entre les membres du binôme.

4.4. Rendre votre travail

Pour rendre votre projet, il vous suffit de vous assurer d’avoir parfaitement bien suivi ce qui est demandé dans la partie "Préparation" au début de ce document, et d’avoir bien validé (commit) et publié (push) tous vos changements et fichiers de travail. Nous vous encourageons à vérifier plusieurs fois que tout a bien été fait exactement comme demandé, autrement nous ne pourrons pas avoir accès à vos projets pour les corriger.

Si vous le souhaitez, vous pouvez également ajouter un fichier “RENDU.md” à la racine du projet, afin de décrire les spécificités de votre projet (choix techniques, parties non traitées, extensions non demandées, etc.).

Tant que tout cela est bien fait avant la date limite de rendu, alors tout est bon !

4.5. Derniers conseils

  • Rappelez-vous que « Une fonction sans test unitaire ne fonctionne pas » !

  • Rappelez-vous aussi que «N’importe qui peut écrire du code compréhensible par les ordinateurs, mais seulement les bon développeurs parviennent à écrire du code intelligible par les humains » !

  • Écrivez les tests unitaires avant ou en même temps que les fonctions. Ne les laissez pas pour la fin, les test unitaires sont très utiles pendant le développement et vous feront gagner du temps.