From a406822272786d022aa853f678a5d19aa4f5c40b Mon Sep 17 00:00:00 2001 From: Tahar Lamred & Theresa Nerz Date: Wed, 1 Jul 2026 17:36:46 +0200 Subject: [PATCH] Add player name and highscore flow --- app/__pycache__/app.cpython-313.pyc | Bin 0 -> 6477 bytes app/app.py | 90 ++++++++++++++++++++++++++-- app/init_db.py | 7 +++ 3 files changed, 91 insertions(+), 6 deletions(-) create mode 100644 app/__pycache__/app.cpython-313.pyc diff --git a/app/__pycache__/app.cpython-313.pyc b/app/__pycache__/app.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d4c8bb23abec01b0353cbeca9fef14e9b96ae2ae GIT binary patch literal 6477 zcmbtYYi!$Cb|ytiq(oViZTaoQwDYi)_?0;C$TFPR@gs>d6|Ky}Mh#k`Z6z}0TuPIT zc4n$z2RriY0Cr|(5v5%q-v06e3$$A-x+%IpQY=v9r&#@n$^_dK9bmElJnKOh$giGD ziL~rVnxMV5E-%kL_uO;OJ?Gr-a=WU^ML^;EM{nG%CW!ySFJ@uNjqSrWg7_&R5+Zq- zK&2;%NaNjxZ1A*QrY31bPuh`v(t#Y43}OUgmhK>C*^^{R3UZ3ntTS%RhAFc|sJ<+} z;t^`9cqunu!`bo*PLDa8`9%C{Mz_CWG%wO8VWqgBYSG?Ipc=7GbTkt;NK`xP4Eala zm9@x-tmy2siLSG@*KlxeAjo;A=b_|i@viqfmkFLNq_wxG0T*n*6o+# zl6q5TksOU7Ig->FB;QKODl}ACRbvSyT_dXzX+`cqiNtb`Do2o+orxqA#aPJ5g}HZzr^j_Fl(?;PC~YXS$I>hRG1-*i%F@Oq?Li z?GD-Zbi=D9!3Gk{q)@?T_6tPV23E68rT^9?l#4ieW%S~-ph(Mdx3D0iWNdLREyt2V zkDw+clq|gri$YXN$;cXZDRk|spsvK^cm?s@@zK!eE+G@5Fm-KOmo=&Mn0jm()lC$tr39Vh#M%A*k>U@;_*T4 z&$8RqPPgOFH3Y-oUHZ|Dty;qF-0~52=Ckp;&$f2T^RR2q!BDEUCnKXi9%a zR0hy1xL)NPqD`bM=W^~yG+U#Ki5a{pMhRIh zlY$e1InxQ7sgHsk8cw~v#pDEsCPTG*dv^i?JABCZ{r(y2WD^~o&<(onP#8>^vCcWs zIw22MTDST8QeSCZ=S-`~iO(Q~3R96R>?fztJ9CC!k?cAM(P1XWc>#2!MfV#=Fk+Qy zyB?TU^x(P&_CujzJa4tUR;#+ynrSn&G;OQc!*+AWr2{a(y_Oh-iG3VQ22E`w4;rpSfm-v5nT;O=b%$YuW!zwosTb69K=g*r8_AP9W#) zJ+dWCRixE+bNxF{%MvVj8Q5@d5nFdj02}QsmIUV;{glOr#p1p&EAGcuG%Y_yO4P2X ze#KE*&JzE+i|=itzwPa!AM_HiUPeC3z)Wv%=k_r3mUec9UFN!_LGUP-*n#Ja0IGS- z4jg#foB}#nSw+Co{$E*T@t}BU<`Af6lrUxbpAij*aea^wJHcim>_hOK*kQN*abNJ z!u8=R;ZafO8tN9{A7ci;?p%pWcVsjdi|SmtiKV37#>qN_f$88eeD)`n;rOMKcUI)I zH?VXpcwI*En5+i+pq;`8e_$o}ZY&e8t7@Tv%(rMVm_5jCX}Fv zL6ocn`pWNtJ}f?%J_Y&&Bw-233xl1;Vl1H2863ATiy$egyoAR~K|{TUz|!%Gepuh} zU?33>zN7>3SWu_2bza)e3A)_?Y%i(a;|nhxUoADVYN70BmV{pbz9Ce0-%tyI|rx9)#rBd`emD7LX(-RXIMlfTTshkmjqTByT5B zQZSGr5L3&tPy&dts4yrDr2}P|C>B{t8j=(#vNVUJ)N*N%lu{QZSy?p4eV9;6y?Ash z-sBMGRq%LWQC>(XQEVun>s6)}hEh6HRz~MddYO>!E-O)qd@Hf-E|qnzf-T(_erIHO zdem}naddhY_603>jZQCOmB+B{q=kiKyP+v~!AMG2lGLOC$_pa&CDYboU?;#!{uf92 z0M>6gi{&E+uE?>djD!U#4wLl?rk{0G1WmfCBdCBUEK6}bE=^z z92~w~!O?+(qa&C;CRD~jN7=R=Rt#Lb{5|*gy-FwDX?Z}}))9oOY1uW>ZmgqlSeaK> z&I|rpgj1C6D8;Bw%@`@hII^KzB$LXbd_#;HQ272Y-h6jwM+B zvrq1RlB+K;Z5vmA{qApOe>Gb;IQ*QiU;AkFqo;hE#n(d^QzjPyqC2VJ>In&t2c`7aIvcT>l63SetGt*^LcmMww>Z#S!#pv`T2Q;p)==SD)J-=pt!~FyI=<1WR zh5oSS3+LaP(|mK9doDXtWZil1ZH>L1rH$se#*UYpevS2mKz?6=Z_CoZ=lEw0E$dX# z>&rPdYB#R`yhUs5-b`wZ1CMGSz57qCk0bdrlUn2DCreu6bAgZeK zzG2NhY|OUKtnx4cUz_E=@iyG&zT|S33*N5GM3M1oOe0<`Q{aU>D|}PFEP{bttF9tD zTXcG}F0i1}@n?s5QDg|a1FTtHd*5{rcrHC@c;ecoY}JlGI6THp(oWbtpo4jne8I4H z?-cnScxKz4GEI4=37agq8q8e>lkMJO=jQPO-}{t5q46gQ{HaIn`M_1}+*E;|dS2J^ z)qCr$ztQg^QL_doBq1#Z(25D`Nsb5>{MMnETXRA{=~hBuP+z9HTT(j?ANX>8__sy zE7qR*?ZBhk{~XY2$DZ_QweRQM@4w*da%ArC1E)n`e=Q4asIcJnVbfB1{PEcgSOH}EK_c`rVep1A&HS@Vkd z>ru@c)!69g^tTk@X?S7X-_xGmCvODe&MG*^KnN1sKZXjvu99%y1&m%Q7P5zrHWp?D zq!lL1wTU%&~Ht>~Av}20sDBqG83u6%#wGG_H5Is)%*gKtJ%i~@+U57zOg4=nlGfeL!Xa8;QAUNXq;7f@1VvGf}_xE z-aVwzL*N_MUh3@J+_Dr?=H~F%m=JuEIosbqkY@UOjX%E)vNRl5I=up@#83Vaf9UqN z>b8W6Sgi0FsC4@R{w9j>wj1YyanKmY1Qw666^N(cqmJ$>eGZ+wDc=E+QgTUW;4>=b z0JH(e6sEwCg;*R9VJ{4eqjMt@A)UUFh$#q9UOJ^PG}Y}W0bjU`)L*h*08<%R`7nkO z3Oa?kr!a{^DdiW0@$IQ}Xt06hL^KtbgJ=%=v3si3P;XHrNj@W-&j`;mg8L6*pg;`# zr-RFm|0t26iq(fQ)TbW&-Rtz~>9wKNq1^F@ryrbtIP_p>^Gu=TM1eb*VT&&JTIXu# zTK8)A`VTht7hL@r=1&fa^nB;8BE4GzVY7eMbhjxxkgMBpEAg|7OkaM(`%osev(_*SSav41rD-8k!C&{yF0etwBgH){TqE4k{{h{ HnCyQ5S@3k@ literal 0 HcmV?d00001 diff --git a/app/app.py b/app/app.py index f8393bf..841f938 100644 --- a/app/app.py +++ b/app/app.py @@ -1,38 +1,102 @@ import os import sqlite3 -from flask import Flask, request +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 + + @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) - if room_id is None: - return '

Verlies

Abenteuer starten' + player_id = session.get("player_id") + + if room_id is None or player_id is None: + html = "

Verlies

" + if player_id is not None: + html += "

Willkommen zurück, " + session.get("player_name", "Spieler") + ".

" + else: + html += "

Bitte gib zuerst deinen Namen ein, bevor du ins Verlies gehst.

" + html += "
" + html += "

Highscores ansehen

" + html += "

Highscores

    " + rows = get_highscores() + if rows: + for row in rows: + html += "
  1. " + row["name"] + ": " + f"{row['dauer']:.2f}" + "s
  2. " + else: + html += "
  3. Noch keine abgeschlossenen Spiele.
  4. " + html += "
" + return html db = get_db() - r = db.execute("SELECT name, beschreibung, raetsel_frage, raetsel_antwort FROM raeume WHERE id = ?", (room_id,)).fetchone() + 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 '

Raum nicht gefunden

' + return "

Raum nicht gefunden

" if r["raetsel_frage"]: if request.method == "POST": if request.form.get("antwort", "").strip() == r["raetsel_antwort"]: - return "

Befreit!

" + 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 "

Geschafft!

Du hast den Schatz gefunden.

Zum Highscore

" return 'Leider falsch. nochmal' html = "

" + r["name"] + "

" @@ -46,6 +110,20 @@ def start(): html += '' + a["richtung"] + '   ' return html + +@app.route("/app/highscore") +def highscore(): + html = "

Highscores

    " + rows = get_highscores() + if rows: + for row in rows: + html += "
  1. " + row["name"] + ": " + f"{row['dauer']:.2f}" + "s
  2. " + else: + html += "
  3. Noch keine abgeschlossenen Spiele.
  4. " + html += "

Zurück zum Spiel

" + return html + + if __name__ == "__main__": port = int(os.environ.get("PORT", "9003")) app.run(host="0.0.0.0", port=port) diff --git a/app/init_db.py b/app/init_db.py index 8530b66..7bd1dc1 100644 --- a/app/init_db.py +++ b/app/init_db.py @@ -5,6 +5,7 @@ db = sqlite3.connect("adventure.db") # Datei wird angelegt, falls nicht da db.executescript(""" DROP TABLE IF EXISTS raeume; DROP TABLE IF EXISTS ausgaenge; +DROP TABLE IF EXISTS spieler; CREATE TABLE raeume ( id INTEGER PRIMARY KEY, @@ -18,6 +19,12 @@ CREATE TABLE ausgaenge ( richtung TEXT, nach_raum INTEGER ); +CREATE TABLE spieler ( + id INTEGER PRIMARY KEY, + name TEXT, + start_zeit REAL, + fertig_zeit REAL +); INSERT INTO raeume (id, name, beschreibung, raetsel_frage, raetsel_antwort) VALUES (1, 'Eingangshalle', 'Eine schwere Tür fällt hinter dir zu. Zwei Gänge führen ins Dunkel.', NULL, NULL),