diff --git a/.gitignore b/.gitignore index f836b6b..38e9997 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ # Compiled class file *.class +Test.java + #VSCode .project .classpath @@ -119,3 +121,5 @@ local.properties nbproject/private/ build/ + +fichier.ics \ No newline at end of file diff --git a/README.md b/README.md index eb1935c..b1c5d28 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ ![GitHub Actions](https://github.com/DevLab-umontp/API-JAVA-EDT/workflows/Java%20CI%20with%20Maven/badge.svg) +[![Javadoc](https://img.shields.io/badge/JavaDoc-Online-green)](https://mathieusoysal.github.io/stats/api-java-edt) [![Gitmoji.dev](https://img.shields.io/badge/gitmoji-%20😜%20😍-FFDD67.svg?style=flat-square)](https://gitmoji.dev) # ![](ressources/devicon.png) API Java : EDT IUT Montpellier diff --git a/pom.xml b/pom.xml index 240da1f..8efdce5 100644 --- a/pom.xml +++ b/pom.xml @@ -1,7 +1,6 @@ - + 4.0.0 edt.umontp.fr @@ -18,56 +17,69 @@ 11 + + + + org.junit + junit-bom + 5.5.2 + pom + import + + + + - junit - junit - 4.13.1 + org.junit.jupiter + junit-jupiter + 5.4.0-M1 test + + org.mnode.ical4j + ical4j + 1.0.2 + - + + - - - maven-clean-plugin - 3.1.0 - - - - maven-resources-plugin - 3.0.2 - - - maven-compiler-plugin - 3.8.0 - + org.apache.maven.plugins maven-surefire-plugin - 2.22.1 - - - maven-jar-plugin - 3.0.2 - - - maven-install-plugin - 2.5.2 + 3.0.0-M5 + + + . + src/test/java/** + + - maven-deploy-plugin - 2.8.2 + org.apache.maven.plugins + maven-javadoc-plugin + 3.0.0 + + 11 + 11 + - - maven-site-plugin - 3.7.1 + org.apache.maven.plugins + maven-failsafe-plugin + 2.22.0 - maven-project-info-reports-plugin - 3.0.0 + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 11 + 11 + diff --git a/ressources/uml/DiagrammeDeClasse.pdf b/ressources/uml/DiagrammeDeClasse.pdf index d591549..4659d46 100644 Binary files a/ressources/uml/DiagrammeDeClasse.pdf and b/ressources/uml/DiagrammeDeClasse.pdf differ diff --git a/ressources/uml/Diagrammes.mdj b/ressources/uml/Diagrammes.mdj index 1f4515a..342abb7 100644 --- a/ressources/uml/Diagrammes.mdj +++ b/ressources/uml/Diagrammes.mdj @@ -366,7 +366,7 @@ "visible": false, "font": "Arial;13;0", "left": 160, - "top": -496, + "top": -528, "height": 13 }, { @@ -377,7 +377,7 @@ }, "font": "Arial;13;1", "left": 405, - "top": 183, + "top": 167, "width": 548.5517578125, "height": 13, "text": "Cours" @@ -391,7 +391,7 @@ "visible": false, "font": "Arial;13;0", "left": 160, - "top": -496, + "top": -528, "width": 73.67724609375, "height": 13, "text": "(from Model)" @@ -405,14 +405,14 @@ "visible": false, "font": "Arial;13;0", "left": 160, - "top": -496, + "top": -528, "height": 13, "horizontalAlignment": 1 } ], "font": "Arial;13;0", "left": 400, - "top": 176, + "top": 160, "width": 558.5517578125, "height": 25, "stereotypeLabel": { @@ -449,7 +449,7 @@ }, "font": "Arial;13;0", "left": 405, - "top": 206, + "top": 190, "width": 548.5517578125, "height": 13, "text": "-date: LocalDate", @@ -466,7 +466,7 @@ }, "font": "Arial;13;0", "left": 405, - "top": 221, + "top": 205, "width": 548.5517578125, "height": 13, "text": "-prof: String", @@ -483,7 +483,7 @@ }, "font": "Arial;13;0", "left": 405, - "top": 236, + "top": 220, "width": 548.5517578125, "height": 13, "text": "-heureDebut: LocalTime", @@ -500,7 +500,7 @@ }, "font": "Arial;13;0", "left": 405, - "top": 251, + "top": 235, "width": 548.5517578125, "height": 13, "text": "-heureFin: LocalTime", @@ -517,7 +517,7 @@ }, "font": "Arial;13;0", "left": 405, - "top": 266, + "top": 250, "width": 548.5517578125, "height": 13, "text": "-lieu: String", @@ -534,7 +534,7 @@ }, "font": "Arial;13;0", "left": 405, - "top": 281, + "top": 265, "width": 548.5517578125, "height": 13, "text": "-duree: int", @@ -552,7 +552,7 @@ "visible": false, "font": "Arial;13;0", "left": 669, - "top": 80, + "top": 48, "width": 142.23828125, "height": 13, "text": "+classe", @@ -561,7 +561,7 @@ ], "font": "Arial;13;0", "left": 400, - "top": 201, + "top": 185, "width": 558.5517578125, "height": 98 }, @@ -586,7 +586,7 @@ }, "font": "Arial;13;0", "left": 405, - "top": 304, + "top": 288, "width": 548.5517578125, "height": 13, "text": "+Cours(date: LocalDate, prof: String, heureDebut: LocalTime, heureFin: LocalTime, lieu: String)", @@ -603,7 +603,7 @@ }, "font": "Arial;13;0", "left": 405, - "top": 319, + "top": 303, "width": 548.5517578125, "height": 13, "text": "+hashCode(): int", @@ -620,7 +620,7 @@ }, "font": "Arial;13;0", "left": 405, - "top": 334, + "top": 318, "width": 548.5517578125, "height": 13, "text": "+equals(other: Cours): boolean", @@ -637,7 +637,7 @@ }, "font": "Arial;13;0", "left": 405, - "top": 349, + "top": 333, "width": 548.5517578125, "height": 13, "text": "+compareTo(other: Cours): int", @@ -646,7 +646,7 @@ ], "font": "Arial;13;0", "left": 400, - "top": 299, + "top": 283, "width": 558.5517578125, "height": 68 }, @@ -662,7 +662,7 @@ "visible": false, "font": "Arial;13;0", "left": 80, - "top": -248, + "top": -264, "width": 10, "height": 10 }, @@ -678,7 +678,7 @@ "visible": false, "font": "Arial;13;0", "left": 80, - "top": -248, + "top": -264, "width": 10, "height": 10 } @@ -686,7 +686,7 @@ "font": "Arial;13;0", "containerChangeable": true, "left": 400, - "top": 176, + "top": 160, "width": 558.5517578125, "height": 191, "autoResize": true, @@ -727,8 +727,8 @@ }, "visible": false, "font": "Arial;13;0", - "left": 1070, - "top": 238, + "left": 1071, + "top": 232, "height": 13, "alpha": 1.5707963267948966, "distance": 15, @@ -748,8 +748,8 @@ }, "visible": null, "font": "Arial;13;0", - "left": 1070, - "top": 223, + "left": 1071, + "top": 217, "height": 13, "alpha": 1.5707963267948966, "distance": 30, @@ -770,7 +770,7 @@ "visible": false, "font": "Arial;13;0", "left": 1071, - "top": 267, + "top": 262, "height": 13, "alpha": -1.5707963267948966, "distance": 15, @@ -791,7 +791,7 @@ "visible": false, "font": "Arial;13;0", "left": 984, - "top": 241, + "top": 232, "height": 13, "alpha": 0.5235987755982988, "distance": 30, @@ -811,8 +811,8 @@ }, "visible": false, "font": "Arial;13;0", - "left": 986, - "top": 227, + "left": 987, + "top": 219, "height": 13, "alpha": 0.7853981633974483, "distance": 40, @@ -832,8 +832,8 @@ }, "visible": false, "font": "Arial;13;0", - "left": 981, - "top": 268, + "left": 980, + "top": 260, "height": 13, "alpha": -0.5235987755982988, "distance": 25, @@ -853,7 +853,7 @@ }, "font": "Arial;13;0", "left": 1115, - "top": 229, + "top": 225, "width": 48.07080078125, "height": 13, "alpha": -0.46743457487643214, @@ -874,8 +874,8 @@ }, "visible": false, "font": "Arial;13;0", - "left": 1153, - "top": 222, + "left": 1154, + "top": 218, "height": 13, "alpha": -0.7853981633974483, "distance": 40, @@ -894,7 +894,7 @@ }, "font": "Arial;13;0", "left": 1152, - "top": 268, + "top": 264, "width": 7.22998046875, "height": 13, "alpha": 0.5514587292381492, @@ -945,7 +945,7 @@ "$ref": "AAAAAAF3BtFqHc8CoK0=" }, "lineStyle": 1, - "points": "959:263;1183:256", + "points": "959:254;1183:253", "showVisibility": true, "nameLabel": { "$ref": "AAAAAAF3DTscxkfsTQo=" @@ -1305,7 +1305,7 @@ "visible": false, "font": "Arial;13;0", "left": 896, - "top": -192, + "top": -208, "height": 13 }, { @@ -1316,7 +1316,7 @@ }, "font": "Arial;13;1", "left": 1397, - "top": 495, + "top": 487, "width": 345.81396484375, "height": 13, "text": "EmploiDuTempsProxy" @@ -1330,7 +1330,7 @@ "visible": false, "font": "Arial;13;0", "left": 896, - "top": -192, + "top": -208, "width": 73.67724609375, "height": 13, "text": "(from Model)" @@ -1344,14 +1344,14 @@ "visible": false, "font": "Arial;13;0", "left": 896, - "top": -192, + "top": -208, "height": 13, "horizontalAlignment": 1 } ], "font": "Arial;13;0", "left": 1392, - "top": 488, + "top": 480, "width": 355.81396484375, "height": 25, "stereotypeLabel": { @@ -1388,7 +1388,7 @@ }, "font": "Arial;13;0", "left": 1397, - "top": 518, + "top": 510, "width": 345.81396484375, "height": 13, "text": "-singleton: EmploiDuTempsProxy", @@ -1397,7 +1397,7 @@ ], "font": "Arial;13;0", "left": 1392, - "top": 513, + "top": 505, "width": 355.81396484375, "height": 23 }, @@ -1422,7 +1422,7 @@ }, "font": "Arial;13;0", "left": 1397, - "top": 541, + "top": 533, "width": 345.81396484375, "height": 13, "text": "-EmploiDuTempsProxy()", @@ -1439,7 +1439,7 @@ }, "font": "Arial;13;0", "left": 1397, - "top": 556, + "top": 548, "width": 345.81396484375, "height": 13, "text": "+getInstance(): EmploiDuTempsProxy", @@ -1456,7 +1456,7 @@ }, "font": "Arial;13;0", "left": 1397, - "top": 571, + "top": 563, "width": 345.81396484375, "height": 13, "text": "+actualiser()", @@ -1473,7 +1473,7 @@ }, "font": "Arial;13;0", "left": 1397, - "top": 586, + "top": 578, "width": 345.81396484375, "height": 13, "text": "+getPlanningOf(date: LocalDate): Planning", @@ -1490,7 +1490,7 @@ }, "font": "Arial;13;0", "left": 1397, - "top": 601, + "top": 593, "width": 345.81396484375, "height": 13, "text": "+getPlanningOf(date: LocalDate, groupe: Groupe): Planning", @@ -1507,7 +1507,7 @@ }, "font": "Arial;13;0", "left": 1397, - "top": 616, + "top": 608, "width": 345.81396484375, "height": 13, "text": "+getPlanning(groupe: Groupe): Planning", @@ -1516,7 +1516,7 @@ ], "font": "Arial;13;0", "left": 1392, - "top": 536, + "top": 528, "width": 355.81396484375, "height": 98 }, @@ -1532,7 +1532,7 @@ "visible": false, "font": "Arial;13;0", "left": 448, - "top": -96, + "top": -104, "width": 10, "height": 10 }, @@ -1548,7 +1548,7 @@ "visible": false, "font": "Arial;13;0", "left": 448, - "top": -96, + "top": -104, "width": 10, "height": 10 } @@ -1556,7 +1556,7 @@ "font": "Arial;13;0", "containerChangeable": true, "left": 1392, - "top": 488, + "top": 480, "width": 355.81396484375, "height": 146, "autoResize": true, @@ -1658,7 +1658,7 @@ "$ref": "AAAAAAF3DT7GhU0hyZc=" }, "lineStyle": 1, - "points": "1569:634;1568:720;1328:720;1329.0833333333333:776", + "points": "1569:626;1568:720;1328:720;1329.0833333333333:776", "showVisibility": true, "nameLabel": { "$ref": "AAAAAAF3DUCFV1J1GXc=" @@ -1692,7 +1692,7 @@ "visible": false, "font": "Arial;13;0", "left": 1304, - "top": 564, + "top": 561, "height": 13, "alpha": 1.5707963267948966, "distance": 15, @@ -1713,7 +1713,7 @@ "visible": null, "font": "Arial;13;0", "left": 1304, - "top": 579, + "top": 576, "height": 13, "alpha": 1.5707963267948966, "distance": 30, @@ -1734,7 +1734,7 @@ "visible": false, "font": "Arial;13;0", "left": 1305, - "top": 535, + "top": 531, "height": 13, "alpha": -1.5707963267948966, "distance": 15, @@ -1754,8 +1754,8 @@ }, "visible": false, "font": "Arial;13;0", - "left": 1364, - "top": 565, + "left": 1365, + "top": 560, "height": 13, "alpha": 0.5235987755982988, "distance": 30, @@ -1776,7 +1776,7 @@ "visible": false, "font": "Arial;13;0", "left": 1362, - "top": 578, + "top": 574, "height": 13, "alpha": 0.7853981633974483, "distance": 40, @@ -1797,7 +1797,7 @@ "visible": false, "font": "Arial;13;0", "left": 1369, - "top": 538, + "top": 533, "height": 13, "alpha": -0.5235987755982988, "distance": 25, @@ -1817,7 +1817,7 @@ }, "font": "Arial;13;0", "left": 1232, - "top": 564, + "top": 560, "width": 143.05078125, "height": 13, "alpha": -0.17181522579126562, @@ -1838,8 +1838,8 @@ }, "visible": false, "font": "Arial;13;0", - "left": 1247, - "top": 577, + "left": 1248, + "top": 574, "height": 13, "alpha": -0.7853981633974483, "distance": 40, @@ -1858,7 +1858,7 @@ }, "font": "Arial;13;0", "left": 1238, - "top": 536, + "top": 533, "width": 7.22998046875, "height": 13, "alpha": 0.5235987755982988, @@ -1909,7 +1909,7 @@ "$ref": "AAAAAAF3DT7GhU0hyZc=" }, "lineStyle": 1, - "points": "1391:557;1220:555", + "points": "1391:552;1220:552", "showVisibility": true, "nameLabel": { "$ref": "AAAAAAF3DUC3aFL/gAk=" @@ -2231,7 +2231,7 @@ "visible": false, "font": "Arial;13;0", "left": 660, - "top": 540, + "top": 532, "height": 13, "alpha": 1.5707963267948966, "distance": 15, @@ -2252,7 +2252,7 @@ "visible": null, "font": "Arial;13;0", "left": 645, - "top": 540, + "top": 532, "height": 13, "alpha": 1.5707963267948966, "distance": 30, @@ -2273,7 +2273,7 @@ "visible": false, "font": "Arial;13;0", "left": 689, - "top": 541, + "top": 533, "height": 13, "alpha": -1.5707963267948966, "distance": 15, @@ -2355,8 +2355,8 @@ "$ref": "AAAAAAF3DYJbn2gpgTM=" }, "font": "Arial;13;0", - "left": 687, - "top": 397, + "left": 688, + "top": 380, "width": 39.380859375, "height": 13, "alpha": 0.7027596317365179, @@ -2378,7 +2378,7 @@ "visible": false, "font": "Arial;13;0", "left": 648, - "top": 389, + "top": 373, "height": 13, "alpha": -0.7853981633974483, "distance": 40, @@ -2397,7 +2397,7 @@ }, "font": "Arial;13;0", "left": 686, - "top": 382, + "top": 366, "width": 6.5, "height": 13, "alpha": 0.5235987755982988, @@ -2448,7 +2448,7 @@ "$ref": "AAAAAAF3DYIX12eTj4w=" }, "lineStyle": 1, - "points": "674:727;677:367", + "points": "674:727;677:351", "showVisibility": true, "nameLabel": { "$ref": "AAAAAAF3DYJboGgs9YE=" @@ -5408,8 +5408,8 @@ "$ref": "AAAAAAF3EcZcAc7ATz4=" }, "font": "Arial;13;0", - "left": 260, - "top": 271, + "left": 261, + "top": 265, "width": 65.37451171875, "height": 13, "alpha": 1.5707963267948966, @@ -5430,8 +5430,8 @@ "$ref": "AAAAAAF3EcZcAc7ATz4=" }, "font": "Arial;13;0", - "left": 273, - "top": 286, + "left": 274, + "top": 280, "width": 39.0380859375, "height": 13, "alpha": 1.5707963267948966, @@ -5453,8 +5453,8 @@ }, "visible": false, "font": "Arial;13;0", - "left": 293, - "top": 242, + "left": 292, + "top": 236, "height": 13, "alpha": -1.5707963267948966, "distance": 15, @@ -5472,7 +5472,7 @@ "$ref": "AAAAAAF3BtFqHc8CoK0=" }, "lineStyle": 1, - "points": "399:265;188:261", + "points": "399:257;188:258", "showVisibility": true, "nameLabel": { "$ref": "AAAAAAF3EcZcAs7DOgk=" @@ -5505,8 +5505,8 @@ }, "visible": false, "font": "Arial;13;0", - "left": 537, - "top": 407, + "left": 539, + "top": 399, "height": 13, "alpha": 1.5707963267948966, "distance": 15, @@ -5526,8 +5526,8 @@ }, "visible": null, "font": "Arial;13;0", - "left": 526, - "top": 397, + "left": 527, + "top": 390, "height": 13, "alpha": 1.5707963267948966, "distance": 30, @@ -5547,8 +5547,8 @@ }, "visible": false, "font": "Arial;13;0", - "left": 560, - "top": 426, + "left": 562, + "top": 418, "height": 13, "alpha": -1.5707963267948966, "distance": 15, @@ -5566,7 +5566,7 @@ "$ref": "AAAAAAF3EAgksCDarvI=" }, "lineStyle": 1, - "points": "502:479;597:367", + "points": "500:479;602:351", "showVisibility": true, "nameLabel": { "$ref": "AAAAAAF3Ece2UdGnMao=" @@ -5605,7 +5605,7 @@ "$ref": "AAAAAAF3DT7GhU0hyZc=" }, "lineStyle": 1, - "points": "1748:543;1816:537" + "points": "1748:539;1816:535" }, { "_type": "UMLNoteView", @@ -5615,7 +5615,7 @@ }, "font": "Arial;13;0", "left": 280, - "top": 136, + "top": 120, "width": 145, "height": 38, "text": "Compare heureDebut" @@ -5634,7 +5634,7 @@ "$ref": "AAAAAAF3EcZcAs7CKZI=" }, "lineStyle": 1, - "points": "293:263;341:174" + "points": "293:257;342:158" }, { "_type": "UMLNoteView", @@ -6042,7 +6042,8 @@ "_parent": { "$ref": "AAAAAAF3BtFqHc8AoKI=" }, - "name": "classe" + "name": "classe", + "type": "" } ], "operations": [ @@ -6796,7 +6797,8 @@ "_parent": { "$ref": "AAAAAAF3EDiSNTms2ZQ=" }, - "name": "groupe" + "name": "groupe", + "type": "" }, { "_type": "UMLParameter", @@ -6825,7 +6827,8 @@ "_parent": { "$ref": "AAAAAAF3EDkI9joluB4=" }, - "name": "groupe" + "name": "groupe", + "type": "" }, { "_type": "UMLParameter", @@ -6979,7 +6982,8 @@ "_parent": { "$ref": "AAAAAAF3EIEEflAw1Y8=" }, - "name": "other" + "name": "other", + "type": "" }, { "_type": "UMLParameter", diff --git a/src/main/java/edt/umontp/fr/App.java b/src/main/java/edt/umontp/fr/App.java deleted file mode 100644 index 02d7dee..0000000 --- a/src/main/java/edt/umontp/fr/App.java +++ /dev/null @@ -1,13 +0,0 @@ -package edt.umontp.fr; - -/** - * Hello world! - * - */ -public class App -{ - public static void main( String[] args ) - { - System.out.println( "Hello World!" ); - } -} diff --git a/src/main/java/edt/umontp/fr/Cours.java b/src/main/java/edt/umontp/fr/Cours.java new file mode 100644 index 0000000..c0f992f --- /dev/null +++ b/src/main/java/edt/umontp/fr/Cours.java @@ -0,0 +1,256 @@ +package edt.umontp.fr; + +import java.text.ParseException; +import java.time.Duration; +import java.time.LocalDate; +import java.time.LocalTime; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Locale; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import net.fortuna.ical4j.model.Component; +import net.fortuna.ical4j.model.DateTime; +import net.fortuna.ical4j.model.Property; + +/** + * Cours est la classe représentant un cours au sein du planning. + *

+ * Un objet Cours est caractérisé par les informations suivantes : + *

    + *
  • Une date.
  • + *
  • D'une liste de professeurs.
  • + *
  • D'une heure de début.
  • + *
  • D'une heure de fin.
  • + *
  • D'une durée.
  • + *
  • D'une liste de {@link Groupe}.
  • + *
  • D'un intitule.
  • + *
+ * + * @see Comparable + * + * @author emerick-biron + * @author MathieuSoysal + * @version 1.0.0 + */ +public class Cours implements Comparable { + private LocalDate date; + private String[] prof; + private LocalTime heureDebut; + private LocalTime heureFin; + private String lieu; + private int duree; + private Groupe[] groupes; + private String intitule; + + public Cours(LocalDate date, String[] prof, LocalTime heureDebut, LocalTime heureFin, String lieu, Groupe[] groupe, + String intitule) { + this.date = date; + this.prof = prof; + this.heureDebut = heureDebut; + this.heureFin = heureFin; + this.lieu = lieu; + this.groupes = groupe; + this.intitule = intitule; + duree = (int) Duration.between(heureDebut, heureFin).toMinutes(); + } + + /** + * Constructeur Cours. + *

+ * Le constructeur est chargé de trouver toutes attributs de class {@link Cours} + * au sein du {@link Component}. + *

+ * + * @param vEvent l'évenement du calendrier qui représente un cours + * + * @see Component + */ + @SuppressWarnings("deprecation") + Cours(Component vEvent) { + Property summary = vEvent.getProperty(Property.SUMMARY); + Property description = vEvent.getProperty(Property.DESCRIPTION); + Property dtStart = vEvent.getProperty(Property.DTSTART); + Property dtEnd = vEvent.getProperty(Property.DTEND); + Property location = vEvent.getProperty(Property.LOCATION); + + DateTime dateDebut = null; + DateTime dateFin = null; + try { + dateDebut = new DateTime(dtStart.getValue()); + dateFin = new DateTime(dtEnd.getValue()); + } catch (ParseException e) { + e.printStackTrace(); + } + + date = LocalDate.of(dateDebut.getYear() + 1900, dateDebut.getMonth() + 1, dateDebut.getDate()); + heureDebut = LocalTime.of(dateDebut.getHours(), dateDebut.getMinutes()); + heureFin = LocalTime.of(dateFin.getHours(), dateFin.getMinutes()); + lieu = location.getValue(); + intitule = summary.getValue(); + prof = getProfFromDesc(description.getValue()); + groupes = Groupe.getGroupeDepuisTexte(description.getValue()); + duree = (int) Duration.between(heureDebut, heureFin).toMinutes(); + } + + /** + * Permet d'obtenir le(s) professeur(s) d'un VENVENT a partir de la description + * de ce dernier + * + * @param desc description du VENVENT + * @return {@code String[]} le(s) professeur(s) du present dans la description + * @since 1.0 + */ + static String[] getProfFromDesc(String desc) { + String regex = "(?<=\\n)[- A-Z]* [- A-Z]*(?=\\n)"; + Matcher m = Pattern.compile(regex).matcher(desc); + final List matches = new ArrayList<>(); + while (m.find()) { + matches.add(m.group(0)); + } + return matches.toArray(new String[matches.size()]); + } + + @Override + public int compareTo(Cours o) { + int result = date.compareTo(o.date); + if (result != 0) + return result; + result = heureDebut.compareTo(o.heureDebut); + if (result != 0) + return result; + result = Integer.compare(duree, o.duree); + if (result != 0) + return result; + for (Groupe groupe : groupes) + for (Groupe autreGroupe : o.groupes) { + result = groupe.getIntitule().compareTo(autreGroupe.getIntitule()); + if (result != 0) + return result; + } + return intitule.compareTo(o.intitule); + } + + /** + * @return {@code LocalDate} la date de début du cours + */ + public LocalDate getDate() { + return date; + } + + /** + * @return {@code String[]} les professeurs organisant le cours + */ + public String[] getProf() { + return prof; + } + + /** + * @return {@code LocalTime} l'heure de début du cours + */ + public LocalTime getHeureDebut() { + return heureDebut; + } + + /** + * @return {@code LocalTime} l'heure de fin du cours + */ + public LocalTime getHeureFin() { + return heureFin; + } + + /** + * @return {@code String} le lieu + */ + public String getLieu() { + return lieu; + } + + /** + * @return {@code int} la durée du cours + */ + public int getDuree() { + return duree; + } + + /** + * @return {@code Groupe[]} les groupes assignés au cours + * + * @see Groupe + */ + public Groupe[] getGroupes() { + return groupes; + } + + /** + * @return {@code String} l'intitulé du cours + */ + public String getIntitule() { + return intitule; + } + + @Override + public String toString() { + return intitule.toUpperCase(Locale.ROOT) + " :\n Date : " + date + "\n Commence à " + heureDebut + ", finit à " + + heureFin + "\n Enseignant :" + Arrays.toString(prof) + " \n Localisation : " + lieu + " \n Groupe : " + + Arrays.toString(groupes); + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#hashCode() + */ + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((date == null) ? 0 : date.hashCode()); + for (Groupe groupe : groupes) + result = prime * result + ((groupe == null) ? 0 : groupe.hashCode()); + result = prime * result + ((heureDebut == null) ? 0 : heureDebut.hashCode()); + result = prime * result + ((lieu == null) ? 0 : lieu.hashCode()); + return result; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#equals(java.lang.Object) + */ + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Cours other = (Cours) obj; + if (date == null) { + if (other.date != null) + return false; + } else if (!date.equals(other.date)) + return false; + for (Groupe groupe : groupes) + for (Groupe oGroupe : other.groupes) + if (groupe != oGroupe) + return false; + if (heureDebut == null) { + if (other.heureDebut != null) + return false; + } else if (!heureDebut.equals(other.heureDebut)) + return false; + if (lieu == null) { + if (other.lieu != null) + return false; + } else if (!lieu.equals(other.lieu)) + return false; + return true; + } + +} diff --git a/src/main/java/edt/umontp/fr/EmploiDuTemps.java b/src/main/java/edt/umontp/fr/EmploiDuTemps.java new file mode 100644 index 0000000..4f2ab58 --- /dev/null +++ b/src/main/java/edt/umontp/fr/EmploiDuTemps.java @@ -0,0 +1,180 @@ +package edt.umontp.fr; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.time.LocalDate; +import java.time.ZoneId; +import java.util.ArrayList; + +import net.fortuna.ical4j.data.CalendarBuilder; +import net.fortuna.ical4j.data.ParserException; +import net.fortuna.ical4j.model.Calendar; +import net.fortuna.ical4j.model.Component; + +/** + * EmploisDuTemps est la classe représentant tout l'emploi du temps + * l'unviersité. + *

+ * De plus, l'EmploiDuTemps est un singleton, il ne peut y avoir donc qu'une + * instance de celle-ci. + *

+ * + * @deprecated Pour l'utilisation de la class EmploiDuTemps, il est préférable + * de passer par son proxy : {@link EmploiDuTempsProxy} afin d'avoir + * de meilleurs temps de réponse. + * + * @see InterfaceEmploiDuTemps + * @see EmploiDuTempsProxy + * + * @author emerick-biron + * @author MathieuSoysal + * @version 1.0.0 + */ +@Deprecated(forRemoval = false) +public final class EmploiDuTemps implements InterfaceEmploiDuTemps { + static final ZoneId ZONE_ID = ZoneId.of("Europe/Paris"); + private static EmploiDuTemps singleton = null; + private final String LIEN_ICAL = "https://proseconsult.umontpellier.fr/jsp/custom/modules/plannings/direct_cal" + + ".jsp?data" + + "=58c99062bab31d256bee14356aca3f2423c0f022cb9660eba051b2653be722c431b66c493702208e664667048bc04373dc5c094f7d1a811b903031bde802c7f59b21846d3c6254443d7b6e956d3145c6e0d5bac87b70fdd185b8b86771d71211a02411e8351020815cfb0dcc54c667187353dbcfc377b44753a4f433d4e51f753c2b0fc0eafdcbc1cbb6ef4e715ebea9d495758b595b12cb294e70e715876fbaa3c654023c76f43cd51442775ff171e0a5f21b50c55a5b52d94df3e7977af823a1e78ee86c6497b1cf8732d52143eeffacc27449fc13ec1f0b04d23e09712df15579474e1aa0cd65f50f33a1dd766301,1"; + private Planning planningEmploisDuTemps; + + /** + * Permet mettre a jour l'emploi du temps + * + * @since 1.0 + */ + private EmploiDuTemps() { + actualiser(); + } + + /** + * Retourne l'instance de {@link EmploiDuTemps}. + * + * @return {@code EmploiDuTemps} + * + * @deprecated Pour des raisons d'optimisation il est préférable de passer pour + * le proxy : {@link EmploiDuTempsProxy} + * + * @see EmploiDuTempsProxy + */ + @Deprecated + public static EmploiDuTemps getInstance() { + EmploiDuTemps localInstance = singleton; + if (localInstance == null) { + synchronized (EmploiDuTemps.class) { + localInstance = singleton; + if (localInstance == null) { + localInstance = new EmploiDuTemps(); + } + } + } + return localInstance; + } + + /** + * Permet d'obtenir un objet {@link Calendar} a parti d'un fichier ics + * + * @param fichierIcs fichier ics source + * @return objet calendar corespondant + * @since 1.0 + */ + private Calendar convertieFichierIcsEnCalendar(File fichierIcs) { + Calendar calendar = null; + try (FileInputStream fileICS = new FileInputStream(fichierIcs)) { + CalendarBuilder builder = new CalendarBuilder(); + calendar = builder.build(fileICS); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } catch (ParserException e) { + e.printStackTrace(); + } + return calendar; + } + + /** + * Permet d'obtenir un fichier ics correspondant a un lien iCal (ici lien iCal = + * {@link #LIEN_ICAL} + * + * @return fichier ics correspondant + * @since 1.0 + */ + private File getFichierIcsDepuisLienIcal() { + File fichierIcs = new File("fichier.ics"); + if (fichierIcs.isFile()) { + fichierIcs.delete(); + } + try { + URL url = new URL(LIEN_ICAL); + InputStream in = url.openStream(); + Files.copy(in, Paths.get(fichierIcs.getName())); + } catch (IOException e) { + e.printStackTrace(); + } + return fichierIcs; + } + + @Override + public void actualiser() { + File fichierIcs = getFichierIcsDepuisLienIcal(); + Calendar calendar = convertieFichierIcsEnCalendar(fichierIcs); + ArrayList coursList = new ArrayList<>(); + for (Object vEvent : calendar.getComponents(Component.VEVENT)) { + coursList.add(new Cours((Component) vEvent)); + } + planningEmploisDuTemps = new Planning(coursList); + } + + /** + * Permet d'obtenir le planning correspondant à une date + * + * @param date date pour laquelle on veut obtenir le planning + * @return {@code Planning} correspondant + * @since 1.0 + * + * @see Planning + */ + @Override + public Planning getPlanningOf(LocalDate date) { + return planningEmploisDuTemps.getPlanningOf(date); + } + + /** + * Permet d'obtenir le planning correspondant à une date et un groupe + * + * @param date date dont on veut obtenir le planning + * @param groupe groupe dont on veut obtenir le planning + * @return planning correspondant + * @since 1.0 + * + * @see Groupe + * @see Planning + */ + @Override + public Planning getPlanningOf(LocalDate date, Groupe groupe) { + return planningEmploisDuTemps.getPlanningOf(date, groupe); + } + + /** + * Permet d'obtenir le planning correspondant à un groupe + * + * @param groupe groupe dont on veut obtenir le planning + * @return planning correspondant + * @since 1.0 + * + * @see Groupe + * @see Planning + */ + @Override + public Planning getPlanningOf(Groupe groupe) { + return planningEmploisDuTemps.getPlanningOf(groupe); + } +} diff --git a/src/main/java/edt/umontp/fr/EmploiDuTempsProxy.java b/src/main/java/edt/umontp/fr/EmploiDuTempsProxy.java new file mode 100644 index 0000000..773ae07 --- /dev/null +++ b/src/main/java/edt/umontp/fr/EmploiDuTempsProxy.java @@ -0,0 +1,151 @@ +package edt.umontp.fr; + +import java.time.LocalDate; +import java.util.EnumMap; +import java.util.HashMap; + +/** + * EmploiDuTempsProxy est la classe représentant le proxy de la class + * {@link EmploiDuTemps}. + *

+ * L'instance d'EmploiDuTempsProxy est caractérisé par une liste de cache. + * + * @author emerick-biron + * @author MathieuSoysal + * @version 1.0.0 + * @see EmploiDuTemps + * @see InterfaceEmploiDuTemps + */ +public final class EmploiDuTempsProxy implements InterfaceEmploiDuTemps { + private static EmploiDuTempsProxy singleton = null; + @SuppressWarnings("deprecation") + private EmploiDuTemps emploiDuTemps; + private EnumMap cacheGroupe; + private HashMap cacheDate; + private HashMap, Planning> cacheDateGroupe; + + @SuppressWarnings("deprecation") + private EmploiDuTempsProxy() { + emploiDuTemps = EmploiDuTemps.getInstance(); + actualiser(); + } + + /** + * @return l'instance de {@link EmploiDuTempsProxy}. + * + */ + public static EmploiDuTempsProxy getInstance() { + EmploiDuTempsProxy localInstance = singleton; + if (localInstance == null) { + synchronized (EmploiDuTempsProxy.class) { + localInstance = singleton; + if (localInstance == null) { + localInstance = new EmploiDuTempsProxy(); + } + } + } + return localInstance; + } + + /** + * Permet d'obtenir le planning correspondant à une date + * + * @param date date pour laquelle on veut obtenir le planning + * @return {@code Planning} correspondant + * @since 1.0 + * + * @see Planning + */ + @SuppressWarnings("deprecation") + @Override + public Planning getPlanningOf(LocalDate date) { + return cacheDate.computeIfAbsent(date, k -> emploiDuTemps.getPlanningOf(k)); + } + + /** + * Permet d'obtenir le planning correspondant à une date et un groupe + * + * @param date date dont on veut obtenir le planning + * @param groupe groupe dont on veut obtenir le planning + * @return planning correspondant + * @since 1.0 + * + * @see Groupe + * @see Planning + */ + @Override + public Planning getPlanningOf(LocalDate date, Groupe groupe) { + MultiKey multiKey = new MultiKey<>(date, groupe); + return cacheDateGroupe.computeIfAbsent(multiKey, k -> getPlanningOf(k.key1).getPlanningOf(k.key2)); + } + + /** + * Permet d'obtenir le planning correspondant à un groupe + * + * @param groupe groupe dont on veut obtenir le planning + * @return planning correspondant + * @since 1.0 + * + * @see Groupe + * @see Planning + */ + @SuppressWarnings("deprecation") + @Override + public Planning getPlanningOf(Groupe groupe) { + return cacheGroupe.computeIfAbsent(groupe, k -> emploiDuTemps.getPlanningOf(k)); + } + + /** + * Permet d'actualiser l'emploi du temps avec celui de l'ent. + */ + @SuppressWarnings("deprecation") + @Override + public void actualiser() { + cacheDate = new HashMap<>(); + cacheGroupe = new EnumMap<>(Groupe.class); + cacheDateGroupe = new HashMap<>(); + emploiDuTemps.actualiser(); + } + + /** + * Cette classe représente une combinaison de clefs + */ + private class MultiKey { + private K1 key1; + private K2 key2; + + public MultiKey(K1 key1, K2 key2) { + this.key1 = key1; + this.key2 = key2; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + MultiKey key = (MultiKey) o; + + if (key1 != null ? !key1.equals(key.key1) : key.key1 != null) + return false; + if (key2 != null ? !key2.equals(key.key2) : key.key2 != null) + return false; + + return true; + } + + @Override + public int hashCode() { + int result = key1 != null ? key1.hashCode() : 0; + result = 31 * result + (key2 != null ? key2.hashCode() : 0); + return result; + } + + @Override + public String toString() { + return "[" + key1 + ", " + key2 + "]"; + } + } +} diff --git a/src/main/java/edt/umontp/fr/Groupe.java b/src/main/java/edt/umontp/fr/Groupe.java new file mode 100644 index 0000000..a03ae0f --- /dev/null +++ b/src/main/java/edt/umontp/fr/Groupe.java @@ -0,0 +1,296 @@ +package edt.umontp.fr; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Groupe est une enumeration qui permet de recenser les différents groupes + * d'élèves de l'université + *

+ * Une instance de groupe est caractérisé par les informations suivantes : + *

    + *
  • Un intitulé.
  • + *
  • Un groupe parent.
  • + *
+ *

+ * De plus, un {@link Groupe} ne pas être instancié, il faut donc passer par + * l'enumération. + *

+ * + * + * @author emerick-biron + * @author MathieuSoysal + * @version 1.2.0 + */ +public enum Groupe { + /** + * {@code A1} est l'objet représentant les classes de première année du + * département informatique de l'IUT de Montpellier. + * + * Cet objet n'est pas modifiable. + * + * @see Groupe + */ + A1("A1"), + + /** + * {@code S1} est l'objet représentant le premier groupe des étudiants de + * première année du département informatique de l'IUT de Montpellier. + * + * Cet objet n'est pas modifiable. + * + * @see Groupe + */ + S1("S1", A1), + /** + * {@code S2} est l'objet représentant le deuxième groupe des étudiants de + * première année du département informatique de l'IUT de Montpellier. + * + * Cet objet n'est pas modifiable. + * + * @see Groupe + */ + S2("S2", A1), + /** + * {@code S3} est l'objet représentant le troisième groupe des étudiants de + * première année du département informatique de l'IUT de Montpellier. + * + * Cet objet n'est pas modifiable. + * + * @see Groupe + */ + S3("S3", A1), + /** + * {@code S4} est l'objet représentant le quatrième groupe des étudiants de + * première année du département informatique de l'IUT de Montpellier. + * + * Cet objet n'est pas modifiable. + * + * @see Groupe + */ + S4("S4", A1), + /** + * {@code S5} est l'objet représentant le cinquième groupe des étudiants de + * première année du département informatique de l'IUT de Montpellier. + * + * Cet objet n'est pas modifiable. + * + * @see Groupe + */ + S5("S5", A1), + /** + * {@code S6} est l'objet représentant le sixième groupe des étudiants de + * première année du département informatique de l'IUT de Montpellier. + * + * Cet objet n'est pas modifiable. + * + * @see Groupe + */ + S6("S6", A1), + /** + * {@code A2} est l'objet représentant les classes de deuxième année du + * département informatique de l'IUT de Montpellier. + * + * Cet objet n'est pas modifiable. + * + * @see Groupe + */ + A2("A2"), + /** + * {@code Q1} est l'objet représentant le premier groupe des étudiants de + * deuxième année de troisième semestre du département informatique de l'IUT de + * Montpellier. + * + * Cet objet n'est pas modifiable. + * + * @see Groupe + */ + Q1("Q1", A2), + /** + * {@code Q2} est l'objet représentant le deuxième groupe des étudiants de + * deuxième année de troisième semestre du département informatique de l'IUT de + * Montpellier. + * + * Cet objet n'est pas modifiable. + * + * @see Groupe + */ + Q2("Q2", A2), + /** + * {@code Q3} est l'objet représentant le troisième groupe des étudiants de + * deuxième année de troisième semestre du département informatique de l'IUT de + * Montpellier. + * + * Cet objet n'est pas modifiable. + * + * @see Groupe + */ + Q3("Q3", A2), + /** + * {@code Q4} est l'objet représentant le quatrième groupe des étudiants de + * deuxième année de troisième semestre du département informatique de l'IUT de + * Montpellier. + * + * Cet objet n'est pas modifiable. + * + * @see Groupe + */ + Q4("Q4", A2), + /** + * {@code G1} est l'objet représentant le premier groupe des étudiants de + * deuxième année de quatrième semestre du département informatique de l'IUT de + * Montpellier. + * + * Cet objet n'est pas modifiable. + * + * @see Groupe + */ + G1("G1", A2), + /** + * {@code G2} est l'objet représentant le deuxième groupe des étudiants de + * deuxième année de quatrième semestre du département informatique de l'IUT de + * Montpellier. + * + * Cet objet n'est pas modifiable. + * + * @see Groupe + */ + G2("G2", A2), + /** + * {@code G3} est l'objet représentant le troisième groupe des étudiants de + * deuxième année de quatrième semestre du département informatique de l'IUT de + * Montpellier. + * + * Cet objet n'est pas modifiable. + * + * @see Groupe + */ + G3("G3", A2), + /** + * {@code G4} est l'objet représentant le quatrième groupe des étudiants de + * deuxième année de quatrième semestre du département informatique de l'IUT de + * Montpellier. + * + * Cet objet n'est pas modifiable. + * + * @see Groupe + */ + G4("G4", A2); + + /** + * Ce regex permet de trouver quelles groupe ont étés référencé au sein d'un + * texte. + * + * @see Groupe#getGroupeDepuisTexte(String) + */ + private static final String REGEX; + + static { + Groupe[] groupes = values(); + String[] strings = new String[groupes.length]; + for (int i = 0; i < strings.length; i++) + strings[i] = groupes[i].getIntitule(); + REGEX = String.format("(%s)", String.join("|", strings)); + } + + /** + * Intitule du groupe, l'intitule est utilisé pour retrouver quelles sont les + * groupes qui ont étés référencé au sein d'un texte. + * + * @see Groupe#REGEX + */ + private String intitule; + + /** + * Cet attribut permet de représenter le groupe englobant le groupe actuel + * (this) + * + * Par exemple : Le groupe parent de {@code S1} est {@code A1} car {@code A1} + * contient {@code S1} + * + * @see Groupe#S1 + * @see Groupe#A1 + * @see Groupe#estContenuDans(Groupe) + */ + private Groupe groupeParent; + + /** + * @param intitule + * + * @see Groupe#intitule + */ + private Groupe(String intitule) { + this.intitule = intitule; + groupeParent = null; + } + + /** + * @param intitule + * @param groupeParent + * + * @see Groupe#intitule + * @see Groupe#groupeParent + */ + private Groupe(String intitule, Groupe groupeParent) { + this.intitule = intitule; + this.groupeParent = groupeParent; + } + + /** + * Permet d'obtenir le(s) groupe(s) d'enseignement a partir d'un texte (dans le + * cadre de cette API a partir de la description d'un VEVENT) + * + * @param texte texte source (ici description) + * @return {@code Groupe[]} groupe(s) correspondant + * @since 1.0 + */ + public static Groupe[] getGroupeDepuisTexte(String texte) { + final Matcher m = Pattern.compile(REGEX).matcher(texte); + Collection result = new ArrayList<>(); + while (m.find()) + result.add(valueOf(m.group(0))); + return result.toArray(Groupe[]::new); + } + + /** + * @return {@code String}l'intitule du groupe + * + * @see Groupe#intitule + */ + public String getIntitule() { + return intitule; + } + + /** + * Permet de savoir si ce groupe appartient a un autre groupe + * + * @return {@code boolean} + * @since 1.0 + * + * @see Groupe#groupeParent + */ + private boolean possedeGroupeParent() { + return groupeParent != null; + } + + /** + * Permet de savoir si ce groupe est contenu dans {@code autreGroupe} + * + * @param autreGroupe {@link Groupe} auquel on vérifie s'il contient le groupe + * actuel (this) + * + * @return {@code boolean} + * @since 1.0 + * + * @see Groupe#groupeParent + * @see Groupe#possedeGroupeParent() + */ + public boolean estContenuDans(Groupe... autreGroupes) { + for (Groupe aGroupe : autreGroupes) + if (aGroupe == this || (possedeGroupeParent() && groupeParent.estContenuDans(aGroupe))) + return true; + return false; + } +} diff --git a/src/main/java/edt/umontp/fr/InterfaceEmploiDuTemps.java b/src/main/java/edt/umontp/fr/InterfaceEmploiDuTemps.java new file mode 100644 index 0000000..f45a371 --- /dev/null +++ b/src/main/java/edt/umontp/fr/InterfaceEmploiDuTemps.java @@ -0,0 +1,17 @@ +package edt.umontp.fr; + +/** + * InterfaceEmploisDuTemps est un interface proposant des méthodes pour un emploi du temps + * + * @author emerick-biron + * @author MathieuSoysal + * @version 1.0 + * @see Planifiable + */ +interface InterfaceEmploiDuTemps extends Planifiable { + + /** + * Permet d'actualiser l'emploi du temps avec celui de l'ent. + */ + public void actualiser(); +} diff --git a/src/main/java/edt/umontp/fr/Planifiable.java b/src/main/java/edt/umontp/fr/Planifiable.java new file mode 100644 index 0000000..3266e7f --- /dev/null +++ b/src/main/java/edt/umontp/fr/Planifiable.java @@ -0,0 +1,50 @@ +package edt.umontp.fr; + +import java.time.LocalDate; + +/** + * Planifiable est une interface proposant des méthodes pour gérer un emploi du + * temps + * + * @author emerick-biron + * @author MathieuSoysal + * @version 1.0 + */ +interface Planifiable { + /** + * Permet d'obtenir le planning correspondant à une date + * + * @param date date pour laquelle on veut obtenir le planning + * @return {@code Planning} correspondant + * @since 1.0 + * + * @see Planning + */ + public Planning getPlanningOf(LocalDate date); + + /** + * Permet d'obtenir le planning correspondant à une date et un groupe + * + * @param date date dont on veut obtenir le planning + * @param groupe groupe dont on veut obtenir le planning + * @return planning correspondant + * @since 1.0 + * + * @see Groupe + * @see Planning + */ + public Planning getPlanningOf(LocalDate date, Groupe groupe); + + /** + * Permet d'obtenir le planning correspondant à un groupe + * + * @param groupe groupe dont on veut obtenir le planning + * @return planning correspondant + * @since 1.0 + * + * @see Groupe + * @see Planning + */ + public Planning getPlanningOf(Groupe groupe); + +} diff --git a/src/main/java/edt/umontp/fr/Planning.java b/src/main/java/edt/umontp/fr/Planning.java new file mode 100644 index 0000000..ebee51d --- /dev/null +++ b/src/main/java/edt/umontp/fr/Planning.java @@ -0,0 +1,132 @@ +package edt.umontp.fr; + +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.SortedSet; +import java.util.Spliterator; +import java.util.TreeSet; +import java.util.function.Consumer; +import java.util.stream.Collectors; + +/** + * Planning est la classe représentant un planning de {@link Cours} de + * l'empois du temps de l'université. + *

+ * Une instance de Planning est caractérisé par une liste de {@link Cours} + *

+ * + * @see Iterable + * @see Planifiable + * @see Cours + * + * @author emerick-biron + * @author MathieuSoysal + * @version 1.0.0 + */ +public class Planning implements Iterable, Planifiable { + private SortedSet cours; + + /** + * Permet de créer un objet Planning a partir d'une collection de cours + * + * @param cours collection de cours + * @since 1.0 + * + * @see Cours + */ + public Planning(Collection cours) { + this.cours = new TreeSet(cours); + } + + @Override + public Iterator iterator() { + return cours.iterator(); + } + + @Override + public void forEach(Consumer action) { + cours.forEach(action); + } + + @Override + public Spliterator spliterator() { + return cours.spliterator(); + } + + @Override + public String toString() { + String res = "EDT :\n\n"; + for (Cours c : cours) { + res += c.toString() + "\n\n"; + } + return res; + } + + /** + * Permet d'obtenir le planning correspondant à une date + * + * @param date date pour laquelle on veut obtenir le planning + * @return {@code Planning} correspondant + * @since 1.0 + * + * @see Planning + */ + @Override + public Planning getPlanningOf(LocalDate date) { + ArrayList result = new ArrayList<>(); + LocalDate lastDate = cours.last().getDate(); + if (!lastDate.isBefore(date)) { + for (Cours c : cours) { + int compare = c.getDate().compareTo(date); + if (compare < 0) + continue; + if (compare == 0) + result.add(c); + else + return new Planning(result); + } + } + return new Planning(result); + } + + /** + * Permet d'obtenir le planning correspondant à une date et un groupe + * + * @param date date dont on veut obtenir le planning + * @param groupe groupe dont on veut obtenir le planning + * @return planning correspondant + * @since 1.0 + * + * @see Groupe + * @see Planning + */ + @Override + public Planning getPlanningOf(LocalDate date, Groupe groupe) { + return getPlanningOf(date).getPlanningOf(groupe); + } + + /** + * Permet d'obtenir le planning correspondant à un groupe + * + * @param groupe groupe dont on veut obtenir le planning + * @return planning correspondant + * @since 1.0 + * + * @see Groupe + * @see Planning + */ + @Override + public Planning getPlanningOf(Groupe groupe) { + return new Planning( + cours.stream().filter(c -> groupe.estContenuDans(c.getGroupes())).collect(Collectors.toList())); + } + + /** + * @return the cours + */ + Collection getCours() { + return cours; + } +} diff --git a/src/test/java/edt/umontp/fr/AppTest.java b/src/test/java/edt/umontp/fr/AppTest.java deleted file mode 100644 index 1712b1a..0000000 --- a/src/test/java/edt/umontp/fr/AppTest.java +++ /dev/null @@ -1,20 +0,0 @@ -package edt.umontp.fr; - -import static org.junit.Assert.assertTrue; - -import org.junit.Test; - -/** - * Unit test for simple App. - */ -public class AppTest -{ - /** - * Rigorous Test :-) - */ - @Test - public void shouldAnswerWithTrue() - { - assertTrue( true ); - } -} diff --git a/src/test/java/edt/umontp/fr/CoursTest.java b/src/test/java/edt/umontp/fr/CoursTest.java new file mode 100644 index 0000000..8b06509 --- /dev/null +++ b/src/test/java/edt/umontp/fr/CoursTest.java @@ -0,0 +1,229 @@ +package edt.umontp.fr; + +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotEquals; + +import java.text.ParseException; +import java.time.LocalDate; +import java.time.LocalTime; +import java.util.Arrays; +import java.util.stream.Stream; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import net.fortuna.ical4j.model.Component; +import net.fortuna.ical4j.model.DateTime; +import net.fortuna.ical4j.model.component.VEvent; +import net.fortuna.ical4j.model.property.Description; +import net.fortuna.ical4j.model.property.Location; + +class CoursTest { + + @Nested + class contructeur_test { + private Component component; + + @BeforeEach + void init_component() { + DateTime startTime, endTime; + try { + startTime = new DateTime("20171127T150000"); + endTime = new DateTime("20171127T160000"); + } catch (ParseException pe) { + // yyyymmddTHHmmss is the correct format, but to make the compiler happy... + startTime = new DateTime(); + endTime = startTime; + } + component = new VEvent(startTime, endTime, "intitule"); + component.getProperties().add(new Description( + "\n\nA2-Semestre-3\nBELMECHERI NASSIM\nHAETTEL THOMAS\nLA XUAN HOANG\nCHIROUZE ANNE\nA valider\n(Exporté le:18/01/2021 10:51)\n")); + component.getProperties().add(new Location("K133")); + } + + @Test + void test_constructeur_VEvent() { + assertAll(() -> new Cours(component)); + } + + @Test + void test_constructeur_VEvent_dateBon() { + Cours cours = new Cours(component); + assertEquals(LocalDate.of(2017, 11, 27), cours.getDate()); + } + + @Test + void test_constructeur_VEvent_heureDebut_Bon() { + Cours cours = new Cours(component); + assertEquals(LocalTime.of(15, 00), cours.getHeureDebut()); + } + + @Test + void test_constructeur_VEvent_heureFin_Bon() { + Cours cours = new Cours(component); + assertEquals(LocalTime.of(16, 00), cours.getHeureFin()); + } + + @Test + void test_constructeur_VEvent_duree_Bon() { + Cours cours = new Cours(component); + assertEquals(60, cours.getDuree()); + } + + @Test + void test_constructeur_VEvent_groupe_Bon() { + Cours cours = new Cours(component); + assertEquals(Groupe.A2, cours.getGroupes()[0]); + } + + @Test + void test_constructeur_VEvent_profs_Bon() { + String[] expected = { "BELMECHERI NASSIM", "HAETTEL THOMAS", "LA XUAN HOANG", + "CHIROUZE ANNE" }; + Cours cours = new Cours(component); + assertEquals(Arrays.toString(expected), Arrays.toString(cours.getProf())); + } + + @Test + void test_constructeur_VEvent_lieu_Bon() { + Cours cours = new Cours(component); + assertEquals("K133", cours.getLieu()); + } + + @Test + void test_constructeur_VEvent_intitule_Bon() { + Cours cours = new Cours(component); + assertEquals("intitule", cours.getIntitule()); + } + } + + @Test + void test_getProfFromDdesc_Desc_NomsDesProfs() { + String desc = "\n\nA2-Semestre-3\nBELMECHERI NASSIM\nHAETTEL THOMAS\nLA XUAN HOANG\nCHIROUZE ANNE\nA valider\n(Exporté le:18/01/2021 10:51)\n"; + String[] expected = { "BELMECHERI NASSIM", "HAETTEL THOMAS", "LA XUAN HOANG", "CHIROUZE ANNE" }; + assertEquals(Arrays.toString(expected), Arrays.toString(Cours.getProfFromDesc(desc))); + } + + @ParameterizedTest(name = "Lorsque l'on compare le cours {0} au cours {1} les résultat doit être {2} ") + @MethodSource("genererArgumentsPourtestCompareTo_avecDate") + void testCompareTo_avecDate(Cours cours1, Cours cours2, int excepted) { + + assertEquals(excepted, cours1.compareTo(cours2)); + } + + private static Stream genererArgumentsPourtestCompareTo_avecDate() { + return Stream.of(// + Arguments.of(new Cours(LocalDate.of(2021, 1, 20), new String[] { "prof" }, + LocalTime.of(13, 30), LocalTime.of(14, 30), "K133", + new Groupe[] { Groupe.S1 }, "Compta1"), + new Cours(LocalDate.of(2021, 1, 20), new String[] { "prof" }, + LocalTime.of(13, 30), LocalTime.of(14, 30), "K133", + new Groupe[] { Groupe.S1 }, "Compta1"), + 0), // + Arguments.of(new Cours(LocalDate.of(2021, 1, 19), new String[] { "prof" }, + LocalTime.of(13, 30), LocalTime.of(14, 30), "K133", + new Groupe[] { Groupe.S1 }, "Compta1"), + new Cours(LocalDate.of(2021, 1, 20), new String[] { "prof" }, + LocalTime.of(13, 30), LocalTime.of(14, 30), "K133", + new Groupe[] { Groupe.S1 }, "Compta1"), + -1), // + Arguments.of(new Cours(LocalDate.of(2021, 1, 21), new String[] { "prof" }, + LocalTime.of(13, 30), LocalTime.of(14, 30), "K133", + new Groupe[] { Groupe.S1 }, "Compta1"), + new Cours(LocalDate.of(2021, 1, 20), new String[] { "prof" }, + LocalTime.of(13, 30), LocalTime.of(14, 30), "K133", + new Groupe[] { Groupe.S1 }, "Compta1"), + 1)); + } + + @ParameterizedTest(name = "Lorsque l'on compare le cours {0} au cours {1} les résultat doit être {2} ") + @MethodSource("genererArgumentsPourtestCompareTo_avecHeure") + void testCompareTo_avecHeure(Cours cours1, Cours cours2, int excepted) { + assertEquals(excepted, cours1.compareTo(cours2)); + } + + private static Stream genererArgumentsPourtestCompareTo_avecHeure() { + return Stream.of(// + Arguments.of(new Cours(LocalDate.of(2021, 1, 20), new String[] { "prof" }, + LocalTime.of(13, 30), LocalTime.of(14, 30), "K133", + new Groupe[] { Groupe.S1 }, "Compta1"), + new Cours(LocalDate.of(2021, 1, 20), new String[] { "prof" }, + LocalTime.of(13, 30), LocalTime.of(14, 30), "K133", + new Groupe[] { Groupe.S1 }, "Compta1"), + 0), // + Arguments.of(new Cours(LocalDate.of(2021, 1, 20), new String[] { "prof" }, + LocalTime.of(12, 30), LocalTime.of(13, 30), "K133", + new Groupe[] { Groupe.S1 }, "Compta1"), + new Cours(LocalDate.of(2021, 1, 20), new String[] { "prof" }, + LocalTime.of(13, 30), LocalTime.of(14, 30), "K133", + new Groupe[] { Groupe.S1 }, "Compta1"), + -1), // + Arguments.of(new Cours(LocalDate.of(2021, 1, 20), new String[] { "prof" }, + LocalTime.of(13, 29), LocalTime.of(13, 30), "K133", + new Groupe[] { Groupe.S1 }, "Compta1"), + new Cours(LocalDate.of(2021, 1, 20), new String[] { "prof" }, + LocalTime.of(13, 30), LocalTime.of(14, 30), "K133", + new Groupe[] { Groupe.S1 }, "Compta1"), + -1), // + Arguments.of(new Cours(LocalDate.of(2021, 1, 20), new String[] { "prof" }, + LocalTime.of(13, 31), LocalTime.of(13, 30), "K133", + new Groupe[] { Groupe.S1 }, "Compta1"), + new Cours(LocalDate.of(2021, 1, 20), new String[] { "prof" }, + LocalTime.of(13, 30), LocalTime.of(14, 30), "K133", + new Groupe[] { Groupe.S1 }, "Compta1"), + 1), // + Arguments.of(new Cours(LocalDate.of(2021, 1, 21), new String[] { "prof" }, + LocalTime.of(14, 30), LocalTime.of(15, 30), "K133", + new Groupe[] { Groupe.S1 }, "Compta1"), + new Cours(LocalDate.of(2021, 1, 20), new String[] { "prof" }, + LocalTime.of(13, 30), LocalTime.of(14, 30), "K133", + new Groupe[] { Groupe.S1 }, "Compta1"), + 1)); + } + + @Test + void test_equals() { + Cours cours1 = new Cours(LocalDate.of(2021, 1, 21), new String[] { "prof" }, LocalTime.of(14, 30), + LocalTime.of(15, 30), "K133", new Groupe[] { Groupe.S4 }, "Compta4"); + Cours cours2 = new Cours(LocalDate.of(2021, 1, 21), new String[] { "prof" }, LocalTime.of(14, 30), + LocalTime.of(15, 30), "K133", new Groupe[] { Groupe.S3 }, "Compta4"); + assertFalse(cours1.equals(cours2)); + } + + @Test + void test_hashcode() { + Cours cours1 = new Cours(LocalDate.of(2021, 1, 21), new String[] { "prof" }, LocalTime.of(14, 30), + LocalTime.of(15, 30), "K133", new Groupe[] { Groupe.S4 }, "Compta4"); + Cours cours2 = new Cours(LocalDate.of(2021, 1, 21), new String[] { "prof" }, LocalTime.of(14, 30), + LocalTime.of(15, 30), "K133", new Groupe[] { Groupe.S3 }, "Compta4"); + assertNotEquals(cours1.hashCode(), cours2.hashCode()); + } + + @Test + void test_getGroupes_plusieursGroupe_retournTousLesGroupes() { + Component component; + DateTime startTime, endTime; + try { + startTime = new DateTime("20171127T150000"); + endTime = new DateTime("20171127T160000"); + } catch (ParseException pe) { + // yyyymmddTHHmmss is the correct format, but to make the compiler happy... + startTime = new DateTime(); + endTime = startTime; + } + component = new VEvent(startTime, endTime, "intitule"); + component.getProperties().add(new Description( + "\n\nA2-Semestre-3 A1\nBELMECHERI NASSIM\nHAETTEL THOMAS\nLA XUAN HOANG\nCHIROUZE ANNE\nA valider\n(Exporté le:18/01/2021 10:51)\n")); + component.getProperties().add(new Location("K133")); + + Cours cours = new Cours(component); + + assertEquals(2, cours.getGroupes().length); + } +} \ No newline at end of file diff --git a/src/test/java/edt/umontp/fr/EmploiDuTempsProxyTest.java b/src/test/java/edt/umontp/fr/EmploiDuTempsProxyTest.java new file mode 100644 index 0000000..9c40f39 --- /dev/null +++ b/src/test/java/edt/umontp/fr/EmploiDuTempsProxyTest.java @@ -0,0 +1,136 @@ +package edt.umontp.fr; + +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.time.LocalDate; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; + +class EmploiDuTempsProxyTest { + + private EmploiDuTempsProxy emploiDuTempsProxy; + + @AfterEach + void init() { + emploiDuTempsProxy.actualiser(); + } + + @Test + void test_getInstance_retourneAucuneErreur() { + assertAll(() -> emploiDuTempsProxy = EmploiDuTempsProxy.getInstance()); + } + + @Test + void test_getPlanningOf_date_plusRapide() { + emploiDuTempsProxy = EmploiDuTempsProxy.getInstance(); + + long tempsExecution1 = rapiditeGetPlanningOfDate(); + long tempsExecution2 = rapiditeGetPlanningOfDate(); + + assertTrue(tempsExecution1 > tempsExecution2); + } + + private long rapiditeGetPlanningOfDate() { + long startTime = System.currentTimeMillis(); + emploiDuTempsProxy.getPlanningOf(LocalDate.now()); + emploiDuTempsProxy.getPlanningOf(LocalDate.now().plusDays(1)); + emploiDuTempsProxy.getPlanningOf(LocalDate.now().plusDays(2)); + emploiDuTempsProxy.getPlanningOf(LocalDate.now().plusDays(3)); + emploiDuTempsProxy.getPlanningOf(LocalDate.now().plusDays(4)); + emploiDuTempsProxy.getPlanningOf(LocalDate.now().plusDays(5)); + emploiDuTempsProxy.getPlanningOf(LocalDate.now().plusDays(6)); + emploiDuTempsProxy.getPlanningOf(LocalDate.now().plusDays(7)); + emploiDuTempsProxy.getPlanningOf(LocalDate.now().plusDays(8)); + emploiDuTempsProxy.getPlanningOf(LocalDate.now().plusDays(9)); + emploiDuTempsProxy.getPlanningOf(LocalDate.now().plusDays(10)); emploiDuTempsProxy.getPlanningOf(LocalDate.now().plusDays(1)); + emploiDuTempsProxy.getPlanningOf(LocalDate.now().plusDays(11)); emploiDuTempsProxy.getPlanningOf(LocalDate.now().plusDays(1)); + emploiDuTempsProxy.getPlanningOf(LocalDate.now().plusDays(12)); + emploiDuTempsProxy.getPlanningOf(LocalDate.now().plusDays(13)); + emploiDuTempsProxy.getPlanningOf(LocalDate.now().plusDays(14)); + emploiDuTempsProxy.getPlanningOf(LocalDate.now().plusDays(15)); + emploiDuTempsProxy.getPlanningOf(LocalDate.now().plusDays(16)); + emploiDuTempsProxy.getPlanningOf(LocalDate.now().plusDays(17)); + emploiDuTempsProxy.getPlanningOf(LocalDate.now().plusDays(18)); + emploiDuTempsProxy.getPlanningOf(LocalDate.now().plusDays(19)); + + return System.currentTimeMillis() - startTime; + } + + @Test + void test_getPlanningOf_Groupe_plusRapide() { + emploiDuTempsProxy = EmploiDuTempsProxy.getInstance(); + + long tempsExecution1 = rapiditeGetPlanningOfGroupe(); + long tempsExecution2 = rapiditeGetPlanningOfGroupe(); + + assertTrue(tempsExecution1 > tempsExecution2); + } + + private long rapiditeGetPlanningOfGroupe() { + long startTime = System.currentTimeMillis(); + emploiDuTempsProxy.getPlanningOf(Groupe.S1); + emploiDuTempsProxy.getPlanningOf(Groupe.S2); + emploiDuTempsProxy.getPlanningOf(Groupe.S3); + emploiDuTempsProxy.getPlanningOf(Groupe.S4); + emploiDuTempsProxy.getPlanningOf(Groupe.A1); + emploiDuTempsProxy.getPlanningOf(Groupe.Q1); + emploiDuTempsProxy.getPlanningOf(Groupe.Q2); + emploiDuTempsProxy.getPlanningOf(Groupe.Q3); + emploiDuTempsProxy.getPlanningOf(Groupe.Q4); + emploiDuTempsProxy.getPlanningOf(Groupe.G1); + emploiDuTempsProxy.getPlanningOf(Groupe.G2); + emploiDuTempsProxy.getPlanningOf(Groupe.G3); + emploiDuTempsProxy.getPlanningOf(Groupe.G4); + emploiDuTempsProxy.getPlanningOf(Groupe.A2); + return System.currentTimeMillis() - startTime; + } + + @Test + void test_getPlanningOf_DateGroupe_plusRapide() { + emploiDuTempsProxy = EmploiDuTempsProxy.getInstance(); + + long tempsExecution1 = rapiditeGetPlanningOfDateGroupe(); + long tempsExecution2 = rapiditeGetPlanningOfDateGroupe(); + + assertTrue(tempsExecution1 > tempsExecution2); + } + + private long rapiditeGetPlanningOfDateGroupe() { + long startTime = System.currentTimeMillis(); + emploiDuTempsProxy.getPlanningOf(LocalDate.now().plusDays(1), Groupe.A1); + emploiDuTempsProxy.getPlanningOf(LocalDate.now().plusDays(2), Groupe.Q1); + emploiDuTempsProxy.getPlanningOf(LocalDate.now().plusDays(3), Groupe.Q2); + emploiDuTempsProxy.getPlanningOf(LocalDate.now().plusDays(4), Groupe.Q3); + emploiDuTempsProxy.getPlanningOf(LocalDate.now().plusDays(5), Groupe.Q4); + emploiDuTempsProxy.getPlanningOf(LocalDate.now().plusDays(6), Groupe.G1); + emploiDuTempsProxy.getPlanningOf(LocalDate.now().plusDays(7), Groupe.G2); + emploiDuTempsProxy.getPlanningOf(LocalDate.now().plusDays(8), Groupe.G3); + emploiDuTempsProxy.getPlanningOf(LocalDate.now().plusDays(9), Groupe.G4); + emploiDuTempsProxy.getPlanningOf(LocalDate.now().plusDays(10), Groupe.A2); + emploiDuTempsProxy.getPlanningOf(LocalDate.now().plusDays(11), Groupe.A1); + emploiDuTempsProxy.getPlanningOf(LocalDate.now().plusDays(12), Groupe.Q1); + emploiDuTempsProxy.getPlanningOf(LocalDate.now().plusDays(13), Groupe.Q2); + emploiDuTempsProxy.getPlanningOf(LocalDate.now().plusDays(14), Groupe.Q3); + emploiDuTempsProxy.getPlanningOf(LocalDate.now().plusDays(15), Groupe.Q4); + emploiDuTempsProxy.getPlanningOf(LocalDate.now().plusDays(16), Groupe.G1); + emploiDuTempsProxy.getPlanningOf(LocalDate.now().plusDays(17), Groupe.G2); + emploiDuTempsProxy.getPlanningOf(LocalDate.now().plusDays(18), Groupe.G3); + emploiDuTempsProxy.getPlanningOf(LocalDate.now().plusDays(19), Groupe.G4); + return System.currentTimeMillis() - startTime; + } + + @Test + void test_getPlanningOf_DateGroupe_plusRapideInteligent() { + emploiDuTempsProxy = EmploiDuTempsProxy.getInstance(); + + long tempsExecution1 = rapiditeGetPlanningOfDateGroupe(); + emploiDuTempsProxy.actualiser(); + rapiditeGetPlanningOfDate(); + long tempsExecution2 = rapiditeGetPlanningOfDateGroupe(); + + assertTrue(tempsExecution1 > tempsExecution2); + } + +} diff --git a/src/test/java/edt/umontp/fr/EmploiDuTempsTest.java b/src/test/java/edt/umontp/fr/EmploiDuTempsTest.java new file mode 100644 index 0000000..3dbe643 --- /dev/null +++ b/src/test/java/edt/umontp/fr/EmploiDuTempsTest.java @@ -0,0 +1,35 @@ +package edt.umontp.fr; + +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.time.LocalDate; + +import org.junit.jupiter.api.Test; + +@SuppressWarnings("deprecation") +class EmploiDuTempsTest { + + @Test + void test_getInstance_verifierRetourneAucuneErreur() { + assertAll(() -> EmploiDuTemps.getInstance()); + } + + @Test + void test_getPlanningOf_date_verifierRetourneAucuneErreur() { + EmploiDuTemps emploiDuTemps = EmploiDuTemps.getInstance(); + assertAll(() -> emploiDuTemps.getPlanningOf(LocalDate.now())); + } + + @Test + void test_getPlanningOf_groupe_verifierRetourneAucuneErreur() { + EmploiDuTemps emploiDuTemps = EmploiDuTemps.getInstance(); + assertAll(() -> emploiDuTemps.getPlanningOf(Groupe.A1)); + } + + @Test + void test_getPlanningOf_groupe_verifierRetournePasDeListeVide() { + EmploiDuTemps emploiDuTemps = EmploiDuTemps.getInstance(); + assertTrue(emploiDuTemps.getPlanningOf(Groupe.A1).iterator().hasNext()); + } +} diff --git a/src/test/java/edt/umontp/fr/GroupeTest.java b/src/test/java/edt/umontp/fr/GroupeTest.java new file mode 100644 index 0000000..c4cc5c4 --- /dev/null +++ b/src/test/java/edt/umontp/fr/GroupeTest.java @@ -0,0 +1,65 @@ +package edt.umontp.fr; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.stream.Stream; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +class GroupeTest { + + @Test + void test_getIntitule() { + assertEquals("A1", Groupe.A1.getIntitule()); + } + + @ParameterizedTest(name = "Le groupe {0} doit retourner {2} lorsqu'il verifie s'il est contenu dans {1}") + @MethodSource("genererArgumentsPourtestestContenuDans") + void test_estContenuDans(Groupe g1, Groupe g2, boolean result) { + assertEquals(result, g1.estContenuDans(g2)); + } + + private static Stream genererArgumentsPourtestestContenuDans() { + return Stream.of(// + Arguments.of(Groupe.S1, Groupe.S3, false), // + Arguments.of(Groupe.S1, Groupe.A1, true), // + Arguments.of(Groupe.S1, Groupe.S1, true), // + Arguments.of(Groupe.A2, Groupe.A1, false), // + Arguments.of(Groupe.A1, Groupe.S3, false)); + } + + @Test + void valueOf() { + assertEquals(Groupe.A1, Groupe.valueOf("A1")); + } + + @Test + void test_getGroupeDepuisTexte_A1Seul_A1() { + String desc = "\n\nA1\nGOUAICH ABDELKADER\nLAGUILLAUMIE FABIEN\nPOUPET VICTOR\nROSENFELD MATTHIEU\nA " + + "valider\n(Exporté le:18 / 01 / 2 021 10:51)\n"; + assertEquals(Groupe.A1, Groupe.getGroupeDepuisTexte(desc)[0]); + } + + @Test + void test_getGroupeDepuisTexte_A1NonSeul_A1() { + String desc = "\n\nA1-Semestre-1\nGOUAICH ABDELKADER\nLAGUILLAUMIE FABIEN\nPOUPET VICTOR\nROSENFELD " + + "MATTHIEU\nA valider\n(Exporté le:18/01/2 021 10:51)\n"; + assertEquals(Groupe.A1, Groupe.getGroupeDepuisTexte(desc)[0]); + } + + @Test + void test_getGroupeDepuisTexte_aucunGroupe_GroupeNULL() { + String desc = "\n\nSemestre-1\nGOUAICH ABDELKADER\nLAGUILLAUMIE FABIEN\nPOUPET VICTOR\nROSENFELD MATTHIEU\nA valider\n(Exporté le:18/01/2 021 10:51)\n"; + assertEquals(0, Groupe.getGroupeDepuisTexte(desc).length); + } + + @Test + void test_getGroupeDepuisTexte_plusieursGroupe_retournPlusieursGroupe() { + String desc = "\n\nA1 & A2 Semestre-1\nGOUAICH ABDELKADER\nLAGUILLAUMIE FABIEN\nPOUPET VICTOR\nROSENFELD MATTHIEU\nA valider\n(Exporté le:18/01/2 021 10:51)\n"; + assertEquals(2, Groupe.getGroupeDepuisTexte(desc).length); + } + +} diff --git a/src/test/java/edt/umontp/fr/PlanningTest.java b/src/test/java/edt/umontp/fr/PlanningTest.java new file mode 100644 index 0000000..45e1393 --- /dev/null +++ b/src/test/java/edt/umontp/fr/PlanningTest.java @@ -0,0 +1,118 @@ +package edt.umontp.fr; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.text.ParseException; +import java.time.LocalDate; +import java.time.LocalTime; +import java.util.ArrayList; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import net.fortuna.ical4j.model.Component; +import net.fortuna.ical4j.model.DateTime; +import net.fortuna.ical4j.model.component.VEvent; +import net.fortuna.ical4j.model.property.Description; +import net.fortuna.ical4j.model.property.Location; + +class PlanningTest { + + private Planning planning; + + private ArrayList coursEnsemble; + + private Cours cours1 = new Cours(LocalDate.of(2021, 1, 20), new String[] { "prof" }, LocalTime.of(13, 30), + LocalTime.of(14, 30), "K133", new Groupe[] { Groupe.S1 }, "Compta1"); + private Cours cours2 = new Cours(LocalDate.of(2021, 1, 21), new String[] { "prof" }, LocalTime.of(14, 30), + LocalTime.of(15, 30), "K133", new Groupe[] { Groupe.S3 }, "Compta2"); + private Cours cours3 = new Cours(LocalDate.of(2021, 1, 21), new String[] { "prof" }, LocalTime.of(13, 30), + LocalTime.of(14, 30), "K133", new Groupe[] { Groupe.S2 }, "Compta3"); + private Cours cours4 = new Cours(LocalDate.of(2021, 1, 22), new String[] { "prof" }, LocalTime.of(11, 30), + LocalTime.of(12, 30), "K133", new Groupe[] { Groupe.S1 }, "Compta4"); + + @BeforeEach + void initPlanning() { + coursEnsemble = new ArrayList<>(); + coursEnsemble.add(cours1); + coursEnsemble.add(cours2); + coursEnsemble.add(cours3); + coursEnsemble.add(cours4); + planning = new Planning(coursEnsemble); + } + + @Test + void test_getPlanningOf_date() { + assertEquals(cours4, planning.getPlanningOf(cours4.getDate()).iterator().next()); + } + + @Test + void test_getPlanningOf_groupe_simpleGroupe() { + Planning planningS3 = planning.getPlanningOf(Groupe.S3); + assertEquals(cours2, planningS3.iterator().next()); + } + + @Test + void test_getPlanningOf_groupe_groupeCompose() { + Planning planningA1 = planning.getPlanningOf(Groupe.A1); + assertEquals(0, planningA1.getCours().size()); + } + + @Test + void test_getPlanningOf_sousGroupeDeA1_doitRetournerLeCoursA1() { + coursEnsemble.add(new Cours(LocalDate.of(2021, 1, 21), new String[] { "prof" }, LocalTime.of(14, 30), + LocalTime.of(15, 30), "K133", new Groupe[] { Groupe.A1 }, "Compta4")); + planning = new Planning(coursEnsemble); + assertEquals(1, planning.getPlanningOf(Groupe.S4).getCours().size()); + } + + @Test + void test_getPlanningOf_groupe_groupeComposeVide() { + Planning planningA2 = planning.getPlanningOf(Groupe.A2); + assertFalse(planningA2.iterator().hasNext()); + } + + @Test + void test_getPlanningOf_date_and_groupe() { + assertNotEquals(cours2, planning.getPlanningOf(cours2.getDate()).iterator().next()); + assertEquals(cours2, + planning.getPlanningOf(cours2.getDate(), cours2.getGroupes()[0]).iterator().next()); + } + + @Test + void test_constructeur_Planning_casPlusieursCoursCommenceEnMemeTemps_neDoitSupprimerAucunCours() { + coursEnsemble.add(new Cours(LocalDate.of(2021, 1, 21), new String[] { "prof" }, LocalTime.of(14, 30), + LocalTime.of(15, 30), "K133", new Groupe[] { Groupe.S4 }, "Compta4")); + planning = new Planning(coursEnsemble); + assertEquals(coursEnsemble.size(), planning.getCours().size()); + } + + @Test + void test_getPlanningOf_groupe_doitRetournerPlusieursGroupe() { + Component component; + DateTime startTime, endTime; + try { + startTime = new DateTime("20171127T150000"); + endTime = new DateTime("20171127T160000"); + } catch (ParseException pe) { + // yyyymmddTHHmmss is the correct format, but to make the compiler happy... + startTime = new DateTime(); + endTime = startTime; + } + component = new VEvent(startTime, endTime, "intitule"); + component.getProperties().add(new Description( + "\n\nA2-Semestre-3 A1\nBELMECHERI NASSIM\nHAETTEL THOMAS\nLA XUAN HOANG\nCHIROUZE ANNE\nA valider\n(Exporté le:18/01/2021 10:51)\n")); + component.getProperties().add(new Location("K133")); + Cours cours = new Cours(component); + ArrayList coursList = new ArrayList<>(); + coursList.add(cours); + Planning planning = new Planning(coursList); + + assertTrue(planning.getPlanningOf(Groupe.A1).iterator().hasNext()); + assertTrue(planning.getPlanningOf(Groupe.A2).iterator().hasNext()); + } + +}