|
""" |
|
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 |
|
|
|
|
|
config_file_path = "config/lang.json" |
|
logo_path = "config/images/logo.png" |
|
logo_win_path = "config/images/logo_win.gif" |
|
|
|
|
|
with open(config_file_path, "r") as file: |
|
Config_full = json.load(file) |
|
|
|
lang_conf = 0 |
|
|
|
|
|
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"] |
|
|
|
|
|
|
|
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: |
|
|
|
state = gr.State(-1) |
|
difficulty = gr.State(-1) |
|
hint = gr.State(False) |
|
|
|
|
|
game = Semantrix(lang=0, model_type="SentenceTransformer") |
|
|
|
|
|
header = gr.Markdown( |
|
""" |
|
<p style="text-align:center"> """ |
|
+ Menu["Header"] |
|
+ """ </p> |
|
""" |
|
) |
|
|
|
|
|
def reset(difficulty, lang, model): |
|
global Config, game, Menu |
|
|
|
|
|
language = 1 if lang == "English" else 0 |
|
|
|
|
|
if model == "Word2Vec": |
|
game = Semantrix(language, "word2vec") |
|
else: |
|
game = Semantrix( |
|
language, "SentenceTransformer" |
|
) |
|
|
|
|
|
if language == 1: |
|
Config = Config_full["ENG"]["Game"] |
|
Menu = Config_full["ENG"]["Menu"] |
|
else: |
|
Config = Config_full["SPA"]["Game"] |
|
Menu = Config_full["SPA"]["Menu"] |
|
|
|
|
|
game.prepare_game(difficulty) |
|
|
|
|
|
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 output |
|
|
|
|
|
def change(state, inp): |
|
|
|
state = state + 1 |
|
|
|
|
|
return [state, inp] |
|
|
|
|
|
def update(state, radio, inp, hint): |
|
global difficulty |
|
|
|
|
|
dif_state = 4 |
|
|
|
|
|
output = [state] |
|
|
|
state_int = 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), |
|
] |
|
) |
|
|
|
|
|
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), |
|
] |
|
) |
|
|
|
|
|
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), |
|
] |
|
) |
|
|
|
|
|
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), |
|
] |
|
) |
|
|
|
|
|
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), |
|
] |
|
) |
|
|
|
|
|
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), |
|
] |
|
) |
|
|
|
|
|
elif state_int > dif_state + 2: |
|
|
|
|
|
feed = game.play_game(inp) |
|
|
|
|
|
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 = "" |
|
|
|
|
|
feedback = feedback_trim[0].split("[hint]") |
|
win = feedback_trim[0].split("[win]") |
|
lose = feedback_trim[0].split("[lose]") |
|
|
|
|
|
if len(feedback) > 1: |
|
hint = True |
|
hint_out = feedback[1] |
|
feedback = feedback[0] |
|
else: |
|
hint = False |
|
feedback = feedback[0] |
|
|
|
|
|
if len(win) > 1 or len(lose) > 1: |
|
|
|
|
|
won = True if len(win) > 1 else False |
|
|
|
|
|
curiosity = game.curiosity() |
|
|
|
|
|
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(visible=True), |
|
gr.Markdown(visible=False), |
|
] |
|
) |
|
|
|
return output |
|
|
|
|
|
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), |
|
] |
|
) |
|
|
|
|
|
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 output |
|
|
|
|
|
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) |
|
|
|
|
|
with gr.Accordion("Configuración/Settings", open=False): |
|
with gr.Row(): |
|
|
|
|
|
model = ( |
|
gr.Dropdown( |
|
["Sentence Transformers", "Word2Vec"], |
|
value="Sentence Transformers", |
|
label="Embedding Model", |
|
), |
|
) |
|
|
|
|
|
lang = ( |
|
gr.Dropdown( |
|
["Español", "English"], value="Español", label="Idioma/Language" |
|
), |
|
) |
|
|
|
|
|
|
|
|
|
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]) |
|
|
|
|
|
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], |
|
) |
|
|
|
|
|
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() |
|
|