Spaces:
Sleeping
Sleeping
# """ | |
# This module defines a Gradio-based web application for the Semantrix game. The application allows users to play the game in either Spanish or English, using different embedding models for word similarity. | |
# Modules: | |
# gradio: Used for creating the web interface. | |
# json: Used for loading configuration files. | |
# game: Contains the Semantrix class for game logic. | |
# File Paths: | |
# config_file_path: Path to the configuration file. | |
# logo_path: Path to the logo image. | |
# logo_win_path: Path to the winning logo image. | |
# Functions: | |
# convert_to_markdown_centered(text): | |
# Converts text to a centered markdown format for displaying game history and last attempt. | |
# reset(difficulty, lang, model): | |
# Resets the game state based on the selected difficulty, language, and model. | |
# change(state, inp): | |
# Changes the game state by incrementing the state variable. | |
# update(state, radio, inp, hint): | |
# Updates the game state and UI components based on the current state and user inputs. | |
# Gradio Components: | |
# demo: The main Gradio Blocks component that contains the entire UI layout. | |
# header: A Markdown component for displaying the game header. | |
# state: A State component for tracking the current game state. | |
# difficulty: A State component for tracking the difficulty level. | |
# hint: A State component for tracking if a hint is provided. | |
# img: An Image component for displaying the game logo. | |
# ranking: A Markdown component for displaying the ranking. | |
# out: A Textbox component for displaying game messages. | |
# hint_out: A Textbox component for displaying hints. | |
# radio: A Radio component for user selections. | |
# inp: A Textbox component for user input. | |
# but: A Button component for several actions. | |
# give_up: A Button component for giving up. | |
# reload: A Button component for reloading the game. | |
# model: A Dropdown component for selecting the embedding model. | |
# lang: A Dropdown component for selecting the language. | |
# Events: | |
# inp.submit: Triggers the change function on input submission. | |
# but.click: Triggers the change function on button click. | |
# give_up.click: Triggers the change function on give up button click. | |
# radio.input: Triggers the change function on radio input. | |
# reload.click: Triggers the reset function on reload button click. | |
# demo.load: Triggers the reset function on demo load. | |
# lang[0].select: Triggers the reset function on language selection. | |
# model[0].select: Triggers the reset function on model selection. | |
# state.change: Triggers the update function on state change. | |
# Main: | |
# Launches the Gradio application if the script is run as the main module. | |
# """ | |
import gradio as gr | |
import json | |
from game import Semantrix | |
# File paths for configuration and images | |
config_file_path = "config/lang.json" | |
logo_path = "config/images/logo.png" | |
logo_win_path = "config/images/logo_win.gif" | |
# Loading the configuration file | |
with open(config_file_path, "r") as file: | |
Config_full = json.load(file) | |
lang_conf = 0 # Language configuration flag (0 for Spanish, 1 for English) | |
# Setting the configuration based on the language flag | |
if lang_conf == 1: | |
Config = Config_full["ENG"]["Game"] | |
Menu = Config_full["ENG"]["Menu"] | |
else: | |
Config = Config_full["SPA"]["Game"] | |
Menu = Config_full["SPA"]["Menu"] | |
# Function to convert text to centered markdown format | |
def convert_to_markdown_centered(text): | |
lines = text.strip().split("\n") | |
if not lines: | |
return "" | |
last_attempt = lines[0] | |
history_attempts = lines[2:12] | |
markdown = '<div align="center">\n\n' | |
markdown += "## " + Menu["Best_tries"] + "\n" | |
markdown += "<table>\n" | |
markdown += " <tr>\n" | |
markdown += " <th>" + Menu["N_try"] + "</th>\n" | |
markdown += " <th>" + Menu["Word"] + "</th>\n" | |
markdown += " <th>" + Menu["Score"] + "</th>\n" | |
markdown += " </tr>\n" | |
for line in history_attempts: | |
items = eval(line.strip()) | |
markdown += " <tr>\n" | |
markdown += f" <td><strong>{items[0]}</strong></td>\n" | |
markdown += f" <td>{items[1]}</td>\n" | |
markdown += f" <td>{items[2]}</td>\n" | |
markdown += " </tr>\n" | |
markdown += "</table>\n\n" | |
last_items = eval(last_attempt) | |
markdown += f"## " + Menu["Last_try"] + "\n" | |
markdown += ( | |
f"**{last_items[0]}:** {last_items[1]} - " | |
+ Menu["Score"] | |
+ f": {last_items[2]}\n\n" | |
) | |
markdown += "---\n\n" | |
markdown += "</div>" | |
return markdown | |
# | |
with gr.Blocks() as demo: | |
# Initializing state variables to manage the internal state of the application | |
state = gr.State(-1) # State variable to track the current game state | |
difficulty = gr.State(-1) # State variable to track the difficulty level | |
hint = gr.State(False) # State variable to track if the hint is provided | |
# Initializing the game using the Semantrix class with default parameters | |
game = Semantrix(lang=0, model_type="SentenceTransformer") | |
# Creating a Markdown component to display the header | |
header = gr.Markdown( | |
""" | |
<p style="text-align:center"> """ | |
+ Menu["Header"] | |
+ """ </p> | |
""" | |
) | |
# Function to reset the game | |
def reset(difficulty, lang, model): | |
global Config, game, Menu # Declare global variables to modify them within the function | |
# Determine the language based on the input parameter | |
language = 1 if lang == "English" else 0 | |
# Initialize the game object based on the selected model | |
if model == "Word2Vec": | |
game = Semantrix(language, "word2vec") # Use Word2Vec model | |
else: | |
game = Semantrix( | |
language, "SentenceTransformer" | |
) # Use Sentence Transformers model | |
# Set the configuration and menu based on the selected language | |
if language == 1: | |
Config = Config_full["ENG"]["Game"] | |
Menu = Config_full["ENG"]["Menu"] | |
else: | |
Config = Config_full["SPA"]["Game"] | |
Menu = Config_full["SPA"]["Menu"] | |
# Prepare the game with the selected difficulty level | |
game.prepare_game(difficulty) | |
# Define the initial output components for the UI | |
output = [ | |
-1, | |
gr.Textbox(visible=False), | |
gr.Textbox(visible=False), | |
gr.Image(logo_path, visible=True, interactive=False), | |
gr.Button(Menu["Start"], visible=True, variant="secondary"), | |
gr.Radio(visible=False), | |
gr.Textbox(visible=False), | |
gr.Button(visible=False), | |
gr.Markdown( | |
""" | |
<p style="text-align:center"> """ | |
+ Menu["Header"] | |
+ """ </p> | |
""" | |
), | |
] | |
# Return the initial output components | |
return output | |
# Function to change the state of the game | |
def change(state, inp): | |
# Increment the state by 1 | |
state = state + 1 | |
# Return the updated state and input component | |
return [state, inp] | |
# Function to update the game state based on the current state of the game | |
def update(state, radio, inp, hint): | |
global difficulty | |
# Define the difficulty state | |
dif_state = 4 | |
# Initialize the output component list with the current state | |
output = [state] | |
state_int = state | |
# Define UI components for the initial state | |
if state_int == -1: | |
output.extend( | |
[ | |
gr.Button(Menu["Start"], visible=True), | |
gr.Radio(label="", visible=False), | |
gr.Textbox( | |
Config[list(Config.keys())[state_int]], visible=False, label="" | |
), | |
gr.Button(Menu["Give_up"], visible=False), | |
gr.Textbox(visible=False), | |
gr.Image(interactive=False, visible=True), | |
gr.Textbox(visible=False), | |
gr.Button(visible=False), | |
gr.Markdown(visible=False), | |
] | |
) | |
# Define UI components for the first state, ask the user if they want to know the rules | |
elif state_int == 1: | |
output.extend( | |
[ | |
gr.Button(visible=False), | |
gr.Radio([Menu["Yes"], Menu["No"]], label="", visible=True), | |
gr.Textbox( | |
Config[list(Config.keys())[state_int]], visible=True, label="" | |
), | |
gr.Button(Menu["Give_up"], visible=False), | |
gr.Textbox(visible=False), | |
gr.Image(interactive=False, visible=False), | |
gr.Textbox(visible=False), | |
gr.Button(visible=False), | |
gr.Markdown(visible=False), | |
] | |
) | |
# Define UI components for the second state, Depending on the answer, show the rules or keep going | |
elif state_int == 2: | |
if radio == Menu["No"]: | |
output = [ | |
dif_state, | |
gr.Button("Introducir", visible=True), | |
gr.Radio(visible=False), | |
gr.Textbox( | |
Config[list(Config.keys())[state_int]], visible=True, label="" | |
), | |
gr.Button(Menu["Give_up"], visible=False), | |
gr.Textbox(visible=False), | |
gr.Image(interactive=False, visible=False), | |
gr.Textbox(visible=False), | |
gr.Button(visible=False), | |
gr.Markdown(visible=False), | |
] | |
else: | |
output.extend( | |
[ | |
gr.Button(Menu["Next"], visible=True), | |
gr.Radio(visible=False), | |
gr.Textbox( | |
Config[list(Config.keys())[state_int]], | |
visible=True, | |
label="", | |
), | |
gr.Button(Menu["Give_up"], visible=False), | |
gr.Textbox(visible=False), | |
gr.Image(interactive=False, visible=False), | |
gr.Textbox(visible=False), | |
gr.Button(visible=False), | |
gr.Markdown(visible=False), | |
] | |
) | |
# Define UI components for the difficulty state, ask the user to select the difficulty level | |
elif state_int == dif_state: | |
output.extend( | |
[ | |
gr.Button(Menu["Next"], visible=False), | |
gr.Radio( | |
[Menu["Easy"], Menu["Normal"], Menu["Hard"], Menu["Expert"]], | |
visible=True, | |
), | |
gr.Textbox( | |
Config[list(Config.keys())[state_int]], visible=True, label="" | |
), | |
gr.Button(Menu["Give_up"], visible=False), | |
gr.Textbox(visible=False), | |
gr.Image(interactive=False, visible=False), | |
gr.Textbox(visible=False), | |
gr.Button(visible=False), | |
gr.Markdown(visible=False), | |
] | |
) | |
# Define UI components for the difficulty state + 1, prepare the game based on the selected difficulty level, and start the game | |
elif state_int == dif_state + 1: | |
if radio == Menu["Easy"]: | |
difficulty = 1 | |
elif radio == Menu["Normal"]: | |
difficulty = 2 | |
elif radio == Menu["Hard"]: | |
difficulty = 3 | |
else: | |
difficulty = 4 | |
output.extend( | |
[ | |
gr.Button(Menu["Start"], visible=True, variant="primary"), | |
gr.Radio(visible=False), | |
gr.Textbox( | |
Config[list(Config.keys())[state_int]], visible=True, label="" | |
), | |
gr.Button(Menu["Give_up"], visible=False), | |
gr.Textbox(visible=False), | |
gr.Image(interactive=False, visible=False), | |
gr.Textbox(visible=False), | |
gr.Button(visible=False), | |
gr.Markdown(visible=False), | |
] | |
) | |
# Define UI components for the difficulty state + 2, play the game based on the selected difficulty level and prepare the game for the word guessing | |
elif state_int == dif_state + 2: | |
game.prepare_game(difficulty) | |
output.extend( | |
[ | |
gr.Button(Menu["Send"], visible=True, variant="primary"), | |
gr.Radio(label="", visible=False), | |
gr.Textbox(visible=False, label=""), | |
gr.Button(visible=True, variant="stop"), | |
gr.Textbox( | |
value="", | |
visible=True, | |
autofocus=True, | |
placeholder=Menu["New_word"], | |
), | |
gr.Image(interactive=False, visible=False), | |
gr.Textbox(visible=False), | |
gr.Button(visible=False), | |
gr.Markdown(visible=False), | |
] | |
) | |
# Define UI components for the state greater than the difficulty state + 2, play the game and provide feedback based on the user input | |
elif state_int > dif_state + 2: | |
# Send the user input to the game and get the feedback from the game | |
feed = game.play_game(inp) | |
# Check if the feedback contains the ranking information and process it | |
feedback_trim = feed.split("[rank]") | |
if len(feedback_trim) > 1: | |
ranking_vis = True | |
ranking_md = convert_to_markdown_centered(feedback_trim[1]) | |
else: | |
ranking_vis = False | |
ranking_md = "" | |
# Check if the feedback contains a hint, win, or lose message | |
feedback = feedback_trim[0].split("[hint]") | |
win = feedback_trim[0].split("[win]") | |
lose = feedback_trim[0].split("[lose]") | |
# Check if the feedback contains a hint message | |
if len(feedback) > 1: | |
hint = True | |
hint_out = feedback[1] | |
feedback = feedback[0] | |
else: | |
hint = False | |
feedback = feedback[0] | |
# Check if the feedback contains a win or lose message and process it | |
if len(win) > 1 or len(lose) > 1: | |
# Check if the user won the game | |
won = True if len(win) > 1 else False | |
# Get the curiosity message from the game | |
curiosity = game.curiosity() | |
# Define the output components for the win or lose state | |
output.extend( | |
[ | |
gr.Button(Menu["Send"], visible=False, variant="primary"), | |
gr.Radio(label="", visible=False), | |
gr.Textbox(win[1] if won else lose[1], visible=True, label=""), | |
gr.Button(visible=False, variant="stop"), | |
gr.Textbox( | |
value="", visible=False, placeholder=Menu["New_word"] | |
), | |
gr.Image( | |
logo_win_path if won else logo_path, | |
interactive=False, | |
visible=True, | |
), | |
gr.Textbox(curiosity, visible=True, label=Menu["Curiosity"]), | |
gr.Button(Menu["Play_again"], visible=True), | |
gr.Markdown(visible=False), | |
] | |
) | |
return output | |
# Define the output components for the feedback and keep playing | |
output.extend( | |
[ | |
gr.Button(Menu["Send"], visible=True, variant="primary"), | |
gr.Radio(label="", visible=False), | |
gr.Textbox(feedback, visible=True, label=""), | |
gr.Button(visible=True, variant="stop"), | |
gr.Textbox(value="", visible=True, placeholder=Menu["New_word"]), | |
gr.Image(logo_path, interactive=False, visible=False), | |
gr.Textbox(hint_out if hint else "", visible=hint, label="Pista"), | |
gr.Button(visible=False), | |
gr.Markdown(ranking_md, visible=ranking_vis), | |
] | |
) | |
# Define UI components for the rest of the states, state for showing basic text to the user | |
else: | |
output.extend( | |
[ | |
gr.Button(Menu["Next"], visible=True), | |
gr.Radio(label="", visible=False), | |
gr.Textbox( | |
Config[list(Config.keys())[state_int]], visible=True, label="" | |
), | |
gr.Button("Pista", visible=False), | |
gr.Textbox(visible=False), | |
gr.Image(interactive=False, visible=False), | |
gr.Textbox(visible=False), | |
gr.Button(visible=False), | |
gr.Markdown(visible=False), | |
] | |
) | |
# Return the output components | |
return output | |
# Define the UI layout for the gam | |
img = gr.Image(logo_path, height=430, interactive=False, visible=True) | |
ranking = gr.Markdown(visible=False) | |
with gr.Row(): | |
out = gr.Textbox(visible=False, placeholder=Config[list(Config.keys())[0]]) | |
hint_out = gr.Textbox(visible=False) | |
radio = gr.Radio(visible=False) | |
with gr.Row(): | |
inp = gr.Textbox(visible=False, interactive=True, label="") | |
but = gr.Button(Menu["Start"]) | |
give_up = gr.Button("Pista", visible=False) | |
reload = gr.Button(Menu["Play_again"], visible=False) | |
# Define the settings components for the game | |
with gr.Accordion("Configuración/Settings", open=False): | |
with gr.Row(): | |
# Dropdown to select the model engine for the game | |
model = ( | |
gr.Dropdown( | |
["Sentence Transformers", "Word2Vec"], | |
value="Sentence Transformers", | |
label="Embedding Model", | |
), | |
) | |
# Dropdown to select the language for the game | |
lang = ( | |
gr.Dropdown( | |
["Español", "English"], value="Español", label="Idioma/Language" | |
), | |
) | |
# Define the UI events for the game | |
# Define events that trigger the game state change | |
inp.submit(change, inputs=[state, inp], outputs=[state, inp]) | |
but.click(change, inputs=[state, inp], outputs=[state, inp]) | |
give_up.click( | |
change, | |
inputs=[ | |
state, | |
gr.Textbox("give_up", visible=False, interactive=True, label=""), | |
], | |
outputs=[state, inp], | |
) | |
radio.input(change, inputs=[state, inp], outputs=[state, inp]) | |
# Define events that trigger the game reset | |
reload.click( | |
reset, | |
inputs=[difficulty, lang[0], model[0]], | |
outputs=[state, out, inp, img, but, radio, hint_out, reload, header], | |
) | |
demo.load( | |
reset, | |
inputs=[difficulty, lang[0], model[0]], | |
outputs=[state, out, inp, img, but, radio, hint_out, reload, header], | |
) | |
lang[0].select( | |
reset, | |
inputs=[difficulty, lang[0], model[0]], | |
outputs=[state, out, inp, img, but, radio, hint_out, reload, header], | |
) | |
model[0].select( | |
reset, | |
inputs=[difficulty, lang[0], model[0]], | |
outputs=[state, out, inp, img, but, radio, hint_out, reload, header], | |
) | |
# Define events that trigger the game state update | |
state.change( | |
update, | |
inputs=[state, radio, inp, hint], | |
outputs=[state, but, radio, out, give_up, inp, img, hint_out, reload, ranking], | |
) | |
if __name__ == "__main__": | |
demo.launch() | |