Tipp für Aufgabe

javac-

Mitglied
Guten Abend,

ich brauche bei einer Aufgabe Hilfe, da ich nicht recht weiß wie ich anfangen soll. Es geht um eine Hotelbuchungssoftware.(Natürlich nur für Übungszwecke)

In einem Hotel gibt es 8 Standart-, 5 Luxus- und 3 Businesszimmer

1)Ich soll eine Methode schreiben die überprüft ob die gewünschte Zimmerkategorie die der Kunde angefragt hat für den Zeitraum verfügbar ist. Der Kunde gibt ein Anreise und ein Abreisedatum an.

Hier weiss ich nicht so recht wie ich vorgehen soll bzw. wie ich eine Zimmerkategorie für einen Zeitraum als nicht verfügbar deklarieren kann bzw. einen Kunden zuweisen kann.

2) Wenn man mehr als 3 Tage ein Zimmer bucht, bekommt man 5 Euro Rabat pro Tag
Auch hier wieder das Problem, dass ich nicht weiss wie ich das mit dem Zeitraum hinbekomme.


Der GregorianCalendar ist mir bekannt und auch dass ich dort ein Anfags- bzw. Enddatum setzen kann, aber nicht wie ich mit Hilfe dessen testen kann ob in diesem Zeitraum etwas frei. Kann man das vl. irgendwie mit einer boolischen Variablen kombinieren, die jeden freien Tag auf ture und jeden gebuchten auf false setzt?

Danke für die Mühe
Gruß
 
Zuletzt bearbeitet:
Nur als Denkanstöße:

- nimm lieber die neue Date-API, zb LocalDate
- Jedes Zimmer hat mehrere Buchungen, diese haben jeweils ein Start- und ein Enddatum
- damit ein Zimmer verfügbar ist, darf kein Buchungs-Start- oder Enddatum zwischen dem Start- und Enddatum liegen, welche angefragt werden
- das zweite Problem kannst du genauso wie das Erste zB mit einer Klasse Buchung lösen
 
die habe ich auch gefunden, nur finde ich nicht den richtigen Algrorithmus dafür. Ich habe jetzt z.B. ein Array mit Zwei Buchungen, die jeweils ein Anfangs und EndDatum haben. Ich will nun prüfen ob das Zimmer durch eine 3. Anfrage frei ist.

1.Buchung vom 01-07.04.2016
2.Buchung vom 08-15.04.2016

3. Buchung = Anfrage vom 14.-20.04.2016

olgende Methode (in der Klasse Zimmer) soll prüfen ob das Anfragedatum frei ist




Java:
public boolean isVerfügbar(Buchung b1) {

 
     for(Buchung c : this.arr){   //arr ist das Array mit den 2 vorh. Buchungen
    
     //Es gibt ja 2. Fälle die zu einem True-Erg. führen, entweder das zu vergl.
     //Datum liegt komplett vor dem angefragtem oder das
    //zu vergl. Datum liegt komplett hinter dem angefragtem, ansonsten
    //überschneiden sie sich ja, da wollte ich mit folgender if-Bedingung ausdrücken
    //der erste Teil bis zum || sollte prüfen ob das komp. Datum danach liegt
    // und der Teil danach ob das komplette Datum davor liegt
    // nur funktionierts nicht so wie ich mir das vorstelle

       if((b1.getStart().after(c.getStart()) && b1.getStart().after(c.getEnd()) &&b1.getEnd().after(c.getStart()) && b1.getEnd().after(c.getEnd()))
         || (b1.getStart().before(c.getStart()) && b1.getStart().before(c.getEnd()) && b1.getEnd().before(c.getStart()) && b1.getEnd().before(c.getEnd()))){
     
         return true;
       }
   
     }
 
     return false;
   }

Die Methode sollte eig. false liefern, da sich die 2. und 3. Buchung überschneiden, ich erhalte aber true
Das Problem ist, da der erste Teil der if-Bedingung schon wahr ist liefert er mir ein True
 
Zuletzt bearbeitet:
Ich glaube jetzt habe ich es. Mit mehreren versch. Daten kam das richtige Erg.

Java:
public boolean isVerfügbar(Buchung b1) {

    
     for(Buchung c : this.arr){
      
       if(!(b1.getStart().after(c.getStart()) && b1.getStart().after(c.getEnd()) &&b1.getEnd().after(c.getStart()) && b1.getEnd().after(c.getEnd()))
        && !(b1.getStart().before(c.getStart()) && b1.getStart().before(c.getEnd()) && b1.getEnd().before(c.getStart()) && b1.getEnd().before(c.getEnd()))){
        
         return false;
        
        
       }
      
     }
    
     return true;
   }

kann aber auch einfach sein, dass ich schon zu lange davor sitze. Schau mir das morgen nochmal an
 
Wann ist eine Buchung verfügbar? Wenn der Start- und der Endtag nicht in einem Intervall eines anderen liegt oder? (Wenn das Enddatum inklusive ist)
Java:
public boolean isAvailable(Buchung b) {
  for (Buchung buchung : buchungen) {
    LocalDate start = buchung.getStart();
    LocalDate end = buchung.getEnd();
    if (isBetween(start, end, b.getStart()) && isBetween(start, end, b.getEnd()) && !isBetween(b.getStart(), b.getEnd(), start)) {
      return false;
    }
  }
  return true;
}

private static boolean isBetween(LocalDate start, LocalDate end, LocalDate date) {
  return start.compareTo(date) <= 0 && end.compareTo(date) >= 0;
}
 
Zuletzt bearbeitet:
damit ein Zimmer verfügbar ist, darf kein Buchungs-Start- oder Enddatum zwischen dem Start- und Enddatum liegen, welche angefragt werde
Ich glaube, das ist nicht ganz korrekt, denn wenn der bereits gebuchte Zeitraum vor dem angefragten Zeitraum beginnt und danach endet, würde das Zimmer als frei gelten.
Mir scheint es am einfachsten zu sein, zu prüfen, ob Endedatum1 vor Beginndatum2 oder Endedatum2 vor Beginndatum1 liegt. Wenn eine der Bedingungen zutrifft, ist das Zimmer frei.
 
Ich habe die Logik noch mal von "isBetween" auf "overlaps" umgestellt, weil mir das etwas geradliniger erscheint.
Java:
    public static boolean isAvailable(Buchung anfrage) {
        for (Buchung buchung : buchungen) {
            if (overlaps(anfrage, buchung)) {
                return false;
            }
        }
        return true;
    }
  
    private static boolean overlaps(Buchung b1, Buchung b2) {
        return b1.getEnd().isAfter(b2.getStart()) && b2.getEnd().isAfter(b1.getStart());
    }
 
Sehr schöne @Meniskusschaden aber ist das auch korrekt.

Aber das Beispiel ist dennoch hervorragend um für TDD zu werben.

Schreibe doch einfach mal Tests! Es gibt folgende Fälle, wenn ich keinen übersehen habe und eine Buchung korrekt ist.
• Anfrage Ende vor Buchung Start
• Anfrage Ende == Buchung Start
• Anfrage Start == Buchung Start und Anfrage Ende vor Buchung Ende
• Anfrage Start == Buchung Start und Anfrage Ende == Buchung Ende
• Anfrage Start == Buchung Start und Anfrage Ende nach Buchung Ende
• Anfrage Start nach Buchung Start und Anfrage Ende vor Buchung Ende
• Anfrage Start nach Buchung Start und Anfrage Ende == Buchung Ende
• Anfrage Start nach Buchung Start und Anfrage Ende nach Buchung Ende
• Anfrage Start == Buchungs Ende
• Anfrage Start nach Buchung Ende

Oder zumindest mal auf dem Papier was dabei herauskommen soll
 
Aber das Beispiel ist dennoch hervorragend um für TDD zu werben.
Ja, das stimmt, aber für echtes TDD hätte ich die Tests ja eigentlich vorher schreiben müssen und ich bin viel zu ehrlich, um TDD vorzutäuschen (übersetzt: zu faul)😀.

Ich finde die Überlappungsbedingung aus meinem Beispiel beim ersten Betrachten übrigens nicht so anschaulich. Hier ist sie noch einmal:
Java:
b1.getEnd().isAfter(b2.getStart()) && b2.getEnd().isAfter(b1.getStart())
Folgende Bedingung wäre dagegen intuitiv relativ schnell verständlich (so hatte ich es in meinem ersten Posting verbal formuliert):
Java:
!(b1.getEnd().isBeforeOrEqual(b2.getStart()) || b2.getEnd().isBeforeOrEqual(b1.getStart()))
Leider enthält LocalDate keine Methode isBeforeOrEqual(), so dass ich es zunächst zu folgender Bedingung umgeformt habe (compareTo finde ich immer etwas verwirrend):
Java:
!(!b1.getEnd().isAfter(b2.getStart()) || !b2.getEnd().isAfter(b1.getStart()))
Das habe ich dann schließlich zum bereits geposteten Ausdruck vereinfacht. Da mein ursprünglicher Ausdruck relativ leicht verständlich ist und die Umformungen ohne Nachdenken schematisch durchgeführt werden können, bin ich sehr zuversichtlich, aber nicht absolut sicher, dass es korrekt ist. Nach genauerer Betrachtung finde ich auch den endgültigen Ausdruck plausibel, aber ich glaube nicht, dass ich so schnell direkt darauf gekommen wäre.
 
@Meniskusschaden du kannst bei Localdate einfach LocalDate::compareTo verwenden, dann hast du dein <= oder >=.
Ja, das stimmt. Bei compareTo wird mir aber immer schwindelig, weil ich beim Vergleich mit 0 dauernd verdrehe, welcher Wert nun kleiner als welcher ist (hoffentlich ist das keine neurale Dysfunktion🙁). Deshalb hatte ich oben schon folgendes angemerkt:😉
(compareTo finde ich immer etwas verwirrend)
 
also ich habe jetzt mal meinen Code aus post #6 mit allen möglichen Konstellationen die mir eingefallen sind getestet und es kam immer das Richtige heraus.
Falls jemand ein Gegenbeispiel findet bzw. die Richtigkeit bestätigen kann bin ich sehr dankbar.
Java:
public boolean isVerfügbar(Buchung b1) {


     for(Buchung c : this.arr){
  
      //Wenn der Zeitraum der Anfrage (hier b1) nicht komplett nach dem
      // schon gebuchten Zeitraum c und auch nicht komplett vor dem schon
      //gebuchten Zeitraum c ist, dann müssen sie sich irgendwo überlappen
      //und somit false liefern
       if(!(b1.getStart().after(c.getStart()) && b1.getStart().after(c.getEnd()) &&b1.getEnd().after(c.getStart()) && b1.getEnd().after(c.getEnd()))
        && !(b1.getStart().before(c.getStart()) && b1.getStart().before(c.getEnd()) && b1.getEnd().before(c.getStart()) && b1.getEnd().before(c.getEnd()))){
   
         return false;
   
   
       }
 
     }
     //ansonsten überlappen sie sich nirgends und es wird true geliefert
     return true;
   }

Gruß
 
Zuletzt bearbeitet:
Die Bedingung ist schon ziemlich komplex und schwer zu lesen. Deshalb bin ich nicht sicher, ob meine Vermutung stimmt, dass das Ergebnis falsch ist, falls Abreise eines Gastes und Anreise des nächsten Gastes am selben Tag sind. Das ist in der Praxis ja möglich.

Was macht dein Programm bei folgendem Beispiel: Gast1 hat vom 01.05.2016 bis zum 31.05.2016 gebucht. Gast2 fragt für den Zeitraum vom 25.04.2016 bis 01.05.2016 an und Gast3 für den Zeitraum vom 31.05.2016 bis 01.06.2016. Eigentlich müssten doch beiden Anfragen zugesagt werden können. Mein Verdacht ist, dass dein Programm beiden Anfragen absagt.
 
ja die werden abgesagt, daran hab ich gar nicht gedacht...das könnte man aber doch beheben, indem man zu den start bzw. end Zeiten des Anfragezeitraums noch ein || .quals() hängt.
Also z.B. (...isbefore(c.getstart()) || ...isquals(c.getstart()))
wird dann halt noch um einiges unübersichtlicher als es onehin schon ist.
 
so jetzt habe ich das Problem auch gelöst durch 2. mal einfügen von ||.equals
Nun werden auch Daten die sich nur am selben Tag überlappen als true dargestellt.

Wenn sich der Startzeitpunkt des Anfragezeitraums mit dem Endzeitpunkt gleicht oder wenn der Endzeitpunkt des Anfragezeitraums mit dem Anfangszeitpunkt gleicht
Java:
if(!(b1.getStart().after(c.getStart()) && (b1.getStart().after(c.getEnd())|| b1.getStart().equals(c.getEnd())) &&b1.getEnd().after(c.getStart()) && b1.getEnd().after(c.getEnd()))
        && !(b1.getStart().before(c.getStart()) && b1.getStart().before(c.getEnd()) && (b1.getEnd().before(c.getStart())||b1.getEnd().equals(c.getStart()) ) && b1.getEnd().before(c.getEnd()))){

Vielen Dank für deinen Hinweis darauf ;-)
 
Ich glaube, bei meinem Beispiel aus Post#16 würde Gast2 jetzt zwar eine Zusage bekommen, Gast3 aber nicht. Das war jetzt ein schnell umgebauter Test für meine Posts von vorgestern. Kann also auch sein, dass ich beim Umbauen einen Fehler gemacht habe, aber ich würde den Fall lieber noch einmal testen.
 

Zurück
Oben