Compare commits

...
Author SHA1 Message Date
gulerdavandGitHub Enterprise 8e3af2ba32 Merge branch 'dev' into feature_taskList_m2 2022-11-18 12:27:33 +01:00
gulerdavandGitHub Enterprise b70a758099 Merge pull request #61 from schrom01/refactor_gui_M3
Refactor gui m3
2022-11-18 12:22:13 +01:00
David Guler 3a69119eb7 refactor: bind croplist in schedule 2022-11-18 12:21:50 +01:00
schrom01 165dc6d901 implemented Method getGrowphaseGroupForDate 2022-11-18 12:21:21 +01:00
schrom01 384dc2d853 completed Tests for GardenScheduleTest 2022-11-18 11:34:53 +01:00
David Guler 2f69c48800 refactor: dedicated loadPaneToDialog function replacing the previous workaround 2022-11-16 20:37:07 +01:00
gulerdavandGitHub Enterprise 86a9eeaf2e Merge pull request #60 from schrom01/refactor_dependency-injection_M3
Refactor: dependency injection M3
2022-11-16 15:30:43 +01:00
David Guler 9ba252b828 refactor: fixed and simplified dayCellFactory even more
Added method to check if a date is within a GrowthPhaseType to plant, thus removing the need for the ugly getMinDate methods and moving knowledge of the phase-internals to the Plant class.

Also removed the need to specify the lifecycle-group to the sowDateFromHarvest method
2022-11-15 22:45:01 +01:00
David Guler 90d2de65de refactor: simplified dayCellFactory for date selector
Instead of generating a list of dates for every single visible date and checking if it is contained in that list, we now use a (admittedly scary-looking) predicate to compare the date to the start and enddates
2022-11-15 15:25:51 +01:00
10 changed files with 182 additions and 120 deletions
@@ -93,8 +93,9 @@ public class CropDetailController {
} }
public void setPlantFromCrop(Crop crop) throws HardinessZoneNotSetException, IOException, PlantNotFoundException { public void setPlantFromCrop(Crop crop) throws PlantNotFoundException {
this.crop = crop; this.crop = crop;
try {
Plant plant = plantList.getPlantById(Settings.getInstance().getCurrentHardinessZone(), crop.getPlantId()) Plant plant = plantList.getPlantById(Settings.getInstance().getCurrentHardinessZone(), crop.getPlantId())
.orElseThrow(PlantNotFoundException::new); .orElseThrow(PlantNotFoundException::new);
@@ -110,6 +111,9 @@ public class CropDetailController {
location_label.setText(""); location_label.setText("");
createTaskLists(crop); createTaskLists(crop);
createPestList(plant); createPestList(plant);
} catch (HardinessZoneNotSetException | IOException e) {
throw new PlantNotFoundException();
}
} }
private void createTaskLists(Crop crop) { private void createTaskLists(Crop crop) {
@@ -90,10 +90,12 @@ public class MyGardenController {
Label label = new Label(plant.name()); Label label = new Label(plant.name());
label.setMaxWidth(2000); label.setMaxWidth(2000);
HBox.setHgrow(label, Priority.ALWAYS); HBox.setHgrow(label, Priority.ALWAYS);
Button details = new Button("Details"); Button details = new Button("Details");
Button delete = new Button("delete"); Button delete = new Button("delete");
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, details, delete);
return hBox; return hBox;
} }
@@ -108,7 +110,7 @@ public class MyGardenController {
stage.initModality(Modality.APPLICATION_MODAL); stage.initModality(Modality.APPLICATION_MODAL);
stage.setResizable(true); stage.setResizable(true);
stage.showAndWait(); stage.showAndWait();
} catch (IOException | HardinessZoneNotSetException | PlantNotFoundException e) { } catch (IOException | PlantNotFoundException e) {
// TODO: show error alert // TODO: show error alert
LOG.log(Level.SEVERE, "Could not load plant details.", e); LOG.log(Level.SEVERE, "Could not load plant details.", e);
} }
@@ -9,9 +9,6 @@ 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.beans.property.ListProperty;
import javafx.beans.property.SimpleListProperty;
import javafx.collections.FXCollections;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.scene.control.Label; import javafx.scene.control.Label;
import javafx.scene.control.ListCell; import javafx.scene.control.ListCell;
@@ -37,8 +34,6 @@ public class MyScheduleController {
@Inject @Inject
private PlantList plantList; private PlantList plantList;
private final ListProperty<Crop> cropListProperty = new SimpleListProperty<>(FXCollections.observableArrayList());
@FXML @FXML
private Label day1_label; private Label day1_label;
@@ -90,15 +85,8 @@ public class MyScheduleController {
@AfterInject @AfterInject
@SuppressWarnings("unused") @SuppressWarnings("unused")
public void init() { public void init() {
List<Crop> cropList;
try {
cropList = garden.getCrops();
cropListProperty.addAll(cropList);
} catch (IOException e) {
e.printStackTrace();
}
setCellFactoryListView(); setCellFactoryListView();
scheduledPlants_listview.itemsProperty().bind(cropListProperty); scheduledPlants_listview.itemsProperty().bind(garden.getPlantedCrops());
lookForSelectedListEntries(); lookForSelectedListEntries();
setDayLabels(); setDayLabels();
information_label.setText(""); information_label.setText("");
@@ -21,7 +21,6 @@ import javafx.scene.image.Image;
import javafx.scene.image.ImageView; import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane; import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.VBox; import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import java.io.IOException; import java.io.IOException;
import java.time.LocalDate; import java.time.LocalDate;
@@ -74,7 +73,6 @@ public class PlantsController {
*/ */
@FXML @FXML
void selectSowDate() throws IOException { void selectSowDate() throws IOException {
Stage stage = new Stage();
Dialog<LocalDate> dateSelection = new Dialog<>(); Dialog<LocalDate> dateSelection = new Dialog<>();
dateSelection.setTitle("Select Date"); dateSelection.setTitle("Select Date");
dateSelection.setHeaderText(String.format("Select Harvest/Sow Date for %s:", selectedPlant.name())); dateSelection.setHeaderText(String.format("Select Harvest/Sow Date for %s:", selectedPlant.name()));
@@ -85,12 +83,10 @@ public class PlantsController {
ButtonType sowButton = new ButtonType("Save", ButtonBar.ButtonData.OK_DONE); ButtonType sowButton = new ButtonType("Save", ButtonBar.ButtonData.OK_DONE);
dialogPane.getButtonTypes().addAll(sowButton, ButtonType.CANCEL); dialogPane.getButtonTypes().addAll(sowButton, ButtonType.CANCEL);
if (appLoader.loadSceneToStage("SelectSowDay.fxml", stage) instanceof SelectSowDayController controller) { if (appLoader.loadPaneToDialog("SelectSowDay.fxml", dialogPane) instanceof SelectSowDayController controller) {
controller.initSaveButton((Button) dialogPane.lookupButton(sowButton)); controller.initSaveButton((Button) dialogPane.lookupButton(sowButton));
controller.setSelectedPlant(selectedPlant); controller.setSelectedPlant(selectedPlant);
dateSelection.setResultConverter(button -> button.equals(sowButton) ? controller.retrieveResult() : null); dateSelection.setResultConverter(button -> button.equals(sowButton) ? controller.retrieveResult() : null);
}
dialogPane.setContent(stage.getScene().getRoot());
dateSelection.showAndWait() dateSelection.showAndWait()
.ifPresent(date -> { .ifPresent(date -> {
@@ -102,6 +98,7 @@ public class PlantsController {
plantsRoot.fireEvent(new ChangeViewEvent(ChangeViewEvent.CHANGE_MAIN_VIEW, "MyGarden.fxml")); plantsRoot.fireEvent(new ChangeViewEvent(ChangeViewEvent.CHANGE_MAIN_VIEW, "MyGarden.fxml"));
}); });
} }
}
/** /**
* fill list view with current hardiness zone * fill list view with current hardiness zone
@@ -7,7 +7,6 @@ import javafx.scene.control.*;
import javafx.util.Callback; import javafx.util.Callback;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.List;
public class SelectSowDayController { public class SelectSowDayController {
private Plant selectedPlant; private Plant selectedPlant;
@@ -17,12 +16,15 @@ public class SelectSowDayController {
@FXML @FXML
private RadioButton harvest_radio; private RadioButton harvest_radio;
@FXML
private RadioButton sow_radio;
@FXML
public ToggleGroup phase_group;
public LocalDate retrieveResult() { public LocalDate retrieveResult() {
LocalDate sowDate = datepicker.getValue(); LocalDate sowDate = datepicker.getValue();
if (harvest_radio.isSelected()) { if (harvest_radio.isSelected()) {
//ToDo method to get current lifecycle group in plant sowDate = selectedPlant.sowDateFromHarvestDate(sowDate);
sowDate = selectedPlant.sowDateFromHarvestDate(datepicker.getValue(), 0);
} }
return sowDate; return sowDate;
} }
@@ -46,6 +48,9 @@ public class SelectSowDayController {
Callback<DatePicker, DateCell> dayCellFactory = getDayCellFactory(); Callback<DatePicker, DateCell> dayCellFactory = getDayCellFactory();
datepicker.setDayCellFactory(dayCellFactory); datepicker.setDayCellFactory(dayCellFactory);
datepicker.setEditable(false); datepicker.setEditable(false);
sow_radio.setUserData(GrowthPhaseType.SOW);
harvest_radio.setUserData(GrowthPhaseType.HARVEST);
} }
public void initSaveButton(Button saveButton) { public void initSaveButton(Button saveButton) {
@@ -61,35 +66,28 @@ public class SelectSowDayController {
/** /**
* date picker disable/enable dates according to selected plant: sow or harvest day * date picker disable/enable dates according to selected plant: sow or harvest day
*
* @return cellFactory of datePicker * @return cellFactory of datePicker
*/ */
private Callback<DatePicker, DateCell> getDayCellFactory() { private Callback<DatePicker, DateCell> getDayCellFactory() {
return (datePicker) -> new DateCell() { return (datePicker) -> new DateCell() {
private final LocalDate today = LocalDate.now();
@Override @Override
public void updateItem(LocalDate item, boolean empty) { public void updateItem(LocalDate item, boolean empty) {
super.updateItem(item, empty); super.updateItem(item, empty);
setDisable(true); setDisable(true);
setStyle("-fx-background-color: #ffc0cb;"); setStyle("-fx-background-color: #ffc0cb;");
List<LocalDate> dates;
LocalDate today = LocalDate.now(); if (item.compareTo(today) > 0 && (!harvest_radio.isSelected() || selectedPlant.sowDateFromHarvestDate(item).compareTo(today) >= 0)) {
if (harvest_radio.isSelected()) { GrowthPhaseType selectedPhase = (GrowthPhaseType) phase_group.getSelectedToggle().getUserData();
dates = selectedPlant.getDateListOfGrowthPhase(GrowthPhaseType.HARVEST);
} else { if (selectedPlant.isDateInPhase(item, selectedPhase)) {
dates = selectedPlant.getDateListOfGrowthPhase(GrowthPhaseType.SOW);
}
for (LocalDate date : dates) {
if (item.getMonth() == date.getMonth()
&& item.getDayOfMonth() == date.getDayOfMonth()
&& item.compareTo(today) > 0) {
setDisable(false); setDisable(false);
setStyle("-fx-background-color: #32CD32;"); setStyle("-fx-background-color: #32CD32;");
} }
} }
if ((harvest_radio.isSelected() && selectedPlant.sowDateFromHarvestDate(item, 0).compareTo(today) < 0)) {
setDisable(true);
setStyle("-fx-background-color: #ffc0cb;");
}
} }
}; };
} }
@@ -12,6 +12,7 @@ import ch.zhaw.gartenverwaltung.models.GardenSchedule;
import ch.zhaw.gartenverwaltung.models.PlantListModel; import ch.zhaw.gartenverwaltung.models.PlantListModel;
import javafx.fxml.FXMLLoader; import javafx.fxml.FXMLLoader;
import javafx.scene.Scene; import javafx.scene.Scene;
import javafx.scene.control.DialogPane;
import javafx.scene.layout.Pane; import javafx.scene.layout.Pane;
import javafx.stage.Stage; import javafx.stage.Stage;
@@ -78,6 +79,24 @@ public class AppLoader {
return controller; return controller;
} }
/**
* Loads the given fxml-file from resources (no caching) and appendeds it's
* contents to the given {@link DialogPane}.
* Performs dependency-injection.
*
* @param fxmlFile The file name to be loaded
* @param appendee The {@link DialogPane} to which the FXML contents are to be appended.
* @return The controller of the loaded scene.
* @throws IOException if the file could not be loaded
*/
public Object loadPaneToDialog(String fxmlFile, DialogPane appendee) throws IOException {
FXMLLoader loader = new FXMLLoader(Objects.requireNonNull(HelloApplication.class.getResource(fxmlFile)));
appendee.setContent(loader.load());
Object controller = loader.getController();
annotationInject(controller);
return controller;
}
/** /**
* Loads the given fxml-file from resources and caches the pane. * Loads the given fxml-file from resources and caches the pane.
* Performs dependency-injection. * Performs dependency-injection.
@@ -46,7 +46,8 @@ public class GardenSchedule {
*/ */
public void planTasksForCrop(Crop crop) throws PlantNotFoundException, HardinessZoneNotSetException, IOException { public void planTasksForCrop(Crop crop) throws PlantNotFoundException, HardinessZoneNotSetException, IOException {
Plant plant = plantList.getPlantById(Settings.getInstance().getCurrentHardinessZone(), crop.getPlantId()).orElseThrow(PlantNotFoundException::new); Plant plant = plantList.getPlantById(Settings.getInstance().getCurrentHardinessZone(), crop.getPlantId()).orElseThrow(PlantNotFoundException::new);
for (GrowthPhase growthPhase : plant.lifecycle()) { int growPhaseGroup = plant.getGrowphaseGroupForDate(crop.getStartDate());
for (GrowthPhase growthPhase : plant.lifecycleForGroup(growPhaseGroup)) {
for (TaskTemplate taskTemplate : growthPhase.taskTemplates()) { for (TaskTemplate taskTemplate : growthPhase.taskTemplates()) {
addTask(taskTemplate.generateTask(crop.getStartDate(), crop.getCropId().orElse(0L))); addTask(taskTemplate.generateTask(crop.getStartDate(), crop.getCropId().orElse(0L)));
} }
@@ -3,7 +3,7 @@ package ch.zhaw.gartenverwaltung.types;
import javafx.scene.image.Image; import javafx.scene.image.Image;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.LinkedList; import java.time.MonthDay;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@@ -39,14 +39,23 @@ public record Plant(
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
public int getGrowphaseGroupForDate(LocalDate date) {
for(GrowthPhase growthPhase : lifecycle){
MonthDay plantingDate = MonthDay.of(date.getMonth().getValue(), date.getDayOfMonth());
if(plantingDate.isAfter(growthPhase.startDate()) && plantingDate.isBefore(growthPhase.endDate())){
return growthPhase.group();
}
}
return 0; // TODO implement
}
/** /**
* get sow date from given harvest day from lifecycle group * get sow date from given harvest day from lifecycle group
* @param harvestDate date of the harvest * @param harvestDate date of the harvest
* @param group lifecycle group
* @return LocaleDate of sow date * @return LocaleDate of sow date
*/ */
public LocalDate sowDateFromHarvestDate(LocalDate harvestDate, int group) { public LocalDate sowDateFromHarvestDate(LocalDate harvestDate) {
return harvestDate.minusDays(timeToHarvest(group)); return harvestDate.minusDays(timeToHarvest(lifecycleGroupFromHarvestDate(harvestDate)));
} }
/** /**
@@ -69,37 +78,43 @@ public record Plant(
return (int) DAYS.between(harvest.startDate().atYear(currentYear), sow.startDate().atYear(currentYear)); return (int) DAYS.between(harvest.startDate().atYear(currentYear), sow.startDate().atYear(currentYear));
} }
/** public int lifecycleGroupFromHarvestDate(LocalDate harvestDate) {
* filter out the given growthPhase out of the lifecycle return lifecycle.stream()
* create list of dates for this growthPhase and return it .filter(growthPhase -> growthPhase.type().equals(GrowthPhaseType.HARVEST) &&
* @param growthPhase the wanted growthPhase dateInRange(harvestDate, growthPhase.startDate(), growthPhase.endDate()))
* @return a list of dates of the current year .map(GrowthPhase::group)
*/ .findFirst()
public List<LocalDate> getDateListOfGrowthPhase(GrowthPhaseType growthPhase) { .orElse(0);
List<LocalDate> dates = new LinkedList<>();
for (GrowthPhase growth : lifecycle) {
if (growth.type().equals(growthPhase)) {
dates = addDatesFromMonthDay(growth);
}
}
return dates;
} }
/** /**
* transform monthDay value of the given growthPhase to localDate * Checks if the given {@link LocalDate} is within a {@link GrowthPhase} of the given {@link GrowthPhaseType}
* return a list of dates from start to end of growth phase *
* @param growthPhase the current growthPhase * @param date The date to check.
* @return a list of dates of the current year * @param phase The {@link GrowthPhaseType} to match against
* @return Whether the date is within the given {@link GrowthPhaseType}
*/ */
private List<LocalDate> addDatesFromMonthDay(GrowthPhase growthPhase) { public boolean isDateInPhase(LocalDate date, GrowthPhaseType phase) {
List<LocalDate> dates = new LinkedList<>(); return lifecycle.stream()
LocalDate today = LocalDate.now(); .filter(growthPhase -> growthPhase.type().equals(phase))
LocalDate start = growthPhase.startDate().atYear(today.getYear()); .anyMatch(growthPhase -> dateInRange(date, growthPhase.startDate(), growthPhase.endDate()));
LocalDate end = growthPhase.endDate().atYear(today.getYear());
while (!start.isAfter(end)) {
dates.add(start);
start = start.plusDays(1);
} }
return dates;
/**
* Checks if the given {@link LocalDate} is within the given {@link MonthDay} range.
* (regardless of year)
*
* @param subject The date to check
* @param min The start of the date-range
* @param max The end of the date-range
* @return Whether the subject is within the range.
*/
private boolean dateInRange(LocalDate subject, MonthDay min, MonthDay max) {
return subject.getMonth().compareTo(min.getMonth()) >= 0 &&
subject.getMonth().compareTo(max.getMonth()) <= 0 &&
// if the day is less than the minimum day, the minimum month must not be equal
(subject.getDayOfMonth() >= min.getDayOfMonth() || !subject.getMonth().equals(min.getMonth())) &&
// if the day is greater than the maximum day, the maximum month must not be equal
(subject.getDayOfMonth() <= max.getDayOfMonth() || !subject.getMonth().equals(max.getMonth()));
} }
} }
@@ -18,15 +18,15 @@
<children> <children>
<VBox alignment="CENTER_LEFT" prefHeight="88.0" prefWidth="155.0"> <VBox alignment="CENTER_LEFT" prefHeight="88.0" prefWidth="155.0">
<children> <children>
<RadioButton fx:id="sow_radio" mnemonicParsing="false" selected="true" text="Sow" toggleGroup="$group"> <RadioButton fx:id="sow_radio" mnemonicParsing="false" selected="true" text="Sow" toggleGroup="$phase_group">
<VBox.margin> <VBox.margin>
<Insets bottom="10.0" /> <Insets bottom="10.0" />
</VBox.margin> </VBox.margin>
<toggleGroup> <toggleGroup>
<ToggleGroup fx:id="group" /> <ToggleGroup fx:id="phase_group" />
</toggleGroup> </toggleGroup>
</RadioButton> </RadioButton>
<RadioButton fx:id="harvest_radio" mnemonicParsing="false" text="Harvest" toggleGroup="$group" /> <RadioButton fx:id="harvest_radio" mnemonicParsing="false" text="Harvest" toggleGroup="$phase_group" />
</children> </children>
<HBox.margin> <HBox.margin>
<Insets top="10.0" /> <Insets top="10.0" />
@@ -1,35 +1,45 @@
package ch.zhaw.gartenverwaltung.taskList; package ch.zhaw.gartenverwaltung.models;
import ch.zhaw.gartenverwaltung.io.*; import ch.zhaw.gartenverwaltung.io.*;
import ch.zhaw.gartenverwaltung.models.GardenSchedule; import ch.zhaw.gartenverwaltung.models.GardenSchedule;
import ch.zhaw.gartenverwaltung.types.HardinessZone; import ch.zhaw.gartenverwaltung.types.*;
import ch.zhaw.gartenverwaltung.types.Plant;
import ch.zhaw.gartenverwaltung.types.Task;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import java.io.IOException; import java.io.IOException;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.MonthDay;
import java.util.*; import java.util.*;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*; import static org.mockito.Mockito.*;
class GardenScheduleTest { class GardenScheduleTest {
LocalDate exampleStartDate = LocalDate.of(2020, 02, 02);
TaskList taskList; TaskList taskList;
PlantList plantList; PlantList plantList;
List<Plant> examplePlantList;
List<Task> exampleTaskList; List<Task> exampleTaskList;
Map<Long, Plant> examplePlantMap; List<TaskTemplate> exampleTaskTemplateList;
GardenSchedule model; GardenSchedule model;
@BeforeEach @BeforeEach
void setUp() throws IOException { void setUp() throws IOException, HardinessZoneNotSetException {
createExampleTaskList(); createExampleTaskList();
createExampleTaskTemplateList();
createExamplePlantList();
taskList = mockTaskDatabase(exampleTaskList); taskList = mockTaskDatabase(exampleTaskList);
plantList = mockPlantDatabase(examplePlantMap); plantList = mockPlantDatabase(examplePlantList);
model = new GardenSchedule(taskList, plantList); model = new GardenSchedule(taskList, plantList);
} }
PlantList mockPlantDatabase(List<Plant> plantList) throws HardinessZoneNotSetException, IOException {
PlantList plantDatabase = mock(JsonPlantList.class);
when(plantDatabase.getPlantList(HardinessZone.ZONE_8A)).thenReturn(plantList);
when(plantDatabase.getPlantById(HardinessZone.ZONE_8A,20)).thenReturn(Optional.of(examplePlantList.get(0)));
return plantDatabase;
}
private TaskList mockTaskDatabase(List<Task> exampleTaskList) throws IOException { private TaskList mockTaskDatabase(List<Task> exampleTaskList) throws IOException {
TaskList taskList = mock(JsonTaskList.class); TaskList taskList = mock(JsonTaskList.class);
when(taskList.getTaskList(LocalDate.MIN, LocalDate.MAX)).thenReturn(exampleTaskList); when(taskList.getTaskList(LocalDate.MIN, LocalDate.MAX)).thenReturn(exampleTaskList);
@@ -54,18 +64,39 @@ class GardenScheduleTest {
return taskList; return taskList;
} }
private PlantList mockPlantDatabase(Map<Long, Plant> examplePlantMap) { void createExampleTaskTemplateList(){
return new PlantList() { exampleTaskTemplateList = new ArrayList<>();
@Override exampleTaskTemplateList.add(mock(TaskTemplate.class));
public List<Plant> getPlantList(HardinessZone zone) { exampleTaskTemplateList.add(mock(TaskTemplate.class));
return null; exampleTaskTemplateList.add(mock(TaskTemplate.class));
exampleTaskTemplateList.add(mock(TaskTemplate.class));
when(exampleTaskTemplateList.get(0).generateTask(exampleStartDate, 30)).thenReturn(exampleTaskList.get(0));
when(exampleTaskTemplateList.get(1).generateTask(exampleStartDate, 30)).thenReturn(exampleTaskList.get(1));
when(exampleTaskTemplateList.get(2).generateTask(exampleStartDate, 30)).thenReturn(exampleTaskList.get(2));
when(exampleTaskTemplateList.get(3).generateTask(exampleStartDate, 30)).thenReturn(exampleTaskList.get(3));
} }
@Override void createExamplePlantList(){
public Optional<Plant> getPlantById(HardinessZone zone, long id) { examplePlantList = new ArrayList<>();
return Optional.ofNullable(examplePlantMap.get(id)); examplePlantList.add(new Plant(
} 20,
}; "summertime onion",
"Onion, (Allium cepa), herbaceous biennial plant in the amaryllis family (Amaryllidaceae) grown for its edible bulb. The onion is likely native to southwestern Asia but is now grown throughout the world, chiefly in the temperate zones. Onions are low in nutrients but are valued for their flavour and are used widely in cooking. They add flavour to such dishes as stews, roasts, soups, and salads and are also served as a cooked vegetable.",
null,
"15,30,2",
0,
"sandy to loamy, loose soil, free of stones",
new ArrayList<>(),
List.of(
new GrowthPhase(MonthDay.of(6, 4), MonthDay.of(12, 4), 0, new WateringCycle(0, 0, null), GrowthPhaseType.HARVEST, HardinessZone.ZONE_8A, List.of(
exampleTaskTemplateList.get(0),
exampleTaskTemplateList.get(1)
)),
new GrowthPhase(MonthDay.of(4, 3), MonthDay.of(12, 4), 0, new WateringCycle(0, 0, null), GrowthPhaseType.PLANT, HardinessZone.ZONE_8A, List.of(
exampleTaskTemplateList.get(2),
exampleTaskTemplateList.get(3)
))
)));
} }
void createExampleTaskList() { void createExampleTaskList() {
@@ -77,12 +108,6 @@ class GardenScheduleTest {
exampleTaskList.add(new Task("name", "description", LocalDate.of(2019, 5, 5), 2L)); exampleTaskList.add(new Task("name", "description", LocalDate.of(2019, 5, 5), 2L));
} }
void createExamplePlantMap() {
examplePlantMap = new HashMap<>();
}
@Test @Test
void addTask() throws IOException { void addTask() throws IOException {
Task taskToAdd = new Task("name", "description", LocalDate.now(), 1L); Task taskToAdd = new Task("name", "description", LocalDate.now(), 1L);
@@ -156,4 +181,17 @@ class GardenScheduleTest {
model.removeTasksForCrop(1L); model.removeTasksForCrop(1L);
verify(taskList, times(1)).removeTasksForCrop(1L); verify(taskList, times(1)).removeTasksForCrop(1L);
} }
@Test
void planTasksForCrop() throws HardinessZoneNotSetException, PlantNotFoundException, IOException {
model.planTasksForCrop(new Crop(20, exampleStartDate).withId(30));
verify(exampleTaskTemplateList.get(0), times(1)).generateTask(exampleStartDate, 30);
verify(exampleTaskTemplateList.get(1), times(1)).generateTask(exampleStartDate, 30);
verify(exampleTaskTemplateList.get(2), times(1)).generateTask(exampleStartDate, 30);
verify(exampleTaskTemplateList.get(3), times(1)).generateTask(exampleStartDate, 30);
verify(taskList, times(1)).saveTask(exampleTaskList.get(0));
verify(taskList, times(1)).saveTask(exampleTaskList.get(1));
verify(taskList, times(1)).saveTask(exampleTaskList.get(2));
verify(taskList, times(1)).saveTask(exampleTaskList.get(3));
}
} }