refactor: fixed and simplified dayCellFactory even more

Added method to check if a date is within a GrowthPhaseType to plant, thus removing the need for the ugly getMinDate methods and moving knowledge of the phase-internals to the Plant class.

Also removed the need to specify the lifecycle-group to the sowDateFromHarvest method
This commit is contained in:
David Guler 2022-11-15 22:45:01 +01:00
parent 90d2de65de
commit 9ba252b828
3 changed files with 50 additions and 42 deletions

View File

@ -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.time.MonthDay;
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) {
@ -75,12 +80,10 @@ public class SelectSowDayController {
setDisable(true); setDisable(true);
setStyle("-fx-background-color: #ffc0cb;"); setStyle("-fx-background-color: #ffc0cb;");
if (item.compareTo(today) > 0 && (!harvest_radio.isSelected() || selectedPlant.sowDateFromHarvestDate(item, 0).compareTo(today) >= 0)) { if (item.compareTo(today) > 0 && (!harvest_radio.isSelected() || selectedPlant.sowDateFromHarvestDate(item).compareTo(today) >= 0)) {
GrowthPhaseType selectedPhase = harvest_radio.isSelected() ? GrowthPhaseType.HARVEST : GrowthPhaseType.SOW; GrowthPhaseType selectedPhase = (GrowthPhaseType) phase_group.getSelectedToggle().getUserData();
MonthDay minDate = selectedPlant.getMinDateForGrowthPhase(selectedPhase);
MonthDay maxDate = selectedPlant.getMaxDateForGrowthPhase(selectedPhase);
if (dateInRange(item, minDate, maxDate)) { if (selectedPlant.isDateInPhase(item, selectedPhase)) {
setDisable(false); setDisable(false);
setStyle("-fx-background-color: #32CD32;"); setStyle("-fx-background-color: #32CD32;");
} }
@ -88,22 +91,4 @@ public class SelectSowDayController {
} }
}; };
} }
/**
* Checks if the given {@link LocalDate} is within the given {@link MonthDay} range.
* (regardless of year)
*
* @param subject The date to check
* @param min The start of the date-range
* @param max The end of the date-range
* @return Whether the subject is within the range.
*/
private boolean dateInRange(LocalDate subject, MonthDay min, MonthDay max) {
return subject.getMonth().compareTo(min.getMonth()) >= 0 &&
subject.getMonth().compareTo(max.getMonth()) <= 0 &&
// if the day is less than the minimum day, the minimum month must not be equal
(subject.getDayOfMonth() >= min.getDayOfMonth() || !subject.getMonth().equals(min.getMonth())) &&
// if the day is greater than the maximum day, the maximum month must not be equal
(subject.getDayOfMonth() <= max.getDayOfMonth() || !subject.getMonth().equals(max.getMonth()));
}
} }

View File

@ -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,19 +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) {
return lifecycle.stream()
.filter(growthPhase -> growthPhase.type().equals(GrowthPhaseType.HARVEST) &&
dateInRange(harvestDate, growthPhase.startDate(), growthPhase.endDate()))
.map(GrowthPhase::group)
.findFirst()
.orElse(0);
}
public MonthDay getMaxDateForGrowthPhase(GrowthPhaseType growthPhase) { /**
* Checks if the given {@link LocalDate} is within a {@link GrowthPhase} of the given {@link GrowthPhaseType}
*
* @param date The date to check.
* @param phase The {@link GrowthPhaseType} to match against
* @return Whether the date is within the given {@link GrowthPhaseType}
*/
public boolean isDateInPhase(LocalDate date, GrowthPhaseType phase) {
return lifecycle.stream() return lifecycle.stream()
.filter(phase -> phase.type().equals(growthPhase)) .filter(growthPhase -> growthPhase.type().equals(phase))
.findFirst() .anyMatch(growthPhase -> dateInRange(date, growthPhase.startDate(), growthPhase.endDate()));
.map(GrowthPhase::endDate)
.orElse(MonthDay.of(12, 31));
} }
public MonthDay getMinDateForGrowthPhase(GrowthPhaseType growthPhase) {
return lifecycle.stream() /**
.filter(phase -> phase.type().equals(growthPhase)) * Checks if the given {@link LocalDate} is within the given {@link MonthDay} range.
.findFirst() * (regardless of year)
.map(GrowthPhase::startDate) *
.orElse(MonthDay.of(1, 1)); * @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()));
} }
} }

View File

@ -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" />