Gamuu / app.py
Iammcqwory's picture
Update app.py
25aa262 verified
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.")