BhargavMN commited on
Commit Β·
64cf79d
1
Parent(s): 4c6c6bd
Enhance lobby UI with new styles: remove outer screen background, add room-code hint, copy-to-clipboard button, team-pick button states, and progress bar. Center prep status and improve host/guest instructions. Update pill styles for better visibility.
Browse files- app.py +94 -19
- app/data/sessions_store.json +1 -1
- app/ui/theme.py +70 -1
app.py
CHANGED
|
@@ -698,15 +698,52 @@ def code_html(session_id: str) -> str:
|
|
| 698 |
code = s.get("room_code", "ββββββ")
|
| 699 |
return (
|
| 700 |
"<div style='text-align:center'>"
|
| 701 |
-
"<div class='
|
| 702 |
f"<div class='cq-code'>{code}</div></div>"
|
| 703 |
)
|
| 704 |
|
| 705 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 706 |
def roster_html(session_id: str, me: str = "") -> str:
|
| 707 |
s = SESSION_STORE.get(session_id) or {}
|
| 708 |
host = s.get("host_name", "")
|
|
|
|
|
|
|
| 709 |
parts = ["<div style='display:flex;flex-direction:column;gap:14px'>"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 710 |
for t in s.get("teams", []):
|
| 711 |
members = [p for p in s.get("players", []) if p["team_id"] == t["id"]]
|
| 712 |
if members:
|
|
@@ -862,16 +899,26 @@ POLL_SLOW = 3.0
|
|
| 862 |
POLL_IDLE_LIMIT = 4 # identical ticks before easing off
|
| 863 |
|
| 864 |
|
| 865 |
-
def poll_tick(session_id, screen, team_id, player_name, poll_state):
|
| 866 |
nav = [gr.update()] * 7
|
| 867 |
new_screen = screen
|
| 868 |
lobby_code = lobby_roster = play_timer = play_status = wait_status = win_score = gr.update()
|
|
|
|
| 869 |
|
| 870 |
if session_id:
|
| 871 |
status = rooms.session_status(session_id)
|
| 872 |
if screen == "lobby":
|
| 873 |
lobby_code = code_html(session_id)
|
| 874 |
lobby_roster = roster_html(session_id, player_name)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 875 |
if status == "playing":
|
| 876 |
new_screen = "play"
|
| 877 |
nav = list(vis("play"))
|
|
@@ -903,7 +950,7 @@ def poll_tick(session_id, screen, team_id, player_name, poll_state):
|
|
| 903 |
timer_update = gr.Timer(target_iv) if target_iv != cur_iv else gr.update()
|
| 904 |
new_state = (sig, idle, target_iv)
|
| 905 |
|
| 906 |
-
return (*nav, new_screen, lobby_code, lobby_roster,
|
| 907 |
play_timer, play_status, wait_status, win_score, timer_update, new_state)
|
| 908 |
|
| 909 |
|
|
@@ -915,6 +962,27 @@ def wall_tick(session_id, screen, team_id, taskids):
|
|
| 915 |
|
| 916 |
|
| 917 |
# ββ Screen-action handlers ββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 918 |
def do_create(name, gtype, city, area, duration, teams_n, head_start,
|
| 919 |
difficulty, age_group, energy, players_n):
|
| 920 |
name = (name or "Host").strip() or "Host"
|
|
@@ -935,11 +1003,11 @@ def do_create(name, gtype, city, area, duration, teams_n, head_start,
|
|
| 935 |
}
|
| 936 |
rooms.create_room(name, config, session_id)
|
| 937 |
teams = rooms.list_teams(session_id)
|
| 938 |
-
tb =
|
| 939 |
-
tb += [gr.update(visible=False)] * (4 - len(teams))
|
| 940 |
return (*vis("lobby"), "lobby", session_id, name, teams[0]["id"], True,
|
| 941 |
code_html(session_id), roster_html(session_id, name),
|
| 942 |
-
gr.update(visible=True
|
|
|
|
| 943 |
|
| 944 |
|
| 945 |
def do_join(code, name):
|
|
@@ -948,25 +1016,27 @@ def do_join(code, name):
|
|
| 948 |
gr.Warning(msg)
|
| 949 |
return (*vis("join"), "join", "", "", "", False, f"β {msg}",
|
| 950 |
gr.update(), gr.update(), gr.update(visible=False),
|
|
|
|
| 951 |
*([gr.update(visible=False)] * 4))
|
| 952 |
gr.Info(f"Joined room β {msg}")
|
| 953 |
name = (name or "").strip()
|
| 954 |
teams = rooms.list_teams(session_id)
|
| 955 |
-
tb =
|
| 956 |
-
tb += [gr.update(visible=False)] * (4 - len(teams))
|
| 957 |
return (*vis("lobby"), "lobby", session_id, name, teams[0]["id"], False, f"β
{msg}",
|
| 958 |
code_html(session_id), roster_html(session_id, name),
|
| 959 |
-
gr.update(visible=False),
|
|
|
|
| 960 |
|
| 961 |
|
| 962 |
def make_pick(idx):
|
| 963 |
def _pick(session_id, player):
|
| 964 |
teams = rooms.list_teams(session_id)
|
| 965 |
if idx >= len(teams):
|
| 966 |
-
return gr.update(), gr.update()
|
| 967 |
tid = teams[idx]["id"]
|
| 968 |
rooms.pick_team(session_id, player, tid)
|
| 969 |
-
return tid, roster_html(session_id, player)
|
|
|
|
| 970 |
return _pick
|
| 971 |
|
| 972 |
|
|
@@ -1401,18 +1471,20 @@ with gr.Blocks(title="CityQuest Β· AI") as demo:
|
|
| 1401 |
with gr.Group(visible=False, elem_classes=["cq-screen"]) as g_lobby:
|
| 1402 |
with gr.Column(elem_classes=["cq-card"]):
|
| 1403 |
lobby_code = gr.HTML("")
|
|
|
|
| 1404 |
gr.HTML("<div class='section-label'>Pick your team</div>")
|
| 1405 |
with gr.Row():
|
| 1406 |
team_btn = [gr.Button("", variant="secondary", visible=False,
|
| 1407 |
elem_classes=["team-pick"]) for _ in range(4)]
|
| 1408 |
gr.HTML("<div class='section-label' style='margin-top:18px'>Who's here</div>")
|
| 1409 |
lobby_roster = gr.HTML("")
|
| 1410 |
-
lobby_prep = gr.HTML("")
|
| 1411 |
-
gr.Markdown(
|
| 1412 |
with gr.Row():
|
| 1413 |
lobby_leave = gr.Button("Leave", variant="secondary", elem_id="lobby-leave")
|
| 1414 |
lobby_start = gr.Button("Start the adventure β", variant="primary",
|
| 1415 |
-
visible=False,
|
|
|
|
| 1416 |
|
| 1417 |
# ββ SCREEN: PLAY ββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 1418 |
with gr.Group(visible=False, elem_classes=["cq-screen"]) as g_play:
|
|
@@ -1503,8 +1575,8 @@ with gr.Blocks(title="CityQuest Β· AI") as demo:
|
|
| 1503 |
# ββ Shared poll timer βββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 1504 |
poll = gr.Timer(1.5)
|
| 1505 |
nav_groups = [g_home, g_create, g_join, g_lobby, g_play, g_wait, g_win]
|
| 1506 |
-
poll.tick(poll_tick, inputs=[s_session, s_screen, s_team, s_player, s_poll_state],
|
| 1507 |
-
outputs=nav_groups + [s_screen, lobby_code, lobby_roster,
|
| 1508 |
play_timer, play_status, wait_status, win_scoreboard,
|
| 1509 |
poll, s_poll_state])
|
| 1510 |
poll.tick(wall_tick, inputs=[s_session, s_screen, s_team, s_taskids],
|
|
@@ -1537,17 +1609,20 @@ with gr.Blocks(title="CityQuest Β· AI") as demo:
|
|
| 1537 |
inputs=[c_name, c_type, c_city, c_area, c_duration, c_teams, c_headstart,
|
| 1538 |
c_diff, c_age, c_energy, c_players],
|
| 1539 |
outputs=nav_groups + [s_screen, s_session, s_player, s_team, s_host,
|
| 1540 |
-
lobby_code, lobby_roster, lobby_start
|
|
|
|
| 1541 |
).then(prepare_game, inputs=[s_session], outputs=[lobby_prep]
|
| 1542 |
).then(_btn_on, None, [create_submit])
|
| 1543 |
join_submit.click(
|
| 1544 |
do_join, inputs=[j_code, j_name],
|
| 1545 |
outputs=nav_groups + [s_screen, s_session, s_player, s_team, s_host,
|
| 1546 |
-
join_feedback, lobby_code, lobby_roster, lobby_start
|
|
|
|
| 1547 |
)
|
| 1548 |
|
| 1549 |
for i, tb in enumerate(team_btn):
|
| 1550 |
-
tb.click(make_pick(i), inputs=[s_session, s_player],
|
|
|
|
| 1551 |
|
| 1552 |
lobby_leave.click(do_leave, outputs=nav_groups + [s_screen, s_session, s_player, s_team, s_host])
|
| 1553 |
lobby_start.click(_btn_off, None, [lobby_start]).then(
|
|
|
|
| 698 |
code = s.get("room_code", "ββββββ")
|
| 699 |
return (
|
| 700 |
"<div style='text-align:center'>"
|
| 701 |
+
"<div class='cq-code-hint'>Share this code with your friends to join</div>"
|
| 702 |
f"<div class='cq-code'>{code}</div></div>"
|
| 703 |
)
|
| 704 |
|
| 705 |
|
| 706 |
+
def copy_btn_html(session_id: str) -> str:
|
| 707 |
+
"""A clipboard button beside the room code. Kept in its own (non-polled)
|
| 708 |
+
HTML component so the 'Copied!' state isn't reset by the 1.5s lobby poll.
|
| 709 |
+
Pure inline JS β Gradio can't reach the clipboard from Python."""
|
| 710 |
+
s = SESSION_STORE.get(session_id) or {}
|
| 711 |
+
code = s.get("room_code", "")
|
| 712 |
+
js = (
|
| 713 |
+
"var b=this;navigator.clipboard.writeText('" + code + "').then(function(){"
|
| 714 |
+
"b.classList.add('copied');var l=b.querySelector('.cq-copy-label');"
|
| 715 |
+
"if(l)l.textContent='β Copied!';"
|
| 716 |
+
"setTimeout(function(){b.classList.remove('copied');"
|
| 717 |
+
"if(l)l.textContent='π Copy';},2000);});"
|
| 718 |
+
)
|
| 719 |
+
return (
|
| 720 |
+
"<div class='cq-copy-wrap'>"
|
| 721 |
+
f"<button type='button' class='cq-copy-btn' onclick=\"{js}\">"
|
| 722 |
+
"<span class='cq-copy-label'>π Copy</span></button></div>"
|
| 723 |
+
)
|
| 724 |
+
|
| 725 |
+
|
| 726 |
+
def _teams_ready(session_id: str):
|
| 727 |
+
"""(teams_with_at_least_one_player, total_teams) for the lobby."""
|
| 728 |
+
s = SESSION_STORE.get(session_id) or {}
|
| 729 |
+
teams = s.get("teams", [])
|
| 730 |
+
have = {p["team_id"] for p in s.get("players", [])}
|
| 731 |
+
ready = sum(1 for t in teams if t["id"] in have)
|
| 732 |
+
return ready, len(teams)
|
| 733 |
+
|
| 734 |
+
|
| 735 |
def roster_html(session_id: str, me: str = "") -> str:
|
| 736 |
s = SESSION_STORE.get(session_id) or {}
|
| 737 |
host = s.get("host_name", "")
|
| 738 |
+
ready, total = _teams_ready(session_id)
|
| 739 |
+
pct = int(round(100 * ready / total)) if total else 0
|
| 740 |
parts = ["<div style='display:flex;flex-direction:column;gap:14px'>"]
|
| 741 |
+
parts.append(
|
| 742 |
+
"<div class='cq-progress'>"
|
| 743 |
+
f"<div class='cq-progress-label'>{ready} / {total} teams ready</div>"
|
| 744 |
+
"<div class='cq-progress-track'>"
|
| 745 |
+
f"<div class='cq-progress-fill' style='width:{pct}%'></div></div></div>"
|
| 746 |
+
)
|
| 747 |
for t in s.get("teams", []):
|
| 748 |
members = [p for p in s.get("players", []) if p["team_id"] == t["id"]]
|
| 749 |
if members:
|
|
|
|
| 899 |
POLL_IDLE_LIMIT = 4 # identical ticks before easing off
|
| 900 |
|
| 901 |
|
| 902 |
+
def poll_tick(session_id, screen, team_id, player_name, is_host, poll_state):
|
| 903 |
nav = [gr.update()] * 7
|
| 904 |
new_screen = screen
|
| 905 |
lobby_code = lobby_roster = play_timer = play_status = wait_status = win_score = gr.update()
|
| 906 |
+
lobby_start = lobby_hint = gr.update()
|
| 907 |
|
| 908 |
if session_id:
|
| 909 |
status = rooms.session_status(session_id)
|
| 910 |
if screen == "lobby":
|
| 911 |
lobby_code = code_html(session_id)
|
| 912 |
lobby_roster = roster_html(session_id, player_name)
|
| 913 |
+
# Keep Start enabled only once every team has a player, and keep the
|
| 914 |
+
# instruction line in sync with who's waiting on whom.
|
| 915 |
+
ready, total = _teams_ready(session_id)
|
| 916 |
+
all_ready = total > 0 and ready == total
|
| 917 |
+
lobby_start = gr.update(interactive=all_ready)
|
| 918 |
+
if is_host:
|
| 919 |
+
lobby_hint = HINT_HOST_READY if all_ready else HINT_HOST_WAIT
|
| 920 |
+
else:
|
| 921 |
+
lobby_hint = HINT_GUEST
|
| 922 |
if status == "playing":
|
| 923 |
new_screen = "play"
|
| 924 |
nav = list(vis("play"))
|
|
|
|
| 950 |
timer_update = gr.Timer(target_iv) if target_iv != cur_iv else gr.update()
|
| 951 |
new_state = (sig, idle, target_iv)
|
| 952 |
|
| 953 |
+
return (*nav, new_screen, lobby_code, lobby_roster, lobby_start, lobby_hint,
|
| 954 |
play_timer, play_status, wait_status, win_score, timer_update, new_state)
|
| 955 |
|
| 956 |
|
|
|
|
| 962 |
|
| 963 |
|
| 964 |
# ββ Screen-action handlers ββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 965 |
+
# Lobby instruction copy β differs for the host vs. everyone else.
|
| 966 |
+
HINT_HOST_WAIT = "β³ Waiting for every team to have at least one playerβ¦"
|
| 967 |
+
HINT_HOST_READY = "β
Everyone's in β start the adventure whenever you're ready."
|
| 968 |
+
HINT_GUEST = "β³ Waiting for the host to start the adventureβ¦"
|
| 969 |
+
|
| 970 |
+
|
| 971 |
+
def _team_btn_updates(session_id, selected_id):
|
| 972 |
+
"""Button updates for the 4 team-pick slots: label + visibility, with the
|
| 973 |
+
player's current team flagged 'selected' so it reads as chosen (green)."""
|
| 974 |
+
teams = rooms.list_teams(session_id)
|
| 975 |
+
ups = []
|
| 976 |
+
for i in range(4):
|
| 977 |
+
if i < len(teams):
|
| 978 |
+
cls = ["team-pick", "selected"] if teams[i]["id"] == selected_id else ["team-pick"]
|
| 979 |
+
ups.append(gr.update(value=f"{teams[i]['name']} Β· {teams[i]['role']}",
|
| 980 |
+
visible=True, elem_classes=cls))
|
| 981 |
+
else:
|
| 982 |
+
ups.append(gr.update(visible=False))
|
| 983 |
+
return ups
|
| 984 |
+
|
| 985 |
+
|
| 986 |
def do_create(name, gtype, city, area, duration, teams_n, head_start,
|
| 987 |
difficulty, age_group, energy, players_n):
|
| 988 |
name = (name or "Host").strip() or "Host"
|
|
|
|
| 1003 |
}
|
| 1004 |
rooms.create_room(name, config, session_id)
|
| 1005 |
teams = rooms.list_teams(session_id)
|
| 1006 |
+
tb = _team_btn_updates(session_id, teams[0]["id"])
|
|
|
|
| 1007 |
return (*vis("lobby"), "lobby", session_id, name, teams[0]["id"], True,
|
| 1008 |
code_html(session_id), roster_html(session_id, name),
|
| 1009 |
+
gr.update(visible=True, interactive=False),
|
| 1010 |
+
copy_btn_html(session_id), HINT_HOST_WAIT, *tb)
|
| 1011 |
|
| 1012 |
|
| 1013 |
def do_join(code, name):
|
|
|
|
| 1016 |
gr.Warning(msg)
|
| 1017 |
return (*vis("join"), "join", "", "", "", False, f"β {msg}",
|
| 1018 |
gr.update(), gr.update(), gr.update(visible=False),
|
| 1019 |
+
gr.update(), gr.update(),
|
| 1020 |
*([gr.update(visible=False)] * 4))
|
| 1021 |
gr.Info(f"Joined room β {msg}")
|
| 1022 |
name = (name or "").strip()
|
| 1023 |
teams = rooms.list_teams(session_id)
|
| 1024 |
+
tb = _team_btn_updates(session_id, teams[0]["id"])
|
|
|
|
| 1025 |
return (*vis("lobby"), "lobby", session_id, name, teams[0]["id"], False, f"β
{msg}",
|
| 1026 |
code_html(session_id), roster_html(session_id, name),
|
| 1027 |
+
gr.update(visible=False),
|
| 1028 |
+
copy_btn_html(session_id), HINT_GUEST, *tb)
|
| 1029 |
|
| 1030 |
|
| 1031 |
def make_pick(idx):
|
| 1032 |
def _pick(session_id, player):
|
| 1033 |
teams = rooms.list_teams(session_id)
|
| 1034 |
if idx >= len(teams):
|
| 1035 |
+
return (gr.update(), gr.update(), *([gr.update()] * 4))
|
| 1036 |
tid = teams[idx]["id"]
|
| 1037 |
rooms.pick_team(session_id, player, tid)
|
| 1038 |
+
return (tid, roster_html(session_id, player),
|
| 1039 |
+
*_team_btn_updates(session_id, tid))
|
| 1040 |
return _pick
|
| 1041 |
|
| 1042 |
|
|
|
|
| 1471 |
with gr.Group(visible=False, elem_classes=["cq-screen"]) as g_lobby:
|
| 1472 |
with gr.Column(elem_classes=["cq-card"]):
|
| 1473 |
lobby_code = gr.HTML("")
|
| 1474 |
+
lobby_copy = gr.HTML("")
|
| 1475 |
gr.HTML("<div class='section-label'>Pick your team</div>")
|
| 1476 |
with gr.Row():
|
| 1477 |
team_btn = [gr.Button("", variant="secondary", visible=False,
|
| 1478 |
elem_classes=["team-pick"]) for _ in range(4)]
|
| 1479 |
gr.HTML("<div class='section-label' style='margin-top:18px'>Who's here</div>")
|
| 1480 |
lobby_roster = gr.HTML("")
|
| 1481 |
+
lobby_prep = gr.HTML("", elem_classes=["lobby-prep"])
|
| 1482 |
+
lobby_hint = gr.Markdown(HINT_GUEST, elem_classes=["lobby-hint"])
|
| 1483 |
with gr.Row():
|
| 1484 |
lobby_leave = gr.Button("Leave", variant="secondary", elem_id="lobby-leave")
|
| 1485 |
lobby_start = gr.Button("Start the adventure β", variant="primary",
|
| 1486 |
+
visible=False, interactive=False,
|
| 1487 |
+
elem_id="lobby-start", elem_classes=["lobby-start-btn"])
|
| 1488 |
|
| 1489 |
# ββ SCREEN: PLAY ββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 1490 |
with gr.Group(visible=False, elem_classes=["cq-screen"]) as g_play:
|
|
|
|
| 1575 |
# ββ Shared poll timer βββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 1576 |
poll = gr.Timer(1.5)
|
| 1577 |
nav_groups = [g_home, g_create, g_join, g_lobby, g_play, g_wait, g_win]
|
| 1578 |
+
poll.tick(poll_tick, inputs=[s_session, s_screen, s_team, s_player, s_host, s_poll_state],
|
| 1579 |
+
outputs=nav_groups + [s_screen, lobby_code, lobby_roster, lobby_start, lobby_hint,
|
| 1580 |
play_timer, play_status, wait_status, win_scoreboard,
|
| 1581 |
poll, s_poll_state])
|
| 1582 |
poll.tick(wall_tick, inputs=[s_session, s_screen, s_team, s_taskids],
|
|
|
|
| 1609 |
inputs=[c_name, c_type, c_city, c_area, c_duration, c_teams, c_headstart,
|
| 1610 |
c_diff, c_age, c_energy, c_players],
|
| 1611 |
outputs=nav_groups + [s_screen, s_session, s_player, s_team, s_host,
|
| 1612 |
+
lobby_code, lobby_roster, lobby_start,
|
| 1613 |
+
lobby_copy, lobby_hint] + team_btn,
|
| 1614 |
).then(prepare_game, inputs=[s_session], outputs=[lobby_prep]
|
| 1615 |
).then(_btn_on, None, [create_submit])
|
| 1616 |
join_submit.click(
|
| 1617 |
do_join, inputs=[j_code, j_name],
|
| 1618 |
outputs=nav_groups + [s_screen, s_session, s_player, s_team, s_host,
|
| 1619 |
+
join_feedback, lobby_code, lobby_roster, lobby_start,
|
| 1620 |
+
lobby_copy, lobby_hint] + team_btn,
|
| 1621 |
)
|
| 1622 |
|
| 1623 |
for i, tb in enumerate(team_btn):
|
| 1624 |
+
tb.click(make_pick(i), inputs=[s_session, s_player],
|
| 1625 |
+
outputs=[s_team, lobby_roster] + team_btn)
|
| 1626 |
|
| 1627 |
lobby_leave.click(do_leave, outputs=nav_groups + [s_screen, s_session, s_player, s_team, s_host])
|
| 1628 |
lobby_start.click(_btn_off, None, [lobby_start]).then(
|
app/data/sessions_store.json
CHANGED
|
@@ -1 +1 @@
|
|
| 1 |
-
{"codes": {"75ZKFE": "9fcb0953-4e36-4485-9bbe-fad577de31fa", "JWR5RV": "6b1af473-b00b-44ae-bffc-7b8e93616767", "NKPZKT": "32e1bbe3-50a1-4e43-a7c2-8ecf3f781550", "NXWHQK": "4b03fbfc-4326-4325-8975-e4216c44e03e", "VMJVMF": "2cfd0fef-a118-4044-a9bd-2583e60b56e1", "EHPYXY": "720ab67a-9428-4c7b-a01e-de3d393d6a96", "Y3ZTX5": "15c4e4e1-c8e9-4f40-be4e-9606abd41f9d", "GY4QMQ": "b56f7a32-961f-4001-be35-503866b95227", "HZWQB4": "a549cbe3-e796-4ca5-9f00-78ea47eb9704", "FHGKNU": "e1e90fde-7eb5-4a56-a2ee-edd451b3c099", "P4XT35": "136f317b-5d93-4b30-aa0a-7a8f501dde2f", "QN4J62": "47bdfb37-1bb6-4346-8d9c-5c23d4c6f164", "EHSFKC": "f02216a5-19f8-46cf-8d52-7dd74eeafb65", "5VDVSH": "26e9880a-4d33-4e4a-a773-a00f097c9c83", "QVTJKG": "70959adc-6172-41e6-ae4f-ef8f90772dba"}, "sessions": {"9fcb0953-4e36-4485-9bbe-fad577de31fa": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Le Marais", "location_type": "mixed", "duration_minutes": 60, "num_players": 2, "difficulty": "easy", "age_group": "adults", "energy_level": "low", "photo_enabled": true}, "room_code": null, "host_name": null, "status": null, "teams": ["team-a", "team-b"], "players": [{"name": "Player 1", "team_id": "team-a"}, {"name": "play 2", "team_id": "team-b"}, {"name": "hola", "team_id": "team-b"}], "game": {"game_id": "mock-8506e14a", "title": "Scavenger_Hunt in Le Marais", "theme": "easy adventure", "setup": {"city": "Paris", "area": "Le Marais", "meeting_point": "Main entrance of Le Marais", "duration_minutes": 60, "num_players": 2}, "rules": ["Complete as many tasks as possible within 60 minutes", "Take photos or notes as proof of completion", "Stay within the designated area at all times", "No entering private buildings or restricted areas", "This game is suitable for adults"], "tasks": [{"task_id": "t1", "title": "Task 1: Explore the main square", "description": "Find and document something interesting in the main square", "location_hint": "Navigate to the main square and look for distinctive features", "points": 15, "time_limit_minutes": 8, "proof_type": "photo", "hint": "Look for signs or landmarks in the main square", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t2", "title": "Task 2: Explore the city center", "description": "Find and document something interesting in the city center", "location_hint": "Navigate to the city center and look for distinctive features", "points": 20, "time_limit_minutes": 10, "proof_type": "observation", "hint": "Look for signs or landmarks in the city center", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t3", "title": "Task 3: Explore the park area", "description": "Find and document something interesting in the park area", "location_hint": "Navigate to the park area and look for distinctive features", "points": 25, "time_limit_minutes": 12, "proof_type": "text", "hint": "Look for signs or landmarks in the park area", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t4", "title": "Task 4: Explore the landmark district", "description": "Find and document something interesting in the landmark district", "location_hint": "Navigate to the landmark district and look for distinctive features", "points": 30, "time_limit_minutes": 14, "proof_type": "photo", "hint": "Look for signs or landmarks in the landmark district", "safety_note": "Stay on public paths and avoid restricted areas"}], "global_hints": ["Explore systematically from the meeting point outward", "Ask locals for directions if needed", "Time management is key - don't spend too long on any single task"], "score_rules": ["Each task completed: full points", "Early completion: +1 bonus point per minute under limit", "Hints used: -5 points per hint", "Late arrival at meeting point: -10 points per minute"], "tie_breaker": "Winner is the player with the most points when time expires. Ties broken by earliest completion time.", "safety": {"allowed_zone": "Le Marais", "forbidden_behaviors": ["Entering buildings without permission", "Crossing busy streets recklessly", "Approaching strangers", "Leaving the designated area"], "adult_supervision": false, "stop_conditions": ["If a player feels unsafe, the game stops immediately", "If weather becomes severe, relocate to shelter", "If anyone is injured, call emergency services"]}, "story_seed": {"tone": "playful", "motifs": ["exploration", "discovery", "teamwork"], "recap_style": "episode_recap"}}, "host_started_at": null, "team_start_offsets": null, "team_finished": null, "photos": [{"photo_id": "photo-71c44ee8", "photo_name": "", "caption": "", "task_id": "t1"}]}, "6b1af473-b00b-44ae-bffc-7b8e93616767": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Le Marais", "location_type": "mixed", "duration_minutes": 60, "num_players": 2, "difficulty": "easy", "age_group": "adults", "energy_level": "low", "photo_enabled": true}, "room_code": null, "host_name": null, "status": null, "teams": ["team-a", "team-b"], "players": [{"name": "Player 1", "team_id": "team-a"}], "game": {"game_id": "mock-6d6ab9cf", "title": "Scavenger_Hunt in Le Marais", "theme": "easy adventure", "setup": {"city": "Paris", "area": "Le Marais", "meeting_point": "Main entrance of Le Marais", "duration_minutes": 60, "num_players": 2}, "rules": ["Complete as many tasks as possible within 60 minutes", "Take photos or notes as proof of completion", "Stay within the designated area at all times", "No entering private buildings or restricted areas", "This game is suitable for adults"], "tasks": [{"task_id": "t1", "title": "Task 1: Explore the main square", "description": "Find and document something interesting in the main square", "location_hint": "Navigate to the main square and look for distinctive features", "points": 15, "time_limit_minutes": 8, "proof_type": "photo", "hint": "Look for signs or landmarks in the main square", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t2", "title": "Task 2: Explore the city center", "description": "Find and document something interesting in the city center", "location_hint": "Navigate to the city center and look for distinctive features", "points": 20, "time_limit_minutes": 10, "proof_type": "observation", "hint": "Look for signs or landmarks in the city center", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t3", "title": "Task 3: Explore the park area", "description": "Find and document something interesting in the park area", "location_hint": "Navigate to the park area and look for distinctive features", "points": 25, "time_limit_minutes": 12, "proof_type": "text", "hint": "Look for signs or landmarks in the park area", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t4", "title": "Task 4: Explore the landmark district", "description": "Find and document something interesting in the landmark district", "location_hint": "Navigate to the landmark district and look for distinctive features", "points": 30, "time_limit_minutes": 14, "proof_type": "photo", "hint": "Look for signs or landmarks in the landmark district", "safety_note": "Stay on public paths and avoid restricted areas"}], "global_hints": ["Explore systematically from the meeting point outward", "Ask locals for directions if needed", "Time management is key - don't spend too long on any single task"], "score_rules": ["Each task completed: full points", "Early completion: +1 bonus point per minute under limit", "Hints used: -5 points per hint", "Late arrival at meeting point: -10 points per minute"], "tie_breaker": "Winner is the player with the most points when time expires. Ties broken by earliest completion time.", "safety": {"allowed_zone": "Le Marais", "forbidden_behaviors": ["Entering buildings without permission", "Crossing busy streets recklessly", "Approaching strangers", "Leaving the designated area"], "adult_supervision": false, "stop_conditions": ["If a player feels unsafe, the game stops immediately", "If weather becomes severe, relocate to shelter", "If anyone is injured, call emergency services"]}, "story_seed": {"tone": "playful", "motifs": ["exploration", "discovery", "teamwork"], "recap_style": "episode_recap"}}, "host_started_at": null, "team_start_offsets": null, "team_finished": null, "photos": []}, "32e1bbe3-50a1-4e43-a7c2-8ecf3f781550": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Le Marais", "location_type": "mixed", "duration_minutes": 60, "num_players": 4, "difficulty": "medium", "age_group": "adults", "energy_level": "medium", "photo_enabled": true}, "room_code": null, "host_name": null, "status": null, "teams": ["team-a", "team-b"], "players": [{"name": "Nithin", "team_id": "team-a"}], "game": {"game_id": "game_042", "title": "Le Marais Mystery Hunt", "theme": "Scavenger Hunt", "setup": {"city": "Paris", "area": "Le Marais", "meeting_point": "Place des Vosges", "duration_minutes": 60, "num_players": 4}, "rules": ["Stay within Le Marais boundaries", "No entering buildings or private property", "No proximity to water, traffic, or rail lines", "No interacting with strangers", "All tasks must be observed, no purchases"], "tasks": [{"task_id": "t1", "title": "Historic Fountain", "description": "Observe the historic fountain at Place des Vosges.", "location_hint": "Place des Vosges", "points": 20, "time_limit_minutes": null, "proof_type": "observation", "hint": "Look for the historic fountain", "safety_note": "Only observe, no touching or entering"}, {"task_id": "t2", "title": "Colorful Door", "description": "Observe the colorful door on Rue des Rosiers.", "location_hint": "Rue des Rosiers", "points": 15, "time_limit_minutes": null, "proof_type": "observation", "hint": "Look for the colorful door", "safety_note": "Only observe, no touching or entering"}, {"task_id": "t3", "title": "Task 3", "description": "Explore and discover something interesting in the area", "location_hint": "Look around the central area", "points": 25, "time_limit_minutes": null, "proof_type": "text", "hint": "Check visible landmarks and signs for clues", "safety_note": "Stay on public paths and respect local rules"}], "global_hints": ["Le Marais is a historic district", "All tasks are observation-based"], "score_rules": ["Higher points win", "Tie broken by total points"], "tie_breaker": "Highest total points wins", "safety": {"allowed_zone": "Le Marais public streets and parks", "forbidden_behaviors": ["Entering buildings or private property", "Proximity to water, traffic, or rail lines", "Interacting with strangers", "Purchasing items"], "adult_supervision": false, "stop_conditions": ["All tasks completed", "Time limit 60 minutes reached", "Any rule violation"]}, "story_seed": {"tone": "playful", "motifs": ["historic architecture", "urban exploration"], "recap_style": "Summarize each player's observations and points"}}, "host_started_at": null, "team_start_offsets": null, "team_finished": null, "photos": []}, "4b03fbfc-4326-4325-8975-e4216c44e03e": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Le Marais", "location_type": "mixed", "duration_minutes": 60, "num_players": 4, "difficulty": "medium", "age_group": "adults", "energy_level": "medium", "photo_enabled": true}, "room_code": null, "host_name": null, "status": null, "teams": ["team-a", "team-b"], "players": [{"name": "Nithin", "team_id": "team-a"}], "game": {"game_id": "game_042", "title": "Le Marais Mystery Hunt", "theme": "Observational scavenger hunt", "setup": {"city": "Paris", "area": "Le Marais", "meeting_point": "Place des Vosges", "duration_minutes": 60, "num_players": 4}, "rules": ["Stay within Le Marais boundaries", "No entering buildings or private property", "No crossing traffic or water", "No interacting with strangers", "No purchases", "All tasks are observation only"], "tasks": [{"task_id": "t1", "title": "Vosges View", "description": "Find the historic square Place des Vosges and note its symmetrical layout.", "location_hint": "Place des Vosges", "points": 20, "time_limit_minutes": null, "proof_type": "observation", "hint": "Look for the central fountain", "safety_note": "Stay on pavement, no building entry"}, {"task_id": "t2", "title": "Rue des Rosiers", "description": "Observe the vibrant street market stalls and colorful awnings.", "location_hint": "Rue des Rosiers", "points": 15, "time_limit_minutes": null, "proof_type": "observation", "hint": "Notice the flower displays", "safety_note": "No entering stalls"}, {"task_id": "t3", "title": "H\u00f4tel de Ville View", "description": "Observe the fa\u00e7ade of the H\u00f4tel de Ville from the street.", "location_hint": "Place des Vosges near H\u00f4tel de Ville", "points": 20, "time_limit_minutes": null, "proof_type": "observation", "hint": "Look for the clock tower", "safety_note": "No entering building"}], "global_hints": ["Stay within Le Marais", "Use observation only", "No purchases"], "score_rules": ["Highest points wins", "All tasks completed for bonus"], "tie_breaker": "First player to reach 50 points wins", "safety": {"allowed_zone": "Le Marais streets and public squares", "forbidden_behaviors": ["Entering buildings", "Crossing traffic", "Approaching water", "Interacting with strangers", "Purchasing items"], "adult_supervision": true, "stop_conditions": ["Time limit 60 minutes", "Safety breach", "All tasks completed"]}, "story_seed": {"tone": "playful", "motifs": ["hidden clues", "Parisian charm", "observation"], "recap_style": "Gather at the meeting point for a recap of findings."}}, "host_started_at": null, "team_start_offsets": null, "team_finished": null, "photos": []}, "2cfd0fef-a118-4044-a9bd-2583e60b56e1": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 45, "num_players": 4, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "VMJVMF", "host_name": "Host", "status": "lobby", "teams": [{"id": "team-a", "name": "River", "role": "Explorers"}, {"id": "team-b", "name": "Meadow", "role": "Explorers"}], "players": [{"name": "Host", "team_id": "team-a"}], "game": {"game_id": "mock-50dd0c65", "game_type": "scavenger_hunt", "title": "Scavenger_Hunt in Downtown", "theme": "medium adventure", "setup": {"city": "Paris", "area": "Downtown", "meeting_point": "Main entrance of Downtown", "duration_minutes": 45, "num_players": 4}, "rules": ["Complete as many tasks as possible within 45 minutes", "Take photos or notes as proof of completion", "Stay within the designated area at all times", "No entering private buildings or restricted areas", "This game is suitable for all"], "tasks": [{"task_id": "t1", "title": "Task 1: Explore the main square", "description": "Find and document something interesting in the main square", "location_hint": "Navigate to the main square and look for distinctive features", "points": 15, "time_limit_minutes": 8, "proof_type": "photo", "hint": "Look for signs or landmarks in the main square", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t2", "title": "Task 2: Explore the city center", "description": "Find and document something interesting in the city center", "location_hint": "Navigate to the city center and look for distinctive features", "points": 20, "time_limit_minutes": 10, "proof_type": "observation", "hint": "Look for signs or landmarks in the city center", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t3", "title": "Task 3: Explore the park area", "description": "Find and document something interesting in the park area", "location_hint": "Navigate to the park area and look for distinctive features", "points": 25, "time_limit_minutes": 12, "proof_type": "text", "hint": "Look for signs or landmarks in the park area", "safety_note": "Stay on public paths and avoid restricted areas"}], "global_hints": ["Explore systematically from the meeting point outward", "Ask locals for directions if needed", "Time management is key - don't spend too long on any single task"], "score_rules": ["Each task completed: full points", "Early completion: +1 bonus point per minute under limit", "Hints used: -5 points per hint", "Late arrival at meeting point: -10 points per minute"], "tie_breaker": "Winner is the player with the most points when time expires. Ties broken by earliest completion time.", "safety": {"allowed_zone": "Downtown", "forbidden_behaviors": ["Entering buildings without permission", "Crossing busy streets recklessly", "Approaching strangers", "Leaving the designated area"], "adult_supervision": false, "stop_conditions": ["If a player feels unsafe, the game stops immediately", "If weather becomes severe, relocate to shelter", "If anyone is injured, call emergency services"]}, "story_seed": {"tone": "playful", "motifs": ["exploration", "discovery", "teamwork"], "recap_style": "episode_recap"}}, "host_started_at": null, "team_start_offsets": {}, "team_finished": {}, "photos": []}, "720ab67a-9428-4c7b-a01e-de3d393d6a96": {"config": {"game_type": "hide_and_seek", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 45, "num_players": 4, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "EHPYXY", "host_name": "Host", "status": "lobby", "teams": [{"id": "team-a", "name": "River", "role": "Hiders"}, {"id": "team-b", "name": "Meadow", "role": "Seekers"}], "players": [{"name": "Host", "team_id": "team-a"}], "game": {"game_id": "mock-15f50146", "game_type": "hide_and_seek", "title": "Hide_And_Seek in Downtown", "theme": "medium adventure", "setup": {"city": "Paris", "area": "Downtown", "meeting_point": "Main entrance of Downtown", "duration_minutes": 45, "num_players": 4}, "rules": ["Complete as many tasks as possible within 45 minutes", "Take photos or notes as proof of completion", "Stay within the designated area at all times", "No entering private buildings or restricted areas", "This game is suitable for all"], "tasks": [{"task_id": "t1", "title": "Task 1: Explore the main square", "description": "Find and document something interesting in the main square", "location_hint": "Navigate to the main square and look for distinctive features", "points": 15, "time_limit_minutes": 8, "proof_type": "photo", "hint": "Look for signs or landmarks in the main square", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t2", "title": "Task 2: Explore the city center", "description": "Find and document something interesting in the city center", "location_hint": "Navigate to the city center and look for distinctive features", "points": 20, "time_limit_minutes": 10, "proof_type": "observation", "hint": "Look for signs or landmarks in the city center", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t3", "title": "Task 3: Explore the park area", "description": "Find and document something interesting in the park area", "location_hint": "Navigate to the park area and look for distinctive features", "points": 25, "time_limit_minutes": 12, "proof_type": "text", "hint": "Look for signs or landmarks in the park area", "safety_note": "Stay on public paths and avoid restricted areas"}], "global_hints": ["Explore systematically from the meeting point outward", "Ask locals for directions if needed", "Time management is key - don't spend too long on any single task"], "score_rules": ["Each task completed: full points", "Early completion: +1 bonus point per minute under limit", "Hints used: -5 points per hint", "Late arrival at meeting point: -10 points per minute"], "tie_breaker": "Winner is the player with the most points when time expires. Ties broken by earliest completion time.", "safety": {"allowed_zone": "Downtown", "forbidden_behaviors": ["Entering buildings without permission", "Crossing busy streets recklessly", "Approaching strangers", "Leaving the designated area"], "adult_supervision": false, "stop_conditions": ["If a player feels unsafe, the game stops immediately", "If weather becomes severe, relocate to shelter", "If anyone is injured, call emergency services"]}, "story_seed": {"tone": "playful", "motifs": ["exploration", "discovery", "teamwork"], "recap_style": "episode_recap"}}, "host_started_at": null, "team_start_offsets": {}, "team_finished": {}, "photos": []}, "15c4e4e1-c8e9-4f40-be4e-9606abd41f9d": {"config": {"game_type": "tag", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 45, "num_players": 4, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "Y3ZTX5", "host_name": "Host", "status": "finished", "teams": [{"id": "team-a", "name": "River", "role": "Runners"}, {"id": "team-b", "name": "Meadow", "role": "Chasers"}], "players": [{"name": "Host", "team_id": "team-a"}, {"name": "jkjlkj", "team_id": "team-b"}], "game": {"game_id": "mock-f949048c", "game_type": "tag", "title": "Tag in Downtown", "theme": "medium adventure", "setup": {"city": "Paris", "area": "Downtown", "meeting_point": "Main entrance of Downtown", "duration_minutes": 45, "num_players": 4}, "rules": ["Complete as many tasks as possible within 45 minutes", "Take photos or notes as proof of completion", "Stay within the designated area at all times", "No entering private buildings or restricted areas", "This game is suitable for all"], "tasks": [{"task_id": "t1", "title": "Task 1: Explore the main square", "description": "Find and document something interesting in the main square", "location_hint": "Navigate to the main square and look for distinctive features", "points": 15, "time_limit_minutes": 8, "proof_type": "photo", "hint": "Look for signs or landmarks in the main square", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t2", "title": "Task 2: Explore the city center", "description": "Find and document something interesting in the city center", "location_hint": "Navigate to the city center and look for distinctive features", "points": 20, "time_limit_minutes": 10, "proof_type": "observation", "hint": "Look for signs or landmarks in the city center", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t3", "title": "Task 3: Explore the park area", "description": "Find and document something interesting in the park area", "location_hint": "Navigate to the park area and look for distinctive features", "points": 25, "time_limit_minutes": 12, "proof_type": "text", "hint": "Look for signs or landmarks in the park area", "safety_note": "Stay on public paths and avoid restricted areas"}], "global_hints": ["Explore systematically from the meeting point outward", "Ask locals for directions if needed", "Time management is key - don't spend too long on any single task"], "score_rules": ["Each task completed: full points", "Early completion: +1 bonus point per minute under limit", "Hints used: -5 points per hint", "Late arrival at meeting point: -10 points per minute"], "tie_breaker": "Winner is the player with the most points when time expires. Ties broken by earliest completion time.", "safety": {"allowed_zone": "Downtown", "forbidden_behaviors": ["Entering buildings without permission", "Crossing busy streets recklessly", "Approaching strangers", "Leaving the designated area"], "adult_supervision": false, "stop_conditions": ["If a player feels unsafe, the game stops immediately", "If weather becomes severe, relocate to shelter", "If anyone is injured, call emergency services"]}, "story_seed": {"tone": "playful", "motifs": ["exploration", "discovery", "teamwork"], "recap_style": "episode_recap"}}, "host_started_at": "2026-06-12T16:03:57.108418+00:00", "team_start_offsets": {"team-a": 0, "team-b": 60}, "team_finished": {"team-b": "2026-06-12T16:05:24.467878+00:00", "team-a": "2026-06-12T16:05:31.049593+00:00"}, "photos": []}, "b56f7a32-961f-4001-be35-503866b95227": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 45, "num_players": 4, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "GY4QMQ", "host_name": "Host", "status": "lobby", "teams": [{"id": "team-a", "name": "River", "role": "Explorers"}, {"id": "team-b", "name": "Meadow", "role": "Explorers"}], "players": [{"name": "Host", "team_id": "team-a"}], "game": null, "host_started_at": null, "team_start_offsets": {}, "team_finished": {}, "photos": []}, "a549cbe3-e796-4ca5-9f00-78ea47eb9704": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 45, "num_players": 4, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "HZWQB4", "host_name": "Host", "status": "playing", "teams": [{"id": "team-a", "name": "River", "role": "Explorers"}, {"id": "team-b", "name": "Meadow", "role": "Explorers"}], "players": [{"name": "Host", "team_id": "team-a"}], "game": {"game_id": "mock-eb9ec682", "game_type": "scavenger_hunt", "title": "Scavenger_Hunt in Downtown", "theme": "medium adventure", "setup": {"city": "Paris", "area": "Downtown", "meeting_point": "Main entrance of Downtown", "duration_minutes": 45, "num_players": 4}, "rules": ["Complete as many tasks as possible within 45 minutes", "Take photos or notes as proof of completion", "Stay within the designated area at all times", "No entering private buildings or restricted areas", "This game is suitable for all"], "tasks": [{"task_id": "t1", "title": "Task 1: Explore the main square", "description": "Find and document something interesting in the main square", "location_hint": "Navigate to the main square and look for distinctive features", "points": 15, "time_limit_minutes": 8, "proof_type": "photo", "hint": "Look for signs or landmarks in the main square", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t2", "title": "Task 2: Explore the city center", "description": "Find and document something interesting in the city center", "location_hint": "Navigate to the city center and look for distinctive features", "points": 20, "time_limit_minutes": 10, "proof_type": "observation", "hint": "Look for signs or landmarks in the city center", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t3", "title": "Task 3: Explore the park area", "description": "Find and document something interesting in the park area", "location_hint": "Navigate to the park area and look for distinctive features", "points": 25, "time_limit_minutes": 12, "proof_type": "text", "hint": "Look for signs or landmarks in the park area", "safety_note": "Stay on public paths and avoid restricted areas"}], "global_hints": ["Explore systematically from the meeting point outward", "Ask locals for directions if needed", "Time management is key - don't spend too long on any single task"], "score_rules": ["Each task completed: full points", "Early completion: +1 bonus point per minute under limit", "Hints used: -5 points per hint", "Late arrival at meeting point: -10 points per minute"], "tie_breaker": "Winner is the player with the most points when time expires. Ties broken by earliest completion time.", "safety": {"allowed_zone": "Downtown", "forbidden_behaviors": ["Entering buildings without permission", "Crossing busy streets recklessly", "Approaching strangers", "Leaving the designated area"], "adult_supervision": false, "stop_conditions": ["If a player feels unsafe, the game stops immediately", "If weather becomes severe, relocate to shelter", "If anyone is injured, call emergency services"]}, "story_seed": {"tone": "playful", "motifs": ["exploration", "discovery", "teamwork"], "recap_style": "episode_recap"}}, "host_started_at": "2026-06-12T16:59:08.914806+00:00", "team_start_offsets": {"team-a": 0, "team-b": 60}, "team_finished": {}, "photos": []}, "e1e90fde-7eb5-4a56-a2ee-edd451b3c099": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 45, "num_players": 4, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "FHGKNU", "host_name": "Host", "status": "lobby", "teams": [{"id": "team-a", "name": "River", "role": "Explorers"}, {"id": "team-b", "name": "Meadow", "role": "Explorers"}], "players": [{"name": "Host", "team_id": "team-a"}], "game": null, "host_started_at": null, "team_start_offsets": {}, "team_finished": {}, "photos": []}, "136f317b-5d93-4b30-aa0a-7a8f501dde2f": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 45, "num_players": 2, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "P4XT35", "host_name": "Host", "status": "playing", "teams": [{"id": "team-a", "name": "River", "role": "Explorers"}, {"id": "team-b", "name": "Meadow", "role": "Explorers"}], "players": [{"name": "Host", "team_id": "team-a"}, {"name": "Hope", "team_id": "team-b"}], "game": {"game_id": "mock-ef48dd67", "game_type": "scavenger_hunt", "title": "Scavenger_Hunt in Downtown", "theme": "medium adventure", "setup": {"city": "Paris", "area": "Downtown", "meeting_point": "Main entrance of Downtown", "duration_minutes": 45, "num_players": 2}, "rules": ["Complete as many tasks as possible within 45 minutes", "Take photos or notes as proof of completion", "Stay within the designated area at all times", "No entering private buildings or restricted areas", "This game is suitable for all"], "tasks": [{"task_id": "t1", "title": "Task 1: Explore the main square", "description": "Find and document something interesting in the main square", "location_hint": "Navigate to the main square and look for distinctive features", "points": 15, "time_limit_minutes": 8, "proof_type": "photo", "hint": "Look for signs or landmarks in the main square", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t2", "title": "Task 2: Explore the city center", "description": "Find and document something interesting in the city center", "location_hint": "Navigate to the city center and look for distinctive features", "points": 20, "time_limit_minutes": 10, "proof_type": "observation", "hint": "Look for signs or landmarks in the city center", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t3", "title": "Task 3: Explore the park area", "description": "Find and document something interesting in the park area", "location_hint": "Navigate to the park area and look for distinctive features", "points": 25, "time_limit_minutes": 12, "proof_type": "text", "hint": "Look for signs or landmarks in the park area", "safety_note": "Stay on public paths and avoid restricted areas"}], "global_hints": ["Explore systematically from the meeting point outward", "Ask locals for directions if needed", "Time management is key - don't spend too long on any single task"], "score_rules": ["Each task completed: full points", "Early completion: +1 bonus point per minute under limit", "Hints used: -5 points per hint", "Late arrival at meeting point: -10 points per minute"], "tie_breaker": "Winner is the player with the most points when time expires. Ties broken by earliest completion time.", "safety": {"allowed_zone": "Downtown", "forbidden_behaviors": ["Entering buildings without permission", "Crossing busy streets recklessly", "Approaching strangers", "Leaving the designated area"], "adult_supervision": false, "stop_conditions": ["If a player feels unsafe, the game stops immediately", "If weather becomes severe, relocate to shelter", "If anyone is injured, call emergency services"]}, "story_seed": {"tone": "playful", "motifs": ["exploration", "discovery", "teamwork"], "recap_style": "episode_recap"}}, "host_started_at": "2026-06-12T17:29:30.570903+00:00", "team_start_offsets": {"team-a": 0, "team-b": 60}, "team_finished": {}, "photos": []}, "47bdfb37-1bb6-4346-8d9c-5c23d4c6f164": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 15, "num_players": 4, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "QN4J62", "host_name": "Host", "status": "lobby", "teams": [{"id": "team-a", "name": "River", "role": "Explorers"}, {"id": "team-b", "name": "Meadow", "role": "Explorers"}], "players": [{"name": "Host", "team_id": "team-b"}, {"name": "Priyasha", "team_id": "team-a"}], "game": {"game_id": "mock-47326f6b", "game_type": "scavenger_hunt", "title": "Scavenger_Hunt in Downtown", "theme": "medium adventure", "setup": {"city": "Paris", "area": "Downtown", "meeting_point": "Main entrance of Downtown", "duration_minutes": 15, "num_players": 4}, "rules": ["Complete as many tasks as possible within 15 minutes", "Take photos or notes as proof of completion", "Stay within the designated area at all times", "No entering private buildings or restricted areas", "This game is suitable for all"], "tasks": [{"task_id": "t1", "title": "Task 1: Explore the main square", "description": "Find and document something interesting in the main square", "location_hint": "Navigate to the main square and look for distinctive features", "points": 15, "time_limit_minutes": 8, "proof_type": "photo", "hint": "Look for signs or landmarks in the main square", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t2", "title": "Task 2: Explore the city center", "description": "Find and document something interesting in the city center", "location_hint": "Navigate to the city center and look for distinctive features", "points": 20, "time_limit_minutes": 10, "proof_type": "observation", "hint": "Look for signs or landmarks in the city center", "safety_note": "Stay on public paths and avoid restricted areas"}], "global_hints": ["Explore systematically from the meeting point outward", "Ask locals for directions if needed", "Time management is key - don't spend too long on any single task"], "score_rules": ["Each task completed: full points", "Early completion: +1 bonus point per minute under limit", "Hints used: -5 points per hint", "Late arrival at meeting point: -10 points per minute"], "tie_breaker": "Winner is the player with the most points when time expires. Ties broken by earliest completion time.", "safety": {"allowed_zone": "Downtown", "forbidden_behaviors": ["Entering buildings without permission", "Crossing busy streets recklessly", "Approaching strangers", "Leaving the designated area"], "adult_supervision": false, "stop_conditions": ["If a player feels unsafe, the game stops immediately", "If weather becomes severe, relocate to shelter", "If anyone is injured, call emergency services"]}, "story_seed": {"tone": "playful", "motifs": ["exploration", "discovery", "teamwork"], "recap_style": "episode_recap"}}, "host_started_at": null, "team_start_offsets": {}, "team_finished": {}, "photos": []}, "f02216a5-19f8-46cf-8d52-7dd74eeafb65": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 45, "num_players": 4, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "EHSFKC", "host_name": "Host", "status": "lobby", "teams": [{"id": "team-a", "name": "River", "role": "Explorers"}, {"id": "team-b", "name": "Meadow", "role": "Explorers"}], "players": [{"name": "Host", "team_id": "team-a"}], "game": {"game_id": "mock-d3ae7576", "game_type": "scavenger_hunt", "title": "Scavenger_Hunt in Downtown", "theme": "medium adventure", "setup": {"city": "Paris", "area": "Downtown", "meeting_point": "Main entrance of Downtown", "duration_minutes": 45, "num_players": 4}, "rules": ["Complete as many tasks as possible within 45 minutes", "Take photos or notes as proof of completion", "Stay within the designated area at all times", "No entering private buildings or restricted areas", "This game is suitable for all"], "tasks": [{"task_id": "t1", "title": "Task 1: Explore the main square", "description": "Find and document something interesting in the main square", "location_hint": "Navigate to the main square and look for distinctive features", "points": 15, "time_limit_minutes": 8, "proof_type": "photo", "hint": "Look for signs or landmarks in the main square", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t2", "title": "Task 2: Explore the city center", "description": "Find and document something interesting in the city center", "location_hint": "Navigate to the city center and look for distinctive features", "points": 20, "time_limit_minutes": 10, "proof_type": "observation", "hint": "Look for signs or landmarks in the city center", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t3", "title": "Task 3: Explore the park area", "description": "Find and document something interesting in the park area", "location_hint": "Navigate to the park area and look for distinctive features", "points": 25, "time_limit_minutes": 12, "proof_type": "text", "hint": "Look for signs or landmarks in the park area", "safety_note": "Stay on public paths and avoid restricted areas"}], "global_hints": ["Explore systematically from the meeting point outward", "Ask locals for directions if needed", "Time management is key - don't spend too long on any single task"], "score_rules": ["Each task completed: full points", "Early completion: +1 bonus point per minute under limit", "Hints used: -5 points per hint", "Late arrival at meeting point: -10 points per minute"], "tie_breaker": "Winner is the player with the most points when time expires. Ties broken by earliest completion time.", "safety": {"allowed_zone": "Downtown", "forbidden_behaviors": ["Entering buildings without permission", "Crossing busy streets recklessly", "Approaching strangers", "Leaving the designated area"], "adult_supervision": false, "stop_conditions": ["If a player feels unsafe, the game stops immediately", "If weather becomes severe, relocate to shelter", "If anyone is injured, call emergency services"]}, "story_seed": {"tone": "playful", "motifs": ["exploration", "discovery", "teamwork"], "recap_style": "episode_recap"}}, "host_started_at": null, "team_start_offsets": {}, "team_finished": {}, "photos": []}, "26e9880a-4d33-4e4a-a773-a00f097c9c83": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 45, "num_players": 4, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "5VDVSH", "host_name": "Host", "status": "finished", "teams": [{"id": "team-a", "name": "River", "role": "Explorers"}, {"id": "team-b", "name": "Meadow", "role": "Explorers"}], "players": [{"name": "Host", "team_id": "team-a"}], "game": {"game_id": "mock-9108f87e", "game_type": "scavenger_hunt", "title": "Scavenger_Hunt in Downtown", "theme": "medium adventure", "setup": {"city": "Paris", "area": "Downtown", "meeting_point": "Main entrance of Downtown", "duration_minutes": 45, "num_players": 4}, "rules": ["Complete as many tasks as possible within 45 minutes", "Take photos or notes as proof of completion", "Stay within the designated area at all times", "No entering private buildings or restricted areas", "This game is suitable for all"], "tasks": [{"task_id": "t1", "title": "Task 1: Explore the main square", "description": "Find and document something interesting in the main square", "location_hint": "Navigate to the main square and look for distinctive features", "points": 15, "time_limit_minutes": 8, "proof_type": "photo", "hint": "Look for signs or landmarks in the main square", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t2", "title": "Task 2: Explore the city center", "description": "Find and document something interesting in the city center", "location_hint": "Navigate to the city center and look for distinctive features", "points": 20, "time_limit_minutes": 10, "proof_type": "observation", "hint": "Look for signs or landmarks in the city center", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t3", "title": "Task 3: Explore the park area", "description": "Find and document something interesting in the park area", "location_hint": "Navigate to the park area and look for distinctive features", "points": 25, "time_limit_minutes": 12, "proof_type": "text", "hint": "Look for signs or landmarks in the park area", "safety_note": "Stay on public paths and avoid restricted areas"}], "global_hints": ["Explore systematically from the meeting point outward", "Ask locals for directions if needed", "Time management is key - don't spend too long on any single task"], "score_rules": ["Each task completed: full points", "Early completion: +1 bonus point per minute under limit", "Hints used: -5 points per hint", "Late arrival at meeting point: -10 points per minute"], "tie_breaker": "Winner is the player with the most points when time expires. Ties broken by earliest completion time.", "safety": {"allowed_zone": "Downtown", "forbidden_behaviors": ["Entering buildings without permission", "Crossing busy streets recklessly", "Approaching strangers", "Leaving the designated area"], "adult_supervision": false, "stop_conditions": ["If a player feels unsafe, the game stops immediately", "If weather becomes severe, relocate to shelter", "If anyone is injured, call emergency services"]}, "story_seed": {"tone": "playful", "motifs": ["exploration", "discovery", "teamwork"], "recap_style": "episode_recap"}}, "host_started_at": "2026-06-12T17:44:34.248892+00:00", "team_start_offsets": {"team-a": 0, "team-b": 60}, "team_finished": {"team-a": "2026-06-12T17:44:40.426298+00:00"}, "photos": []}, "70959adc-6172-41e6-ae4f-ef8f90772dba": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 45, "num_players": 4, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "QVTJKG", "host_name": "Host", "status": "lobby", "teams": [{"id": "team-a", "name": "River", "role": "Explorers"}, {"id": "team-b", "name": "Meadow", "role": "Explorers"}], "players": [{"name": "Host", "team_id": "team-a"}], "game": null, "host_started_at": null, "team_start_offsets": {}, "team_finished": {}, "photos": []}}}
|
|
|
|
| 1 |
+
{"codes": {"75ZKFE": "9fcb0953-4e36-4485-9bbe-fad577de31fa", "JWR5RV": "6b1af473-b00b-44ae-bffc-7b8e93616767", "NKPZKT": "32e1bbe3-50a1-4e43-a7c2-8ecf3f781550", "NXWHQK": "4b03fbfc-4326-4325-8975-e4216c44e03e", "VMJVMF": "2cfd0fef-a118-4044-a9bd-2583e60b56e1", "EHPYXY": "720ab67a-9428-4c7b-a01e-de3d393d6a96", "Y3ZTX5": "15c4e4e1-c8e9-4f40-be4e-9606abd41f9d", "GY4QMQ": "b56f7a32-961f-4001-be35-503866b95227", "HZWQB4": "a549cbe3-e796-4ca5-9f00-78ea47eb9704", "FHGKNU": "e1e90fde-7eb5-4a56-a2ee-edd451b3c099", "P4XT35": "136f317b-5d93-4b30-aa0a-7a8f501dde2f", "QN4J62": "47bdfb37-1bb6-4346-8d9c-5c23d4c6f164", "EHSFKC": "f02216a5-19f8-46cf-8d52-7dd74eeafb65", "5VDVSH": "26e9880a-4d33-4e4a-a773-a00f097c9c83", "QVTJKG": "70959adc-6172-41e6-ae4f-ef8f90772dba", "NCVFAZ": "8e04b90f-baa6-45a6-9a8b-21d91a4b4d8a", "9F2X98": "bc218c4b-3b0d-4f33-b91a-8b10500ea29e", "AFV67H": "29725220-ef25-499f-9ef3-47f4afacbff4", "WQ799U": "9c9f53d7-5b26-4d11-be5a-eb6b657b63c2", "CUJCK3": "c4f53a5f-6e23-4030-a2e7-a04a47fe14f5", "8MRZWG": "03491a8c-e9ad-47fe-810e-10acbf649270", "FAUV65": "1959d776-cd89-4aa9-82b1-4922f4d5e37f"}, "sessions": {"9fcb0953-4e36-4485-9bbe-fad577de31fa": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Le Marais", "location_type": "mixed", "duration_minutes": 60, "num_players": 2, "difficulty": "easy", "age_group": "adults", "energy_level": "low", "photo_enabled": true}, "room_code": null, "host_name": null, "status": null, "teams": ["team-a", "team-b"], "players": [{"name": "Player 1", "team_id": "team-a"}, {"name": "play 2", "team_id": "team-b"}, {"name": "hola", "team_id": "team-b"}], "game": {"game_id": "mock-8506e14a", "title": "Scavenger_Hunt in Le Marais", "theme": "easy adventure", "setup": {"city": "Paris", "area": "Le Marais", "meeting_point": "Main entrance of Le Marais", "duration_minutes": 60, "num_players": 2}, "rules": ["Complete as many tasks as possible within 60 minutes", "Take photos or notes as proof of completion", "Stay within the designated area at all times", "No entering private buildings or restricted areas", "This game is suitable for adults"], "tasks": [{"task_id": "t1", "title": "Task 1: Explore the main square", "description": "Find and document something interesting in the main square", "location_hint": "Navigate to the main square and look for distinctive features", "points": 15, "time_limit_minutes": 8, "proof_type": "photo", "hint": "Look for signs or landmarks in the main square", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t2", "title": "Task 2: Explore the city center", "description": "Find and document something interesting in the city center", "location_hint": "Navigate to the city center and look for distinctive features", "points": 20, "time_limit_minutes": 10, "proof_type": "observation", "hint": "Look for signs or landmarks in the city center", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t3", "title": "Task 3: Explore the park area", "description": "Find and document something interesting in the park area", "location_hint": "Navigate to the park area and look for distinctive features", "points": 25, "time_limit_minutes": 12, "proof_type": "text", "hint": "Look for signs or landmarks in the park area", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t4", "title": "Task 4: Explore the landmark district", "description": "Find and document something interesting in the landmark district", "location_hint": "Navigate to the landmark district and look for distinctive features", "points": 30, "time_limit_minutes": 14, "proof_type": "photo", "hint": "Look for signs or landmarks in the landmark district", "safety_note": "Stay on public paths and avoid restricted areas"}], "global_hints": ["Explore systematically from the meeting point outward", "Ask locals for directions if needed", "Time management is key - don't spend too long on any single task"], "score_rules": ["Each task completed: full points", "Early completion: +1 bonus point per minute under limit", "Hints used: -5 points per hint", "Late arrival at meeting point: -10 points per minute"], "tie_breaker": "Winner is the player with the most points when time expires. Ties broken by earliest completion time.", "safety": {"allowed_zone": "Le Marais", "forbidden_behaviors": ["Entering buildings without permission", "Crossing busy streets recklessly", "Approaching strangers", "Leaving the designated area"], "adult_supervision": false, "stop_conditions": ["If a player feels unsafe, the game stops immediately", "If weather becomes severe, relocate to shelter", "If anyone is injured, call emergency services"]}, "story_seed": {"tone": "playful", "motifs": ["exploration", "discovery", "teamwork"], "recap_style": "episode_recap"}}, "host_started_at": null, "team_start_offsets": null, "team_finished": null, "photos": [{"photo_id": "photo-71c44ee8", "photo_name": "", "caption": "", "task_id": "t1"}]}, "6b1af473-b00b-44ae-bffc-7b8e93616767": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Le Marais", "location_type": "mixed", "duration_minutes": 60, "num_players": 2, "difficulty": "easy", "age_group": "adults", "energy_level": "low", "photo_enabled": true}, "room_code": null, "host_name": null, "status": null, "teams": ["team-a", "team-b"], "players": [{"name": "Player 1", "team_id": "team-a"}], "game": {"game_id": "mock-6d6ab9cf", "title": "Scavenger_Hunt in Le Marais", "theme": "easy adventure", "setup": {"city": "Paris", "area": "Le Marais", "meeting_point": "Main entrance of Le Marais", "duration_minutes": 60, "num_players": 2}, "rules": ["Complete as many tasks as possible within 60 minutes", "Take photos or notes as proof of completion", "Stay within the designated area at all times", "No entering private buildings or restricted areas", "This game is suitable for adults"], "tasks": [{"task_id": "t1", "title": "Task 1: Explore the main square", "description": "Find and document something interesting in the main square", "location_hint": "Navigate to the main square and look for distinctive features", "points": 15, "time_limit_minutes": 8, "proof_type": "photo", "hint": "Look for signs or landmarks in the main square", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t2", "title": "Task 2: Explore the city center", "description": "Find and document something interesting in the city center", "location_hint": "Navigate to the city center and look for distinctive features", "points": 20, "time_limit_minutes": 10, "proof_type": "observation", "hint": "Look for signs or landmarks in the city center", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t3", "title": "Task 3: Explore the park area", "description": "Find and document something interesting in the park area", "location_hint": "Navigate to the park area and look for distinctive features", "points": 25, "time_limit_minutes": 12, "proof_type": "text", "hint": "Look for signs or landmarks in the park area", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t4", "title": "Task 4: Explore the landmark district", "description": "Find and document something interesting in the landmark district", "location_hint": "Navigate to the landmark district and look for distinctive features", "points": 30, "time_limit_minutes": 14, "proof_type": "photo", "hint": "Look for signs or landmarks in the landmark district", "safety_note": "Stay on public paths and avoid restricted areas"}], "global_hints": ["Explore systematically from the meeting point outward", "Ask locals for directions if needed", "Time management is key - don't spend too long on any single task"], "score_rules": ["Each task completed: full points", "Early completion: +1 bonus point per minute under limit", "Hints used: -5 points per hint", "Late arrival at meeting point: -10 points per minute"], "tie_breaker": "Winner is the player with the most points when time expires. Ties broken by earliest completion time.", "safety": {"allowed_zone": "Le Marais", "forbidden_behaviors": ["Entering buildings without permission", "Crossing busy streets recklessly", "Approaching strangers", "Leaving the designated area"], "adult_supervision": false, "stop_conditions": ["If a player feels unsafe, the game stops immediately", "If weather becomes severe, relocate to shelter", "If anyone is injured, call emergency services"]}, "story_seed": {"tone": "playful", "motifs": ["exploration", "discovery", "teamwork"], "recap_style": "episode_recap"}}, "host_started_at": null, "team_start_offsets": null, "team_finished": null, "photos": []}, "32e1bbe3-50a1-4e43-a7c2-8ecf3f781550": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Le Marais", "location_type": "mixed", "duration_minutes": 60, "num_players": 4, "difficulty": "medium", "age_group": "adults", "energy_level": "medium", "photo_enabled": true}, "room_code": null, "host_name": null, "status": null, "teams": ["team-a", "team-b"], "players": [{"name": "Nithin", "team_id": "team-a"}], "game": {"game_id": "game_042", "title": "Le Marais Mystery Hunt", "theme": "Scavenger Hunt", "setup": {"city": "Paris", "area": "Le Marais", "meeting_point": "Place des Vosges", "duration_minutes": 60, "num_players": 4}, "rules": ["Stay within Le Marais boundaries", "No entering buildings or private property", "No proximity to water, traffic, or rail lines", "No interacting with strangers", "All tasks must be observed, no purchases"], "tasks": [{"task_id": "t1", "title": "Historic Fountain", "description": "Observe the historic fountain at Place des Vosges.", "location_hint": "Place des Vosges", "points": 20, "time_limit_minutes": null, "proof_type": "observation", "hint": "Look for the historic fountain", "safety_note": "Only observe, no touching or entering"}, {"task_id": "t2", "title": "Colorful Door", "description": "Observe the colorful door on Rue des Rosiers.", "location_hint": "Rue des Rosiers", "points": 15, "time_limit_minutes": null, "proof_type": "observation", "hint": "Look for the colorful door", "safety_note": "Only observe, no touching or entering"}, {"task_id": "t3", "title": "Task 3", "description": "Explore and discover something interesting in the area", "location_hint": "Look around the central area", "points": 25, "time_limit_minutes": null, "proof_type": "text", "hint": "Check visible landmarks and signs for clues", "safety_note": "Stay on public paths and respect local rules"}], "global_hints": ["Le Marais is a historic district", "All tasks are observation-based"], "score_rules": ["Higher points win", "Tie broken by total points"], "tie_breaker": "Highest total points wins", "safety": {"allowed_zone": "Le Marais public streets and parks", "forbidden_behaviors": ["Entering buildings or private property", "Proximity to water, traffic, or rail lines", "Interacting with strangers", "Purchasing items"], "adult_supervision": false, "stop_conditions": ["All tasks completed", "Time limit 60 minutes reached", "Any rule violation"]}, "story_seed": {"tone": "playful", "motifs": ["historic architecture", "urban exploration"], "recap_style": "Summarize each player's observations and points"}}, "host_started_at": null, "team_start_offsets": null, "team_finished": null, "photos": []}, "4b03fbfc-4326-4325-8975-e4216c44e03e": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Le Marais", "location_type": "mixed", "duration_minutes": 60, "num_players": 4, "difficulty": "medium", "age_group": "adults", "energy_level": "medium", "photo_enabled": true}, "room_code": null, "host_name": null, "status": null, "teams": ["team-a", "team-b"], "players": [{"name": "Nithin", "team_id": "team-a"}], "game": {"game_id": "game_042", "title": "Le Marais Mystery Hunt", "theme": "Observational scavenger hunt", "setup": {"city": "Paris", "area": "Le Marais", "meeting_point": "Place des Vosges", "duration_minutes": 60, "num_players": 4}, "rules": ["Stay within Le Marais boundaries", "No entering buildings or private property", "No crossing traffic or water", "No interacting with strangers", "No purchases", "All tasks are observation only"], "tasks": [{"task_id": "t1", "title": "Vosges View", "description": "Find the historic square Place des Vosges and note its symmetrical layout.", "location_hint": "Place des Vosges", "points": 20, "time_limit_minutes": null, "proof_type": "observation", "hint": "Look for the central fountain", "safety_note": "Stay on pavement, no building entry"}, {"task_id": "t2", "title": "Rue des Rosiers", "description": "Observe the vibrant street market stalls and colorful awnings.", "location_hint": "Rue des Rosiers", "points": 15, "time_limit_minutes": null, "proof_type": "observation", "hint": "Notice the flower displays", "safety_note": "No entering stalls"}, {"task_id": "t3", "title": "H\u00f4tel de Ville View", "description": "Observe the fa\u00e7ade of the H\u00f4tel de Ville from the street.", "location_hint": "Place des Vosges near H\u00f4tel de Ville", "points": 20, "time_limit_minutes": null, "proof_type": "observation", "hint": "Look for the clock tower", "safety_note": "No entering building"}], "global_hints": ["Stay within Le Marais", "Use observation only", "No purchases"], "score_rules": ["Highest points wins", "All tasks completed for bonus"], "tie_breaker": "First player to reach 50 points wins", "safety": {"allowed_zone": "Le Marais streets and public squares", "forbidden_behaviors": ["Entering buildings", "Crossing traffic", "Approaching water", "Interacting with strangers", "Purchasing items"], "adult_supervision": true, "stop_conditions": ["Time limit 60 minutes", "Safety breach", "All tasks completed"]}, "story_seed": {"tone": "playful", "motifs": ["hidden clues", "Parisian charm", "observation"], "recap_style": "Gather at the meeting point for a recap of findings."}}, "host_started_at": null, "team_start_offsets": null, "team_finished": null, "photos": []}, "2cfd0fef-a118-4044-a9bd-2583e60b56e1": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 45, "num_players": 4, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "VMJVMF", "host_name": "Host", "status": "lobby", "teams": [{"id": "team-a", "name": "River", "role": "Explorers"}, {"id": "team-b", "name": "Meadow", "role": "Explorers"}], "players": [{"name": "Host", "team_id": "team-a"}], "game": {"game_id": "mock-50dd0c65", "game_type": "scavenger_hunt", "title": "Scavenger_Hunt in Downtown", "theme": "medium adventure", "setup": {"city": "Paris", "area": "Downtown", "meeting_point": "Main entrance of Downtown", "duration_minutes": 45, "num_players": 4}, "rules": ["Complete as many tasks as possible within 45 minutes", "Take photos or notes as proof of completion", "Stay within the designated area at all times", "No entering private buildings or restricted areas", "This game is suitable for all"], "tasks": [{"task_id": "t1", "title": "Task 1: Explore the main square", "description": "Find and document something interesting in the main square", "location_hint": "Navigate to the main square and look for distinctive features", "points": 15, "time_limit_minutes": 8, "proof_type": "photo", "hint": "Look for signs or landmarks in the main square", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t2", "title": "Task 2: Explore the city center", "description": "Find and document something interesting in the city center", "location_hint": "Navigate to the city center and look for distinctive features", "points": 20, "time_limit_minutes": 10, "proof_type": "observation", "hint": "Look for signs or landmarks in the city center", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t3", "title": "Task 3: Explore the park area", "description": "Find and document something interesting in the park area", "location_hint": "Navigate to the park area and look for distinctive features", "points": 25, "time_limit_minutes": 12, "proof_type": "text", "hint": "Look for signs or landmarks in the park area", "safety_note": "Stay on public paths and avoid restricted areas"}], "global_hints": ["Explore systematically from the meeting point outward", "Ask locals for directions if needed", "Time management is key - don't spend too long on any single task"], "score_rules": ["Each task completed: full points", "Early completion: +1 bonus point per minute under limit", "Hints used: -5 points per hint", "Late arrival at meeting point: -10 points per minute"], "tie_breaker": "Winner is the player with the most points when time expires. Ties broken by earliest completion time.", "safety": {"allowed_zone": "Downtown", "forbidden_behaviors": ["Entering buildings without permission", "Crossing busy streets recklessly", "Approaching strangers", "Leaving the designated area"], "adult_supervision": false, "stop_conditions": ["If a player feels unsafe, the game stops immediately", "If weather becomes severe, relocate to shelter", "If anyone is injured, call emergency services"]}, "story_seed": {"tone": "playful", "motifs": ["exploration", "discovery", "teamwork"], "recap_style": "episode_recap"}}, "host_started_at": null, "team_start_offsets": {}, "team_finished": {}, "photos": []}, "720ab67a-9428-4c7b-a01e-de3d393d6a96": {"config": {"game_type": "hide_and_seek", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 45, "num_players": 4, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "EHPYXY", "host_name": "Host", "status": "lobby", "teams": [{"id": "team-a", "name": "River", "role": "Hiders"}, {"id": "team-b", "name": "Meadow", "role": "Seekers"}], "players": [{"name": "Host", "team_id": "team-a"}], "game": {"game_id": "mock-15f50146", "game_type": "hide_and_seek", "title": "Hide_And_Seek in Downtown", "theme": "medium adventure", "setup": {"city": "Paris", "area": "Downtown", "meeting_point": "Main entrance of Downtown", "duration_minutes": 45, "num_players": 4}, "rules": ["Complete as many tasks as possible within 45 minutes", "Take photos or notes as proof of completion", "Stay within the designated area at all times", "No entering private buildings or restricted areas", "This game is suitable for all"], "tasks": [{"task_id": "t1", "title": "Task 1: Explore the main square", "description": "Find and document something interesting in the main square", "location_hint": "Navigate to the main square and look for distinctive features", "points": 15, "time_limit_minutes": 8, "proof_type": "photo", "hint": "Look for signs or landmarks in the main square", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t2", "title": "Task 2: Explore the city center", "description": "Find and document something interesting in the city center", "location_hint": "Navigate to the city center and look for distinctive features", "points": 20, "time_limit_minutes": 10, "proof_type": "observation", "hint": "Look for signs or landmarks in the city center", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t3", "title": "Task 3: Explore the park area", "description": "Find and document something interesting in the park area", "location_hint": "Navigate to the park area and look for distinctive features", "points": 25, "time_limit_minutes": 12, "proof_type": "text", "hint": "Look for signs or landmarks in the park area", "safety_note": "Stay on public paths and avoid restricted areas"}], "global_hints": ["Explore systematically from the meeting point outward", "Ask locals for directions if needed", "Time management is key - don't spend too long on any single task"], "score_rules": ["Each task completed: full points", "Early completion: +1 bonus point per minute under limit", "Hints used: -5 points per hint", "Late arrival at meeting point: -10 points per minute"], "tie_breaker": "Winner is the player with the most points when time expires. Ties broken by earliest completion time.", "safety": {"allowed_zone": "Downtown", "forbidden_behaviors": ["Entering buildings without permission", "Crossing busy streets recklessly", "Approaching strangers", "Leaving the designated area"], "adult_supervision": false, "stop_conditions": ["If a player feels unsafe, the game stops immediately", "If weather becomes severe, relocate to shelter", "If anyone is injured, call emergency services"]}, "story_seed": {"tone": "playful", "motifs": ["exploration", "discovery", "teamwork"], "recap_style": "episode_recap"}}, "host_started_at": null, "team_start_offsets": {}, "team_finished": {}, "photos": []}, "15c4e4e1-c8e9-4f40-be4e-9606abd41f9d": {"config": {"game_type": "tag", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 45, "num_players": 4, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "Y3ZTX5", "host_name": "Host", "status": "finished", "teams": [{"id": "team-a", "name": "River", "role": "Runners"}, {"id": "team-b", "name": "Meadow", "role": "Chasers"}], "players": [{"name": "Host", "team_id": "team-a"}, {"name": "jkjlkj", "team_id": "team-b"}], "game": {"game_id": "mock-f949048c", "game_type": "tag", "title": "Tag in Downtown", "theme": "medium adventure", "setup": {"city": "Paris", "area": "Downtown", "meeting_point": "Main entrance of Downtown", "duration_minutes": 45, "num_players": 4}, "rules": ["Complete as many tasks as possible within 45 minutes", "Take photos or notes as proof of completion", "Stay within the designated area at all times", "No entering private buildings or restricted areas", "This game is suitable for all"], "tasks": [{"task_id": "t1", "title": "Task 1: Explore the main square", "description": "Find and document something interesting in the main square", "location_hint": "Navigate to the main square and look for distinctive features", "points": 15, "time_limit_minutes": 8, "proof_type": "photo", "hint": "Look for signs or landmarks in the main square", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t2", "title": "Task 2: Explore the city center", "description": "Find and document something interesting in the city center", "location_hint": "Navigate to the city center and look for distinctive features", "points": 20, "time_limit_minutes": 10, "proof_type": "observation", "hint": "Look for signs or landmarks in the city center", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t3", "title": "Task 3: Explore the park area", "description": "Find and document something interesting in the park area", "location_hint": "Navigate to the park area and look for distinctive features", "points": 25, "time_limit_minutes": 12, "proof_type": "text", "hint": "Look for signs or landmarks in the park area", "safety_note": "Stay on public paths and avoid restricted areas"}], "global_hints": ["Explore systematically from the meeting point outward", "Ask locals for directions if needed", "Time management is key - don't spend too long on any single task"], "score_rules": ["Each task completed: full points", "Early completion: +1 bonus point per minute under limit", "Hints used: -5 points per hint", "Late arrival at meeting point: -10 points per minute"], "tie_breaker": "Winner is the player with the most points when time expires. Ties broken by earliest completion time.", "safety": {"allowed_zone": "Downtown", "forbidden_behaviors": ["Entering buildings without permission", "Crossing busy streets recklessly", "Approaching strangers", "Leaving the designated area"], "adult_supervision": false, "stop_conditions": ["If a player feels unsafe, the game stops immediately", "If weather becomes severe, relocate to shelter", "If anyone is injured, call emergency services"]}, "story_seed": {"tone": "playful", "motifs": ["exploration", "discovery", "teamwork"], "recap_style": "episode_recap"}}, "host_started_at": "2026-06-12T16:03:57.108418+00:00", "team_start_offsets": {"team-a": 0, "team-b": 60}, "team_finished": {"team-b": "2026-06-12T16:05:24.467878+00:00", "team-a": "2026-06-12T16:05:31.049593+00:00"}, "photos": []}, "b56f7a32-961f-4001-be35-503866b95227": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 45, "num_players": 4, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "GY4QMQ", "host_name": "Host", "status": "lobby", "teams": [{"id": "team-a", "name": "River", "role": "Explorers"}, {"id": "team-b", "name": "Meadow", "role": "Explorers"}], "players": [{"name": "Host", "team_id": "team-a"}], "game": null, "host_started_at": null, "team_start_offsets": {}, "team_finished": {}, "photos": []}, "a549cbe3-e796-4ca5-9f00-78ea47eb9704": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 45, "num_players": 4, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "HZWQB4", "host_name": "Host", "status": "playing", "teams": [{"id": "team-a", "name": "River", "role": "Explorers"}, {"id": "team-b", "name": "Meadow", "role": "Explorers"}], "players": [{"name": "Host", "team_id": "team-a"}], "game": {"game_id": "mock-eb9ec682", "game_type": "scavenger_hunt", "title": "Scavenger_Hunt in Downtown", "theme": "medium adventure", "setup": {"city": "Paris", "area": "Downtown", "meeting_point": "Main entrance of Downtown", "duration_minutes": 45, "num_players": 4}, "rules": ["Complete as many tasks as possible within 45 minutes", "Take photos or notes as proof of completion", "Stay within the designated area at all times", "No entering private buildings or restricted areas", "This game is suitable for all"], "tasks": [{"task_id": "t1", "title": "Task 1: Explore the main square", "description": "Find and document something interesting in the main square", "location_hint": "Navigate to the main square and look for distinctive features", "points": 15, "time_limit_minutes": 8, "proof_type": "photo", "hint": "Look for signs or landmarks in the main square", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t2", "title": "Task 2: Explore the city center", "description": "Find and document something interesting in the city center", "location_hint": "Navigate to the city center and look for distinctive features", "points": 20, "time_limit_minutes": 10, "proof_type": "observation", "hint": "Look for signs or landmarks in the city center", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t3", "title": "Task 3: Explore the park area", "description": "Find and document something interesting in the park area", "location_hint": "Navigate to the park area and look for distinctive features", "points": 25, "time_limit_minutes": 12, "proof_type": "text", "hint": "Look for signs or landmarks in the park area", "safety_note": "Stay on public paths and avoid restricted areas"}], "global_hints": ["Explore systematically from the meeting point outward", "Ask locals for directions if needed", "Time management is key - don't spend too long on any single task"], "score_rules": ["Each task completed: full points", "Early completion: +1 bonus point per minute under limit", "Hints used: -5 points per hint", "Late arrival at meeting point: -10 points per minute"], "tie_breaker": "Winner is the player with the most points when time expires. Ties broken by earliest completion time.", "safety": {"allowed_zone": "Downtown", "forbidden_behaviors": ["Entering buildings without permission", "Crossing busy streets recklessly", "Approaching strangers", "Leaving the designated area"], "adult_supervision": false, "stop_conditions": ["If a player feels unsafe, the game stops immediately", "If weather becomes severe, relocate to shelter", "If anyone is injured, call emergency services"]}, "story_seed": {"tone": "playful", "motifs": ["exploration", "discovery", "teamwork"], "recap_style": "episode_recap"}}, "host_started_at": "2026-06-12T16:59:08.914806+00:00", "team_start_offsets": {"team-a": 0, "team-b": 60}, "team_finished": {}, "photos": []}, "e1e90fde-7eb5-4a56-a2ee-edd451b3c099": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 45, "num_players": 4, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "FHGKNU", "host_name": "Host", "status": "lobby", "teams": [{"id": "team-a", "name": "River", "role": "Explorers"}, {"id": "team-b", "name": "Meadow", "role": "Explorers"}], "players": [{"name": "Host", "team_id": "team-a"}], "game": null, "host_started_at": null, "team_start_offsets": {}, "team_finished": {}, "photos": []}, "136f317b-5d93-4b30-aa0a-7a8f501dde2f": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 45, "num_players": 2, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "P4XT35", "host_name": "Host", "status": "playing", "teams": [{"id": "team-a", "name": "River", "role": "Explorers"}, {"id": "team-b", "name": "Meadow", "role": "Explorers"}], "players": [{"name": "Host", "team_id": "team-a"}, {"name": "Hope", "team_id": "team-b"}], "game": {"game_id": "mock-ef48dd67", "game_type": "scavenger_hunt", "title": "Scavenger_Hunt in Downtown", "theme": "medium adventure", "setup": {"city": "Paris", "area": "Downtown", "meeting_point": "Main entrance of Downtown", "duration_minutes": 45, "num_players": 2}, "rules": ["Complete as many tasks as possible within 45 minutes", "Take photos or notes as proof of completion", "Stay within the designated area at all times", "No entering private buildings or restricted areas", "This game is suitable for all"], "tasks": [{"task_id": "t1", "title": "Task 1: Explore the main square", "description": "Find and document something interesting in the main square", "location_hint": "Navigate to the main square and look for distinctive features", "points": 15, "time_limit_minutes": 8, "proof_type": "photo", "hint": "Look for signs or landmarks in the main square", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t2", "title": "Task 2: Explore the city center", "description": "Find and document something interesting in the city center", "location_hint": "Navigate to the city center and look for distinctive features", "points": 20, "time_limit_minutes": 10, "proof_type": "observation", "hint": "Look for signs or landmarks in the city center", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t3", "title": "Task 3: Explore the park area", "description": "Find and document something interesting in the park area", "location_hint": "Navigate to the park area and look for distinctive features", "points": 25, "time_limit_minutes": 12, "proof_type": "text", "hint": "Look for signs or landmarks in the park area", "safety_note": "Stay on public paths and avoid restricted areas"}], "global_hints": ["Explore systematically from the meeting point outward", "Ask locals for directions if needed", "Time management is key - don't spend too long on any single task"], "score_rules": ["Each task completed: full points", "Early completion: +1 bonus point per minute under limit", "Hints used: -5 points per hint", "Late arrival at meeting point: -10 points per minute"], "tie_breaker": "Winner is the player with the most points when time expires. Ties broken by earliest completion time.", "safety": {"allowed_zone": "Downtown", "forbidden_behaviors": ["Entering buildings without permission", "Crossing busy streets recklessly", "Approaching strangers", "Leaving the designated area"], "adult_supervision": false, "stop_conditions": ["If a player feels unsafe, the game stops immediately", "If weather becomes severe, relocate to shelter", "If anyone is injured, call emergency services"]}, "story_seed": {"tone": "playful", "motifs": ["exploration", "discovery", "teamwork"], "recap_style": "episode_recap"}}, "host_started_at": "2026-06-12T17:29:30.570903+00:00", "team_start_offsets": {"team-a": 0, "team-b": 60}, "team_finished": {}, "photos": []}, "47bdfb37-1bb6-4346-8d9c-5c23d4c6f164": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 15, "num_players": 4, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "QN4J62", "host_name": "Host", "status": "lobby", "teams": [{"id": "team-a", "name": "River", "role": "Explorers"}, {"id": "team-b", "name": "Meadow", "role": "Explorers"}], "players": [{"name": "Host", "team_id": "team-b"}, {"name": "Priyasha", "team_id": "team-a"}], "game": {"game_id": "mock-47326f6b", "game_type": "scavenger_hunt", "title": "Scavenger_Hunt in Downtown", "theme": "medium adventure", "setup": {"city": "Paris", "area": "Downtown", "meeting_point": "Main entrance of Downtown", "duration_minutes": 15, "num_players": 4}, "rules": ["Complete as many tasks as possible within 15 minutes", "Take photos or notes as proof of completion", "Stay within the designated area at all times", "No entering private buildings or restricted areas", "This game is suitable for all"], "tasks": [{"task_id": "t1", "title": "Task 1: Explore the main square", "description": "Find and document something interesting in the main square", "location_hint": "Navigate to the main square and look for distinctive features", "points": 15, "time_limit_minutes": 8, "proof_type": "photo", "hint": "Look for signs or landmarks in the main square", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t2", "title": "Task 2: Explore the city center", "description": "Find and document something interesting in the city center", "location_hint": "Navigate to the city center and look for distinctive features", "points": 20, "time_limit_minutes": 10, "proof_type": "observation", "hint": "Look for signs or landmarks in the city center", "safety_note": "Stay on public paths and avoid restricted areas"}], "global_hints": ["Explore systematically from the meeting point outward", "Ask locals for directions if needed", "Time management is key - don't spend too long on any single task"], "score_rules": ["Each task completed: full points", "Early completion: +1 bonus point per minute under limit", "Hints used: -5 points per hint", "Late arrival at meeting point: -10 points per minute"], "tie_breaker": "Winner is the player with the most points when time expires. Ties broken by earliest completion time.", "safety": {"allowed_zone": "Downtown", "forbidden_behaviors": ["Entering buildings without permission", "Crossing busy streets recklessly", "Approaching strangers", "Leaving the designated area"], "adult_supervision": false, "stop_conditions": ["If a player feels unsafe, the game stops immediately", "If weather becomes severe, relocate to shelter", "If anyone is injured, call emergency services"]}, "story_seed": {"tone": "playful", "motifs": ["exploration", "discovery", "teamwork"], "recap_style": "episode_recap"}}, "host_started_at": null, "team_start_offsets": {}, "team_finished": {}, "photos": []}, "f02216a5-19f8-46cf-8d52-7dd74eeafb65": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 45, "num_players": 4, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "EHSFKC", "host_name": "Host", "status": "lobby", "teams": [{"id": "team-a", "name": "River", "role": "Explorers"}, {"id": "team-b", "name": "Meadow", "role": "Explorers"}], "players": [{"name": "Host", "team_id": "team-a"}], "game": {"game_id": "mock-d3ae7576", "game_type": "scavenger_hunt", "title": "Scavenger_Hunt in Downtown", "theme": "medium adventure", "setup": {"city": "Paris", "area": "Downtown", "meeting_point": "Main entrance of Downtown", "duration_minutes": 45, "num_players": 4}, "rules": ["Complete as many tasks as possible within 45 minutes", "Take photos or notes as proof of completion", "Stay within the designated area at all times", "No entering private buildings or restricted areas", "This game is suitable for all"], "tasks": [{"task_id": "t1", "title": "Task 1: Explore the main square", "description": "Find and document something interesting in the main square", "location_hint": "Navigate to the main square and look for distinctive features", "points": 15, "time_limit_minutes": 8, "proof_type": "photo", "hint": "Look for signs or landmarks in the main square", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t2", "title": "Task 2: Explore the city center", "description": "Find and document something interesting in the city center", "location_hint": "Navigate to the city center and look for distinctive features", "points": 20, "time_limit_minutes": 10, "proof_type": "observation", "hint": "Look for signs or landmarks in the city center", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t3", "title": "Task 3: Explore the park area", "description": "Find and document something interesting in the park area", "location_hint": "Navigate to the park area and look for distinctive features", "points": 25, "time_limit_minutes": 12, "proof_type": "text", "hint": "Look for signs or landmarks in the park area", "safety_note": "Stay on public paths and avoid restricted areas"}], "global_hints": ["Explore systematically from the meeting point outward", "Ask locals for directions if needed", "Time management is key - don't spend too long on any single task"], "score_rules": ["Each task completed: full points", "Early completion: +1 bonus point per minute under limit", "Hints used: -5 points per hint", "Late arrival at meeting point: -10 points per minute"], "tie_breaker": "Winner is the player with the most points when time expires. Ties broken by earliest completion time.", "safety": {"allowed_zone": "Downtown", "forbidden_behaviors": ["Entering buildings without permission", "Crossing busy streets recklessly", "Approaching strangers", "Leaving the designated area"], "adult_supervision": false, "stop_conditions": ["If a player feels unsafe, the game stops immediately", "If weather becomes severe, relocate to shelter", "If anyone is injured, call emergency services"]}, "story_seed": {"tone": "playful", "motifs": ["exploration", "discovery", "teamwork"], "recap_style": "episode_recap"}}, "host_started_at": null, "team_start_offsets": {}, "team_finished": {}, "photos": []}, "26e9880a-4d33-4e4a-a773-a00f097c9c83": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 45, "num_players": 4, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "5VDVSH", "host_name": "Host", "status": "finished", "teams": [{"id": "team-a", "name": "River", "role": "Explorers"}, {"id": "team-b", "name": "Meadow", "role": "Explorers"}], "players": [{"name": "Host", "team_id": "team-a"}], "game": {"game_id": "mock-9108f87e", "game_type": "scavenger_hunt", "title": "Scavenger_Hunt in Downtown", "theme": "medium adventure", "setup": {"city": "Paris", "area": "Downtown", "meeting_point": "Main entrance of Downtown", "duration_minutes": 45, "num_players": 4}, "rules": ["Complete as many tasks as possible within 45 minutes", "Take photos or notes as proof of completion", "Stay within the designated area at all times", "No entering private buildings or restricted areas", "This game is suitable for all"], "tasks": [{"task_id": "t1", "title": "Task 1: Explore the main square", "description": "Find and document something interesting in the main square", "location_hint": "Navigate to the main square and look for distinctive features", "points": 15, "time_limit_minutes": 8, "proof_type": "photo", "hint": "Look for signs or landmarks in the main square", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t2", "title": "Task 2: Explore the city center", "description": "Find and document something interesting in the city center", "location_hint": "Navigate to the city center and look for distinctive features", "points": 20, "time_limit_minutes": 10, "proof_type": "observation", "hint": "Look for signs or landmarks in the city center", "safety_note": "Stay on public paths and avoid restricted areas"}, {"task_id": "t3", "title": "Task 3: Explore the park area", "description": "Find and document something interesting in the park area", "location_hint": "Navigate to the park area and look for distinctive features", "points": 25, "time_limit_minutes": 12, "proof_type": "text", "hint": "Look for signs or landmarks in the park area", "safety_note": "Stay on public paths and avoid restricted areas"}], "global_hints": ["Explore systematically from the meeting point outward", "Ask locals for directions if needed", "Time management is key - don't spend too long on any single task"], "score_rules": ["Each task completed: full points", "Early completion: +1 bonus point per minute under limit", "Hints used: -5 points per hint", "Late arrival at meeting point: -10 points per minute"], "tie_breaker": "Winner is the player with the most points when time expires. Ties broken by earliest completion time.", "safety": {"allowed_zone": "Downtown", "forbidden_behaviors": ["Entering buildings without permission", "Crossing busy streets recklessly", "Approaching strangers", "Leaving the designated area"], "adult_supervision": false, "stop_conditions": ["If a player feels unsafe, the game stops immediately", "If weather becomes severe, relocate to shelter", "If anyone is injured, call emergency services"]}, "story_seed": {"tone": "playful", "motifs": ["exploration", "discovery", "teamwork"], "recap_style": "episode_recap"}}, "host_started_at": "2026-06-12T17:44:34.248892+00:00", "team_start_offsets": {"team-a": 0, "team-b": 60}, "team_finished": {"team-a": "2026-06-12T17:44:40.426298+00:00"}, "photos": []}, "70959adc-6172-41e6-ae4f-ef8f90772dba": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 45, "num_players": 4, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "QVTJKG", "host_name": "Host", "status": "lobby", "teams": [{"id": "team-a", "name": "River", "role": "Explorers"}, {"id": "team-b", "name": "Meadow", "role": "Explorers"}], "players": [{"name": "Host", "team_id": "team-a"}], "game": null, "host_started_at": null, "team_start_offsets": {}, "team_finished": {}, "photos": []}, "8e04b90f-baa6-45a6-9a8b-21d91a4b4d8a": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 45, "num_players": 4, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "NCVFAZ", "host_name": "Host", "status": "lobby", "teams": [{"id": "team-a", "name": "River", "role": "Explorers"}, {"id": "team-b", "name": "Meadow", "role": "Explorers"}], "players": [{"name": "Host", "team_id": "team-a"}], "game": null, "host_started_at": null, "team_start_offsets": {}, "team_finished": {}, "photos": []}, "bc218c4b-3b0d-4f33-b91a-8b10500ea29e": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 45, "num_players": 4, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "9F2X98", "host_name": "Host", "status": "lobby", "teams": [{"id": "team-a", "name": "River", "role": "Explorers"}, {"id": "team-b", "name": "Meadow", "role": "Explorers"}], "players": [{"name": "Host", "team_id": "team-a"}], "game": null, "host_started_at": null, "team_start_offsets": {}, "team_finished": {}, "photos": []}, "29725220-ef25-499f-9ef3-47f4afacbff4": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 45, "num_players": 4, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "AFV67H", "host_name": "Host", "status": "lobby", "teams": [{"id": "team-a", "name": "River", "role": "Explorers"}, {"id": "team-b", "name": "Meadow", "role": "Explorers"}], "players": [{"name": "Host", "team_id": "team-a"}, {"name": "hola", "team_id": "team-b"}], "game": null, "host_started_at": null, "team_start_offsets": {}, "team_finished": {}, "photos": []}, "9c9f53d7-5b26-4d11-be5a-eb6b657b63c2": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 45, "num_players": 4, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "WQ799U", "host_name": "Host", "status": "lobby", "teams": [{"id": "team-a", "name": "River", "role": "Explorers"}, {"id": "team-b", "name": "Meadow", "role": "Explorers"}], "players": [{"name": "Host", "team_id": "team-a"}, {"name": "lkjdfsdf", "team_id": "team-b"}], "game": null, "host_started_at": null, "team_start_offsets": {}, "team_finished": {}, "photos": []}, "c4f53a5f-6e23-4030-a2e7-a04a47fe14f5": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 45, "num_players": 4, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "CUJCK3", "host_name": "Host", "status": "lobby", "teams": [{"id": "team-a", "name": "River", "role": "Explorers"}, {"id": "team-b", "name": "Meadow", "role": "Explorers"}], "players": [{"name": "Host", "team_id": "team-a"}, {"name": "holakdf", "team_id": "team-b"}], "game": null, "host_started_at": null, "team_start_offsets": {}, "team_finished": {}, "photos": []}, "03491a8c-e9ad-47fe-810e-10acbf649270": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 45, "num_players": 4, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "8MRZWG", "host_name": "Player", "status": "lobby", "teams": [{"id": "team-a", "name": "River", "role": "Explorers"}, {"id": "team-b", "name": "Meadow", "role": "Explorers"}], "players": [{"name": "Player", "team_id": "team-a"}, {"name": "kljdfi", "team_id": "team-b"}], "game": null, "host_started_at": null, "team_start_offsets": {}, "team_finished": {}, "photos": []}, "1959d776-cd89-4aa9-82b1-4922f4d5e37f": {"config": {"game_type": "scavenger_hunt", "city": "Paris", "area": "Downtown", "location_type": "mixed", "duration_minutes": 45, "num_players": 4, "num_teams": 2, "head_start_seconds": 60, "difficulty": "medium", "age_group": "all", "energy_level": "balanced", "photo_enabled": true, "landscape_tags": [], "theme": "", "mobility": "standard", "allow_transport": false}, "room_code": "FAUV65", "host_name": "kljsdf", "status": "lobby", "teams": [{"id": "team-a", "name": "River", "role": "Explorers"}, {"id": "team-b", "name": "Meadow", "role": "Explorers"}], "players": [{"name": "kljsdf", "team_id": "team-a"}, {"name": "kljdfi", "team_id": "team-b"}], "game": null, "host_started_at": null, "team_start_offsets": {}, "team_finished": {}, "photos": []}}}
|
app/ui/theme.py
CHANGED
|
@@ -196,6 +196,20 @@ footer { display: none !important; }
|
|
| 196 |
}
|
| 197 |
|
| 198 |
/* ββ Create screen refinements (scoped to .cq-create only) ββ */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 199 |
/* CHANGE 1: Give the dropdown fields (game type, difficulty, age group, energy)
|
| 200 |
the same grey opaque input box as the textbox fields. Gradio renders a
|
| 201 |
dropdown's display element as .wrap (not a typed <input>), so it never picked
|
|
@@ -359,6 +373,60 @@ ul.options[role="listbox"] li {
|
|
| 359 |
padding: 14px 26px; display: inline-block;
|
| 360 |
}
|
| 361 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 362 |
/* ββ Task wall ββ */
|
| 363 |
.cq-wall { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px,1fr)); gap: 14px; }
|
| 364 |
.cq-tcard {
|
|
@@ -381,7 +449,8 @@ ul.options[role="listbox"] li {
|
|
| 381 |
fragments that re-render every poll tick β it won't re-trigger/flicker. */
|
| 382 |
.cq-pill { transition: background .35s ease, border-color .35s ease, color .35s ease; }
|
| 383 |
.cq-pill.live { border-color: var(--teal); color: var(--teal-dk); }
|
| 384 |
-
.cq-pill.wait { border-color: var(--clay); color: var(--clay-dk);
|
|
|
|
| 385 |
.cq-pill.done { background: var(--teal); color:#0A1F0A; border-color: var(--teal); }
|
| 386 |
.cq-pill.alert { border-color: var(--red); color: #FF8A80; background: rgba(244,67,54,0.18); }
|
| 387 |
.cq-timer { font-family:'Fraunces',serif; font-weight:700; font-size: clamp(1.6rem,5vw,2.4rem);
|
|
|
|
| 196 |
}
|
| 197 |
|
| 198 |
/* ββ Create screen refinements (scoped to .cq-create only) ββ */
|
| 199 |
+
/* Remove the outer grey rectangle around the whole screen. Each screen's own
|
| 200 |
+
gr.Group (.cq-screen) renders Gradio's default card chrome; strip it so the
|
| 201 |
+
inner .cq-card floats against the animated background. Scoped to the group's
|
| 202 |
+
own wrapper layers so the inner .cq-card keeps its border/fill. Applies to
|
| 203 |
+
every screen (create, join, lobby, play, wait, win). */
|
| 204 |
+
.cq-screen,
|
| 205 |
+
.cq-screen > .block,
|
| 206 |
+
.cq-screen > div:not(.cq-card),
|
| 207 |
+
.cq-screen > .block > div:not(.cq-card) {
|
| 208 |
+
background: transparent !important;
|
| 209 |
+
border: none !important;
|
| 210 |
+
box-shadow: none !important;
|
| 211 |
+
backdrop-filter: none !important;
|
| 212 |
+
}
|
| 213 |
/* CHANGE 1: Give the dropdown fields (game type, difficulty, age group, energy)
|
| 214 |
the same grey opaque input box as the textbox fields. Gradio renders a
|
| 215 |
dropdown's display element as .wrap (not a typed <input>), so it never picked
|
|
|
|
| 373 |
padding: 14px 26px; display: inline-block;
|
| 374 |
}
|
| 375 |
|
| 376 |
+
/* ββ Lobby: room-code hint (replaces the redundant "SHAREβ¦" label) ββ */
|
| 377 |
+
.cq-code-hint {
|
| 378 |
+
text-align: center; color: var(--muted);
|
| 379 |
+
font-size: 0.95rem; margin-bottom: 10px;
|
| 380 |
+
}
|
| 381 |
+
|
| 382 |
+
/* ββ Lobby: copy-to-clipboard button beside the room code ββ */
|
| 383 |
+
.cq-copy-wrap { display: flex; justify-content: center; margin-top: 12px; }
|
| 384 |
+
.cq-copy-btn {
|
| 385 |
+
background: var(--paper-2); color: var(--ink);
|
| 386 |
+
border: 1px solid var(--line); border-radius: 999px;
|
| 387 |
+
padding: 8px 20px; font-size: 0.95rem; font-family: 'Inter', sans-serif;
|
| 388 |
+
font-weight: 600; cursor: pointer; transition: all 0.2s ease;
|
| 389 |
+
}
|
| 390 |
+
.cq-copy-btn:hover {
|
| 391 |
+
background: #4A4A4A; border-color: var(--green); transform: scale(1.03);
|
| 392 |
+
}
|
| 393 |
+
.cq-copy-btn.copied {
|
| 394 |
+
background: rgba(76,175,80,0.22); border-color: var(--green); color: var(--ink);
|
| 395 |
+
transform: scale(1.0);
|
| 396 |
+
}
|
| 397 |
+
|
| 398 |
+
/* ββ Lobby: team-pick buttons β selected state ββ */
|
| 399 |
+
.team-pick.selected button {
|
| 400 |
+
background: rgba(76,175,80,0.20) !important;
|
| 401 |
+
border: 2px solid var(--green) !important;
|
| 402 |
+
color: var(--ink) !important; font-weight: 700 !important;
|
| 403 |
+
box-shadow: 0 0 12px rgba(76,175,80,0.3) !important;
|
| 404 |
+
}
|
| 405 |
+
|
| 406 |
+
/* ββ Lobby: "N / M teams ready" progress bar ββ */
|
| 407 |
+
.cq-progress { margin: 2px 0 6px 0; }
|
| 408 |
+
.cq-progress-label {
|
| 409 |
+
font-size: 0.85rem; color: var(--muted); margin-bottom: 6px; display: block;
|
| 410 |
+
}
|
| 411 |
+
.cq-progress-track {
|
| 412 |
+
height: 6px; background: var(--paper-2); border-radius: 3px; overflow: hidden;
|
| 413 |
+
}
|
| 414 |
+
.cq-progress-fill {
|
| 415 |
+
height: 100%; background: var(--green); border-radius: 3px;
|
| 416 |
+
transition: width 0.4s ease;
|
| 417 |
+
}
|
| 418 |
+
|
| 419 |
+
/* ββ Lobby: center the prep status pill (loading / ready) ββ */
|
| 420 |
+
.lobby-prep { text-align: center; }
|
| 421 |
+
|
| 422 |
+
/* ββ Lobby: host/guest instruction line ββ */
|
| 423 |
+
.lobby-hint, .lobby-hint p {
|
| 424 |
+
text-align: center; color: var(--clay-dk) !important;
|
| 425 |
+
font-size: 1rem !important; font-weight: 500 !important;
|
| 426 |
+
background: rgba(255,193,7,0.08); border-radius: 8px;
|
| 427 |
+
padding: 8px 16px; margin: 8px 0 !important;
|
| 428 |
+
}
|
| 429 |
+
|
| 430 |
/* ββ Task wall ββ */
|
| 431 |
.cq-wall { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px,1fr)); gap: 14px; }
|
| 432 |
.cq-tcard {
|
|
|
|
| 449 |
fragments that re-render every poll tick β it won't re-trigger/flicker. */
|
| 450 |
.cq-pill { transition: background .35s ease, border-color .35s ease, color .35s ease; }
|
| 451 |
.cq-pill.live { border-color: var(--teal); color: var(--teal-dk); }
|
| 452 |
+
.cq-pill.wait { border-color: var(--clay); color: var(--clay-dk);
|
| 453 |
+
background: rgba(255,193,7,0.15); }
|
| 454 |
.cq-pill.done { background: var(--teal); color:#0A1F0A; border-color: var(--teal); }
|
| 455 |
.cq-pill.alert { border-color: var(--red); color: #FF8A80; background: rgba(244,67,54,0.18); }
|
| 456 |
.cq-timer { font-family:'Fraunces',serif; font-weight:700; font-size: clamp(1.6rem,5vw,2.4rem);
|