diff --git a/bin/models/Flight.class b/bin/models/Flight.class index 807295d..d365ae0 100644 Binary files a/bin/models/Flight.class and b/bin/models/Flight.class differ diff --git a/bin/views/AddFlightScreen.class b/bin/views/AddFlightScreen.class index bd42181..009fef8 100644 Binary files a/bin/views/AddFlightScreen.class and b/bin/views/AddFlightScreen.class differ diff --git a/flights.xml b/flights.xml index 0090274..48806f2 100644 --- a/flights.xml +++ b/flights.xml @@ -8,274 +8,36 @@ 2.0 - ea + 123 - 2 - - - 2 - - - 1 - - - 2 - - - aed - - - - - asd - - - asd - - - - asd - - - ss - - - ddas - - - - sad - - - - asd - - - asd - - - eee - - - - - - - - - - 2.0 - - - asd - - - 11:00 - - 12:00 - - 2 - - - asd - - - asd - - - - - asd - - - asd - - - - asd - - - ss - - - ddas - - - - sad - - - - asd - - - asd - - - eee - - - - - - - - - - 123.0 - - - sad - - - 123 - - 123 - - - 123 - - - 123 - - - asd - - - true - - - - - asd - - - asd - - - - asd - - - ss - - - ddas - - - - sad - - - - asd - - - asd - - - eee - - - - - - - - - - 123.0 - - - asd - - - dsa - - - asda - - - 12 - - - 123 - - - asda - - - - - asdasdasd - - - asdasd - - - - 124312 - - - - asdasd - - - - asd - - - - - - - - - - 1.0 - - - ea - - - 11:00 - - - 12:30 + 14:00 2 + + 2024-06-10 + - lol + asd - test + asdasd - + - asdasdasd + sad - asdasd - - - - 124312 - + ads - asdasd - - - - asd - + sad diff --git a/pilots.xml b/pilots.xml index fca6cd6..efef9b4 100644 --- a/pilots.xml +++ b/pilots.xml @@ -15,6 +15,32 @@ + + + + asdasd + + + asdasd + + + sad + + + + + + + asdasd + + + 23 + + + adsasd + + + diff --git a/src/models/Flight.java b/src/models/Flight.java index c9c96d6..1fd8a10 100644 --- a/src/models/Flight.java +++ b/src/models/Flight.java @@ -11,8 +11,8 @@ import javafx.beans.property.*; public class Flight implements Serializable { private static final long serialVersionUID = 1L; - private transient ObjectProperty datum; - private String datumStr; + private String datumStr; // String zur Speicherung des Datums in XML + private transient ObjectProperty datum; // transient, um die direkte Serialization zu vermeiden private StringProperty muster; private StringProperty abflugort; private StringProperty abflugzeit; @@ -23,6 +23,8 @@ public class Flight implements Serializable { private BooleanProperty nachtflug; private StringProperty kommentar; + private static final DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE; + // Standardkonstruktor public Flight() { this.datum = new SimpleObjectProperty<>(); @@ -38,17 +40,17 @@ public class Flight implements Serializable { } public Flight(LocalDate datum, String muster, String abflugort, String abflugzeit, String ankunftszeit, double tToF, int anzahlLandungen, Pilot pilot, boolean nachtflug, String kommentar) { - this.datum = new SimpleObjectProperty<>(datum); - this.datumStr = datum.format(DateTimeFormatter.ISO_LOCAL_DATE); - this.muster = new SimpleStringProperty(muster); - this.abflugort = new SimpleStringProperty(abflugort); - this.abflugzeit = new SimpleStringProperty(abflugzeit); - this.ankunftszeit = new SimpleStringProperty(ankunftszeit); - this.tToF = new SimpleDoubleProperty(tToF); - this.anzahlLandungen = new SimpleIntegerProperty(anzahlLandungen); - this.pilot = new SimpleObjectProperty<>(pilot); - this.nachtflug = new SimpleBooleanProperty(nachtflug); - this.kommentar = new SimpleStringProperty(kommentar); + this(); + this.setDatum(datum); + this.muster.set(muster); + this.abflugort.set(abflugort); + this.abflugzeit.set(abflugzeit); + this.ankunftszeit.set(ankunftszeit); + this.tToF.set(tToF); + this.anzahlLandungen.set(anzahlLandungen); + this.pilot.set(pilot); + this.nachtflug.set(nachtflug); + this.kommentar.set(kommentar); } public LocalDate getDatum() { @@ -57,13 +59,22 @@ public class Flight implements Serializable { public void setDatum(LocalDate datum) { this.datum.set(datum); - this.datumStr = datum.format(DateTimeFormatter.ISO_LOCAL_DATE); + this.datumStr = datum != null ? datum.format(formatter) : null; } public ObjectProperty datumProperty() { return datum; } + public String getDatumStr() { + return datumStr; + } + + public void setDatumStr(String datumStr) { + this.datumStr = datumStr; + this.datum.set(datumStr != null ? LocalDate.parse(datumStr, formatter) : null); + } + public String getMuster() { return muster.get(); } @@ -180,5 +191,20 @@ public class Flight implements Serializable { return "Keine Pilotinformationen verfügbar"; } - + // Custom Serialization + private void writeObject(ObjectOutputStream oos) throws IOException { + oos.defaultWriteObject(); + oos.writeObject(datum.get() != null ? datum.get().format(formatter) : null); + } + + // Custom Deserialization + private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException { + ois.defaultReadObject(); + String datumStr = (String) ois.readObject(); + if (datumStr != null) { + this.datum = new SimpleObjectProperty<>(LocalDate.parse(datumStr, formatter)); + } else { + this.datum = new SimpleObjectProperty<>(); + } + } } diff --git a/src/views/AddFlightScreen.java b/src/views/AddFlightScreen.java index c8fa81a..b01e383 100644 --- a/src/views/AddFlightScreen.java +++ b/src/views/AddFlightScreen.java @@ -16,11 +16,15 @@ import models.Pilots; import utils.XMLHelper; import java.time.LocalDate; +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; import java.util.ArrayList; import java.util.List; public class AddFlightScreen { private Stage stage; + private DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm"); public AddFlightScreen(Stage stage) { this.stage = stage; @@ -42,25 +46,43 @@ public class AddFlightScreen { datumField.setPromptText("YYYY-MM-DD"); musterField.setPromptText("Muster"); abflugortField.setPromptText("Abflugort"); - abflugzeitField.setPromptText("HH:MM"); - ankunftszeitField.setPromptText("HH:MM"); + abflugzeitField.setPromptText("HH:mm"); + ankunftszeitField.setPromptText("HH:mm"); tToFField.setPromptText("Flugdauer (Stunden)"); anzahlLandungenField.setPromptText("Anzahl der Landungen"); kommentarField.setPromptText("Kommentar"); // Nur numerische Eingaben für Flugdauer und Anzahl der Landungen zulassen - tToFField.textProperty().addListener((observable, oldValue, newValue) -> { - if (!newValue.matches("\\d*\\.?\\d*")) { - tToFField.setText(oldValue); - } - }); - + tToFField.setEditable(false); anzahlLandungenField.textProperty().addListener((observable, oldValue, newValue) -> { if (!newValue.matches("\\d*")) { anzahlLandungenField.setText(oldValue); } }); + // Validierung und Berechnung der Flugdauer + abflugzeitField.focusedProperty().addListener((observable, oldValue, newValue) -> { + if (!newValue) { + if (!isValidTime(abflugzeitField.getText())) { + abflugzeitField.setStyle("-fx-border-color: red;"); + } else { + abflugzeitField.setStyle(null); + calculateFlightDuration(abflugzeitField, ankunftszeitField, tToFField); + } + } + }); + + ankunftszeitField.focusedProperty().addListener((observable, oldValue, newValue) -> { + if (!newValue) { + if (!isValidTime(ankunftszeitField.getText())) { + ankunftszeitField.setStyle("-fx-border-color: red;"); + } else { + ankunftszeitField.setStyle(null); + calculateFlightDuration(abflugzeitField, ankunftszeitField, tToFField); + } + } + }); + // Laden der Piloten für die Auswahlbox Pilots pilotsData = (Pilots) XMLHelper.loadFromXML("pilots.xml"); List pilotList = pilotsData != null ? pilotsData.getPilots() : new ArrayList<>(); @@ -71,8 +93,9 @@ public class AddFlightScreen { Button submitBtn = new Button("Hinzufügen"); submitBtn.setStyle("-fx-background-color: #000000; -fx-text-fill: #FFFFFF; -fx-font-weight: bold;"); - submitBtn.setOnAction(e -> handleAddFlight(datumField, musterField, abflugortField, abflugzeitField, ankunftszeitField, - tToFField, anzahlLandungenField, nachtflugBox.isSelected(), kommentarField, pilotComboBox)); + submitBtn.setOnAction( + e -> handleAddFlight(datumField, musterField, abflugortField, abflugzeitField, ankunftszeitField, + tToFField, anzahlLandungenField, nachtflugBox.isSelected(), kommentarField, pilotComboBox)); Button backButton = new Button("Zurück"); backButton.setStyle("-fx-background-color: #000000; -fx-text-fill: #FFFFFF; -fx-font-weight: bold;"); @@ -104,51 +127,84 @@ public class AddFlightScreen { stage.show(); } - private void handleAddFlight(DatePicker datumField, TextField musterField, TextField abflugortField, TextField abflugzeitField, - TextField ankunftszeitField, TextField tToFField, TextField anzahlLandungenField, boolean isNachtflug, - TextField kommentarField, ComboBox pilotComboBox) { - clearFieldStyles(datumField, musterField, abflugortField, abflugzeitField, ankunftszeitField, tToFField, anzahlLandungenField, pilotComboBox); - + private void calculateFlightDuration(TextField abflugzeitField, TextField ankunftszeitField, TextField tToFField) { try { - if (datumField.getValue() == null) { - setErrorStyle(datumField); - throw new IllegalArgumentException("Datum ist erforderlich."); + LocalTime abflugzeit = LocalTime.parse(abflugzeitField.getText(), timeFormatter); + LocalTime ankunftszeit = LocalTime.parse(ankunftszeitField.getText(), timeFormatter); + long durationInMinutes = java.time.Duration.between(abflugzeit, ankunftszeit).toMinutes(); + if (durationInMinutes < 0) { + durationInMinutes += 24 * 60; // Falls über Mitternacht } - if (musterField.getText().isEmpty()) { - setErrorStyle(musterField); - throw new IllegalArgumentException("Muster ist erforderlich."); - } - if (abflugortField.getText().isEmpty()) { - setErrorStyle(abflugortField); - throw new IllegalArgumentException("Abflugort ist erforderlich."); - } - if (abflugzeitField.getText().isEmpty()) { - setErrorStyle(abflugzeitField); - throw new IllegalArgumentException("Abflugzeit ist erforderlich."); - } - if (ankunftszeitField.getText().isEmpty()) { - setErrorStyle(ankunftszeitField); - throw new IllegalArgumentException("Ankunftszeit ist erforderlich."); - } - if (tToFField.getText().isEmpty()) { - setErrorStyle(tToFField); - throw new IllegalArgumentException("Flugdauer ist erforderlich."); - } - if (anzahlLandungenField.getText().isEmpty()) { - setErrorStyle(anzahlLandungenField); - throw new IllegalArgumentException("Anzahl der Landungen ist erforderlich."); - } - if (pilotComboBox.getValue() == null) { - setErrorStyle(pilotComboBox); - throw new IllegalArgumentException("Pilot ist erforderlich."); + double durationInHours = durationInMinutes / 60.0; + String formattedDuration = String.format("%.2f", durationInHours); + + tToFField.setText(formattedDuration); + } catch (DateTimeParseException e) { + tToFField.setText(""); + } + } + + private boolean isValidTime(String time) { + try { + LocalTime.parse(time, timeFormatter); + return true; + } catch (DateTimeParseException e) { + return false; + } + } + + private void handleAddFlight(DatePicker datumField, TextField musterField, TextField abflugortField, + TextField abflugzeitField, TextField ankunftszeitField, TextField tToFField, + TextField anzahlLandungenField, boolean isNachtflug, TextField kommentarField, + ComboBox pilotComboBox) { + try { + clearFieldStyles(datumField, musterField, abflugortField, abflugzeitField, ankunftszeitField, + tToFField, anzahlLandungenField, kommentarField, pilotComboBox); + + if (datumField.getValue() == null || musterField.getText().isEmpty() || abflugortField.getText().isEmpty() + || + abflugzeitField.getText().isEmpty() || ankunftszeitField.getText().isEmpty() + || tToFField.getText().isEmpty() || + anzahlLandungenField.getText().isEmpty() || pilotComboBox.getValue() == null) { + throw new IllegalArgumentException("Bitte füllen Sie alle Felder aus."); + } + + if (!isValidTime(abflugzeitField.getText())) { + setErrorStyle(abflugzeitField); + throw new IllegalArgumentException("Ungültige Abflugzeit."); + } + + if (!isValidTime(ankunftszeitField.getText())) { + setErrorStyle(ankunftszeitField); + throw new IllegalArgumentException("Ungültige Ankunftszeit."); + } + + System.out.println("Flugdauer vor dem Parsen: " + tToFField.getText()); // Debug-Ausgabe + double flightDuration; + try { + // Ersetzen des Kommas durch einen Punkt + String flightDurationText = tToFField.getText().replace(",", "."); + flightDuration = Double.parseDouble(flightDurationText); + } catch (NumberFormatException e) { + setErrorStyle(tToFField); + throw new IllegalArgumentException("Flugdauer muss eine gültige Zahl sein."); } - double flightDuration = Double.parseDouble(tToFField.getText()); int landings = Integer.parseInt(anzahlLandungenField.getText()); - Flight newFlight = new Flight(datumField.getValue(), musterField.getText(), abflugortField.getText(), - abflugzeitField.getText(), ankunftszeitField.getText(), flightDuration, landings, - pilotComboBox.getValue(), isNachtflug, kommentarField.getText()); + Flight newFlight = new Flight(); + newFlight.setDatum(datumField.getValue()); // Setzen des Datums als LocalDate + newFlight.setMuster(musterField.getText()); + newFlight.setAbflugort(abflugortField.getText()); + newFlight.setAbflugzeit(abflugzeitField.getText()); + newFlight.setAnkunftszeit(ankunftszeitField.getText()); + newFlight.setTToF(flightDuration); + newFlight.setAnzahlLandungen(landings); + newFlight.setPilot(pilotComboBox.getValue()); + newFlight.setNachtflug(isNachtflug); + newFlight.setKommentar(kommentarField.getText()); + newFlight.setDatumStr(datumField.getValue().format(DateTimeFormatter.ISO_LOCAL_DATE)); // Setzen des DatumStr + Flights flights = (Flights) XMLHelper.loadFromXML("flights.xml"); if (flights == null) { @@ -159,7 +215,8 @@ public class AddFlightScreen { new HomeScreen(stage).display(); } catch (NumberFormatException e) { - showAlert("Ungültige Eingabe", "Bitte stellen Sie sicher, dass die Flugdauer und die Anzahl der Landungen numerisch sind."); + showAlert("Ungültige Eingabe", + "Bitte stellen Sie sicher, dass die Flugdauer und die Anzahl der Landungen numerisch sind."); } catch (IllegalArgumentException e) { showAlert("Fehlende Eingabe", e.getMessage()); } catch (Exception e) {