TroglodyteDerivations commited on
Commit
3f63052
·
verified ·
1 Parent(s): 3f46706

Upload 3 files

Browse files
Files changed (4) hide show
  1. .gitattributes +1 -0
  2. app.py +326 -0
  3. demo.mp4 +3 -0
  4. requirements.txt +1 -0
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ demo.mp4 filter=lfs diff=lfs merge=lfs -text
app.py ADDED
@@ -0,0 +1,326 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sys
2
+ import math
3
+ from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout,
4
+ QHBoxLayout, QLabel, QPushButton, QRadioButton,
5
+ QButtonGroup, QMessageBox, QProgressBar, QFrame)
6
+ from PyQt5.QtCore import Qt, QTimer
7
+ from PyQt5.QtGui import QFont, QPalette
8
+
9
+ class AStarQuizGame(QMainWindow):
10
+ def __init__(self):
11
+ super().__init__()
12
+ self.initUI()
13
+ self.initQuestions()
14
+ self.current_question = 0
15
+ self.score = 0
16
+ self.showQuestion()
17
+
18
+ def initUI(self):
19
+ self.setWindowTitle("A* Heuristic Functions Quiz Game")
20
+ self.setGeometry(100, 100, 800, 600)
21
+ self.setStyleSheet("""
22
+ QMainWindow {
23
+ background: qlineargradient(x1:0, y1:0, x2:1, y2:1,
24
+ stop:0 #2c3e50, stop:1 #34495e);
25
+ }
26
+ QLabel {
27
+ color: white;
28
+ background: transparent;
29
+ }
30
+ QRadioButton {
31
+ color: white;
32
+ background: transparent;
33
+ padding: 8px;
34
+ }
35
+ QRadioButton::indicator {
36
+ width: 20px;
37
+ height: 20px;
38
+ border-radius: 10px;
39
+ border: 2px solid #3498db;
40
+ }
41
+ QRadioButton::indicator:checked {
42
+ background-color: #3498db;
43
+ }
44
+ QPushButton {
45
+ background-color: #3498db;
46
+ color: white;
47
+ border: none;
48
+ padding: 12px 24px;
49
+ border-radius: 5px;
50
+ font-size: 14px;
51
+ font-weight: bold;
52
+ }
53
+ QPushButton:hover {
54
+ background-color: #2980b9;
55
+ }
56
+ QPushButton:disabled {
57
+ background-color: #7f8c8d;
58
+ }
59
+ QFrame {
60
+ background-color: rgba(44, 62, 80, 0.9);
61
+ border-radius: 10px;
62
+ border: 2px solid #3498db;
63
+ }
64
+ QProgressBar {
65
+ border: 2px solid #3498db;
66
+ border-radius: 5px;
67
+ text-align: center;
68
+ color: white;
69
+ background-color: #2c3e50;
70
+ }
71
+ QProgressBar::chunk {
72
+ background-color: #3498db;
73
+ width: 20px;
74
+ }
75
+ """)
76
+
77
+ # Central widget
78
+ central_widget = QWidget()
79
+ self.setCentralWidget(central_widget)
80
+ layout = QVBoxLayout(central_widget)
81
+ layout.setSpacing(20)
82
+ layout.setContentsMargins(30, 30, 30, 30)
83
+
84
+ # Title
85
+ title = QLabel("A* Heuristic Functions Quiz")
86
+ title.setAlignment(Qt.AlignCenter)
87
+ title.setFont(QFont("Arial", 24, QFont.Bold))
88
+ layout.addWidget(title)
89
+
90
+ # Score and progress
91
+ score_layout = QHBoxLayout()
92
+ self.score_label = QLabel("Score: 0/0")
93
+ self.score_label.setFont(QFont("Arial", 14))
94
+ self.progress_bar = QProgressBar()
95
+ self.progress_bar.setMaximum(100)
96
+ self.progress_bar.setMinimum(0)
97
+ score_layout.addWidget(self.score_label)
98
+ score_layout.addWidget(self.progress_bar)
99
+ layout.addLayout(score_layout)
100
+
101
+ # Question frame
102
+ self.question_frame = QFrame()
103
+ question_frame_layout = QVBoxLayout(self.question_frame)
104
+ question_frame_layout.setSpacing(15)
105
+
106
+ self.question_label = QLabel()
107
+ self.question_label.setWordWrap(True)
108
+ self.question_label.setFont(QFont("Arial", 16))
109
+ self.question_label.setAlignment(Qt.AlignCenter)
110
+ question_frame_layout.addWidget(self.question_label)
111
+
112
+ # Options
113
+ self.option_group = QButtonGroup()
114
+ self.options_layout = QVBoxLayout()
115
+ self.option_buttons = []
116
+ for i in range(4):
117
+ radio = QRadioButton()
118
+ radio.setFont(QFont("Arial", 12))
119
+ self.option_group.addButton(radio, i)
120
+ self.options_layout.addWidget(radio)
121
+ self.option_buttons.append(radio)
122
+
123
+ question_frame_layout.addLayout(self.options_layout)
124
+ layout.addWidget(self.question_frame)
125
+
126
+ # Buttons
127
+ buttons_layout = QHBoxLayout()
128
+ self.prev_button = QPushButton("Previous")
129
+ self.next_button = QPushButton("Next")
130
+ self.submit_button = QPushButton("Submit Answer")
131
+ self.restart_button = QPushButton("Restart Quiz")
132
+
133
+ self.prev_button.clicked.connect(self.previousQuestion)
134
+ self.next_button.clicked.connect(self.nextQuestion)
135
+ self.submit_button.clicked.connect(self.submitAnswer)
136
+ self.restart_button.clicked.connect(self.restartQuiz)
137
+
138
+ buttons_layout.addWidget(self.prev_button)
139
+ buttons_layout.addWidget(self.next_button)
140
+ buttons_layout.addWidget(self.submit_button)
141
+ buttons_layout.addWidget(self.restart_button)
142
+ layout.addLayout(buttons_layout)
143
+
144
+ # Explanation
145
+ self.explanation_label = QLabel()
146
+ self.explanation_label.setWordWrap(True)
147
+ self.explanation_label.setFont(QFont("Arial", 12))
148
+ self.explanation_label.setStyleSheet("color: #f39c12; background: transparent;")
149
+ self.explanation_label.setAlignment(Qt.AlignCenter)
150
+ self.explanation_label.hide()
151
+ layout.addWidget(self.explanation_label)
152
+
153
+ def initQuestions(self):
154
+ self.questions = [
155
+ {
156
+ "question": "Which heuristic function is calculated as |x₁ - x₂| + |y₁ - y₂|?",
157
+ "options": ["Euclidean Distance", "Manhattan Distance", "Chebyshev Distance", "Hamming Distance"],
158
+ "correct": 1,
159
+ "explanation": "Manhattan Distance is calculated as the sum of absolute differences in x and y coordinates: |x₁ - x₂| + |y₁ - y₂|"
160
+ },
161
+ {
162
+ "question": "Which heuristic is optimal for grid-based movement with 4-direction movement (up, down, left, right)?",
163
+ "options": ["Euclidean Distance", "Manhattan Distance", "Chebyshev Distance", "All are equally good"],
164
+ "correct": 1,
165
+ "explanation": "Manhattan Distance is optimal for 4-direction grid movement as it exactly matches the movement cost."
166
+ },
167
+ {
168
+ "question": "What is the formula for Euclidean Distance between points (x₁,y₁) and (x₂,y₂)?",
169
+ "options": [
170
+ "|x₁ - x₂| + |y₁ - y₂|",
171
+ "√((x₁ - x₂)² + (y₁ - y₂)²)",
172
+ "max(|x₁ - x₂|, |y₁ - y₂|)",
173
+ "(x₁ - x₂)² + (y₁ - y₂)²"
174
+ ],
175
+ "correct": 1,
176
+ "explanation": "Euclidean Distance uses the Pythagorean theorem: √((x₁ - x₂)² + (y₁ - y₂)²)"
177
+ },
178
+ {
179
+ "question": "Which heuristic is calculated as max(|x₁ - x₂|, |y₁ - y₂|)?",
180
+ "options": ["Euclidean Distance", "Manhattan Distance", "Chebyshev Distance", "Minkowski Distance"],
181
+ "correct": 2,
182
+ "explanation": "Chebyshev Distance takes the maximum of the absolute differences in coordinates."
183
+ },
184
+ {
185
+ "question": "For 8-direction movement (including diagonals), which heuristic is most appropriate?",
186
+ "options": ["Euclidean Distance", "Manhattan Distance", "Chebyshev Distance", "Manhattan is always better"],
187
+ "correct": 2,
188
+ "explanation": "Chebyshev Distance is optimal for 8-direction movement as diagonal moves have cost equal to the maximum coordinate difference."
189
+ },
190
+ {
191
+ "question": "Which heuristic is always admissible (never overestimates) for grid-based pathfinding?",
192
+ "options": [
193
+ "Only Manhattan Distance",
194
+ "Only Euclidean Distance",
195
+ "Both Manhattan and Euclidean",
196
+ "All three: Manhattan, Euclidean, and Chebyshev"
197
+ ],
198
+ "correct": 3,
199
+ "explanation": "All three heuristics are admissible for grid-based pathfinding as they never overestimate the actual cost."
200
+ },
201
+ {
202
+ "question": "In terms of computation cost, which heuristic is generally the fastest to calculate?",
203
+ "options": ["Euclidean Distance", "Manhattan Distance", "Chebyshev Distance", "They are all similar"],
204
+ "correct": 1,
205
+ "explanation": "Manhattan Distance is fastest as it only uses absolute values and addition, avoiding square roots and powers."
206
+ },
207
+ {
208
+ "question": "Which heuristic would be most suitable for a game with diagonal movement costing the same as horizontal/vertical?",
209
+ "options": ["Euclidean Distance", "Manhattan Distance", "Chebyshev Distance", "None are suitable"],
210
+ "correct": 2,
211
+ "explanation": "Chebyshev Distance is perfect when diagonal moves cost the same as horizontal/vertical moves."
212
+ }
213
+ ]
214
+
215
+ self.user_answers = [None] * len(self.questions)
216
+ self.answered = [False] * len(self.questions)
217
+
218
+ def showQuestion(self):
219
+ question_data = self.questions[self.current_question]
220
+ self.question_label.setText(f"Question {self.current_question + 1}: {question_data['question']}")
221
+
222
+ for i, option in enumerate(question_data['options']):
223
+ self.option_buttons[i].setText(option)
224
+ self.option_buttons[i].setChecked(self.user_answers[self.current_question] == i)
225
+
226
+ self.explanation_label.hide()
227
+ self.updateNavigation()
228
+ self.updateProgress()
229
+
230
+ def updateNavigation(self):
231
+ self.prev_button.setEnabled(self.current_question > 0)
232
+ self.next_button.setEnabled(self.current_question < len(self.questions) - 1)
233
+
234
+ if self.answered[self.current_question]:
235
+ self.submit_button.setEnabled(False)
236
+ self.explanation_label.show()
237
+ else:
238
+ self.submit_button.setEnabled(True)
239
+
240
+ def updateProgress(self):
241
+ # FIX: Convert float to int for progress bar
242
+ progress = int((self.current_question + 1) / len(self.questions) * 100)
243
+ self.progress_bar.setValue(progress)
244
+ self.score_label.setText(f"Score: {self.score}/{len(self.questions)}")
245
+
246
+ def nextQuestion(self):
247
+ if self.current_question < len(self.questions) - 1:
248
+ self.current_question += 1
249
+ self.showQuestion()
250
+
251
+ def previousQuestion(self):
252
+ if self.current_question > 0:
253
+ self.current_question -= 1
254
+ self.showQuestion()
255
+
256
+ def submitAnswer(self):
257
+ selected = self.option_group.checkedId()
258
+ if selected == -1:
259
+ QMessageBox.warning(self, "No Selection", "Please select an answer before submitting.")
260
+ return
261
+
262
+ self.user_answers[self.current_question] = selected
263
+ self.answered[self.current_question] = True
264
+
265
+ question_data = self.questions[self.current_question]
266
+ is_correct = (selected == question_data['correct'])
267
+
268
+ # Update score
269
+ if is_correct:
270
+ self.score += 1
271
+
272
+ # Show explanation
273
+ self.explanation_label.setText(
274
+ f"{'✓ Correct!' if is_correct else '✗ Incorrect!'} {question_data['explanation']}"
275
+ )
276
+ self.explanation_label.show()
277
+
278
+ self.updateNavigation()
279
+ self.updateProgress()
280
+
281
+ # Auto-advance if not last question
282
+ if self.current_question < len(self.questions) - 1:
283
+ QTimer.singleShot(2000, self.nextQuestion)
284
+ else:
285
+ self.showFinalScore()
286
+
287
+ def showFinalScore(self):
288
+ percentage = (self.score / len(self.questions)) * 100
289
+ if percentage >= 80:
290
+ message = "Excellent! You're an A* heuristic expert! 🎉"
291
+ elif percentage >= 60:
292
+ message = "Good job! You have a solid understanding! 👍"
293
+ else:
294
+ message = "Keep practicing! Review the heuristics and try again! 📚"
295
+
296
+ QMessageBox.information(
297
+ self,
298
+ "Quiz Completed!",
299
+ f"Final Score: {self.score}/{len(self.questions)} ({percentage:.1f}%)\n\n{message}"
300
+ )
301
+
302
+ def restartQuiz(self):
303
+ self.current_question = 0
304
+ self.score = 0
305
+ self.user_answers = [None] * len(self.questions)
306
+ self.answered = [False] * len(self.questions)
307
+ self.option_group.setExclusive(False)
308
+ for button in self.option_buttons:
309
+ button.setChecked(False)
310
+ self.option_group.setExclusive(True)
311
+ self.showQuestion()
312
+
313
+ def main():
314
+ app = QApplication(sys.argv)
315
+
316
+ # Set application-wide font
317
+ font = QFont("Arial", 10)
318
+ app.setFont(font)
319
+
320
+ game = AStarQuizGame()
321
+ game.show()
322
+
323
+ sys.exit(app.exec_())
324
+
325
+ if __name__ == '__main__':
326
+ main()
demo.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:bf0add0dfd274b9af62bfda917116ee5b210b7d9b5de52b597015f86da248ed9
3
+ size 10649648
requirements.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ PyQt5