diff --git a/src/fr/iutfbleau/projetIHM2021FI2/API/Reservation.java b/src/fr/iutfbleau/projetIHM2021FI2/API/Reservation.java index bd02c1b..f95a294 100644 --- a/src/fr/iutfbleau/projetIHM2021FI2/API/Reservation.java +++ b/src/fr/iutfbleau/projetIHM2021FI2/API/Reservation.java @@ -31,7 +31,7 @@ public interface Reservation { /** * permet de récupérer - * @return le type de chambre + * @return la chambre */ public Chambre getChambre(); diff --git a/src/fr/iutfbleau/projetIHM2021FI2/MNP/ReservationFactoryNP.java b/src/fr/iutfbleau/projetIHM2021FI2/MNP/ReservationFactoryNP.java new file mode 100644 index 0000000..996c65f --- /dev/null +++ b/src/fr/iutfbleau/projetIHM2021FI2/MNP/ReservationFactoryNP.java @@ -0,0 +1,372 @@ +package fr.iutfbleau.projetIHM2021FI2.MNP; +import fr.iutfbleau.projetIHM2021FI2.API.*; +import java.time.LocalDate; +import java.util.*; +import java.util.function.Predicate; +import java.lang.*; + +/** + * Usine non persistante stockant les réservations dans une structure de données permettant de simuler un ensemble. + * + * L'hôtel est magique. + * Il y a trop de chambres (3 millions, 1 million de chaque sorte). + * on va juste prendre la prochaine chambre. + * on ne fera même peut-être jamais le ménage (beurk). + * + * Par paresse, la réservation possède la même référence que la préréservation correspondante. + * + */ +public class ReservationFactoryNP implements ReservationFactory{ + + // On dispose de beaucoup de chambres. + // On stocke le prochain numéro libre dans un map particulier dont les clé viennent d'un type énuméré (ici celui des chambres). + // La valeur étant forcément un objet, il faut stocker un Integer plutôt qu'un int pour le numéro. + // Par contre les Integer ne sont pas mutables. Pour incrémenter il faut aller chercher le prochain Integer. + // Pour éviter de créer inutilement ce prochain Integer si il existe déjà, on va utiliser Integer.ValueOf(int) + // https://docs.oracle.com/javase/8/docs/api/java/lang/Integer.html#valueOf-int- + private EnumMap nextFreeRoom; + + // similaire pour stocker la valeur max, même un hotel magique devrait faire le ménage. + private EnumMap brokenMagic; + + // plus petite et plus grande valeur pour les chambres UNLS + private static int MIN_UNLS = 0; + private static int MAX_UNLS = 10^6 -1; + // plus petite et plus grande valeur pour les chambres DEUXLS + private static int MIN_DEUXLS = 10^6; + private static int MAX_DEUXLS = 2*10^6 -1; + // plus petite et plus grande valeur pour les chambres UNLD + private static int MIN_UNLD = 2*10^6; + private static int MAX_UNLD = 3*10^6 -1; + + // plus grand nombre de chambres à proposer si le client souhaite choisir (va automatiquement salir les chambres précédentes) + private static int ADEQUATE = 5; + + + // Plutôt que d'utiliser un ensemble, on utilise un HashMap indexé par les dates car on va devoir chercher + // les réservations par date pour faire des statistiques. + // En effet, sinon il faudrait tout parcourir. + // + // Si par exemple, on faisait comme les préréservations en stockant une réservation par référence. + //
+    //     private HashMap brain;
+    // 
+ // + // On pourrait alors chercher les réservations comme ceci (mais au bout de plusieurs années ça risque d'être looooooong). + //
{@code
+    //     Collection c = this.brain.values();
+    //     // on définit un prédicat sur les Réservations :
+    //     // il faut enlever les réservations telles que date de fin (date de debut + nbre jours) termine avant d
+    //     // il faut enlever les réservations telles que date de début resa est après d
+    //     Predicate filtre = resa -> resa.getDateDebut().isAfter(d) || resa.getDateDebut().plusDays(resa.getJours()).isBefore(d) ;
+    //     // on filtre la collection.
+    //     c.removeIf(filtre);
+    //     // on fabrique un ensemble.
+    //     Set found = new HashSet(c);
+    //     return found;
+    // }
+ // + // On va donc utiliser un hasmap indexé par les dates pour trouver directement l'information sans tout parcourir. + // Toutefois, le hashMap ne peut contenir qu'une valeur pour une clé donnée. + // Puisqu'on a en général plusieurs réservations pour une date donnée, il faut que la valeur soit un ensemble de réservations. + // + // Pour rester efficace pendant la recherche, on va supposer que l'espace pris par quelques pointeurs n'est pas un soucis et + // une reservation va apparaître pour tous les jours concernés. + // Alternativement, si il y avait une limite sur la durée d'une réservation, on pourrait décider de se passer de ces pointeurs et chercher autour d'une date dans cette limite + // pour trouver une réservation. + // + // Pour une recherche pour un type de chambre donné, il faudra filtrer en ne conservant que les réservations du type qui nous intéresse. + // + // Pour plus d'efficacité dans la recherche, on aurait pu utiliser un second niveau d'indexation en changeant Set par un + // EnumMap> + // Mais bon il vaut mieux faire tout ça avec une base de données. + // C'est précisément ce que l'index sous-jacent à la clé primaire ou un index secondaire bien choisi fera. + // + private HashMap> brain; + + // /** + // * Constructeur + // */ + public ReservationFactoryNP(){ + // voir https://docs.oracle.com/javase/8/docs/api/java/util/EnumMap.html#EnumMap-java.lang.Class- + nextFreeRoom = new EnumMap<>(TypeChambre.class); + this.nextFreeRoom.put(TypeChambre.UNLS,Integer.valueOf(this.MIN_UNLS)); + this.nextFreeRoom.put(TypeChambre.DEUXLS,Integer.valueOf(this.MIN_DEUXLS)); + this.nextFreeRoom.put(TypeChambre.UNLD,Integer.valueOf(this.MIN_UNLD)); + + brokenMagic = new EnumMap<>(TypeChambre.class); + this.brokenMagic.put(TypeChambre.UNLS,Integer.valueOf(this.MAX_UNLS)); + this.brokenMagic.put(TypeChambre.DEUXLS,Integer.valueOf(this.MAX_DEUXLS)); + this.brokenMagic.put(TypeChambre.UNLD,Integer.valueOf(this.MAX_UNLD)); + + brain = new HashMap>(); + } + + /** + * Recherche une chambre adéquate à partir de + * @param p une préréservation + * @return la chambre + * @throws NullPointerException si un argument est null + * @throws IllegalStateException si une chambre correspondant à cette Préréservation n'existe pas. + * + * Ne devrait pas retourner un objet null. + */ + public Chambre getChambre(Prereservation p){ + Objects.requireNonNull(p,"La préréservation est null."); + Integer numero = this.nextFreeRoom.get(p.getTypeChambre()); + if(numero.compareTo(this.brokenMagic.get(p.getTypeChambre())) >= 0){ + throw new IllegalStateException("Hotel Magique is sadly experiencing a lack of clean rooms of type "+ p.getTypeChambre()); + } + Chambre c = new ChambreNP(numero,p.getTypeChambre()); + return c; + } + + /** + * Recherche toutes les chambres adéquates à partir de + * @param p une préréservation + * @return les chambres (set de chambre) + * @throws NullPointerException si un argument est null + * @throws IllegalStateException si une chambre correspondant à cette Préréservation n'existe pas. + * Ne devrait pas retourner un objet null. + * + * NB. On considère que seulement les this.ADEQUATE prochaines chambres disponibles sont adéquates. + * + */ + public Set getChambres(Prereservation p){ + Objects.requireNonNull(p,"La préréservation est null."); + Integer numero = this.nextFreeRoom.get(p.getTypeChambre()); + if(numero.compareTo(this.brokenMagic.get(p.getTypeChambre())) >= 0){ + throw new IllegalStateException("Hotel Magique is sadly experiencing a lack of clean rooms of type "+ p.getTypeChambre()); + } + + Set res = new HashSet(); + int howMany = Math.min(this.brokenMagic.get(p.getTypeChambre()) - this.nextFreeRoom.get(p.getTypeChambre()), this.ADEQUATE); + + for (int i=0; i< howMany ;i++) { + Chambre c = new ChambreNP(numero,p.getTypeChambre()); + res.add(c); + } + + return res; + + } + + /* + * Prend en compte la réservation (ajout dans brain, mis à jour du prochain numéro) + * @param r une réservation (qu'on suppose correcte) + * + * NB. pas de vérification. + * Utiliser les vérifications avant. + * + */ + private void addReservationToBrain(Reservation r){ + // mise à jour de la prochaine chambre libre à 1 de plus que moi + this.nextFreeRoom.put(r.getChambre().getType(),Integer.valueOf(r.getChambre().getNumero() + 1)); + // Ajout pour toutes les dates de la réservation. + LocalDate d = r.getDateDebut(); + for (int i=0; i< r.getJours() ;i++) { + this.addReservationToBrain(r,d); + d = d.plusDays(1); // Le jour suivant le matou revient. + } + } + + /* + * Ajout dans brain de la réservation à la date donnée. + * @param r une réservation (qu'on suppose correcte) + * + * NB. pas de vérification. + * Utiliser les vérifications avant. + * + */ + private void addReservationToBrain(Reservation r, LocalDate d){ + Set s = this.getReservation(d); + s.add(r); + this.brain.put(d,s); + } + + + + /** + * Fabrique (ajoute) une réservation + * @param p une préréservation + * @param c une chambre (normalement libre et adaptée à la préréservation) + * @return la réservation + * @throws NullPointerException si un argument est null + * @throws IllegalArgumentException si la chambre ne correspondant pas au type de chambre de la préréservation. + * @throws IllegalStateException si la chambre n'est pas disponible. + * + * Ne devrait pas retourner un objet null. + */ + public Reservation createReservation(Prereservation p, Chambre c){ + Objects.requireNonNull(p,"La préréservation est null."); + Objects.requireNonNull(p,"La chambre est null."); + if (c.getType()!=p.getTypeChambre()) { + throw new IllegalArgumentException("Erreur sur le type de la chambre: la préréservation indique " + p.getTypeChambre() + " mais la chambre est " + c.getType()); + } + else if (false) // n'arrive jamais dans l'hôtel magique. + { + throw new IllegalArgumentException("Pas de chambre disponible de type " + p.getTypeChambre()); + } + else { + Reservation r = new ReservationNP(p.getReference(), p.getDateDebut(), p.getJours(), c, p.getClient()); + this.addReservationToBrain(r); + return r; + } + } + + /** + * Cherche les réservations + * @param d une date + * @return la ou les réservation(s) à cette date sous forme d'un ensemble + * @throws NullPointerException si un argument est null + * + * Ne devrait pas retourner un objet null, par contre peut être un ensemble qui est vide. + */ + public Set getReservation(LocalDate d){ + Objects.requireNonNull(d,"La date proposée est null."); + + Set s; + if (this.brain.containsKey(d)){ + s = this.brain.get(d); + } + else{ + s = new HashSet(); + } + return s; + } + + /** + * Cherche le nombre de chambres disponibles pour une date (réservées ou non). + * @param d une date + * @return un entier + * @throws NullPointerException si un argument est null + * + * Ne devrait pas retourner un entier négatif. + */ + public int getDisponibles(LocalDate d){ + throw new UnsupportedOperationException("pas encore implanté"); + } + + /** + * Cherche les réservations + * @param d une date + * @param t un type de chambre + * @return la ou les réservation(s) pour ce type de chambre à cette date sous forme d'un ensemble + * @throws NullPointerException si un argument est null + * + * Ne devrait pas retourner un objet null, par contre peut être un ensemble qui est vide. + */ + public Set getReservation(LocalDate d, TypeChambre t){ + throw new UnsupportedOperationException("pas encore implanté"); + } + + /** + * Cherche le nombre de chambres disponibles d'un certain type pour une date (réservées ou non). + * @param d une date + * @param t un type de chambre + * @return un entier + * @throws NullPointerException si un argument est null + * + * Ne devrait pas retourner un entier négatif. + */ + public int getDisponibles(LocalDate d, TypeChambre t){ + throw new UnsupportedOperationException("pas encore implanté"); + } + + + /** + * Cherche la proportion de chambres disponibles pour une date (réservées sur réservables). + * @param d une date + * @return un entier entre 0 et 100 + * @throws NullPointerException si un argument est null + */ + public int getRatio(LocalDate d){ + throw new UnsupportedOperationException("pas encore implanté"); + } + + + /** + * Cherche la proportion de chambres disponibles d'un certain type pour une date (réservées sur réservables). + * @param d une date + * @param t un type de chambre + * @return un entier entre 0 et 100 + * @throws NullPointerException si un argument est null + */ + public int getRatio(LocalDate d, TypeChambre t){ + throw new UnsupportedOperationException("pas encore implanté"); + } + + + /** + * Cherche le nombre moyen de chambres disponibles entre deux date (réservées ou non), arrondies à l'entier inférieur. + * @param d1 une date + * @param d2 une date + * @return un entier + * @throws NullPointerException si un argument est null + * @throws IllegalArgumentException si l'ordre temporel d1 avant d2 n'est pas respecté. + * + * Ne devrait pas retourner un entier négatif. + */ + public int getDisponibles(LocalDate d1, LocalDate d2){ + throw new UnsupportedOperationException("pas encore implanté"); + } + + + /** + * Cherche les réservations + * @param d1 une date + * @param d2 une date + * @param t un type de chambre + * @return la ou les réservation(s) pour ce type de chambre entre les dates sous forme d'un ensemble + * @throws NullPointerException si un argument est null + * @throws IllegalArgumentException si l'ordre temporel d1 avant d2 n'est pas respecté. + * + * Ne devrait pas retourner un objet null, par contre peut être un ensemble qui est vide. + */ + public Set getReservation(LocalDate d1, LocalDate d2, TypeChambre t){ + throw new UnsupportedOperationException("pas encore implanté"); + } + + + /** + * Cherche le nombre moyen de chambres disponibles d'un certain type entre deux date (réservées ou non), arrondies à l'entier inférieur. + * @param d1 une date + * @param d2 une date + * @param t un type de chambre + * @return un entier + * @throws NullPointerException si un argument est null + * @throws IllegalArgumentException si l'ordre temporel d1 avant d2 n'est pas respecté. + * + * Ne devrait pas retourner un entier négatif. + */ + public int getDisponibles(LocalDate d1, LocalDate d2, TypeChambre t){ + throw new UnsupportedOperationException("pas encore implanté"); + } + + + /** + * Cherche la proportion moyenne de chambres disponibles pour une date (réservées sur réservables). + * @param d1 une date + * @param d2 une date + * @return un entier entre 0 et 100 + * @throws NullPointerException si un argument est null + */ + public int getRatio(LocalDate d1, LocalDate d2){ + throw new UnsupportedOperationException("pas encore implanté"); + } + + + /** + * Cherche la proportion moyenne de chambres disponibles d'un certain type pour une date (réservées sur réservables). + * @param d1 une date + * @param d2 une date + * @param t un type de chambre + * @return un entier entre 0 et 100 + * @throws NullPointerException si un argument est null + */ + public int getRatio(LocalDate d1, LocalDate d2, TypeChambre t){ + throw new UnsupportedOperationException("pas encore implanté"); + } + + +} diff --git a/src/fr/iutfbleau/projetIHM2021FI2/MNP/ReservationNP.java b/src/fr/iutfbleau/projetIHM2021FI2/MNP/ReservationNP.java index 442a324..f0af284 100644 --- a/src/fr/iutfbleau/projetIHM2021FI2/MNP/ReservationNP.java +++ b/src/fr/iutfbleau/projetIHM2021FI2/MNP/ReservationNP.java @@ -1,5 +1,6 @@ package fr.iutfbleau.projetIHM2021FI2.MNP; import fr.iutfbleau.projetIHM2021FI2.API.*; +import java.time.LocalDate; import java.util.*; /** * Une Réservation non presistante toute bête @@ -11,7 +12,7 @@ import java.util.*; public class ReservationNP implements Reservation { private String reference; - private Date dateDebut; + private LocalDate dateDebut; private int jours; private Chambre chambre; private Client client; @@ -21,7 +22,7 @@ public class ReservationNP implements Reservation { * * NB. on force jours>0 et les autres attributs à ne pas être null */ - public ReservationNP(String reference, Date dateDebut, int jours, Chambre chambre, Client client){ + public ReservationNP(String reference, LocalDate dateDebut, int jours, Chambre chambre, Client client){ Objects.requireNonNull(reference,"On ne peut pas créer une réservation avec un reference à null."); Objects.requireNonNull(dateDebut,"On ne peut pas créer une réservation avec un date de début à null."); if (jours<1) { @@ -52,7 +53,7 @@ public class ReservationNP implements Reservation { * * A priori seule la date est importante, le reste est sans importance. */ - public Date getDateDebut(){ + public LocalDate getDateDebut(){ return this.dateDebut; } @@ -66,7 +67,7 @@ public class ReservationNP implements Reservation { /** * permet de récupérer - * @return le type de chambre + * @return la chambre */ public Chambre getChambre(){ return this.chambre; diff --git a/src/fr/iutfbleau/projetIHM2021FI2/Test/TestTexteMNP.java b/src/fr/iutfbleau/projetIHM2021FI2/Test/TestTexteMNP.java index 574bc9d..c0d1111 100644 --- a/src/fr/iutfbleau/projetIHM2021FI2/Test/TestTexteMNP.java +++ b/src/fr/iutfbleau/projetIHM2021FI2/Test/TestTexteMNP.java @@ -17,7 +17,7 @@ public class TestTexteMNP{ Client c4 = new ClientNP(4, "Florentin", "Giraud"); Client c5 = new ClientNP(5, "Martin", "Gillet"); - bookingPointCom.ajoutePrereservation("4751-3708-LRFM", LocalDate.of(2018,1,5),1, TypeChambre.DEUXLS,c1); + bookingPointCom.ajoutePrereservation("4751-3708-LRFM", LocalDate.of(2018,01,5),1, TypeChambre.DEUXLS,c1); bookingPointCom.ajoutePrereservation("2436-3909-NXLL", LocalDate.of(2018,01,07),1, TypeChambre.UNLS,c1); bookingPointCom.ajoutePrereservation("1351-0775-BETZ", LocalDate.of(2018,01,05),2, TypeChambre.DEUXLS,c2); bookingPointCom.ajoutePrereservation("3440-0631-NFCU", LocalDate.of(2018,01,06),2, TypeChambre.UNLD,c2); @@ -30,7 +30,9 @@ public class TestTexteMNP{ System.out.print("Le modèle de Préréservation est prêt.\n"); - // TODO : Idem ici avec un modèle non persistant de Réservation. + // Idem ici avec un modèle non persistant de Réservation. + ReservationFactory grandLivreDOrAPISeulement = new ReservationFactoryNP(); + // Normalement ce qu'il faut pour faire marcher la vue sont créées ci-dessous. @@ -67,9 +69,27 @@ public class TestTexteMNP{ Prereservation preresa = bookingPointComAPISeulement.getPrereservation("2436-3909-NXLL"); System.out.print("I found your booking.\n"); System.out.println(preresa.monPrint()); + + Chambre libre=null; + try{ + libre = grandLivreDOrAPISeulement.getChambre(preresa); + System.out.print("I have a great room for you.\n"); + System.out.println(libre.monPrint()); + } + catch(IllegalStateException e){ + System.out.print(e.getMessage()); + } + try{ + System.out.print("You like this room? Excellent! Let me confirm the reservation for you.\n"); + Reservation resa = grandLivreDOrAPISeulement.createReservation(preresa,libre); + System.out.println(resa.monPrint()); + } + catch(IllegalStateException e){ + System.out.print(e.getMessage()); + } } catch(IllegalStateException e){ - System.out.print("I am sorry sir, no booking under this reference.\n"); + System.out.print("I am sorry Madam, no booking under this reference.\n"); } System.out.println("=========================="); System.out.print("Hello Madam. Vous avez oubliée votre numéro de préréservation. Ce n'est pas grave, je vais chercher avec votre nom et prénom.\n"); @@ -85,6 +105,13 @@ public class TestTexteMNP{ System.out.print("I am sorry Madam, no booking under this reference.\n"); } System.out.println("=========================="); + System.out.println("=== Vue du manageur ===="); + System.out.println("=========================="); + Set resas = grandLivreDOrAPISeulement.getReservation(LocalDate.of(2018,01,05)); + System.out.print("Réservations du "+ LocalDate.of(2018,01,07) + ".\n"); + for(Reservation r : resas){ + System.out.println(r.monPrint()); + } } }