On souhaite développer une application simple permettant d'organiser des virements d'argent entre entités habilitées à le faire. Dans ce système, aucune devise n'est prise en compte et les sommes s'expriment simplement en valeurs entières. ## Description générale Les virements seront de trois types : - les **dons** sont envoyés d'un _émetteur_ vers un _récepteur_, pour un montant n'excédant pas le solde de l'émetteur - les **avances** sont comme des dons mais doivent être compensés ultérieurement par un **remboursement** - les **remboursement** doivent couvrir tout ou partie d'**avances** précédentes accordées par un _récepteur_ du remboursement à son émetteur Un **virement** est décrit par : - un type de virement - un émetteur - un récepteur - un montant (>0) - une description textuelle Pour être valide, un **virement** ne doit pas avoir un montant excédant le solde de l'émetteur. Une même entité ne peut être à la fois émetteur et récepteur d'un virement. Le traitement d'un **virement** par son récepteur produit le **résultat d'un virement** , décrit par : - son statut, soit accepté, soit refusé - une description éventuelle - le virement d'origine Dans ce système simplifié, un **virement** peut être refusé si un **remboursement** excède la somme totale due par son émetteur à son récepteur. L'**émetteur** d'un virement doit pouvoir effectuer les actions suivantes : - préparer un virement, en précisant son type, son récepteur, son montant et sa description - transférer une somme pour un virement (dans votre implémentation, la somme d'un virement pourra être gelée et placée sur un compte d'autorité en attendant le résultat du virement) - traiter le résultat d'un virement ; en cas de succès, débit définitif de la somme, en cas d'échec restitution sur le compte de l'émetteur Le **récepteur** d'un virement devra pouvoir effectuer l'action suivante : - recevoir un virement ; en cas de succès, la somme est effectivement transférée sur son compte On implémentera de simples entités sous forme de **personnes**, à la fois capables des rôles d'émetteur et de récepteur pour des virements. Celles-ci seront caractérisées par : - un pseudo (unique sur la plateforme) - un prénom et un nom - un solde On s'intéressera également à : - la possibilité d'ajouter du solde ou d'en retirer - la mémorisation des sommes dues par récepteur - la mémorisation des sommes avancées par récepteur - la mémorisation des virements réussis, des virements rejetés, et des virements reçus # Modélisation des types de virements On suppose que les types de virements sont en nombre connu et fixé définitivement. Les **émetteurs** et les **récepteurs** ne devront pas être limités à des **personnes**. ```java title:"votre code pour les types de virements" // votre code ici ``` ^TP1TypesDeVirementsNEPASEDITER # Modélisation des virements Un **virement** ne doit pas pouvoir être modifié une fois créé. ```java title:"votre code" ``` ^TP1VirementsNEPASEDITER >[!Question] Comment modélisez-vous les émetteurs et récepteurs, pourquoi ? quelles autres implémentations seraient alors possibles ? >votre réponse ici ^TP1QuestionEmetteursRecepteursNEPASEDITER ```java title:"votre code pour les émetteurs / récepteurs" // votre code ici ``` ^TP1EmetteursRecepteursNEPASEDITER # Modélisation du résultat d'un virement Le **résultat d'un virement** ne doit pas pouvoir être modifié une fois créé. ```java title:"votre code pour le résultat d'un virement" // votre code ici ``` ^TP1ResultatVirementNEPASEDITER # Modélisation des personnes Les **personnes** peuvent être émetteurs et récepteurs dans l'application. ```java title:"votre code pour une personne" // votre code ici ``` ^TP1PersonnesNEPASEDITER # Programme de test Afin de tester tout d'abord simplement votre application, vous allez créer par programme un certain nombre de personnes, puis allez créer aléatoirement des virements entre elles en créant un journal d'exécution inspectable. Pour créer des personnes fictives, vous utiliserez la bibliothèque [DataFaker](https://github.com/datafaker-net/datafaker) pour obtenir facilement des prénoms et noms fictifs, ex. ```java ln=false net.datafaker.Faker faker = new net.datafaker.Faker(new java.util.Locale("fr_FR", "FR")); firstName = faker.name().firstName(); // ex. obtention d'un nom fictif streetAddress = faker.address().streetAddress(); // ex. obtention d'une adresse fictive for (int i = 0; i < 10; i++) // ex. affichage de films des studios Ghibli System.out.println(faker.studioGhibli().movie()); ``` Des [instructions](https://github.com/datafaker-net/datafaker) sont données pour ajouter la librairie à votre _build_. Si vous utilisez le système de construction d'[IntelliJ IDEA](https://www.jetbrains.com/fr-fr/idea/download), allez dans `File > Project Structure > Projects Settings > Librairies > New Project Library > From Maven` et cherchez `DataFaker` (prenez : `org.geckoprojects.libraries:net.datafaker:2.4.2`). >[!Question] Quelle utilité trouvez-vous à cette librairie, pour des types tels que des valeurs fictives ou des valeurs réelles ([voir la liste de tous les types proposés](https://www.datafaker.net/documentation/providers/)). Pour quelles étapes du développement celle-ci peut-être intéressante ? En production, à quoi pourrait-elle servir ? >votre réponse ici ^TP1UtiliteDataFakerNEPASEDITER On suppose que les **personnes** seront stockées dans une carte de type `{java}Map`, associant son pseudo à chaque personne. Afin de réaliser vos tests et tirer aléatoire des personnes, implémentez une méthode `{java}static` sur un ensemble générique (`{java}Set`) permettant d'obtenir un clé (_key_) tirée aléatoirement dans un ensemble : `{java}static E cléAléatoireDUnEnsemble(Set ensemble)` ainsi que sa variante permettant d'exclure une clé particulière (utile lorsque l'on cherche un récepteur différent de l'émetteur) : `{java}static E cléAléatoireDUnEnsemble(Set ensemble, E élémentExclu)` ```java title:"votre code pour le tirage aléatoire d'une clé dans un ensemble" // votre code ici ``` ^TP1TirageAleatoireCleDansEnsembleNEPASEDITER Donnez finalement le code de votre programme principal (ainsi que d'autres éléments éventuellement nécessaires). ```java title:"votre code pour votre programme principal" // votre code ici ``` ^TP1ProgrammePrincipalNEPASEDITER