Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a81c073407 | ||
|
|
aa9c543624 | ||
|
|
95748c79b1 | ||
|
|
3a50c2655d | ||
|
|
de01503598 | ||
|
|
a8a693296e | ||
|
|
a519393fc7 | ||
|
|
2864c54c72 | ||
|
|
a20edae4b8 | ||
|
|
2dd8cffda2 | ||
|
|
3f51adcbd0 | ||
|
|
4acd328286 | ||
|
|
dbba4e2662 | ||
|
|
6aeda395c3 | ||
|
|
7741569659 | ||
|
|
27b8d1754e | ||
|
|
06c4c47e44 | ||
|
|
dc0830120f | ||
|
|
39bff805ac | ||
|
|
3ebbb0e0e3 | ||
|
|
08d40d8b80 |
@@ -1,32 +1,19 @@
|
|||||||
# PM3-HS22-IT21b_WIN-Team1
|
# GardenPlanner
|
||||||
PM3 FivePlants Gartenverwaltung
|
|
||||||
|
|
||||||
## Class Diagram
|
## Installations- und Gebrauchsanweisung
|
||||||
Umletino: https://www.umletino.com/umletino.html
|
### Vorbedingungen
|
||||||
|
- Das Java Runtime Environment (JRE) muss in der Version 17 auf Ihrem Computer installiert sein.
|
||||||
|
- Das Java Development Kit (JDK) muss in der Version 17 auf Ihrem Computer installiert sein.
|
||||||
|
|
||||||
Draft File: doc/ClassDiagramDraft.uxf
|
### Installation und Starten der Applikation
|
||||||
|
1. Laden sie die neuste Version der Applikation herunter. Sie finden die Applikation hier:
|
||||||
|
https://github.zhaw.ch/schrom01/PM3-HS22-IT21b_WIN-Team1/tags
|
||||||
|
2. Extrahieren sie die heruntergeladene ZIP-Datei
|
||||||
|
3. Öffnen sie ein Kommandozeilenfenster und navigieren sie an den Speicherort der Entpack-ten Applikation.
|
||||||
|
4. Führen sie den Befehl: «./gradlew.bat run» (auf Windows) oder «./gradlew run» (auf ma-cOS und Linux) aus.
|
||||||
|
|
||||||
## Branch model
|
### Anwendung
|
||||||
- production branch: `main`
|
Eine Bedienungsanleitung finden Sie im Dokument ["Technischer Bericht II"](doc/PM3-HS22-IT21b_WIN-Technischer_Bericht_II-Team1.pdf) im Kapitel 6.3.3.
|
||||||
|
|
||||||
This branch has a working version of the code.
|
## Projektdokumentation
|
||||||
|
Die gesamte Projektdokumentation ist im Dokument ["Technischer Bericht II"](doc/PM3-HS22-IT21b_WIN-Technischer_Bericht_II-Team1.pdf) zu finden.
|
||||||
- development branch: `dev`
|
|
||||||
|
|
||||||
This branch should contain a running (although not necessarily working) version of the code. Working states are to be merged into the `main` branch regularly.
|
|
||||||
|
|
||||||
- feature: `feature_xy_<Milestone>`
|
|
||||||
|
|
||||||
These branches contain features in active development. When the code is ready it will be merged into the `dev` branch.
|
|
||||||
|
|
||||||
- bugfix: `bugfix_xy_<Milestone>`
|
|
||||||
|
|
||||||
These branches are for bugfixes.
|
|
||||||
|
|
||||||
- documentation: `doc_xy_<Milestone>`
|
|
||||||
|
|
||||||
These branches are for javadoc and project documentation (such as the readme, class diagrams etc.).
|
|
||||||
|
|
||||||
|
|
||||||
## User Manual
|
|
||||||
- Search Plant List: if first Char is '#': only exact match in ID.
|
|
||||||
@@ -1,92 +0,0 @@
|
|||||||
<diagram program="umletino" version="15.0.0"><zoom_level>10</zoom_level><element><id>UMLClass</id><coordinates><x>720</x><y>30</y><w>100</w><h>30</h></coordinates><panel_attributes>Main</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>1240</x><y>250</y><w>300</w><h>140</h></coordinates><panel_attributes><<Interface>>
|
|
||||||
PlantDatabase
|
|
||||||
--
|
|
||||||
+ getPlantList(zone: HardinessZone): List<Plant>
|
|
||||||
+ getPlant(id: long): Optional<Plant></panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>940</x><y>580</y><w>220</w><h>40</h></coordinates><panel_attributes>TaskListController</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>1240</x><y>10</y><w>300</w><h>180</h></coordinates><panel_attributes><<Record>>
|
|
||||||
Plant
|
|
||||||
--
|
|
||||||
+ id: long
|
|
||||||
+ name: String
|
|
||||||
+ description: String
|
|
||||||
+ spacing: int
|
|
||||||
+ lifecycle: List<GrowthPhase>
|
|
||||||
--
|
|
||||||
+ calculateStartDate(harvestDate: Date): Date
|
|
||||||
+ generateTasks()
|
|
||||||
</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>1210</x><y>580</y><w>210</w><h>120</h></coordinates><panel_attributes>TaskListModel
|
|
||||||
--
|
|
||||||
- tasks: ListProperty<Task>
|
|
||||||
- taskDb: TaskDatabase
|
|
||||||
--
|
|
||||||
+ getTask(id: long): Optional<Task>
|
|
||||||
+ saveTask(task: Task)
|
|
||||||
+ removeTask(task: Task)</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>590</x><y>560</y><w>250</w><h>110</h></coordinates><panel_attributes>GardenPlanModel
|
|
||||||
--
|
|
||||||
- tasks: ListProperty<Task>
|
|
||||||
- gardenPlan: GardenPlan
|
|
||||||
--
|
|
||||||
+ savePlanting(planting: UserPlanting)
|
|
||||||
+ removePlanting(planting: UserPlanting)</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>340</x><y>550</y><w>180</w><h>80</h></coordinates><panel_attributes>GardenPlanController</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>1660</x><y>720</y><w>490</w><h>240</h></coordinates><panel_attributes>Task
|
|
||||||
--
|
|
||||||
+ id: long
|
|
||||||
+ name: String {readOnly}
|
|
||||||
+ description: String {readOnly}
|
|
||||||
+ startDate: Date {readOnly}
|
|
||||||
+ isReadOnly: boolean {readOnly}
|
|
||||||
- interval: int
|
|
||||||
- endDate: Date
|
|
||||||
--
|
|
||||||
+ Task(name: String, description: String, startDate: String, isReadOnly: boolean): Task
|
|
||||||
+ withInterval(interval: int): Task
|
|
||||||
+ withEndDate(endDate: Date): Task
|
|
||||||
+ withId(id: long): Task
|
|
||||||
--
|
|
||||||
+ getInterval(): Optional<int>
|
|
||||||
+ getEndDate(): Optional<Date></panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>1170</x><y>760</y><w>280</w><h>140</h></coordinates><panel_attributes><<Interface>>
|
|
||||||
TaskDatabase
|
|
||||||
--
|
|
||||||
+ getTaskList(start: Date, end: Date): List<Task>
|
|
||||||
+ saveTask(Task task) throws ??Exception
|
|
||||||
+ removeTask(Task task) throws ??Exception</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>780</x><y>310</y><w>100</w><h>100</h></coordinates><panel_attributes>MainWindow</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>440</x><y>180</y><w>180</w><h>130</h></coordinates><panel_attributes>MainWindowController</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>1340</x><y>1070</y><w>210</w><h>70</h></coordinates><panel_attributes>NotificationService
|
|
||||||
--
|
|
||||||
- taskDb: TaskDatabase
|
|
||||||
--
|
|
||||||
+ tick()</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>1640</x><y>1210</y><w>240</w><h>140</h></coordinates><panel_attributes><<Interface>>
|
|
||||||
WeatherProvider
|
|
||||||
--
|
|
||||||
+ getWeatherForecast: WeatherForecast</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>1620</x><y>1040</y><w>400</w><h>100</h></coordinates><panel_attributes>WeatherService
|
|
||||||
--
|
|
||||||
- weatherPovider: WeatherProvider
|
|
||||||
- taskDb: TaskDatabase
|
|
||||||
--
|
|
||||||
+ WeatherService(provider: WeatherProvider, taskDb: TaskDatabase)
|
|
||||||
- updateTasks()</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>1620</x><y>10</y><w>260</w><h>150</h></coordinates><panel_attributes><<Record>>
|
|
||||||
GrowthPhase
|
|
||||||
--
|
|
||||||
+ startDate: Date
|
|
||||||
+ endDate: Date
|
|
||||||
+ type: GrowthPhaseType
|
|
||||||
|
|
||||||
</panel_attributes><additional_attributes></additional_attributes></element><element><id>Relation</id><coordinates><x>1530</x><y>80</y><w>110</w><h>30</h></coordinates><panel_attributes>lt=<->>>>></panel_attributes><additional_attributes>90;10;10;10</additional_attributes></element><element><id>Text</id><coordinates><x>420</x><y>0</y><w>190</w><h>70</h></coordinates><panel_attributes>Note:
|
|
||||||
--
|
|
||||||
{final, readOnly} omitted on public data fields in <<Record>> Entities for clarity
|
|
||||||
style=wordwrap</panel_attributes><additional_attributes></additional_attributes></element><element><id>Relation</id><coordinates><x>1440</x><y>820</y><w>240</w><h>30</h></coordinates><panel_attributes>lt=<.</panel_attributes><additional_attributes>220;10;10;10</additional_attributes></element><element><id>Relation</id><coordinates><x>1300</x><y>690</y><w>30</w><h>90</h></coordinates><panel_attributes>lt=<.</panel_attributes><additional_attributes>10;70;10;10</additional_attributes></element><element><id>UMLClass</id><coordinates><x>600</x><y>980</y><w>210</w><h>120</h></coordinates><panel_attributes><<Record>>
|
|
||||||
UserPlanting
|
|
||||||
--
|
|
||||||
+ plantId: long
|
|
||||||
+ asSowing: boolean
|
|
||||||
+ startDate: Date
|
|
||||||
+ area: int</panel_attributes><additional_attributes></additional_attributes></element><element><id>Relation</id><coordinates><x>1380</x><y>180</y><w>30</w><h>90</h></coordinates><panel_attributes>lt=<.</panel_attributes><additional_attributes>10;10;10;70</additional_attributes></element><element><id>UMLClass</id><coordinates><x>1950</x><y>10</y><w>140</w><h>120</h></coordinates><panel_attributes><<Enumeration>>
|
|
||||||
GrowthPhaseType
|
|
||||||
--
|
|
||||||
SOW
|
|
||||||
PLANT
|
|
||||||
HARVEST</panel_attributes><additional_attributes></additional_attributes></element><element><id>Relation</id><coordinates><x>1870</x><y>70</y><w>100</w><h>30</h></coordinates><panel_attributes>lt=<->>>></panel_attributes><additional_attributes>80;10;10;10</additional_attributes></element><element><id>Relation</id><coordinates><x>1150</x><y>590</y><w>80</w><h>30</h></coordinates><panel_attributes>lt=<->>>></panel_attributes><additional_attributes>60;10;10;10</additional_attributes></element><element><id>Relation</id><coordinates><x>700</x><y>890</y><w>30</w><h>110</h></coordinates><panel_attributes>lt=<.</panel_attributes><additional_attributes>10;90;10;10</additional_attributes></element><element><id>Relation</id><coordinates><x>510</x><y>580</y><w>100</w><h>30</h></coordinates><panel_attributes>lt=<->>>></panel_attributes><additional_attributes>80;10;10;10</additional_attributes></element><element><id>UMLClass</id><coordinates><x>570</x><y>760</y><w>280</w><h>140</h></coordinates><panel_attributes><<Interface>>
|
|
||||||
GardenPlan
|
|
||||||
--
|
|
||||||
+ getPlantings(): List<UserPlanting>
|
|
||||||
+ addPlanting(plantId: long, startDate)
|
|
||||||
+ savePlanting(planting: UserPlanting)
|
|
||||||
</panel_attributes><additional_attributes></additional_attributes></element><element><id>Relation</id><coordinates><x>690</x><y>660</y><w>30</w><h>120</h></coordinates><panel_attributes>lt=<.</panel_attributes><additional_attributes>10;100;10;10</additional_attributes></element><element><id>UMLClass</id><coordinates><x>60</x><y>390</y><w>180</w><h>80</h></coordinates><panel_attributes>PlantingCell
|
|
||||||
{extends ListCell<>}</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>0</x><y>540</y><w>290</w><h>80</h></coordinates><panel_attributes>PlantingCellFactory
|
|
||||||
{implements Callback<ListView<UserPlanting> >}</panel_attributes><additional_attributes></additional_attributes></element><element><id>Relation</id><coordinates><x>140</x><y>460</y><w>30</w><h>100</h></coordinates><panel_attributes>lt=<.</panel_attributes><additional_attributes>10;10;10;80</additional_attributes></element><element><id>Relation</id><coordinates><x>1750</x><y>1130</y><w>30</w><h>100</h></coordinates><panel_attributes>lt=<.</panel_attributes><additional_attributes>10;80;10;10</additional_attributes></element><element><id>Relation</id><coordinates><x>1350</x><y>890</y><w>120</w><h>200</h></coordinates><panel_attributes>lt=<.</panel_attributes><additional_attributes>10;10;100;180</additional_attributes></element><element><id>Relation</id><coordinates><x>1380</x><y>890</y><w>260</w><h>220</h></coordinates><panel_attributes>lt=<.</panel_attributes><additional_attributes>10;10;240;200</additional_attributes></element><element><id>UMLClass</id><coordinates><x>1090</x><y>1060</y><w>200</w><h>50</h></coordinates><panel_attributes>JsonTaskDatabase</panel_attributes><additional_attributes></additional_attributes></element><element><id>Relation</id><coordinates><x>1180</x><y>890</y><w>30</w><h>190</h></coordinates><panel_attributes>lt=<<-</panel_attributes><additional_attributes>10;10;10;170</additional_attributes></element><element><id>UMLClass</id><coordinates><x>1620</x><y>310</y><w>200</w><h>50</h></coordinates><panel_attributes>JsonPlantDatabase</panel_attributes><additional_attributes></additional_attributes></element><element><id>Relation</id><coordinates><x>1530</x><y>320</y><w>110</w><h>30</h></coordinates><panel_attributes>lt=<<-</panel_attributes><additional_attributes>10;10;90;10</additional_attributes></element><element><id>UMLClass</id><coordinates><x>300</x><y>800</y><w>200</w><h>50</h></coordinates><panel_attributes>JsonGardenPlan</panel_attributes><additional_attributes></additional_attributes></element><element><id>Relation</id><coordinates><x>490</x><y>810</y><w>100</w><h>30</h></coordinates><panel_attributes>lt=<<-</panel_attributes><additional_attributes>80;10;10;10</additional_attributes></element><element><id>Relation</id><coordinates><x>280</x><y>570</y><w>80</w><h>30</h></coordinates><panel_attributes>lt=<.</panel_attributes><additional_attributes>10;10;60;10</additional_attributes></element><element><id>Relation</id><coordinates><x>850</x><y>400</y><w>220</w><h>200</h></coordinates><panel_attributes>lt=<.</panel_attributes><additional_attributes>200;180;10;10</additional_attributes></element><element><id>Relation</id><coordinates><x>440</x><y>400</y><w>390</w><h>170</h></coordinates><panel_attributes>lt=<.</panel_attributes><additional_attributes>10;150;370;10</additional_attributes></element><element><id>UMLClass</id><coordinates><x>850</x><y>120</y><w>160</w><h>60</h></coordinates><panel_attributes>PlantListController</panel_attributes><additional_attributes></additional_attributes></element><element><id>Relation</id><coordinates><x>760</x><y>50</y><w>90</w><h>280</h></coordinates><panel_attributes>lt=<.</panel_attributes><additional_attributes>70;260;10;10</additional_attributes></element><element><id>Relation</id><coordinates><x>610</x><y>230</y><w>190</w><h>140</h></coordinates><panel_attributes>lt=<.</panel_attributes><additional_attributes>10;10;170;120</additional_attributes></element><element><id>Relation</id><coordinates><x>870</x><y>170</y><w>80</w><h>210</h></coordinates><panel_attributes>lt=<.</panel_attributes><additional_attributes>60;10;10;190</additional_attributes></element><element><id>UMLClass</id><coordinates><x>1020</x><y>290</y><w>160</w><h>60</h></coordinates><panel_attributes>PlantListModel</panel_attributes><additional_attributes></additional_attributes></element><element><id>Relation</id><coordinates><x>1000</x><y>150</y><w>110</w><h>160</h></coordinates><panel_attributes>lt=<.</panel_attributes><additional_attributes>90;140;10;10</additional_attributes></element><element><id>Relation</id><coordinates><x>1170</x><y>310</y><w>90</w><h>30</h></coordinates><panel_attributes>lt=<.</panel_attributes><additional_attributes>70;10;10;10</additional_attributes></element></diagram>
|
|
||||||
|
Before Width: | Height: | Size: 25 KiB |
@@ -1,7 +0,0 @@
|
|||||||
<diagram program="umletino" version="15.0.0"><zoom_level>10</zoom_level><element><id>UMLPackage</id><coordinates><x>390</x><y>60</y><w>340</w><h>100</h></coordinates><panel_attributes>UI</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLPackage</id><coordinates><x>390</x><y>180</y><w>460</w><h>120</h></coordinates><panel_attributes>Domain</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLPackage</id><coordinates><x>390</x><y>330</y><w>460</w><h>120</h></coordinates><panel_attributes>Technical Services</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLPackage</id><coordinates><x>400</x><y>90</y><w>100</w><h>60</h></coordinates><panel_attributes>Views (JFX)</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLPackage</id><coordinates><x>400</x><y>220</y><w>100</w><h>60</h></coordinates><panel_attributes>IO</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLPackage</id><coordinates><x>400</x><y>370</y><w>100</w><h>60</h></coordinates><panel_attributes>Jackson</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLPackage</id><coordinates><x>510</x><y>220</y><w>100</w><h>60</h></coordinates><panel_attributes>Types</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLPackage</id><coordinates><x>620</x><y>220</y><w>100</w><h>60</h></coordinates><panel_attributes>Models</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLPackage</id><coordinates><x>510</x><y>90</y><w>110</w><h>60</h></coordinates><panel_attributes>Controllers (JFX)</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLPackage</id><coordinates><x>510</x><y>370</y><w>100</w><h>60</h></coordinates><panel_attributes>Logging</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLPackage</id><coordinates><x>620</x><y>370</y><w>100</w><h>60</h></coordinates><panel_attributes>JavaFX</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLPackage</id><coordinates><x>730</x><y>220</y><w>110</w><h>60</h></coordinates><panel_attributes>Services</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLPackage</id><coordinates><x>730</x><y>370</y><w>110</w><h>60</h></coordinates><panel_attributes>HTTP/API</panel_attributes><additional_attributes></additional_attributes></element><element><id>Relation</id><coordinates><x>570</x><y>150</y><w>90</w><h>70</h></coordinates><panel_attributes>lt=.>
|
|
||||||
</panel_attributes><additional_attributes>70;10;10;50</additional_attributes></element><element><id>Relation</id><coordinates><x>570</x><y>290</y><w>110</w><h>80</h></coordinates><panel_attributes>lt=.>
|
|
||||||
</panel_attributes><additional_attributes>90;10;10;60</additional_attributes></element><element><id>Relation</id><coordinates><x>340</x><y>120</y><w>350</w><h>400</h></coordinates><panel_attributes>lt=.>
|
|
||||||
</panel_attributes><additional_attributes>60;10;10;10;10;380;330;380;330;310</additional_attributes></element><element><id>Relation</id><coordinates><x>770</x><y>270</y><w>30</w><h>120</h></coordinates><panel_attributes>lt=.>
|
|
||||||
</panel_attributes><additional_attributes>10;10;10;100</additional_attributes></element><element><id>Relation</id><coordinates><x>360</x><y>250</y><w>60</w><h>180</h></coordinates><panel_attributes>lt=.>
|
|
||||||
</panel_attributes><additional_attributes>40;10;10;10;10;160;40;160</additional_attributes></element><element><id>Relation</id><coordinates><x>610</x><y>120</y><w>70</w><h>120</h></coordinates><panel_attributes>lt=.>
|
|
||||||
</panel_attributes><additional_attributes>10;10;50;10;50;100</additional_attributes></element></diagram>
|
|
||||||
|
Before Width: | Height: | Size: 286 KiB |
@@ -1,144 +0,0 @@
|
|||||||
<diagram program="umletino" version="15.0.0"><zoom_level>10</zoom_level><element><id>UMLClass</id><coordinates><x>482</x><y>360</y><w>100</w><h>30</h></coordinates><panel_attributes>Main</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>1082</x><y>380</y><w>370</w><h>100</h></coordinates><panel_attributes><<Interface>>
|
|
||||||
PlantDatabase
|
|
||||||
--
|
|
||||||
+ getPlantList(zone: HardinessZone): List<Plant>
|
|
||||||
+ getPlantById(zone: HardinessZone id: long): Optional<Plant></panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>672</x><y>710</y><w>220</w><h>40</h></coordinates><panel_attributes>TaskListController</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>1132</x><y>110</y><w>300</w><h>180</h></coordinates><panel_attributes><<Record>>
|
|
||||||
Plant
|
|
||||||
--
|
|
||||||
+ id: long
|
|
||||||
+ name: String
|
|
||||||
+ description: String
|
|
||||||
+ spacing: int
|
|
||||||
+ lifecycle: List<GrowthPhase>
|
|
||||||
--
|
|
||||||
+ calculateStartDate(harvestDate: Date): Date
|
|
||||||
+ generateTasks()
|
|
||||||
</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>942</x><y>710</y><w>210</w><h>120</h></coordinates><panel_attributes>TaskListModel
|
|
||||||
--
|
|
||||||
- tasks: ListProperty<Task>
|
|
||||||
- taskDb: TaskDatabase
|
|
||||||
--
|
|
||||||
+ getTask(id: long): Optional<Task>
|
|
||||||
+ saveTask(task: Task)
|
|
||||||
+ removeTask(task: Task)</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>322</x><y>690</y><w>250</w><h>120</h></coordinates><panel_attributes>GardenPlanModel
|
|
||||||
--
|
|
||||||
- tasks: ListProperty<Crop>
|
|
||||||
- gardenPlan: GardenPlan
|
|
||||||
--
|
|
||||||
+ plantAsCrop(planting: UserPlanting)
|
|
||||||
+ removePlanting(planting: UserPlanting)</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>72</x><y>680</y><w>180</w><h>80</h></coordinates><panel_attributes>GardenPlanController</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>1362</x><y>830</y><w>490</w><h>240</h></coordinates><panel_attributes>Task
|
|
||||||
--
|
|
||||||
+ id: long
|
|
||||||
+ name: String {readOnly}
|
|
||||||
+ description: String {readOnly}
|
|
||||||
+ startDate: Date {readOnly}
|
|
||||||
+ isOptional: boolean {readOnly}
|
|
||||||
- interval: int
|
|
||||||
- endDate: Date
|
|
||||||
--
|
|
||||||
+ Task(name: String, description: String, startDate: String, isReadOnly: boolean): Task
|
|
||||||
+ withInterval(interval: int): Task
|
|
||||||
+ withEndDate(endDate: Date): Task
|
|
||||||
+ withId(id: long): Task
|
|
||||||
--
|
|
||||||
+ getInterval(): Optional<int>
|
|
||||||
+ getEndDate(): Optional<Date></panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>902</x><y>930</y><w>280</w><h>140</h></coordinates><panel_attributes><<Interface>>
|
|
||||||
TaskDatabase
|
|
||||||
--
|
|
||||||
+ getTaskList(start: Date, end: Date): List<Task>
|
|
||||||
+ saveTask(Task task) throws ??Exception
|
|
||||||
+ removeTask(Task task) throws ??Exception</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>442</x><y>440</y><w>170</w><h>80</h></coordinates><panel_attributes>MainWindowController</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>962</x><y>1310</y><w>210</w><h>70</h></coordinates><panel_attributes>NotificationService
|
|
||||||
--
|
|
||||||
- taskDb: TaskDatabase
|
|
||||||
--
|
|
||||||
+ tick()</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>1412</x><y>1310</y><w>240</w><h>90</h></coordinates><panel_attributes><<Interface>>
|
|
||||||
WeatherProvider
|
|
||||||
--
|
|
||||||
+ getWeatherForecast: WeatherForecast</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>1392</x><y>1150</y><w>400</w><h>100</h></coordinates><panel_attributes>WeatherService
|
|
||||||
--
|
|
||||||
- weatherPovider: WeatherProvider
|
|
||||||
- taskDb: TaskDatabase
|
|
||||||
--
|
|
||||||
+ WeatherService(provider: WeatherProvider, taskDb: TaskDatabase)
|
|
||||||
- updateTasks()</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>1502</x><y>110</y><w>260</w><h>150</h></coordinates><panel_attributes><<Record>>
|
|
||||||
GrowthPhase
|
|
||||||
--
|
|
||||||
+ startDate: MonthDay
|
|
||||||
+ endDate: MonthDay
|
|
||||||
+ type: GrowthPhaseType
|
|
||||||
|
|
||||||
</panel_attributes><additional_attributes></additional_attributes></element><element><id>Relation</id><coordinates><x>1422</x><y>180</y><w>100</w><h>40</h></coordinates><panel_attributes>lt=<->>>>>
|
|
||||||
m1=*
|
|
||||||
m2=1</panel_attributes><additional_attributes>80;10;10;10</additional_attributes></element><element><id>Text</id><coordinates><x>152</x><y>130</y><w>190</w><h>70</h></coordinates><panel_attributes>Note:
|
|
||||||
--
|
|
||||||
{final, readOnly} omitted on public data fields in <<Record>> Entities for clarity
|
|
||||||
style=wordwrap</panel_attributes><additional_attributes></additional_attributes></element><element><id>Relation</id><coordinates><x>1172</x><y>970</y><w>210</w><h>50</h></coordinates><panel_attributes>lt=<.
|
|
||||||
m1=*
|
|
||||||
m2=1
|
|
||||||
returns ></panel_attributes><additional_attributes>190;20;10;20</additional_attributes></element><element><id>Relation</id><coordinates><x>1032</x><y>820</y><w>140</w><h>130</h></coordinates><panel_attributes>lt=<-
|
|
||||||
m1=1 external database
|
|
||||||
m2=1 internal list
|
|
||||||
accesses</panel_attributes><additional_attributes>10;110;10;10</additional_attributes></element><element><id>UMLClass</id><coordinates><x>322</x><y>1120</y><w>240</w><h>150</h></coordinates><panel_attributes>Crop
|
|
||||||
--
|
|
||||||
- cropId: Long
|
|
||||||
+ plantId: long {final, readOnly}
|
|
||||||
+ startDate: LocalDate {final, readOnly}
|
|
||||||
+ area: Double
|
|
||||||
--
|
|
||||||
+ withId(long): Crop
|
|
||||||
+ withArea(double): Crop
|
|
||||||
--
|
|
||||||
+ getCropId(): Optional<Long></panel_attributes><additional_attributes></additional_attributes></element><element><id>Relation</id><coordinates><x>1262</x><y>280</y><w>70</w><h>120</h></coordinates><panel_attributes>lt=<.
|
|
||||||
m1=*
|
|
||||||
m2=1
|
|
||||||
returns</panel_attributes><additional_attributes>10;10;10;100</additional_attributes></element><element><id>UMLClass</id><coordinates><x>1632</x><y>290</y><w>130</w><h>100</h></coordinates><panel_attributes><<Enumeration>>
|
|
||||||
GrowthPhaseType
|
|
||||||
--
|
|
||||||
SOW
|
|
||||||
PLANT
|
|
||||||
HARVEST</panel_attributes><additional_attributes></additional_attributes></element><element><id>Relation</id><coordinates><x>1582</x><y>250</y><w>70</w><h>120</h></coordinates><panel_attributes>lt=<->>>>
|
|
||||||
m1=1
|
|
||||||
m2=*</panel_attributes><additional_attributes>50;90;10;90;10;10</additional_attributes></element><element><id>Relation</id><coordinates><x>882</x><y>720</y><w>80</w><h>30</h></coordinates><panel_attributes>lt=<->>>></panel_attributes><additional_attributes>60;10;10;10</additional_attributes></element><element><id>Relation</id><coordinates><x>432</x><y>1020</y><w>110</w><h>120</h></coordinates><panel_attributes>lt=<.
|
|
||||||
m1=*
|
|
||||||
m2=1
|
|
||||||
returns / saves</panel_attributes><additional_attributes>10;100;10;10</additional_attributes></element><element><id>Relation</id><coordinates><x>242</x><y>710</y><w>100</w><h>30</h></coordinates><panel_attributes>lt=<->>>></panel_attributes><additional_attributes>80;10;10;10</additional_attributes></element><element><id>UMLClass</id><coordinates><x>302</x><y>890</y><w>280</w><h>140</h></coordinates><panel_attributes><<Interface>>
|
|
||||||
GardenPlan
|
|
||||||
--
|
|
||||||
+ getPlantings(): List<UserPlanting>
|
|
||||||
+ addPlanting(plantId: long, startDate)
|
|
||||||
+ savePlanting(planting: UserPlanting)
|
|
||||||
</panel_attributes><additional_attributes></additional_attributes></element><element><id>Relation</id><coordinates><x>422</x><y>800</y><w>80</w><h>110</h></coordinates><panel_attributes>lt=<.
|
|
||||||
m1=1
|
|
||||||
m2=1
|
|
||||||
accesses</panel_attributes><additional_attributes>10;90;10;10</additional_attributes></element><element><id>Relation</id><coordinates><x>1522</x><y>1240</y><w>30</w><h>90</h></coordinates><panel_attributes>lt=<.</panel_attributes><additional_attributes>10;70;10;10</additional_attributes></element><element><id>Relation</id><coordinates><x>1062</x><y>1060</y><w>80</w><h>270</h></coordinates><panel_attributes>lt=<-
|
|
||||||
m1=1
|
|
||||||
m2=1
|
|
||||||
accesses</panel_attributes><additional_attributes>10;10;10;250</additional_attributes></element><element><id>Relation</id><coordinates><x>1142</x><y>1060</y><w>270</w><h>170</h></coordinates><panel_attributes>lt=<-
|
|
||||||
m1=1
|
|
||||||
m2=1
|
|
||||||
adds Tasks</panel_attributes><additional_attributes>10;10;10;140;250;140</additional_attributes></element><element><id>UMLClass</id><coordinates><x>822</x><y>1140</y><w>200</w><h>50</h></coordinates><panel_attributes>JsonTaskDatabase</panel_attributes><additional_attributes></additional_attributes></element><element><id>Relation</id><coordinates><x>912</x><y>1060</y><w>30</w><h>100</h></coordinates><panel_attributes>lt=<<-</panel_attributes><additional_attributes>10;10;10;80</additional_attributes></element><element><id>UMLClass</id><coordinates><x>1562</x><y>430</y><w>200</w><h>50</h></coordinates><panel_attributes>JsonPlantDatabase</panel_attributes><additional_attributes></additional_attributes></element><element><id>Relation</id><coordinates><x>1442</x><y>440</y><w>140</w><h>30</h></coordinates><panel_attributes>lt=<<-</panel_attributes><additional_attributes>10;10;120;10</additional_attributes></element><element><id>UMLClass</id><coordinates><x>32</x><y>930</y><w>200</w><h>50</h></coordinates><panel_attributes>JsonGardenPlan</panel_attributes><additional_attributes></additional_attributes></element><element><id>Relation</id><coordinates><x>222</x><y>940</y><w>100</w><h>30</h></coordinates><panel_attributes>lt=<<-</panel_attributes><additional_attributes>80;10;10;10</additional_attributes></element><element><id>Relation</id><coordinates><x>582</x><y>510</y><w>220</w><h>220</h></coordinates><panel_attributes>lt=<.</panel_attributes><additional_attributes>200;200;10;10</additional_attributes></element><element><id>Relation</id><coordinates><x>172</x><y>510</y><w>340</w><h>190</h></coordinates><panel_attributes>lt=<.</panel_attributes><additional_attributes>10;170;320;10</additional_attributes></element><element><id>UMLClass</id><coordinates><x>582</x><y>250</y><w>160</w><h>60</h></coordinates><panel_attributes>PlantListController</panel_attributes><additional_attributes></additional_attributes></element><element><id>Relation</id><coordinates><x>522</x><y>380</y><w>30</w><h>80</h></coordinates><panel_attributes>lt=<.</panel_attributes><additional_attributes>10;60;10;10</additional_attributes></element><element><id>Relation</id><coordinates><x>602</x><y>300</y><w>80</w><h>210</h></coordinates><panel_attributes>lt=<.</panel_attributes><additional_attributes>60;10;10;190</additional_attributes></element><element><id>UMLClass</id><coordinates><x>732</x><y>390</y><w>160</w><h>60</h></coordinates><panel_attributes>PlantListModel</panel_attributes><additional_attributes></additional_attributes></element><element><id>Relation</id><coordinates><x>732</x><y>280</y><w>90</w><h>130</h></coordinates><panel_attributes>lt=<.</panel_attributes><additional_attributes>70;110;10;10</additional_attributes></element><element><id>Relation</id><coordinates><x>882</x><y>400</y><w>220</w><h>70</h></coordinates><panel_attributes>lt=<-
|
|
||||||
m1=1\nexternal\ndatabase
|
|
||||||
m2=1\ninternal\nlist
|
|
||||||
accesses ></panel_attributes><additional_attributes>200;20;10;20</additional_attributes></element><element><id>Relation</id><coordinates><x>582</x><y>0</y><w>190</w><h>50</h></coordinates><panel_attributes>lt=-
|
|
||||||
m1=0..n
|
|
||||||
m2=0..1
|
|
||||||
teaches to ></panel_attributes><additional_attributes>10;20;170;20</additional_attributes></element><element><id>UMLClass</id><coordinates><x>1412</x><y>530</y><w>420</w><h>200</h></coordinates><panel_attributes>TaskTemplate
|
|
||||||
--
|
|
||||||
+ name: String {readOnly}
|
|
||||||
+ description: String {readOnly}
|
|
||||||
+ relativeStartDate: int {readOnly}
|
|
||||||
- interval: Integer
|
|
||||||
- relativeEndDate: Integer
|
|
||||||
- isOptional: boolean
|
|
||||||
--
|
|
||||||
+ Task(name: String, description: String, startDate: String): TaskTemplate
|
|
||||||
+ setRelativeEndDate(relativeEndDate: int)
|
|
||||||
+ setInterval(interval: Integer)
|
|
||||||
+ generateTask(realStartDate: LocalDate): Task
|
|
||||||
</panel_attributes><additional_attributes></additional_attributes></element><element><id>Relation</id><coordinates><x>1752</x><y>180</y><w>130</w><h>490</h></coordinates><panel_attributes>lt=<->>>>>
|
|
||||||
m1=*
|
|
||||||
m2=1</panel_attributes><additional_attributes>80;460;110;460;110;10;10;10</additional_attributes></element><element><id>Relation</id><coordinates><x>1602</x><y>720</y><w>90</w><h>130</h></coordinates><panel_attributes>lt=<.
|
|
||||||
m1=*
|
|
||||||
m2=1
|
|
||||||
generates</panel_attributes><additional_attributes>10;110;10;10</additional_attributes></element><element><id>Relation</id><coordinates><x>562</x><y>770</y><w>400</w><h>40</h></coordinates><panel_attributes>lt=<-
|
|
||||||
delegates generating Tasks</panel_attributes><additional_attributes>380;20;10;20</additional_attributes></element></diagram>
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
<diagram program="umletino" version="15.0.0"><zoom_level>12</zoom_level><element><id>UMLClass</id><coordinates><x>852</x><y>372</y><w>120</w><h>72</h></coordinates><panel_attributes>Gardener
|
|
||||||
--
|
|
||||||
Name
|
|
||||||
Type</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>144</x><y>372</y><w>120</w><h>120</h></coordinates><panel_attributes>Plant
|
|
||||||
--
|
|
||||||
name
|
|
||||||
description</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>600</x><y>372</y><w>120</w><h>84</h></coordinates><panel_attributes>Garden
|
|
||||||
--
|
|
||||||
Location
|
|
||||||
hardiness zone</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>384</x><y>372</y><w>120</w><h>72</h></coordinates><panel_attributes>Bed
|
|
||||||
--
|
|
||||||
Area</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>1152</x><y>624</y><w>120</w><h>36</h></coordinates><panel_attributes>Weather</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>852</x><y>816</y><w>120</w><h>36</h></coordinates><panel_attributes>Calendar</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>852</x><y>96</y><w>144</w><h>72</h></coordinates><panel_attributes>Community
|
|
||||||
--
|
|
||||||
Plant Information
|
|
||||||
</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>288</x><y>636</y><w>120</w><h>72</h></coordinates><panel_attributes>Growth phase
|
|
||||||
--
|
|
||||||
duration</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>852</x><y>624</y><w>120</w><h>84</h></coordinates><panel_attributes>Gardening task
|
|
||||||
--
|
|
||||||
start date
|
|
||||||
end date
|
|
||||||
interval</panel_attributes><additional_attributes></additional_attributes></element><element><id>Relation</id><coordinates><x>852</x><y>156</y><w>120</w><h>240</h></coordinates><panel_attributes>lt=-
|
|
||||||
m1=0..*
|
|
||||||
m2=1..*
|
|
||||||
< is part of </panel_attributes><additional_attributes>10;180;10;10</additional_attributes></element><element><id>Relation</id><coordinates><x>708</x><y>372</y><w>168</w><h>60</h></coordinates><panel_attributes>lt=-
|
|
||||||
m1=1
|
|
||||||
m2=1..*
|
|
||||||
< has </panel_attributes><additional_attributes>120;20;10;20</additional_attributes></element><element><id>Relation</id><coordinates><x>252</x><y>372</y><w>156</w><h>60</h></coordinates><panel_attributes>lt=-
|
|
||||||
m1=1
|
|
||||||
m2=0..*
|
|
||||||
< contains </panel_attributes><additional_attributes>110;20;10;20</additional_attributes></element><element><id>Relation</id><coordinates><x>252</x><y>444</y><w>156</w><h>216</h></coordinates><panel_attributes>lt=-
|
|
||||||
m1=1
|
|
||||||
m2=1..*
|
|
||||||
has ></panel_attributes><additional_attributes>10;10;80;10;80;160</additional_attributes></element><element><id>Relation</id><coordinates><x>492</x><y>372</y><w>132</w><h>60</h></coordinates><panel_attributes>lt=-
|
|
||||||
m1=1
|
|
||||||
m2=1..*
|
|
||||||
< contains </panel_attributes><additional_attributes>90;20;10;20</additional_attributes></element><element><id>Relation</id><coordinates><x>900</x><y>432</y><w>120</w><h>216</h></coordinates><panel_attributes>lt=-
|
|
||||||
m1=1
|
|
||||||
m2=1..*
|
|
||||||
< manages </panel_attributes><additional_attributes>10;10;10;160</additional_attributes></element><element><id>Relation</id><coordinates><x>960</x><y>624</y><w>216</w><h>60</h></coordinates><panel_attributes>lt=-
|
|
||||||
m1=1
|
|
||||||
m2=1..*
|
|
||||||
< manipulates</panel_attributes><additional_attributes>160;20;10;20</additional_attributes></element><element><id>Relation</id><coordinates><x>900</x><y>696</y><w>108</w><h>144</h></coordinates><panel_attributes>lt=-
|
|
||||||
m1=1
|
|
||||||
m2=0..*
|
|
||||||
< contains</panel_attributes><additional_attributes>10;10;10;100</additional_attributes></element><element><id>Relation</id><coordinates><x>960</x><y>408</y><w>468</w><h>468</h></coordinates><panel_attributes>lt=-
|
|
||||||
m1=1
|
|
||||||
m2=1
|
|
||||||
< informs </panel_attributes><additional_attributes>10;360;310;360;310;10;10;10</additional_attributes></element><element><id>UMLClass</id><coordinates><x>12</x><y>636</y><w>120</w><h>84</h></coordinates><panel_attributes>Need
|
|
||||||
--
|
|
||||||
start date
|
|
||||||
end date</panel_attributes><additional_attributes></additional_attributes></element><element><id>Relation</id><coordinates><x>60</x><y>432</y><w>108</w><h>228</h></coordinates><panel_attributes>lt=-
|
|
||||||
m1=1..*
|
|
||||||
m2=1..*
|
|
||||||
has ></panel_attributes><additional_attributes>10;170;10;10;70;10</additional_attributes></element><element><id>Relation</id><coordinates><x>60</x><y>672</y><w>816</w><h>120</h></coordinates><panel_attributes>lt=-
|
|
||||||
m1=1
|
|
||||||
m2=1
|
|
||||||
requires ></panel_attributes><additional_attributes>660;10;520;10;520;80;10;80;10;40</additional_attributes></element><element><id>UMLClass</id><coordinates><x>456</x><y>588</y><w>120</w><h>36</h></coordinates><panel_attributes>Team
|
|
||||||
</panel_attributes><additional_attributes></additional_attributes></element><element><id>Relation</id><coordinates><x>564</x><y>432</y><w>312</w><h>180</h></coordinates><panel_attributes>lt=-
|
|
||||||
m1=1
|
|
||||||
m2=1..*
|
|
||||||
contains of ></panel_attributes><additional_attributes>10;130;240;10</additional_attributes></element><element><id>Relation</id><coordinates><x>564</x><y>600</y><w>312</w><h>60</h></coordinates><panel_attributes>lt=-
|
|
||||||
m1=1
|
|
||||||
m2=0..*
|
|
||||||
manages ></panel_attributes><additional_attributes>10;20;240;20</additional_attributes></element><element><id>Relation</id><coordinates><x>960</x><y>156</y><w>216</w><h>240</h></coordinates><panel_attributes>lt=-
|
|
||||||
m1=0..n
|
|
||||||
m2=1..n
|
|
||||||
exchanges Informatione ></panel_attributes><additional_attributes>10;10;10;180</additional_attributes></element><element><id>Relation</id><coordinates><x>120</x><y>648</y><w>192</w><h>60</h></coordinates><panel_attributes>lt=-
|
|
||||||
m1=0..n
|
|
||||||
m2=1
|
|
||||||
< contains </panel_attributes><additional_attributes>10;20;140;20</additional_attributes></element></diagram>
|
|
||||||
|
Before Width: | Height: | Size: 44 KiB |
@@ -12,6 +12,7 @@ import ch.zhaw.gartenverwaltung.types.Crop;
|
|||||||
import ch.zhaw.gartenverwaltung.types.Pest;
|
import ch.zhaw.gartenverwaltung.types.Pest;
|
||||||
import ch.zhaw.gartenverwaltung.types.Plant;
|
import ch.zhaw.gartenverwaltung.types.Plant;
|
||||||
import ch.zhaw.gartenverwaltung.types.Task;
|
import ch.zhaw.gartenverwaltung.types.Task;
|
||||||
|
import javafx.application.Platform;
|
||||||
import javafx.beans.property.ListProperty;
|
import javafx.beans.property.ListProperty;
|
||||||
import javafx.beans.property.SimpleListProperty;
|
import javafx.beans.property.SimpleListProperty;
|
||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
@@ -133,8 +134,14 @@ public class CropDetailController {
|
|||||||
initializeTaskListProperty(crop);
|
initializeTaskListProperty(crop);
|
||||||
|
|
||||||
TaskList.TaskListObserver taskListObserver = newTaskList -> {
|
TaskList.TaskListObserver taskListObserver = newTaskList -> {
|
||||||
taskListProperty.clear();
|
Platform.runLater(() -> {
|
||||||
taskListProperty.addAll(gardenSchedule.getTaskListForCrop(crop.getCropId().get()));
|
taskListProperty.clear();
|
||||||
|
try {
|
||||||
|
taskListProperty.addAll(gardenSchedule.getTaskListForCrop(crop.getCropId().get()));
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
gardenSchedule.setTaskListObserver(taskListObserver);
|
gardenSchedule.setTaskListObserver(taskListObserver);
|
||||||
|
|
||||||
@@ -205,7 +212,6 @@ public class CropDetailController {
|
|||||||
taskListProperty.clear();
|
taskListProperty.clear();
|
||||||
taskListProperty.addAll(taskList);
|
taskListProperty.addAll(taskList);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
// TODO: Alert
|
|
||||||
LOG.log(Level.SEVERE, "Could not get task list for crop", e.getCause());
|
LOG.log(Level.SEVERE, "Could not get task list for crop", e.getCause());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -414,9 +420,7 @@ public class CropDetailController {
|
|||||||
if (buttonType == ButtonType.OK) {
|
if (buttonType == ButtonType.OK) {
|
||||||
try {
|
try {
|
||||||
gardenSchedule.removeTask(task);
|
gardenSchedule.removeTask(task);
|
||||||
//setTaskListProperty(this.crop);
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
// TODO: Show error alert
|
|
||||||
LOG.log(Level.SEVERE, "Could not remove crop.", e);
|
LOG.log(Level.SEVERE, "Could not remove crop.", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,30 +13,46 @@ import javafx.stage.Stage;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Timer;
|
import java.util.Timer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main class of the Application
|
||||||
|
*/
|
||||||
public class Main extends Application {
|
public class Main extends Application {
|
||||||
Timer backGroundTaskTimer = new Timer();
|
Timer backGroundTaskTimer = new Timer();
|
||||||
BackgroundTasks backgroundTasks;
|
BackgroundTasks backgroundTasks;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method which is automatically called if Application is starting. It loads the scenes to stage and shows the stage.
|
||||||
|
* It creates a new Instance of BackgroundTasks and schedules them with a Timer instance to execute them every minute.
|
||||||
|
* @param stage Stage to show
|
||||||
|
* @throws IOException If loading Scenes can not access the fxml Resource File
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void start(Stage stage) throws IOException {
|
public void start(Stage stage) throws IOException {
|
||||||
AppLoader appLoader = new AppLoader();
|
AppLoader appLoader = new AppLoader();
|
||||||
|
|
||||||
backgroundTasks = new BackgroundTasks((TaskList) appLoader.getAppDependency(TaskList.class),(CropList) appLoader.getAppDependency(CropList.class), (PlantList) appLoader.getAppDependency(PlantList.class));
|
|
||||||
|
|
||||||
appLoader.loadSceneToStage("MainFXML.fxml", stage);
|
appLoader.loadSceneToStage("MainFXML.fxml", stage);
|
||||||
|
|
||||||
stage.setTitle("Gartenverwaltung");
|
stage.setTitle("Gartenverwaltung");
|
||||||
stage.show();
|
stage.show();
|
||||||
|
|
||||||
|
backgroundTasks = new BackgroundTasks((TaskList) appLoader.getAppDependency(TaskList.class),(CropList) appLoader.getAppDependency(CropList.class), (PlantList) appLoader.getAppDependency(PlantList.class));
|
||||||
backGroundTaskTimer.scheduleAtFixedRate(backgroundTasks, 0, 60000);
|
backGroundTaskTimer.scheduleAtFixedRate(backgroundTasks, 0, 60000);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method which is automatically called when application is stopped.
|
||||||
|
* It cancels the timer to not execute the background tasks anymore.
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void stop(){
|
public void stop(){
|
||||||
backGroundTaskTimer.cancel();
|
backGroundTaskTimer.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Main method launches the application
|
||||||
|
* @param args There are no arguments needed.
|
||||||
|
*/
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
launch();
|
launch();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,7 +56,6 @@ public class MainFXMLController {
|
|||||||
@FXML
|
@FXML
|
||||||
void goToHome() {
|
void goToHome() {
|
||||||
showPaneAsMainView("Home.fxml");
|
showPaneAsMainView("Home.fxml");
|
||||||
styleChangeButton(home_button);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -65,7 +64,6 @@ public class MainFXMLController {
|
|||||||
@FXML
|
@FXML
|
||||||
void goToMyPlants() {
|
void goToMyPlants() {
|
||||||
showPaneAsMainView("MyGarden.fxml");
|
showPaneAsMainView("MyGarden.fxml");
|
||||||
styleChangeButton(myGarden_button);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -74,7 +72,6 @@ public class MainFXMLController {
|
|||||||
@FXML
|
@FXML
|
||||||
void goToMySchedule() {
|
void goToMySchedule() {
|
||||||
showPaneAsMainView("MySchedule.fxml");
|
showPaneAsMainView("MySchedule.fxml");
|
||||||
styleChangeButton(mySchedule_button);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -160,15 +157,6 @@ public class MainFXMLController {
|
|||||||
appLoader.loadAndCacheFxml("Plants.fxml");
|
appLoader.loadAndCacheFxml("Plants.fxml");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void styleChangeButton(Button button) {
|
|
||||||
/*home_button.setStyle("-fx-background-color: rgb(0,128,0)");
|
|
||||||
myGarden_button.setStyle("-fx-background-color: rgb(0,128,0)");
|
|
||||||
mySchedule_button.setStyle("-fx-background-color: rgb(0,128,0)");
|
|
||||||
settings_button.setStyle("-fx-background-color: rgb(0,128,0)");
|
|
||||||
tutorial_button.setStyle("-fx-background-color: rgb(0,128,0)");
|
|
||||||
button.setStyle("-fx-background-color: darkgreen");*/
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* loads the default FXML File
|
* loads the default FXML File
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
@@ -179,7 +167,6 @@ public class MainFXMLController {
|
|||||||
try {
|
try {
|
||||||
preloadPanes();
|
preloadPanes();
|
||||||
showPaneAsMainView("MyGarden.fxml");
|
showPaneAsMainView("MyGarden.fxml");
|
||||||
styleChangeButton(myGarden_button);
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOG.log(Level.SEVERE, "Failed to load FXML-Pane!", e);
|
LOG.log(Level.SEVERE, "Failed to load FXML-Pane!", e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import javafx.scene.image.ImageView;
|
|||||||
import javafx.scene.layout.AnchorPane;
|
import javafx.scene.layout.AnchorPane;
|
||||||
import javafx.scene.layout.HBox;
|
import javafx.scene.layout.HBox;
|
||||||
import javafx.scene.layout.Priority;
|
import javafx.scene.layout.Priority;
|
||||||
|
import javafx.scene.layout.VBox;
|
||||||
import javafx.stage.Modality;
|
import javafx.stage.Modality;
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
|
|
||||||
@@ -99,7 +100,6 @@ public class MyGardenController {
|
|||||||
* @throws IOException exception
|
* @throws IOException exception
|
||||||
*/
|
*/
|
||||||
private HBox createHBoxForListView(Crop crop) throws HardinessZoneNotSetException, IOException {
|
private HBox createHBoxForListView(Crop crop) throws HardinessZoneNotSetException, IOException {
|
||||||
//ToDo add better design
|
|
||||||
Plant plant = plantList.getPlantById(Settings.getInstance().getCurrentHardinessZone(), crop.getPlantId()).get();
|
Plant plant = plantList.getPlantById(Settings.getInstance().getCurrentHardinessZone(), crop.getPlantId()).get();
|
||||||
HBox hBox = new HBox(10);
|
HBox hBox = new HBox(10);
|
||||||
ImageView imageView = new ImageView();
|
ImageView imageView = new ImageView();
|
||||||
@@ -112,8 +112,23 @@ public class MyGardenController {
|
|||||||
}
|
}
|
||||||
hBox.setMinHeight(100);
|
hBox.setMinHeight(100);
|
||||||
Label label = new Label(plant.name());
|
Label label = new Label(plant.name());
|
||||||
label.setMaxWidth(2000);
|
label.setMinWidth(100);
|
||||||
HBox.setHgrow(label, Priority.ALWAYS);
|
|
||||||
|
VBox vbox = new VBox(10);
|
||||||
|
HBox startDateHBox = new HBox(10);
|
||||||
|
Label startDateDescription = new Label("Start Date:");
|
||||||
|
startDateDescription.setMinWidth(75);
|
||||||
|
Label startDate = new Label(crop.getStartDate().toString());
|
||||||
|
startDateHBox.getChildren().addAll(startDateDescription, startDate);
|
||||||
|
HBox endDateHBox = new HBox(10);
|
||||||
|
Label endDateDescription = new Label("End Date:");
|
||||||
|
endDateDescription.setMinWidth(75);
|
||||||
|
Label endDate = new Label(crop.getStartDate().plusDays(plant.timeToHarvest(0)).toString());
|
||||||
|
endDateHBox.getChildren().addAll(endDateDescription, endDate);
|
||||||
|
vbox.getChildren().addAll(startDateHBox, endDateHBox);
|
||||||
|
|
||||||
|
vbox.setMaxWidth(2000);
|
||||||
|
HBox.setHgrow(vbox, Priority.ALWAYS);
|
||||||
|
|
||||||
Button details = new Button();
|
Button details = new Button();
|
||||||
Button delete = new Button();
|
Button delete = new Button();
|
||||||
@@ -125,7 +140,7 @@ public class MyGardenController {
|
|||||||
details.setOnAction(getGoToCropDetailEvent(crop));
|
details.setOnAction(getGoToCropDetailEvent(crop));
|
||||||
delete.setOnAction(getDeleteCropEvent(crop));
|
delete.setOnAction(getDeleteCropEvent(crop));
|
||||||
|
|
||||||
hBox.getChildren().addAll(imageView, label, details, delete);
|
hBox.getChildren().addAll(imageView, label, vbox, details, delete);
|
||||||
return hBox;
|
return hBox;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,7 +173,6 @@ public class MyGardenController {
|
|||||||
stage.setResizable(true);
|
stage.setResizable(true);
|
||||||
stage.showAndWait();
|
stage.showAndWait();
|
||||||
} catch (IOException | PlantNotFoundException e) {
|
} catch (IOException | PlantNotFoundException e) {
|
||||||
// TODO: show error alert
|
|
||||||
LOG.log(Level.SEVERE, "Could not load plant details.", e);
|
LOG.log(Level.SEVERE, "Could not load plant details.", e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -204,7 +218,6 @@ public class MyGardenController {
|
|||||||
try {
|
try {
|
||||||
garden.removeCrop(crop);
|
garden.removeCrop(crop);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
// TODO: Show error alert
|
|
||||||
LOG.log(Level.SEVERE, "Could not remove crop.", e);
|
LOG.log(Level.SEVERE, "Could not remove crop.", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import javafx.scene.layout.VBox;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
@@ -208,6 +209,12 @@ public class MyScheduleController {
|
|||||||
alert.setHeaderText("Are you sure you have completed this task?");
|
alert.setHeaderText("Are you sure you have completed this task?");
|
||||||
alert.setContentText("Confirming that you have completed the task will remove it from the schedule.");
|
alert.setContentText("Confirming that you have completed the task will remove it from the schedule.");
|
||||||
|
|
||||||
|
DialogPane dialogPane = alert.getDialogPane();
|
||||||
|
|
||||||
|
dialogPane.getStylesheets().add(
|
||||||
|
Objects.requireNonNull(getClass().getResource("bootstrap/dialogStyle.css")).toExternalForm());
|
||||||
|
dialogPane.getStyleClass().add("myDialog");
|
||||||
|
|
||||||
alert.showAndWait()
|
alert.showAndWait()
|
||||||
.ifPresent(buttonType -> {
|
.ifPresent(buttonType -> {
|
||||||
if (buttonType == ButtonType.OK) {
|
if (buttonType == ButtonType.OK) {
|
||||||
|
|||||||
@@ -6,21 +6,58 @@ import javafx.beans.property.BooleanProperty;
|
|||||||
import javafx.beans.property.SimpleBooleanProperty;
|
import javafx.beans.property.SimpleBooleanProperty;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Singleton Class to store default Settings and User Settings
|
||||||
|
*/
|
||||||
public class Settings {
|
public class Settings {
|
||||||
private static final Settings instance;
|
/*
|
||||||
private HardinessZone currentHardinessZone = HardinessZone.ZONE_8A;
|
* The Class instance to use everywhere
|
||||||
private final BooleanProperty showTutorial = new SimpleBooleanProperty(false);
|
*/
|
||||||
private SmtpCredentials smtpCredentials = new SmtpCredentials("imap.gmail.com", "587", "pm3.hs22.it21b.win.team1@gmail.com", "pm3.hs22.it21b.win.team1@gmail.com", "bisefhhjtrrhtoqr", true);
|
|
||||||
// Gmail Address: pm3.hs22.it21b.win.team1@gmail.com
|
|
||||||
// Gmail Passwort: Gartenverwaltung.PM3.2022
|
|
||||||
// E-Mail Inbox: https://www.mailinator.com/v4/public/inboxes.jsp?to=pm3.hs22.it21b.win.team1
|
|
||||||
private String mailNotificationReceivers = "pm3.hs22.it21b.win.team1@mailinator.com";
|
|
||||||
private String mailNotificationSubjectTemplate = "Task %s is due!"; // {0} = Task Name
|
|
||||||
private String mailNotificationTextTemplate = "Dear user\nYour gardentask %s for plant %s is due at %tF. Don't forget to confirm in your application if the task is done.\nTask description:\n%s"; // {0} = Task Name, {1} = plantname, {2} = nextExecution, {3} = Task description
|
|
||||||
|
|
||||||
|
private static final Settings instance;
|
||||||
|
/**
|
||||||
|
* The current Hardiness zone initialized as default value Zone_8A
|
||||||
|
*/
|
||||||
|
private HardinessZone currentHardinessZone = HardinessZone.ZONE_8A;
|
||||||
|
/**
|
||||||
|
* Setting to show or hide the Tutorial in Main Menu
|
||||||
|
*/
|
||||||
|
private final BooleanProperty showTutorial = new SimpleBooleanProperty(false);
|
||||||
|
/**
|
||||||
|
* The SMTP Credentials which are used to send E-Mail Notifications
|
||||||
|
* The following Google Account is created for Testing:
|
||||||
|
* E-Mail Address: pm3.hs22.it21b.win.team1@gmail.com
|
||||||
|
* Account Password: Gartenverwaltung.PM3.2022
|
||||||
|
* SMTP Password: bisefhhjtrrhtoqr
|
||||||
|
*/
|
||||||
|
private SmtpCredentials smtpCredentials = new SmtpCredentials("imap.gmail.com", "587", "pm3.hs22.it21b.win.team1@gmail.com", "pm3.hs22.it21b.win.team1@gmail.com", "bisefhhjtrrhtoqr", true);
|
||||||
|
/**
|
||||||
|
* List of Receivers for E-Mailnotifications. Multiple E-Mailadresses can be separated by ";"
|
||||||
|
* Following Public E-mail address was used for Testing: pm3.hs22.it21b.win.team1@mailinator.com
|
||||||
|
* The E-Mail inbox of this address can be found here: https://www.mailinator.com/v4/public/inboxes.jsp?to=pm3.hs22.it21b.win.team1
|
||||||
|
*/
|
||||||
|
private String mailNotificationReceivers = "pm3.hs22.it21b.win.team1@mailinator.com";
|
||||||
|
/**
|
||||||
|
* String Template to create E-Mail Subject for Notifications
|
||||||
|
* Variables: Task Name
|
||||||
|
*/
|
||||||
|
private String mailNotificationSubjectTemplate = "Task %s is due!";
|
||||||
|
/**
|
||||||
|
* String Template to create E-Mail Text for Notifications
|
||||||
|
* Variables: Task Name, plant Name, nextExecution, Task description
|
||||||
|
*/
|
||||||
|
private String mailNotificationTextTemplate = "Dear user\nYour gardentask %s for plant %s is due at %tF. Don't forget to confirm in your application if the task is done.\nTask description:\n%s";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Location of the garden can be set by user (Used for Weather Service)
|
||||||
|
*/
|
||||||
private String location = "";
|
private String location = "";
|
||||||
|
|
||||||
|
/*
|
||||||
|
Create Instance of Settings
|
||||||
|
*/
|
||||||
static {
|
static {
|
||||||
instance = new Settings();
|
instance = new Settings();
|
||||||
}
|
}
|
||||||
@@ -29,14 +66,21 @@ public class Settings {
|
|||||||
return Settings.instance;
|
return Settings.instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private constructor to prevent Classes from creating more instances
|
||||||
|
*/
|
||||||
private Settings() {}
|
private Settings() {}
|
||||||
|
|
||||||
public HardinessZone getCurrentHardinessZone() {
|
public HardinessZone getCurrentHardinessZone() {
|
||||||
return currentHardinessZone;
|
return currentHardinessZone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to set the current Hardiness Zone. If no Hardiness Zone is given the default zone (ZONE_8A) will be used.
|
||||||
|
* @param currentHardinessZone the new Hardiness Zone
|
||||||
|
*/
|
||||||
public void setCurrentHardinessZone(HardinessZone currentHardinessZone) {
|
public void setCurrentHardinessZone(HardinessZone currentHardinessZone) {
|
||||||
this.currentHardinessZone = currentHardinessZone;
|
this.currentHardinessZone = Objects.requireNonNullElse(currentHardinessZone, HardinessZone.ZONE_8A);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setShowTutorial (boolean showTutorial) {
|
public void setShowTutorial (boolean showTutorial) {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import javafx.scene.image.Image;
|
|||||||
import javafx.scene.image.ImageView;
|
import javafx.scene.image.ImageView;
|
||||||
import javafx.scene.layout.StackPane;
|
import javafx.scene.layout.StackPane;
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Controller class for the Tutorial.fxml file
|
* Controller class for the Tutorial.fxml file
|
||||||
@@ -32,17 +33,27 @@ public class TutorialController {
|
|||||||
switchViews();
|
switchViews();
|
||||||
setButtonAbilities();
|
setButtonAbilities();
|
||||||
|
|
||||||
Image addNewPlantImage = new Image(String.valueOf(PlantsController.class.getResource("add-new-plant.png")));
|
setImageView(imgAddNewPlant, "add-new-plant.png");
|
||||||
Image selectSowHarvestImage = new Image(String.valueOf(PlantsController.class.getResource("select-sow-harvest.png")));
|
setImageView(imgSelectDate, "select-sow-harvest.png");
|
||||||
Image scheduleImage = new Image(String.valueOf(PlantsController.class.getResource("schedule.png")));
|
setImageView(imgDetailDeleteButtons, "details-delete.png");
|
||||||
Image detailDeleteButtonsImage = new Image(String.valueOf(PlantsController.class.getResource("details-delete.png")));
|
setImageView(imgTaskList, "schedule.png");
|
||||||
Image addTaskImage = new Image(String.valueOf(PlantsController.class.getResource("add-task.png")));
|
setImageView(imgAddTaskButton, "add-task.png");
|
||||||
|
}
|
||||||
|
|
||||||
imgAddNewPlant.setImage(addNewPlantImage);
|
/**
|
||||||
imgSelectDate.setImage(selectSowHarvestImage);
|
* update the given image view with screenshot or placeholder image.
|
||||||
imgDetailDeleteButtons.setImage(detailDeleteButtonsImage);
|
* @param imageView the image view to update
|
||||||
imgAddTaskButton.setImage(addTaskImage);
|
* @param fileName the file name of the source
|
||||||
imgTaskList.setImage(scheduleImage);
|
*/
|
||||||
|
private void setImageView(ImageView imageView, String fileName) {
|
||||||
|
InputStream is = PlantsController.class.getResourceAsStream("screenshots/" + fileName);
|
||||||
|
Image image;
|
||||||
|
if (is != null) {
|
||||||
|
image = new Image(String.valueOf(PlantsController.class.getResource("screenshots/" + fileName)));
|
||||||
|
} else {
|
||||||
|
image = new Image(String.valueOf(PlantsController.class.getResource("placeholder.png")));
|
||||||
|
}
|
||||||
|
imageView.setImage(image);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void viewNextPage() {
|
public void viewNextPage() {
|
||||||
|
|||||||
@@ -17,14 +17,27 @@ import java.util.TimerTask;
|
|||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class with tasks which must be executed periodic and not triggered by user. Method run must be called in a fix interval.
|
||||||
|
*/
|
||||||
public class BackgroundTasks extends TimerTask {
|
public class BackgroundTasks extends TimerTask {
|
||||||
private static final Logger LOG = Logger.getLogger(CropDetailController.class.getName());
|
private static final Logger LOG = Logger.getLogger(CropDetailController.class.getName());
|
||||||
private final TaskList taskList;
|
private final TaskList taskList;
|
||||||
private final Notifier notifier;
|
private final Notifier notifier;
|
||||||
private final WeatherGradenTaskPlanner weatherGardenTaskPlaner;
|
private final WeatherGradenTaskPlanner weatherGardenTaskPlaner;
|
||||||
|
|
||||||
|
public BackgroundTasks(TaskList taskList, CropList cropList, PlantList plantList) {
|
||||||
|
this.taskList = taskList;
|
||||||
|
notifier = new Notifier(taskList, plantList, cropList);
|
||||||
|
weatherGardenTaskPlaner = new WeatherGradenTaskPlanner(taskList, plantList, cropList);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Changes the field "nextExecution" of all tasks if it's in the past to the actual date as long as they are not done.
|
||||||
|
* @throws IOException if the taskList can't be read.
|
||||||
|
*/
|
||||||
private void movePastTasks() throws IOException {
|
private void movePastTasks() throws IOException {
|
||||||
List<Task> taskList = this.taskList.getTaskList(LocalDate.MIN, LocalDate.now().minusDays(1));
|
List<Task> taskList = this.taskList.getTaskList(LocalDate.MIN.plusDays(1), LocalDate.now().minusDays(1));
|
||||||
for (Task task : taskList) {
|
for (Task task : taskList) {
|
||||||
if (!task.isDone()) {
|
if (!task.isDone()) {
|
||||||
task.setNextExecution(LocalDate.now());
|
task.setNextExecution(LocalDate.now());
|
||||||
@@ -33,31 +46,28 @@ public class BackgroundTasks extends TimerTask {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public BackgroundTasks(TaskList taskList, CropList cropList, PlantList plantList) {
|
/**
|
||||||
this.taskList = taskList;
|
* Method to call if Tasks should be executed. It calls all Background tasks after each other.
|
||||||
notifier = new Notifier(taskList, plantList, cropList);
|
*/
|
||||||
weatherGardenTaskPlaner = new WeatherGradenTaskPlanner(taskList, plantList, cropList);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
movePastTasks();
|
movePastTasks();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
LOG.log(Level.SEVERE, "Could not execute Background Task: move past Tasks ", e.getCause());
|
LOG.log(Level.WARNING, "Could not execute Background Task: move past Tasks ", e.getCause());
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
weatherGardenTaskPlaner.refreshTasks();
|
weatherGardenTaskPlaner.refreshTasks();
|
||||||
} catch (IOException | HardinessZoneNotSetException | PlantNotFoundException e) {
|
} catch (IOException | HardinessZoneNotSetException | PlantNotFoundException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
LOG.log(Level.SEVERE, "Could not execute Background Task: Refresh Tasks by WeatherGardenTaskPlaner ", e.getCause());
|
LOG.log(Level.WARNING, "Could not execute Background Task: Refresh Tasks by WeatherGardenTaskPlaner ", e.getCause());
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
notifier.sendNotifications();
|
notifier.sendNotifications();
|
||||||
} catch (IOException | MessagingException | HardinessZoneNotSetException e) {
|
} catch (IOException | MessagingException | HardinessZoneNotSetException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
LOG.log(Level.SEVERE, "Could not execute Background Task: send Notification for due Tasks", e.getCause());
|
LOG.log(Level.WARNING, "Could not execute Background Task: send Notification for due Tasks", e.getCause());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,9 @@ import javax.mail.MessagingException;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class to send Notifications to the user
|
||||||
|
*/
|
||||||
public class Notifier {
|
public class Notifier {
|
||||||
private final TaskList taskList;
|
private final TaskList taskList;
|
||||||
private final CropList cropList;
|
private final CropList cropList;
|
||||||
@@ -25,6 +28,13 @@ public class Notifier {
|
|||||||
this.plantList = plantList;
|
this.plantList = plantList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to send a Notification to the user for e specific Task
|
||||||
|
* @param task The task to use for notification
|
||||||
|
* @throws IOException if tasklist can not be read
|
||||||
|
* @throws MessagingException if E-Mail can not be sent for any reason
|
||||||
|
* @throws HardinessZoneNotSetException if hardiness zone is not set in plant list.
|
||||||
|
*/
|
||||||
private void sendNotification(Task task) throws IOException, MessagingException, HardinessZoneNotSetException {
|
private void sendNotification(Task task) throws IOException, MessagingException, HardinessZoneNotSetException {
|
||||||
String plantName = "unkown plant";
|
String plantName = "unkown plant";
|
||||||
if(cropList.getCropById((task.getCropId())).isPresent()){
|
if(cropList.getCropById((task.getCropId())).isPresent()){
|
||||||
@@ -38,6 +48,12 @@ public class Notifier {
|
|||||||
eMailSender.sendMails(Settings.getInstance().getMailNotificationReceivers(), messageSubject, messageText);
|
eMailSender.sendMails(Settings.getInstance().getMailNotificationReceivers(), messageSubject, messageText);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a notification to the user for each task which is due and not done every day as long as it's not done.
|
||||||
|
* @throws IOException if tasklist can not be read
|
||||||
|
* @throws MessagingException if E-Mail can not be sent for any reason
|
||||||
|
* @throws HardinessZoneNotSetException if hardiness zone is not set in plant list.
|
||||||
|
*/
|
||||||
public void sendNotifications() throws IOException, MessagingException, HardinessZoneNotSetException {
|
public void sendNotifications() throws IOException, MessagingException, HardinessZoneNotSetException {
|
||||||
for (Task task : taskList.getTaskList(LocalDate.MIN, LocalDate.MAX)) {
|
for (Task task : taskList.getTaskList(LocalDate.MIN, LocalDate.MAX)) {
|
||||||
if (task.getNextNotification() != null && task.getNextNotification().isBefore(LocalDate.now().minusDays(1))) {
|
if (task.getNextNotification() != null && task.getNextNotification().isBefore(LocalDate.now().minusDays(1))) {
|
||||||
|
|||||||
@@ -10,16 +10,20 @@ import java.util.Arrays;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class to send E-Mails
|
||||||
|
*/
|
||||||
public class EMailSender {
|
public class EMailSender {
|
||||||
|
|
||||||
|
/**
|
||||||
public EMailSender(){
|
* Method to send E-Mail to one or multiple recipients
|
||||||
|
* @param recipients recipients E-Mail addresses separated by ";"
|
||||||
}
|
* @param subject Subject of the E-Mail
|
||||||
|
* @param text E-Mail message Text as rear text or html
|
||||||
|
* @throws MessagingException If sending the E-Mail fails for any reason
|
||||||
|
*/
|
||||||
public void sendMails(String recipients, String subject, String text) throws MessagingException {
|
public void sendMails(String recipients, String subject, String text) throws MessagingException {
|
||||||
// TODO replace printMail with implementation
|
printMail(recipients, subject, text);
|
||||||
printMail(recipients, subject, text); // TODO Remove Printing E-Mail to console to test it
|
|
||||||
MimeMessage message = new MimeMessage(Settings.getInstance().getSmtpCredentials().getSession());
|
MimeMessage message = new MimeMessage(Settings.getInstance().getSmtpCredentials().getSession());
|
||||||
message.addHeader("Content-type", "text/HTML; charset=UTF-8");
|
message.addHeader("Content-type", "text/HTML; charset=UTF-8");
|
||||||
message.addHeader("format", "flowed");
|
message.addHeader("format", "flowed");
|
||||||
|
|||||||
@@ -5,6 +5,10 @@ import javax.mail.Session;
|
|||||||
import java.net.Authenticator;
|
import java.net.Authenticator;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class to store SMTP Credentials to send E-Mails and create
|
||||||
|
* corresponding Session Object
|
||||||
|
*/
|
||||||
public record SmtpCredentials(
|
public record SmtpCredentials(
|
||||||
String host,
|
String host,
|
||||||
String port,
|
String port,
|
||||||
@@ -14,6 +18,10 @@ public record SmtpCredentials(
|
|||||||
boolean startTLS
|
boolean startTLS
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a Properties Object with SMTP Server Information
|
||||||
|
* @return the created Properties Object
|
||||||
|
*/
|
||||||
private Properties getProperties() {
|
private Properties getProperties() {
|
||||||
Properties properties = new Properties();
|
Properties properties = new Properties();
|
||||||
properties.put("mail.smtp.host", host);
|
properties.put("mail.smtp.host", host);
|
||||||
@@ -23,6 +31,10 @@ public record SmtpCredentials(
|
|||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a javax.mail.Authenticator Object with username and password for SMTP Server
|
||||||
|
* @return the created javax.mail.Authenticator Object
|
||||||
|
*/
|
||||||
private javax.mail.Authenticator getAuthenticator() {
|
private javax.mail.Authenticator getAuthenticator() {
|
||||||
return new javax.mail.Authenticator() {
|
return new javax.mail.Authenticator() {
|
||||||
@Override
|
@Override
|
||||||
@@ -32,10 +44,11 @@ public record SmtpCredentials(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to get the Session Instance with the given SMTP Credentials
|
||||||
|
* @return the Session Instance
|
||||||
|
*/
|
||||||
public Session getSession() {
|
public Session getSession() {
|
||||||
return Session.getInstance(getProperties(), getAuthenticator());
|
return Session.getInstance(getProperties(), getAuthenticator());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
package ch.zhaw.gartenverwaltung.backgroundtasks.weather;
|
package ch.zhaw.gartenverwaltung.backgroundtasks.weather;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enum of possible Weather events
|
||||||
|
*/
|
||||||
public enum SevereWeather {
|
public enum SevereWeather {
|
||||||
FROST,SNOW,HAIL,NO_SEVERE_WEATHER,RAIN
|
FROST,SNOW,HAIL,NO_SEVERE_WEATHER,RAIN
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,14 +10,10 @@ import ch.zhaw.gartenverwaltung.types.*;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static java.util.stream.Collectors.toList;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The WeatherGardenTaskPlanner creates Tasks based on weather events and the rain amount from the last days
|
* The WeatherGardenTaskPlanner creates Tasks based on weather events and the rain amount from the last days
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class WeatherGradenTaskPlanner {
|
public class WeatherGradenTaskPlanner {
|
||||||
private final TaskList taskList;
|
private final TaskList taskList;
|
||||||
@@ -46,12 +42,19 @@ public class WeatherGradenTaskPlanner {
|
|||||||
|
|
||||||
private void getSevereWeatherEvents() throws IOException {
|
private void getSevereWeatherEvents() throws IOException {
|
||||||
SevereWeather actualWeather = weatherService.causeSevereWeather(1);
|
SevereWeather actualWeather = weatherService.causeSevereWeather(1);
|
||||||
if (SevereWeather.HAIL.equals(actualWeather)) {
|
|
||||||
createPreHailTask();
|
List<Crop> actualCrops = cropList.getCrops();
|
||||||
} else if (SevereWeather.FROST.equals(actualWeather)) {
|
for (Crop crop : actualCrops) {
|
||||||
createPreFrostTask();
|
|
||||||
} else if (SevereWeather.SNOW.equals(actualWeather)) {
|
List<Task> actualCropTasks = taskList.getTaskForCrop(crop.getCropId().orElse(-1L));
|
||||||
createPreSnowTask();
|
|
||||||
|
if (SevereWeather.HAIL.equals(actualWeather)) {
|
||||||
|
createPreHailTask(crop, actualCropTasks);
|
||||||
|
} else if (SevereWeather.FROST.equals(actualWeather)) {
|
||||||
|
createPreFrostTask(crop, actualCropTasks);
|
||||||
|
} else if (SevereWeather.SNOW.equals(actualWeather)) {
|
||||||
|
createPreSnowTask(crop, actualCropTasks);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,87 +64,69 @@ public class WeatherGradenTaskPlanner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method to create a PreHailTask
|
* Method to create a PreHailTask and saves it in the tasklist
|
||||||
* @throws IOException If the database cannot be accessed
|
* @throws IOException If the database cannot be accessed
|
||||||
*/
|
*/
|
||||||
private void createPreHailTask() throws IOException {
|
private void createPreHailTask(Crop crop, List<Task> actualTasksForCrop) throws IOException {
|
||||||
|
Task preHailTask = new Task("Hail",
|
||||||
|
"During a summer Thunderstorm it could hail heavily. THe Hail could damage the crops. To prevent damage cover the plants with a strong tarpaulin",
|
||||||
|
dateSevereWeather,dateSevereWeather.plusDays(1L),crop.getCropId().orElse(-1L));
|
||||||
|
|
||||||
List<Crop> actualCrops = cropList.getCrops();
|
List<Task> hailTasks = actualTasksForCrop.stream().filter(task -> task.getName().equals("Hail")).toList();
|
||||||
|
|
||||||
for (Crop crop : actualCrops) {
|
if(isNoSevereWeatherTaskAtDate(preHailTask, hailTasks) && hailTasks.isEmpty()){
|
||||||
Task preHailTask = new Task("Hail",
|
taskList.saveTask(preHailTask);
|
||||||
"During a summer Thunderstorm it could hail heavily. THe Hail could damage the crops. To prevent damage cover the plants with a strong tarpaulin",
|
|
||||||
dateSevereWeather,dateSevereWeather.plusDays(1L),crop.getCropId().orElse(-1L));
|
|
||||||
|
|
||||||
List<Task> actualCropTaskList = taskList.getTaskForCrop(crop.getCropId().orElse(-1L));
|
|
||||||
List<Task> hailTasklist = actualCropTaskList.stream().filter(task -> task.getName().equals("Hail")).toList();
|
|
||||||
|
|
||||||
List<Task> hailTaskListAtDate = new ArrayList<>();
|
|
||||||
for (Task task : hailTasklist) {
|
|
||||||
if (task.getStartDate() == (preHailTask.getStartDate())) {
|
|
||||||
hailTaskListAtDate.add(task);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(hailTaskListAtDate.isEmpty() && hailTasklist.isEmpty()){
|
|
||||||
taskList.saveTask(preHailTask);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method to create a PreFrosttask
|
* Method to create a PreFrosttask and saves it in the tasklist
|
||||||
* @throws IOException If the database cannot be accessed
|
* @throws IOException If the database cannot be accessed
|
||||||
*/
|
*/
|
||||||
private void createPreFrostTask() throws IOException {
|
private void createPreFrostTask(Crop crop, List<Task> actualTasksForCrop) throws IOException {
|
||||||
List<Crop> actualCrops = cropList.getCrops();
|
Task preFrostTask = new Task("Frost",
|
||||||
for (Crop crop : actualCrops) {
|
|
||||||
|
|
||||||
Task preFrostTask = new Task("Frost",
|
|
||||||
"The temperatur falls below zero degrees, cover especially the root with wool",
|
"The temperatur falls below zero degrees, cover especially the root with wool",
|
||||||
dateSevereWeather,dateSevereWeather.plusDays(1L),crop.getCropId().orElse(-1L));
|
dateSevereWeather,dateSevereWeather.plusDays(1L),crop.getCropId().orElse(-1L));
|
||||||
|
|
||||||
List<Task> actualCropTaskList = taskList.getTaskForCrop(crop.getCropId().orElse(-1L));
|
List<Task> frostTasks = actualTasksForCrop.stream().filter(task -> task.getName().equals("Frost")).toList();
|
||||||
List<Task> frostTasklist = actualCropTaskList.stream().filter(task -> task.getName().equals("Frost")).toList();
|
|
||||||
|
|
||||||
List<Task> frostTaskListAtDate = new ArrayList<>();
|
if(isNoSevereWeatherTaskAtDate(preFrostTask, frostTasks) && frostTasks.isEmpty()){
|
||||||
for (Task task : frostTasklist) {
|
taskList.saveTask(preFrostTask);
|
||||||
if (task.getStartDate() == preFrostTask.getStartDate()) {
|
}
|
||||||
frostTaskListAtDate.add(task);
|
}
|
||||||
}
|
|
||||||
}
|
/**
|
||||||
if(frostTaskListAtDate.isEmpty() && frostTasklist.isEmpty()){
|
* Method to create a PreSnowTask and saves it in the tasklist
|
||||||
taskList.saveTask(preFrostTask);
|
* @throws IOException If the database cannot be accessed
|
||||||
}
|
*/
|
||||||
|
private void createPreSnowTask(Crop crop, List<Task> actualTasksForCrop) throws IOException {
|
||||||
|
Task preSnowTask = new Task("Snow",
|
||||||
|
"The weather brings little snowfall. Cover your crops",
|
||||||
|
dateSevereWeather, dateSevereWeather.plusDays(1L), crop.getCropId().orElse(-1L));
|
||||||
|
|
||||||
|
List<Task> snowTasklist = actualTasksForCrop.stream().filter(task -> task.getName().equals("Snow")).toList();
|
||||||
|
|
||||||
|
if(isNoSevereWeatherTaskAtDate(preSnowTask, snowTasklist) && snowTasklist.isEmpty()){
|
||||||
|
taskList.saveTask(preSnowTask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method to create a PreSnowTask
|
* Method to create a PreSnowTask and saves it in the tasklist
|
||||||
* @throws IOException If the database cannot be accessed
|
* @param preSevereWeatherTask the Task which would be added if there is not already
|
||||||
|
* the same Type of severe weather task
|
||||||
|
* @param severeWeatherTasks List of severe weather tasks from e specific severe weather
|
||||||
|
* @return true If there is not already a severe weather task of the same type of preSevereWeatherTask
|
||||||
|
* task at the date of the preSevereWeatherTask
|
||||||
*/
|
*/
|
||||||
private void createPreSnowTask() throws IOException {
|
private boolean isNoSevereWeatherTaskAtDate(Task preSevereWeatherTask, List<Task> severeWeatherTasks) {
|
||||||
List<Crop> actualCrops = cropList.getCrops();
|
List<Task> severeWeatherTasksAtDate = new ArrayList<>();
|
||||||
for (Crop crop : actualCrops) {
|
for (Task task : severeWeatherTasks) {
|
||||||
|
if (task.getStartDate() == preSevereWeatherTask.getStartDate()) {
|
||||||
Task preSnowTask = new Task("Snow",
|
severeWeatherTasksAtDate.add(task);
|
||||||
"The weather brings little snowfall. Cover your crops",
|
|
||||||
dateSevereWeather, dateSevereWeather.plusDays(1L), crop.getCropId().orElse(-1L));
|
|
||||||
|
|
||||||
List<Task> actualCropTaskList = taskList.getTaskForCrop(crop.getCropId().orElse(-1L));
|
|
||||||
List<Task> snowTasklist = actualCropTaskList.stream().filter(task -> task.getName().equals("Snow")).toList();
|
|
||||||
|
|
||||||
List<Task> snowTaskListAtDate = new ArrayList<>();
|
|
||||||
for (Task task : snowTasklist) {
|
|
||||||
if (task.getStartDate() == preSnowTask.getStartDate()) {
|
|
||||||
snowTaskListAtDate.add(task);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if(snowTaskListAtDate .isEmpty() && snowTasklist.isEmpty()){
|
|
||||||
taskList.saveTask(preSnowTask);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
return severeWeatherTasksAtDate.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package ch.zhaw.gartenverwaltung.backgroundtasks.weather;
|
package ch.zhaw.gartenverwaltung.backgroundtasks.weather;
|
||||||
/**
|
/**
|
||||||
* The WeatherService is a class to cause weather events for the WeatherGardenTaskPlanner
|
* The WeatherService is a class to cause weather events for the WeatherGardenTaskPlanner
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class WeatherService {
|
public class WeatherService {
|
||||||
private static final int NO_RAIN = 0;
|
private static final int NO_RAIN = 0;
|
||||||
@@ -9,6 +8,11 @@ public class WeatherService {
|
|||||||
private static final int RAIN = 25;
|
private static final int RAIN = 25;
|
||||||
private static final int HEAVY_RAIN = 50;
|
private static final int HEAVY_RAIN = 50;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to simmulate a Weather Service for testing
|
||||||
|
* @param randomWeather random int. Range: 1-3
|
||||||
|
* @return the selected SevereWeather
|
||||||
|
*/
|
||||||
public SevereWeather causeSevereWeather(int randomWeather) {
|
public SevereWeather causeSevereWeather(int randomWeather) {
|
||||||
return switch (randomWeather) {
|
return switch (randomWeather) {
|
||||||
case 1 -> SevereWeather.HAIL;
|
case 1 -> SevereWeather.HAIL;
|
||||||
@@ -19,6 +23,11 @@ public class WeatherService {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to simulate a Weather Service for testing
|
||||||
|
* @param randomRainAmount random int. Range: 1-4
|
||||||
|
* @return the selected rain amount
|
||||||
|
*/
|
||||||
public int causeRainAmount(int randomRainAmount) {
|
public int causeRainAmount(int randomRainAmount) {
|
||||||
return switch (randomRainAmount) {
|
return switch (randomRainAmount) {
|
||||||
case 1 -> NO_RAIN;
|
case 1 -> NO_RAIN;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package ch.zhaw.gartenverwaltung.bootstrap;
|
package ch.zhaw.gartenverwaltung.bootstrap;
|
||||||
|
|
||||||
|
import ch.zhaw.gartenverwaltung.CropDetailController;
|
||||||
import ch.zhaw.gartenverwaltung.Main;
|
import ch.zhaw.gartenverwaltung.Main;
|
||||||
import ch.zhaw.gartenverwaltung.io.*;
|
import ch.zhaw.gartenverwaltung.io.*;
|
||||||
import ch.zhaw.gartenverwaltung.models.Garden;
|
import ch.zhaw.gartenverwaltung.models.Garden;
|
||||||
@@ -17,12 +18,15 @@ import java.util.Arrays;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class responsible for bootstrapping the application wide dependencies
|
* Class responsible for bootstrapping the application wide dependencies
|
||||||
* and injecting them into JavaFX Controllers.
|
* and injecting them into JavaFX Controllers.
|
||||||
*/
|
*/
|
||||||
public class AppLoader {
|
public class AppLoader {
|
||||||
|
private static final Logger LOG = Logger.getLogger(CropDetailController.class.getName());
|
||||||
/**
|
/**
|
||||||
* Caching the panes
|
* Caching the panes
|
||||||
*/
|
*/
|
||||||
@@ -146,12 +150,17 @@ public class AppLoader {
|
|||||||
try {
|
try {
|
||||||
afterInjectMethod.invoke(controller);
|
afterInjectMethod.invoke(controller);
|
||||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||||
// TODO: Log
|
LOG.log(Level.SEVERE, "Could not invoke afterInjectMethod", e.getCause());
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to get any AppDependency
|
||||||
|
* @param type Class of Dependency
|
||||||
|
* @return the App dependency
|
||||||
|
*/
|
||||||
public Object getAppDependency(Class<?> type) {
|
public Object getAppDependency(Class<?> type) {
|
||||||
return dependencies.get(type.getSimpleName());
|
return dependencies.get(type.getSimpleName());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
package ch.zhaw.gartenverwaltung.io;
|
package ch.zhaw.gartenverwaltung.io;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exceptionm which is thrown if Hardiness zone is not set in plant list.
|
||||||
|
*/
|
||||||
public class HardinessZoneNotSetException extends Exception {
|
public class HardinessZoneNotSetException extends Exception {
|
||||||
public HardinessZoneNotSetException() {
|
public HardinessZoneNotSetException() {
|
||||||
super("HardinessZone must be set to retrieve plants!");
|
super("HardinessZone must be set to retrieve plants!");
|
||||||
|
|||||||
@@ -2,6 +2,9 @@ package ch.zhaw.gartenverwaltung.io;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Excption which is thrown if a JSON file has a invalid File format.
|
||||||
|
*/
|
||||||
class InvalidJsonException extends IOException {
|
class InvalidJsonException extends IOException {
|
||||||
public InvalidJsonException(String reason) {
|
public InvalidJsonException(String reason) {
|
||||||
super(reason);
|
super(reason);
|
||||||
|
|||||||
@@ -50,8 +50,6 @@ public class Garden {
|
|||||||
*/
|
*/
|
||||||
public void plantAsCrop(Plant plant, LocalDate plantingDate) throws IOException, HardinessZoneNotSetException, PlantNotFoundException {
|
public void plantAsCrop(Plant plant, LocalDate plantingDate) throws IOException, HardinessZoneNotSetException, PlantNotFoundException {
|
||||||
Crop crop = new Crop(plant.id(), plantingDate);
|
Crop crop = new Crop(plant.id(), plantingDate);
|
||||||
//TODO Add Area to Plant
|
|
||||||
//crop.withArea(0);
|
|
||||||
cropList.saveCrop(crop);
|
cropList.saveCrop(crop);
|
||||||
gardenSchedule.planTasksForCrop(crop);
|
gardenSchedule.planTasksForCrop(crop);
|
||||||
plantedCrops.clear();
|
plantedCrops.clear();
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package ch.zhaw.gartenverwaltung.models;
|
package ch.zhaw.gartenverwaltung.models;
|
||||||
|
|
||||||
|
import ch.zhaw.gartenverwaltung.Settings;
|
||||||
import ch.zhaw.gartenverwaltung.io.HardinessZoneNotSetException;
|
import ch.zhaw.gartenverwaltung.io.HardinessZoneNotSetException;
|
||||||
import ch.zhaw.gartenverwaltung.io.PlantList;
|
import ch.zhaw.gartenverwaltung.io.PlantList;
|
||||||
import ch.zhaw.gartenverwaltung.types.GrowthPhaseType;
|
import ch.zhaw.gartenverwaltung.types.GrowthPhaseType;
|
||||||
@@ -16,7 +17,6 @@ import java.util.stream.Collectors;
|
|||||||
|
|
||||||
public class PlantListModel {
|
public class PlantListModel {
|
||||||
private final PlantList plantList;
|
private final PlantList plantList;
|
||||||
private HardinessZone currentZone;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Comparators to create sorted Plant List
|
* Comparators to create sorted Plant List
|
||||||
@@ -33,15 +33,15 @@ public class PlantListModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setDefaultZone() {
|
private void setDefaultZone() {
|
||||||
currentZone = HardinessZone.ZONE_8A; // TODO: get Default Zone from Settings
|
Settings.getInstance().setCurrentHardinessZone(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCurrentZone(HardinessZone currentZone) {
|
public void setCurrentZone(HardinessZone currentZone) {
|
||||||
this.currentZone = currentZone;
|
Settings.getInstance().setCurrentHardinessZone(currentZone);
|
||||||
}
|
}
|
||||||
|
|
||||||
public HardinessZone getCurrentZone() {
|
public HardinessZone getCurrentZone() {
|
||||||
return currentZone;
|
return Settings.getInstance().getCurrentHardinessZone();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
package ch.zhaw.gartenverwaltung.models;
|
package ch.zhaw.gartenverwaltung.models;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception which is thrown if there is no plant in plant Database with the given id.
|
||||||
|
*/
|
||||||
public class PlantNotFoundException extends Exception {
|
public class PlantNotFoundException extends Exception {
|
||||||
public PlantNotFoundException() {
|
public PlantNotFoundException() {
|
||||||
super("The selected Plant was not found in Database!");
|
super("The selected Plant was not found in Database!");
|
||||||
|
|||||||
@@ -40,7 +40,6 @@ public class Crop {
|
|||||||
public Optional<Long> getCropId() {
|
public Optional<Long> getCropId() {
|
||||||
return Optional.ofNullable(cropId);
|
return Optional.ofNullable(cropId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getPlantId() { return plantId; }
|
public long getPlantId() { return plantId; }
|
||||||
public LocalDate getStartDate() { return startDate; }
|
public LocalDate getStartDate() { return startDate; }
|
||||||
public double getArea() { return area; }
|
public double getArea() { return area; }
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ public record Plant(
|
|||||||
return growthPhase.group();
|
return growthPhase.group();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0; // TODO implement
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -4,6 +4,9 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
|||||||
|
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class which represents a Task if the start and enddate is not known yet.
|
||||||
|
*/
|
||||||
public class TaskTemplate {
|
public class TaskTemplate {
|
||||||
@JsonProperty
|
@JsonProperty
|
||||||
private final String name;
|
private final String name;
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
<?import javafx.scene.text.Text?>
|
<?import javafx.scene.text.Text?>
|
||||||
<?import javafx.scene.text.TextFlow?>
|
<?import javafx.scene.text.TextFlow?>
|
||||||
|
|
||||||
<BorderPane maxHeight="470.0" maxWidth="724.0" minHeight="470.0" minWidth="724.0" prefHeight="470.0" prefWidth="724.0" xmlns="http://javafx.com/javafx/19" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ch.zhaw.gartenverwaltung.TutorialController">
|
<BorderPane maxHeight="470.0" maxWidth="724.0" minHeight="470.0" minWidth="724.0" prefHeight="470.0" prefWidth="724.0" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ch.zhaw.gartenverwaltung.TutorialController">
|
||||||
<bottom>
|
<bottom>
|
||||||
<HBox alignment="CENTER" prefHeight="0.0" prefWidth="724.0" BorderPane.alignment="CENTER">
|
<HBox alignment="CENTER" prefHeight="0.0" prefWidth="724.0" BorderPane.alignment="CENTER">
|
||||||
<children>
|
<children>
|
||||||
|
|||||||
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 34 KiB |
@@ -101,7 +101,7 @@ class PlantListModelTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void setCurrentZone() {
|
void setCurrentZone() {
|
||||||
checkCurrentZone(HardinessZone.ZONE_8A); // TODO change to get default zone from config
|
checkCurrentZone(HardinessZone.ZONE_8A);
|
||||||
model.setCurrentZone(HardinessZone.ZONE_1A);
|
model.setCurrentZone(HardinessZone.ZONE_1A);
|
||||||
checkCurrentZone(HardinessZone.ZONE_1A);
|
checkCurrentZone(HardinessZone.ZONE_1A);
|
||||||
model.setCurrentZone(HardinessZone.ZONE_8A);
|
model.setCurrentZone(HardinessZone.ZONE_8A);
|
||||||
|
|||||||