Spaces:
Running
Running
import streamlit as st | |
import random | |
import time | |
from datetime import datetime | |
import base64 | |
# --- App Title and Config --- | |
st.set_page_config(page_title="Gamuu", page_icon="๐ฎ", layout="wide") | |
st.title("๐ฎ Gamuu - Ultimate Connection Game") | |
# --- Initialize Session State (with some additions for robustness) --- | |
if 'registered' not in st.session_state: | |
st.session_state.registered = False # True if at least one player is registered | |
if 'players' not in st.session_state: | |
st.session_state.players = {} # {name: {details}} | |
if 'teams' not in st.session_state: | |
st.session_state.teams = {} # {team_name: [player_name1, player_name2]} - for multi-player teams | |
if 'questions' not in st.session_state: | |
st.session_state.questions = { | |
'Music': [ | |
"If your life had a theme song, what would it be?", | |
"What song describes your love life?", | |
"What concert would you travel back in time to see?", | |
"If you could only listen to one artist for the rest of your life, who would it be?", | |
"What song always makes you want to dance?", | |
"Which music genre do you think best represents your personality?", | |
"What's the most underrated song you know?", | |
"If you could write a song about your life, what would the title be?", | |
"What's your favorite music video?", | |
"What song do you listen to when you're feeling down?", | |
"What's the best live performance you've ever seen?", | |
"What song reminds you of your childhood?", | |
"What's your favorite karaoke song?", | |
"What song do you wish you could play on an instrument?", | |
"What's the first album you ever bought?", | |
"What song do you associate with your favorite memory?", | |
"What's your favorite song to sing in the shower?", | |
"What song always gets stuck in your head?", | |
"What's your favorite song from a movie soundtrack?", | |
"What song do you listen to when you need motivation?", | |
"What's your favorite cover of a song?", | |
"What song do you think has the best lyrics?", | |
"What's your favorite instrumental song?", | |
"What song do you listen to when you're relaxing?", | |
"What's your favorite song to dance to at a party?", | |
"What song reminds you of a past relationship?", | |
"What's your favorite song to listen to while driving?", | |
"What song do you think is overrated?", | |
"What's your favorite song from a video game?", | |
"What song do you listen to when you're working out?" | |
], | |
'Love Language': [ | |
"How do you prefer to receive affection?", | |
"What's your unconventional love language?", | |
"How do you show love when words aren't enough?", | |
"What's the most thoughtful gift you've ever received?", | |
"How do you express love without using words?", | |
"What's the sweetest thing someone has done for you?", | |
"How do you like to be comforted when you're feeling down?", | |
"What's your favorite way to spend quality time with someone?", | |
"What's the most romantic gesture you've ever experienced?", | |
"What's your favorite thing to wear to feel sexy?", | |
"What's the most unexpected place you've felt a spark with someone?", | |
"What's your favorite scent on a partner?", | |
"What's the most adventurous place you've ever had a romantic encounter?", | |
"What's your favorite fantasy role-play scenario?", | |
"What's the most daring thing you've done to impress someone?", | |
"What's your favorite part of your partner's body?", | |
"What's the wildest place you've ever had sex?", | |
"What's your favorite position and why?", | |
"What's the most adventurous thing you've done in the bedroom?", | |
"What's your favorite toy or accessory to use during intimate moments?", | |
"What's the most daring fantasy you've ever had?", | |
"What's the most taboo thing you've ever fantasized about?", | |
"Have you ever had a threesome or group experience? Details?", | |
"What's the most intense BDSM experience you've had?", | |
"What's your favorite kink or fetish?", | |
"Have you ever had sex in a public place? What happened?", | |
"What's the craziest travel adventure you've had?", | |
"What's your favorite self-care activity?", | |
"What's the biggest lesson you've learned in life?", | |
"What's your proudest achievement?" | |
], | |
'Movies': [ | |
"What movie character represents your ideal partner?", | |
"What romantic scene from a movie would you reenact?", | |
"If you could be any movie character, who would it be and why?", | |
"What movie scene always makes you cry?", | |
"Which movie do you wish you could watch for the first time again?", | |
"What's the most quotable movie you've seen?", | |
"If you could direct a movie, what genre would it be and what would the plot be?", | |
"What's your favorite movie soundtrack?", | |
"What movie do you always watch when you're sick?", | |
"What's the scariest movie you've ever seen?", | |
"What movie has the best twist ending?", | |
"What's your favorite animated movie?", | |
"What movie do you love that everyone else hates?", | |
"What's your favorite movie quote?", | |
"What movie has the best special effects?", | |
"What's your favorite comedy movie?", | |
"What movie has the best fight scene?", | |
"What's your favorite movie to watch with friends?", | |
"What movie has the best car chase?", | |
"What's your favorite movie adaptation of a book?", | |
"What movie has the best costume design?", | |
"What's your favorite movie franchise?", | |
"What movie has the best opening scene?", | |
"What's your favorite movie ending?", | |
"What movie has the best cinematography?", | |
"What's your favorite movie villain?", | |
"What movie has the best love story?", | |
"What's your favorite movie soundtrack song?", | |
"What movie has the best dance scene?", | |
"What's your favorite movie genre?" | |
], | |
'Activities': [ | |
"What's the most adventurous thing you've ever done?", | |
"If you could learn any new skill instantly, what would it be?", | |
"What's your favorite childhood game or activity?", | |
"If you could travel anywhere in the world, where would you go and why?", | |
"What's the most relaxing activity you enjoy?", | |
"What's your idea of a perfect day together?", | |
"What adventure would you want to experience with a partner?", | |
"What's the most beautiful place you've ever visited?", | |
"If you could live anywhere in the world, where would it be?", | |
"What's the most memorable trip you've taken?", | |
"What's your dream vacation destination?", | |
"What's the craziest travel adventure you've had?", | |
"What's your favorite self-care activity?", | |
"What's the biggest lesson you've learned in life?", | |
"What's your proudest achievement?", | |
"What's the best advice you've ever received?", | |
"What's your biggest fear and how do you overcome it?", | |
"What's your favorite way to spend a rainy day?", | |
"What's your favorite outdoor activity?", | |
"What's your favorite indoor activity?", | |
"What's your favorite sport to play or watch?", | |
"What's your favorite board game or card game?", | |
"What's your favorite video game?", | |
"What's your favorite hobby?", | |
"What's your favorite way to exercise?", | |
"What's your favorite way to relax?", | |
"What's your favorite way to spend time with friends?", | |
"What's your favorite way to spend time alone?", | |
"What's your favorite way to celebrate a special occasion?", | |
"What's your favorite way to unwind after a long day?" | |
], | |
'18+': { | |
'Spicy': [ | |
"What's your secret turn-on?", | |
"Where's the most unusual place you've been kissed?", | |
"What fantasy have you never admitted?", | |
"What's your favorite role-play scenario?", | |
"What's the most adventurous intimate experience you've had?", | |
"What's your wildest unfulfilled desire?", | |
"What's the most daring thing you've done in the bedroom?", | |
"What's your favorite intimate accessory?", | |
"What's the most unexpected place you've felt a spark with someone?", | |
"What's your favorite scent on a partner?", | |
"What's the most adventurous place you've ever had a romantic encounter?", | |
"What's your favorite fantasy role-play scenario?", | |
"What's the most daring thing you've done to impress someone?", | |
"What's your favorite part of your partner's body?", | |
"What's the wildest place you've ever had sex?", | |
"What's your favorite position and why?", | |
"What's the most adventurous thing you've done in the bedroom?", | |
"What's your favorite toy or accessory to use during intimate moments?", | |
"What's your most daring fantasy you've ever had?", | |
"What's the most taboo thing you've ever fantasized about?", | |
"Have you ever had a threesome or group experience? Details?", | |
"What's the most intense BDSM experience you've had?", | |
"What's your favorite kink or fetish?", | |
"Have you ever had sex in a public place? What happened?", | |
"What's the craziest travel adventure you've had?", | |
"What's your favorite self-care activity?", | |
"What's the biggest lesson you've learned in life?", | |
"What's your proudest achievement?", | |
"What's the best advice you've ever received?", | |
"What's your biggest fear and how do you overcome it?" | |
], | |
'Extra Spicy': [ | |
"What's your favorite piece of lingerie or underwear?", | |
"What's the most adventurous place you've ever had a romantic encounter?", | |
"What's your favorite fantasy role-play scenario?", | |
"What's the most daring thing you've done to impress someone?", | |
"What's your favorite part of your partner's body?", | |
"What's the wildest place you've ever had sex?", | |
"What's your favorite position and why?", | |
"What's the most adventurous thing you've done in the bedroom?", | |
"What's your favorite toy or accessory to use during intimate moments?", | |
"What's your most daring fantasy you've ever had?", | |
"What's the most taboo thing you've ever fantasized about?", | |
"Have you ever had a threesome or group experience? Details?", | |
"What's the most intense BDSM experience you've had?", | |
"What's your favorite kink or fetish?", | |
"Have you ever had sex in a public place? What happened?", | |
"What's the craziest travel adventure you've had?", | |
"What's your favorite self-care activity?", | |
"What's the biggest lesson you've learned in life?", | |
"What's your proudest achievement?", | |
"What's the best advice you've ever received?", | |
"What's your biggest fear and how do you overcome it?", | |
"What's your favorite way to spend a rainy day?", | |
"What's your favorite outdoor activity?", | |
"What's your favorite indoor activity?", | |
"What's your favorite sport to play or watch?", | |
"What's your favorite board game or card game?", | |
"What's your favorite video game?", | |
"What's your favorite hobby?", | |
"What's your favorite way to exercise?", | |
"What's your favorite way to relax?", | |
"What's your favorite way to spend time with friends?" | |
], | |
'Space Spicy': [ | |
"Describe your most adventurous intimate experience.", | |
"What's your wildest unfulfilled desire?", | |
"What's the most daring thing you've done in the bedroom?", | |
"What's your favorite intimate accessory?", | |
"What's the most unexpected place you've felt a spark with someone?", | |
"What's your favorite scent on a partner?", | |
"What's the most adventurous place you've ever had a romantic encounter?", | |
"What's your favorite fantasy role-play scenario?", | |
"What's the most daring thing you've done to impress someone?", | |
"What's your favorite part of your partner's body?", | |
"What's the wildest place you've ever had sex?", | |
"What's your favorite position and why?", | |
"What's the most adventurous thing you've done in the bedroom?", | |
"What's your favorite toy or accessory to use during intimate moments?", | |
"What's your most daring fantasy you've ever had?", | |
"What's the most taboo thing you've ever fantasized about?", | |
"Have you ever had a threesome or group experience? Details?", | |
"What's the most intense BDSM experience you've had?", | |
"What's your favorite kink or fetish?", | |
"Have you ever had sex in a public place? What happened?", | |
"What's the craziest travel adventure you've had?", | |
"What's your favorite self-care activity?", | |
"What's the biggest lesson you've learned in life?", | |
"What's your proudest achievement?", | |
"What's the best advice you've ever received?", | |
"What's your biggest fear and how do you overcome it?", | |
"What's your favorite way to spend a rainy day?", | |
"What's your favorite outdoor activity?", | |
"What's your favorite indoor activity?", | |
"What's your favorite sport to play or watch?", | |
"What's your favorite board game or card game?", | |
"What's your favorite video game?" | |
], | |
'Hardcore': [ | |
"What's the most taboo thing you've ever fantasized about?", | |
"Have you ever had a threesome or group experience? Details?", | |
"What's the most intense BDSM experience you've had?", | |
"What's your favorite kink or fetish?", | |
"Have you ever had sex in a public place? What happened?", | |
"What's the craziest travel adventure you've had?", | |
"What's your favorite self-care activity?", | |
"What's the biggest lesson you've learned in life?", | |
"What's your proudest achievement?", | |
"What's the best advice you've ever received?", | |
"What's your biggest fear and how do you overcome it?", | |
"What's your favorite way to spend a rainy day?", | |
"What's your favorite outdoor activity?", | |
"What's your favorite indoor activity?", | |
"What's your favorite sport to play or watch?", | |
"What's your favorite board game or card game?", | |
"What's your favorite video game?", | |
"What's your favorite hobby?", | |
"What's your favorite way to exercise?", | |
"What's your favorite way to relax?", | |
"What's your favorite way to spend time with friends?", | |
"What's your favorite way to spend time alone?", | |
"What's your favorite way to celebrate a special occasion?", | |
"What's your favorite way to unwind after a long day?", | |
"What's your favorite movie soundtrack song?", | |
"What movie has the best dance scene?", | |
"What's your favorite movie genre?", | |
"What's your favorite movie villain?", | |
"What movie has the best love story?", | |
"What's your favorite movie soundtrack?", | |
"What movie do you always watch when you're sick?" | |
] | |
}, | |
'Travel': [ | |
"What's the most beautiful place you've ever visited?", | |
"If you could live anywhere in the world, where would it be?", | |
"What's the most memorable trip you've taken?", | |
"What's your dream vacation destination?", | |
"What's the craziest travel adventure you've had?", | |
"What's your favorite mode of transportation when traveling?", | |
"What's the best local cuisine you've ever tried?", | |
"What's the most interesting cultural experience you've had?", | |
"What's the most beautiful natural wonder you've seen?", | |
"What's your favorite travel memory?", | |
"What's the most challenging travel experience you've had?", | |
"What's your favorite travel companion?", | |
"What's the most unexpected place you've visited?", | |
"What's your favorite travel book or movie?", | |
"What's the most luxurious travel experience you've had?", | |
"What's your favorite travel quote?", | |
"What's the most adventurous thing you've done while traveling?", | |
"What's your favorite travel souvenir?", | |
"What's the most beautiful sunset you've seen?", | |
"What's your favorite travel photo you've taken?", | |
"What's the most interesting historical site you've visited?", | |
"What's your favorite travel app or tool?", | |
"What's the most relaxing travel experience you've had?", | |
"What's your favorite travel hack?", | |
"What's the most beautiful beach you've visited?", | |
"What's your favorite travel destination for food?", | |
"What's the most interesting wildlife you've seen?", | |
"What's your favorite travel destination for adventure?", | |
"What's the most beautiful city you've visited?", | |
"What's your favorite travel destination for culture?" | |
], | |
'Food': [ | |
"What's your favorite comfort food?", | |
"If you could only eat one cuisine for the rest of your life, what would it be?", | |
"What's the most exotic food you've ever tried?", | |
"What's your go-to meal to cook for someone special?", | |
"What's the best meal you've ever had?", | |
"What's your favorite dessert?", | |
"What's your favorite cooking show or chef?", | |
"What's the most memorable meal you've had while traveling?", | |
"What's your favorite food memory from childhood?", | |
"What's your favorite type of cheese?", | |
"What's your favorite food to order for delivery?", | |
"What's your favorite food to eat at a sports game?", | |
"What's your favorite food to eat at the movies?", | |
"What's your favorite food to eat for breakfast?", | |
"What's your favorite food to eat for a midnight snack?", | |
"What's your favorite food to eat at a picnic?", | |
"What's your favorite food to eat at a barbecue?", | |
"What's your favorite food to eat at a fancy restaurant?", | |
"What's your favorite food to eat at a casual restaurant?", | |
"What's your favorite food to eat at a food truck?", | |
"What's your favorite food to eat at a street market?", | |
"What's your favorite food to eat at a festival?", | |
"What's your favorite food to eat at a theme park?", | |
"What's your favorite food to eat at a concert?", | |
"What's_your favorite food to eat at a sporting event?", | |
"What's your favorite food to eat at a carnival?", | |
"What's your favorite food to eat at a fair?", | |
"What's your favorite food to eat at a holiday gathering?", | |
"What's your favorite food to eat at a family reunion?" | |
], | |
'Personal Growth': [ | |
"What's the biggest lesson you've learned in life?", | |
"What's your proudest achievement?", | |
"What's the best advice you've ever received?", | |
"What's your biggest fear and how do you overcome it?", | |
"What's your favorite self-care activity?", | |
"What's the most challenging thing you've ever done?", | |
"What's your favorite way to relax and unwind?", | |
"What's your favorite book or podcast for personal growth?", | |
"What's the most important value you live by?", | |
"What's your favorite quote or mantra?", | |
"What's the most meaningful compliment you've ever received?", | |
"What's your favorite way to give back to your community?", | |
"What's the most impactful experience you've had?", | |
"What's your favorite way to stay motivated?", | |
"What's the most important goal you're working towards?", | |
"What's your favorite way to stay organized?", | |
"What's the most important habit you've developed?", | |
"What's your favorite way to stay healthy?", | |
"What's the most important relationship in your life?", | |
"What's your favorite way to stay connected with friends and family?", | |
"What's the most important lesson you've learned from a failure?", | |
"What's your favorite way to stay positive?", | |
"What's the most important quality you look for in a friend?", | |
"What's your favorite way to stay creative?", | |
"What's the most important skill you've learned?", | |
"What's your favorite way to stay curious?", | |
"What's the most important lesson you've learned from a mentor?", | |
"What's your favorite way to stay inspired?", | |
"What's the most important change you've made in your life?", | |
"What's your favorite way to stay grateful?" | |
], | |
'Dare': [ | |
"Show us your best dance move!", | |
"Sing a song out loud for 30 seconds!", | |
"Tell a funny joke that makes everyone laugh!", | |
"Share a secret talent you have!", | |
"Do a 30-second plank!", | |
"Mimic your favorite celebrity!", | |
"Share your most embarrassing moment!", | |
"Do a dramatic reading of a random text message!", | |
"Show us your best impression of another player!", | |
"Share a childhood nickname and the story behind it!", | |
"Do a 30-second freestyle rap!", | |
"Share a hidden skill or hobby you have!", | |
"Do a 30-second yoga pose!", | |
"Share a funny childhood memory!", | |
"Do a 30-second impersonation of a famous character!", | |
"Share a funny pet story!", | |
"Do a 30-second interpretive dance!", | |
"Share a funny travel story!", | |
"Do a 30-second comedy skit!", | |
"Share a funny family tradition!", | |
"Do a 30-second magic trick!", | |
"Share a funny school memory!", | |
"Do a 30-second fitness challenge!", | |
"Share a funny work story!", | |
"Do a 30-second karaoke performance!", | |
"Share a funny dating story!", | |
"Do a 30-second stand-up comedy routine!", | |
"Share a funny holiday memory!", | |
"Do a 30-second dance-off with another player!", | |
"Share a funny prank you've pulled!", | |
"Do a 30-second lip-sync performance!" | |
] | |
} | |
if 'points' not in st.session_state: | |
st.session_state.points = {} # Individual player points | |
if 'team_points' not in st.session_state: | |
st.session_state.team_points = {} # Team points (for multi-player teams) | |
if 'feedback' not in st.session_state: | |
st.session_state.feedback = [] | |
if 'suggestions' not in st.session_state: | |
st.session_state.suggestions = [] | |
if 'current_player' not in st.session_state: | |
st.session_state.current_player = None | |
if 'question' not in st.session_state: | |
st.session_state.question = None | |
if 'timer_start' not in st.session_state: | |
st.session_state.timer_start = None | |
if 'timer_instance_key' not in st.session_state: # Key for HTML timer component | |
st.session_state.timer_instance_key = "timer_initial" | |
if 'achievements' not in st.session_state: | |
st.session_state.achievements = {} # {player_name: [achievement1, ...]} | |
if 'timeouts' not in st.session_state: | |
st.session_state.timeouts = {} # {player_name: count} | |
if 'admin' not in st.session_state: | |
st.session_state.admin = False | |
if 'round' not in st.session_state: | |
st.session_state.round = 0 | |
if 'dare_frequency' not in st.session_state: | |
st.session_state.dare_frequency = 5 | |
if 'penalty_threshold' not in st.session_state: | |
st.session_state.penalty_threshold = 3 | |
if 'game_paused' not in st.session_state: | |
st.session_state.game_paused = False | |
if 'available_categories' not in st.session_state: # Categories chosen by at least one player | |
st.session_state.available_categories = [] | |
if 'theme' not in st.session_state: | |
st.session_state.theme = "Light" | |
if 'leaderboard_history' not in st.session_state: | |
st.session_state.leaderboard_history = [] | |
if 'question_count' not in st.session_state: | |
st.session_state.question_count = 0 | |
if 'current_category_index' not in st.session_state: | |
st.session_state.current_category_index = 0 | |
if 'round_start_time' not in st.session_state: | |
st.session_state.round_start_time = None | |
# --- Theme CSS --- | |
def apply_theme(): | |
if st.session_state.theme == "Dark": | |
st.markdown(""" | |
<style> | |
body { background-color: #1a1a1a; color: #ffffff; } | |
.stApp { background-color: #1a1a1a; color: #ffffff; } | |
.stButton>button { background-color: #4CAF50; color: white; } | |
.stTextInput>div>input { background-color: #333; color: #fff; } | |
</style> | |
""", unsafe_allow_html=True) | |
elif st.session_state.theme == "Retro": | |
st.markdown(""" | |
<style> | |
body { background-color: #f0e68c; color: #8b4513; font-family: 'Courier New', Courier, monospace; } | |
.stApp { background-color: #f0e68c; color: #8b4513; } | |
.stButton>button { background-color: #ff4500; color: white; } | |
.stTextInput>div>input { background-color: #fffacd; color: #8b4513; } | |
</style> | |
""", unsafe_allow_html=True) | |
else: # Light | |
st.markdown(""" | |
<style> | |
body { background-color: #ffffff; color: #000000; } | |
.stApp { background-color: #ffffff; color: #000000; } | |
/* You might want to remove button styling for light theme or make it default */ | |
</style> | |
""", unsafe_allow_html=True) | |
# --- Non-blocking Timer HTML --- | |
timer_html = """ | |
<script> | |
let timeLeft = 30; // This will be visually reset, but actual timeout is Python-driven | |
let timerInterval; // Store interval ID to clear it | |
function startTimer() { | |
clearInterval(timerInterval); // Clear any existing timer | |
timeLeft = 30; // Reset time | |
document.getElementById("timer").innerHTML = `โณ Time Remaining: ${timeLeft}s`; | |
document.getElementById("progress").value = 0; | |
timerInterval = setInterval(() => { | |
if (timeLeft > 0 && !window.gamuuPaused) { // Check a global pause flag | |
timeLeft--; | |
document.getElementById("timer").innerHTML = `โณ Time Remaining: ${timeLeft}s`; | |
document.getElementById("progress").value = 30 - timeLeft; | |
} else if (timeLeft <= 0) { | |
clearInterval(timerInterval); | |
document.getElementById("timer").innerHTML = "โฐ Time's up!"; | |
} | |
}, 1000); | |
} | |
// Functions to be called by Streamlit via st.components.v1.html | |
window.pauseGamuuTimer = function() { window.gamuuPaused = true; } | |
window.resumeGamuuTimer = function() { window.gamuuPaused = false; } | |
// Start timer on initial load of this component | |
// This script block re-runs when the component is re-rendered with a new key. | |
startTimer(); | |
</script> | |
<div id="timer">โณ Time Remaining: 30s</div> | |
<progress id="progress" value="0" max="30" style="width: 100%;"></progress> | |
""" | |
# --- Helper to get registered players for selectboxes --- | |
def get_registered_player_names(): | |
return list(st.session_state.players.keys()) if st.session_state.players else [] | |
# --- Sidebar --- | |
with st.sidebar: | |
st.header("๐ Player Registration") | |
with st.form("registration_form"): # Added form key | |
player_name_input = st.text_input("Your Name") | |
team_name_input = st.text_input("Team Name (leave blank for solo)") | |
all_categories_list = ['Music', 'Love Language', 'Movies', 'Activities', '18+', 'Travel', 'Food', 'Personal Growth', 'Dare'] | |
# Use a dynamic key for multiselect to avoid issues if players have same name (though names are keys now) | |
categories_selected = st.multiselect("Choose Categories", all_categories_list, key=f"categories_input_{len(st.session_state.players)}") | |
avatar_file_uploaded = st.file_uploader("Upload Avatar (optional)", type=["png", "jpg", "jpeg"]) | |
submitted_registration = st.form_submit_button("Join Game") | |
if submitted_registration and player_name_input: | |
if player_name_input in st.session_state.players: | |
st.error(f"Player name '{player_name_input}' already taken!") | |
else: | |
avatar_data_bytes = avatar_file_uploaded.read() if avatar_file_uploaded else None | |
player_team_key = team_name_input if team_name_input else player_name_input # Player's own name if solo | |
st.session_state.players[player_name_input] = { | |
'categories': categories_selected, | |
'joined': datetime.now(), | |
'team': player_team_key, | |
'avatar': base64.b64encode(avatar_data_bytes).decode('utf-8') if avatar_data_bytes else None | |
} | |
st.session_state.points[player_name_input] = 0 | |
st.session_state.timeouts[player_name_input] = 0 | |
if team_name_input: # If it's a multi-player team | |
if team_name_input not in st.session_state.teams: | |
st.session_state.teams[team_name_input] = [] | |
st.session_state.team_points[team_name_input] = 0 # Initialize points for new multi-player team | |
st.session_state.teams[team_name_input].append(player_name_input) | |
st.session_state.registered = True # At least one player is now registered | |
# Update available_categories based on ALL registered players | |
all_player_categories = set() | |
for p_data in st.session_state.players.values(): | |
all_player_categories.update(p_data['categories']) | |
st.session_state.available_categories = sorted(list(all_player_categories)) # Sorted for consistent order | |
st.success(f"Welcome {player_name_input}! You've joined the game.") | |
st.rerun() # Rerun to update UI elements that depend on player list | |
st.header("๐จ Theme Selection") | |
st.session_state.theme = st.selectbox("Choose Theme", ["Light", "Dark", "Retro"], index=["Light", "Dark", "Retro"].index(st.session_state.theme), key="theme_selector") | |
apply_theme() # Apply theme immediately | |
st.header("๐ฑ Social Connect") | |
st.write("๐ [Instagram](https://instagram.com) | [Twitter](https://twitter.com)") | |
st.write("๐ง [Discord Server](https://discord.com) | ๐ง support@gamuu.com") | |
st.header("๐ก Feedback & Suggestions") | |
with st.form("feedback_form"): | |
feedback_text = st.text_area("Share your experience or suggest improvements") | |
feedback_player_name = st.selectbox("Submitting as:", get_registered_player_names(), key="feedback_player", help="Select your player name.") | |
if st.form_submit_button("Submit Feedback"): | |
if feedback_player_name and feedback_text: # Check if a player is selected and text is provided | |
st.session_state.feedback.append({'player': feedback_player_name, 'feedback': feedback_text, 'time': datetime.now()}) | |
st.session_state.points[feedback_player_name] = st.session_state.points.get(feedback_player_name, 0) + 5 | |
st.success(f"Thanks for your feedback, {feedback_player_name}! +5 points") | |
st.rerun() | |
elif not feedback_player_name: | |
st.error("Please select your player name to submit feedback.") | |
else: | |
st.error("Please write some feedback before submitting.") | |
st.header("๐ Admin Login") | |
admin_password_input = st.text_input("Admin Password", type="password", key="admin_pass") | |
if st.button("Login as Admin", key="admin_login_btn"): | |
if admin_password_input == "admin123": # Replace with a secure method (e.g., Streamlit Secrets) | |
st.session_state.admin = True | |
st.success("Admin login successful!") | |
st.rerun() | |
else: | |
st.error("Incorrect password.") | |
# --- Admin Dashboard (if logged in) --- | |
if st.session_state.admin: | |
st.sidebar.header("๐ง Admin Dashboard") | |
admin_tab1, admin_tab2 = st.sidebar.tabs(["Manage Questions", "Game Settings"]) | |
with admin_tab1: | |
st.subheader("Add New Question") | |
with st.form("add_question_form"): | |
add_q_category = st.selectbox("Category", list(st.session_state.questions.keys()), key="admin_add_cat") | |
add_q_subcategory = None | |
if isinstance(st.session_state.questions.get(add_q_category), dict): | |
add_q_subcategory = st.selectbox("Subcategory", list(st.session_state.questions[add_q_category].keys()), key="admin_add_subcat") | |
new_question_text = st.text_input("New Question", key="admin_new_q_text") | |
if st.form_submit_button("Add Question"): | |
if new_question_text: | |
if add_q_subcategory: | |
st.session_state.questions[add_q_category][add_q_subcategory].append(new_question_text) | |
elif add_q_category in st.session_state.questions and isinstance(st.session_state.questions[add_q_category], list): | |
st.session_state.questions[add_q_category].append(new_question_text) | |
else: | |
st.error(f"Cannot add question to category '{add_q_category}' structure.") # Should not happen with current setup | |
st.success("Question added successfully!") | |
else: | |
st.error("Question text cannot be empty.") | |
st.subheader("Remove Question") | |
with st.form("remove_question_form"): | |
rem_q_category = st.selectbox("Category to Remove From", list(st.session_state.questions.keys()), key="admin_rem_cat") | |
rem_q_subcategory = None | |
questions_for_removal = [] | |
if rem_q_category in st.session_state.questions: | |
if isinstance(st.session_state.questions[rem_q_category], dict): | |
rem_q_subcategory = st.selectbox("Subcategory", list(st.session_state.questions[rem_q_category].keys()), key="admin_rem_subcat") | |
if rem_q_subcategory and rem_q_subcategory in st.session_state.questions[rem_q_category]: | |
questions_for_removal = st.session_state.questions[rem_q_category][rem_q_subcategory] | |
elif isinstance(st.session_state.questions[rem_q_category], list): | |
questions_for_removal = st.session_state.questions[rem_q_category] | |
question_to_remove_text = st.selectbox("Question to Remove", questions_for_removal, key="admin_rem_q_select", disabled=not questions_for_removal) | |
if st.form_submit_button("Remove Question", disabled=not question_to_remove_text): | |
try: | |
if rem_q_subcategory: | |
st.session_state.questions[rem_q_category][rem_q_subcategory].remove(question_to_remove_text) | |
else: | |
st.session_state.questions[rem_q_category].remove(question_to_remove_text) | |
st.success("Question removed successfully!") | |
st.rerun() # To update the selectbox | |
except ValueError: | |
st.error("Question not found for removal (should not happen with selectbox).") | |
except Exception as e: | |
st.error(f"Error removing question: {e}") | |
with admin_tab2: | |
st.subheader("Game Settings") | |
penalty_threshold_input = st.number_input("Penalty Threshold (Timeouts)", min_value=1, value=st.session_state.penalty_threshold, key="admin_penalty") | |
dare_frequency_input = st.number_input("Dare Frequency (every N rounds)", min_value=1, value=st.session_state.dare_frequency, key="admin_dare_freq") | |
if st.button("Save Settings", key="admin_save_settings"): | |
st.session_state.penalty_threshold = penalty_threshold_input | |
st.session_state.dare_frequency = dare_frequency_input | |
st.success(f"Settings saved! Penalty Threshold: {penalty_threshold_input}, Dare Frequency: every {dare_frequency_input} rounds.") | |
# --- Main Game Interface --- | |
tab1, tab2, tab3, tab4 = st.tabs(["๐ฏ Game Zone", "๐ Leaderboard", "๐ Redeem Points", "๐ Achievements"]) | |
with tab1: | |
if st.session_state.registered: # Only show game zone if players are registered | |
st.header("๐ Current Round") | |
col1, col2 = st.columns([3, 2]) | |
current_registered_players = get_registered_player_names() | |
with col1: | |
if st.button("โธ๏ธ Pause Game" if not st.session_state.game_paused else "โถ๏ธ Resume Game", key="pause_resume_btn"): | |
st.session_state.game_paused = not st.session_state.game_paused | |
if st.session_state.game_paused: | |
st.warning("Game Paused!") | |
st.components.v1.html("<script>window.pauseGamuuTimer();</script>", height=0) | |
else: | |
st.success("Game Resumed!") | |
st.components.v1.html("<script>window.resumeGamuuTimer();</script>", height=0) | |
st.rerun() | |
if not st.session_state.game_paused: | |
# Round Timer (5 minutes = 300 seconds) - This is an overall round timer, not per question | |
if st.session_state.round_start_time is None: | |
st.session_state.round_start_time = time.time() | |
round_elapsed_time = int(time.time() - st.session_state.round_start_time) | |
round_time_limit = 300 # 5 minutes | |
round_time_left = round_time_limit - round_elapsed_time | |
if round_time_left <= 0: | |
st.warning("Round time limit reached! Resetting for a new round.") | |
st.session_state.current_player = None | |
st.session_state.question = None | |
st.session_state.timer_start = None # Reset question timer | |
st.session_state.round_start_time = time.time() # Reset round timer | |
st.session_state.question_count = 0 | |
st.session_state.current_category_index = 0 | |
# Potentially add more logic here like ending the game or auto-advancing | |
st.rerun() | |
else: | |
st.write(f"โณ Overall Round Time Left: {round_time_left // 60}m {round_time_left % 60}s") | |
# Category Cycling Logic | |
if st.session_state.available_categories: # Only if there are categories to cycle through | |
if st.session_state.question_count >= 9 and len(st.session_state.available_categories) > 1: | |
st.session_state.current_category_index = (st.session_state.current_category_index + 1) % len(st.session_state.available_categories) | |
st.session_state.question_count = 0 | |
st.success(f"Switching to category: {st.session_state.available_categories[st.session_state.current_category_index]}") | |
st.rerun() # Rerun to reflect new category selection | |
# Ensure current_category_index is valid | |
if st.session_state.current_category_index >= len(st.session_state.available_categories): | |
st.session_state.current_category_index = 0 | |
category_options_for_select = st.session_state.available_categories + ['Random'] | |
try: | |
default_cat_index = category_options_for_select.index(st.session_state.available_categories[st.session_state.current_category_index]) | |
except (IndexError, ValueError): # If index is bad or category not found (e.g. available_categories empty) | |
default_cat_index = len(category_options_for_select) -1 # Default to Random | |
selected_category_name = st.selectbox("Choose Question Category", | |
category_options_for_select, index=default_cat_index, key="category_select") | |
else: | |
selected_category_name = st.selectbox("Choose Question Category", ['Random'], key="category_select_norandom") # Only random if no categories | |
st.info("No specific categories selected by players. Defaulting to Random from all questions.") | |
spice_level_selection = None | |
if selected_category_name == '18+' and '18+' in st.session_state.available_categories: | |
spice_level_selection = st.select_slider("๐ถ๏ธ Spice Level", | |
options=['Spicy', 'Extra Spicy', 'Space Spicy', 'Hardcore'], key="spice_slider") | |
if st.button("๐ Spin the Bottle", use_container_width=True, key="spin_bottle_btn", disabled=len(current_registered_players) < 1): | |
if current_registered_players: # Ensure there are players | |
st.session_state.current_player = random.choice(current_registered_players) | |
st.session_state.timer_start = time.time() # Start of question timer | |
st.session_state.round += 1 | |
st.session_state.question_count += 1 | |
# Update timer key to force JS timer reset | |
st.session_state.timer_instance_key = f"timer_q_{st.session_state.round}_{st.session_state.current_player}" | |
potential_questions = [] | |
chosen_category_for_question = selected_category_name | |
# Dare logic | |
is_dare_round = (st.session_state.round % st.session_state.dare_frequency == 0 and | |
'Dare' in st.session_state.available_categories and | |
st.session_state.questions.get('Dare')) | |
if is_dare_round: | |
potential_questions = st.session_state.questions['Dare'] | |
chosen_category_for_question = "Dare" | |
else: | |
if selected_category_name == '18+' and spice_level_selection: | |
if '18+' in st.session_state.questions and \ | |
spice_level_selection in st.session_state.questions['18+']: | |
potential_questions = st.session_state.questions['18+'][spice_level_selection] | |
else: | |
st.warning(f"No questions found for 18+ {spice_level_selection}. Check admin setup.") | |
elif selected_category_name == 'Random': | |
all_q_lists = [] | |
for cat_key, cat_value in st.session_state.questions.items(): | |
if isinstance(cat_value, list) and cat_value: | |
all_q_lists.append(cat_value) | |
elif isinstance(cat_value, dict): # e.g., 18+ | |
for sub_cat_list in cat_value.values(): | |
if sub_cat_list: | |
all_q_lists.append(sub_cat_list) | |
if all_q_lists: | |
random_list_choice = random.choice(all_q_lists) | |
potential_questions = random_list_choice | |
# Finding the name of the randomly chosen category is complex, skip for now for question text | |
chosen_category_for_question = "Random Mix" | |
else: | |
st.warning("No questions available in any category for Random selection.") | |
elif selected_category_name in st.session_state.questions and st.session_state.questions[selected_category_name]: | |
potential_questions = st.session_state.questions[selected_category_name] | |
else: | |
st.warning(f"No questions found for category '{selected_category_name}'.") | |
if potential_questions: | |
st.session_state.question = random.choice(potential_questions) | |
st.success(f"๐ฏ {st.session_state.current_player}, it's your turn! ({chosen_category_for_question})") | |
else: | |
st.session_state.question = "Oops! No questions found for this selection. Admin might need to add some or check category choices." | |
st.session_state.current_player = None # Can't proceed | |
st.session_state.timer_start = None | |
st.rerun() | |
else: | |
st.error("Not enough players to spin the bottle!") | |
else: # Game Paused | |
st.info("Game is paused. Press Resume to continue.") | |
# --- Display Current Player, Question, Timer (col2) --- | |
if st.session_state.current_player and st.session_state.question and not st.session_state.game_paused: | |
with col2: | |
player_details = st.session_state.players.get(st.session_state.current_player) | |
if player_details and player_details.get('avatar'): | |
try: | |
st.image(f"data:image/png;base64,{player_details['avatar']}", width=100, caption=st.session_state.current_player) | |
except Exception as e: | |
st.caption(f"{st.session_state.current_player} (avatar error)") | |
else: | |
st.subheader(f"๐ฏ Current Player: {st.session_state.current_player}") | |
st.subheader("โ Your Question:") | |
st.markdown(f"**{st.session_state.question}**") | |
# Non-blocking Timer - Python logic for timeout is primary | |
st.components.v1.html(timer_html, height=80, key=st.session_state.timer_instance_key) # Unique key forces re-render | |
if st.session_state.timer_start and (time.time() - st.session_state.timer_start >= 30): | |
st.error("โฐ Time's up! Points deducted.") | |
st.session_state.points[st.session_state.current_player] = st.session_state.points.get(st.session_state.current_player, 0) - 10 | |
st.session_state.timeouts[st.session_state.current_player] = st.session_state.timeouts.get(st.session_state.current_player, 0) + 1 | |
st.session_state.timer_start = None # Reset timer for next turn logic | |
st.session_state.question = None # Clear question | |
# Check for penalty after timeout | |
current_player_timeouts = st.session_state.timeouts.get(st.session_state.current_player, 0) | |
if current_player_timeouts >= st.session_state.penalty_threshold: | |
st.warning(f"{st.session_state.current_player} has timed out {current_player_timeouts} times and is penalized!") | |
# Penalty logic will be handled below, rerun to show it | |
st.session_state.current_player = None # End turn | |
st.rerun() | |
# Penalty System (if current_player was set and timed out previously, or just timed out now) | |
# This needs to be accessible even if the question timed out, so check before the "Submit Answer" button | |
penalized_player = None | |
for p_name, t_outs in st.session_state.timeouts.items(): | |
if t_outs >= st.session_state.penalty_threshold: | |
penalized_player = p_name | |
break # Handle one penalty at a time for simplicity | |
if penalized_player and penalized_player == st.session_state.current_player: # Only if it's the current player's turn for this penalty UI | |
st.error(f"๐จ PENALTY! {penalized_player} has timed out too many times.") | |
eligible_saviors = [p for p in current_registered_players if p != penalized_player] | |
if eligible_saviors: | |
savior_name = st.selectbox(f"Choose a Savior for {penalized_player}", eligible_saviors, key=f"savior_{penalized_player}") | |
hardcore_questions = st.session_state.questions.get('18+', {}).get('Hardcore', []) | |
if hardcore_questions: | |
ultimate_question_text = random.choice(hardcore_questions) | |
st.write(f"๐ฆธ {savior_name}, answer this ultimate question to save {penalized_player}:") | |
st.write(f"**{ultimate_question_text}**") | |
if st.button(f"Submit Savior Answer for {penalized_player}", key=f"savior_submit_{penalized_player}"): | |
st.success(f"{savior_name} has saved {penalized_player}! Penalty reset.") | |
st.session_state.timeouts[penalized_player] = 0 | |
# Award points to savior? | |
st.session_state.points[savior_name] = st.session_state.points.get(savior_name,0) + 20 | |
st.session_state.current_player = None # End penalized player's effective turn | |
st.session_state.question = None | |
st.rerun() | |
else: | |
st.warning("No 'Hardcore' questions available for savior task. Penalty waived for now.") | |
st.session_state.timeouts[penalized_player] = 0 | |
st.rerun() | |
else: | |
st.warning(f"No saviors available for {penalized_player}. Penalty remains, but consider waiving.") | |
# Decide: st.session_state.timeouts[penalized_player] = 0 # or keep penalty | |
# Only show submit if not penalized or penalty handled | |
if st.session_state.current_player and st.session_state.question and not (penalized_player and penalized_player == st.session_state.current_player) : | |
if st.button("โ Submit Answer", key="answer_submit_btn"): | |
if st.session_state.timer_start: # Check if timer was actually running | |
time_taken = int(time.time() - st.session_state.timer_start) | |
points_earned = max(50 - time_taken, 10) # Min 10 points | |
else: # Should not happen if button is visible, but safeguard | |
points_earned = 10 | |
st.warning("Timer was not active, default points awarded.") | |
st.session_state.points[st.session_state.current_player] += points_earned | |
player_team = st.session_state.players[st.session_state.current_player]['team'] | |
# Add points to actual multi-player teams | |
if player_team in st.session_state.teams: # st.session_state.teams stores names of multi-player teams | |
st.session_state.team_points[player_team] = st.session_state.team_points.get(player_team, 0) + points_earned | |
st.success(f"๐ Answer accepted, {st.session_state.current_player}! +{points_earned} points") | |
st.session_state.current_player = None | |
st.session_state.question = None | |
st.session_state.timer_start = None | |
st.rerun() | |
# Suggest a New Question (always visible in game zone if players are registered) | |
with st.expander("๐ก Suggest a New Question"): | |
with st.form("question_suggestion_form"): | |
sugg_player_name = st.selectbox("Suggesting as:", get_registered_player_names(), key="sugg_player", help="Select your player name.") | |
sugg_new_category = st.selectbox("Category", list(st.session_state.questions.keys()), key="sugg_cat") | |
sugg_new_question = st.text_input("Your Question Suggestion", key="sugg_q_text") | |
if st.form_submit_button("Suggest Question"): | |
if sugg_player_name and sugg_new_question and sugg_new_category: | |
st.session_state.suggestions.append({'player': sugg_player_name, 'category': sugg_new_category, 'question': sugg_new_question, 'time': datetime.now()}) | |
st.session_state.points[sugg_player_name] = st.session_state.points.get(sugg_player_name, 0) + 15 | |
st.success(f"Question suggestion submitted by {sugg_player_name}! +15 points") | |
st.rerun() | |
else: | |
st.error("Please select your name, category, and write a question to suggest.") | |
else: | |
st.info("๐ Welcome to Gamuu! Please register players in the sidebar to start the game.") | |
with tab2: # Leaderboard | |
st.header("๐ Player Leaderboard") | |
if st.session_state.points: | |
sorted_players_points = sorted(st.session_state.points.items(), key=lambda x: x[1], reverse=True) | |
for i, (p_name, p_points) in enumerate(sorted_players_points): | |
player_data = st.session_state.players.get(p_name) | |
cols = st.columns([1,4]) | |
with cols[0]: | |
if player_data and player_data.get('avatar'): | |
try: | |
st.image(f"data:image/png;base64,{player_data['avatar']}", width=50) | |
except: pass # Ignore avatar display error | |
with cols[1]: | |
st.metric(f"{'๐ฅ' if i==0 else '๐ฅ' if i==1 else '๐ฅ' if i==2 else f'{i+1}.'} {p_name}", f"{p_points} points") | |
else: | |
st.info("No player points recorded yet.") | |
st.header("๐ Team Leaderboard (Multi-player Teams)") | |
if st.session_state.team_points: # Only show if there are actual multi-player teams with points | |
# Filter for actual teams, not solo players who are their own "team" unless explicitly handled | |
actual_teams_points = {team_name: pts for team_name, pts in st.session_state.team_points.items() if team_name in st.session_state.teams} | |
if actual_teams_points: | |
sorted_teams_display = sorted(actual_teams_points.items(), key=lambda x: x[1], reverse=True) | |
for i, (t_name, t_points) in enumerate(sorted_teams_display): | |
st.metric(f"{'๐ฅ' if i==0 else '๐ฅ' if i==1 else '๐ฅ' if i==2 else f'{i+1}.'} Team {t_name}", f"{t_points} points") | |
else: | |
st.info("No multi-player team points recorded yet.") | |
else: | |
st.info("No team points recorded yet.") | |
st.header("๐ Leaderboard History") | |
if st.button("Save Current Leaderboard to History", key="save_leaderboard_btn"): | |
if st.session_state.points or st.session_state.team_points: | |
history_entry = { | |
'date': datetime.now().strftime("%Y-%m-%d %H:%M:%S"), | |
'players': dict(st.session_state.points), # Save a copy | |
'teams': dict(st.session_state.team_points) # Save a copy | |
} | |
st.session_state.leaderboard_history.append(history_entry) | |
st.success("Leaderboard snapshot saved!") | |
else: | |
st.warning("Nothing to save (no points recorded).") | |
if st.session_state.leaderboard_history: | |
for entry in reversed(st.session_state.leaderboard_history): # Show newest first | |
with st.expander(f"Snapshot from: {entry['date']}"): | |
st.write("**Players:**", entry['players']) | |
st.write("**Teams:**", entry['teams']) | |
else: | |
st.info("No leaderboard history saved yet.") | |
with tab3: # Redeem Points | |
st.header("๐๏ธ Redeem Points") | |
redeeming_player = st.selectbox("Select Player for Redemption:", get_registered_player_names(), key="redeem_player_select", help="Choose who is redeeming points.") | |
if redeeming_player: | |
current_player_points = st.session_state.points.get(redeeming_player, 0) | |
st.write(f"**{redeeming_player}** has **{current_player_points}** points available.") | |
rewards = { | |
"Basic": [("Custom Emoji ๐จ", 50, "emoji_reward"), ("Nickname Color Change ๐", 75, "color_reward")], | |
"Premium": [("Special Badge โจ", 200, "badge_reward"), ("Unlock 'Dare Devil' Mode (more dares) ๐", 250, "dare_mode_reward")], | |
"Spicy": [("18+ Question Pack ๐ฅ", 300, "spicy_pack_reward"), ("'Ultimate Truth' Question for someone else ๐ฃ", 400, "ultimate_truth_reward")] | |
} | |
cols = st.columns(len(rewards)) | |
for i, (tier_name, tier_rewards) in enumerate(rewards.items()): | |
with cols[i]: | |
st.subheader(f"๐ {tier_name} Rewards") | |
for reward_name, cost, reward_key_suffix in tier_rewards: | |
if st.button(f"{reward_name} ({cost} points)", key=f"redeem_{reward_key_suffix}_{redeeming_player}", disabled=current_player_points < cost): | |
if current_player_points >= cost: | |
st.session_state.points[redeeming_player] -= cost | |
# Add achievement logic or actual reward effect here | |
if redeeming_player not in st.session_state.achievements: | |
st.session_state.achievements[redeeming_player] = [] | |
achievement_text = f"Redeemed '{reward_name}'" | |
if achievement_text not in st.session_state.achievements[redeeming_player]: | |
st.session_state.achievements[redeeming_player].append(achievement_text) | |
st.success(f"๐ {reward_name} redeemed by {redeeming_player}!") | |
st.rerun() # Update points display and button states | |
# else: # Button should be disabled, but as a fallback | |
# st.error("Not enough points! (Button should have been disabled)") | |
else: | |
st.info("Please register players and select a player to see redeemable rewards.") | |
with tab4: # Achievements | |
st.header("๐ Achievements") | |
achievements_player = st.selectbox("View Achievements For:", get_registered_player_names(), key="achievements_player_select", help="Select player to view their achievements.") | |
if achievements_player: | |
st.write(f"๐ **{achievements_player}'s Achievements:**") | |
player_achievements = st.session_state.achievements.get(achievements_player, []) | |
if player_achievements: | |
for ach in player_achievements: | |
st.markdown(f"- {ach}") | |
else: | |
st.write("No achievements unlocked yet. Keep playing to earn them!") | |
else: | |
st.info("Please register players and select a player to view achievements.") | |
# --- Footer --- | |
st.markdown("---") | |
st.markdown("Made with โค๏ธ for **Gamuu** - v3.1 โ [Privacy Policy] โ [Terms of Service]") | |
st.caption("Note: 'Ultimate Truth' and 'Dare Devil Mode' are conceptual and not fully implemented in game logic yet.") |