Javierss commited on
Commit
7c2eafe
·
1 Parent(s): e70a337

Add comments to code,Update README.md, Sintezise game.py modules

Browse files
README.md CHANGED
@@ -10,4 +10,105 @@ pinned: false
10
  license: other
11
  ---
12
 
13
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  license: other
11
  ---
12
 
13
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
14
+ # Semantrix Game
15
+
16
+ This repository contains the implementation of the Semantrix game, a word guessing game using word embeddings. The game supports multiple languages (Spanish and English) and can be configured to use either a Word2Vec model or a SentenceTransformer model for word embeddings.
17
+
18
+ ## Modules
19
+
20
+
21
+
22
+ ### app.py
23
+
24
+ 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.
25
+
26
+ #### Functions
27
+
28
+ - `convert_to_markdown_centered(text)`: Converts text to a centered markdown format for displaying game history and last attempt.
29
+ - **Parameters**:
30
+ - `text (str)`: The text to be converted.
31
+ - **Returns**: `str`: The centered markdown formatted text.
32
+
33
+ - `reset(difficulty, lang, model)`: Resets the game state based on the selected difficulty, language, and model.
34
+ - **Parameters**:
35
+ - `difficulty`: The selected difficulty level.
36
+ - `lang`: The selected language.
37
+ - `model`: The selected embedding model.
38
+ - **Returns**: `list`: A list of initial output components for the UI.
39
+
40
+ - `change(state, inp)`: Changes the game state by incrementing the state variable.
41
+ - **Parameters**:
42
+ - `state`: The current game state.
43
+ - `inp`: The user input.
44
+ - **Returns**: `list`: A list containing the updated state and input component.
45
+
46
+ - `update(state, radio, inp, hint)`: Updates the game state and UI components based on the current state and user inputs.
47
+ - **Parameters**:
48
+ - `state`: The current game state.
49
+ - `radio`: The radio input component.
50
+ - `inp`: The user input.
51
+ - `hint`: The hint state.
52
+ - **Returns**: `list`: A list of updated output components for the UI.
53
+
54
+ ### game.py
55
+
56
+ This module defines the Semantrix class, which implements a word guessing game using word embeddings. The game can be configured to use either a Word2Vec model or a SentenceTransformer model for word embeddings. The game supports multiple languages and difficulty levels.
57
+
58
+ #### Classes
59
+
60
+ - `Semantrix`: A class that implements the Semantrix word guessing game.
61
+ - **Methods**:
62
+ - `__init__(self, lang=0, model_type="SentenceTransformer")`: Initializes the Semantrix game with the specified language and model type.
63
+ - `prepare_game(self, difficulty)`: Prepares the game with the selected difficulty level.
64
+ - `gen_rank(self, repeated)`: Generates the ranking file based on the scores.
65
+ - `play_game(self, word)`: Plays the game with the selected word and returns feedback.
66
+ - `curiosity(self)`: Generates a curiosity hint about the secret word once the game is over.
67
+
68
+ ### hints.py
69
+
70
+ This module provides functions to generate dynamic hints and curiosities about a secret word using language models (LLMs).
71
+
72
+ #### Functions
73
+
74
+ - `hint(secret, n, model, last_hint, lang, Config)`: Generates a dynamic hint based on the secret word and the number of hints given.
75
+ - **Parameters**:
76
+ - `secret (str)`: The secret word.
77
+ - `n (int)`: The number of hints already given.
78
+ - `model`: The sentence transformer model used for encoding.
79
+ - `last_hint (int)`: The index of the last hint given.
80
+ - `lang (int)`: The language code (0 for Spanish, 1 for English).
81
+ - `Config`: Configuration object containing hint templates.
82
+ - **Returns**: `tuple`: A tuple containing the generated hint (str), the updated number of hints (int), and the index of the last hint given (int).
83
+
84
+ - `curiosity(secret, Config)`: Generates a curiosity about the secret word.
85
+ - **Parameters**:
86
+ - `secret (str)`: The secret word.
87
+ - `Config`: Configuration object containing the curiosity template.
88
+ - **Returns**: `str`: The generated curiosity.
89
+
90
+ - `ireplace(old, new, text)`: Replaces all occurrences of a substring in a string, case-insensitively.
91
+ - **Parameters**:
92
+ - `old (str)`: The substring to be replaced.
93
+ - `new (str)`: The substring to replace with.
94
+ - `text (str)`: The original string.
95
+ - **Returns**: `str`: The modified string with all occurrences of the old substring replaced by the new substring.
96
+
97
+
98
+ ## How to Run
99
+
100
+ 1. Clone the repository.
101
+ 2. Install the required dependencies.
102
+ 3. Run the `app.py` script to launch the Gradio web application.
103
+
104
+ ## Dependencies
105
+
106
+ - Gradio
107
+ - OpenAI
108
+ - SentenceTransformers
109
+ - Gensim
110
+ - NumPy
111
+
112
+ ## License
113
+
114
+ This project is licensed under the MIT License.
__pycache__/app.cpython-311.pyc CHANGED
Binary files a/__pycache__/app.cpython-311.pyc and b/__pycache__/app.cpython-311.pyc differ
 
__pycache__/game.cpython-311.pyc CHANGED
Binary files a/__pycache__/game.cpython-311.pyc and b/__pycache__/game.cpython-311.pyc differ
 
__pycache__/game_transformer.cpython-311.pyc CHANGED
Binary files a/__pycache__/game_transformer.cpython-311.pyc and b/__pycache__/game_transformer.cpython-311.pyc differ
 
__pycache__/hints.cpython-311.pyc CHANGED
Binary files a/__pycache__/hints.cpython-311.pyc and b/__pycache__/hints.cpython-311.pyc differ
 
app.py CHANGED
@@ -1,19 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import gradio as gr
2
  import json
3
- from game_word2vec import Semantrix as semantrix_word2vec
4
- from game_transformer import Semantrix as semantrix_sentence_transformers
5
-
6
 
 
7
  config_file_path = "config/lang.json"
8
  logo_path = "config/images/logo.png"
9
  logo_win_path = "config/images/logo_win.gif"
10
 
 
11
  with open(config_file_path, "r") as file:
12
  Config_full = json.load(file)
13
 
14
- lang_conf = 0
15
-
16
 
 
17
  if lang_conf == 1:
18
  Config = Config_full["ENG"]["Game"]
19
  Menu = Config_full["ENG"]["Menu"]
@@ -22,6 +81,7 @@ else:
22
  Menu = Config_full["SPA"]["Menu"]
23
 
24
 
 
25
  def convert_to_markdown_centered(text):
26
  lines = text.strip().split("\n")
27
 
@@ -64,13 +124,17 @@ def convert_to_markdown_centered(text):
64
  return markdown
65
 
66
 
 
67
  with gr.Blocks() as demo:
68
- state = gr.State(-1)
69
- difficulty = gr.State(-1)
70
- hint = gr.State(False)
 
71
 
72
- game = semantrix_sentence_transformers()
 
73
 
 
74
  header = gr.Markdown(
75
  """
76
  <p style="text-align:center"> """
@@ -79,15 +143,22 @@ with gr.Blocks() as demo:
79
  """
80
  )
81
 
 
82
  def reset(difficulty, lang, model):
83
- global Config, game, Menu
 
 
84
  language = 1 if lang == "English" else 0
85
 
 
86
  if model == "Word2Vec":
87
- game = semantrix_word2vec(language)
88
  else:
89
- game = semantrix_sentence_transformers(language)
 
 
90
 
 
91
  if language == 1:
92
  Config = Config_full["ENG"]["Game"]
93
  Menu = Config_full["ENG"]["Menu"]
@@ -95,7 +166,10 @@ with gr.Blocks() as demo:
95
  Config = Config_full["SPA"]["Game"]
96
  Menu = Config_full["SPA"]["Menu"]
97
 
 
98
  game.prepare_game(difficulty)
 
 
99
  output = [
100
  -1,
101
  gr.Textbox(visible=False),
@@ -114,20 +188,30 @@ with gr.Blocks() as demo:
114
  ),
115
  ]
116
 
 
117
  return output
118
 
 
119
  def change(state, inp):
120
-
121
  state = state + 1
 
 
122
  return [state, inp]
123
 
 
124
  def update(state, radio, inp, hint):
125
  global difficulty
 
 
126
  dif_state = 4
 
 
127
  output = [state]
128
 
129
  state_int = state
130
 
 
131
  if state_int == -1:
132
  output.extend(
133
  [
@@ -145,6 +229,7 @@ with gr.Blocks() as demo:
145
  ]
146
  )
147
 
 
148
  elif state_int == 1:
149
  output.extend(
150
  [
@@ -161,6 +246,8 @@ with gr.Blocks() as demo:
161
  gr.Markdown(visible=False),
162
  ]
163
  )
 
 
164
  elif state_int == 2:
165
  if radio == Menu["No"]:
166
  output = [
@@ -196,6 +283,8 @@ with gr.Blocks() as demo:
196
  gr.Markdown(visible=False),
197
  ]
198
  )
 
 
199
  elif state_int == dif_state:
200
  output.extend(
201
  [
@@ -215,6 +304,8 @@ with gr.Blocks() as demo:
215
  gr.Markdown(visible=False),
216
  ]
217
  )
 
 
218
  elif state_int == dif_state + 1:
219
  if radio == Menu["Easy"]:
220
  difficulty = 1
@@ -241,6 +332,7 @@ with gr.Blocks() as demo:
241
  ]
242
  )
243
 
 
244
  elif state_int == dif_state + 2:
245
 
246
  game.prepare_game(difficulty)
@@ -263,8 +355,14 @@ with gr.Blocks() as demo:
263
  gr.Markdown(visible=False),
264
  ]
265
  )
 
 
266
  elif state_int > dif_state + 2:
 
 
267
  feed = game.play_game(inp)
 
 
268
  feedback_trim = feed.split("[rank]")
269
  if len(feedback_trim) > 1:
270
  ranking_vis = True
@@ -274,17 +372,30 @@ with gr.Blocks() as demo:
274
  ranking_vis = False
275
  ranking_md = ""
276
 
 
277
  feedback = feedback_trim[0].split("[hint]")
278
  win = feedback_trim[0].split("[win]")
279
  lose = feedback_trim[0].split("[lose]")
 
 
280
  if len(feedback) > 1:
281
  hint = True
 
 
282
  else:
283
  hint = False
 
284
 
 
285
  if len(win) > 1 or len(lose) > 1:
 
 
286
  won = True if len(win) > 1 else False
 
 
287
  curiosity = game.curiosity()
 
 
288
  output.extend(
289
  [
290
  gr.Button(Menu["Send"], visible=False, variant="primary"),
@@ -304,24 +415,25 @@ with gr.Blocks() as demo:
304
  gr.Markdown(visible=False),
305
  ]
306
  )
 
307
  return output
308
 
 
309
  output.extend(
310
  [
311
  gr.Button(Menu["Send"], visible=True, variant="primary"),
312
  gr.Radio(label="", visible=False),
313
- gr.Textbox(feedback[0], visible=True, label=""),
314
  gr.Button(visible=True, variant="stop"),
315
  gr.Textbox(value="", visible=True, placeholder=Menu["New_word"]),
316
  gr.Image(logo_path, interactive=False, visible=False),
317
- gr.Textbox(
318
- feedback[1] if hint else "", visible=hint, label="Pista"
319
- ),
320
  gr.Button(visible=False),
321
  gr.Markdown(ranking_md, visible=ranking_vis),
322
  ]
323
  )
324
 
 
325
  else:
326
  output.extend(
327
  [
@@ -338,23 +450,31 @@ with gr.Blocks() as demo:
338
  gr.Markdown(visible=False),
339
  ]
340
  )
 
 
341
  return output
342
 
 
343
  img = gr.Image(logo_path, height=430, interactive=False, visible=True)
344
  ranking = gr.Markdown(visible=False)
345
 
346
  with gr.Row():
347
  out = gr.Textbox(visible=False, placeholder=Config[list(Config.keys())[0]])
348
  hint_out = gr.Textbox(visible=False)
 
349
  radio = gr.Radio(visible=False)
 
350
  with gr.Row():
351
  inp = gr.Textbox(visible=False, interactive=True, label="")
352
  but = gr.Button(Menu["Start"])
353
  give_up = gr.Button("Pista", visible=False)
354
  reload = gr.Button(Menu["Play_again"], visible=False)
355
 
 
356
  with gr.Accordion("Configuración/Settings", open=False):
357
  with gr.Row():
 
 
358
  model = (
359
  gr.Dropdown(
360
  ["Sentence Transformers", "Word2Vec"],
@@ -362,12 +482,17 @@ with gr.Blocks() as demo:
362
  label="Embedding Model",
363
  ),
364
  )
 
 
365
  lang = (
366
  gr.Dropdown(
367
  ["Español", "English"], value="Español", label="Idioma/Language"
368
  ),
369
  )
370
 
 
 
 
371
  inp.submit(change, inputs=[state, inp], outputs=[state, inp])
372
  but.click(change, inputs=[state, inp], outputs=[state, inp])
373
  give_up.click(
@@ -380,6 +505,7 @@ with gr.Blocks() as demo:
380
  )
381
  radio.input(change, inputs=[state, inp], outputs=[state, inp])
382
 
 
383
  reload.click(
384
  reset,
385
  inputs=[difficulty, lang[0], model[0]],
@@ -401,6 +527,7 @@ with gr.Blocks() as demo:
401
  outputs=[state, out, inp, img, but, radio, hint_out, reload, header],
402
  )
403
 
 
404
  state.change(
405
  update,
406
  inputs=[state, radio, inp, hint],
 
1
+ """
2
+ 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.
3
+
4
+ Modules:
5
+ gradio: Used for creating the web interface.
6
+ json: Used for loading configuration files.
7
+ game: Contains the Semantrix class for game logic.
8
+
9
+ File Paths:
10
+ config_file_path: Path to the configuration file.
11
+ logo_path: Path to the logo image.
12
+ logo_win_path: Path to the winning logo image.
13
+
14
+ Functions:
15
+ convert_to_markdown_centered(text):
16
+ Converts text to a centered markdown format for displaying game history and last attempt.
17
+
18
+ reset(difficulty, lang, model):
19
+ Resets the game state based on the selected difficulty, language, and model.
20
+
21
+ change(state, inp):
22
+ Changes the game state by incrementing the state variable.
23
+
24
+ update(state, radio, inp, hint):
25
+ Updates the game state and UI components based on the current state and user inputs.
26
+
27
+ Gradio Components:
28
+ demo: The main Gradio Blocks component that contains the entire UI layout.
29
+ header: A Markdown component for displaying the game header.
30
+ state: A State component for tracking the current game state.
31
+ difficulty: A State component for tracking the difficulty level.
32
+ hint: A State component for tracking if a hint is provided.
33
+ img: An Image component for displaying the game logo.
34
+ ranking: A Markdown component for displaying the ranking.
35
+ out: A Textbox component for displaying game messages.
36
+ hint_out: A Textbox component for displaying hints.
37
+ radio: A Radio component for user selections.
38
+ inp: A Textbox component for user input.
39
+ but: A Button component for several actions.
40
+ give_up: A Button component for giving up.
41
+ reload: A Button component for reloading the game.
42
+ model: A Dropdown component for selecting the embedding model.
43
+ lang: A Dropdown component for selecting the language.
44
+
45
+ Events:
46
+ inp.submit: Triggers the change function on input submission.
47
+ but.click: Triggers the change function on button click.
48
+ give_up.click: Triggers the change function on give up button click.
49
+ radio.input: Triggers the change function on radio input.
50
+ reload.click: Triggers the reset function on reload button click.
51
+ demo.load: Triggers the reset function on demo load.
52
+ lang[0].select: Triggers the reset function on language selection.
53
+ model[0].select: Triggers the reset function on model selection.
54
+ state.change: Triggers the update function on state change.
55
+
56
+ Main:
57
+ Launches the Gradio application if the script is run as the main module.
58
+ """
59
+
60
  import gradio as gr
61
  import json
62
+ from game import Semantrix
 
 
63
 
64
+ # File paths for configuration and images
65
  config_file_path = "config/lang.json"
66
  logo_path = "config/images/logo.png"
67
  logo_win_path = "config/images/logo_win.gif"
68
 
69
+ # Loading the configuration file
70
  with open(config_file_path, "r") as file:
71
  Config_full = json.load(file)
72
 
73
+ lang_conf = 0 # Language configuration flag (0 for Spanish, 1 for English)
 
74
 
75
+ # Setting the configuration based on the language flag
76
  if lang_conf == 1:
77
  Config = Config_full["ENG"]["Game"]
78
  Menu = Config_full["ENG"]["Menu"]
 
81
  Menu = Config_full["SPA"]["Menu"]
82
 
83
 
84
+ # Function to convert text to centered markdown format
85
  def convert_to_markdown_centered(text):
86
  lines = text.strip().split("\n")
87
 
 
124
  return markdown
125
 
126
 
127
+ #
128
  with gr.Blocks() as demo:
129
+ # Initializing state variables to manage the internal state of the application
130
+ state = gr.State(-1) # State variable to track the current game state
131
+ difficulty = gr.State(-1) # State variable to track the difficulty level
132
+ hint = gr.State(False) # State variable to track if the hint is provided
133
 
134
+ # Initializing the game using the Semantrix class with default parameters
135
+ game = Semantrix(lang=0, model_type="SentenceTransformer")
136
 
137
+ # Creating a Markdown component to display the header
138
  header = gr.Markdown(
139
  """
140
  <p style="text-align:center"> """
 
143
  """
144
  )
145
 
146
+ # Function to reset the game
147
  def reset(difficulty, lang, model):
148
+ global Config, game, Menu # Declare global variables to modify them within the function
149
+
150
+ # Determine the language based on the input parameter
151
  language = 1 if lang == "English" else 0
152
 
153
+ # Initialize the game object based on the selected model
154
  if model == "Word2Vec":
155
+ game = Semantrix(language, "word2vec") # Use Word2Vec model
156
  else:
157
+ game = Semantrix(
158
+ language, "SentenceTransformer"
159
+ ) # Use Sentence Transformers model
160
 
161
+ # Set the configuration and menu based on the selected language
162
  if language == 1:
163
  Config = Config_full["ENG"]["Game"]
164
  Menu = Config_full["ENG"]["Menu"]
 
166
  Config = Config_full["SPA"]["Game"]
167
  Menu = Config_full["SPA"]["Menu"]
168
 
169
+ # Prepare the game with the selected difficulty level
170
  game.prepare_game(difficulty)
171
+
172
+ # Define the initial output components for the UI
173
  output = [
174
  -1,
175
  gr.Textbox(visible=False),
 
188
  ),
189
  ]
190
 
191
+ # Return the initial output components
192
  return output
193
 
194
+ # Function to change the state of the game
195
  def change(state, inp):
196
+ # Increment the state by 1
197
  state = state + 1
198
+
199
+ # Return the updated state and input component
200
  return [state, inp]
201
 
202
+ # Function to update the game state based on the current state of the game
203
  def update(state, radio, inp, hint):
204
  global difficulty
205
+
206
+ # Define the difficulty state
207
  dif_state = 4
208
+
209
+ # Initialize the output component list with the current state
210
  output = [state]
211
 
212
  state_int = state
213
 
214
+ # Define UI components for the initial state
215
  if state_int == -1:
216
  output.extend(
217
  [
 
229
  ]
230
  )
231
 
232
+ # Define UI components for the first state, ask the user if they want to know the rules
233
  elif state_int == 1:
234
  output.extend(
235
  [
 
246
  gr.Markdown(visible=False),
247
  ]
248
  )
249
+
250
+ # Define UI components for the second state, Depending on the answer, show the rules or keep going
251
  elif state_int == 2:
252
  if radio == Menu["No"]:
253
  output = [
 
283
  gr.Markdown(visible=False),
284
  ]
285
  )
286
+
287
+ # Define UI components for the difficulty state, ask the user to select the difficulty level
288
  elif state_int == dif_state:
289
  output.extend(
290
  [
 
304
  gr.Markdown(visible=False),
305
  ]
306
  )
307
+
308
+ # Define UI components for the difficulty state + 1, prepare the game based on the selected difficulty level, and start the game
309
  elif state_int == dif_state + 1:
310
  if radio == Menu["Easy"]:
311
  difficulty = 1
 
332
  ]
333
  )
334
 
335
+ # 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
336
  elif state_int == dif_state + 2:
337
 
338
  game.prepare_game(difficulty)
 
355
  gr.Markdown(visible=False),
356
  ]
357
  )
358
+
359
+ # Define UI components for the state greater than the difficulty state + 2, play the game and provide feedback based on the user input
360
  elif state_int > dif_state + 2:
361
+
362
+ # Send the user input to the game and get the feedback from the game
363
  feed = game.play_game(inp)
364
+
365
+ # Check if the feedback contains the ranking information and process it
366
  feedback_trim = feed.split("[rank]")
367
  if len(feedback_trim) > 1:
368
  ranking_vis = True
 
372
  ranking_vis = False
373
  ranking_md = ""
374
 
375
+ # Check if the feedback contains a hint, win, or lose message
376
  feedback = feedback_trim[0].split("[hint]")
377
  win = feedback_trim[0].split("[win]")
378
  lose = feedback_trim[0].split("[lose]")
379
+
380
+ # Check if the feedback contains a hint message
381
  if len(feedback) > 1:
382
  hint = True
383
+ hint_out = feedback[1]
384
+ feedback = feedback[0]
385
  else:
386
  hint = False
387
+ feedback = feedback[0]
388
 
389
+ # Check if the feedback contains a win or lose message and process it
390
  if len(win) > 1 or len(lose) > 1:
391
+
392
+ # Check if the user won the game
393
  won = True if len(win) > 1 else False
394
+
395
+ # Get the curiosity message from the game
396
  curiosity = game.curiosity()
397
+
398
+ # Define the output components for the win or lose state
399
  output.extend(
400
  [
401
  gr.Button(Menu["Send"], visible=False, variant="primary"),
 
415
  gr.Markdown(visible=False),
416
  ]
417
  )
418
+
419
  return output
420
 
421
+ # Define the output components for the feedback and keep playing
422
  output.extend(
423
  [
424
  gr.Button(Menu["Send"], visible=True, variant="primary"),
425
  gr.Radio(label="", visible=False),
426
+ gr.Textbox(feedback, visible=True, label=""),
427
  gr.Button(visible=True, variant="stop"),
428
  gr.Textbox(value="", visible=True, placeholder=Menu["New_word"]),
429
  gr.Image(logo_path, interactive=False, visible=False),
430
+ gr.Textbox(hint_out if hint else "", visible=hint, label="Pista"),
 
 
431
  gr.Button(visible=False),
432
  gr.Markdown(ranking_md, visible=ranking_vis),
433
  ]
434
  )
435
 
436
+ # Define UI components for the rest of the states, state for showing basic text to the user
437
  else:
438
  output.extend(
439
  [
 
450
  gr.Markdown(visible=False),
451
  ]
452
  )
453
+
454
+ # Return the output components
455
  return output
456
 
457
+ # Define the UI layout for the gam
458
  img = gr.Image(logo_path, height=430, interactive=False, visible=True)
459
  ranking = gr.Markdown(visible=False)
460
 
461
  with gr.Row():
462
  out = gr.Textbox(visible=False, placeholder=Config[list(Config.keys())[0]])
463
  hint_out = gr.Textbox(visible=False)
464
+
465
  radio = gr.Radio(visible=False)
466
+
467
  with gr.Row():
468
  inp = gr.Textbox(visible=False, interactive=True, label="")
469
  but = gr.Button(Menu["Start"])
470
  give_up = gr.Button("Pista", visible=False)
471
  reload = gr.Button(Menu["Play_again"], visible=False)
472
 
473
+ # Define the settings components for the game
474
  with gr.Accordion("Configuración/Settings", open=False):
475
  with gr.Row():
476
+
477
+ # Dropdown to select the model engine for the game
478
  model = (
479
  gr.Dropdown(
480
  ["Sentence Transformers", "Word2Vec"],
 
482
  label="Embedding Model",
483
  ),
484
  )
485
+
486
+ # Dropdown to select the language for the game
487
  lang = (
488
  gr.Dropdown(
489
  ["Español", "English"], value="Español", label="Idioma/Language"
490
  ),
491
  )
492
 
493
+ # Define the UI events for the game
494
+
495
+ # Define events that trigger the game state change
496
  inp.submit(change, inputs=[state, inp], outputs=[state, inp])
497
  but.click(change, inputs=[state, inp], outputs=[state, inp])
498
  give_up.click(
 
505
  )
506
  radio.input(change, inputs=[state, inp], outputs=[state, inp])
507
 
508
+ # Define events that trigger the game reset
509
  reload.click(
510
  reset,
511
  inputs=[difficulty, lang[0], model[0]],
 
527
  outputs=[state, out, inp, img, but, radio, hint_out, reload, header],
528
  )
529
 
530
+ # Define events that trigger the game state update
531
  state.change(
532
  update,
533
  inputs=[state, radio, inp, hint],
data/ranking.txt CHANGED
@@ -1,5 +1,10 @@
1
- ['#3', 'dfsdffdf', 3.96]
2
  ---------------------------
3
- ['#1', 'amigo', 6.48]
4
- ['#2', 'loco', 5.79]
5
- ['#3', 'dfsdffdf', 3.96]
 
 
 
 
 
 
1
+ ['#8', 'medium', 6.94]
2
  ---------------------------
3
+ ['#1', 'amigo', 8.3]
4
+ ['#2', 'loco', 7.64]
5
+ ['#7', 'fantasma', 7.41]
6
+ ['#8', 'medium', 6.94]
7
+ ['#4', 'hermano', 6.81]
8
+ ['#5', 'duelo', 5.76]
9
+ ['#3', 'familia', 4.88]
10
+ ['#6', 'divorcio', 1.67]
game_word2vec.py → game.py RENAMED
@@ -1,4 +1,41 @@
1
- # %%
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  import json
3
  import random
4
  from datetime import datetime
@@ -15,65 +52,102 @@ import warnings
15
  warnings.filterwarnings(action="ignore", category=UserWarning, module="gensim")
16
 
17
 
 
18
  class Semantrix:
19
 
20
- model_st = SentenceTransformer(
21
- "sentence-transformers/paraphrase-multilingual-mpnet-base-v2"
22
- )
23
 
 
24
  config_file_path = "config/lang.json"
25
-
26
  secret_file_path = "config/secret.json"
27
-
28
  data_path = "data/"
29
 
 
30
  class DictWrapper:
31
  def __init__(self, data_dict):
32
  self.__dict__.update(data_dict)
33
 
34
- def __init__(self, lang=0):
35
-
36
- self.lang = lang
37
-
38
- self.embeddings_dict = {}
39
 
 
40
  with open(self.config_file_path, "r") as file:
41
  self.Config_full = json.load(file)
42
 
 
43
  with open(self.secret_file_path, "r") as file:
44
  self.secret = json.load(file)
45
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
  if self.lang == 1:
47
- self.model = KeyedVectors.load("config/w2v_models/eng_w2v_model", mmap="r")
48
  self.Config = self.DictWrapper(self.Config_full["ENG"]["Game"])
49
  self.secret_dict = self.secret["ENG"]
50
  else:
51
- self.model = KeyedVectors.load("config/w2v_models/esp_w2v_model", mmap="r")
52
  self.Config = self.DictWrapper(self.Config_full["SPA"]["Game"])
53
  self.secret_dict = self.secret["SPA"]
54
 
 
55
  with open(self.data_path + "ranking.txt", "w+") as file:
56
  file.write("---------------------------")
57
 
 
58
  def prepare_game(self, difficulty):
59
 
 
60
  self.secret_list = (
61
  self.secret_dict["basic"]
62
  if difficulty <= 2
63
  else self.secret_dict["advanced"]
64
  )
65
 
 
66
  self.secret = self.secret_list.pop(random.randint(0, len(self.secret_list) - 1))
67
  self.secret = self.secret.lower()
68
 
 
69
  self.words = [self.Config.secret_word]
 
 
70
  self.scores = [10]
71
 
72
- if self.secret not in self.embeddings_dict.keys():
73
- self.embeddings_dict[self.secret] = self.model[self.secret]
74
 
75
- self.word_vect = [self.embeddings_dict[self.secret].tolist()]
 
 
 
 
 
 
76
 
 
77
  self.win = False
78
  self.n = 0
79
  self.recent_hint = 0
@@ -81,10 +155,12 @@ class Semantrix:
81
  self.last_hint = -1
82
  self.difficulty = difficulty
83
 
 
84
  if self.difficulty == 1:
85
  self.n = 3
86
 
87
- def preproc_vectors(self, repeated):
 
88
  ascending_indices = np.argsort(self.scores)
89
  descending_indices = list(ascending_indices[::-1])
90
  ranking_data = []
@@ -104,9 +180,13 @@ class Semantrix:
104
  for item in ranking_data:
105
  file.write("%s\n" % item)
106
 
 
107
  def play_game(self, word):
108
 
 
109
  word = word.lower()
 
 
110
  if word == "give_up":
111
  text = (
112
  "[lose]"
@@ -117,14 +197,22 @@ class Semantrix:
117
  )
118
  return text
119
 
 
120
  if word in self.words:
121
  repeated = self.words.index(word)
122
  else:
123
  repeated = -1
124
  self.words.append(word)
125
 
126
- if word not in self.embeddings_dict.keys():
127
- if word not in self.model.key_to_index.keys():
 
 
 
 
 
 
 
128
  self.words.pop(len(self.words) - 1)
129
  feedback = (
130
  "I don't know that word. Try again."
@@ -136,18 +224,23 @@ class Semantrix:
136
  if len(self.words) > 1
137
  else "\n\n"
138
  )
139
-
140
  return feedback
141
 
142
- embedding = self.model[word]
143
- self.embeddings_dict[word] = embedding
144
-
145
- score = round(self.model.similarity(self.secret, word) * 10, 2)
 
 
 
 
 
146
 
 
147
  if repeated == -1:
148
- self.word_vect.append(self.embeddings_dict[word].tolist())
149
  self.scores.append(score)
150
 
 
151
  if score <= 2.5:
152
  feedback = self.Config.Feedback_0 + str(score)
153
  elif score > 2.5 and score <= 4.0:
@@ -160,28 +253,38 @@ class Semantrix:
160
  feedback = self.Config.Feedback_4 + str(score)
161
  elif score > 8.0 and score < 10.0:
162
  feedback = self.Config.Feedback_5 + str(score)
 
163
  else:
164
  self.win = True
165
  feedback = "[win]" + self.Config.Feedback_8
166
  self.words[0] = self.secret
167
  self.words.pop(len(self.words) - 1)
168
- self.word_vect.pop(len(self.word_vect) - 1)
169
  self.scores.pop(len(self.scores) - 1)
170
 
 
171
  if score > self.scores[len(self.scores) - 2] and self.win == False:
172
  feedback += "\n" + self.Config.Feedback_6
173
  elif score < self.scores[len(self.scores) - 2] and self.win == False:
174
  feedback += "\n" + self.Config.Feedback_7
175
 
 
 
176
  if self.difficulty != 4:
177
  mov_avg = calculate_moving_average(self.scores[1:], 5)
178
 
 
179
  if len(mov_avg) > 1 and self.win == False:
180
  f_dev = calculate_tendency_slope(mov_avg)
181
  f_dev_avg = calculate_moving_average(f_dev, 3)
 
 
182
  if f_dev_avg[len(f_dev_avg) - 1] < 0 and self.recent_hint == 0:
 
 
183
  i = random.randint(0, len(self.Config.hint_intro) - 1)
184
  feedback += "\n\n[hint]" + self.Config.hint_intro[i]
 
 
185
  hint_text, self.n, self.last_hint = hint(
186
  self.secret,
187
  self.n,
@@ -200,26 +303,30 @@ class Semantrix:
200
  if self.recent_hint != 0:
201
  self.recent_hint -= 1
202
 
203
- self.preproc_vectors(repeated)
 
204
 
 
205
  feedback += "[rank]" + open(self.data_path + "ranking.txt", "r").read()
206
 
207
- if self.win:
208
- bold_display = 0
209
-
210
  if self.win:
211
 
212
  with open(self.data_path + "ranking.txt", "r") as original_file:
213
  file_content = original_file.readlines()
214
 
215
  new_file_name = self.secret + "_" + str(datetime.now()) + ".txt"
 
216
  with open(self.data_path + "plays/" + new_file_name, "w+") as new_file:
217
  new_file.writelines(file_content[2:])
218
 
 
219
  return feedback
220
 
 
221
  def curiosity(self):
222
 
 
223
  feedback = curiosity(
224
  self.secret,
225
  (
@@ -229,4 +336,5 @@ class Semantrix:
229
  ),
230
  )
231
 
 
232
  return feedback
 
1
+ """
2
+ Semantrix Game Module
3
+
4
+ This module defines the Semantrix class, which implements a word guessing game using word embeddings. The game can be configured to use either a Word2Vec model or a SentenceTransformer model for word embeddings. The game supports multiple languages and difficulty levels.
5
+
6
+ Classes:
7
+ Semantrix: A class that implements the Semantrix word guessing game.
8
+ Semantrix.DictWrapper: A helper class to wrap configuration dictionaries.
9
+
10
+ Functions:
11
+ __init__(self, lang=0, model_type="SentenceTransformer"): Initializes the Semantrix game with the specified language and model type.
12
+ prepare_game(self, difficulty): Prepares the game with the selected difficulty level.
13
+ gen_rank(self, repeated): Generates the ranking file based on the scores.
14
+ play_game(self, word): Plays the game with the selected word and returns feedback.
15
+ curiosity(self): Generates a curiosity hint about the secret word once the game is over.
16
+
17
+ Attributes:
18
+ model (KeyedVectors): The word embeddings model.
19
+ config_file_path (str): Path to the configuration file.
20
+ secret_file_path (str): Path to the secret words file.
21
+ data_path (str): Path to the data directory.
22
+ Config_full (dict): Full configuration data.
23
+ secret (dict): Secret words data.
24
+ lang (int): Language of the game (0 for Spanish, 1 for English).
25
+ model_type (str): Type of the model ("word2vec" or "SentenceTransformer").
26
+ Config (DictWrapper): Configuration data for the selected language.
27
+ secret_dict (dict): Secret words for the selected language.
28
+ secret_list (list): List of secret words for the selected difficulty.
29
+ words (list): List of words guessed by the player.
30
+ scores (list): List of scores for the guessed words.
31
+ win (bool): Indicates if the player has won the game.
32
+ n (int): Number of hints given.
33
+ recent_hint (int): Counter for recent hints.
34
+ f_dev_avg (float): Moving average of the tendency slope.
35
+ last_hint (int): Index of the last hint given.
36
+ difficulty (int): Difficulty level of the game.
37
+ """
38
+
39
  import json
40
  import random
41
  from datetime import datetime
 
52
  warnings.filterwarnings(action="ignore", category=UserWarning, module="gensim")
53
 
54
 
55
+ # Define the class Semantrix
56
  class Semantrix:
57
 
58
+ # Create empty KeyedVectors model with predefined size where the embeddings will be stored
59
+ model = KeyedVectors(768)
 
60
 
61
+ # Define the paths for the configuration files and the data
62
  config_file_path = "config/lang.json"
 
63
  secret_file_path = "config/secret.json"
 
64
  data_path = "data/"
65
 
66
+ # Define the class DictWrapper to store the configuration data
67
  class DictWrapper:
68
  def __init__(self, data_dict):
69
  self.__dict__.update(data_dict)
70
 
71
+ # Define the constructor of the class which loads the configuration files and initializes the class variables depending on the language parameter and the model type
72
+ def __init__(self, lang=0, model_type="SentenceTransformer"):
 
 
 
73
 
74
+ # Load the configuration files
75
  with open(self.config_file_path, "r") as file:
76
  self.Config_full = json.load(file)
77
 
78
+ # Load the secret file where the secret words are stored
79
  with open(self.secret_file_path, "r") as file:
80
  self.secret = json.load(file)
81
 
82
+ # Set the language of the game
83
+ self.lang = lang
84
+
85
+ # Set the model type
86
+ self.model_type = model_type
87
+
88
+ # Load word2vec model if needed
89
+ if self.model_type == "word2vec":
90
+ if self.lang == 1:
91
+ self.model = KeyedVectors.load(
92
+ "config/w2v_models/eng_w2v_model", mmap="r"
93
+ )
94
+ self.Config = self.DictWrapper(self.Config_full["ENG"]["Game"])
95
+ self.secret_dict = self.secret["ENG"]
96
+ else:
97
+ self.model = KeyedVectors.load(
98
+ "config/w2v_models/esp_w2v_model", mmap="r"
99
+ )
100
+ self.Config = self.DictWrapper(self.Config_full["SPA"]["Game"])
101
+ self.secret_dict = self.secret["SPA"]
102
+ else:
103
+ self.model_st = SentenceTransformer(
104
+ "sentence-transformers/paraphrase-multilingual-mpnet-base-v2"
105
+ )
106
+
107
+ # Set the configuration variables depending on the language
108
  if self.lang == 1:
 
109
  self.Config = self.DictWrapper(self.Config_full["ENG"]["Game"])
110
  self.secret_dict = self.secret["ENG"]
111
  else:
 
112
  self.Config = self.DictWrapper(self.Config_full["SPA"]["Game"])
113
  self.secret_dict = self.secret["SPA"]
114
 
115
+ # Create the ranking file
116
  with open(self.data_path + "ranking.txt", "w+") as file:
117
  file.write("---------------------------")
118
 
119
+ # Define the function to prepare the game with the selected difficulty
120
  def prepare_game(self, difficulty):
121
 
122
+ # Set the secret list depending on the difficulty
123
  self.secret_list = (
124
  self.secret_dict["basic"]
125
  if difficulty <= 2
126
  else self.secret_dict["advanced"]
127
  )
128
 
129
+ # Select a random secret word from the secret list
130
  self.secret = self.secret_list.pop(random.randint(0, len(self.secret_list) - 1))
131
  self.secret = self.secret.lower()
132
 
133
+ # Store the secret word in the words list
134
  self.words = [self.Config.secret_word]
135
+
136
+ # Store the score in the scores list
137
  self.scores = [10]
138
 
139
+ # Store the embedding of the secret word in the embeddings dictionary
140
+ if self.secret not in self.model.key_to_index.keys():
141
 
142
+ # Add the secret word to the KeyedVectors model if the model type is SentenceTransformer
143
+ # If the model type is word2vec, the secret word is already in the model
144
+ if self.model_type == "SentenceTransformer":
145
+ self.model.add_vector(
146
+ self.secret,
147
+ self.model_st.encode(self.secret, convert_to_tensor=True).tolist(),
148
+ )
149
 
150
+ # Initialize the game variables
151
  self.win = False
152
  self.n = 0
153
  self.recent_hint = 0
 
155
  self.last_hint = -1
156
  self.difficulty = difficulty
157
 
158
+ # Set the number of hints depending on the difficulty
159
  if self.difficulty == 1:
160
  self.n = 3
161
 
162
+ # Define the function to generate the ranking file
163
+ def gen_rank(self, repeated):
164
  ascending_indices = np.argsort(self.scores)
165
  descending_indices = list(ascending_indices[::-1])
166
  ranking_data = []
 
180
  for item in ranking_data:
181
  file.write("%s\n" % item)
182
 
183
+ # Define the function to play the game with the selected word
184
  def play_game(self, word):
185
 
186
+ # Convert the word to lowercase
187
  word = word.lower()
188
+
189
+ # Check if the user wants to give up
190
  if word == "give_up":
191
  text = (
192
  "[lose]"
 
197
  )
198
  return text
199
 
200
+ # Check if the word is repeated
201
  if word in self.words:
202
  repeated = self.words.index(word)
203
  else:
204
  repeated = -1
205
  self.words.append(word)
206
 
207
+ # Check if the word is in the model already
208
+ if word not in self.model.key_to_index.keys():
209
+ # Add the word to the KeyedVectors model if the model type is SentenceTransformer
210
+ if self.model_type == "SentenceTransformer":
211
+ self.model.add_vector(
212
+ word, self.model_st.encode(word, convert_to_tensor=True).tolist()
213
+ )
214
+ else:
215
+ # If the word is not in the model when using word2vec, remove it from the words list and provide feedback
216
  self.words.pop(len(self.words) - 1)
217
  feedback = (
218
  "I don't know that word. Try again."
 
224
  if len(self.words) > 1
225
  else "\n\n"
226
  )
 
227
  return feedback
228
 
229
+ # Calculate the score of the word, apply logarithmic scaling, interpolate the score to a range from 0 to 10, and round it to two decimal places
230
+ score = round(
231
+ np.interp(
232
+ np.log(self.model.similarity(self.secret, word) * 10),
233
+ [0, np.log(10)],
234
+ [0, 10],
235
+ ),
236
+ 2,
237
+ )
238
 
239
+ # Remove the word from the score list if it is repeated
240
  if repeated == -1:
 
241
  self.scores.append(score)
242
 
243
+ # Generate the feedback message depending on the score
244
  if score <= 2.5:
245
  feedback = self.Config.Feedback_0 + str(score)
246
  elif score > 2.5 and score <= 4.0:
 
253
  feedback = self.Config.Feedback_4 + str(score)
254
  elif score > 8.0 and score < 10.0:
255
  feedback = self.Config.Feedback_5 + str(score)
256
+ # If the score is 10, the user wins the game
257
  else:
258
  self.win = True
259
  feedback = "[win]" + self.Config.Feedback_8
260
  self.words[0] = self.secret
261
  self.words.pop(len(self.words) - 1)
 
262
  self.scores.pop(len(self.scores) - 1)
263
 
264
+ # Generate the feedback message depending on the score and the previous score
265
  if score > self.scores[len(self.scores) - 2] and self.win == False:
266
  feedback += "\n" + self.Config.Feedback_6
267
  elif score < self.scores[len(self.scores) - 2] and self.win == False:
268
  feedback += "\n" + self.Config.Feedback_7
269
 
270
+ ## Hint generation
271
+ # If the difficulty is not 4, calculate the moving average of the scores and the tendency slope
272
  if self.difficulty != 4:
273
  mov_avg = calculate_moving_average(self.scores[1:], 5)
274
 
275
+ # If the moving average has more than one element and the user has not won yet, calculate the tendency slope and the moving average of the tendency slope
276
  if len(mov_avg) > 1 and self.win == False:
277
  f_dev = calculate_tendency_slope(mov_avg)
278
  f_dev_avg = calculate_moving_average(f_dev, 3)
279
+
280
+ # If the tendency slope is negative and the hint has not been given recently (at least three rounds earlier), generate a hint
281
  if f_dev_avg[len(f_dev_avg) - 1] < 0 and self.recent_hint == 0:
282
+
283
+ # Generate a random hint intro from the hint list
284
  i = random.randint(0, len(self.Config.hint_intro) - 1)
285
  feedback += "\n\n[hint]" + self.Config.hint_intro[i]
286
+
287
+ # Generate a dynamic hint
288
  hint_text, self.n, self.last_hint = hint(
289
  self.secret,
290
  self.n,
 
303
  if self.recent_hint != 0:
304
  self.recent_hint -= 1
305
 
306
+ # Generate the ranking file
307
+ self.gen_rank(repeated)
308
 
309
+ # Add the ranking file to the feedback message
310
  feedback += "[rank]" + open(self.data_path + "ranking.txt", "r").read()
311
 
312
+ # Save the ranking file with the plays of the user if the user wins
 
 
313
  if self.win:
314
 
315
  with open(self.data_path + "ranking.txt", "r") as original_file:
316
  file_content = original_file.readlines()
317
 
318
  new_file_name = self.secret + "_" + str(datetime.now()) + ".txt"
319
+
320
  with open(self.data_path + "plays/" + new_file_name, "w+") as new_file:
321
  new_file.writelines(file_content[2:])
322
 
323
+ # Return the feedback message
324
  return feedback
325
 
326
+ # Define the function to generate a curiosity hint once the game is over
327
  def curiosity(self):
328
 
329
+ # Generate a curiosity aboyt the secret word
330
  feedback = curiosity(
331
  self.secret,
332
  (
 
336
  ),
337
  )
338
 
339
+ # Return the feedback message
340
  return feedback
game_transformer.py DELETED
@@ -1,228 +0,0 @@
1
- # %%
2
- import json
3
- import re
4
- import random
5
- from datetime import datetime
6
- import numpy as np
7
- from gensim.models import KeyedVectors
8
- from hints import curiosity, hint
9
- from tracking import (
10
- calculate_moving_average,
11
- calculate_tendency_slope,
12
- )
13
- from sentence_transformers import SentenceTransformer
14
- import warnings
15
-
16
- warnings.filterwarnings(action="ignore", category=UserWarning, module="gensim")
17
-
18
-
19
- class Semantrix:
20
- model = KeyedVectors(768)
21
- model_st = SentenceTransformer(
22
- "sentence-transformers/paraphrase-multilingual-mpnet-base-v2"
23
- )
24
-
25
- config_file_path = "config/lang.json"
26
- secret_file_path = "config/secret.json"
27
- data_path = "data/"
28
-
29
- class DictWrapper:
30
- def __init__(self, data_dict):
31
- self.__dict__.update(data_dict)
32
-
33
- def __init__(self, lang=0):
34
-
35
- self.embeddings_dict = {}
36
-
37
- with open(self.config_file_path, "r") as file:
38
- self.Config_full = json.load(file)
39
-
40
- with open(self.secret_file_path, "r") as file:
41
- self.secret = json.load(file)
42
-
43
- self.lang = lang
44
-
45
- if self.lang == 1:
46
- self.Config = self.DictWrapper(self.Config_full["ENG"]["Game"])
47
- self.secret_dict = self.secret["ENG"]
48
- else:
49
- self.Config = self.DictWrapper(self.Config_full["SPA"]["Game"])
50
- self.secret_dict = self.secret["SPA"]
51
-
52
- with open(self.data_path + "ranking.txt", "w+") as file:
53
- file.write("---------------------------")
54
-
55
- def prepare_game(self, difficulty):
56
-
57
- self.secret_list = (
58
- self.secret_dict["basic"]
59
- if difficulty <= 2
60
- else self.secret_dict["advanced"]
61
- )
62
-
63
- self.secret = self.secret_list.pop(random.randint(0, len(self.secret_list) - 1))
64
- self.secret = self.secret.lower()
65
-
66
- self.words = [self.Config.secret_word]
67
- self.scores = [10]
68
-
69
- if self.secret not in self.embeddings_dict.keys():
70
- self.embeddings_dict[self.secret] = self.model_st.encode(
71
- self.secret, convert_to_tensor=True
72
- )
73
- self.model.add_vector(
74
- self.secret, self.embeddings_dict[self.secret].tolist()
75
- )
76
-
77
- self.word_vect = [self.embeddings_dict[self.secret].tolist()]
78
-
79
- self.win = False
80
- self.n = 0
81
- self.recent_hint = 0
82
- self.f_dev_avg = 0
83
- self.last_hint = -1
84
- self.difficulty = difficulty
85
-
86
- if self.difficulty == 1:
87
- self.n = 3
88
-
89
- def preproc_vectors(self, repeated):
90
- ascending_indices = np.argsort(self.scores)
91
- descending_indices = list(ascending_indices[::-1])
92
- ranking_data = []
93
- k = len(self.words) - 1
94
- if repeated != -1:
95
- k = repeated
96
-
97
- ranking_data.append(["#" + str(k), self.words[k], self.scores[k]])
98
-
99
- ranking_data.append("---------------------------")
100
- for i in descending_indices:
101
- if i == 0:
102
- continue
103
- ranking_data.append(["#" + str(i), self.words[i], self.scores[i]])
104
-
105
- with open(self.data_path + "ranking.txt", "w+") as file:
106
- for item in ranking_data:
107
- file.write("%s\n" % item)
108
-
109
- def play_game(self, word):
110
-
111
- word = word.lower()
112
- if word == "give_up":
113
- text = (
114
- "[lose]"
115
- + self.Config.Feedback_9
116
- + self.secret
117
- + "\n\n"
118
- + self.Config.Feedback_10
119
- )
120
- return text
121
-
122
- if word in self.words:
123
- repeated = self.words.index(word)
124
- else:
125
- repeated = -1
126
- self.words.append(word)
127
-
128
- if word not in self.embeddings_dict.keys():
129
- embedding = self.model_st.encode(word, convert_to_tensor=True)
130
- self.embeddings_dict[word] = embedding
131
- self.model.add_vector(word, embedding.tolist())
132
-
133
- score = round(
134
- np.interp(
135
- np.log(self.model.similarity(self.secret, word) * 10),
136
- [0, np.log(10)],
137
- [0, 10],
138
- ),
139
- 2,
140
- )
141
-
142
- if repeated == -1:
143
- self.word_vect.append(self.embeddings_dict[word].tolist())
144
- self.scores.append(score)
145
-
146
- if score <= 2.5:
147
- feedback = self.Config.Feedback_0 + str(score)
148
- elif score > 2.5 and score <= 4.0:
149
- feedback = self.Config.Feedback_1 + str(score)
150
- elif score > 4.0 and score <= 6.0:
151
- feedback = self.Config.Feedback_2 + str(score)
152
- elif score > 6.0 and score <= 7.5:
153
- feedback = self.Config.Feedback_3 + str(score)
154
- elif score > 7.5 and score <= 8.0:
155
- feedback = self.Config.Feedback_4 + str(score)
156
- elif score > 8.0 and score < 10.0:
157
- feedback = self.Config.Feedback_5 + str(score)
158
- else:
159
- self.win = True
160
- feedback = "[win]" + self.Config.Feedback_8
161
- self.words[0] = self.secret
162
- self.words.pop(len(self.words) - 1)
163
- self.word_vect.pop(len(self.word_vect) - 1)
164
- self.scores.pop(len(self.scores) - 1)
165
-
166
- if score > self.scores[len(self.scores) - 2] and self.win == False:
167
- feedback += "\n" + self.Config.Feedback_6
168
- elif score < self.scores[len(self.scores) - 2] and self.win == False:
169
- feedback += "\n" + self.Config.Feedback_7
170
-
171
- if self.difficulty != 4:
172
- mov_avg = calculate_moving_average(self.scores[1:], 5)
173
-
174
- if len(mov_avg) > 1 and self.win == False:
175
- f_dev = calculate_tendency_slope(mov_avg)
176
- f_dev_avg = calculate_moving_average(f_dev, 3)
177
- if f_dev_avg[len(f_dev_avg) - 1] < 0 and self.recent_hint == 0:
178
- i = random.randint(0, len(self.Config.hint_intro) - 1)
179
- feedback += "\n\n[hint]" + self.Config.hint_intro[i]
180
- hint_text, self.n, self.last_hint = hint(
181
- self.secret,
182
- self.n,
183
- self.model_st,
184
- self.last_hint,
185
- self.lang,
186
- (
187
- self.DictWrapper(self.Config_full["ENG"]["Hint"])
188
- if self.lang == 1
189
- else self.DictWrapper(self.Config_full["SPA"]["Hint"])
190
- ),
191
- )
192
- feedback += "\n" + hint_text
193
- self.recent_hint = 3
194
-
195
- if self.recent_hint != 0:
196
- self.recent_hint -= 1
197
-
198
- self.preproc_vectors(repeated)
199
-
200
- feedback += "[rank]" + open(self.data_path + "ranking.txt", "r").read()
201
-
202
- if self.win:
203
- bold_display = 0
204
-
205
- if self.win:
206
-
207
- with open(self.data_path + "ranking.txt", "r") as original_file:
208
- file_content = original_file.readlines()
209
-
210
- new_file_name = self.secret + "_" + str(datetime.now()) + ".txt"
211
-
212
- with open(self.data_path + "plays/" + new_file_name, "w+") as new_file:
213
- new_file.writelines(file_content[2:])
214
-
215
- return feedback
216
-
217
- def curiosity(self):
218
-
219
- feedback = curiosity(
220
- self.secret,
221
- (
222
- self.DictWrapper(self.Config_full["ENG"]["Hint"])
223
- if self.lang == 1
224
- else self.DictWrapper(self.Config_full["SPA"]["Hint"])
225
- ),
226
- )
227
-
228
- return feedback
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
hints.py CHANGED
@@ -1,24 +1,60 @@
1
- import json
2
- import os
3
- import random
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
 
 
 
 
 
 
 
 
 
 
 
 
5
  import openai
6
  from sentence_transformers import util
7
 
8
- openai.api_key = os.getenv("OPENAI_API_KEY")
 
9
 
 
 
10
 
11
- def hint(secret, n, model, last_pista, lang, Config):
12
- pista = ""
13
 
14
- # Pistas avanzadas
15
  if n >= 3:
16
  j = random.randint(0, 2)
17
- while j == last_pista:
18
  j = random.randint(0, 2)
 
 
19
  if j == 0:
20
  response = openai.chat.completions.create(
21
- model="gpt-3.5-turbo",
22
  messages=[
23
  {
24
  "role": "user",
@@ -38,6 +74,7 @@ def hint(secret, n, model, last_pista, lang, Config):
38
  output = str(response.choices[0].message.content)
39
  output = output.replace('"', "").replace("'", "")
40
 
 
41
  if lang == 0:
42
  output = ireplace("la " + secret, "La palabra secreta", output)
43
  output = ireplace("las " + secret, "La palabra secreta", output)
@@ -51,11 +88,13 @@ def hint(secret, n, model, last_pista, lang, Config):
51
  output = ireplace("the " + secret, "The secret word", output)
52
  output = ireplace("a " + secret, "The secret word", output)
53
 
54
- pista += Config.hint_0_3 + output # type: ignore
55
- last_pista = 0
 
 
56
  elif j == 1:
57
  response = openai.chat.completions.create(
58
- model="gpt-3.5-turbo",
59
  messages=[
60
  {
61
  "role": "user",
@@ -69,11 +108,13 @@ def hint(secret, n, model, last_pista, lang, Config):
69
  presence_penalty=0,
70
  )
71
  output = str(response.choices[0].message.content)
72
- pista += Config.hint_1_2 + output # type: ignore
73
- last_pista = 1
 
 
74
  elif j == 2:
75
  response = openai.chat.completions.create(
76
- model="gpt-3.5-turbo",
77
  messages=[
78
  {
79
  "role": "user",
@@ -88,18 +129,20 @@ def hint(secret, n, model, last_pista, lang, Config):
88
  )
89
  output = str(response.choices[0].message.content)
90
 
91
- pista += Config.hint_2_2 + output # type: ignore
92
 
93
- last_pista = 2
94
- # Pistas iniciales
95
  else:
96
  j = random.randint(3, 4)
97
- while j == last_pista:
98
  j = random.randint(3, 4)
 
 
99
  if j == 3:
100
  words = []
101
  response = openai.chat.completions.create(
102
- model="gpt-3.5-turbo",
103
  messages=[
104
  {
105
  "role": "user",
@@ -116,7 +159,7 @@ def hint(secret, n, model, last_pista, lang, Config):
116
  output = (output.replace(" ", "").replace(".", "")).lower()
117
  words.extend(output.strip().split(","))
118
  response = openai.chat.completions.create(
119
- model="gpt-3.5-turbo",
120
  messages=[
121
  {
122
  "role": "user",
@@ -145,7 +188,7 @@ def hint(secret, n, model, last_pista, lang, Config):
145
  sum_scores = sum(scores)
146
  normalized_scores = [round(score * 100 / sum_scores, 1) for score in scores]
147
 
148
- pista += Config.hint_3_3 # type: ignore
149
 
150
  max_len = -1
151
  for ele in words:
@@ -156,19 +199,21 @@ def hint(secret, n, model, last_pista, lang, Config):
156
  for i in range(len(words)):
157
 
158
  word_hint = words[i].ljust(len(longest_word) + 1)
159
- pista += (
160
  # word_hint[: len(longest_word)]
161
  word_hint
162
  + "|"
163
- + ("🟩") * round(normalized_scores[i] * 0.1)
164
  + " "
165
  + str(normalized_scores[i])
166
  + "%\n"
167
  )
168
- last_pista = 3
 
 
169
  elif j == 4:
170
  response = openai.chat.completions.create(
171
- model="gpt-3.5-turbo",
172
  messages=[
173
  {
174
  "role": "user",
@@ -185,7 +230,7 @@ def hint(secret, n, model, last_pista, lang, Config):
185
  )
186
  film_title = str(response.choices[0].message.content).replace('"', "")
187
  response = openai.chat.completions.create(
188
- model="gpt-3.5-turbo",
189
  messages=[
190
  {
191
  "role": "user",
@@ -201,16 +246,17 @@ def hint(secret, n, model, last_pista, lang, Config):
201
  presence_penalty=0,
202
  )
203
  output = str(response.choices[0].message.content)
204
- pista += Config.hint_4_4 + "\n" + output # type: ignore
205
- last_pista = 4
206
 
207
- return pista, n + 1, last_pista
208
 
209
 
 
210
  def curiosity(secret, Config):
211
 
212
  response = openai.chat.completions.create(
213
- model="gpt-3.5-turbo",
214
  messages=[
215
  {
216
  "role": "user",
@@ -228,6 +274,7 @@ def curiosity(secret, Config):
228
  return output
229
 
230
 
 
231
  def ireplace(old, new, text):
232
  idx = 0
233
  while idx < len(text):
 
1
+ """
2
+ This module provides functions to generate dynamic hints and curiosities about a secret word using llms.
3
+
4
+ Functions:
5
+ hint(secret, n, model, last_hint, lang, Config):
6
+ Generates a dynamic hint based on the secret word and the number of hints given.
7
+ Parameters:
8
+ secret (str): The secret word.
9
+ n (int): The number of hints already given.
10
+ model: The sentence transformer model used for encoding.
11
+ last_hint (int): The index of the last hint given.
12
+ lang (int): The language code (0 for Spanish, 1 for English).
13
+ Config: Configuration object containing hint templates.
14
+ Returns:
15
+ tuple: A tuple containing the generated hint (str), the updated number of hints (int), and the index of the last hint given (int).
16
+
17
+ curiosity(secret, Config):
18
+ Generates a curiosity about the secret word.
19
+ Parameters:
20
+ secret (str): The secret word.
21
+ Config: Configuration object containing the curiosity template.
22
+ Returns:
23
+ str: The generated curiosity.
24
 
25
+ ireplace(old, new, text):
26
+ Replaces all occurrences of a substring in a string, case-insensitively.
27
+ Parameters:
28
+ old (str): The substring to be replaced.
29
+ new (str): The substring to replace with.
30
+ text (str): The original string.
31
+ Returns:
32
+ str: The modified string with all occurrences of the old substring replaced by the new substring.
33
+ """
34
+
35
+ import random
36
  import openai
37
  from sentence_transformers import util
38
 
39
+ gpt_model = "gpt-3.5-turbo"
40
+
41
 
42
+ # Dynamic hint function that returns a hint based on the secret word and the number of hints given
43
+ def hint(secret, n, model, last_hint, lang, Config):
44
 
45
+ # Initialize hint variable
46
+ hint = ""
47
 
48
+ # Advanced hints
49
  if n >= 3:
50
  j = random.randint(0, 2)
51
+ while j == last_hint:
52
  j = random.randint(0, 2)
53
+
54
+ # Advanced hint 1: Definition of the secret word
55
  if j == 0:
56
  response = openai.chat.completions.create(
57
+ model=gpt_model,
58
  messages=[
59
  {
60
  "role": "user",
 
74
  output = str(response.choices[0].message.content)
75
  output = output.replace('"', "").replace("'", "")
76
 
77
+ # Replace the secret word with "La palabra secreta" or "The secret word" just in case the model uses the secret word in the definition
78
  if lang == 0:
79
  output = ireplace("la " + secret, "La palabra secreta", output)
80
  output = ireplace("las " + secret, "La palabra secreta", output)
 
88
  output = ireplace("the " + secret, "The secret word", output)
89
  output = ireplace("a " + secret, "The secret word", output)
90
 
91
+ hint += Config.hint_0_3 + output # type: ignore
92
+ last_hint = 0
93
+
94
+ # Advanced hint 2: Representation of the secret word with emojis
95
  elif j == 1:
96
  response = openai.chat.completions.create(
97
+ model=gpt_model,
98
  messages=[
99
  {
100
  "role": "user",
 
108
  presence_penalty=0,
109
  )
110
  output = str(response.choices[0].message.content)
111
+ hint += Config.hint_1_2 + output # type: ignore
112
+ last_hint = 1
113
+
114
+ # Advanced hint 3: Poem about the secret word
115
  elif j == 2:
116
  response = openai.chat.completions.create(
117
+ model=gpt_model,
118
  messages=[
119
  {
120
  "role": "user",
 
129
  )
130
  output = str(response.choices[0].message.content)
131
 
132
+ hint += Config.hint_2_2 + output # type: ignore
133
 
134
+ last_hint = 2
135
+ # Initial hints
136
  else:
137
  j = random.randint(3, 4)
138
+ while j == last_hint:
139
  j = random.randint(3, 4)
140
+
141
+ # Initial hint 1: Rank of four words related to the secret word
142
  if j == 3:
143
  words = []
144
  response = openai.chat.completions.create(
145
+ model=gpt_model,
146
  messages=[
147
  {
148
  "role": "user",
 
159
  output = (output.replace(" ", "").replace(".", "")).lower()
160
  words.extend(output.strip().split(","))
161
  response = openai.chat.completions.create(
162
+ model=gpt_model,
163
  messages=[
164
  {
165
  "role": "user",
 
188
  sum_scores = sum(scores)
189
  normalized_scores = [round(score * 100 / sum_scores, 1) for score in scores]
190
 
191
+ hint += Config.hint_3_3 # type: ignore
192
 
193
  max_len = -1
194
  for ele in words:
 
199
  for i in range(len(words)):
200
 
201
  word_hint = words[i].ljust(len(longest_word) + 1)
202
+ hint += (
203
  # word_hint[: len(longest_word)]
204
  word_hint
205
  + "|"
206
+ + ("🟩") * round(normalized_scores[i] * 0.2)
207
  + " "
208
  + str(normalized_scores[i])
209
  + "%\n"
210
  )
211
+ last_hint = 3
212
+
213
+ # Initial hint 2: Film representation with emojis with the secret word
214
  elif j == 4:
215
  response = openai.chat.completions.create(
216
+ model=gpt_model,
217
  messages=[
218
  {
219
  "role": "user",
 
230
  )
231
  film_title = str(response.choices[0].message.content).replace('"', "")
232
  response = openai.chat.completions.create(
233
+ model=gpt_model,
234
  messages=[
235
  {
236
  "role": "user",
 
246
  presence_penalty=0,
247
  )
248
  output = str(response.choices[0].message.content)
249
+ hint += Config.hint_4_4 + "\n" + output # type: ignore
250
+ last_hint = 4
251
 
252
+ return hint, n + 1, last_hint
253
 
254
 
255
+ # Tell a curiosity about the secret word
256
  def curiosity(secret, Config):
257
 
258
  response = openai.chat.completions.create(
259
+ model=gpt_model,
260
  messages=[
261
  {
262
  "role": "user",
 
274
  return output
275
 
276
 
277
+ # Replace all occurrences of a substring in a string
278
  def ireplace(old, new, text):
279
  idx = 0
280
  while idx < len(text):
ranking.txt DELETED
@@ -1 +0,0 @@
1
- ---------------------------
 
 
requirements.txt CHANGED
@@ -3,5 +3,5 @@ sentence_transformers==2.2.2
3
  openai==1.2.3
4
  gradio==5.1.0
5
  transformers==4.33.2
6
- huggingface-hub==0.25.2
7
- python-multipart==0.0.12
 
3
  openai==1.2.3
4
  gradio==5.1.0
5
  transformers==4.33.2
6
+ # huggingface-hub==0.25.2
7
+ # python-multipart==0.0.12