MarcosAutuori commited on
Commit
3196102
·
verified ·
1 Parent(s): 36e0f4e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +26 -21
app.py CHANGED
@@ -11,7 +11,7 @@ import time
11
  import os
12
  import base64
13
 
14
- # --- CONFIGURAÇÕES ---
15
  GRID_NUMBERS = [
16
  10, 12, 14, 15, 16, 18, 20, 21,
17
  24, 25, 27, 28, 30, 32, 35, 36,
@@ -19,9 +19,9 @@ GRID_NUMBERS = [
19
  63, 64, 70, 72, 80, 81, 90, 100
20
  ]
21
  KEYBOARD_KEYS = [2, 3, 4, 5, 6, 7, 8, 9, 10]
22
- MAX_TIME = 200 # Tempo aumentado conforme solicitado
23
 
24
- # --- CARREGAMENTO DE ÁUDIO (BASE64) ---
25
  def get_audio_base64(filename):
26
  path = os.path.join("sounds", filename)
27
  if os.path.exists(path):
@@ -30,7 +30,7 @@ def get_audio_base64(filename):
30
  return "data:audio/wav;base64," + base64.b64encode(data).decode()
31
  return ""
32
 
33
- # Pré-carrega os sons da pasta /sounds para o dicionário JS
34
  SOUNDS = {
35
  "click": get_audio_base64("click.wav"),
36
  "correct": get_audio_base64("correct.wav"),
@@ -38,20 +38,20 @@ SOUNDS = {
38
  "complete": get_audio_base64("complete.wav")
39
  }
40
 
41
- # --- JAVASCRIPT PARA PLAYBACK IMEDIATO ---
42
  js_sound_trigger = """
43
  (tag) => {
44
  if (!tag) return;
45
  const soundData = """ + str(SOUNDS) + """;
46
  if (soundData[tag]) {
47
  const audio = new Audio(soundData[tag]);
48
- audio.play().catch(e => console.log("Audio playback blocked"));
49
  }
50
  return tag;
51
  }
52
  """
53
 
54
- # --- LÓGICA DO JOGO ---
55
  def get_empty_state():
56
  return {
57
  "solved": [False] * 32,
@@ -64,7 +64,7 @@ def get_empty_state():
64
 
65
  def handle_game_logic(state, action_type, value=None):
66
  if state["game_over"]:
67
- return state, "Game Over!", ""
68
 
69
  feedback = "Select a target number..."
70
  sound_key = "click"
@@ -94,34 +94,34 @@ def handle_game_logic(state, action_type, value=None):
94
  sound_key = "wrong"
95
  state["current_factors"] = []
96
 
97
- # Cálculo do Score
98
  elapsed = int(time.time() - state["start_time"])
99
  state["score"] = max(0, MAX_TIME - elapsed)
100
 
101
  if all(state["solved"]):
102
  state["game_over"] = True
103
- feedback = f"🏆 VICTORY! Final Score: {state['score']}"
104
- sound_key = "complete" # Som final solicitado
105
 
106
  return state, feedback, sound_key
107
 
108
- # --- INTERFACE ---
109
  custom_css = """
110
  .grid-btn { min-width: 80px !important; height: 80px !important; font-size: 20px !important; margin: 2px !important; }
111
- .kb-btn { min-width: 60px !important; height: 50px !important; }
112
  """
113
 
114
  with gr.Blocks(title="Autuori - Factorization Game", css=custom_css) as demo:
115
  state = gr.State(get_empty_state())
116
 
117
- # Campo invisível que dispara o som via JS
118
  sound_trigger = gr.Textbox(visible=False)
119
  sound_trigger.change(None, inputs=sound_trigger, js=js_sound_trigger)
120
 
121
- gr.Markdown("# 🎮 Interactive Factorization v1.5 EN\n**Developer: Marcos Autuori**")
122
 
123
  with gr.Row():
124
  with gr.Column(scale=4):
 
125
  grid_buttons = []
126
  for r in range(4):
127
  with gr.Row():
@@ -131,14 +131,19 @@ with gr.Blocks(title="Autuori - Factorization Game", css=custom_css) as demo:
131
  grid_buttons.append(btn)
132
 
133
  with gr.Column(scale=1):
134
- status_box = gr.Textbox(label="Status", value="Select a blue target", interactive=False)
 
135
  score_display = gr.Number(label="Score", value=MAX_TIME, interactive=False)
136
 
137
- gr.Markdown("### Factors")
138
  keyboard_btns = []
139
- for val in KEYBOARD_KEYS:
140
- kb_btn = gr.Button(str(val), variant="secondary", elem_classes="kb-btn")
141
- keyboard_btns.append(kb_btn)
 
 
 
 
142
 
143
  reset_btn = gr.Button("Restart Game", variant="stop")
144
 
@@ -150,7 +155,7 @@ with gr.Blocks(title="Autuori - Factorization Game", css=custom_css) as demo:
150
  updates.append(gr.update(value=label, variant=variant, interactive=not s["solved"][i]))
151
  return updates + [s["score"]]
152
 
153
- # Eventos
154
  for i, btn in enumerate(grid_buttons):
155
  btn.click(
156
  fn=lambda s, idx=i: handle_game_logic(s, "select_target", idx),
 
11
  import os
12
  import base64
13
 
14
+ # --- CONFIGURATION ---
15
  GRID_NUMBERS = [
16
  10, 12, 14, 15, 16, 18, 20, 21,
17
  24, 25, 27, 28, 30, 32, 35, 36,
 
19
  63, 64, 70, 72, 80, 81, 90, 100
20
  ]
21
  KEYBOARD_KEYS = [2, 3, 4, 5, 6, 7, 8, 9, 10]
22
+ MAX_TIME = 200
23
 
24
+ # --- AUDIO LOADING (BASE64 for Zero Latency) ---
25
  def get_audio_base64(filename):
26
  path = os.path.join("sounds", filename)
27
  if os.path.exists(path):
 
30
  return "data:audio/wav;base64," + base64.b64encode(data).decode()
31
  return ""
32
 
33
+ # Pre-load sounds from the /sounds folder
34
  SOUNDS = {
35
  "click": get_audio_base64("click.wav"),
36
  "correct": get_audio_base64("correct.wav"),
 
38
  "complete": get_audio_base64("complete.wav")
39
  }
40
 
41
+ # --- JAVASCRIPT FOR INSTANT PLAYBACK ---
42
  js_sound_trigger = """
43
  (tag) => {
44
  if (!tag) return;
45
  const soundData = """ + str(SOUNDS) + """;
46
  if (soundData[tag]) {
47
  const audio = new Audio(soundData[tag]);
48
+ audio.play().catch(e => console.log("Audio blocked: Interact with the page first."));
49
  }
50
  return tag;
51
  }
52
  """
53
 
54
+ # --- GAME LOGIC ---
55
  def get_empty_state():
56
  return {
57
  "solved": [False] * 32,
 
64
 
65
  def handle_game_logic(state, action_type, value=None):
66
  if state["game_over"]:
67
+ return state, "Game Over! Restart to play.", ""
68
 
69
  feedback = "Select a target number..."
70
  sound_key = "click"
 
94
  sound_key = "wrong"
95
  state["current_factors"] = []
96
 
 
97
  elapsed = int(time.time() - state["start_time"])
98
  state["score"] = max(0, MAX_TIME - elapsed)
99
 
100
  if all(state["solved"]):
101
  state["game_over"] = True
102
+ feedback = "🏆 CONGRATULATIONS! ALL SOLVED!"
103
+ sound_key = "complete"
104
 
105
  return state, feedback, sound_key
106
 
107
+ # --- STYLING ---
108
  custom_css = """
109
  .grid-btn { min-width: 80px !important; height: 80px !important; font-size: 20px !important; margin: 2px !important; }
110
+ .kb-btn { min-width: 60px !important; height: 60px !important; font-size: 18px !important; }
111
  """
112
 
113
  with gr.Blocks(title="Autuori - Factorization Game", css=custom_css) as demo:
114
  state = gr.State(get_empty_state())
115
 
116
+ # Hidden field to trigger JS sound
117
  sound_trigger = gr.Textbox(visible=False)
118
  sound_trigger.change(None, inputs=sound_trigger, js=js_sound_trigger)
119
 
120
+ gr.Markdown("# 🎮 Interactive Factorization v1.5 EN\n**Developed by Marcos Autuori**")
121
 
122
  with gr.Row():
123
  with gr.Column(scale=4):
124
+ # 4x8 Target Grid
125
  grid_buttons = []
126
  for r in range(4):
127
  with gr.Row():
 
131
  grid_buttons.append(btn)
132
 
133
  with gr.Column(scale=1):
134
+ # Status & Info
135
+ status_box = gr.Textbox(label="Status", value="Select a target", interactive=False)
136
  score_display = gr.Number(label="Score", value=MAX_TIME, interactive=False)
137
 
138
+ gr.Markdown("### Factor Keyboard")
139
  keyboard_btns = []
140
+ # Keyboard 3x3 (Correct Layout)
141
+ for r_kb in range(3):
142
+ with gr.Row():
143
+ for c_kb in range(3):
144
+ val = KEYBOARD_KEYS[r_kb * 3 + c_kb]
145
+ kb_btn = gr.Button(str(val), variant="secondary", elem_classes="kb-btn")
146
+ keyboard_btns.append(kb_btn)
147
 
148
  reset_btn = gr.Button("Restart Game", variant="stop")
149
 
 
155
  updates.append(gr.update(value=label, variant=variant, interactive=not s["solved"][i]))
156
  return updates + [s["score"]]
157
 
158
+ # Events
159
  for i, btn in enumerate(grid_buttons):
160
  btn.click(
161
  fn=lambda s, idx=i: handle_game_logic(s, "select_target", idx),