eis-website/app/app.py
2026-07-10 07:59:51 +02:00

162 lines
5.6 KiB
Python

import os
import random
import sqlite3
import time
from flask import Flask, redirect, request, session
app = Flask(__name__)
app.secret_key = "escape-room-secret"
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
DB_PATH = os.path.join(BASE_DIR, "adventure.db")
def get_db():
db = sqlite3.connect(DB_PATH)
db.row_factory = sqlite3.Row
return db
def get_highscores(limit=10):
db = get_db()
rows = db.execute(
"""
SELECT name, fertig_zeit - start_zeit AS dauer
FROM spieler
WHERE fertig_zeit IS NOT NULL
ORDER BY dauer
LIMIT ?
""",
(limit,),
).fetchall()
db.close()
return rows
def get_story_html(room, exits):
mood = random.choice(
[
"Die Luft ist kalt, als würde das Verlies selbst atmen.",
"Ein feiner Staubschleier tanzt im Licht, als wolle er dir etwas zeigen.",
"Ein leises Knarren erfüllt den Raum, als hätte die Dunkelheit ein Auge geöffnet.",
]
)
hint = random.choice(
[
"Irgendwo in der Finsternis liegt ein Hinweis auf den nächsten Schritt.",
"Der Weg zum Ziel ist nicht immer der einfachste, aber er ist der richtige.",
"Jede Ecke scheint ein kleines Geheimnis zu verbergen.",
]
)
goal = random.choice(
[
"Dein Ziel ist klar: den Schatz zu finden, bevor die Tür sich wieder schließt.",
"Mit jedem Schritt näherst du dich dem letzten Geheimnis.",
"Ein letzter Atemzug, und der Weg wäre frei.",
]
)
directions = [exit_row["richtung"] for exit_row in exits]
falltuer = random.choice(directions) if directions else None
html = "<h1>" + room["name"] + "</h1>"
html += "<p>" + room["beschreibung"] + "</p>"
html += "<p>" + mood + " " + hint + " " + goal + "</p>"
if falltuer:
html += "<p>Im Schatten des Raums scheint ein möglicher Weg nach <strong>" + falltuer + "</strong> zu führen — vielleicht ist das die Falltür.</p>"
return html
@app.route("/", methods=["GET", "POST"])
@app.route("/app", methods=["GET", "POST"])
@app.route("/app/", methods=["GET", "POST"])
def start():
if request.method == "POST" and "spielername" in request.form:
name = request.form.get("spielername", "").strip() or "Unbekannt"
db = get_db()
cur = db.execute(
"INSERT INTO spieler (name, start_zeit, fertig_zeit) VALUES (?, ?, NULL)",
(name, time.time()),
)
db.commit()
db.close()
session["player_id"] = cur.lastrowid
session["player_name"] = name
return redirect("/app/?room=1")
room_id = request.args.get("room", type=int)
player_id = session.get("player_id")
if room_id is None or player_id is None:
html = "<h1>Verlies</h1>"
if player_id is not None:
html += "<p>Willkommen zurück, " + session.get("player_name", "Spieler") + ".</p>"
else:
html += "<p>Bitte gib zuerst deinen Namen ein, bevor du ins Verlies gehst.</p>"
html += "<form method='post'><label>Dein Name</label><input name='spielername'><button>Starten</button></form>"
html += "<p><a href='/app/highscore'>Highscores ansehen</a></p>"
html += "<h2>Highscores</h2><ol>"
rows = get_highscores()
if rows:
for row in rows:
html += "<li>" + row["name"] + ": " + f"{row['dauer']:.2f}" + "s</li>"
else:
html += "<li>Noch keine abgeschlossenen Spiele.</li>"
html += "</ol>"
return html
db = get_db()
r = db.execute(
"SELECT name, beschreibung, raetsel_frage, raetsel_antwort FROM raeume WHERE id = ?",
(room_id,),
).fetchone()
ausgaenge = db.execute(
"SELECT richtung, nach_raum FROM ausgaenge WHERE von_raum = ?", (room_id,)
).fetchall()
db.close()
if r is None:
return "<h1>Raum nicht gefunden</h1>"
if r["raetsel_frage"]:
if request.method == "POST":
if request.form.get("antwort", "").strip() == r["raetsel_antwort"]:
db = get_db()
current = db.execute(
"SELECT fertig_zeit FROM spieler WHERE id = ?", (player_id,)
).fetchone()
if current and current["fertig_zeit"] is None:
db.execute(
"UPDATE spieler SET fertig_zeit = ? WHERE id = ?",
(time.time(), player_id),
)
db.commit()
db.close()
return "<h1>Geschafft!</h1><p>Du hast den Schatz gefunden.</p><p><a href='/app/highscore'>Zum Highscore</a></p>"
return 'Leider falsch. <a href="/app/?room=' + str(room_id) + '">nochmal</a>'
html = get_story_html(r, ausgaenge)
html += '<form method="post">' + r["raetsel_frage"] + ' <input name="antwort"><button>OK</button></form>'
return html
html = get_story_html(r, ausgaenge)
for a in ausgaenge:
html += '<a href="/app/?room=' + str(a["nach_raum"]) + '">' + a["richtung"] + '</a> &nbsp; '
return html
@app.route("/app/highscore")
def highscore():
html = "<h1>Highscores</h1><ol>"
rows = get_highscores()
if rows:
for row in rows:
html += "<li>" + row["name"] + ": " + f"{row['dauer']:.2f}" + "s</li>"
else:
html += "<li>Noch keine abgeschlossenen Spiele.</li>"
html += "</ol><p><a href='/app/'>Zurück zum Spiel</a></p>"
return html
if __name__ == "__main__":
port = int(os.environ.get("PORT", "9003"))
app.run(host="0.0.0.0", port=port)