import java.io.*;
import java.awt.*;
import java.awt.event.*;

abstract class Hotel {

  Zimmer z1 = new Zimmer("z1", 1,  90);
  Zimmer z2 = new Zimmer("z2", 1,  90);
  Zimmer z3 = new Zimmer("z3", 2, 150);
  Zimmer z4 = new Zimmer("z4", 2, 150);
  Zimmer z5 = new Zimmer("z5", 3, 210);

  Gast g1 = new Gast("g1", "Alexander Bierseidler",    "Bonn");
  Gast g2 = new Gast("g2", "Corinna und Carl Cosinus", "Hildesheim");

  Belegung b1 = new Belegung(g1, z2, "19.05.00", 2);
  Belegung b2 = new Belegung(g2, z4, "23.06.00", 7);

  Zimmer[]   zimmerliste  = {null, z1, z2, z3, z4, z5};
  Gast[]     gästeliste = new Gast[10];
  Belegung[] belegungsliste = new Belegung[20];

  Zimmer[] holeZimmer()
    {return zimmerliste;}

  Gast[] holeGäste()
    {return gästeliste;}

  void setzGast (int index, Gast g)
    {gästeliste[index] = g;}

  Belegung[] holeBelegungen()
    {return belegungsliste;}

  void setzBelegung (int index, Belegung b)
    {belegungsliste[index] = b;}

  void initialisiere() {
    for (int i = 0; i < gästeliste.length; ++i)
      setzGast(i, null);
    for (int i = 0; i < belegungsliste.length; ++i)
      setzBelegung(i, null);
    setzGast(1, g1);
    setzGast(2, g2);
    setzBelegung(1, b1);
    setzBelegung(2, b2);
    } // Ende initialisiere

  abstract void zeigeZimmer();

  abstract void zeigeGäste();

  Zimmer sucheZimmer (String nummer) {
    Zimmer  zimmer = null;
    boolean gefunden = false;
    for (int i = 1; i < zimmerliste.length; ++i) {
      zimmer = zimmerliste[i];
      if (nummer.equals(zimmer.Nummer()))
        {gefunden = true; break;}
      } // Ende for
    if (gefunden) return zimmer; else return null;
    } // Ende suche Zimmer

  Gast sucheGast (String nummer) {
    Gast    gast = null;
    boolean gefunden = false;
    for (int i = 1; i < gästeliste.length; ++i) {
      gast = gästeliste[i];
      if (gast != null && nummer.equals(gast.Nummer()))
        {gefunden = true; break;}
      } // Ende for
    if (gefunden) return gast; else return null;
    } // Ende suche Gast

  Belegung sucheBelegung (String zimmernummer) {
    Belegung b = null;
    boolean  gefunden = false;
    for (int i = 1; i < belegungsliste.length; ++i) {
      b = belegungsliste[i];
      if (b != null && zimmernummer.equals(b.Zimmernummer())) 
        {gefunden = true; break;}
      } // Ende for
    if (gefunden) return b; else return null;
    } // Ende suche Belegung

  Belegung findeBelegung (String gastnummer) {
    Belegung b = null;
    boolean  gefunden = false;
    for (int i = 1; i < belegungsliste.length; ++i) {
      b = belegungsliste[i];
      if (b != null && gastnummer.equals(b.Gastnummer())) 
        {gefunden = true; break;}
      } // Ende for
    if (gefunden) return b; else return null;
    } // Ende finde Belegung

  void streicheGast (String nummer) {
    int  i = 0;
    Gast g = null;
    boolean gefunden = false;
    for (i = 1; i < gästeliste.length; ++i) {
      g = holeGäste()[i];
      if (g != null && nummer.equals(g.Nummer()))
        {gefunden = true; break;}
      } // Ende for
    if (gefunden) setzGast(i, null); 
    } // Ende streiche Gast

  void einfügeGast (Gast g) {
    for (int i = 1; i < gästeliste.length; ++i)
      if (gästeliste[i] == null) 
        {setzGast(i, g); break;}
    } // Ende einfüge Gast

  void streicheBelegung (String gastnummer) {
    int     i = 0;
    boolean gefunden = false;
    for (i = 1; i < belegungsliste.length; ++i)
      if (gastnummer.equals(belegungsliste[i].Gastnummer()))
        {gefunden = true; break;}
    if (gefunden) setzBelegung(i, null);
    } // Ende streiche Belegung

  void einfügeBelegung (Belegung b) {
    for (int i = 1; i < belegungsliste.length; ++i)
      if (belegungsliste[i] == null) 
        {setzBelegung(i, b); break;}
    } // Ende einfüge Belegung

  abstract Gast erzeugeGast();

  abstract void belegeZimmer();

  abstract void ausbucheGast();

  int Rechnungsbetrag (Gast g) {
    Belegung b = findeBelegung(g.Nummer());
    Zimmer z = sucheZimmer(b.Zimmernummer());
    int betrag = b.Nächtezahl()* z.Preis();
    return betrag;
    } // Ende Rechnungsbetrag

  abstract void anzeige();

  } // Ende Hotel


class HotelTF extends Hotel {
  // Benutzerschnittstelle als TextFenster (TF)

  InputStreamReader lies = new InputStreamReader(System.in);
  BufferedReader    eing = new BufferedReader(lies);

  String  zimmernummer;
  Zimmer  zimmerAktuell;
  Gast    gastAktuell;
  boolean belegt = false;

  void zeigeZimmer() {
    System.out.println();
    System.out.println("Alle Zimmer:\n");
    for (int i = 1; i < holeZimmer().length; ++i)
      System.out.println(holeZimmer()[i].Beschreibung());
    } // Ende zeige alle Zimmer
    
  void zeigeGäste() {
    boolean leer = true;
    System.out.println();
    System.out.println("Alle derzeit im Hotel logierenden Gäste:\n");
    for (int i = 1; i < holeGäste().length; ++i) {
      Gast g = holeGäste()[i];
      if (g != null) {
        leer = false;
        Belegung b = findeBelegung(g.Nummer());
        System.out.println(g.Beschreibung() + " in Zimmer " +
                           b.Zimmernummer());
        } // Ende if
      } // Ende for
      if (leer) System.out.println("Das Hotel hat leider keine Gäste.");
    } // Ende zeige alle Gäste

  Gast erzeugeGast() {
    Gast neuGast = null;
    System.out.println("\nRegistrierung eines neuen Gastes:");
    try {
      System.out.println();
      System.out.print("Vorname, Familienname: ");
      String name = eing.readLine();
      System.out.print("Anschrift (Wohnort):   ");
      String anschrift = eing.readLine();
      System.out.print("Gastnummer (z. B. g3): ");
      String nummer = eing.readLine();
      neuGast = new Gast(nummer, name, anschrift);
      einfügeGast(neuGast);
      System.out.println(name + " als neuer Gast registriert");
      } // Ende try
    catch(IOException e) {}
    return neuGast;
    } // Ende erzeuge Gast

  void belegeZimmer() {

    Gast     gast = null;
    Zimmer   zimmer = null;
    String   zimmernummer = "";
    Belegung belegung;

    gast = erzeugeGast();
    System.out.println(gast.Beschreibung());
    try {
      System.out.print("Zimmernummer (z. B. z2): ");
      zimmernummer = eing.readLine();
      zimmer = sucheZimmer(zimmernummer);
      if (zimmer == null)
        System.out.println("Dieses Zimmer existiert nicht");
      else {
        System.out.println(zimmer.Beschreibung());
        belegung = sucheBelegung(zimmernummer);
        if (belegung == null) {
          System.out.println("Das Zimmer ist frei");
          System.out.print("Anreisetag (z. B. 25.05.00): ");
          String d1 = eing.readLine();
          einfügeBelegung(new Belegung(gast, zimmer, d1, 3));
          System.out.println("Zimmerbelegung erfolgt");
          } // Ende if
        else {
          System.out.print("Das Zimmer ist bereits von ");
          System.out.println(belegung.Gastname() + " belegt");
          } // Ende else 
        } // Ende else
      } // Ende try
    catch(IOException e){}
    } // Ende belege Zimmer

  void ausbucheGast() {
    System.out.println("\nAusbuchen eines Gastes:");
    try {
      System.out.println();
      System.out.print("Gastnummer (z. B. g2): ");
      String nummer = eing.readLine();
      Gast gast = sucheGast(nummer);
      if (gast == null)
        System.out.println("Falsche Gastnummer!");
      else {
        System.out.println("Zu zahlen: " + Rechnungsbetrag(gast) 
                                         + " Euro");
        System.out.print(gast.Beschreibung());
        streicheGast(nummer);
        streicheBelegung(gast.Nummer());
        System.out.println(" ist (bzw. sind) ausgebucht");
        } // Ende else
      } // Ende try
    catch(IOException e){}
    } // Ende ausbuche Gast

  void anzeige() {   
    System.out.println("\nHotelverwaltung");
    System.out.println("---------------\n");
    while(true) try {
      System.out.println();
      System.out.println("Z(immer G(äste B(uchen A(usbuchen E(nde");
      System.out.print("Wählen Sie! ");
      String taste = eing.readLine();
      if (taste.equals("e"))
        break;
      else if (taste.equals("z"))
        zeigeZimmer();
      else if (taste.equals("g"))
        zeigeGäste();
      else if (taste.equals("b"))
        belegeZimmer();
      else
        ausbucheGast();
      } // Ende try
    catch(IOException e) {}
    } // Ende anzeige

  static void main (String[] xy) {
    Hotel h = new HotelTF();
    h.initialisiere();
    h.anzeige();
    } // Ende main

  } // Ende HotelTF


class HotelGO extends Hotel implements ActionListener {
  // Benutzerschnittstelle als grafische Oberfläche (GO)

  Frame     fenster;
  Button    knopf1, knopf2, knopf3, knopf4,
            knopf5, knopf6, knopf7, knopf8;
  TextField feld1, feld2, feld3;
  TextArea  textbereich;
  boolean   eingabe1Vorbereitet = false;
  boolean   eingabe2Vorbereitet = false;

  HotelGO() {

    fenster = new Frame();
    fenster.setTitle("Hotelverwaltung");
    fenster.setLayout(new BorderLayout());

    Panel p1 = new Panel();
      p1.setLayout(new FlowLayout());
      knopf1 = new Button("ZIMMER");
      knopf1.addActionListener(this);
      p1.add(knopf1);
      knopf2 = new Button("GÄSTE");
      knopf2.addActionListener(this);
      p1.add(knopf2);
      knopf3 = new Button("BUCHEN");
      knopf3.addActionListener(this);
      p1.add(knopf3);
      knopf4 = new Button("JA");
      knopf4.addActionListener(this);
      p1.add(knopf4);
      knopf5 = new Button("AUSBUCHEN");
      knopf5.addActionListener(this);
      p1.add(knopf5);
      knopf6 = new Button("JA");
      knopf6.addActionListener(this);
      p1.add(knopf6);
      knopf7 = new Button("SPEICHERN");
      knopf7.addActionListener(this);
      p1.add(knopf7);
      knopf8 = new Button("LADEN");
      knopf8.addActionListener(this);
      p1.add(knopf8);
      fenster.add("North", p1);

    Panel p2 = new Panel();
      p2.setLayout(new GridLayout(4, 2));
      p2.add(new Label("       Name des Gastes"));
      feld1 = new TextField(8);
      feld1.setEditable(false);
      feld1.addActionListener(this);
      p2.add(feld1);
      p2.add(new Label("       Wohnort"));
      feld2 = new TextField(8);
      feld2.setEditable(false);
      feld2.addActionListener(this);
      p2.add(feld2);
      p2.add(new Label("       Gastnummer"));
      feld3 = new TextField(4);
      feld3.setEditable(false);
      feld3.addActionListener(this);
      p2.add(feld3);
      fenster.add("Center", p2);

    Panel p3 = new Panel();
      textbereich = new TextArea("", 12, 58,
                        TextArea.SCROLLBARS_VERTICAL_ONLY);
      textbereich.setEditable(false);
      textbereich.setForeground(new Color(0));
      p3.add(textbereich);
      fenster.add("South", p3);

    } // Ende Konstruktor HotelGO

  void anzeige() {
    fenster.setSize(600, 400);
    fenster.setLocation(100, 100);
    fenster.setBackground(Color.pink);
    fenster.setVisible(true);
    fenster.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e)
        {System.exit(0);}});
    } // Ende anzeige

  public void actionPerformed (ActionEvent e) {
    Object ereignisquelle = e.getSource();
    if (ereignisquelle == knopf1)
      zeigeZimmer();
    else if (ereignisquelle == knopf2)
      zeigeGäste();
    else if (ereignisquelle == knopf3)
      vorbereiteEingabe1();
    else if (ereignisquelle == knopf4)
      belegeZimmer();
    else if (ereignisquelle == knopf5) 
      vorbereiteEingabe2();
    else if (ereignisquelle == knopf6)
      ausbucheGast();
    else if (ereignisquelle == knopf7)
      speichereDaten();
    else if (ereignisquelle == knopf8)
      ladeDaten();
    } // Ende actionPerformed

  void zeigeZimmer() {
    textbereich.setText("");
    textbereich.append("Alle im Hotel verfügbaren Zimmer:\n");
    for (int i = 1; i < holeZimmer().length; ++i)
      textbereich.append(holeZimmer()[i].Beschreibung() + "\n");
    } // Ende zeige Zimmer

  void zeigeGäste() {
    boolean leer = true;
    for (int i = 1; i < holeGäste().length; ++i)
      if (holeGäste()[i] != null) 
        {leer = false; break;}
    textbereich.setText("");
    if (leer) 
      textbereich.append("Das Hotel hat derzeit keine Gäste (mehr)\n");
    else {
      textbereich.append("Alle derzeit im Hotel logierenden Gäste:\n");
      for (int i = 1; i < holeGäste().length; ++i) {
        Gast g = holeGäste()[i];
        if (g != null) {
          Belegung b = findeBelegung(g.Nummer());
          textbereich.append(g.Beschreibung() + " in Zimmer " +
                             b.Zimmernummer() + "\n");
          } // Ende if
        } // Ende for
      } // Ende else
    } // Ende zeige Gäste

  void vorbereiteEingabe1() {
    feld1.setText("");
    feld1.setEditable(true);
    feld1.requestFocus();
    feld2.setText("");
    feld2.setEditable(true);
    feld3.setText("");
    feld3.setEditable(true);
    textbereich.setText("Nach Eingabe der Daten JA-Knopf drücken!\n");
    eingabe1Vorbereitet = true;
    } // Ende vorbereite Eingabe1

  Gast erzeugeGast() {
    Gast neuGast = null;
    String name = feld1.getText();
    String wohnort = feld2.getText();
    String nummer = feld3.getText();
    if (! name.equals("") && ! wohnort.equals("") && ! nummer.equals("")) 
      neuGast = new Gast(nummer, name, wohnort);
    einfügeGast(neuGast);
    feld1.setEditable(false);
    feld2.setEditable(false);
    feld3.setEditable(false);
    return neuGast;
    } // Ende erzeuge Gast

  void belegeZimmer() {

    Gast     gast = null;
    Zimmer   zimmer = null;
    String   zimmernummer = "";
    Belegung belegung;

    if (eingabe1Vorbereitet) {
      gast = erzeugeGast();
      if (gast != null) {
        textbereich.append("Neu: " + gast.Beschreibung() + "\n");
        zimmernummer = "z5";
        zimmer = sucheZimmer(zimmernummer);
        if (zimmer == null)
          textbereich.append("Dieses Zimmer existiert nicht\n");
        else {
          textbereich.append(zimmer.Beschreibung() + "\n");
          belegung = sucheBelegung(zimmernummer);
          if (belegung == null) {
            textbereich.append("Das Zimmer ist frei\n");
            String d1 = "30.05.00";
            einfügeBelegung(new Belegung(gast, zimmer, d1, 3));
            textbereich.append("Zimmerbelegung erfolgt\n");
            } // Ende if
          else {
            textbereich.append("Das Zimmer ist bereits von ");
            textbereich.append(belegung.Gastname() + " belegt\n");
            } // Ende else 
          } // Ende else
        } // Ende if
      eingabe1Vorbereitet = false;
      } // Ende if
    } // Ende belege Zimmer

  void vorbereiteEingabe2() {
    feld1.setText("");
    feld1.setEditable(false);
    feld2.setText("");
    feld2.setEditable(false);
    feld3.setText("");
    feld3.setEditable(true);
    feld3.requestFocus();
    textbereich.setText("Zum Schluss JA-Knopf drücken!\n");
    eingabe2Vorbereitet = true;
    } // Ende vorbereite Eingabe2

  void ausbucheGast() {
    if (eingabe2Vorbereitet) {
      textbereich.setText("");
      String nummer = feld3.getText();
      Gast gast = sucheGast(nummer);
      if (gast == null) {
        textbereich.append("Falsche Gastnummer!\n");
        feld3.setEditable(false);
        } // Ende if
      else {
        textbereich.append("Zu zahlen: " + Rechnungsbetrag(gast) 
                                         + " Euro\n");
        textbereich.append(gast.Beschreibung() + "\n");
        streicheGast(nummer);
        streicheBelegung(gast.Nummer());
        textbereich.append("ist (bzw. sind) ausgebucht\n");
        } // Ende else
      eingabe2Vorbereitet = false;
      } // Ende if
    } // Ende ausbuche Gast

  void speichereDaten() {
    try {
      OutputStream os = new FileOutputStream("hoteldaten");
      ObjectOutputStream oos = new ObjectOutputStream(os);
      oos.writeObject(holeZimmer());
      oos.writeObject(holeGäste());
      oos.writeObject(holeBelegungen());
      oos.close();
      } // Ende try
    catch(FileNotFoundException e) {}
    catch(IOException e) {}
    } // Ende speichere Daten

  void ladeDaten() {
    System.out.println("Laden ...");
    try {
      InputStream is = new FileInputStream("hoteldaten");
      ObjectInputStream ois = new ObjectInputStream(is);
      zimmerliste = (Zimmer[]) ois.readObject();
      gästeliste = (Gast[]) ois.readObject();
      belegungsliste = (Belegung[]) ois.readObject();
      ois.close();
      } // Ende try
    catch(FileNotFoundException e) {return;}
    catch(ClassNotFoundException e) {return;}
    catch(StreamCorruptedException e) {return;}
    catch(OptionalDataException e) {return;}
    catch(IOException e) {return;}
    } // Ende lade Daten

  static void main (String[] xy) {
    Hotel h = new HotelGO();
    h.initialisiere();
    h.anzeige();
    } // Ende main

  } // Ende HotelGO

class Zimmer implements Serializable {

  private String nummer;
  private int    bettenzahl, preis;

  Zimmer (String n, int b, int p)
    {nummer = n; bettenzahl = b; preis = p;}

  String Nummer()
    {return nummer;}

  int Bettenzahl()
    {return bettenzahl;}

  int Preis()
    {return preis;}

  String Beschreibung() {
    String b = " Betten, ";
    if (bettenzahl == 1) b = " Bett, ";
    return nummer + ": " + bettenzahl + b
           + preis + " DM pro Nacht";
    } // Ende Beschreibung

  } // Ende Zimmer

class Gast implements Serializable {
  
  private String nummer, name, wohnort;

  Gast(String nr, String na, String w)
    {nummer = nr; name = na; wohnort = w;}

  String Nummer()
    {return nummer;}

  String Name()
    {return name;}

  String Wohnort()
    {return wohnort;}

  String Beschreibung()
    {return nummer + ": " + name + " aus " + wohnort;}

  } // Ende Gast

class Belegung implements Serializable {

  private Gast   gast;
  private Zimmer zimmer;
  private String ankunftstag;
  private int    nächtezahl;

  Belegung (Gast g, Zimmer z, String a, int n) {
    gast = g; zimmer = z; 
    ankunftstag = a; nächtezahl = n;
    } // Ende Konstruktor Belegung

  String Gastnummer()
    {return gast.Nummer();}

  String Gastname()
    {return gast.Name();}

  String Zimmernummer()
    {return zimmer.Nummer();}

  String Ankunftstag()
    {return ankunftstag;}

  int Nächtezahl()
    {return nächtezahl;}

  String Beschreibung()
    {return "Zimmer " + Zimmernummer() 
                      + " belegt von " + Gastname();}

  } // Ende Belegung

