Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -336,7 +336,6 @@ async def websocket_handler(websocket, path):
|
|
336 |
st.session_state.active_connections[room_id] = {}
|
337 |
st.session_state.active_connections[room_id][client_id] = websocket
|
338 |
username = st.session_state.username
|
339 |
-
|
340 |
game_state = load_game_state(st.session_state.game_state_timestamp)
|
341 |
if "prairie" in path:
|
342 |
char = next(c for c in EDGE_TTS_VOICES if c["name"] == username)
|
@@ -355,7 +354,6 @@ async def websocket_handler(websocket, path):
|
|
355 |
update_game_state(game_state)
|
356 |
st.session_state.players[client_id] = game_state["players"][username]
|
357 |
await broadcast_message(f"System|{username} joins the quest!", room_id)
|
358 |
-
|
359 |
try:
|
360 |
async for message in websocket:
|
361 |
if '|' in message:
|
@@ -400,17 +398,14 @@ async def periodic_update():
|
|
400 |
for username in game_state["players"]:
|
401 |
game_state["players"][username]["score"] += int((current_time - game_state["players"][username]["last_active"]) * 60)
|
402 |
update_game_state(game_state)
|
403 |
-
|
404 |
player_list = ", ".join([p for p in game_state["players"].keys()]) or "No adventurers yet!"
|
405 |
message = f"π’ Quest Update: Active Adventurers - {player_list}"
|
406 |
player_data = json.dumps(list(game_state["players"].values()))
|
407 |
await broadcast_message(f"MAP_UPDATE:{player_data}", "quest")
|
408 |
-
|
409 |
prairie_list = ", ".join([f"{p['username']} ({p['animal']})" for p in st.session_state.prairie_players.values()]) or "No animals yet!"
|
410 |
prairie_message = f"πΎ Prairie Update: {prairie_list}"
|
411 |
prairie_data = json.dumps(list(st.session_state.prairie_players.values()))
|
412 |
await broadcast_message(f"PRAIRIE_UPDATE:{prairie_data}", "quest")
|
413 |
-
|
414 |
chat_content = await load_chat()
|
415 |
await broadcast_message(f"CHAT_UPDATE:{json.dumps(chat_content[-10:])}", "quest")
|
416 |
await broadcast_message(f"GAME_STATE:{json.dumps(game_state)}", "quest")
|
@@ -486,7 +481,7 @@ def log_performance_metrics():
|
|
486 |
# -----------------------------------------------------------
|
487 |
# Enhanced 3D Game HTML (With dynamic insertion of username and fluid movement)
|
488 |
# -----------------------------------------------------------
|
489 |
-
# Precompute
|
490 |
player_color = next(c["color"] for c in EDGE_TTS_VOICES if c["name"] == st.session_state.username)
|
491 |
player_shape = next(c["shape"] for c in EDGE_TTS_VOICES if c["name"] == st.session_state.username)
|
492 |
|
@@ -758,6 +753,7 @@ rocky_map_html = f"""
|
|
758 |
# -----------------------------------------------------------
|
759 |
def main():
|
760 |
st.markdown(f"<h2 style='text-align: center;'>Welcome, {st.session_state.username}!</h2>", unsafe_allow_html=True)
|
|
|
761 |
message = st.text_input(f"π¨οΈ Chat as {st.session_state.username}:", placeholder="Type to chat or add world features! π²", key="chat_input")
|
762 |
if st.button("π Send"):
|
763 |
if message:
|
@@ -793,9 +789,11 @@ def main():
|
|
793 |
|
794 |
left_col, right_col = st.columns([2, 1])
|
795 |
with left_col:
|
796 |
-
|
797 |
chat_content = asyncio.run(load_chat())
|
798 |
-
st.
|
|
|
|
|
799 |
uploaded_file = st.file_uploader("Upload a File π€", type=["txt", "md", "mp3"])
|
800 |
if uploaded_file:
|
801 |
with open(uploaded_file.name, "wb") as f:
|
@@ -807,24 +805,27 @@ def main():
|
|
807 |
update_game_state(game_state)
|
808 |
st.session_state.last_activity = time.time()
|
809 |
st.success(f"File uploaded! +20 points! New Score: ${st.session_state.score}")
|
810 |
-
|
811 |
-
|
812 |
-
|
813 |
-
|
814 |
-
|
815 |
-
|
816 |
-
|
817 |
-
|
818 |
-
|
819 |
-
|
820 |
-
|
821 |
-
|
|
|
822 |
with right_col:
|
823 |
st.subheader("πΎ Prairie Map")
|
824 |
prairie_map = folium.Map(location=[44.0, -103.0], zoom_start=8, tiles="CartoDB Positron")
|
|
|
825 |
for loc, (lat, lon) in PRAIRIE_LOCATIONS.items():
|
826 |
folium.Marker([lat, lon], popup=loc).add_to(prairie_map)
|
827 |
game_state = load_game_state(st.session_state.game_state_timestamp)
|
|
|
828 |
for username, player in game_state["players"].items():
|
829 |
folium.CircleMarker(
|
830 |
location=[44.0 + player["x"] * 0.01, -103.0 + player["z"] * 0.01],
|
@@ -834,6 +835,7 @@ def main():
|
|
834 |
fill_opacity=0.7,
|
835 |
popup=f"{username} (Score: ${player['score']}, Treasures: {player['treasures']})"
|
836 |
).add_to(prairie_map)
|
|
|
837 |
for client_id, player in st.session_state.prairie_players.items():
|
838 |
folium.CircleMarker(
|
839 |
location=player['location'],
|
@@ -843,7 +845,15 @@ def main():
|
|
843 |
fill_opacity=0.7,
|
844 |
popup=f"{player['username']} ({player['animal']})"
|
845 |
).add_to(prairie_map)
|
846 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
847 |
st_folium(prairie_map, width=600, height=400)
|
848 |
animal = st.selectbox("Choose Animal πΎ", ["prairie_dog", "deer", "sheep", "groundhog"])
|
849 |
location = st.selectbox("Move to π", list(PRAIRIE_LOCATIONS.keys()))
|
|
|
336 |
st.session_state.active_connections[room_id] = {}
|
337 |
st.session_state.active_connections[room_id][client_id] = websocket
|
338 |
username = st.session_state.username
|
|
|
339 |
game_state = load_game_state(st.session_state.game_state_timestamp)
|
340 |
if "prairie" in path:
|
341 |
char = next(c for c in EDGE_TTS_VOICES if c["name"] == username)
|
|
|
354 |
update_game_state(game_state)
|
355 |
st.session_state.players[client_id] = game_state["players"][username]
|
356 |
await broadcast_message(f"System|{username} joins the quest!", room_id)
|
|
|
357 |
try:
|
358 |
async for message in websocket:
|
359 |
if '|' in message:
|
|
|
398 |
for username in game_state["players"]:
|
399 |
game_state["players"][username]["score"] += int((current_time - game_state["players"][username]["last_active"]) * 60)
|
400 |
update_game_state(game_state)
|
|
|
401 |
player_list = ", ".join([p for p in game_state["players"].keys()]) or "No adventurers yet!"
|
402 |
message = f"π’ Quest Update: Active Adventurers - {player_list}"
|
403 |
player_data = json.dumps(list(game_state["players"].values()))
|
404 |
await broadcast_message(f"MAP_UPDATE:{player_data}", "quest")
|
|
|
405 |
prairie_list = ", ".join([f"{p['username']} ({p['animal']})" for p in st.session_state.prairie_players.values()]) or "No animals yet!"
|
406 |
prairie_message = f"πΎ Prairie Update: {prairie_list}"
|
407 |
prairie_data = json.dumps(list(st.session_state.prairie_players.values()))
|
408 |
await broadcast_message(f"PRAIRIE_UPDATE:{prairie_data}", "quest")
|
|
|
409 |
chat_content = await load_chat()
|
410 |
await broadcast_message(f"CHAT_UPDATE:{json.dumps(chat_content[-10:])}", "quest")
|
411 |
await broadcast_message(f"GAME_STATE:{json.dumps(game_state)}", "quest")
|
|
|
481 |
# -----------------------------------------------------------
|
482 |
# Enhanced 3D Game HTML (With dynamic insertion of username and fluid movement)
|
483 |
# -----------------------------------------------------------
|
484 |
+
# Precompute player color and shape for use in the HTML.
|
485 |
player_color = next(c["color"] for c in EDGE_TTS_VOICES if c["name"] == st.session_state.username)
|
486 |
player_shape = next(c["shape"] for c in EDGE_TTS_VOICES if c["name"] == st.session_state.username)
|
487 |
|
|
|
753 |
# -----------------------------------------------------------
|
754 |
def main():
|
755 |
st.markdown(f"<h2 style='text-align: center;'>Welcome, {st.session_state.username}!</h2>", unsafe_allow_html=True)
|
756 |
+
# Chat Input Area
|
757 |
message = st.text_input(f"π¨οΈ Chat as {st.session_state.username}:", placeholder="Type to chat or add world features! π²", key="chat_input")
|
758 |
if st.button("π Send"):
|
759 |
if message:
|
|
|
789 |
|
790 |
left_col, right_col = st.columns([2, 1])
|
791 |
with left_col:
|
792 |
+
# Display the Quest Log as a code block with Python syntax and line numbers (if supported)
|
793 |
chat_content = asyncio.run(load_chat())
|
794 |
+
st.code("\n".join(chat_content[-10:]), language="python")
|
795 |
+
# Then display the 3D world
|
796 |
+
components.html(rocky_map_html, width=800, height=600)
|
797 |
uploaded_file = st.file_uploader("Upload a File π€", type=["txt", "md", "mp3"])
|
798 |
if uploaded_file:
|
799 |
with open(uploaded_file.name, "wb") as f:
|
|
|
805 |
update_game_state(game_state)
|
806 |
st.session_state.last_activity = time.time()
|
807 |
st.success(f"File uploaded! +20 points! New Score: ${st.session_state.score}")
|
808 |
+
# Speech component integration remains as before.
|
809 |
+
mycomponent = components.declare_component("speech_component", path="./speech_component")
|
810 |
+
val = mycomponent(my_input_value="", key=f"speech_{st.session_state.get('speech_processed', False)}")
|
811 |
+
if val and val != st.session_state.last_transcript:
|
812 |
+
val_stripped = val.strip().replace('\n', ' ')
|
813 |
+
if val_stripped:
|
814 |
+
voice = next(c["voice"] for c in EDGE_TTS_VOICES if c["name"] == st.session_state.username)
|
815 |
+
st.session_state['speech_processed'] = True
|
816 |
+
md_file, audio_file = asyncio.run(save_chat_entry(st.session_state.username, val_stripped, voice))
|
817 |
+
if audio_file:
|
818 |
+
play_and_download_audio(audio_file)
|
819 |
+
st.session_state.last_activity = time.time()
|
820 |
+
st.rerun()
|
821 |
with right_col:
|
822 |
st.subheader("πΎ Prairie Map")
|
823 |
prairie_map = folium.Map(location=[44.0, -103.0], zoom_start=8, tiles="CartoDB Positron")
|
824 |
+
# Add base locations
|
825 |
for loc, (lat, lon) in PRAIRIE_LOCATIONS.items():
|
826 |
folium.Marker([lat, lon], popup=loc).add_to(prairie_map)
|
827 |
game_state = load_game_state(st.session_state.game_state_timestamp)
|
828 |
+
# Mark players
|
829 |
for username, player in game_state["players"].items():
|
830 |
folium.CircleMarker(
|
831 |
location=[44.0 + player["x"] * 0.01, -103.0 + player["z"] * 0.01],
|
|
|
835 |
fill_opacity=0.7,
|
836 |
popup=f"{username} (Score: ${player['score']}, Treasures: {player['treasures']})"
|
837 |
).add_to(prairie_map)
|
838 |
+
# Mark prairie players (animals)
|
839 |
for client_id, player in st.session_state.prairie_players.items():
|
840 |
folium.CircleMarker(
|
841 |
location=player['location'],
|
|
|
845 |
fill_opacity=0.7,
|
846 |
popup=f"{player['username']} ({player['animal']})"
|
847 |
).add_to(prairie_map)
|
848 |
+
# Mark world objects (plants, trees, etc.) with emojis and pins
|
849 |
+
for obj in game_state["world_objects"]:
|
850 |
+
lat = 44.0 + obj["x"] * 0.01
|
851 |
+
lon = -103.0 + obj["z"] * 0.01
|
852 |
+
folium.Marker(
|
853 |
+
location=[lat, lon],
|
854 |
+
popup=f"{obj['emoji']} {obj['type']}",
|
855 |
+
icon=folium.DivIcon(html=f"<div style='font-size: 24px;'>{obj['emoji']}</div>")
|
856 |
+
).add_to(prairie_map)
|
857 |
st_folium(prairie_map, width=600, height=400)
|
858 |
animal = st.selectbox("Choose Animal πΎ", ["prairie_dog", "deer", "sheep", "groundhog"])
|
859 |
location = st.selectbox("Move to π", list(PRAIRIE_LOCATIONS.keys()))
|