Compare commits
13
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3f02bedd1d | ||
|
|
62fb3869e6 | ||
|
|
3c70c8ac48 | ||
|
|
5229c03fd5 | ||
|
|
6dea42dd1f | ||
|
|
11a1a63345 | ||
|
|
bfe3fcfb79 | ||
|
|
b70a758099 | ||
|
|
3a69119eb7 | ||
|
|
2f69c48800 | ||
|
|
86a9eeaf2e | ||
|
|
9ba252b828 | ||
|
|
90d2de65de |
@@ -93,23 +93,27 @@ 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;
|
||||||
Plant plant = plantList.getPlantById(Settings.getInstance().getCurrentHardinessZone(), crop.getPlantId())
|
try {
|
||||||
.orElseThrow(PlantNotFoundException::new);
|
Plant plant = plantList.getPlantById(Settings.getInstance().getCurrentHardinessZone(), crop.getPlantId())
|
||||||
|
.orElseThrow(PlantNotFoundException::new);
|
||||||
|
|
||||||
cropName_label.setText(plant.name());
|
cropName_label.setText(plant.name());
|
||||||
description_label.setText(plant.description());
|
description_label.setText(plant.description());
|
||||||
light_label.setText(String.valueOf(plant.light()));
|
light_label.setText(String.valueOf(plant.light()));
|
||||||
soil_label.setText(plant.soil());
|
soil_label.setText(plant.soil());
|
||||||
spacing_label.setText(plant.spacing());
|
spacing_label.setText(plant.spacing());
|
||||||
if (plant.image() != null) {
|
if (plant.image() != null) {
|
||||||
imageView.setImage(plant.image());
|
imageView.setImage(plant.image());
|
||||||
|
}
|
||||||
|
area_label.setText("");
|
||||||
|
location_label.setText("");
|
||||||
|
createTaskLists(crop);
|
||||||
|
createPestList(plant);
|
||||||
|
} catch (HardinessZoneNotSetException | IOException e) {
|
||||||
|
throw new PlantNotFoundException();
|
||||||
}
|
}
|
||||||
area_label.setText("");
|
|
||||||
location_label.setText("");
|
|
||||||
createTaskLists(crop);
|
|
||||||
createPestList(plant);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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,22 +83,21 @@ 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 -> {
|
||||||
try {
|
try {
|
||||||
garden.plantAsCrop(selectedPlant, date);
|
garden.plantAsCrop(selectedPlant, date);
|
||||||
} catch (IOException | HardinessZoneNotSetException | PlantNotFoundException e) {
|
} catch (IOException | HardinessZoneNotSetException | PlantNotFoundException e) {
|
||||||
LOG.log(Level.SEVERE, "Couldn't save Crop", e);
|
LOG.log(Level.SEVERE, "Couldn't save Crop", e);
|
||||||
}
|
}
|
||||||
plantsRoot.fireEvent(new ChangeViewEvent(ChangeViewEvent.CHANGE_MAIN_VIEW, "MyGarden.fxml"));
|
plantsRoot.fireEvent(new ChangeViewEvent(ChangeViewEvent.CHANGE_MAIN_VIEW, "MyGarden.fxml"));
|
||||||
});
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ public class JsonCropList implements CropList {
|
|||||||
public JsonCropList(URL dataSource) {
|
public JsonCropList(URL dataSource) {
|
||||||
this.dataSource = dataSource;
|
this.dataSource = dataSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ import java.util.Optional;
|
|||||||
* The reads are cached to minimize file-io operations.
|
* The reads are cached to minimize file-io operations.
|
||||||
*/
|
*/
|
||||||
public class JsonPlantList implements PlantList {
|
public class JsonPlantList implements PlantList {
|
||||||
private final URL dataSource = getClass().getResource("plantdb.json");
|
private final URL dataSource;
|
||||||
|
|
||||||
private HardinessZone currentZone;
|
private HardinessZone currentZone;
|
||||||
private Map<Long, Plant> plantMap = Collections.emptyMap();
|
private Map<Long, Plant> plantMap = Collections.emptyMap();
|
||||||
@@ -44,6 +44,13 @@ public class JsonPlantList implements PlantList {
|
|||||||
imageModule.addDeserializer(Image.class, new PlantImageDeserializer());
|
imageModule.addDeserializer(Image.class, new PlantImageDeserializer());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public JsonPlantList() {
|
||||||
|
this.dataSource = getClass().getResource("plantdb.json");
|
||||||
|
}
|
||||||
|
public JsonPlantList(URL dataSource) {
|
||||||
|
this.dataSource = dataSource;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If no data is currently loaded, or the specified zone differs
|
* If no data is currently loaded, or the specified zone differs
|
||||||
* from the {@link #currentZone}, data is loaded from {@link #dataSource}.
|
* from the {@link #currentZone}, data is loaded from {@link #dataSource}.
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ import java.util.Map;
|
|||||||
*/
|
*/
|
||||||
public class JsonTaskList implements TaskList {
|
public class JsonTaskList implements TaskList {
|
||||||
IdProvider idProvider;
|
IdProvider idProvider;
|
||||||
private final URL dataSource = getClass().getResource("taskdb.json");
|
private final URL dataSource;
|
||||||
private final static String INVALID_DATASOURCE_MSG = "Invalid datasource specified!";
|
private final static String INVALID_DATASOURCE_MSG = "Invalid datasource specified!";
|
||||||
|
|
||||||
private Map<Long, Task> taskMap = Collections.emptyMap();
|
private Map<Long, Task> taskMap = Collections.emptyMap();
|
||||||
@@ -43,6 +43,13 @@ public class JsonTaskList implements TaskList {
|
|||||||
timeModule.addSerializer(LocalDate.class, dateSerializer);
|
timeModule.addSerializer(LocalDate.class, dateSerializer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public JsonTaskList() {
|
||||||
|
this.dataSource = getClass().getResource("taskdb.json");
|
||||||
|
}
|
||||||
|
public JsonTaskList(URL dataSource) {
|
||||||
|
this.dataSource = dataSource;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If no data is currently loaded, data is loaded from {@link #dataSource}.
|
* If no data is currently loaded, data is loaded from {@link #dataSource}.
|
||||||
* In any case, the values of {@link #taskMap} are returned.
|
* In any case, the values of {@link #taskMap} are returned.
|
||||||
@@ -79,7 +86,13 @@ public class JsonTaskList implements TaskList {
|
|||||||
if(taskMap.isEmpty()) {
|
if(taskMap.isEmpty()) {
|
||||||
loadTaskListFromFile();
|
loadTaskListFromFile();
|
||||||
}
|
}
|
||||||
taskMap.values().removeIf(task -> task.getCropId() == cropId);
|
|
||||||
|
List<Task> temptasks = taskMap.values().stream().
|
||||||
|
filter(task -> { return task.getCropId() == cropId;}).toList();
|
||||||
|
for (Task task : temptasks ) {
|
||||||
|
taskMap.remove(task.getId());
|
||||||
|
}
|
||||||
|
writeTaskListToFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -99,6 +112,7 @@ public class JsonTaskList implements TaskList {
|
|||||||
if(task.getId() == 0) {
|
if(task.getId() == 0) {
|
||||||
task.withId(idProvider.incrementAndGet());
|
task.withId(idProvider.incrementAndGet());
|
||||||
}
|
}
|
||||||
|
taskMap.put(task.getId(),task);
|
||||||
writeTaskListToFile();
|
writeTaskListToFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
@@ -42,11 +42,10 @@ public record Plant(
|
|||||||
/**
|
/**
|
||||||
* 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 +68,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);
|
* Checks if the given {@link LocalDate} is within the given {@link MonthDay} range.
|
||||||
}
|
* (regardless of year)
|
||||||
return dates;
|
*
|
||||||
|
* @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" />
|
||||||
|
|||||||
@@ -28,8 +28,8 @@ public class JsonCropListTest {
|
|||||||
/**
|
/**
|
||||||
* Files to isolate the test-units
|
* Files to isolate the test-units
|
||||||
*/
|
*/
|
||||||
private final URL dbDataSource = this.getClass().getResource("user-crops.json");
|
private final URL dbDataSource = this.getClass().getResource("test-user-crops.json");
|
||||||
private final URL testFile = this.getClass().getResource("test-user-crops.json");
|
private final URL testFile = this.getClass().getResource("template-user-crops.json");
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void connectToDb() throws URISyntaxException, IOException {
|
void connectToDb() throws URISyntaxException, IOException {
|
||||||
|
|||||||
@@ -8,17 +8,22 @@ import org.junit.jupiter.api.DisplayName;
|
|||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
|
||||||
public class JsonPlantListTest {
|
public class JsonPlantListTest {
|
||||||
|
private final URL testFile = this.getClass().getResource("test-plantdb.json");
|
||||||
PlantList testDatabase;
|
PlantList testDatabase;
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void connectToDb() {
|
void connectToDb() {
|
||||||
testDatabase = new JsonPlantList();
|
assertNotNull(testFile);
|
||||||
|
testDatabase = new JsonPlantList(testFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -18,27 +18,27 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
|
|||||||
public class JsonTaskListTest {
|
public class JsonTaskListTest {
|
||||||
|
|
||||||
TaskList testDatabase;
|
TaskList testDatabase;
|
||||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy");
|
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
|
||||||
|
|
||||||
private final URL dbDataSource = this.getClass().getResource("taskdb.json");
|
private final URL dbDataSource = this.getClass().getResource("test-taskdb.json");
|
||||||
private final URL testFile = this.getClass().getResource("test-taskdb.json");
|
private final URL testFile = this.getClass().getResource("template-taskdb.json");
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void connectToDb() throws URISyntaxException, IOException {
|
void connectToDb() throws URISyntaxException, IOException {
|
||||||
assertNotNull(testFile);
|
assertNotNull(testFile);
|
||||||
assertNotNull(dbDataSource);
|
assertNotNull(dbDataSource);
|
||||||
Files.copy(Path.of(testFile.toURI()), Path.of(dbDataSource.toURI()), StandardCopyOption.REPLACE_EXISTING);
|
Files.copy(Path.of(testFile.toURI()), Path.of(dbDataSource.toURI()), StandardCopyOption.REPLACE_EXISTING);
|
||||||
testDatabase = new JsonTaskList();
|
testDatabase = new JsonTaskList(dbDataSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("Check if results are retrieved completely")
|
@DisplayName("Check if results are retrieved completely")
|
||||||
void getTasks() {
|
void getTasks() {
|
||||||
|
|
||||||
List<Task> taskList = null;
|
List<Task> taskList;
|
||||||
try {
|
try {
|
||||||
taskList = testDatabase.getTaskList(LocalDate.parse("30.04.2022", formatter),
|
taskList = testDatabase.getTaskList(LocalDate.parse("2022-04-30", formatter),
|
||||||
LocalDate.parse("31.05.2022", formatter));
|
LocalDate.parse("2022-05-31", formatter));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
@@ -47,17 +47,16 @@ public class JsonTaskListTest {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Disabled("disabled until adding works.")
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("Add task.")
|
@DisplayName("Add task.")
|
||||||
void addTask() {
|
void addTask() {
|
||||||
Task task = new Task("Testtask", "This is a test Task.", LocalDate.parse("01.05.2022", formatter), 1);
|
Task task = new Task("Testtask", "This is a test Task.", LocalDate.parse("2022-05-01", formatter), 1);
|
||||||
try {
|
try {
|
||||||
testDatabase.saveTask(task);
|
testDatabase.saveTask(task);
|
||||||
List<Task> taskList = null;
|
List<Task> taskList;
|
||||||
try {
|
try {
|
||||||
taskList = testDatabase.getTaskList(LocalDate.parse("30.04.2022", formatter),
|
taskList = testDatabase.getTaskList(LocalDate.parse("2022-04-30", formatter),
|
||||||
LocalDate.parse("31.05.2022", formatter));
|
LocalDate.parse("2022-05-31", formatter));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
@@ -72,13 +71,13 @@ public class JsonTaskListTest {
|
|||||||
@Test
|
@Test
|
||||||
@DisplayName("Remove task.")
|
@DisplayName("Remove task.")
|
||||||
void removeTask() {
|
void removeTask() {
|
||||||
Task task = new Task("Dummy", "Dummy", LocalDate.parse("31.05.2022", formatter), 1).withId(2);
|
Task task = new Task("Dummy", "Dummy", LocalDate.parse("2022-05-31", formatter), 1).withId(2);
|
||||||
try {
|
try {
|
||||||
testDatabase.removeTask(task);
|
testDatabase.removeTask(task);
|
||||||
List<Task> taskList = null;
|
List<Task> taskList;
|
||||||
|
|
||||||
taskList = testDatabase.getTaskList(LocalDate.parse("30.04.2022", formatter),
|
taskList = testDatabase.getTaskList(LocalDate.parse("2022-04-30", formatter),
|
||||||
LocalDate.parse("31.05.2022", formatter));
|
LocalDate.parse("2022-05-31", formatter));
|
||||||
|
|
||||||
Assertions.assertEquals(2, taskList.size());
|
Assertions.assertEquals(2, taskList.size());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
@@ -90,7 +89,7 @@ public class JsonTaskListTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void getTaskForCrop() {
|
void getTaskForCrop() {
|
||||||
List<Task> taskList = null;
|
List<Task> taskList;
|
||||||
try {
|
try {
|
||||||
taskList = testDatabase.getTaskForCrop(0);
|
taskList = testDatabase.getTaskForCrop(0);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
@@ -101,10 +100,9 @@ public class JsonTaskListTest {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Disabled("Disabled until removing works")
|
|
||||||
@Test
|
@Test
|
||||||
void removeTasksForCrop() {
|
void removeTasksForCrop() {
|
||||||
List<Task> taskList = null;
|
List<Task> taskList;
|
||||||
try {
|
try {
|
||||||
testDatabase.removeTasksForCrop(0);
|
testDatabase.removeTasksForCrop(0);
|
||||||
taskList = testDatabase.getTaskForCrop(0);
|
taskList = testDatabase.getTaskForCrop(0);
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
|
|||||||
import static org.mockito.Mockito.*;
|
import static org.mockito.Mockito.*;
|
||||||
|
|
||||||
public class GardenPlanModelTest {
|
public class GardenPlanModelTest {
|
||||||
private final URL dbDataSource = JsonCropList.class.getResource("user-crops.json");
|
private final URL dbDataSource = JsonCropListTest.class.getResource("test-user-crops.json");
|
||||||
private final URL testFile = JsonCropList.class.getResource("test-user-crops.json");
|
private final URL testFile = JsonCropListTest.class.getResource("template-user-crops.json");
|
||||||
|
|
||||||
CropList cropList;
|
CropList cropList;
|
||||||
List<Crop> exampleCrops;
|
List<Crop> exampleCrops;
|
||||||
|
|||||||
@@ -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"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
+6
-6
@@ -1,11 +1,11 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"id" : 1,
|
"id" : 1,
|
||||||
"name" : "sow plant",
|
"name" : "sow plant",
|
||||||
"description": "Plant the seeds, crops in de bed.",
|
"description": "Plant the seeds, crops in de bed.",
|
||||||
"startDate" : "2022-05-01",
|
"startDate" : "2022-05-01",
|
||||||
"endDate" : "2022-05-01",
|
"endDate" : "2022-05-01",
|
||||||
"interval" : 0,
|
"interval" : 0,
|
||||||
"cropId" : 0
|
"cropId" : 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"cropId": 0,
|
||||||
|
"plantId": 1,
|
||||||
|
"startDate": "2023-02-25",
|
||||||
|
"area": 0.5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cropId": 1,
|
||||||
|
"plantId": 1,
|
||||||
|
"startDate": "2023-03-01",
|
||||||
|
"area": 0.5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cropId": 2,
|
||||||
|
"plantId": 0,
|
||||||
|
"startDate": "2023-03-25",
|
||||||
|
"area": 1.5
|
||||||
|
}
|
||||||
|
]
|
||||||
+5
-2
@@ -31,7 +31,7 @@
|
|||||||
"name": "Germinate",
|
"name": "Germinate",
|
||||||
"relativeStartDate": -14,
|
"relativeStartDate": -14,
|
||||||
"relativeEndDate": null,
|
"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.\"",
|
"description": "Take an egg carton and fill it with soil. Put the seedling deep enough so its half covered with soil. Keep it in 10-15 * Celsius with lots of light.",
|
||||||
"interval": null,
|
"interval": null,
|
||||||
"isOptional": false
|
"isOptional": false
|
||||||
}
|
}
|
||||||
@@ -53,7 +53,7 @@
|
|||||||
"name": "hilling",
|
"name": "hilling",
|
||||||
"relativeStartDate": 0,
|
"relativeStartDate": 0,
|
||||||
"relativeEndDate": null,
|
"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.\"",
|
"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,
|
"interval": 21,
|
||||||
"isOptional": false
|
"isOptional": false
|
||||||
}
|
}
|
||||||
@@ -94,6 +94,7 @@
|
|||||||
"endDate": "03-10",
|
"endDate": "03-10",
|
||||||
"zone": "ZONE_8A",
|
"zone": "ZONE_8A",
|
||||||
"type": "SOW",
|
"type": "SOW",
|
||||||
|
"group": 0,
|
||||||
"wateringCycle": {
|
"wateringCycle": {
|
||||||
"litersPerSqM": 15,
|
"litersPerSqM": 15,
|
||||||
"interval": 3,
|
"interval": 3,
|
||||||
@@ -115,6 +116,7 @@
|
|||||||
"endDate": "05-10",
|
"endDate": "05-10",
|
||||||
"zone": "ZONE_8A",
|
"zone": "ZONE_8A",
|
||||||
"type": "PLANT",
|
"type": "PLANT",
|
||||||
|
"group": 0,
|
||||||
"wateringCycle": {
|
"wateringCycle": {
|
||||||
"litersPerSqM": 25,
|
"litersPerSqM": 25,
|
||||||
"interval": 3,
|
"interval": 3,
|
||||||
@@ -138,6 +140,7 @@
|
|||||||
"endDate": "05-20",
|
"endDate": "05-20",
|
||||||
"zone": "ZONE_8A",
|
"zone": "ZONE_8A",
|
||||||
"type": "HARVEST",
|
"type": "HARVEST",
|
||||||
|
"group": 0,
|
||||||
"wateringCycle": {
|
"wateringCycle": {
|
||||||
"litersPerSqM": 0,
|
"litersPerSqM": 0,
|
||||||
"interval": null,
|
"interval": null,
|
||||||
@@ -1,56 +1,2 @@
|
|||||||
[
|
[
|
||||||
{
|
|
||||||
"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
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
@@ -1,20 +1,2 @@
|
|||||||
[
|
[
|
||||||
{
|
|
||||||
"cropId": 0,
|
|
||||||
"plantId": 1,
|
|
||||||
"startDate": "2023-02-25",
|
|
||||||
"area": 0.5
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cropId": 1,
|
|
||||||
"plantId": 1,
|
|
||||||
"startDate": "2023-03-01",
|
|
||||||
"area": 0.5
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cropId": 2,
|
|
||||||
"plantId": 0,
|
|
||||||
"startDate": "2023-03-25",
|
|
||||||
"area": 1.5
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
[
|
|
||||||
]
|
|
||||||
Reference in New Issue
Block a user