Muthuraja18 commited on
Commit
5f7862e
ยท
verified ยท
1 Parent(s): 7f47350

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +88 -128
app.py CHANGED
@@ -400,21 +400,23 @@ def unified_push_message(game_id, msg_obj):
400
  # ---------------------------
401
  def unified_push_leaderboard(row):
402
  """
403
- Push a row to leaderboard (Firebase if Online, CSV if Offline)
404
- and automatically adds a UTC timestamp.
405
  """
406
- row = row.copy() # avoid mutating input
407
- # Add UTC timestamp
408
- row["timestamp"] = datetime.utcnow().isoformat() + "Z" # e.g., 2026-01-03T17:30:00Z
 
409
 
410
  mode = st.session_state.get("mode_selection", "Offline")
411
 
412
  if mode == "Online":
413
  ok, _ = init_firebase_if_needed()
414
- if ok:
415
- fb_push("/leaderboard", row)
 
 
416
 
417
- # Always save local CSV backup
418
  try:
419
  df = pd.read_csv(LEADERBOARD_FILE)
420
  except FileNotFoundError:
@@ -423,6 +425,30 @@ def unified_push_leaderboard(row):
423
  df = pd.concat([df, pd.DataFrame([row])], ignore_index=True)
424
  df.to_csv(LEADERBOARD_FILE, index=False)
425
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
426
  # ---------------------------
427
  # Get weekly leaderboard
428
  # ---------------------------
@@ -828,86 +854,82 @@ def get_top3_and_player_count(game_id):
828
  # Home page
829
 
830
  HEARTBEAT_THRESHOLD_SECONDS = 60 # adjust if needed
831
-
832
  def home_page():
833
  st.header("Home")
834
  st.write("Create games, invite friends, play and climb the leaderboard.")
835
 
836
  # ---------------- TOTAL ONLINE PLAYERS ----------------
837
- players_map = unified_get("players") or {}
838
- total_online = sum(len(v) for v in players_map.values())
839
  st.metric("๐ŸŸข Players Online", total_online)
840
 
841
  # ---------------- SHOW LAST SCORE ----------------
842
  last_score = st.session_state.get('last_score')
843
  last_game = st.session_state.get('last_game')
844
- if last_score is not None:
845
  st.success(f"Your last score: {last_score} (Game {last_game})")
846
 
847
  # ---------------- LOAD GAMES ----------------
848
  games = unified_get("games") or {}
849
- st.subheader("Recent games")
 
 
850
 
 
851
  for g in sorted(games.values(), key=lambda x: x.get("created_at", ""), reverse=True)[:10]:
852
  gid = g.get("game_id")
853
-
854
- # Use players/submissions stored in game dict
855
- players = g.get("players", [])
856
- submissions = g.get("submissions", {})
857
-
858
  st.markdown(f"### ๐ŸŽฎ Game: **{gid}** {'(Closed)' if g.get('closed') else ''}")
859
  st.write(f"Host: {g.get('host')} โ€” Topics: {', '.join(g.get('topics', []))}")
860
  st.write(f"Created: {g.get('created_at')}")
861
 
862
- joined = len(players)
863
- submitted = len(submissions)
 
864
 
865
- st.write(f"Players joined: **{joined}**")
866
- st.write(f"Submitted: **{submitted} / {joined}**")
867
 
868
- # ---------------- TOP 3 PLAYERS ----------------
869
  if submissions:
870
  st.markdown("๐Ÿ† **Top 3 Players**")
871
  top_players = sorted(submissions.items(), key=lambda x: x[1], reverse=True)[:3]
872
- for i, (uname_p, score) in enumerate(top_players, start=1):
873
- st.write(f"{i}. ๐ŸŽฎ **{uname_p}** โ€” {score} pts")
874
 
875
- # ---------------- PLAYER STATUS ----------------
876
  if players:
877
  st.markdown("**๐Ÿ‘ฅ Player Status**")
878
- for uname_p in players:
879
- if uname_p in submissions:
880
- st.write(f"๐ŸŽฎ **{uname_p}** โ€” โœ… Submitted ({submissions[uname_p]} pts)")
881
  else:
882
- st.write(f"๐ŸŽฎ **{uname_p}** โ€” โณ Playing")
883
 
884
  st.markdown("---")
885
 
886
- # ---------------- INVITE & CHALLENGE ----------------
887
- if not g.get("closed"):
888
  st.info(f"Share this Game ID: {gid}")
889
  render_copy_button(gid, gid)
890
 
891
- if st.session_state.get("username"):
892
- if st.button(f"Invite your friends to {gid}", key=f"invite_{gid}"):
893
- friends = get_friends_map().get(st.session_state["username"], [])
894
- if not friends:
895
- st.warning("No friends to invite.")
896
- else:
897
- for f in friends:
898
- send_game_invite(st.session_state["username"], f, gid)
899
- st.success("Invites sent to friends.")
900
-
901
- if st.button(f"Challenge friends with a new game like {gid}", key=f"challenge_{gid}"):
902
- new_id = create_game(
903
- st.session_state.get("username", "Host"),
904
- g.get("topics", []),
905
- num_questions=len(g.get("questions", []))
906
- )
907
- st.session_state["active_game_id"] = new_id
908
- st.session_state["game_questions"] = games.get(new_id, {}).get("questions", [])
909
- st.success(f"Challenge created: {new_id}")
910
- st.experimental_rerun()
911
 
912
  # ---------------- WEEKLY LEADERBOARD ----------------
913
  st.subheader("๐Ÿ† Weekly Leaderboard (Top 10)")
@@ -918,87 +940,25 @@ def home_page():
918
  for i, r in enumerate(weekly, 1):
919
  st.write(f"{i}. {r.get('avatar','๐ŸŽฎ')} **{r['name']}** (Game {r['game_id']}) โ€” {r['score']} pts")
920
 
921
- # ---------------- PLAY PAGE SETUP ----------------
922
- if 'active_game' not in st.session_state:
923
- if games:
924
- st.session_state['active_game'] = list(games.keys())[0]
925
- else:
926
- st.warning("No games exist yet. Please create a game first.")
927
-
928
- if 'username' not in st.session_state:
929
- st.session_state['username'] = "Guest"
930
-
931
- # Safely update player submissions if a game is active
932
  active_game_id = st.session_state.get('active_game')
933
- if active_game_id and 'final_score' in st.session_state:
934
- game = unified_get(f"games/{active_game_id}") or {}
935
- players = game.get("players", [])
936
- username = st.session_state['username']
937
-
938
- if username not in players:
939
- players.append(username)
940
 
941
- submissions = game.get("submissions", {})
942
- submissions[username] = st.session_state['final_score']
 
943
 
944
- game["players"] = players
945
- game["submissions"] = submissions
946
- unified_set(f"games/{active_game_id}", game)
947
 
948
- def create_game(host=None, topics=[], num_questions=5, auto_close=True, ai_topic=None):
949
- games = unified_get("games") or {}
950
- gid = f"GAME{int(time.time())}"
951
- host = host or st.session_state.get("username", "Host")
952
-
953
- questions = []
954
-
955
- # 1๏ธโƒฃ AI questions (already dict format)
956
- if ai_topic:
957
- ai_questions = generate_ai_questions(ai_topic, num_questions=num_questions)
958
- if ai_questions:
959
- for q in ai_questions:
960
- questions.append({
961
- "question": q.get("question", ""),
962
- "options": q.get("options", []),
963
- "answer": q.get("answer", "")
964
- })
965
 
966
- # 2๏ธโƒฃ Static fallback (tuple โ†’ dict conversion)
967
- if not questions:
968
- for topic in topics:
969
- qs = questions_db.get(topic, [])
970
- for q in qs[:num_questions]:
971
- questions.append({
972
- "question": q[0],
973
- "options": q[1],
974
- "answer": q[2]
975
- })
976
-
977
- # ๐Ÿ”น Store game
978
- games[gid] = {
979
- "game_id": gid,
980
- "host": host,
981
- "topics": topics,
982
- "questions": questions,
983
- "created_at": now_iso(),
984
- "closed": False,
985
- "auto_close": auto_close
986
- }
987
-
988
- unified_set("games", games)
989
-
990
- # โœ… REQUIRED: prepare play state
991
- st.session_state['game_id'] = gid
992
- st.session_state['active_game_id'] = gid
993
- st.session_state['game_questions'] = questions
994
- st.session_state['current_index'] = 0
995
- st.session_state['answers'] = [""] * len(questions)
996
- st.session_state['answer_times'] = [None] * len(questions)
997
- st.session_state['question_started_at'] = None
998
-
999
- st.success(f"Game created: {gid} with {len(questions)} questions.")
1000
- return gid
1001
-
1002
  # -------------------------
1003
  # PLAY PAGE
1004
  # -------------------------
 
400
  # ---------------------------
401
  def unified_push_leaderboard(row):
402
  """
403
+ Push a row to leaderboard per game_id in Firebase and also local CSV.
 
404
  """
405
+ row = row.copy()
406
+ row["timestamp"] = datetime.utcnow().isoformat() + "Z"
407
+ game_id = row.get("game_id")
408
+ username = row.get("name")
409
 
410
  mode = st.session_state.get("mode_selection", "Offline")
411
 
412
  if mode == "Online":
413
  ok, _ = init_firebase_if_needed()
414
+ if ok and game_id and username:
415
+ # Push under game_id
416
+ ref = db.reference(f"/games/{game_id}/scores/{username}")
417
+ ref.set(row)
418
 
419
+ # Local CSV backup
420
  try:
421
  df = pd.read_csv(LEADERBOARD_FILE)
422
  except FileNotFoundError:
 
425
  df = pd.concat([df, pd.DataFrame([row])], ignore_index=True)
426
  df.to_csv(LEADERBOARD_FILE, index=False)
427
 
428
+ def show_game_leaderboard(game_id):
429
+ st.subheader(f"Leaderboard for Game {game_id}")
430
+
431
+ mode = st.session_state.get("mode_selection", "Offline")
432
+
433
+ rows = []
434
+ if mode == "Online":
435
+ ok, _ = init_firebase_if_needed()
436
+ if ok:
437
+ rows_dict = fb_get(f"/games/{game_id}/scores") or {}
438
+ rows = list(rows_dict.values())
439
+ else:
440
+ df = pd.read_csv(LEADERBOARD_FILE)
441
+ rows = df[df["game_id"]==game_id].to_dict(orient="records")
442
+
443
+ if not rows:
444
+ st.info("No scores yet for this game.")
445
+ return
446
+
447
+ rows.sort(key=lambda x: x.get("score",0), reverse=True)
448
+
449
+ for i, r in enumerate(rows, 1):
450
+ st.write(f"{i}. {r.get('avatar','๐ŸŽฎ')} **{r['name']}** โ€” {r.get('score')} pts")
451
+
452
  # ---------------------------
453
  # Get weekly leaderboard
454
  # ---------------------------
 
854
  # Home page
855
 
856
  HEARTBEAT_THRESHOLD_SECONDS = 60 # adjust if needed
 
857
  def home_page():
858
  st.header("Home")
859
  st.write("Create games, invite friends, play and climb the leaderboard.")
860
 
861
  # ---------------- TOTAL ONLINE PLAYERS ----------------
862
+ total_online = get_total_online_players()
 
863
  st.metric("๐ŸŸข Players Online", total_online)
864
 
865
  # ---------------- SHOW LAST SCORE ----------------
866
  last_score = st.session_state.get('last_score')
867
  last_game = st.session_state.get('last_game')
868
+ if last_score is not None and last_game:
869
  st.success(f"Your last score: {last_score} (Game {last_game})")
870
 
871
  # ---------------- LOAD GAMES ----------------
872
  games = unified_get("games") or {}
873
+ if not games:
874
+ st.info("No games exist yet. Please create a game first.")
875
+ return
876
 
877
+ st.subheader("Recent Games")
878
  for g in sorted(games.values(), key=lambda x: x.get("created_at", ""), reverse=True)[:10]:
879
  gid = g.get("game_id")
 
 
 
 
 
880
  st.markdown(f"### ๐ŸŽฎ Game: **{gid}** {'(Closed)' if g.get('closed') else ''}")
881
  st.write(f"Host: {g.get('host')} โ€” Topics: {', '.join(g.get('topics', []))}")
882
  st.write(f"Created: {g.get('created_at')}")
883
 
884
+ # Players & submissions
885
+ players = g.get("players", [])
886
+ submissions = g.get("submissions", {})
887
 
888
+ st.write(f"Players joined: **{len(players)}**")
889
+ st.write(f"Submitted: **{len(submissions)} / {len(players)}**")
890
 
891
+ # Top 3 players
892
  if submissions:
893
  st.markdown("๐Ÿ† **Top 3 Players**")
894
  top_players = sorted(submissions.items(), key=lambda x: x[1], reverse=True)[:3]
895
+ for i, (uname, score) in enumerate(top_players, start=1):
896
+ st.write(f"{i}. ๐ŸŽฎ **{uname}** โ€” {score} pts")
897
 
898
+ # Player status
899
  if players:
900
  st.markdown("**๐Ÿ‘ฅ Player Status**")
901
+ for uname in players:
902
+ if uname in submissions:
903
+ st.write(f"๐ŸŽฎ **{uname}** โ€” โœ… Submitted ({submissions[uname]} pts)")
904
  else:
905
+ st.write(f"๐ŸŽฎ **{uname}** โ€” โณ Playing")
906
 
907
  st.markdown("---")
908
 
909
+ # Invite & challenge friends
910
+ if not g.get("closed") and st.session_state.get("username"):
911
  st.info(f"Share this Game ID: {gid}")
912
  render_copy_button(gid, gid)
913
 
914
+ if st.button(f"Invite friends to {gid}", key=f"invite_{gid}"):
915
+ friends = get_friends_map().get(st.session_state["username"], [])
916
+ if not friends:
917
+ st.warning("No friends to invite.")
918
+ else:
919
+ for f in friends:
920
+ send_game_invite(st.session_state["username"], f, gid)
921
+ st.success("Invites sent to friends.")
922
+
923
+ if st.button(f"Challenge friends with a new game like {gid}", key=f"challenge_{gid}"):
924
+ new_id = create_game(
925
+ host=st.session_state.get("username", "Host"),
926
+ topics=g.get("topics", []),
927
+ num_questions=len(g.get("questions", []))
928
+ )
929
+ st.success(f"Challenge created: {new_id}")
930
+ st.session_state['active_game_id'] = new_id
931
+ st.session_state['game_questions'] = games.get(new_id, {}).get("questions", [])
932
+ st.experimental_rerun()
 
933
 
934
  # ---------------- WEEKLY LEADERBOARD ----------------
935
  st.subheader("๐Ÿ† Weekly Leaderboard (Top 10)")
 
940
  for i, r in enumerate(weekly, 1):
941
  st.write(f"{i}. {r.get('avatar','๐ŸŽฎ')} **{r['name']}** (Game {r['game_id']}) โ€” {r['score']} pts")
942
 
943
+ # ---------------- UPDATE ACTIVE GAME SUBMISSIONS ----------------
 
 
 
 
 
 
 
 
 
 
944
  active_game_id = st.session_state.get('active_game')
945
+ username = st.session_state.get('username')
946
+ if active_game_id and 'final_score' in st.session_state and username:
947
+ games = unified_get("games") or {}
948
+ game = games.get(active_game_id, {})
949
+ if game:
950
+ players = game.get("players", [])
951
+ submissions = game.get("submissions", {})
952
 
953
+ if username not in players:
954
+ players.append(username)
955
+ submissions[username] = st.session_state['final_score']
956
 
957
+ game["players"] = players
958
+ game["submissions"] = submissions
959
+ unified_set("games", {active_game_id: game})
960
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
961
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
962
  # -------------------------
963
  # PLAY PAGE
964
  # -------------------------