Files changed (1) hide show
  1. app.py +48 -26
app.py CHANGED
@@ -921,6 +921,10 @@ def create_game(host=None, topics=[], num_questions=5, auto_close=True, ai_topic
921
  # PLAY PAGE
922
  # -------------------------
923
  def play_page():
 
 
 
 
924
  gid = st.session_state.get("active_game_id")
925
  uname = st.session_state.get("username")
926
 
@@ -928,7 +932,7 @@ def play_page():
928
  st.error("No active game or username found. Please join or create a game first.")
929
  return
930
 
931
- # ---------------- Load game ----------------
932
  games = unified_get("games") or {}
933
  game = games.get(gid)
934
 
@@ -942,36 +946,51 @@ def play_page():
942
 
943
  questions = game.get("questions", [])
944
  if not questions:
945
- st.info("No questions loaded for this game.")
946
  return
947
 
948
- # ---------------- Init session state ----------------
949
- if "answers" not in st.session_state:
950
- st.session_state.answers = [""] * len(questions)
951
- if "answer_times" not in st.session_state:
952
- st.session_state.answer_times = [0] * len(questions)
953
- if "current_index" not in st.session_state:
 
 
 
 
954
  st.session_state.current_index = 0
 
955
  if "question_started_at" not in st.session_state:
956
  st.session_state.question_started_at = time.time()
957
 
958
  idx = st.session_state.current_index
959
 
960
- # ---------------- All done ----------------
961
- if idx >= len(questions):
962
- st.success("All done โ€” submit your answers!")
963
  return
964
 
965
- # ---------------- Question UI ----------------
966
  q = questions[idx]
967
- st.subheader(f"Question {idx + 1}/{len(questions)}")
968
  st.write(q["question"])
969
 
 
 
970
  start_time = st.session_state.get("question_started_at")
971
- elapsed = int(time.time() - start_time)
 
 
 
 
 
972
  time_limit = 15
973
- st.markdown(f"**โฑ Time left:** {max(0, time_limit - elapsed)} seconds")
 
 
974
 
 
975
  choice = st.radio(
976
  "Choose an answer:",
977
  q["options"],
@@ -984,28 +1003,28 @@ def play_page():
984
  with col1:
985
  if st.button("Next", key=f"next_{gid}_{idx}"):
986
  st.session_state.answers[idx] = choice
987
- st.session_state.answer_times[idx] = time.time() - start_time
988
  st.session_state.current_index += 1
989
  st.session_state.question_started_at = time.time()
990
  st.rerun()
991
 
992
  # ---------------- SUBMIT ----------------
993
  with col2:
994
- if idx == len(questions) - 1:
995
  if st.button("Submit All Answers", key=f"submit_{gid}_{idx}"):
996
 
997
  # Save last answer
998
  st.session_state.answers[idx] = choice
999
- st.session_state.answer_times[idx] = time.time() - start_time
1000
 
1001
  answers = st.session_state.answers
1002
  times = st.session_state.answer_times
1003
 
1004
  # Compute score
1005
  score, flags = compute_score(questions, answers, times)
1006
- percentage = int(score / (len(questions) * 15) * 100)
1007
 
1008
- # ---------------- Update players ----------------
1009
  players = unified_get("players") or {}
1010
  players.setdefault(gid, {})
1011
  players[gid][uname] = {
@@ -1018,7 +1037,7 @@ def play_page():
1018
  }
1019
  unified_set("players", players)
1020
 
1021
- # ---------------- Save leaderboard ----------------
1022
  row = {
1023
  "name": uname,
1024
  "score": score,
@@ -1026,7 +1045,7 @@ def play_page():
1026
  "topics": ",".join(game.get("topics", [])),
1027
  "timestamp": now_iso(),
1028
  "avatar": st.session_state.get("avatar", "๐ŸŽฎ"),
1029
- "questions": len(questions),
1030
  "answers": json.dumps(answers),
1031
  "correct_flags": json.dumps(flags),
1032
  }
@@ -1034,19 +1053,22 @@ def play_page():
1034
  unified_push_leaderboard(row)
1035
  save_score_to_csv(row)
1036
 
1037
- # ---------------- Auto close game ----------------
1038
  if game.get("auto_close", True):
1039
  games[gid]["closed"] = True
1040
  games[gid]["closed_at"] = now_iso()
1041
  unified_set("games", games)
1042
 
1043
- st.success(f"๐ŸŽ‰ Submitted! Score: {score} / {len(questions)*15} ({percentage}%)")
1044
  st.balloons()
1045
 
1046
- # Reset state
1047
- st.session_state.clear()
 
 
1048
  st.rerun()
1049
 
 
1050
  # Join game
1051
  def join_game_page():
1052
  st.header("Join Game")
 
921
  # PLAY PAGE
922
  # -------------------------
923
  def play_page():
924
+ import time, json
925
+ import streamlit as st
926
+
927
+ # ---------------- BASIC CHECKS ----------------
928
  gid = st.session_state.get("active_game_id")
929
  uname = st.session_state.get("username")
930
 
 
932
  st.error("No active game or username found. Please join or create a game first.")
933
  return
934
 
935
+ # ---------------- LOAD GAME ----------------
936
  games = unified_get("games") or {}
937
  game = games.get(gid)
938
 
 
946
 
947
  questions = game.get("questions", [])
948
  if not questions:
949
+ st.info("No questions available.")
950
  return
951
 
952
+ # ---------------- INIT SESSION STATE (SAFE) ----------------
953
+ n = len(questions)
954
+
955
+ if "answers" not in st.session_state or not isinstance(st.session_state.answers, list):
956
+ st.session_state.answers = [""] * n
957
+
958
+ if "answer_times" not in st.session_state or not isinstance(st.session_state.answer_times, list):
959
+ st.session_state.answer_times = [0] * n
960
+
961
+ if "current_index" not in st.session_state or not isinstance(st.session_state.current_index, int):
962
  st.session_state.current_index = 0
963
+
964
  if "question_started_at" not in st.session_state:
965
  st.session_state.question_started_at = time.time()
966
 
967
  idx = st.session_state.current_index
968
 
969
+ # ---------------- FINISHED ----------------
970
+ if idx >= n:
971
+ st.success("All questions completed.")
972
  return
973
 
974
+ # ---------------- QUESTION UI ----------------
975
  q = questions[idx]
976
+ st.subheader(f"Question {idx + 1} / {n}")
977
  st.write(q["question"])
978
 
979
+ # ---------------- SAFE TIMER (ZERO CRASH) ----------------
980
+ now = time.time()
981
  start_time = st.session_state.get("question_started_at")
982
+
983
+ if start_time is None:
984
+ start_time = now
985
+ st.session_state.question_started_at = now
986
+
987
+ elapsed = int(now - start_time)
988
  time_limit = 15
989
+ remaining = max(0, time_limit - elapsed)
990
+
991
+ st.markdown(f"**โฑ Time left:** {remaining} seconds")
992
 
993
+ # ---------------- ANSWER ----------------
994
  choice = st.radio(
995
  "Choose an answer:",
996
  q["options"],
 
1003
  with col1:
1004
  if st.button("Next", key=f"next_{gid}_{idx}"):
1005
  st.session_state.answers[idx] = choice
1006
+ st.session_state.answer_times[idx] = elapsed
1007
  st.session_state.current_index += 1
1008
  st.session_state.question_started_at = time.time()
1009
  st.rerun()
1010
 
1011
  # ---------------- SUBMIT ----------------
1012
  with col2:
1013
+ if idx == n - 1:
1014
  if st.button("Submit All Answers", key=f"submit_{gid}_{idx}"):
1015
 
1016
  # Save last answer
1017
  st.session_state.answers[idx] = choice
1018
+ st.session_state.answer_times[idx] = elapsed
1019
 
1020
  answers = st.session_state.answers
1021
  times = st.session_state.answer_times
1022
 
1023
  # Compute score
1024
  score, flags = compute_score(questions, answers, times)
1025
+ percentage = int(score / (n * time_limit) * 100)
1026
 
1027
+ # ---------------- UPDATE PLAYERS ----------------
1028
  players = unified_get("players") or {}
1029
  players.setdefault(gid, {})
1030
  players[gid][uname] = {
 
1037
  }
1038
  unified_set("players", players)
1039
 
1040
+ # ---------------- SAVE LEADERBOARD ----------------
1041
  row = {
1042
  "name": uname,
1043
  "score": score,
 
1045
  "topics": ",".join(game.get("topics", [])),
1046
  "timestamp": now_iso(),
1047
  "avatar": st.session_state.get("avatar", "๐ŸŽฎ"),
1048
+ "questions": n,
1049
  "answers": json.dumps(answers),
1050
  "correct_flags": json.dumps(flags),
1051
  }
 
1053
  unified_push_leaderboard(row)
1054
  save_score_to_csv(row)
1055
 
1056
+ # ---------------- AUTO CLOSE GAME ----------------
1057
  if game.get("auto_close", True):
1058
  games[gid]["closed"] = True
1059
  games[gid]["closed_at"] = now_iso()
1060
  unified_set("games", games)
1061
 
1062
+ st.success(f"๐ŸŽ‰ Submitted! Score: {score} / {n*time_limit} ({percentage}%)")
1063
  st.balloons()
1064
 
1065
+ # ---------------- SAFE RESET (NO CLEAR) ----------------
1066
+ for k in ["answers", "answer_times", "current_index", "question_started_at"]:
1067
+ st.session_state.pop(k, None)
1068
+
1069
  st.rerun()
1070
 
1071
+
1072
  # Join game
1073
  def join_game_page():
1074
  st.header("Join Game")