Compare commits
13 Commits
56020a7529
...
8a2119028c
Author | SHA1 | Date |
---|---|---|
Roman Schenk | 8a2119028c | |
giavaphi | 083d934472 | |
schrom01 | 1b096035a7 | |
schrom01 | 0074d43364 | |
Gian-Andrea Hutter | 3bda390708 | |
Roman Schenk | c6952aba55 | |
Roman Schenk | 807a9017ad | |
Roman Schenk | c134025408 | |
Roman Schenk | 1e95e0ff30 | |
David Guler | fb21797040 | |
Elias Csomor | 76197a19df | |
schrom01 | 5f7d690875 | |
giavaphi | 96dc0ad827 |
|
@ -3,15 +3,15 @@ package ch.zhaw.gartenverwaltung;
|
||||||
import ch.zhaw.gartenverwaltung.bootstrap.AfterInject;
|
import ch.zhaw.gartenverwaltung.bootstrap.AfterInject;
|
||||||
import ch.zhaw.gartenverwaltung.bootstrap.Inject;
|
import ch.zhaw.gartenverwaltung.bootstrap.Inject;
|
||||||
import ch.zhaw.gartenverwaltung.io.PlantList;
|
import ch.zhaw.gartenverwaltung.io.PlantList;
|
||||||
|
import ch.zhaw.gartenverwaltung.io.TaskList;
|
||||||
import ch.zhaw.gartenverwaltung.models.Garden;
|
import ch.zhaw.gartenverwaltung.models.Garden;
|
||||||
import ch.zhaw.gartenverwaltung.io.HardinessZoneNotSetException;
|
import ch.zhaw.gartenverwaltung.io.HardinessZoneNotSetException;
|
||||||
import ch.zhaw.gartenverwaltung.models.GardenSchedule;
|
import ch.zhaw.gartenverwaltung.models.GardenSchedule;
|
||||||
import ch.zhaw.gartenverwaltung.types.Crop;
|
import ch.zhaw.gartenverwaltung.types.Crop;
|
||||||
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.collections.FXCollections;
|
|
||||||
import javafx.event.ActionEvent;
|
import javafx.event.ActionEvent;
|
||||||
import javafx.event.EventHandler;
|
import javafx.event.EventHandler;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
|
@ -51,9 +51,15 @@ public class MyScheduleController {
|
||||||
@FXML
|
@FXML
|
||||||
private ListView<Crop> scheduledPlants_listview;
|
private ListView<Crop> scheduledPlants_listview;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private void showAllTasks(ActionEvent actionEvent) throws IOException {
|
||||||
|
gardenSchedule.getTasksUpcomingWeek();
|
||||||
|
scheduledPlants_listview.getSelectionModel().clearSelection();
|
||||||
|
}
|
||||||
|
|
||||||
@AfterInject
|
@AfterInject
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public void init() {
|
public void init() throws IOException {
|
||||||
setCellFactoryCropListView();
|
setCellFactoryCropListView();
|
||||||
setCellFactoryTaskListView();
|
setCellFactoryTaskListView();
|
||||||
scheduledPlants_listview.itemsProperty().bind(garden.getPlantedCrops());
|
scheduledPlants_listview.itemsProperty().bind(garden.getPlantedCrops());
|
||||||
|
@ -61,6 +67,19 @@ public class MyScheduleController {
|
||||||
week_listView.itemsProperty().bind(taskListProperty);
|
week_listView.itemsProperty().bind(taskListProperty);
|
||||||
lookForSelectedListEntries();
|
lookForSelectedListEntries();
|
||||||
information_label.setText("");
|
information_label.setText("");
|
||||||
|
|
||||||
|
gardenSchedule.getTasksUpcomingWeek();
|
||||||
|
TaskList.TaskListObserver taskListObserver = newTaskList -> {
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
try {
|
||||||
|
gardenSchedule.getTasksUpcomingWeek();
|
||||||
|
scheduledPlants_listview.getSelectionModel().clearSelection();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
gardenSchedule.setTaskListObserver(taskListObserver);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -81,6 +100,8 @@ public class MyScheduleController {
|
||||||
* set cellFactory for the crops.
|
* set cellFactory for the crops.
|
||||||
*/
|
*/
|
||||||
private void setCellFactoryCropListView() {
|
private void setCellFactoryCropListView() {
|
||||||
|
MultipleSelectionModel<Crop> selectionModel = scheduledPlants_listview.getSelectionModel();
|
||||||
|
selectionModel.setSelectionMode(SelectionMode.MULTIPLE);
|
||||||
scheduledPlants_listview.setCellFactory(param -> new ListCell<>() {
|
scheduledPlants_listview.setCellFactory(param -> new ListCell<>() {
|
||||||
@Override
|
@Override
|
||||||
protected void updateItem(Crop crop, boolean empty) {
|
protected void updateItem(Crop crop, boolean empty) {
|
||||||
|
@ -133,8 +154,6 @@ public class MyScheduleController {
|
||||||
} else {
|
} else {
|
||||||
gardenSchedule.getTasksUpcomingWeek();
|
gardenSchedule.getTasksUpcomingWeek();
|
||||||
}
|
}
|
||||||
//taskListProperty.clear();
|
|
||||||
//taskListProperty.addAll(taskLists);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -202,5 +221,4 @@ public class MyScheduleController {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,8 @@ public class TutorialController {
|
||||||
public ImageView imgAddNewPlant;
|
public ImageView imgAddNewPlant;
|
||||||
public ImageView imgTaskList;
|
public ImageView imgTaskList;
|
||||||
public ImageView imgSelectDate;
|
public ImageView imgSelectDate;
|
||||||
|
public ImageView imgAddTaskButton;
|
||||||
|
public ImageView imgDetailDeleteButtons;
|
||||||
|
|
||||||
private int page = 0;
|
private int page = 0;
|
||||||
|
|
||||||
|
@ -30,10 +32,17 @@ public class TutorialController {
|
||||||
switchViews();
|
switchViews();
|
||||||
setButtonAbilities();
|
setButtonAbilities();
|
||||||
|
|
||||||
Image placeholder = new Image(String.valueOf(PlantsController.class.getResource("placeholder.png")));
|
Image addNewPlantImage = new Image(String.valueOf(PlantsController.class.getResource("add-new-plant.png")));
|
||||||
imgAddNewPlant.setImage(placeholder);
|
Image selectSowHarvestImage = new Image(String.valueOf(PlantsController.class.getResource("select-sow-harvest.png")));
|
||||||
imgSelectDate.setImage(placeholder);
|
Image scheduleImage = new Image(String.valueOf(PlantsController.class.getResource("schedule.png")));
|
||||||
imgTaskList.setImage(placeholder);
|
Image detailDeleteButtonsImage = new Image(String.valueOf(PlantsController.class.getResource("details-delete.png")));
|
||||||
|
Image addTaskImage = new Image(String.valueOf(PlantsController.class.getResource("add-task.png")));
|
||||||
|
|
||||||
|
imgAddNewPlant.setImage(addNewPlantImage);
|
||||||
|
imgSelectDate.setImage(selectSowHarvestImage);
|
||||||
|
imgDetailDeleteButtons.setImage(detailDeleteButtonsImage);
|
||||||
|
imgAddTaskButton.setImage(addTaskImage);
|
||||||
|
imgTaskList.setImage(scheduleImage);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void viewNextPage() {
|
public void viewNextPage() {
|
||||||
|
|
|
@ -25,11 +25,12 @@ public class BackgroundTasks extends TimerTask {
|
||||||
|
|
||||||
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, LocalDate.now().minusDays(1));
|
||||||
taskList.forEach(task -> {
|
for (Task task : taskList) {
|
||||||
if (!task.isDone()) {
|
if (!task.isDone()) {
|
||||||
task.setNextExecution(LocalDate.now());
|
task.setNextExecution(LocalDate.now());
|
||||||
|
this.taskList.saveTask(task);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public BackgroundTasks(TaskList taskList, CropList cropList, PlantList plantList) {
|
public BackgroundTasks(TaskList taskList, CropList cropList, PlantList plantList) {
|
||||||
|
|
|
@ -9,8 +9,12 @@ 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.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
|
||||||
*
|
*
|
||||||
|
@ -43,8 +47,7 @@ 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)) {
|
if (SevereWeather.HAIL.equals(actualWeather)) {
|
||||||
//ToDo creates hail task all 3 seconds, pls fix
|
createPreHailTask();
|
||||||
//createPreHailTask();
|
|
||||||
} else if (SevereWeather.FROST.equals(actualWeather)) {
|
} else if (SevereWeather.FROST.equals(actualWeather)) {
|
||||||
createPreFrostTask();
|
createPreFrostTask();
|
||||||
} else if (SevereWeather.SNOW.equals(actualWeather)) {
|
} else if (SevereWeather.SNOW.equals(actualWeather)) {
|
||||||
|
@ -63,11 +66,27 @@ public class WeatherGradenTaskPlanner {
|
||||||
*/
|
*/
|
||||||
private void createPreHailTask() throws IOException {
|
private void createPreHailTask() throws IOException {
|
||||||
|
|
||||||
Task preHailTask = new Task("Hail",
|
List<Crop> actualCrops = cropList.getCrops();
|
||||||
"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.minusDays(1L),dateSevereWeather.plusDays(1L),1L);
|
|
||||||
taskList.saveTask(preHailTask);
|
|
||||||
|
|
||||||
|
for (Crop crop : actualCrops) {
|
||||||
|
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<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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -75,10 +94,26 @@ public class WeatherGradenTaskPlanner {
|
||||||
* @throws IOException If the database cannot be accessed
|
* @throws IOException If the database cannot be accessed
|
||||||
*/
|
*/
|
||||||
private void createPreFrostTask() throws IOException {
|
private void createPreFrostTask() throws IOException {
|
||||||
Task preFrostTask = new Task("Frost",
|
List<Crop> actualCrops = cropList.getCrops();
|
||||||
"The temperatur falls below zero degrees, cover especially the root with wool",
|
for (Crop crop : actualCrops) {
|
||||||
dateSevereWeather.minusDays(1L),dateSevereWeather.plusDays(1L),1L);
|
|
||||||
taskList.saveTask(preFrostTask);
|
Task preFrostTask = new Task("Frost",
|
||||||
|
"The temperatur falls below zero degrees, cover especially the root with wool",
|
||||||
|
dateSevereWeather,dateSevereWeather.plusDays(1L),crop.getCropId().orElse(-1L));
|
||||||
|
|
||||||
|
List<Task> actualCropTaskList = taskList.getTaskForCrop(crop.getCropId().orElse(-1L));
|
||||||
|
List<Task> frostTasklist = actualCropTaskList.stream().filter(task -> task.getName().equals("Frost")).toList();
|
||||||
|
|
||||||
|
List<Task> frostTaskListAtDate = new ArrayList<>();
|
||||||
|
for (Task task : frostTasklist) {
|
||||||
|
if (task.getStartDate() == preFrostTask.getStartDate()) {
|
||||||
|
frostTaskListAtDate.add(task);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(frostTaskListAtDate.isEmpty() && frostTasklist.isEmpty()){
|
||||||
|
taskList.saveTask(preFrostTask);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -86,10 +121,27 @@ public class WeatherGradenTaskPlanner {
|
||||||
* @throws IOException If the database cannot be accessed
|
* @throws IOException If the database cannot be accessed
|
||||||
*/
|
*/
|
||||||
private void createPreSnowTask() throws IOException {
|
private void createPreSnowTask() throws IOException {
|
||||||
Task preSnowTask = new Task("Snow",
|
List<Crop> actualCrops = cropList.getCrops();
|
||||||
"The weather brings little snowfall. Cover your crops",
|
for (Crop crop : actualCrops) {
|
||||||
dateSevereWeather.minusDays(1L),dateSevereWeather.plusDays(1L),1L);
|
|
||||||
taskList.saveTask(preSnowTask);
|
Task preSnowTask = new Task("Snow",
|
||||||
|
"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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -32,16 +32,6 @@ public class GardenSchedule {
|
||||||
public GardenSchedule(TaskList taskList, PlantList plantList) throws IOException {
|
public GardenSchedule(TaskList taskList, PlantList plantList) throws IOException {
|
||||||
this.taskList = taskList;
|
this.taskList = taskList;
|
||||||
this.plantList = plantList;
|
this.plantList = plantList;
|
||||||
TaskList.TaskListObserver taskListObserver = newTaskList -> {
|
|
||||||
Platform.runLater(() -> {
|
|
||||||
try {
|
|
||||||
getTasksUpcomingWeek();
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
setTaskListObserver(taskListObserver);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ListProperty<List<Task>> getWeeklyTaskListProperty() {
|
public ListProperty<List<Task>> getWeeklyTaskListProperty() {
|
||||||
|
@ -176,14 +166,12 @@ public class GardenSchedule {
|
||||||
dayTaskList.add(new ArrayList<>());
|
dayTaskList.add(new ArrayList<>());
|
||||||
final int finalI = i;
|
final int finalI = i;
|
||||||
weekTasks.forEach(task -> {
|
weekTasks.forEach(task -> {
|
||||||
if (task.getNextExecution() == null) {
|
if(task.getNextExecution() != null) {
|
||||||
task.isDone();
|
|
||||||
} else {
|
|
||||||
LocalDate checkDate = task.getNextExecution();
|
LocalDate checkDate = task.getNextExecution();
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (date.equals(checkDate) && !date.isAfter(task.getEndDate().orElse(LocalDate.MIN))) {
|
if (date.equals(task.getNextExecution()) || (date.equals(checkDate) && !date.isAfter(task.getEndDate().orElse(LocalDate.MIN)))) {
|
||||||
dayTaskList.get(finalI).add(task);
|
dayTaskList.get(finalI).add(task);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
checkDate = checkDate.plusDays(task.getInterval().orElse(0));
|
checkDate = checkDate.plusDays(task.getInterval().orElse(0));
|
||||||
} while (!(task.getInterval().orElse(0) == 0) && checkDate.isBefore(LocalDate.now().plusDays(listLength)));
|
} while (!(task.getInterval().orElse(0) == 0) && checkDate.isBefore(LocalDate.now().plusDays(listLength)));
|
||||||
|
|
|
@ -63,6 +63,7 @@ public class Task {
|
||||||
this.startDate = startDate;
|
this.startDate = startDate;
|
||||||
nextExecution = startDate;
|
nextExecution = startDate;
|
||||||
this.endDate = endDate;
|
this.endDate = endDate;
|
||||||
|
this.cropId = cropId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -107,7 +108,7 @@ public class Task {
|
||||||
* @return Whether the Task is within the given range
|
* @return Whether the Task is within the given range
|
||||||
*/
|
*/
|
||||||
public boolean isInTimePeriod(LocalDate searchStartDate, LocalDate searchEndDate) {
|
public boolean isInTimePeriod(LocalDate searchStartDate, LocalDate searchEndDate) {
|
||||||
return endDate.isAfter(searchStartDate) && startDate.isBefore(searchEndDate) || (nextExecution != null && nextExecution.isBefore(searchEndDate) && nextExecution.isAfter(searchStartDate));
|
return (endDate.isAfter(searchStartDate) && startDate.isBefore(searchEndDate)) || ((nextExecution != null && nextExecution.isBefore(searchEndDate.plusDays(1)) && nextExecution.isAfter(searchStartDate.minusDays(1))));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -89,7 +89,7 @@
|
||||||
<Insets bottom="10.0" />
|
<Insets bottom="10.0" />
|
||||||
</VBox.margin>
|
</VBox.margin>
|
||||||
</ListView>
|
</ListView>
|
||||||
<Button styleClass="button-class" fx:id="addTask_button" mnemonicParsing="false" onAction="#addTask" prefHeight="25.0" prefWidth="45.0" VBox.vgrow="NEVER">
|
<Button styleClass="button-class" fx:id="addTask_button" mnemonicParsing="false" onAction="#addTask" prefHeight="25.0" prefWidth="120.0" VBox.vgrow="NEVER" text="Add Task">
|
||||||
<VBox.margin>
|
<VBox.margin>
|
||||||
<Insets />
|
<Insets />
|
||||||
</VBox.margin>
|
</VBox.margin>
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
<?import javafx.geometry.Insets?>
|
<?import javafx.geometry.Insets?>
|
||||||
|
<?import javafx.scene.control.Button?>
|
||||||
<?import javafx.scene.control.Label?>
|
<?import javafx.scene.control.Label?>
|
||||||
<?import javafx.scene.control.ListView?>
|
<?import javafx.scene.control.ListView?>
|
||||||
<?import javafx.scene.layout.AnchorPane?>
|
<?import javafx.scene.layout.AnchorPane?>
|
||||||
|
@ -19,11 +20,12 @@
|
||||||
</Label>
|
</Label>
|
||||||
<HBox maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="541.0" prefWidth="867.0" spacing="10.0" VBox.vgrow="ALWAYS">
|
<HBox maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="541.0" prefWidth="867.0" spacing="10.0" VBox.vgrow="ALWAYS">
|
||||||
<children>
|
<children>
|
||||||
<ListView fx:id="scheduledPlants_listview" maxWidth="1.7976931348623157E308" prefHeight="522.0" prefWidth="271.0" HBox.hgrow="NEVER">
|
<VBox prefHeight="497.0" prefWidth="237.0" spacing="10.0" HBox.hgrow="NEVER">
|
||||||
<HBox.margin>
|
<children>
|
||||||
<Insets />
|
<ListView fx:id="scheduledPlants_listview" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="522.0" prefWidth="271.0" VBox.vgrow="ALWAYS" />
|
||||||
</HBox.margin>
|
<Button maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#showAllTasks" styleClass="button-class" text="Show All Tasks" VBox.vgrow="NEVER" />
|
||||||
</ListView>
|
</children>
|
||||||
|
</VBox>
|
||||||
<VBox maxWidth="1.7976931348623157E308" prefHeight="537.0" prefWidth="650.0" spacing="10.0" HBox.hgrow="ALWAYS">
|
<VBox maxWidth="1.7976931348623157E308" prefHeight="537.0" prefWidth="650.0" spacing="10.0" HBox.hgrow="ALWAYS">
|
||||||
<children>
|
<children>
|
||||||
<ListView fx:id="week_listView" maxWidth="1.7976931348623157E308" prefHeight="200.0" prefWidth="200.0" VBox.vgrow="ALWAYS">
|
<ListView fx:id="week_listView" maxWidth="1.7976931348623157E308" prefHeight="200.0" prefWidth="200.0" VBox.vgrow="ALWAYS">
|
||||||
|
|
|
@ -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/17" 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/19" 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>
|
||||||
|
@ -22,9 +22,9 @@
|
||||||
<Separator prefWidth="50.0" visible="false" HBox.hgrow="ALWAYS" />
|
<Separator prefWidth="50.0" visible="false" HBox.hgrow="ALWAYS" />
|
||||||
<ButtonBar prefHeight="40.0" prefWidth="200.0">
|
<ButtonBar prefHeight="40.0" prefWidth="200.0">
|
||||||
<buttons>
|
<buttons>
|
||||||
<Button styleClass="button-class" cancelButton="true" contentDisplay="CENTER" graphicTextGap="5.0" mnemonicParsing="false" text="Close" onAction="#closeTutorial"/>
|
<Button cancelButton="true" contentDisplay="CENTER" graphicTextGap="5.0" mnemonicParsing="false" onAction="#closeTutorial" styleClass="button-class" text="Close" />
|
||||||
<Button styleClass="button-class" fx:id="previousPageButton" mnemonicParsing="false" text="Previous" onAction="#viewPreviousPage"/>
|
<Button fx:id="previousPageButton" mnemonicParsing="false" onAction="#viewPreviousPage" styleClass="button-class" text="Previous" />
|
||||||
<Button styleClass="button-class" fx:id="nextPageButton" defaultButton="true" mnemonicParsing="false" text="Next" onAction="#viewNextPage" />
|
<Button fx:id="nextPageButton" defaultButton="true" mnemonicParsing="false" onAction="#viewNextPage" styleClass="button-class" text="Next" />
|
||||||
</buttons>
|
</buttons>
|
||||||
</ButtonBar>
|
</ButtonBar>
|
||||||
</children>
|
</children>
|
||||||
|
@ -38,7 +38,7 @@
|
||||||
<children>
|
<children>
|
||||||
<VBox layoutX="30.0" layoutY="26.0" opacity="0.0" prefHeight="200.0" prefWidth="100.0">
|
<VBox layoutX="30.0" layoutY="26.0" opacity="0.0" prefHeight="200.0" prefWidth="100.0">
|
||||||
<children>
|
<children>
|
||||||
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="Managing Your Crops">
|
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="Adding Crops">
|
||||||
<font>
|
<font>
|
||||||
<Font size="24.0" />
|
<Font size="24.0" />
|
||||||
</font>
|
</font>
|
||||||
|
@ -75,7 +75,7 @@
|
||||||
</children>
|
</children>
|
||||||
</TextFlow>
|
</TextFlow>
|
||||||
<Separator prefWidth="200.0" visible="false" HBox.hgrow="ALWAYS" />
|
<Separator prefWidth="200.0" visible="false" HBox.hgrow="ALWAYS" />
|
||||||
<ImageView fx:id="imgSelectDate" fitHeight="150.0" fitWidth="200.0" pickOnBounds="true" preserveRatio="true" />
|
<ImageView fx:id="imgSelectDate" fitHeight="150.0" fitWidth="400.0" pickOnBounds="true" preserveRatio="true" />
|
||||||
</children>
|
</children>
|
||||||
</HBox>
|
</HBox>
|
||||||
</children>
|
</children>
|
||||||
|
@ -83,7 +83,50 @@
|
||||||
<Insets />
|
<Insets />
|
||||||
</opaqueInsets>
|
</opaqueInsets>
|
||||||
</VBox>
|
</VBox>
|
||||||
<VBox prefHeight="200.0" prefWidth="100.0">
|
<VBox layoutX="30.0" layoutY="30.0" prefHeight="200.0" prefWidth="100.0">
|
||||||
|
<children>
|
||||||
|
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="Managing Your Crops">
|
||||||
|
<font>
|
||||||
|
<Font size="24.0" />
|
||||||
|
</font>
|
||||||
|
</Text>
|
||||||
|
<Separator prefWidth="200.0">
|
||||||
|
<VBox.margin>
|
||||||
|
<Insets bottom="15.0" top="10.0" />
|
||||||
|
</VBox.margin>
|
||||||
|
</Separator>
|
||||||
|
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="Once you've added a crop to your garden, it will be displayed in the "My Garden" tab.">
|
||||||
|
<VBox.margin>
|
||||||
|
<Insets bottom="20.0" />
|
||||||
|
</VBox.margin>
|
||||||
|
</Text>
|
||||||
|
<HBox prefHeight="100.0" prefWidth="200.0">
|
||||||
|
<children>
|
||||||
|
<TextFlow lineSpacing="4.0" prefHeight="200.0" prefWidth="500.0">
|
||||||
|
<children>
|
||||||
|
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="On the right hand side of the listing, you'll see two buttons. Button with the "trash can" icon lets you remove a crop from your garden plan. This will also delete all associated tasks. The button on the left will display the details of the crop in a new window." />
|
||||||
|
</children>
|
||||||
|
</TextFlow>
|
||||||
|
<Separator prefWidth="200.0" visible="false" HBox.hgrow="ALWAYS" />
|
||||||
|
<ImageView fitHeight="70.0" fitWidth="100.0" pickOnBounds="true" preserveRatio="true" fx:id="imgDetailDeleteButtons"/>
|
||||||
|
</children></HBox>
|
||||||
|
<HBox layoutX="10.0" layoutY="105.0" prefHeight="100.0" prefWidth="200.0">
|
||||||
|
<children>
|
||||||
|
<TextFlow lineSpacing="4.0" prefHeight="200.0" prefWidth="500.0">
|
||||||
|
<children>
|
||||||
|
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="Here, you can also add your own custom tasks, by clicking the "Add Task" button. In the subsequently shown dialog, you can enter the corresponding details. Note: If you want to make a task recurring, you need to set both an interval (in days) AND an end date, so the task won't repeat for all eternity." />
|
||||||
|
</children>
|
||||||
|
</TextFlow>
|
||||||
|
<Separator prefWidth="200.0" visible="false" HBox.hgrow="ALWAYS" />
|
||||||
|
<ImageView fitHeight="150.0" fitWidth="400.0" pickOnBounds="true" preserveRatio="true" fx:id="imgAddTaskButton"/>
|
||||||
|
</children>
|
||||||
|
</HBox>
|
||||||
|
</children>
|
||||||
|
<opaqueInsets>
|
||||||
|
<Insets />
|
||||||
|
</opaqueInsets>
|
||||||
|
</VBox>
|
||||||
|
<VBox opacity="0.0" prefHeight="200.0" prefWidth="100.0">
|
||||||
<children>
|
<children>
|
||||||
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="Managing Your Tasks">
|
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="Managing Your Tasks">
|
||||||
<font>
|
<font>
|
||||||
|
@ -111,19 +154,9 @@
|
||||||
</HBox.margin>
|
</HBox.margin>
|
||||||
</TextFlow>
|
</TextFlow>
|
||||||
<Separator prefWidth="200.0" visible="false" HBox.hgrow="ALWAYS" />
|
<Separator prefWidth="200.0" visible="false" HBox.hgrow="ALWAYS" />
|
||||||
<ImageView fx:id="imgTaskList" fitHeight="98.0" fitWidth="200.0" pickOnBounds="true" preserveRatio="true" />
|
<ImageView fx:id="imgTaskList" fitHeight="200.0" fitWidth="400.0" pickOnBounds="true" preserveRatio="true" />
|
||||||
</children>
|
</children>
|
||||||
</HBox>
|
</HBox>
|
||||||
<HBox prefHeight="100.0" prefWidth="200.0">
|
|
||||||
<children>
|
|
||||||
<TextFlow lineSpacing="4.0" prefHeight="200.0" prefWidth="500.0">
|
|
||||||
<children>
|
|
||||||
<Text strokeType="OUTSIDE" strokeWidth="0.0" text="You can also add your own custom tasks, by clicking the "Add Task" button. In the subsequently shown dialog, you can enter the corresponding details. Note: If you want to make a task recurring, you need to set both an interval (in days) AND an end date, so the task won't repeat for all eternity." />
|
|
||||||
</children>
|
|
||||||
</TextFlow>
|
|
||||||
<Separator prefWidth="200.0" visible="false" HBox.hgrow="ALWAYS" />
|
|
||||||
<ImageView fitHeight="150.0" fitWidth="200.0" pickOnBounds="true" preserveRatio="true" />
|
|
||||||
</children></HBox>
|
|
||||||
</children>
|
</children>
|
||||||
<opaqueInsets>
|
<opaqueInsets>
|
||||||
<Insets />
|
<Insets />
|
||||||
|
|
|
@ -52,7 +52,7 @@ public class WeatherGardenTaskPlannerTest {
|
||||||
exampleTask.setNextExecution(LocalDate.now().plusDays(1L));
|
exampleTask.setNextExecution(LocalDate.now().plusDays(1L));
|
||||||
exampleWeatherTask = new Task("Hail",
|
exampleWeatherTask = 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",
|
"During a summer Thunderstorm it could hail heavily. THe Hail could damage the crops. To prevent damage cover the plants with a strong tarpaulin",
|
||||||
LocalDate.now().minusDays(1L),LocalDate.now().plusDays(1L),3L);
|
LocalDate.now(),LocalDate.now().plusDays(1L),3L);
|
||||||
|
|
||||||
taskList = new JsonTaskList(testFile);
|
taskList = new JsonTaskList(testFile);
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,12 @@
|
||||||
package ch.zhaw.gartenverwaltung.io;
|
package ch.zhaw.gartenverwaltung.io;
|
||||||
|
|
||||||
|
import ch.zhaw.gartenverwaltung.models.GardenSchedule;
|
||||||
|
import ch.zhaw.gartenverwaltung.models.PlantNotFoundException;
|
||||||
|
import ch.zhaw.gartenverwaltung.types.Crop;
|
||||||
import ch.zhaw.gartenverwaltung.types.Task;
|
import ch.zhaw.gartenverwaltung.types.Task;
|
||||||
|
import javafx.application.Platform;
|
||||||
import org.junit.jupiter.api.*;
|
import org.junit.jupiter.api.*;
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
import org.mockito.ArgumentMatchers;
|
import org.mockito.ArgumentMatchers;
|
||||||
import org.mockito.Mockito;
|
import org.mockito.Mockito;
|
||||||
|
|
||||||
|
@ -13,6 +18,7 @@ import java.nio.file.Path;
|
||||||
import java.nio.file.StandardCopyOption;
|
import java.nio.file.StandardCopyOption;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
@ -27,6 +33,22 @@ public class JsonTaskListTest {
|
||||||
private final URL dbDataSource = this.getClass().getResource("test-taskdb.json");
|
private final URL dbDataSource = this.getClass().getResource("test-taskdb.json");
|
||||||
private final URL testFile = this.getClass().getResource("template-taskdb.json");
|
private final URL testFile = this.getClass().getResource("template-taskdb.json");
|
||||||
|
|
||||||
|
|
||||||
|
@BeforeAll
|
||||||
|
static void setUpAll() {
|
||||||
|
try{
|
||||||
|
Platform.startup(()->{});
|
||||||
|
}catch (IllegalStateException ise){
|
||||||
|
//ignore double launches
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterAll
|
||||||
|
static void tearDownAll() {
|
||||||
|
//Dont do: Platform.exit();
|
||||||
|
}
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void connectToDb() throws URISyntaxException, IOException {
|
void connectToDb() throws URISyntaxException, IOException {
|
||||||
assertNotNull(testFile);
|
assertNotNull(testFile);
|
||||||
|
@ -35,6 +57,10 @@ public class JsonTaskListTest {
|
||||||
testDatabase = new JsonTaskList(dbDataSource);
|
testDatabase = new JsonTaskList(dbDataSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void reloadDb() {
|
||||||
|
testDatabase = new JsonTaskList(dbDataSource);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("Check if results are retrieved completely")
|
@DisplayName("Check if results are retrieved completely")
|
||||||
void getTasks() {
|
void getTasks() {
|
||||||
|
@ -47,7 +73,8 @@ public class JsonTaskListTest {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
Assertions.assertEquals(3, taskList.size());
|
List<Long> ids = taskList.stream().map(t -> t.getId().orElse(0L)).toList();
|
||||||
|
Assertions.assertEquals(Arrays.asList(1L, 2L, 5L), ids);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,7 +92,8 @@ public class JsonTaskListTest {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
Assertions.assertEquals(4, taskList.size());
|
List<Long> ids = taskList.stream().map(t -> t.getId().orElse(0L)).toList();
|
||||||
|
Assertions.assertEquals(Arrays.asList(1L, 2L, 5L, 9L), ids);
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
|
@ -83,7 +111,8 @@ public class JsonTaskListTest {
|
||||||
taskList = testDatabase.getTaskList(LocalDate.parse("2022-04-30", formatter),
|
taskList = testDatabase.getTaskList(LocalDate.parse("2022-04-30", formatter),
|
||||||
LocalDate.parse("2022-05-31", formatter));
|
LocalDate.parse("2022-05-31", formatter));
|
||||||
|
|
||||||
Assertions.assertEquals(2, taskList.size());
|
List<Long> ids = taskList.stream().map(t -> t.getId().orElse(0L)).toList();
|
||||||
|
Assertions.assertEquals(Arrays.asList(1L, 5L), ids);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
@ -100,8 +129,8 @@ public class JsonTaskListTest {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
Assertions.assertEquals(6, taskList.size());
|
List<Long> ids = taskList.stream().map(t -> t.getId().orElse(0L)).toList();
|
||||||
|
Assertions.assertEquals(Arrays.asList(1L, 2L, 3L, 4L, 5L, 6L), ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -116,10 +145,20 @@ public class JsonTaskListTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
Assertions.assertEquals(0, taskList.size());
|
Assertions.assertEquals(0, taskList.size());
|
||||||
|
|
||||||
|
try {
|
||||||
|
taskList = testDatabase.getTaskForCrop(1);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Long> ids = (taskList.stream().map( task -> task.getId().orElse(0L)).toList());
|
||||||
|
Assertions.assertEquals(Arrays.asList(7L, 8L), ids);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testDefaultConstructor(){
|
void testDefaultConstructor() {
|
||||||
JsonTaskList db = new JsonTaskList();
|
JsonTaskList db = new JsonTaskList();
|
||||||
try {
|
try {
|
||||||
assertNotNull(db.getTaskForCrop(0));
|
assertNotNull(db.getTaskForCrop(0));
|
||||||
|
@ -138,6 +177,43 @@ public class JsonTaskListTest {
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
verify(mockObs, times(1)).onChange(ArgumentMatchers.anyList());
|
|
||||||
|
ArgumentCaptor<List<Task>> captor = ArgumentCaptor.forClass(List.class);
|
||||||
|
|
||||||
|
verify(mockObs, times(1)).onChange(captor.capture());
|
||||||
|
List<Long> ids = captor.getValue().stream().map(t -> t.getId().orElse(0L)).toList();
|
||||||
|
Assertions.assertEquals(Arrays.asList(7L, 8L), ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Tag("IntegrationTest")
|
||||||
|
void testComplete() {
|
||||||
|
JsonPlantList plantList = new JsonPlantList();
|
||||||
|
try {
|
||||||
|
testDatabase.removeTasksForCrop(0);
|
||||||
|
testDatabase.removeTasksForCrop(1);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
GardenSchedule gardenSchedule = null;
|
||||||
|
try {
|
||||||
|
gardenSchedule = new GardenSchedule(testDatabase, plantList);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
Crop crop = new Crop(3L, LocalDate.parse("2022-12-01", formatter));
|
||||||
|
|
||||||
|
try {
|
||||||
|
gardenSchedule.planTasksForCrop(crop);
|
||||||
|
|
||||||
|
reloadDb();
|
||||||
|
|
||||||
|
List<Task> tasks = gardenSchedule.getTaskList();
|
||||||
|
List<String> tasknames = (tasks.stream().map( task -> task.getName().substring(0,3).toLowerCase()).toList());
|
||||||
|
Assertions.assertEquals(Arrays.asList("ger","wat","hil","har"), tasknames);
|
||||||
|
} catch (IOException | PlantNotFoundException | HardinessZoneNotSetException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -34,12 +34,17 @@ class GardenScheduleTest {
|
||||||
|
|
||||||
@BeforeAll
|
@BeforeAll
|
||||||
static void setUpAll() {
|
static void setUpAll() {
|
||||||
|
try{
|
||||||
Platform.startup(()->{});
|
Platform.startup(()->{});
|
||||||
|
}catch (IllegalStateException ise){
|
||||||
|
//ignore double launches
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterAll
|
@AfterAll
|
||||||
static void tearDownAll() {
|
static void tearDownAll() {
|
||||||
Platform.exit();
|
//Dont do: Platform.exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
|
@ -234,5 +239,8 @@ class GardenScheduleTest {
|
||||||
testTaskList.getTaskList(LocalDate.MIN,LocalDate.MAX).get(0);
|
testTaskList.getTaskList(LocalDate.MIN,LocalDate.MAX).get(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testPlantNotFoundException() throws HardinessZoneNotSetException, IOException {
|
||||||
|
assertThrowsExactly(PlantNotFoundException.class, () -> { model.planTasksForCrop(new Crop(0, exampleStartDate)); });
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -64,5 +64,27 @@
|
||||||
"endDate" : "2022-09-01",
|
"endDate" : "2022-09-01",
|
||||||
"interval" : 0,
|
"interval" : 0,
|
||||||
"cropId" : 0
|
"cropId" : 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id" : 7,
|
||||||
|
"name" : "sow plant",
|
||||||
|
"description": "Plant the seeds, crops in de bed.",
|
||||||
|
"startDate" : "2022-11-01",
|
||||||
|
"nextExecution": "2022-11-01",
|
||||||
|
"nextNotification": "2022-11-01",
|
||||||
|
"endDate" : "2022-11-01",
|
||||||
|
"interval" : 0,
|
||||||
|
"cropId" : 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id" : 8,
|
||||||
|
"name" : "harvest plant",
|
||||||
|
"description": "Pull the ripe vegetables out from the soil. Clean them with clear, fresh water. ",
|
||||||
|
"startDate" : "2022-12-01",
|
||||||
|
"nextExecution": "2022-12-01",
|
||||||
|
"nextNotification": "2022-12-01",
|
||||||
|
"endDate" : "2022-12-01",
|
||||||
|
"interval" : 0,
|
||||||
|
"cropId" : 1
|
||||||
}
|
}
|
||||||
]
|
]
|
Loading…
Reference in New Issue