Zual commited on
Commit
ae42fd3
·
verified ·
1 Parent(s): fa2b69d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +110 -291
app.py CHANGED
@@ -6,303 +6,154 @@ import git
6
  import sys
7
  import random
8
  from streamlit.components.v1 import html
 
 
 
 
 
9
 
10
  # Configuration de la page
11
  st.set_page_config(page_title="Échecs contre IA", layout="wide")
12
 
13
  def render_board():
14
  """Rendre l'échiquier interactif"""
15
- # Générer le SVG de l'échiquier
16
- board_svg = chess.svg.board(
17
- board=st.session_state.board,
18
- size=400,
19
- lastmove=st.session_state.board.peek() if st.session_state.board.move_stack else None,
20
- )
21
-
22
- # Code HTML/JS pour rendre l'échiquier interactif
23
- html_content = f"""
24
- <style>
25
- #chess-board {{
26
- position: relative;
27
- width: 400px;
28
- margin: auto;
29
- }}
30
- #chess-board svg {{
31
- position: absolute;
32
- top: 0;
33
- left: 0;
34
- width: 100%;
35
- height: 100%;
36
- pointer-events: none;
37
- }}
38
- #chess-board svg * {{
39
- pointer-events: auto;
40
- }}
41
- .piece {{
42
- cursor: grab;
43
- pointer-events: auto;
44
- }}
45
- .piece.dragging {{
46
- cursor: grabbing;
47
- }}
48
- .square {{
49
- pointer-events: auto;
50
- }}
51
- .highlight {{
52
- fill: rgba(255, 255, 0, 0.3);
53
- }}
54
- .possible-move {{
55
- fill: rgba(0, 255, 0, 0.3);
56
- }}
57
- .ghost-piece {{
58
- opacity: 0.3;
59
- pointer-events: none;
60
- }}
61
- </style>
62
 
63
- <div id="chess-board">
64
- {board_svg}
65
- <div id="drag-layer" style="position: absolute; top: 0; left: 0; pointer-events: none;"></div>
66
- </div>
67
-
68
- <script>
69
- (function() {{
70
- const board = document.querySelector('#chess-board');
71
- const svg = board.querySelector('svg');
72
- const dragLayer = document.getElementById('drag-layer');
73
- let selectedPiece = null;
74
- let ghostPiece = null;
75
- let startSquare = null;
76
- let currentSquare = null;
77
- let isDragging = false;
78
- let offset = {{ x: 0, y: 0 }};
79
-
80
- // Convertir les coordonnées en notation algébrique
81
- function getSquareFromCoords(x, y) {{
82
- const boardRect = board.getBoundingClientRect();
83
- const squareSize = boardRect.width / 8;
84
- const file = Math.floor((x - boardRect.left) / squareSize);
85
- const rank = 7 - Math.floor((y - boardRect.top) / squareSize);
86
- if (file >= 0 && file < 8 && rank >= 0 && rank < 8) {{
87
- return String.fromCharCode(97 + file) + (rank + 1);
88
- }}
89
- return null;
90
- }}
91
-
92
- // Créer une copie fantôme de la pièce pour le glissement
93
- function createGhostPiece(piece) {{
94
- const clone = piece.cloneNode(true);
95
- clone.classList.add('ghost-piece');
96
- return clone;
97
- }}
98
-
99
- // Mettre à jour la position du fantôme
100
- function updateGhostPosition(x, y) {{
101
- if (ghostPiece) {{
102
- ghostPiece.style.transform = `translate(${{x - offset.x}}px, ${{y - offset.y}}px)`;
103
- }}
104
- }}
105
-
106
- // Gérer le début du glissement
107
- svg.addEventListener('mousedown', function(e) {{
108
- const piece = e.target.closest('.piece');
109
- if (piece && piece.classList.contains('white')) {{
110
- e.preventDefault();
111
- selectedPiece = piece;
112
- const rect = piece.getBoundingClientRect();
113
- offset.x = e.clientX - rect.left;
114
- offset.y = e.clientY - rect.top;
115
-
116
- // Créer et positionner le fantôme
117
- ghostPiece = createGhostPiece(piece);
118
- dragLayer.appendChild(ghostPiece);
119
- updateGhostPosition(e.clientX, e.clientY);
120
-
121
- startSquare = getSquareFromCoords(e.clientX, e.clientY);
122
- isDragging = true;
123
- selectedPiece.classList.add('dragging');
124
- }}
125
- }});
126
-
127
- // Gérer le glissement
128
- document.addEventListener('mousemove', function(e) {{
129
- if (isDragging && ghostPiece) {{
130
- e.preventDefault();
131
- updateGhostPosition(e.clientX, e.clientY);
132
- currentSquare = getSquareFromCoords(e.clientX, e.clientY);
133
- }}
134
  }});
135
-
136
- // Gérer la fin du glissement
137
- document.addEventListener('mouseup', function(e) {{
138
- if (isDragging && selectedPiece) {{
139
- const endSquare = getSquareFromCoords(e.clientX, e.clientY);
140
-
141
- if (startSquare && endSquare && startSquare !== endSquare) {{
142
- window.parent.postMessage({{
143
- type: 'chess_move',
144
- from: startSquare,
145
- to: endSquare
146
- }}, '*');
147
- }}
148
-
149
- // Nettoyer
150
- if (ghostPiece) {{
151
- dragLayer.removeChild(ghostPiece);
152
- ghostPiece = null;
153
- }}
154
- selectedPiece.classList.remove('dragging');
155
- selectedPiece = null;
156
- isDragging = false;
157
- }}
158
  }});
159
- }})();
160
- </script>
161
- """
162
-
163
- html(html_content, height=450)
164
-
165
- def calculate_max_length(move_count):
166
- """Calcule le max_length optimal"""
167
- base_length = 10
168
- increment = 1
169
- max_length = 100
170
- return min(base_length + (move_count * increment), max_length)
 
 
 
 
 
 
 
 
 
171
 
 
172
  @st.cache_resource
173
  def setup_inference():
174
  """Initialise le modèle d'IA"""
175
- if not os.path.exists('chess'):
176
- git.Repo.clone_from('https://github.com/l-pommeret/chess.git', 'chess')
177
- if 'chess' not in sys.path:
178
- sys.path.append('chess')
179
- from inference import InferenceConfig, ChessGenerator
180
-
181
- config = InferenceConfig(
182
- model_name="Zual/chess",
183
- temperature=0.8,
184
- max_length=6
185
- )
186
- return ChessGenerator(config)
187
-
188
- def initialize_state():
189
- """Initialise ou réinitialise l'état du jeu"""
190
- if 'board' not in st.session_state:
191
- st.session_state.board = chess.Board()
192
- if 'moves' not in st.session_state:
193
- st.session_state.moves = []
194
-
195
- def get_ai_move(prompt):
196
- """Obtient le coup de l'IA"""
197
- moves_count = len(st.session_state.moves)
198
- dynamic_max_length = calculate_max_length(moves_count)
199
- generator.config.max_length = dynamic_max_length
200
-
201
  try:
202
- if not prompt: # Premier coup
203
- response = generator.generate("1.")
204
- else:
205
- moves = prompt.split()
206
- last_moves = " ".join(moves[-4:]) # Garder seulement les 2 derniers coups
207
 
208
- if len(moves) % 2 == 0: # Tour des blancs
209
- next_move_num = f"{(len(moves)//2 + 1)}."
210
- response = generator.generate(f"{last_moves} {next_move_num}")
211
- else: # Tour des noirs
212
- response = generator.generate(f"{last_moves}")
213
-
214
- moves = response[0].split() if isinstance(response, list) else response.split()
215
- next_move = moves[-1]
216
- if '.' in next_move and len(moves) > 1:
217
- next_move = moves[-2]
218
 
219
- # Vérifier si le coup est légal
220
- try:
221
- move = st.session_state.board.parse_san(next_move)
222
- if move in st.session_state.board.legal_moves:
223
- return next_move
224
- except ValueError:
225
- pass
226
 
227
- # Si le coup n'est pas légal, jouer un coup aléatoire
228
- legal_moves = list(st.session_state.board.legal_moves)
229
- if legal_moves:
230
- random_move = random.choice(legal_moves)
231
- return st.session_state.board.san(random_move)
232
-
 
233
  except Exception as e:
234
- st.error(f"Erreur lors de la génération du coup: {str(e)}")
235
- return None
236
-
237
- def try_move(move_str):
238
- """Tente d'appliquer un coup"""
239
- try:
240
- clean_move = move_str.split('.')[-1].strip()
241
- move = st.session_state.board.parse_san(clean_move)
242
-
243
- if move in st.session_state.board.legal_moves:
244
- st.session_state.board.push(move)
245
- st.session_state.moves.append(clean_move)
246
- return True
247
- return False
248
- except ValueError:
249
- return False
250
 
251
- def get_game_string():
252
- """Obtient la notation de la partie"""
253
- result = []
254
- for i in range(0, len(st.session_state.moves), 2):
255
- move_num = i//2 + 1
256
- result.append(f"{move_num}.{st.session_state.moves[i]}")
257
- if i+1 < len(st.session_state.moves):
258
- result.append(st.session_state.moves[i+1])
259
- return " ".join(result)
260
-
261
- def handle_move(move_from, move_to):
262
- """Gère un coup joué via l'interface graphique"""
263
- move = chess.Move.from_uci(f"{move_from}{move_to}")
264
- if move in st.session_state.board.legal_moves:
265
- san_move = st.session_state.board.san(move)
266
- if try_move(san_move):
267
- return True
268
- return False
269
 
270
  # Initialisation
271
  try:
 
272
  generator = setup_inference()
 
 
273
  except Exception as e:
 
274
  st.error(f"Erreur d'initialisation: {str(e)}")
275
  st.stop()
276
 
277
- initialize_state()
278
-
279
  # Interface utilisateur
280
  st.title("♟️ Échecs contre IA")
281
 
282
  col1, col2 = st.columns([2, 1])
283
 
284
  with col1:
285
- # Échiquier interactif
286
  render_board()
287
 
288
- # Input texte alternatif
289
  move = st.text_input(
290
- "Ou saisissez votre coup ici",
291
  key=f"move_input_{len(st.session_state.moves)}",
292
  placeholder="ex: e4, Nf3, O-O"
293
  )
294
 
295
  with col2:
296
- # Informations de la partie
297
- st.subheader("Partie en cours")
298
- game_str = get_game_string()
299
- if game_str:
300
- st.text_area("Historique", value=game_str, height=100, label_visibility="collapsed")
301
-
302
  # Instructions
303
  st.markdown("""
304
  **Comment jouer:**
305
- - Glissez et déposez les pièces blanches
306
  - Ou utilisez la notation algébrique :
307
  - Pion: e4, d5
308
  - Cavalier: Nf3, Nc6
@@ -315,47 +166,15 @@ with col2:
315
 
316
  # Nouvelle partie
317
  if st.button("Nouvelle partie"):
 
318
  st.session_state.board = chess.Board()
319
  st.session_state.moves = []
320
  st.rerun()
321
 
322
- # Gestion des coups (glisser-déposer et texte)
323
- if st.session_state.get("chess_move"):
324
- move_data = st.session_state.chess_move
325
- st.session_state.chess_move = None
326
- if handle_move(move_data["from"], move_data["to"]):
327
- game_str = get_game_string()
328
- # Tour de l'IA
329
- with st.spinner("L'IA réfléchit..."):
330
- ai_move = get_ai_move(game_str)
331
- if ai_move and try_move(ai_move):
332
- if st.session_state.board.is_checkmate():
333
- st.success("Échec et mat!")
334
- elif st.session_state.board.is_game_over():
335
- st.info("Partie terminée!")
336
- else:
337
- st.error("Problème avec le coup de l'IA")
338
- st.rerun()
339
- else:
340
- st.error("Coup invalide")
341
-
342
- # Gestion des coups via input texte
343
- if move:
344
- if try_move(move):
345
- game_str = get_game_string()
346
- with st.spinner("L'IA réfléchit..."):
347
- ai_move = get_ai_move(game_str)
348
- if ai_move and try_move(ai_move):
349
- if st.session_state.board.is_checkmate():
350
- st.success("Échec et mat!")
351
- elif st.session_state.board.is_game_over():
352
- st.info("Partie terminée!")
353
- else:
354
- st.error("Problème avec le coup de l'IA")
355
- st.rerun()
356
- else:
357
- st.error("Coup invalide")
358
-
359
  # État du jeu
360
  if st.session_state.board.is_check():
361
- st.warning("⚠️ Échec!")
 
 
 
 
 
6
  import sys
7
  import random
8
  from streamlit.components.v1 import html
9
+ import logging
10
+
11
+ # Configuration des logs
12
+ logging.basicConfig(level=logging.DEBUG)
13
+ logger = logging.getLogger(__name__)
14
 
15
  # Configuration de la page
16
  st.set_page_config(page_title="Échecs contre IA", layout="wide")
17
 
18
  def render_board():
19
  """Rendre l'échiquier interactif"""
20
+ try:
21
+ logger.debug("Génération du SVG de l'échiquier...")
22
+ # Générer le SVG de l'échiquier
23
+ board_svg = chess.svg.board(
24
+ board=st.session_state.board,
25
+ size=400,
26
+ lastmove=st.session_state.board.peek() if st.session_state.board.move_stack else None,
27
+ )
28
+ logger.debug("SVG généré avec succès")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
 
30
+ logger.debug("Création du contenu HTML...")
31
+ # Code HTML/JS pour l'échiquier interactif
32
+ html_content = f'''
33
+ <div id="board-container" style="width: 400px; margin: auto;">
34
+ {board_svg}
35
+ </div>
36
+
37
+ <script>
38
+ console.log("Initialisation du JavaScript...");
39
+ const boardContainer = document.getElementById('board-container');
40
+ console.log("Container trouvé:", boardContainer);
41
+
42
+ // Ajouter des événements de débogage
43
+ boardContainer.addEventListener('mouseover', (e) => {{
44
+ console.log("Survol:", e.target);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
  }});
46
+
47
+ // Trouver toutes les pièces
48
+ const pieces = boardContainer.getElementsByClassName('piece');
49
+ console.log("Pièces trouvées:", pieces.length);
50
+
51
+ // Ajouter des gestionnaires d'événements à chaque pièce
52
+ Array.from(pieces).forEach(piece => {{
53
+ piece.style.cursor = 'grab';
54
+ piece.draggable = true;
55
+
56
+ piece.addEventListener('dragstart', (e) => {{
57
+ console.log("Début du glissement", e);
58
+ e.target.classList.add('dragging');
59
+ }});
60
+
61
+ piece.addEventListener('dragend', (e) => {{
62
+ console.log("Fin du glissement", e);
63
+ e.target.classList.remove('dragging');
64
+ }});
 
 
 
 
65
  }});
66
+ </script>
67
+
68
+ <style>
69
+ .piece {{
70
+ cursor: grab;
71
+ }}
72
+ .dragging {{
73
+ opacity: 0.5;
74
+ }}
75
+ </style>
76
+ '''
77
+ logger.debug("Contenu HTML créé")
78
+
79
+ # Afficher le contenu
80
+ logger.debug("Affichage du composant HTML...")
81
+ html(html_content, height=450)
82
+ logger.debug("Composant HTML affiché")
83
+
84
+ except Exception as e:
85
+ logger.error(f"Erreur lors du rendu de l'échiquier: {e}", exc_info=True)
86
+ st.error(f"Erreur lors de l'affichage de l'échiquier: {str(e)}")
87
 
88
+ # Setup du modèle
89
  @st.cache_resource
90
  def setup_inference():
91
  """Initialise le modèle d'IA"""
92
+ logger.info("Initialisation du modèle d'IA...")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93
  try:
94
+ if not os.path.exists('chess'):
95
+ logger.info("Clonage du répertoire git...")
96
+ git.Repo.clone_from('https://github.com/l-pommeret/chess.git', 'chess')
 
 
97
 
98
+ if 'chess' not in sys.path:
99
+ sys.path.append('chess')
 
 
 
 
 
 
 
 
100
 
101
+ from inference import InferenceConfig, ChessGenerator
 
 
 
 
 
 
102
 
103
+ config = InferenceConfig(
104
+ model_name="Zual/chess",
105
+ temperature=0.8,
106
+ max_length=6
107
+ )
108
+ logger.info("Modèle initialisé avec succès")
109
+ return ChessGenerator(config)
110
  except Exception as e:
111
+ logger.error(f"Erreur lors de l'initialisation du modèle: {e}", exc_info=True)
112
+ raise
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113
 
114
+ # Initialisation de l'état
115
+ def initialize_state():
116
+ """Initialise l'état du jeu"""
117
+ logger.debug("Initialisation de l'état du jeu...")
118
+ if 'board' not in st.session_state:
119
+ st.session_state.board = chess.Board()
120
+ logger.debug("Nouvel échiquier créé")
121
+ if 'moves' not in st.session_state:
122
+ st.session_state.moves = []
123
+ logger.debug("Liste des coups initialisée")
 
 
 
 
 
 
 
 
124
 
125
  # Initialisation
126
  try:
127
+ logger.info("Démarrage de l'application...")
128
  generator = setup_inference()
129
+ initialize_state()
130
+ logger.info("Initialisation terminée")
131
  except Exception as e:
132
+ logger.error(f"Erreur lors de l'initialisation: {e}", exc_info=True)
133
  st.error(f"Erreur d'initialisation: {str(e)}")
134
  st.stop()
135
 
 
 
136
  # Interface utilisateur
137
  st.title("♟️ Échecs contre IA")
138
 
139
  col1, col2 = st.columns([2, 1])
140
 
141
  with col1:
142
+ logger.debug("Rendu de l'échiquier...")
143
  render_board()
144
 
145
+ # Input texte comme méthode alternative
146
  move = st.text_input(
147
+ "Saisissez votre coup",
148
  key=f"move_input_{len(st.session_state.moves)}",
149
  placeholder="ex: e4, Nf3, O-O"
150
  )
151
 
152
  with col2:
 
 
 
 
 
 
153
  # Instructions
154
  st.markdown("""
155
  **Comment jouer:**
156
+ - Glissez et déposez les pièces
157
  - Ou utilisez la notation algébrique :
158
  - Pion: e4, d5
159
  - Cavalier: Nf3, Nc6
 
166
 
167
  # Nouvelle partie
168
  if st.button("Nouvelle partie"):
169
+ logger.info("Nouvelle partie demandée")
170
  st.session_state.board = chess.Board()
171
  st.session_state.moves = []
172
  st.rerun()
173
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
174
  # État du jeu
175
  if st.session_state.board.is_check():
176
+ st.warning("⚠️ Échec!")
177
+
178
+ # Afficher les logs dans Streamlit
179
+ if st.checkbox("Afficher les logs de débogage"):
180
+ st.code("\n".join(logging.getLogger().handlers[0].stream.getvalue().split("\n")[-50:]))