Aller au contenu

TP2

Dans ce TP2, on vous demande d’effectuer les tâches suivantes :

  1. (Finalisez l’implémentation de votre modèle, si ce n’est pas déjà fait)
  2. Migrez votre projet vers Maven
    • Remplacez les copies précédentes des interfaces par une référence à une bibliothèque
    • Intégrez le plugin exec, afin que votre code soit exécutable
  3. Implémentez un contrôleur pour :
    • L’initialisation du modèle (à l’aide d’une factory)
    • Le transfert d’état du modèle à l’aide de commandes. Au minimum :
      • Retirer une carte de la pile
      • Rejeter une carte
      • Révéler une carte non divulguée

Pensez au contrôleur comme à un gestionnaire de jeu invisible, qui veille au respect des règles pendant la partie.

Le code est une condition préliminaire à la note

Votre note dépendra de votre capacité à expliquer et à raisonner à propos de votre code soumis, lors de l’examen oral subséquent. Un code fonctionnel est une condition préliminaire pour passer l’examen oral : bien que des fonctionnalités manquantes entraînent une réduction de la note, aucun point n’est accordé uniquement pour le code soumis.

Interfaces

Comme la dernière fois, vous travaillerez avec des interfaces fournies, afin de rester sur la bonne voie.

  • La dernière fois, les interfaces étaient fournies sous forme de code.
  • Cette fois, elles sont fournies sous forme de bibliothèque Maven, accompagnée d’une documentation en ligne.

Migration vers Maven

Pour le TP2, il vous est demandé de passer d’une structure de projet Java standard à Maven. Concrètement, cela signifie :

  • Vous devez ajuster la structure des dossiers.
  • Vous devez créer un fichier pom.xml.

Utilisez un gabarit (template)

Si vous ne savez pas par où commencer, créez un nouveau projet Maven à partir d’un gabarit (vous avez vu la commande au dernier cours), puis copiez les fichiers sources de votre TP1 dans ce projet gabarit. Cela vous fournira également un fichier pom.xml par défaut.

Structure du projet

Comme vu en classe, les projets Maven doivent suivre une structure spécifique.

  • Modifiez la structure de votre projet pour qu’elle soit conforme à Maven.
  • Créez un fichier pom.xml
  • Assurez-vous que le projet compile avec la commande mvn compile.

Interfaces en tant que bibliothèque

  • Pour ce deuxième TP, votre projet ne doit contenir que vos propres classes.
  • Autrement dit, vous devez supprimer toutes les interfaces fournies ainsi que le paquet view.
  • Ces classes restent néanmoins disponibles pour votre usage ! Pour y accéder sous forme de bibliothèque, utilisez la configuration suivante :
    • repository indique à Maven télécharger les interfaces / classes (elles ne sont pas sur les serveurs Maven officiels).
    • dependency indique à Maven quoi télécharger exactement.
...

<repositories>
    <repository>
        <id>Max's third party repo on a UQAM GitLab file server</id>
        <url>https://max.pages.info.uqam.ca/inf2050repo/</url>
    </repository>
</repositories>
<dependencies>

<!-- DO NOT ADD ANY OTHER DEPENDENCIES HERE!-->
<dependency>
    <groupId>ca.uqam.info.mgl7010.max</groupId>
    <artifactId>skyjo-interfaces</artifactId>
    <version>f25-1.0</version>
</dependency>
</dependencies>

...

Plugin Exec

  • Par défaut, les projets Maven ne sont pas exécutables (Maven ne peut pas savoir s’il s’agit de programmes ou de bibliothèques).
  • Ajoutez le plugin exec à la configuration de votre fichier pom.xml afin d’ajouter une configuration de lancement.
  • Faites-le pointer vers le code de lancement TP2 fourni (voir l’exemple de code plus bas), afin qu’il soit exécuté avec la commande mvn exec:java.

Contrôleur

Dans le TP précédent, tout votre code se trouvait dans un seul paquet : model.

  • model sert uniquement à stocker l’état du jeu.
  • Dans ce TP2, vous gérez les interactions des joueurs (qui modifient l’état), vous devez donc créer un nouveau paquet : controller.

Initialisation du modèle

  • Créez une nouvelle classe LauncherTP2.java dans votre nouveau paquet controller.
  • Utilisez le code d’exemple ci-dessous pour lancer votre logiciel...
    • Vous devrez implémenter une nouvelle classe ControllerImpl qui implémente l’interface Controller fournie, afin que cela fonctionne.
    • Assurez-vous que c’est votre controller qui gère toute la logique nécessaire pour instancier de nouveaux modèles (controller.initializeModel(ModelPreset.DEFAULT, players)). Cela nécessitera un certain remaniement de votre code du TP1, où vous avez probablement placé toute la logique dans le constructeur de la classe Model. Par logique, on entend par exemple la création du paquet de cartes, le mélange des cartes, etc.
public static void main(String[] args) {

  // Visual parameters and player names (hard coded for TP2)
  boolean useTtyColours = true;
  String[] players = new String[] {"Max", "Ryan", "Maram", "Quentin"};

  // Initialize a new game
  Controller controller = new ControllerImpl();
  controller.initializeModel(ModelPreset.DEFAULT, players);

  // Register UI to automatically refresh on model updates
  CommandSelector controller.addModelObserver(new TextualVisualizer(controller.getModel(), useTtyColours));

  // Initialize commandSelector for interactive / TTY mode
  commandSelector = new TextualCommandSelector(useTtyColours, false);

  // Play the game :)
  playUntilGameEnd(controller);
}

/**
 * Note: This method is not concerned with updating model state representations, for the model
 * adheres to the observer pattern for this purpose.
 * This loop is only about retrieving user inputs until game end. The model is automatically
 * rendered after each executed command.
 *
 * @param controller as the MVC controller allowing to progress the game command by command.
 *                   Note that the view has no direct access to the model, and can only
 *                   manipulate model state by executing commands.
 */
private static void playUntilGameEnd(Controller controller) {

  // Initialize options for game start
  Command[] options = controller.getCurrentPlayerCommands();

  // Keep playing until controller offers no more options (game end)
  while (options.length > 0) {

    // Request a choice from robot / human player
    int selectedCommand = commandSelector.selectCommand(options, controller.isUndoAvailable());

    // Execute choice (this implicitly re-renders the model)
    controller.doCommand(selectedCommand);

    // Update options
    options = controller.getCurrentPlayerCommands();
  }
}

La deuxième méthode implémente la logique du jeu.

  • Par défaut, elle utilise l’interface utilisateur textuelle fournie pour demander des choix aux utilisateurs.
  • Vous n’avez pas besoin d’implémenter de fonctionnalités d’interface utilisateur, tout est déjà fourni avec la bibliothèque Maven.

Testez en sélectionnant automatiquement la première option

Vous pouvez ignorer les invites utilisateur en choisissant automatiquement la première option (0) comme selectedCommand. Ainsi, votre jeu avancera automatiquement jusqu’à la fin sans interaction humaine, ce qui vous permettra de vérifier votre implémentation.

Transfert d’état du modèle avec des commandes

La boucle de contrôle principale ci-dessus exige que votre ControllerImpl détermine quelles actions de joueur sont possibles.

  • Pour faire avancer le jeu, vous répartirez la logique du jeu sur plusieurs objets Command, chaque commande étant un objet qui modifie l’état du jeu.
  • Vous en apprendrez davantage sur les commandes dans un cours ultérieur. Pour l’instant, il suffit de savoir que chaque commande correspond à une action de joueur.

Pour ce TP2, vous n’avez pas besoin d’implémenter le jeu complet. Il suffit de limiter les actions des joueurs à :

  1. Prendre une carte de la pile (RevealFreshCardCommand implements Command)
  2. Rejeter la carte révélée (RejectCard implements Command)
  3. Révéler une des cartes du joueur encore cachées (RevealCard implements Command)

Ces commandes sont suffisantes, car la séquence des trois définit un tour de jeu valide.

Ignorez undo

Il n'est pas nécessaire d'implementer undo à ce stade. Vous serez invités à les implémenter plus tard.

Ne vous préoccupez pas des autres commandes

Les commandes ci-dessus suffisent pour jouer une partie valide de Skyjo. Ne vous occupez pas des autres pour le moment, vous serez invités à les implémenter plus tard.

Déclaration de contribution

Incluez un fichier PDF contenant les informations et la déclaration suivantes :

Informations

Pour chaque membre de l’équipe :

  • Le pourcentage du travail auquel il ou elle a contribué.
  • 2 classes / méthodes pour lesquelles il ou elle se déclare expert désigné.

Déclaration

Incluez cette déclaration dans votre soumission, signez-la à la main, prenez une photo et ajoutez-la à votre soumission.

Nous déclarons par la présente n’avoir utilisé aucune intelligence artificielle générative pour produire le contenu de ce TP, et n’avoir copié aucun code provenant d’autres sources sans en indiquer la provenance dans les commentaires du programme.
Nous comprenons que l’inclusion de contenu généré par IA ou la copie de code étranger sans mention appropriée constitue une faute académique grave qui sera signalée à la commission universitaire du plagiat, ce qui pourrait mener à notre expulsion du programme d’études.

  • Signature : ____
  • Signature : ____
  • Signature : ____

  • Date : ____

Remise

La remise est prévue pour le vendredi 07-11-2025 samedi 15-11-2025, avant 23h59, par courriel à
schiedermeier.maximilian@uqam.ca.

  • Sujet : TP2
  • Contenu :
    • Un seul fichier ZIP contenant le projet Maven :
      • pom.xml
      • Dossier src
    • Déclaration de contribution signée.

Ne soumettez pas votre dossier target.

Réductions de points

Bien que votre note repose sur votre capacité à expliquer votre code, vous pouvez perdre des points (c’est-à-dire que la note maximale sera réduite) si certaines exigences sont ignorées dans votre solution :

Réductions liées à l’implémentation

  • Pas de Maven : -100 %, à éviter absolument.
  • Pas de contrôleur / 3 commandes de base non implémentées : -100 %, à éviter absolument.
  • Aucune déclaration de contribution : -100 %, à éviter absolument.
  • Interfaces fournies modifiées ou non utilisées, c’est-à-dire absence de implements Controller : -100 %, à éviter absolument.
  • Code ne compilant pas avec mvn clean compile, version 24 : -100 %, à éviter absolument.
  • Code qui plante à l’exécution avec mvn exec:java, version 24 : -100 %, à éviter absolument.
  • Dépendances supplémentaires non-JDK ou bibliothèques tierces ajoutées (sauf interfaces fournies) : -100 %, à éviter absolument.
  • Jeu de cartes non implémenté avec une structure de données propre : -30 %
  • État codé en dur / ne change pas au redémarrage : -20 %
  • Méthodes du modèle manquantes ou incomplètes : -10 % par méthode manquante ou incomplète.
  • Méthodes inutilement complexes : -5 % par méthode dépassant 25 lignes (hors commentaires).

Réductions liées à la remise

  • Remise en retard : -30 % dès le dépassement de l’échéance, puis -20 % supplémentaires par 24 h de retard.
  • La soumission contient des fichiers inutiles/temporaires ou binaires (.class) : -5 % par fichier inutile.

DIVERS

Questions

  • Pour les questions relatives aux exigences du TP, veuillez utiliser le forum Mattermost.
  • Ne partagez pas de code ni de parties de votre solution sur Mattermost.

Suggestions

Bien que cela ne soit pas une exigence stricte ni directement lié à des points bonus, il est toujours bon d’améliorer l’humeur du professeur avec quelques bonnes pratiques :

  • Vérifiez votre soumission avant de l’envoyer :
    • Envoyez-la d’abord à un membre de l’équipe. Laissez-le extraire le ZIP, compiler le code, etc., sur une autre machine.
    • Si tout fonctionne, transférez ensuite le courriel au professeur.
  • Formatez votre code : utilisez le formateur de code d’IntelliJ, afin que votre code soit plus lisible.
  • Revisitez les laboratoires : certaines parties des solutions de ce TP ont été subtilement couvertes dans les laboratoires. Si vous pensez qu’une solution de labo peut être réutilisée, indiquez-le dans un commentaire dans votre code.
  • Commentez votre code : utilisez Javadoc /** ... */ pour les méthodes, et des commentaires réguliers // en ligne.

Habituez-vous aux commentaires et conventions de nommage en anglais

Vous avez le droit de commenter en français, et la langue utilisée pour vos commentaires n’aura absolument aucun impact sur votre note.
Cependant, gardez à l’esprit que l’informatique est une discipline internationale et que, sur le long terme, vous devrez probablement commenter en anglais. Autant vous y habituer tôt.
Même chose pour les noms de variables et de méthodes : adoptez les noms en anglais, cela facilite énormément la collaboration à long terme.
J’ai déjà travaillé dans une équipe internationale où chaque stagiaire ajoutait des commentaires et des noms dans sa langue maternelle : anglais, allemand, français, espagnol, voire chinois. Sans surprise, cela a nui au projet.