diff --git a/README.md b/README.md index 38664ff..68996e7 100644 --- a/README.md +++ b/README.md @@ -20,14 +20,7 @@ Der bisher dokumentierte Serverpfad lautet: Glueck-Auf/ ├── flask_app/ │ ├── app.py Flask-Anwendung und Routen -│ ├── templates/ -│ │ ├── base.html Gemeinsames Layout und Styling -│ │ ├── index.html Startseite des Stadion-Escape-Rooms -│ │ └── raetsel.html Rätselseite mit Formular -│ └── assets/ -│ ├── css/ Platz für ausgelagerte Stylesheets -│ ├── img/ Platz für Bilder -│ └── js/ Platz für JavaScript +│ └── init_db.py Legt die SQLite-Datenbank für das Spiel an │ ├── index.html Startseite der bisherigen statischen Website ├── ueber_mich.html Persönliche Vorstellungsseite @@ -71,81 +64,43 @@ Die Anwendung läuft anschließend auf: http://localhost:9007/ ``` -Der Entwicklungsserver lauscht auf `0.0.0.0` und verwendet Port `9007`. +Der Entwicklungsserver lauscht auf `0.0.0.0` und verwendet Port `9000`. ## Flask-Routen | Route | Methoden | Inhalt | | --- | --- | --- | -| `/` und `/app/` | GET | Startseite des Stadion-Escape-Rooms | -| `/raetsel` und `/app/raetsel` | GET, POST | Rätsel am Stadiontor | -| `/frage` und `/app/frage` | GET, POST | Alternative Adressen für dieselbe Rätselseite | - -Die Routen funktionieren jeweils auch mit abschließendem Schrägstrich. +| `/` und `/app/` | GET, POST | Startseite mit Namenseingabe | +| `/raum/` und `/app/raum/` | GET, POST | Räume, Ausgänge und Rätsel des Stadion-Escape-Rooms | ## Aufbau der Flask-App ### `flask_app/app.py` - Erstellt die Flask-Anwendung. -- Rendert die HTML-Seiten mit Jinja. -- Nimmt die Antwort des Rätsel-Formulars per `POST` entgegen. -- Vergleicht die Eingabe mit dem gesuchten Code `4`. -- Übergibt die passende Rückmeldung an das Template. -- Stellt zukünftige statische Dateien aus `flask_app/assets/` unter - `/assets` bereit. +- Baut die HTML-Seiten direkt in Python-Strings zusammen. +- Enthält das gemeinsame Styling direkt in der Konstante `STYLE`. +- Nimmt den Namen und Rätselantworten per `POST` entgegen. +- Speichert Spielstart und Abschlusszeit in SQLite. +- Zeigt nach dem gelösten Rätsel eine Highscore-Liste an. -### Templates +### `flask_app/init_db.py` -`base.html` enthält das gemeinsame HTML-Grundgerüst, die Navigation und das -aktuelle Styling. `index.html` und `raetsel.html` erweitern dieses -Basis-Template mit Jinja-Blöcken. - -Die Startseite führt in den Stadiongang ein. Auf der Rätselseite kann der Code -für das Stadiontor eingegeben werden. Die Auswertung erfolgt durch Flask auf -dem Server und wird anschließend auf derselben Seite angezeigt. +Legt die SQLite-Datenbank `adventure.db` an und füllt sie mit den Räumen, +Ausgängen und der Rätselantwort. ### Ablauf des Rätsels 1. Die Startseite wird über `/` oder `/app/` aufgerufen. -2. Der Link „Zum Stadiontor“ führt zur Rätselseite. -3. Das Formular sendet die eingegebene Antwort mit der Methode `POST` an - dieselbe Route. -4. Flask liest den Wert aus `request.form["antwort"]`. -5. Bei der Antwort `4` wird eine Erfolgsmeldung angezeigt, bei jeder anderen - Eingabe eine Fehlermeldung. +2. Nach der Namenseingabe wird ein Spielstand in der Datenbank angelegt. +3. Der Link „Zum Stadiontor“ führt in den ersten Raum. +4. Über Ausgänge bewegt man sich durch Tunnel, Kabine, Kiosk und Nordkurve. +5. Im Rätselraum liest Flask `request.form["antwort"]`. +6. Bei der richtigen Antwort wird die Abschlusszeit gespeichert und der + Highscore angezeigt. -Die Rückmeldung wird in `app.py` erzeugt und als Variable `ergebnis` an -`raetsel.html` übergeben. Jinja zeigt den Ergebnisbereich nur an, wenn diese -Variable vorhanden ist. - -### Gemeinsames Template `base.html` - -Das Basis-Template stellt die wiederverwendbaren Bestandteile der Flask-Seiten -bereit: - -- HTML-Grundgerüst und deutsche Spracheinstellung, -- responsive Meta-Angaben, -- Google Fonts, -- Navigation zur Start- und Rätselseite, -- gemeinsames blaues Stadion-Design, -- responsive Darstellung für kleinere Bildschirme, -- Jinja-Blöcke für Seitentitel und Seiteninhalt. - -Die beiden Unterseiten verwenden `{% extends "base.html" %}`. Dadurch müssen -Navigation, Layout und Styling nicht in jeder Datei wiederholt werden. - -### Vorbereitete Assets - -Flask wurde mit folgendem Verzeichnis für statische Dateien eingerichtet: - -```text -flask_app/assets/ -``` - -Dateien aus diesem Verzeichnis wären unter `/assets/...` erreichbar. Die -Unterordner `css`, `img` und `js` sind bereits angelegt, derzeit aber noch -leer. Das CSS der Flask-App steht deshalb momentan direkt in `base.html`. +Das HTML-Grundgerüst, die Navigation und das blaue Stadion-Design werden direkt +in `app.py` erzeugt. Es gibt keine Jinja-Templates für die Flask-App. ## Statische Website @@ -161,8 +116,7 @@ anderem: Die statische Website und die Flask-App sind derzeit getrennte Bereiche des Projekts. Die Dateien in den Verzeichnissen `css/`, `img/` und `js/` gehören -zu den statischen HTML-Seiten. Für die Flask-App ist das Verzeichnis -`flask_app/assets/` vorgesehen. +zu den statischen HTML-Seiten. ### `index.html` – Startseite @@ -284,10 +238,8 @@ verwenden `../img/logo.png`. | Datei oder Ziel | Verlinkt beziehungsweise verwendet in | Zweck | | --- | --- | --- | -| `flask_app/templates/index.html` | Flask-Routen `/` und `/app/` | Start des Stadion-Escape-Rooms | -| `flask_app/templates/raetsel.html` | Rätsel- und Frage-Routen | Formular und Auswertung des Stadiontor-Codes | -| `flask_app/templates/base.html` | Beide Flask-Seiten | Gemeinsames Layout, Navigation und Styling | -| `flask_app/assets/` | Flask-Konfiguration in `app.py` | Vorbereiteter Bereich für statische Flask-Dateien | +| `flask_app/app.py` | Flask-Routen `/`, `/app/` und `/app/raum/` | Logik, HTML-Ausgabe und Styling des Stadion-Escape-Rooms | +| `flask_app/init_db.py` | Lokale Vorbereitung der Flask-App | Erstellt die SQLite-Datenbank | | `index.html` | Navigation aller statischen Seiten | Rückkehr zur statischen Startseite | | `ueber_mich.html` | Navigation, Startseiten-Button und Startseiten-Card | Vorstellungsseite | | `eis_projekt.html` | Navigation und Startseiten-Card | Projektseite | @@ -301,13 +253,12 @@ verwenden `../img/logo.png`. | `js/textanalyse.js` | `uebungen/textanalyse.html` | Textanalyse-Logik | | `img/Hintergrund.jpg` | `css/style.css` über die Klasse `.hero` | Hero-Hintergrundbild | | `img/logo.png` | Alle statischen HTML-Seiten | Favicon | -| Google Fonts | Flask-Templates und statische Seiten | Schriftarten Bebas Neue und Barlow | +| Google Fonts | Flask-App und statische Seiten | Schriftarten Bebas Neue und Barlow | ## Verwendete Technologien - Python 3 - Flask -- Jinja - HTML5 - CSS3 mit Custom Properties, Grid, Flexbox und Animationen - JavaScript mit DOM-Manipulation, Events und `localStorage` @@ -317,9 +268,7 @@ verwenden `../img/logo.png`. - Es gibt derzeit keine `requirements.txt`; Flask muss lokal manuell installiert werden. -- Die Styles der Flask-App befinden sich aktuell direkt in `base.html`. -- Die Unterordner in `flask_app/assets/` sind vorbereitet, enthalten aber - noch keine eigenen CSS-, Bild- oder JavaScript-Dateien. +- Die Styles der Flask-App befinden sich direkt in `flask_app/app.py`. - Das Kontaktformular der statischen Website sendet keine Daten. - Die Projektseite enthält noch keinen vollständig ausgearbeiteten Inhalt. - Die Angaben im Impressum sind fiktive Platzhalterdaten und nicht für eine diff --git a/flask_app/app.py b/flask_app/app.py index 87fed25..ef53ae3 100644 --- a/flask_app/app.py +++ b/flask_app/app.py @@ -9,39 +9,241 @@ app.secret_key = "stadion-escape-secret" STYLE = """ + + + + + +Glück Auf Stadion Escape + + + + +
+""" + + +HTML_END = """ +
+ + """ @@ -51,6 +253,10 @@ def get_db(): return db +def seite_html(inhalt, klasse="puzzle"): + return STYLE + '
' + inhalt + "
" + HTML_END + + def highscore_html(db): eintraege = db.execute( """ @@ -65,10 +271,10 @@ def highscore_html(db): if not eintraege: return "" - html = "

Highscore

    " + html = '

    Highscore

      ' for eintrag in eintraege: html += "
    1. " + escape(eintrag["name"]) + " - " + str(round(eintrag["dauer"], 1)) + " Sekunden
    2. " - html += "
    " + html += "
" return html @@ -92,19 +298,23 @@ def start(): session["spieler_id"] = spieler_id session["spieler_name"] = name - return STYLE + ( + return seite_html( "

Eintrittskarte gelöst

" "

Willkommen, " + escape(name) + ". Dein Weg durchs Stadion beginnt.

" - 'Zum Stadiontor' + 'Zum Stadiontor' ) - return STYLE + ( - "

Stadion Escape

" + return seite_html( + '

Escape Room im Stadiongang

' + "

Glück Auf
im Stadion

" "

Trage deinen Namen auf der Eintrittskarte ein. Ab dann läuft deine Zeit.

" '
' + '' '' "" "
" + '

Direkt zum Stadiontor

', + "scene", ) @@ -116,7 +326,9 @@ def raum(raum_id): if r is None: db.close() - return STYLE + '

Raum nicht gefunden

Zurück zum Start', 404 + return seite_html( + '

Raum nicht gefunden

Zurück zum Start' + ), 404 if r["raetsel_frage"]: if request.method == "POST": @@ -141,22 +353,23 @@ def raum(raum_id): ) html += highscore_html(db) db.close() - return STYLE + html - return STYLE + ( + return seite_html(html) + return seite_html( '

Leider falsch

' '

Erwin schüttelt den Kopf. Die Botschaft stimmt noch nicht.

' - 'Nochmal versuchen' + 'Nochmal versuchen' ) - html = "

" + r["name"] + "

" - html += "

" + r["beschreibung"] + "

" + html = "

" + escape(r["name"]) + "

" + html += "

" + escape(r["beschreibung"]) + "

" html += '
' - html += "

" + r["raetsel_frage"] + "

" - html += '' + html += '

' + escape(r["raetsel_frage"]) + "

" + html += '' + html += '' html += "" html += "
" db.close() - return STYLE + html + return seite_html(html) ausgaenge = db.execute( "SELECT richtung, nach_raum FROM ausgaenge WHERE von_raum=?", @@ -164,14 +377,14 @@ def raum(raum_id): ).fetchall() db.close() - html = "

" + r["name"] + "

" - html += "

" + r["beschreibung"] + "

" + html = "

" + escape(r["name"]) + "

" + html += "

" + escape(r["beschreibung"]) + "

" for a in ausgaenge: - html += '' - html += a["richtung"] + html += '' + html += escape(a["richtung"]) html += " " - return STYLE + html + return seite_html(html) if __name__ == "__main__": diff --git a/flask_app/templates/base.html b/flask_app/templates/base.html deleted file mode 100644 index 519d9d6..0000000 --- a/flask_app/templates/base.html +++ /dev/null @@ -1,212 +0,0 @@ - - - - - - {% block title %}Glück Auf Stadion Escape{% endblock %} - - - - - - -
- {% block content %}{% endblock %} -
- - diff --git a/flask_app/templates/index.html b/flask_app/templates/index.html deleted file mode 100644 index a652534..0000000 --- a/flask_app/templates/index.html +++ /dev/null @@ -1,19 +0,0 @@ -{% extends "base.html" %} - -{% block title %}Glück Auf Stadion Escape{% endblock %} - -{% block content %} -
-

Escape Room im Stadiongang

-

Glück Auf
im Stadion

-

- Der Gang unter der Tribüne ist fast leer. Aus dem Innenraum - dringt Flutlicht, aber das Drehkreuz zum Spielfeld bleibt gesperrt. -

-

- Auf einer blauen Tafel steht ein Hinweis: - Der erste Code steckt in der Zahl, die jeder Fan sofort erkennt. -

- Zum Stadiontor -
-{% endblock %} diff --git a/flask_app/templates/raetsel.html b/flask_app/templates/raetsel.html deleted file mode 100644 index 89bdb9e..0000000 --- a/flask_app/templates/raetsel.html +++ /dev/null @@ -1,28 +0,0 @@ -{% extends "base.html" %} - -{% block title %}Rätsel am Stadiontor{% endblock %} - -{% block content %} -
-

Das Stadiontor

-

- Das Drehkreuz ist verriegelt. Über dem Eingang leuchtet eine besonders blaue Markierung: Nordkurve. -

-

- Hinweis: Schau auf das Logo des Vereins. Ein wahrer Fan erkennt die - gesuchte Zahl sofort. -

- -
- - - -
- - {% if ergebnis %} -

{{ ergebnis }}

- {% endif %} - -

Zurück in den Gang

-
-{% endblock %}