Compare commits

..

No commits in common. "0e40bc63041fa8ea17902c516e5127a0ad23d8e7" and "ea4a1ecc6a893c0322b8b7c2f43aa8f092eb3699" have entirely different histories.

28 changed files with 137 additions and 1661 deletions

View File

@ -1,19 +0,0 @@
package ch.zhaw.gartenverwaltung;
import ch.zhaw.gartenverwaltung.types.HardinessZone;
public class Config {
private static HardinessZone currentHardinessZone;
static {
currentHardinessZone = HardinessZone.ZONE_8A;
}
public static HardinessZone getCurrentHardinessZone() {
return currentHardinessZone;
}
public static void setCurrentHardinessZone(HardinessZone currentHardinessZone) {
Config.currentHardinessZone = currentHardinessZone;
}
}

View File

@ -1,7 +1,5 @@
package ch.zhaw.gartenverwaltung;
import ch.zhaw.gartenverwaltung.types.Crop;
import ch.zhaw.gartenverwaltung.types.Plant;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
@ -9,8 +7,6 @@ import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
public class CropDetailController {
private Crop crop = null;
private Plant plant = null;
@FXML
private Button area_button;
@ -25,10 +21,10 @@ public class CropDetailController {
private Label description_label;
@FXML
private VBox growthPhases_vbox;
private VBox growthPahses_vbox;
@FXML
private Label location_label;
private Label lacation_label;
@FXML
private Label light_label;
@ -65,8 +61,4 @@ public class CropDetailController {
}
public void setPlantFromCrop(Crop crop) {
this.crop = crop;
this.plant = null;
}
}

View File

@ -1,39 +1,30 @@
package ch.zhaw.gartenverwaltung;
import ch.zhaw.gartenverwaltung.gardenplan.Gardenplanmodel;
import ch.zhaw.gartenverwaltung.taskList.TaskListModel;
import ch.zhaw.gartenverwaltung.types.Crop;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Modality;
import javafx.stage.Stage;
import java.io.IOException;
import java.net.URL;
import java.util.*;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.ResourceBundle;
public class MyPlantsController implements Initializable {
MainFXMLController mainController;
private final TaskListModel taskListModel = new TaskListModel();
private final Gardenplanmodel gardenplanmodel = new Gardenplanmodel(taskListModel);
@FXML
private VBox myPlants_vbox;
public MyPlantsController() throws IOException {
}
@FXML
void addPlant(ActionEvent event) throws IOException {
mainController.loadPane("Plants.fxml");
@ -41,21 +32,12 @@ public class MyPlantsController implements Initializable {
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
loadCropList();
}
private void loadCropList() {
List<Crop> cropList = new LinkedList<>();
try {
cropList = getCropList();
} catch (IOException e) {
e.printStackTrace();
}
//ToDo
List<Crop> cropList = getCropList();
createPlantView(cropList);
}
private void createPlantView(List<Crop> crops) {
myPlants_vbox.getChildren().clear();
for(Crop crop : crops) {
HBox hBox = createPlantView(crop);
myPlants_vbox.getChildren().add(hBox);
@ -66,15 +48,15 @@ public class MyPlantsController implements Initializable {
mainController = controller;
}
private List<Crop> getCropList() throws IOException {
List<Crop> cropList;
cropList = gardenplanmodel.getCrops();
private List<Crop> getCropList() {
//ToDo method to get cropList
//Method to get Crop List
List<Crop> cropList = new LinkedList<>();
return cropList;
}
private HBox createPlantView(Crop crop) {
//ToDo add good design
//ToDo get plant information from crop
//ToDo add dynamic design
HBox hBox = new HBox();
Label label = new Label("Placeholder");
Button details = new Button("Details");
@ -89,17 +71,9 @@ public class MyPlantsController implements Initializable {
EventHandler<ActionEvent> event = new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
Parent root;
FXMLLoader fxmlLoader = new FXMLLoader(Objects.requireNonNull(getClass().getResource("CropDetail.fxml")));
//ToDo uncomment when new FXML exists
try {
root = fxmlLoader.load();
CropDetailController controller = fxmlLoader.getController();
controller.setPlantFromCrop(crop);
Stage stage = new Stage();
stage.setScene(new Scene(root));
stage.initModality(Modality.APPLICATION_MODAL);
stage.setResizable(true);
stage.showAndWait();
mainController.loadPane("CropDetail.fxml");
} catch (IOException e) {
e.printStackTrace();
}
@ -112,17 +86,13 @@ public class MyPlantsController implements Initializable {
EventHandler<ActionEvent> event = new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
try {
showConfirmation(crop);
} catch (IOException e) {
e.printStackTrace();
}
showConfirmation(crop);
}
};
return event;
}
private void showConfirmation(Crop crop) throws IOException {
private void showConfirmation(Crop crop) {
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
alert.setTitle("Delete Crop");
alert.setHeaderText("Are you sure want to delete this Crop?");
@ -131,10 +101,7 @@ public class MyPlantsController implements Initializable {
Optional<ButtonType> option = alert.showAndWait();
if (option.get() == ButtonType.OK) {
//ToDo uncomment, when error from JsonTaskDatabase.java loadTaskListFromFile() is fixed.
//gardenplanmodel.removeCrop(crop);
loadCropList();
System.out.println("Delete Crop");
//ToDo Method to remove crop
}
}
}

View File

@ -1,7 +1,5 @@
package ch.zhaw.gartenverwaltung;
import ch.zhaw.gartenverwaltung.gardenplan.Gardenplanmodel;
import ch.zhaw.gartenverwaltung.taskList.TaskListModel;
import ch.zhaw.gartenverwaltung.types.Crop;
import ch.zhaw.gartenverwaltung.types.Task;
import javafx.beans.property.ListProperty;
@ -17,7 +15,6 @@ import javafx.scene.control.ListView;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import java.io.IOException;
import java.net.URL;
import java.time.LocalDate;
import java.util.LinkedList;
@ -26,8 +23,6 @@ import java.util.ResourceBundle;
public class MyScheduleController implements Initializable {
private Crop selectedCrop = null;
private final TaskListModel taskListModel = new TaskListModel();
private final Gardenplanmodel gardenplanmodel = new Gardenplanmodel(taskListModel);
private final ListProperty<Crop> cropListProperty = new SimpleListProperty<>(FXCollections.observableArrayList());
@ -79,29 +74,16 @@ public class MyScheduleController implements Initializable {
@FXML
private ListView<Crop> scheduledPlants_listview;
public MyScheduleController() throws IOException {
}
@Override
public void initialize(URL location, ResourceBundle resources) {
//ToDo method to load crop list
List<Crop> cropList;
try {
cropList = gardenplanmodel.getCrops();
cropListProperty.addAll(cropList);
} catch (IOException e) {
e.printStackTrace();
}
List<Crop> cropList = new LinkedList<>();
setCellFactoryListView();
scheduledPlants_listview.itemsProperty().bind(cropListProperty);
lookForSelectedListEntries();
setDayLabels();
information_label.setText("");
try {
loadTaskList();
} catch (IOException e) {
e.printStackTrace();
}
loadTaskList();
}
private void lookForSelectedListEntries() {
@ -109,11 +91,7 @@ public class MyScheduleController implements Initializable {
@Override
public void changed(ObservableValue<? extends Crop> observable, Crop oldValue, Crop newValue) {
selectedCrop = newValue;
try {
loadTaskList();
} catch (IOException e) {
e.printStackTrace();
}
loadTaskList();
}
});
}
@ -144,13 +122,13 @@ public class MyScheduleController implements Initializable {
});
}
private void loadTaskList() throws IOException {
private void loadTaskList() {
//ToDo load task list according to selectedCrop
List<List<Task>> taskLists = new LinkedList<>();
//ToDo uncomment, when error from JsonTaskDatabase.java loadTaskListFromFile() is fixed.
if (selectedCrop != null) {
//taskLists = taskListModel.getTasksUpcomingWeekForCrop(selectedCrop.getCropId().get());
} else {
//taskLists = taskListModel.getTasksUpcomingWeek();
}
if (!taskLists.isEmpty()) {
viewTaskListOfDay(day1_pane, taskLists.get(0));

View File

@ -5,6 +5,7 @@ import ch.zhaw.gartenverwaltung.plantList.PlantListModel;
import ch.zhaw.gartenverwaltung.types.HardinessZone;
import ch.zhaw.gartenverwaltung.types.Plant;
import ch.zhaw.gartenverwaltung.types.Seasons;
import javafx.application.Platform;
import javafx.beans.property.ListProperty;
import javafx.beans.property.SimpleListProperty;
import javafx.beans.value.ChangeListener;
@ -12,22 +13,18 @@ import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.geometry.Insets;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.geometry.Bounds;
import javafx.scene.control.*;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.VBox;
import javafx.stage.Modality;
import javafx.stage.Stage;
import java.io.IOException;
import java.net.URL;
import java.util.List;
import java.util.Objects;
import java.util.ResourceBundle;
public class PlantsController implements Initializable {
@ -36,6 +33,7 @@ public class PlantsController implements Initializable {
private final HardinessZone DEFAULT_HARDINESS_ZONE = HardinessZone.ZONE_8A;
// TODO: move to model
private final ListProperty<Plant> plantListProperty = new SimpleListProperty<>(FXCollections.observableArrayList());
@FXML
@ -54,27 +52,18 @@ public class PlantsController implements Initializable {
private ListView<Plant> list_plants;
@FXML
private Button selectSowDay_button;
private Button saveToMyPlant_button;
@FXML
private TextField search_plants;
/**
* open new window to select sow or harvest day to save the crop
* saves the current selected plant in new JSON database
* @param event event
*/
@FXML
void selectSowDate(ActionEvent event) throws IOException {
Parent root;
FXMLLoader fxmlLoader = new FXMLLoader(Objects.requireNonNull(getClass().getResource("SelectSowDay.fxml")));
root = fxmlLoader.load();
SelectSowDayController controller = fxmlLoader.getController();
controller.getSelectedPlant(selectedPlant);
Stage stage = new Stage();
stage.setScene(new Scene(root));
stage.initModality(Modality.APPLICATION_MODAL);
stage.setResizable(false);
stage.showAndWait();
void saveToMyPlant(ActionEvent event) {
//ToDo model save selectedPlant to mySelectedPlant(IO)
}
/**
@ -91,7 +80,7 @@ public class PlantsController implements Initializable {
list_plants.itemsProperty().bind(plantListProperty);
description_plant.setText("");
selectSowDay_button.setDisable(true);
saveToMyPlant_button.setDisable(true);
createFilterSeasons();
createFilterHardinessZone();
@ -201,7 +190,7 @@ public class PlantsController implements Initializable {
private void createFilterSeasons() {
ToggleGroup seasonGroup = new ToggleGroup();
for (Seasons season : Seasons.values()) {
RadioButton radioButton = new RadioButton(season.getName());
RadioButton radioButton = new RadioButton(season.name());
radioButton.setToggleGroup(seasonGroup);
radioButton.setPadding(new Insets(0,0,10,0));
if (season.equals(Seasons.AllSEASONS)) {
@ -232,18 +221,13 @@ public class PlantsController implements Initializable {
* image of the plant
*/
private void lookForSelectedListEntry() {
selectedPlant = null;
description_plant.setText("");
selectSowDay_button.setDisable(true);
Image img = new Image(String.valueOf(PlantsController.class.getResource("placeholder.png")));
img_plant.setImage(img);
list_plants.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Plant>() {
@Override
public void changed(ObservableValue<? extends Plant> observable, Plant oldValue, Plant newValue) {
if(newValue != null) {
selectedPlant = newValue;
description_plant.setText(selectedPlant.description());
selectSowDay_button.setDisable(false);
saveToMyPlant_button.setDisable(false);
Image img;
if(selectedPlant.image() != null) {
img = selectedPlant.image();
@ -251,10 +235,12 @@ public class PlantsController implements Initializable {
img = new Image(String.valueOf(PlantsController.class.getResource("placeholder.png")));
}
img_plant.setImage(img);
} else {
selectedPlant = null;
description_plant.setText("");
selectSowDay_button.setDisable(true);
saveToMyPlant_button.setDisable(true);
Image img = new Image(String.valueOf(PlantsController.class.getResource("placeholder.png")));
img_plant.setImage(img);
}

View File

@ -1,175 +0,0 @@
package ch.zhaw.gartenverwaltung;
import ch.zhaw.gartenverwaltung.gardenplan.Gardenplanmodel;
import ch.zhaw.gartenverwaltung.io.HardinessZoneNotSetException;
import ch.zhaw.gartenverwaltung.taskList.PlantNotFoundException;
import ch.zhaw.gartenverwaltung.taskList.TaskListModel;
import ch.zhaw.gartenverwaltung.types.GrowthPhaseType;
import ch.zhaw.gartenverwaltung.types.Plant;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.*;
import javafx.stage.Stage;
import javafx.util.Callback;
import java.io.IOException;
import java.net.URL;
import java.time.LocalDate;
import java.util.List;
import java.util.ResourceBundle;
public class SelectSowDayController implements Initializable {
private Plant selectedPlant = null;
private final TaskListModel taskListModel = new TaskListModel();
private final Gardenplanmodel gardenplanmodel = new Gardenplanmodel(taskListModel);
@FXML
private DatePicker datepicker;
@FXML
private Label popup_label;
@FXML
private Button save_button;
@FXML
private RadioButton sow_radio;
public SelectSowDayController() throws IOException {}
/**
* close the date selector window
* @param event event
*/
@FXML
void cancel(ActionEvent event) {
closeWindow();
}
/**
* get sow date from datePicker or calculate sow date from harvest date
* save selected plant and sow date
* @param event event
*/
@FXML
void save(ActionEvent event) throws HardinessZoneNotSetException, IOException, PlantNotFoundException {
LocalDate sowDate;
if (sow_radio.isSelected()) {
sowDate = datepicker.getValue();
} else {
//ToDo method to get current lifecycle group in plant
sowDate = selectedPlant.sowDateFromHarvestDate(datepicker.getValue(), 0);
}
//ToDo uncomment, when error from JsonTaskDatabase.java loadTaskListFromFile() is fixed.
//gardenplanmodel.plantAsCrop(selectedPlant, sowDate);
closeWindow();
}
/**
* save the plant which will be planted and update label
* @param plant Plant
*/
public void getSelectedPlant(Plant plant) {
selectedPlant = plant;
popup_label.setText("Select Harvest/Sow Date for" + selectedPlant.name());
}
/**
* add listener and set default values
* {@inheritDoc}
* @param location location
* @param resources resources
*/
@Override
public void initialize(URL location, ResourceBundle resources) {
clearDatePickerEntries();
Callback<DatePicker, DateCell> dayCellFactory= getDayCellFactory();
datepicker.setDayCellFactory(dayCellFactory);
datepicker.getEditor().setEditable(false);
enableDisableSaveButton();
}
/**
* clear date picker editor when radio button is changed
*/
private void clearDatePickerEntries() {
sow_radio.selectedProperty().addListener(new ChangeListener<Boolean>() {
@Override
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean isNowSelected) {
datepicker.getEditor().clear();
}
});
}
/**
* date picker disable/enable dates according to selected plant: sow or harvest day
* @return cellFactory of datePicker
*/
private Callback<DatePicker, DateCell> getDayCellFactory() {
final Callback<DatePicker, DateCell> dayCellFactory = new Callback<DatePicker, DateCell>() {
@Override
public DateCell call(final DatePicker datePicker) {
return new DateCell() {
@Override
public void updateItem(LocalDate item, boolean empty) {
super.updateItem(item, empty);
setDisable(true);
setStyle("-fx-background-color: #ffc0cb;");
List<LocalDate> dates;
LocalDate today = LocalDate.now();
if (sow_radio.isSelected()) {
dates = selectedPlant.getDateListOfGrowthPhase(GrowthPhaseType.SOW);
} else {
dates = selectedPlant.getDateListOfGrowthPhase(GrowthPhaseType.HARVEST);
}
for (LocalDate date : dates) {
if (item.getMonth() == date.getMonth()
&& item.getDayOfMonth() == date.getDayOfMonth()
&& item.compareTo(today) > 0) {
setDisable(false);
setStyle("-fx-background-color: #32CD32;");
}
}
if ((!sow_radio.isSelected() && selectedPlant.sowDateFromHarvestDate(item, 0).compareTo(today) < 0)) {
setDisable(true);
setStyle("-fx-background-color: #ffc0cb;");
}
}
};
}
};
return dayCellFactory;
}
/**
* close date picker window
*/
private void closeWindow() {
Stage stage = (Stage) save_button.getScene().getWindow();
stage.close();
}
/**
* disable save button, when there is no date selected in date picker
*/
private void enableDisableSaveButton() {
save_button.setDisable(true);
datepicker.getEditor().textProperty().addListener(new ChangeListener<String>() {
@Override
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
if (newValue == null || newValue.equals("")) {
save_button.setDisable(true);
} else {
save_button.setDisable(false);
}
}
});
}
}

View File

@ -1,92 +1,8 @@
package ch.zhaw.gartenverwaltung.gardenplan;
import ch.zhaw.gartenverwaltung.io.GardenPlan;
import ch.zhaw.gartenverwaltung.io.HardinessZoneNotSetException;
import ch.zhaw.gartenverwaltung.io.JsonGardenPlan;
import ch.zhaw.gartenverwaltung.taskList.PlantNotFoundException;
import ch.zhaw.gartenverwaltung.taskList.TaskListModel;
import ch.zhaw.gartenverwaltung.types.Crop;
import ch.zhaw.gartenverwaltung.types.Plant;
import ch.zhaw.gartenverwaltung.types.Task;
import java.io.IOException;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.Supplier;
/**
* The Gardenplan model manages the crops in the gardenplan.
*/
public class Gardenplanmodel {
private GardenPlan gardenPlan;
private List<Crop> cropList;
private TaskListModel taskListModel;
private Object IllegalArgumentException;
/**
* Constructor of Gardenplan model
*
* @param taskListModel holds a reference to the task list object.
*/
public Gardenplanmodel(TaskListModel taskListModel) throws IOException {
this.taskListModel = taskListModel;
gardenPlan = new JsonGardenPlan();
cropList = new ArrayList<>();
cropList = gardenPlan.getCrops();
}
/**
* Creates a Crop with a {@link Plant} and the planting date of the plant. Then let the Tasklistmodel create the
* gardening {@link Task} for the crop. Store the crop in the gardenplan file and the cache.
*
* @param plant The plant which is wnated to be planted
* @param plantingDate The date, when the plant is planted
* @throws IOException If the database cannot be accessed
* @throws HardinessZoneNotSetException If the hardinesszone could not be added
* @throws PlantNotFoundException If the plant is not found in the database.
*/
public void plantAsCrop(Plant plant, LocalDate plantingDate) throws IOException, HardinessZoneNotSetException, PlantNotFoundException {
Crop crop = new Crop(plant.id(), plantingDate);
//TODO Add Area to Plant
//crop.withArea(0);
gardenPlan.saveCrop(crop);
taskListModel.planTasksForCrop(crop);
cropList = gardenPlan.getCrops();
}
/**
* Removes a {@link Crop} from the file and the cache
*
* @param crop The plant which is wnated to be planted
* @throws IOException If the database cannot be accessed
*/
public void removeCrop(Crop crop) throws IOException {
gardenPlan.removeCrop(crop);
taskListModel.removeTasksForCrop(crop.getCropId().orElseThrow(IllegalArgumentException::new));
cropList = gardenPlan.getCrops();
}
/**
* Returns a list of {@link Crop}s which are currently in the gardenplan.
*
* @throws IOException If the database cannot be accessed
*/
public List<Crop> getCrops() throws IOException {
if(!cropList.isEmpty()){
cropList = gardenPlan.getCrops();
}
return cropList;
}
/**
* Returns an Optional of {@link Crop} if the crop is the gardenplan
*
* @param cropId The date, when the plant is planted
* @throws IOException If the database cannot be accessed
*/
public Optional<Crop> getCrop(Long cropId) throws IOException {
return gardenPlan.getCropById(cropId);
}
// private JasonGardenplan gardenplan;
// liste von crops
//task generieren
//plant holen, task template mit tasktemplateklasse tasks erstellen
}

View File

@ -18,11 +18,11 @@ public interface GardenPlan {
/**
* Attempts to retrieve the {@link Crop} with the specified cropId.
*
* @param cropId The {@link Crop} to look for
* @param id The {@link Crop#cropId} to look for
* @return {@link Optional} of the found {@link Crop}, {@link Optional#empty()} if no entry matched the criteria
* @throws IOException If there is a problem reading from or writing to the database
*/
Optional<Crop> getCropById(long cropId) throws IOException;
Optional<Crop> getCropById(long id) throws IOException;
/**
* Saves a Crop to the Database.

View File

@ -1,16 +1,13 @@
package ch.zhaw.gartenverwaltung.io;
import ch.zhaw.gartenverwaltung.types.Crop;
import ch.zhaw.gartenverwaltung.types.Task;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
@ -27,7 +24,6 @@ import java.util.Map;
public class JsonTaskDatabase implements TaskDatabase{
IdProvider idProvider;
private final URL dataSource = getClass().getResource("taskdb.json");
private final static String INVALID_DATASOURCE_MSG = "Invalid datasource specified!";
private Map<Long, Task> taskMap = Collections.emptyMap();
@ -38,10 +34,7 @@ public class JsonTaskDatabase implements TaskDatabase{
static {
DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd");
LocalDateDeserializer dateDeserializer = new LocalDateDeserializer(dateFormat);
LocalDateSerializer dateSerializer = new LocalDateSerializer(dateFormat);
timeModule.addDeserializer(LocalDate.class, dateDeserializer);
timeModule.addSerializer(LocalDate.class, dateSerializer);
}
/**
@ -58,31 +51,6 @@ public class JsonTaskDatabase implements TaskDatabase{
return taskMap.values().stream().filter(task -> task.isInTimePeriode(start, end)).toList();
}
/**
* Method get all Tasks for a specific Crop
* @param cropId the cropId
* @return List of Tasks for given Crop
*/
@Override
public List<Task> getTaskForCrop(long cropId) throws IOException {
if(taskMap.isEmpty()) {
loadTaskListFromFile();
}
return taskMap.values().stream().filter(task -> task.getCropId() == cropId).toList();
}
/**
* Method remove all Tasks for a specific Crop
* @param cropId the crop
*/
@Override
public void removeTasksForCrop(long cropId) throws IOException {
if(taskMap.isEmpty()) {
loadTaskListFromFile();
}
taskMap.values().removeIf(task -> task.getCropId() == cropId);
}
/**
* If no data is currently loaded, data is loaded from {@link #dataSource}.
* If the {@link Task} has an id than the task is added to the {@link #taskMap}
@ -127,16 +95,12 @@ public class JsonTaskDatabase implements TaskDatabase{
* @throws IOException If the database cannot be accessed
*/
private void writeTaskListToFile() throws IOException {
if(dataSource != null) {
try {
new ObjectMapper()
.registerModule(timeModule)
.registerModule(new Jdk8Module())
.writeValue(new File(dataSource.toURI()), taskMap.values());
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(timeModule)
.registerModule(new Jdk8Module());
} catch (URISyntaxException e) {
throw new IOException(INVALID_DATASOURCE_MSG, e);
}
if(dataSource != null) {
mapper.writeValue(new File(dataSource.getFile()), taskMap);
}
}
@ -148,8 +112,7 @@ public class JsonTaskDatabase implements TaskDatabase{
private void loadTaskListFromFile() throws IOException {
if (dataSource != null) {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(timeModule)
.registerModule(new Jdk8Module());
mapper.registerModule(timeModule);
List<Task> result;
result = mapper.readerForListOf(Task.class).readValue(dataSource);
@ -159,8 +122,5 @@ public class JsonTaskDatabase implements TaskDatabase{
(res, task) -> res.put(task.getId(), task),
(existing, replacement) -> {});
}
Long maxId = taskMap.isEmpty() ? 0L : Collections.max(taskMap.keySet());
idProvider = new IdProvider(maxId);
}
}

View File

@ -1,6 +1,5 @@
package ch.zhaw.gartenverwaltung.io;
import ch.zhaw.gartenverwaltung.types.Crop;
import ch.zhaw.gartenverwaltung.types.HardinessZone;
import ch.zhaw.gartenverwaltung.types.Plant;
import ch.zhaw.gartenverwaltung.types.Task;
@ -25,21 +24,6 @@ public interface TaskDatabase {
*/
List<Task> getTaskList(LocalDate start, LocalDate end) throws IOException;
/**
* Method get all Tasks for a specific Crop
* @param cropId the cropId
* @return List of Tasks for given Crop
* @throws IOException If the database cannot be accessed
*/
List<Task> getTaskForCrop(long cropId) throws IOException;
/**
* Method remove all Tasks for a specific Crop
* @param cropId the cropId
* @throws IOException If the database cannot be accessed
*/
void removeTasksForCrop(long cropId) throws IOException;
/**
* Saves the {@link Task} in the Cache.
*

View File

@ -1,7 +0,0 @@
package ch.zhaw.gartenverwaltung.taskList;
public class PlantNotFoundException extends Exception {
public PlantNotFoundException() {
super("The selected Plant was not found in Database!");
}
}

View File

@ -1,186 +0,0 @@
package ch.zhaw.gartenverwaltung.taskList;
import ch.zhaw.gartenverwaltung.Config;
import ch.zhaw.gartenverwaltung.io.*;
import ch.zhaw.gartenverwaltung.types.*;
import java.io.IOException;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
public class TaskListModel {
private TaskDatabase taskDatabase;
private PlantDatabase plantDatabase;
/**
* Comparators to create sorted Task List
*/
static final Comparator<Task> sortByStartDate = Comparator.comparing(Task::getStartDate);
public TaskListModel(){
taskDatabase = new JsonTaskDatabase();
plantDatabase = new JsonPlantDatabase();
}
/**
* Constructor to create Database Objects.
*/
public TaskListModel(TaskDatabase taskDatabase, PlantDatabase plantDatabase) {
this.taskDatabase = taskDatabase;
this.plantDatabase = plantDatabase;
}
/**
* Method to save a new Task to Task Database
* @param task the Task to save
* @throws IOException If the database cannot be accessed
*/
public void addTask(Task task) throws IOException {
taskDatabase.saveTask(task);
}
/**
* Method to add all Tasks for a new crop
* @param crop the crop which is added
* @throws PlantNotFoundException if the plantId in the crop doesn't exist in Plant Database
* @throws HardinessZoneNotSetException If there is no Hardiness Zone Set in Plant Database
* @throws IOException If the database cannot be accessed
*/
public void planTasksForCrop(Crop crop) throws PlantNotFoundException, HardinessZoneNotSetException, IOException {
Plant plant = plantDatabase.getPlantById(Config.getCurrentHardinessZone(), crop.getPlantId()).orElseThrow(PlantNotFoundException::new);
for (GrowthPhase growthPhase : plant.lifecycle()) {
for (TaskTemplate taskTemplate : growthPhase.taskTemplates()) {
addTask(taskTemplate.generateTask(crop.getStartDate(), crop.getCropId().orElse(0L)));
}
}
}
/**
* Method to remove all Tasks for a specific Crop
* @param cropId The crop which is removed
* @throws IOException If the database cannot be accessed
*/
public void removeTasksForCrop(long cropId) throws IOException {
taskDatabase.removeTasksForCrop(cropId);
}
/**
* Method to remove a Task from Database
* @param task the Task to remove
* @throws IOException If the database cannot be accessed
*/
public void removeTask(Task task) throws IOException {
taskDatabase.removeTask(task);
}
private List<Task> filterListByCrop(List<Task> taskList, Long cropId) {
return taskList.stream().filter(task -> task.getCropId() == cropId).collect(Collectors.toList());
}
/**
* Method to get all Tasks
* @return List of all Tasks
* @throws IOException If the database cannot be accessed
*/
public List<Task> getTaskList() throws IOException {
return getFilteredTaskList(LocalDate.MIN, LocalDate.MAX);
}
/**
* Method to get all Tasks for specific Crop
* @return List of all Tasks for with given CropID
* @throws IOException If the database cannot be accessed
*/
public List<Task> getTaskListForCrop(Long cropId) throws IOException {
return filterListByCrop(getTaskList(), cropId);
}
/**
* Method to get all Tasks which are today or in future
* @return List of Tasks
* @throws IOException If the database cannot be accessed
*/
public List<Task> getFutureTasks() throws IOException {
return getFilteredTaskList(LocalDate.now(), LocalDate.MAX);
}
/**
* Method to get all Tasks which are today or in future for specific Crop
* @return List of Tasks with given crop ID
* @throws IOException If the database cannot be accessed
*/
public List<Task> getFutureTasksForCrop(Long cropId) throws IOException {
return filterListByCrop(getFutureTasks(), cropId);
}
/**
* Method to get all Tasks which are today or in past
* @return List of Tasks
* @throws IOException If the database cannot be accessed
*/
public List<Task> getPastTasks() throws IOException {
return getFilteredTaskList(LocalDate.MIN, LocalDate.now());
}
/**
* Method to get all Tasks which are today or in past for specifc crop
* @return List of Tasks with given grop id
* @throws IOException If the database cannot be accessed
*/
public List<Task> getPastTasksForCrop(Long cropId) throws IOException {
return filterListByCrop(getPastTasks(), cropId);
}
/**
* Method to get an List of 7 Tasklists for the next 7 days. Index 0 is Tasklist for Today.
* @return List with length 7 (List<List<Task>>)
* @throws IOException If the database cannot be accessed
*/
public List<List<Task>> getTasksUpcomingWeek() throws IOException {
List<List<Task>> dayTaskList = new ArrayList<>();
for(int i = 0; i < 7; i++) {
LocalDate date = LocalDate.now().plusDays(i);
dayTaskList.add(taskDatabase.getTaskList(date, date));
}
return dayTaskList;
}
/**
* Method to get an List of 7 Tasklists for the next 7 days. (Filtered Index 0 is Tasklist for Today.
* @return List with length 7 (List<List<Task>>)
* @throws IOException If the database cannot be accessed
*/
public List<List<Task>> getTasksUpcomingWeekForCrop(Long cropId) throws IOException {
List<List<Task>> dayTaskList = new ArrayList<>();
for(int i = 0; i < 7; i++) {
LocalDate date = LocalDate.now().plusDays(i);
dayTaskList.add(filterListByCrop(taskDatabase.getTaskList(date, date), cropId));
}
return dayTaskList;
}
/**
* Method to get Tasklist filtered by date.
* @param start the start date for the filter
* @param end the end date for the filter
* @return List of Tasks matched by the filter
* @throws IOException If the database cannot be accessed
*/
public List<Task> getFilteredTaskList(LocalDate start, LocalDate end) throws IOException {
return getSortedTaskList(taskDatabase.getTaskList(start, end), sortByStartDate);
}
/**
* Method to sort a Tasklist by a given Comparator
* @param taskList The Tasklist to sort
* @param comparator the comparator to sort
* @return a sorted coppy of the given Tasklist
*/
private List<Task> getSortedTaskList(List<Task> taskList, Comparator<Task> comparator) {
return taskList.stream().sorted(comparator).collect(Collectors.toList());
}
}

View File

@ -3,7 +3,6 @@ package ch.zhaw.gartenverwaltung.types;
import javafx.scene.image.Image;
import java.time.LocalDate;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;
@ -20,40 +19,20 @@ public record Plant(
List<Pest> pests,
List<GrowthPhase> lifecycle) {
/**
* remove all growthPhase which do not belong to the hardiness zone
* @param zone hardiness zone
*/
public void inZone(HardinessZone zone) {
lifecycle.removeIf(growthPhase -> !growthPhase.zone().equals(zone));
}
/**
* get all growthPhases of lifecycle group
* @param group lifecycle group
* @return list of growthPhases
*/
public List<GrowthPhase> lifecycleForGroup(int group) {
return lifecycle.stream()
.filter(growthPhase -> growthPhase.group() == group)
.filter(growthPhase -> growthPhase.group() != group)
.collect(Collectors.toList());
}
/**
* get sow date from given harvest day from lifecycle group
* @param harvestDate date of the harvest
* @param group lifecycle group
* @return LocaleDate of sow date
*/
public LocalDate sowDateFromHarvestDate(LocalDate harvestDate, int group) {
return harvestDate.minusDays(timeToHarvest(group));
}
/**
* calculate the days between sow and harvest day for lifecycle group
* @param group the lifecycle group
* @return Integer number of dates between sow and harvest day
*/
public int timeToHarvest(int group) {
List<GrowthPhase> activeLifecycle = lifecycleForGroup(group);
GrowthPhase sow = activeLifecycle.stream()
@ -68,38 +47,4 @@ public record Plant(
int currentYear = LocalDate.now().getYear();
return (int) DAYS.between(harvest.startDate().atYear(currentYear), sow.startDate().atYear(currentYear));
}
/**
* filter out the given growthPhase out of the lifecycle
* create list of dates for this growthPhase and return it
* @param growthPhase the wanted growthPhase
* @return a list of dates of the current year
*/
public List<LocalDate> getDateListOfGrowthPhase(GrowthPhaseType growthPhase) {
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
* return a list of dates from start to end of growth phase
* @param growthPhase the current growthPhase
* @return a list of dates of the current year
*/
private List<LocalDate> addDatesFromMonthDay(GrowthPhase growthPhase) {
List<LocalDate> dates = new LinkedList<>();
LocalDate today = LocalDate.now();
LocalDate start = growthPhase.startDate().atYear(today.getYear());
LocalDate end = growthPhase.endDate().atYear(today.getYear());
while (!start.isAfter(end)) {
dates.add(start);
start = start.plusDays(1);
}
return dates;
}
}

View File

@ -3,20 +3,18 @@ package ch.zhaw.gartenverwaltung.types;
import java.time.MonthDay;
public enum Seasons {
AllSEASONS("--01-01", "--12-31", "All Seasons"),
SPRING("--03-01", "--05-30", "Spring"),
SUMMER("--06-01", "--08-30", "Summer"),
AUTUMN("--09-01", "--11-30", "Autumn"),
WINTER("--12-01", "--02-28", "Winter");
AllSEASONS("--01-01", "--12-31"),
SPRING("--03-01", "--05-30"),
SOMMER("--06-01", "--08-30"),
AUTUM("--09-01", "--11-30"),
WINTER("--12-01", "--02-28");
public final String startDate;
public final String endDate;
public final String name;
Seasons(String startDate, String endDate, String name) {
Seasons(String startDate, String endDate) {
this.startDate = startDate;
this.endDate = endDate;
this.name = name;
}
public MonthDay getStartDate() {
@ -25,7 +23,4 @@ public enum Seasons {
public MonthDay getEndDate() {
return MonthDay.parse(this.endDate);
}
public String getName() {
return this.name;
}
}

View File

@ -15,33 +15,29 @@ public class Task {
private final LocalDate startDate;
private Integer interval;
private LocalDate endDate;
private long cropId;
/**
* default constructor
* (used by Json deserializer)
*/
public Task(long cropId){
public Task(){
name= "";
description= "";
startDate = LocalDate.now();
this.cropId = cropId;
}
public Task(String name, String description, LocalDate startDate, long cropId) {
public Task(String name, String description, LocalDate startDate) {
this.name = name;
this.description = description;
this.startDate = startDate;
this.cropId = cropId;
}
public Task(String name, String description, LocalDate startDate, LocalDate endDate, int interval, long cropId) {
public Task(String name, String description, LocalDate startDate, LocalDate endDate, int interval) {
this.name = name;
this.description = description;
this.startDate = startDate;
this.endDate = endDate;
this.interval = interval;
this.cropId = cropId;
}
// Builder-pattern-style setters
@ -59,7 +55,10 @@ public class Task {
}
public boolean isInTimePeriode(LocalDate searchStartDate, LocalDate searchEndDate){
return startDate.isAfter(searchStartDate) && startDate.isBefore(searchEndDate);
if(startDate.isAfter(searchStartDate) &&startDate.isBefore(searchEndDate)){
return true;
}
return false;
}
// Getters
@ -67,7 +66,6 @@ public class Task {
public String getName() { return name; }
public String getDescription() { return description; }
public LocalDate getStartDate() { return startDate; }
public long getCropId() { return cropId; }
public Optional<Integer> getInterval() {
return Optional.ofNullable(interval);

View File

@ -44,8 +44,8 @@ public class TaskTemplate {
this.relativeStartDate = relativeStartDate;
}
public Task generateTask(LocalDate realStartDate, long cropId) {
Task task = new Task(name, description, realStartDate.plusDays(relativeStartDate), cropId);
public Task generateTask(LocalDate realStartDate) {
Task task = new Task(name, description, realStartDate.plusDays(relativeStartDate));
if (relativeEndDate != null) {
task.withEndDate(realStartDate.plusDays(relativeEndDate));
}

View File

@ -85,7 +85,7 @@
<Insets bottom="10.0" />
</VBox.margin>
</Label>
<VBox fx:id="growthPhases_vbox" prefHeight="135.0" prefWidth="879.0">
<VBox fx:id="growthPahses_vbox" prefHeight="135.0" prefWidth="879.0">
<VBox.margin>
<Insets bottom="10.0" />
</VBox.margin>
@ -126,7 +126,7 @@
<Insets right="40.0" />
</HBox.margin>
</Label>
<Label fx:id="location_label" text="Label">
<Label fx:id="lacation_label" text="Label">
<HBox.margin>
<Insets right="10.0" />
</HBox.margin>

View File

@ -1,12 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.geometry.Rectangle2D?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ListView?>
<?import javafx.scene.control.SplitPane?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.control.TitledPane?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.HBox?>
@ -31,8 +33,15 @@
<TextField fx:id="search_plants" promptText="Search for Plant Name" />
<HBox alignment="CENTER_LEFT" prefHeight="480.0" prefWidth="881.0" VBox.vgrow="ALWAYS">
<children>
<ListView fx:id="list_plants" maxWidth="1.7976931348623157E308" prefHeight="497.0" prefWidth="400.0" HBox.hgrow="ALWAYS" />
<ImageView fx:id="img_plant" fitWidth="300" pickOnBounds="true" preserveRatio="true" HBox.hgrow="NEVER" />
<ListView fx:id="list_plants" maxWidth="1.7976931348623157E308" prefHeight="497.0" prefWidth="580.0" HBox.hgrow="ALWAYS" />
<ImageView fx:id="img_plant" fitHeight="322.0" fitWidth="861.0" pickOnBounds="true" preserveRatio="true" HBox.hgrow="NEVER">
<viewport>
<Rectangle2D height="300.0" width="300.0" />
</viewport>
<image>
<Image url="@placeholder.png" />
</image>
</ImageView>
</children>
</HBox>
<Label prefHeight="33.0" prefWidth="919.0" text="Plant Information:">
@ -48,7 +57,7 @@
<Insets bottom="10.0" top="10.0" />
</padding>
</Label>
<Button fx:id="selectSowDay_button" alignment="CENTER" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#selectSowDate" prefHeight="38.0" prefWidth="917.0" text="Select Harvest/Sow Day" />
<Button fx:id="saveToMyPlant_button" alignment="CENTER" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#saveToMyPlant" prefHeight="38.0" prefWidth="917.0" text="Save to MyPlants" />
</children>
</VBox>
</children>

View File

@ -1,57 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.DatePicker?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.RadioButton?>
<?import javafx.scene.control.ToggleGroup?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="150.0"
prefWidth="308.0" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ch.zhaw.gartenverwaltung.SelectSowDayController">
<children>
<VBox maxWidth="1.7976931348623157E308" prefHeight="408.0" prefWidth="640.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<Label fx:id="popup_label" text="Label" />
<HBox alignment="CENTER" prefHeight="293.0" prefWidth="631.0">
<children>
<VBox alignment="CENTER_LEFT" prefHeight="88.0" prefWidth="155.0">
<children>
<RadioButton fx:id="sow_radio" mnemonicParsing="false" selected="true" text="Sow">
<VBox.margin>
<Insets bottom="10.0" />
</VBox.margin>
<toggleGroup>
<ToggleGroup fx:id="group" />
</toggleGroup>
</RadioButton>
<RadioButton fx:id="harvest_radio" mnemonicParsing="false" text="Harvest" toggleGroup="$group" />
</children>
<HBox.margin>
<Insets top="10.0" />
</HBox.margin>
</VBox>
<DatePicker fx:id="datepicker" />
</children>
</HBox>
<HBox fillHeight="false" prefHeight="54.0" prefWidth="631.0" VBox.vgrow="NEVER">
<children>
<Button fx:id="save_button" mnemonicParsing="false" onAction="#save" prefHeight="25.0" prefWidth="53.0" text="Save">
<HBox.margin>
<Insets right="10.0" />
</HBox.margin>
</Button>
<Button fx:id="cancel_button" mnemonicParsing="false" onAction="#cancel" text="Cancel" />
</children>
</HBox>
</children>
<padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</padding>
</VBox>
</children>
</AnchorPane>

View File

@ -94,7 +94,6 @@
"endDate": "03-10",
"zone": "ZONE_8A",
"type": "SOW",
"group": 0,
"wateringCycle": {
"litersPerSqM": 15,
"interval": 3,
@ -116,7 +115,6 @@
"endDate": "05-10",
"zone": "ZONE_8A",
"type": "PLANT",
"group": 0,
"wateringCycle": {
"litersPerSqM": 25,
"interval": 3,
@ -140,7 +138,6 @@
"endDate": "05-20",
"zone": "ZONE_8A",
"type": "HARVEST",
"group": 0,
"wateringCycle": {
"litersPerSqM": 0,
"interval": null,

View File

@ -5,8 +5,7 @@
"description": "Plant the seeds, crops in de bed.",
"startDate" : "2022-05-01",
"endDate" : "2022-05-01",
"interval" : 0,
"cropId" : 0
"interval" : 0
},
{
"id" : 2,
@ -14,8 +13,7 @@
"description": "water the plant, so that the soil is wet around the plant.",
"startDate" : "2022-05-01",
"endDate" : "2022-09-01",
"interval" : 2,
"cropId" : 0
"interval" : 2
},
{
"id" : 3,
@ -23,8 +21,7 @@
"description": "The fertilizer has to be mixed with water. Then fertilize the plants soil with the mixture",
"startDate" : "2022-06-01",
"endDate" : "2022-08-01",
"interval" : 28,
"cropId" : 0
"interval" : 28
},
{
"id" : 4,
@ -32,8 +29,7 @@
"description": "Take a big enough coverage for the plants. Cover the whole plant with a bit space between the plant and the coverage",
"startDate" : "2022-07-01",
"endDate" : "2022-07-01",
"interval" : 0,
"cropId" : 0
"interval" : 0
},
{
"id" : 5,
@ -41,8 +37,7 @@
"description": "Look for pest or illness at the leaves of the plant. Check the soil around the plant, if the roots are enough covered with soil",
"startDate" : "2022-05-01",
"endDate" : "2022-09-01",
"interval" : 5,
"cropId" : 0
"interval" : 5
},
{
"id" : 6,
@ -50,7 +45,6 @@
"description": "Pull the ripe vegetables out from the soil. Clean them with clear, fresh water. ",
"startDate" : "2022-09-01",
"endDate" : "2022-09-01",
"interval" : 0,
"cropId" : 0
"interval" : 0
}
]

View File

@ -1,113 +0,0 @@
package ch.zhaw.gartenverwaltung.gardenplan;
import ch.zhaw.gartenverwaltung.io.*;
import ch.zhaw.gartenverwaltung.taskList.PlantNotFoundException;
import ch.zhaw.gartenverwaltung.taskList.TaskListModel;
import ch.zhaw.gartenverwaltung.types.*;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.nio.file.Files;
import java.time.LocalDate;
import java.time.MonthDay;
import java.util.ArrayList;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.*;
public class GardenPlanModelTest {
GardenPlan gardenPlan;
List<Crop> cropList;
Crop exampleCropOnion;
Crop exampleCropCarrot;
Crop exampleCrop1;
Crop exampleCrop2;
Crop exampleCrop3;
Plant examplePlantOnion;
Plant examplePlantCarrot;
Gardenplanmodel model;
@BeforeEach
void setUp() throws IOException {
examplePlantOnion = new Plant(
0,
"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, new ArrayList<>()),
new GrowthPhase(MonthDay.of(4, 3), MonthDay.of(12, 4), 0, new WateringCycle(0, 0, null), GrowthPhaseType.PLANT, HardinessZone.ZONE_8A, new ArrayList<>()),
new GrowthPhase(MonthDay.of(8, 5), MonthDay.of(12, 4), 0, new WateringCycle(0, 0, null), GrowthPhaseType.PLANT, HardinessZone.ZONE_8A, new ArrayList<>()),
new GrowthPhase(MonthDay.of(2, 8), MonthDay.of(12, 4), 0, new WateringCycle(0, 0, null), GrowthPhaseType.PLANT, HardinessZone.ZONE_8A, new ArrayList<>()),
new GrowthPhase(MonthDay.of(10, 2), MonthDay.of(12, 4), 0, new WateringCycle(0, 0, null), GrowthPhaseType.PLANT, HardinessZone.ZONE_8A, new ArrayList<>())));
exampleCropOnion = new Crop(examplePlantOnion.id(), LocalDate.of(2023,3,1));
exampleCropOnion.withId(3);
examplePlantCarrot = new Plant(
1,
"Early Carrot",
"Carrot, (Daucus carota), herbaceous, generally biennial plant of the Apiaceae family that produces an edible taproot. Among common varieties root shapes range from globular to long, with lower ends blunt to pointed. Besides the orange-coloured roots, white-, yellow-, and purple-fleshed varieties are known.",
null,
"5,35,2.5",
0,
"sandy to loamy, loose soil, free of stones",
new ArrayList<>(),
List.of(new GrowthPhase(MonthDay.of(4, 4), MonthDay.of(12, 4), 0, new WateringCycle(0, 0, null), GrowthPhaseType.PLANT, HardinessZone.ZONE_8A, new ArrayList<>())));
exampleCropCarrot = new Crop(examplePlantCarrot.id(), LocalDate.now());
exampleCropCarrot.withId(5);
exampleCrop1 = new Crop(1, LocalDate.of(2023,2,25));
exampleCrop1.withId(0);
exampleCrop1.withArea(0.5);
exampleCrop2 = new Crop(1,LocalDate.of(2023,3,1));
exampleCrop2.withId(1);
exampleCrop2.withArea(0.5);
exampleCrop3 = new Crop(0,LocalDate.of(2023,3,01));
exampleCrop3.withId(2);
exampleCrop3.withArea(1.0);
cropList = new ArrayList<>();
cropList.add(exampleCrop1);
cropList.add(exampleCrop2);
cropList.add(exampleCrop3);
gardenPlan = mockGardenPlan(cropList);
TaskListModel taskListModel = new TaskListModel(new JsonTaskDatabase(), new JsonPlantDatabase());
model = new Gardenplanmodel(taskListModel);
}
GardenPlan mockGardenPlan(List<Crop> cropList) throws IOException {
GardenPlan gardenPlan = mock(GardenPlan.class);
when(gardenPlan.getCrops()).thenReturn(cropList);
when(gardenPlan.getCropById(5)).thenReturn(java.util.Optional.ofNullable(exampleCropCarrot));
when(gardenPlan.getCropById(3)).thenReturn(java.util.Optional.ofNullable(exampleCropOnion));
return gardenPlan;
}
@Test
void plantAsCrop() throws HardinessZoneNotSetException, IOException, PlantNotFoundException {
model.plantAsCrop(examplePlantOnion, LocalDate.of(2023,3,1));
exampleCropOnion = model.getCrop(2L).get();
assertEquals(model.getCrops().get(2),exampleCropOnion);
}
@Test
void removeCrop() throws IOException {
exampleCrop1.withId(2);
exampleCrop1.withArea(1.500000);
model.removeCrop(exampleCrop1);
assertEquals(2,model.getCrops().size());
}
}

View File

@ -34,14 +34,4 @@ public class JsonTaskDatabaseTest {
Assertions.assertTrue(taskList.size()>0);
*/
}
@Test
void getTaskForCrop() {
// TODO implement Test
}
@Test
void removeTasksForCrop() {
// TODO implement Test
}
}

View File

@ -1,158 +0,0 @@
package ch.zhaw.gartenverwaltung.taskList;
import ch.zhaw.gartenverwaltung.io.*;
import ch.zhaw.gartenverwaltung.types.HardinessZone;
import ch.zhaw.gartenverwaltung.types.Plant;
import ch.zhaw.gartenverwaltung.types.Task;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.time.LocalDate;
import java.util.*;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
class TaskListModelTest {
TaskDatabase taskDatabase;
PlantDatabase plantDatabase;
List<Task> exampleTaskList;
Map<Long, Plant> examplePlantMap;
TaskListModel model;
@BeforeEach
void setUp() throws IOException {
createExampleTaskList();
taskDatabase = mockTaskDatabase(exampleTaskList);
plantDatabase = mockPlantDatabase(examplePlantMap);
model = new TaskListModel(taskDatabase, plantDatabase);
}
private TaskDatabase mockTaskDatabase(List<Task> exampleTaskList) throws IOException {
TaskDatabase taskDatabase = mock(JsonTaskDatabase.class);
when(taskDatabase.getTaskList(LocalDate.MIN, LocalDate.MAX)).thenReturn(exampleTaskList);
when(taskDatabase.getTaskList(LocalDate.now(), LocalDate.MAX)).thenReturn((exampleTaskList.subList(1, 4)));
List<Task> pastTasks = new ArrayList<>();
pastTasks.add(exampleTaskList.get(0));
pastTasks.add(exampleTaskList.get(2));
pastTasks.add(exampleTaskList.get(4));
when(taskDatabase.getTaskList(LocalDate.MIN, LocalDate.now())).thenReturn(pastTasks);
when(taskDatabase.getTaskList(LocalDate.now(), LocalDate.now())).thenReturn(List.of(exampleTaskList.get(2)));
when(taskDatabase.getTaskList(LocalDate.now().plusDays(1L), LocalDate.now().plusDays(1L))).thenReturn(List.of(exampleTaskList.get(1)));
when(taskDatabase.getTaskList(LocalDate.now().plusDays(2L), LocalDate.now().plusDays(2L))).thenReturn(List.of());
when(taskDatabase.getTaskList(LocalDate.now().plusDays(3L), LocalDate.now().plusDays(3L))).thenReturn(List.of());
when(taskDatabase.getTaskList(LocalDate.now().plusDays(4L), LocalDate.now().plusDays(4L))).thenReturn(List.of());
when(taskDatabase.getTaskList(LocalDate.now().plusDays(5L), LocalDate.now().plusDays(5L))).thenReturn(List.of());
when(taskDatabase.getTaskList(LocalDate.now().plusDays(6L), LocalDate.now().plusDays(6L))).thenReturn(List.of());
return taskDatabase;
}
private PlantDatabase mockPlantDatabase(Map<Long, Plant> examplePlantMap) {
return new PlantDatabase() {
@Override
public List<Plant> getPlantList(HardinessZone zone) {
return null;
}
@Override
public Optional<Plant> getPlantById(HardinessZone zone, long id) {
return Optional.ofNullable(examplePlantMap.get(id));
}
};
}
void createExampleTaskList() {
exampleTaskList = new ArrayList<>();
exampleTaskList.add(new Task("name", "description", LocalDate.now().minusDays(1), 1L));
exampleTaskList.add(new Task("name", "description", LocalDate.now().plusDays(1), 2L));
exampleTaskList.add(new Task("name", "description", LocalDate.now(), 1L));
exampleTaskList.add(new Task("name", "description", LocalDate.of(9019, 5, 5), 1L));
exampleTaskList.add(new Task("name", "description", LocalDate.of(2019, 5, 5), 2L));
}
void createExamplePlantMap() {
examplePlantMap = new HashMap<>();
}
@Test
void addTask() throws IOException {
Task taskToAdd = new Task("name", "description", LocalDate.now(), 1L);
model.addTask(taskToAdd);
verify(taskDatabase, times(1)).saveTask(taskToAdd);
}
@Test
void removeTask() throws IOException {
Task taskToRemove = new Task("name", "description", LocalDate.now(), 1L);
model.removeTask(taskToRemove);
verify(taskDatabase, times(1)).removeTask(taskToRemove);
}
@Test
void getTaskList() throws IOException {
List<Task> listToCheck = model.getTaskList();
assertEquals(5, listToCheck.size());
assertEquals(exampleTaskList.get(4), listToCheck.get(0));
assertEquals(exampleTaskList.get(0), listToCheck.get(1));
assertEquals(exampleTaskList.get(2), listToCheck.get(2));
assertEquals(exampleTaskList.get(1), listToCheck.get(3));
assertEquals(exampleTaskList.get(3), listToCheck.get(4));
}
@Test
void getFutureTasks() throws IOException {
List<Task> listToCheck = model.getFutureTasks();
assertEquals(3, listToCheck.size());
assertEquals(exampleTaskList.get(2), listToCheck.get(0));
assertEquals(exampleTaskList.get(1), listToCheck.get(1));
assertEquals(exampleTaskList.get(3), listToCheck.get(2));
}
@Test
void getPastTasks() throws IOException {
List<Task> listToCheck = model.getPastTasks();
assertEquals(3, listToCheck.size());
assertEquals(exampleTaskList.get(4), listToCheck.get(0));
assertEquals(exampleTaskList.get(0), listToCheck.get(1));
assertEquals(exampleTaskList.get(2), listToCheck.get(2));
}
@Test
void getTasksUpcomingWeek() throws IOException {
List<List<Task>> dayList = model.getTasksUpcomingWeek();
assertEquals(7, dayList.size());
//Check day 0
assertEquals(1, dayList.get(0).size());
assertEquals(exampleTaskList.get(2), dayList.get(0).get(0));
//Check day 1
assertEquals(1, dayList.get(1).size());
assertEquals(exampleTaskList.get(1), dayList.get(1).get(0));
//Check day 2
assertEquals(0, dayList.get(2).size());
//Check day 3
assertEquals(0, dayList.get(3).size());
//Check day 4
assertEquals(0, dayList.get(4).size());
//Check day 5
assertEquals(0, dayList.get(5).size());
//Check day 6
assertEquals(0, dayList.get(6).size());
}
@Test
void removeTasksForCrop() throws IOException {
model.removeTasksForCrop(1L);
verify(taskDatabase, times(1)).removeTasksForCrop(1L);
}
}

View File

@ -1,257 +0,0 @@
[
{
"id": 0,
"name": "Potato",
"description": "The potato is a tuber, round or oval, with small white roots called 'eyes', that are growth buds. The size varies depending on the variety; the colour of the skin can be white, yellow or even purple.",
"light": 6,
"spacing": "35",
"soil": "sandy",
"image": "potato.jpg",
"pests": [
{
"name": "Rot",
"description": "Rot, any of several plant diseases, caused by any of hundreds of species of soil-borne bacteria, fungi, and funguslike organisms (Oomycota). Rot diseases are characterized by plant decomposition and putrefaction. The decay may be hard, dry, spongy, watery, mushy, or slimy and may affect any plant part.",
"measures": "Less water."
}
],
"lifecycle": [
{
"startDate": "03-10",
"endDate": "04-10",
"type": "SOW",
"zone": "ZONE_8A",
"group": 0,
"wateringCycle": {
"litersPerSqM": 0,
"interval": null,
"notes": []
},
"taskTemplates": [
{
"name": "Germinate",
"relativeStartDate": -14,
"relativeEndDate": null,
"description": "\"Take an egg carton and fill it with soil. Put the seedling deep enaugh so its half covered with soil. Keep it in 10-15 * Celsius with lots of light.\"",
"interval": null,
"isOptional": false
}
]
},
{
"startDate": "04-10",
"endDate": "07-10",
"type": "PLANT",
"zone": "ZONE_8A",
"group": 0,
"wateringCycle": {
"litersPerSqM": 25,
"interval": 7,
"notes": []
},
"taskTemplates": [
{
"name": "hilling",
"relativeStartDate": 0,
"relativeEndDate": null,
"description": "\"When the plants are 20 cm tall, begin hilling the potatoes by gently mounding the soil from the center of your rows around the stems of the plant. Mound up the soil around the plant until just the top few leaves show above the soil. Two weeks later, hill up the soil again when the plants grow another 20 cm.\"",
"interval": 21,
"isOptional": false
}
]
},
{
"startDate": "06-10",
"endDate": "08-10",
"type": "HARVEST",
"zone": "ZONE_8A",
"group": 0,
"wateringCycle": {
"litersPerSqM": 0,
"interval": null,
"notes": []
},
"taskTemplates": [
{
"name": "Harvest",
"relativeStartDate": 0,
"relativeEndDate": null,
"description": "Once the foliage has wilted and dried completely, harvest on a dry day. Store in a dark and cool location.",
"interval": null,
"isOptional": false
}
]
}
]
},
{
"id": 1,
"name": "Early Carrot",
"description": "Carrot, (Daucus carota), herbaceous, generally biennial plant of the Apiaceae family that produces an edible taproot. Among common varieties root shapes range from globular to long, with lower ends blunt to pointed. Besides the orange-coloured roots, white-, yellow-, and purple-fleshed varieties are known.",
"image": "carrot.jpg",
"lifecycle": [
{
"startDate": "02-20",
"endDate": "03-10",
"zone": "ZONE_8A",
"type": "SOW",
"wateringCycle": {
"litersPerSqM": 15,
"interval": 3,
"notes": []
},
"taskTemplates": [
{
"name": "hilling",
"relativeStartDate": 0,
"relativeEndDate": 0,
"description": "Mound up the soil around the plant until just the top few leaves show above the soil. ",
"interval": null,
"isOptional": false
}
]
},
{
"startDate": "03-10",
"endDate": "05-10",
"zone": "ZONE_8A",
"type": "PLANT",
"wateringCycle": {
"litersPerSqM": 25,
"interval": 3,
"notes": [
"Be careful not to pour water over the leaves, as this will lead to sunburn."
]
},
"taskTemplates": [
{
"name": "hilling",
"relativeStartDate": 0,
"relativeEndDate": null,
"description": "Mound up the soil around the plant until just the top few leaves show above the soil. ",
"interval": 15,
"isOptional": true
}
]
},
{
"startDate": "05-10",
"endDate": "05-20",
"zone": "ZONE_8A",
"type": "HARVEST",
"wateringCycle": {
"litersPerSqM": 0,
"interval": null,
"notes": []
},
"taskTemplates": [
{
"name": "Harvesting",
"relativeStartDate": 0,
"relativeEndDate": 14,
"description": "When the leaves turn to a yellowish brown. Do not harvest earlier. The plant will show when it's ready.",
"interval": null,
"isOptional": false
}
]
}
],
"soil": "sandy to loamy, loose soil, free of stones",
"spacing": "5,35,2.5",
"pests": [
{
"name": "Rot",
"description": "rot, any of several plant diseases, caused by any of hundreds of species of soil-borne bacteria, fungi, and funguslike organisms (Oomycota). Rot diseases are characterized by plant decomposition and putrefaction. The decay may be hard, dry, spongy, watery, mushy, or slimy and may affect any plant part.",
"measures": "less water"
}
]
},
{
"id": 2,
"name": "Summertime Onion",
"description": "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.",
"image": "onion.jpg",
"lifecycle": [
{
"startDate": "03-15",
"endDate": "04-10",
"type": "SOW",
"zone": "ZONE_8A",
"group": 0,
"wateringCycle": {
"litersPerSqM": 15,
"interval": 4,
"notes": [
]
},
"taskTemplates": [
{
"name": "hilling",
"relativeStartDate": 0,
"relativeEndDate": 0,
"description": "Mound up the soil around the plant until just the top few leaves show above the soil. ",
"interval": null,
"isOptional": false
}
]
},
{
"startDate": "04-10",
"endDate": "07-10",
"type": "PLANT",
"zone": "ZONE_8A",
"group": 0,
"wateringCycle": {
"litersPerSqM": 25,
"interval": 3,
"notes": [
""
]
},
"taskTemplates": [
{
"name": "hilling",
"relativeStartDate": 0,
"relativeEndDate": null,
"description": "Mound up the soil around the plant until just the top few leaves show above the soil. ",
"interval": 15,
"isOptional": true
}
]
},
{
"startDate": "07-10",
"endDate": "09-20",
"type": "HARVEST",
"zone": "ZONE_8A",
"group": 0,
"wateringCycle": {
"litersPerSqM": 0,
"interval": null,
"notes": [
]
},
"taskTemplates": [
{
"name": "Harvesting",
"relativeStartDate": 0,
"relativeEndDate": 14,
"description": "When ready for harvest, the leaves on your onion plants will start to flop over. This happens at the \"neck\" of the onion and it signals that the plant has stopped growing and is ready for storage. Onions should be harvested soon thereafter",
"interval": null,
"isOptional": false
}
]
}
],
"soil": "sandy to loamy, loose soil, free of stones",
"spacing": "15,30,2",
"pests": [
{
"name": "Rot",
"description": "rot, any of several plant diseases, caused by any of hundreds of species of soil-borne bacteria, fungi, and funguslike organisms (Oomycota). Rot diseases are characterized by plant decomposition and putrefaction. The decay may be hard, dry, spongy, watery, mushy, or slimy and may affect any plant part.",
"measures": "less water"
}
]
}
]

View File

@ -1,56 +0,0 @@
[
{
"id" : 1,
"name" : "sow plant",
"description": "Plant the seeds, crops in de bed.",
"startDate" : "2022-05-01",
"endDate" : "2022-05-01",
"interval" : 0,
"cropID" : 0
},
{
"id" : 2,
"name" : "water plant",
"description": "water the plant, so that the soil is wet around the plant.",
"startDate" : "2022-05-01",
"endDate" : "2022-09-01",
"interval" : 2,
"cropID" : 0
},
{
"id" : 3,
"name" : "fertilize plant",
"description": "The fertilizer has to be mixed with water. Then fertilize the plants soil with the mixture",
"startDate" : "2022-06-01",
"endDate" : "2022-08-01",
"interval" : 28,
"cropID" : 0
},
{
"id" : 4,
"name" : "covering plant",
"description": "Take a big enough coverage for the plants. Cover the whole plant with a bit space between the plant and the coverage",
"startDate" : "2022-07-01",
"endDate" : "2022-07-01",
"interval" : 0,
"cropID" : 0
},
{
"id" : 5,
"name" : "look after plant",
"description": "Look for pest or illness at the leaves of the plant. Check the soil around the plant, if the roots are enough covered with soil",
"startDate" : "2022-05-01",
"endDate" : "2022-09-01",
"interval" : 5,
"cropID" : 0
},
{
"id" : 6,
"name" : "harvest plant",
"description": "Pull the ripe vegetables out from the soil. Clean them with clear, fresh water. ",
"startDate" : "2022-09-01",
"endDate" : "2022-09-01",
"interval" : 0,
"cropID" : 0
}
]

View File

@ -1,257 +0,0 @@
[
{
"id": 0,
"name": "Potato",
"description": "The potato is a tuber, round or oval, with small white roots called 'eyes', that are growth buds. The size varies depending on the variety; the colour of the skin can be white, yellow or even purple.",
"light": 6,
"spacing": "35",
"soil": "sandy",
"image": "potato.jpg",
"pests": [
{
"name": "Rot",
"description": "Rot, any of several plant diseases, caused by any of hundreds of species of soil-borne bacteria, fungi, and funguslike organisms (Oomycota). Rot diseases are characterized by plant decomposition and putrefaction. The decay may be hard, dry, spongy, watery, mushy, or slimy and may affect any plant part.",
"measures": "Less water."
}
],
"lifecycle": [
{
"startDate": "03-10",
"endDate": "04-10",
"type": "SOW",
"zone": "ZONE_8A",
"group": 0,
"wateringCycle": {
"litersPerSqM": 0,
"interval": null,
"notes": []
},
"taskTemplates": [
{
"name": "Germinate",
"relativeStartDate": -14,
"relativeEndDate": null,
"description": "\"Take an egg carton and fill it with soil. Put the seedling deep enaugh so its half covered with soil. Keep it in 10-15 * Celsius with lots of light.\"",
"interval": null,
"isOptional": false
}
]
},
{
"startDate": "04-10",
"endDate": "07-10",
"type": "PLANT",
"zone": "ZONE_8A",
"group": 0,
"wateringCycle": {
"litersPerSqM": 25,
"interval": 7,
"notes": []
},
"taskTemplates": [
{
"name": "hilling",
"relativeStartDate": 0,
"relativeEndDate": null,
"description": "\"When the plants are 20 cm tall, begin hilling the potatoes by gently mounding the soil from the center of your rows around the stems of the plant. Mound up the soil around the plant until just the top few leaves show above the soil. Two weeks later, hill up the soil again when the plants grow another 20 cm.\"",
"interval": 21,
"isOptional": false
}
]
},
{
"startDate": "06-10",
"endDate": "08-10",
"type": "HARVEST",
"zone": "ZONE_8A",
"group": 0,
"wateringCycle": {
"litersPerSqM": 0,
"interval": null,
"notes": []
},
"taskTemplates": [
{
"name": "Harvest",
"relativeStartDate": 0,
"relativeEndDate": null,
"description": "Once the foliage has wilted and dried completely, harvest on a dry day. Store in a dark and cool location.",
"interval": null,
"isOptional": false
}
]
}
]
},
{
"id": 1,
"name": "Early Carrot",
"description": "Carrot, (Daucus carota), herbaceous, generally biennial plant of the Apiaceae family that produces an edible taproot. Among common varieties root shapes range from globular to long, with lower ends blunt to pointed. Besides the orange-coloured roots, white-, yellow-, and purple-fleshed varieties are known.",
"image": "carrot.jpg",
"lifecycle": [
{
"startDate": "02-20",
"endDate": "03-10",
"zone": "ZONE_8A",
"type": "SOW",
"wateringCycle": {
"litersPerSqM": 15,
"interval": 3,
"notes": []
},
"taskTemplates": [
{
"name": "hilling",
"relativeStartDate": 0,
"relativeEndDate": 0,
"description": "Mound up the soil around the plant until just the top few leaves show above the soil. ",
"interval": null,
"isOptional": false
}
]
},
{
"startDate": "03-10",
"endDate": "05-10",
"zone": "ZONE_8A",
"type": "PLANT",
"wateringCycle": {
"litersPerSqM": 25,
"interval": 3,
"notes": [
"Be careful not to pour water over the leaves, as this will lead to sunburn."
]
},
"taskTemplates": [
{
"name": "hilling",
"relativeStartDate": 0,
"relativeEndDate": null,
"description": "Mound up the soil around the plant until just the top few leaves show above the soil. ",
"interval": 15,
"isOptional": true
}
]
},
{
"startDate": "05-10",
"endDate": "05-20",
"zone": "ZONE_8A",
"type": "HARVEST",
"wateringCycle": {
"litersPerSqM": 0,
"interval": null,
"notes": []
},
"taskTemplates": [
{
"name": "Harvesting",
"relativeStartDate": 0,
"relativeEndDate": 14,
"description": "When the leaves turn to a yellowish brown. Do not harvest earlier. The plant will show when it's ready.",
"interval": null,
"isOptional": false
}
]
}
],
"soil": "sandy to loamy, loose soil, free of stones",
"spacing": "5,35,2.5",
"pests": [
{
"name": "Rot",
"description": "rot, any of several plant diseases, caused by any of hundreds of species of soil-borne bacteria, fungi, and funguslike organisms (Oomycota). Rot diseases are characterized by plant decomposition and putrefaction. The decay may be hard, dry, spongy, watery, mushy, or slimy and may affect any plant part.",
"measures": "less water"
}
]
},
{
"id": 2,
"name": "Summertime Onion",
"description": "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.",
"image": "onion.jpg",
"lifecycle": [
{
"startDate": "03-15",
"endDate": "04-10",
"type": "SOW",
"zone": "ZONE_8A",
"group": 0,
"wateringCycle": {
"litersPerSqM": 15,
"interval": 4,
"notes": [
]
},
"taskTemplates": [
{
"name": "hilling",
"relativeStartDate": 0,
"relativeEndDate": 0,
"description": "Mound up the soil around the plant until just the top few leaves show above the soil. ",
"interval": null,
"isOptional": false
}
]
},
{
"startDate": "04-10",
"endDate": "07-10",
"type": "PLANT",
"zone": "ZONE_8A",
"group": 0,
"wateringCycle": {
"litersPerSqM": 25,
"interval": 3,
"notes": [
""
]
},
"taskTemplates": [
{
"name": "hilling",
"relativeStartDate": 0,
"relativeEndDate": null,
"description": "Mound up the soil around the plant until just the top few leaves show above the soil. ",
"interval": 15,
"isOptional": true
}
]
},
{
"startDate": "07-10",
"endDate": "09-20",
"type": "HARVEST",
"zone": "ZONE_8A",
"group": 0,
"wateringCycle": {
"litersPerSqM": 0,
"interval": null,
"notes": [
]
},
"taskTemplates": [
{
"name": "Harvesting",
"relativeStartDate": 0,
"relativeEndDate": 14,
"description": "When ready for harvest, the leaves on your onion plants will start to flop over. This happens at the \"neck\" of the onion and it signals that the plant has stopped growing and is ready for storage. Onions should be harvested soon thereafter",
"interval": null,
"isOptional": false
}
]
}
],
"soil": "sandy to loamy, loose soil, free of stones",
"spacing": "15,30,2",
"pests": [
{
"name": "Rot",
"description": "rot, any of several plant diseases, caused by any of hundreds of species of soil-borne bacteria, fungi, and funguslike organisms (Oomycota). Rot diseases are characterized by plant decomposition and putrefaction. The decay may be hard, dry, spongy, watery, mushy, or slimy and may affect any plant part.",
"measures": "less water"
}
]
}
]

View File

@ -0,0 +1,50 @@
[
{
"id" : "1",
"name" : "sow plant",
"description": "Plant the seeds/ crops in de bed.",
"startDate" : "01.05.2022",
"endDate" : "01.05.2022",
"interval" : "null"
},
{
"id" : "2",
"name" : "water plant",
"description": "water the plant, so that the soil is wet around the plant.",
"startDate" : "01.05.2022",
"endDate" : "01.09.2022",
"interval" : "2"
},
{
"id" : "3",
"name" : "fertilize plant",
"description": "The fertilizer has to be mixed with water. Then fertilize the plant's soil with the mixture",
"startDate" : "01.06.2022",
"endDate" : "01.08.2022",
"interval" : "28"
},
{
"id" : "4",
"name" : "covering plant",
"description": "Take a big enough coverage for the plants. Cover the whole plant with a bit space between the plant and the coverage",
"startDate" : "15.07.2022",
"endDate" : "15.07.2022",
"interval" : "null"
},
{
"id" : "5",
"name" : "look after plant",
"description": "Look for pest or illness at the leaves of the plant. Check the soil around the plant, if the roots are enough covered with soil",
"startDate" : "01.05.2022",
"endDate" : "01.09.2022",
"interval" : "5"
},
{
"id" : "6",
"name" : "harvest plant",
"description": "Pull the ripe vegetables out from the soil. Clean them with clear, fresh water. ",
"startDate" : "01.09.2022",
"endDate" : "01.09.2022",
"interval" : "null"
}
]