# """ # 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 = '
\n\n' markdown += "## " + Menu["Best_tries"] + "\n" markdown += "\n" markdown += " \n" markdown += " \n" markdown += " \n" markdown += " \n" markdown += " \n" for line in history_attempts: items = eval(line.strip()) markdown += " \n" markdown += f" \n" markdown += f" \n" markdown += f" \n" markdown += " \n" markdown += "
" + Menu["N_try"] + "" + Menu["Word"] + "" + Menu["Score"] + "
{items[0]}{items[1]}{items[2]}
\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 += "
" 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( """

""" + Menu["Header"] + """

""" ) # 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( """

""" + Menu["Header"] + """

""" ), ] # 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()