forked from hermonochy/QuizMaster
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathquizcreator
More file actions
executable file
·285 lines (254 loc) · 12.9 KB
/
Copy pathquizcreator
File metadata and controls
executable file
·285 lines (254 loc) · 12.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
#!/usr/bin/env python3
import argparse
import json
import subprocess
import webbrowser
import modules.PySimpleGUI as sg
from modules.persistence import QuizQuestion
changes = False
questionList = []
current_file_path = None
difficultyList = [i for i in range(1, 6)]
menuBar = [
['&File', ['&Clear', '&New', '&Open', '&Save', 'Save &As', '---', '&Restart', '&Quit']],
['&Edit', ['&Add Question', '&Edit Question', 'Dupli&cate Question', '&Delete Question']],
['!&View', ['&Question Overview', '!&Editor', '&Raw JSON']],
['&Run', ['&Play']],
['&Help', ['!About', '&Tutorials', '&Github', ['QuizMaster &Repository', 'QuizMaster &Organisation']]]
]
mainWindowLayout = [
[sg.Menu(menuBar)],
[sg.Text("Title of Quiz:"), sg.InputText(key='quiz_name', tooltip="The title of the quiz that players will see.")],
[sg.Text("Difficulty:", tooltip="Select the difficulty level for this quiz (1 = Baby Quiz, 3 = Secondary School Level, 5 = Requires a professional understanding of the subject)."),
sg.Spin(difficultyList, key='difficulty', initial_value=3)],
[sg.Checkbox("Randomize Questions", default=False, tooltip="Randomize the order of questions when the quiz is played.", key='randomOrder')],
[sg.Listbox(questionList, size=(150, 20), auto_size_text = True, expand_x = True, expand_y = True, key='quizquestionentry', enable_events=True, tooltip="The list of the questions."),
sg.Text(key='textbox', size=(20, 10))],
[sg.Button("Add Question", tooltip="Add a new question."), sg.Button("Edit Question", tooltip="Select a question from the listbox to edit."),
sg.Button('Duplicate Question', tooltip="Duplicate the selected question"),
sg.Button("Delete Question", tooltip="Select a question from the listbox to delete.")],
[sg.Button('Quit')]
]
mainWindow = sg.Window('Quiz Creator', mainWindowLayout, return_keyboard_events=True,resizable = True, finalize=True, use_default_focus=False)
def make_questionEditorWindow():
questionEditorLayout = [
[sg.Text('Enter the question:'), sg.InputText(key='question', size=105, tooltip="Enter the question.")],
[sg.Text('Enter the correct answer:'), sg.InputText(key='correct_answer', size=75, tooltip="Enter the answer.")],
[sg.Text('Enter the wrong answers:'), sg.InputText(key='wrong_answers', size=100, tooltip="Enter some related but incorrect answers, separated by commas.")],
[sg.Text('Enter the time given to answer:'), sg.InputText(key='time_given', size=3, tooltip="Enter an integer number of seconds. Average is 10-20, default (if you leave it blank) is 15")],
[sg.Button('Add'), sg.Button('Cancel')]
]
questionEditorWindow = sg.Window('Question Editor', questionEditorLayout, finalize=True, keep_on_top=True)
return questionEditorWindow
def save_quiz(file_path):
with open(f'{file_path}', 'w') as file:
savedData = {
"title": mainWindow['quiz_name'].get(),
"difficulty": int(values['difficulty']),
"randomOrder": mainWindow['randomOrder'].get(),
"listOfQuestions": questionList
}
json.dump(savedData, file, default=vars)
def Add():
questionEditorWindow = make_questionEditorWindow()
editorEvent, editorValues = questionEditorWindow.read()
if editorEvent == 'Add':
question = editorValues['question']
correct_answer = editorValues['correct_answer']
wrong_answers = editorValues['wrong_answers'].split(',')
try:
time_given = int(editorValues['time_given'])
except ValueError:
time_given = 15
newquestion = QuizQuestion(question, correct_answer, wrong_answers, time_given)
questionList.append(newquestion)
questionEditorWindow.close()
mainWindow["quizquestionentry"].update(questionList)
if editorEvent == 'Cancel':
questionEditorWindow.close()
if __name__ == '__main__':
parser = argparse.ArgumentParser(
prog='QuizCreator',
description='Side program for QuizMaster, to make quizzes.',
)
parser.add_argument('-q', '--quizPath', nargs='?', const="")
args = parser.parse_args()
if args.quizPath is not None:
print("Loading quiz: ", args.quizPath)
try:
filename = args.quizPath
event = 'Open'
except Exception as ex:
print("Error:", ex)
sys.exit()
try:
with open(filename, 'r') as file:
try:
quizDicts = json.load(file)
questionList = []
for q in quizDicts["listOfQuestions"]:
qq = QuizQuestion(**q)
questionList.append(qq)
mainWindow["quizquestionentry"].update(questionList)
titleofquiz = quizDicts["title"]
mainWindow["quiz_name"].update(titleofquiz)
current_file_path = filename
except Exception as ex:
sg.Popup(f"Error with this file! {ex}", keep_on_top=True, auto_close=True, auto_close_duration=1.5)
print(f"Error with this file! {ex}")
except FileNotFoundError:
print(f"{filename} does not exist!")
while True:
event, values = mainWindow.read()
if event == 'quizquestionentry':
changes = True
if len(values['quizquestionentry']) > 0:
answers = ("correct answer:", values['quizquestionentry'][0].correctAnswer, "wrong answers:", values['quizquestionentry'][0].wrongAnswers)
outputtext = "Correct answer: \n" + answers[1] + "\n Wrong answers:\n" + str(answers[3])
mainWindow["textbox"].update(outputtext)
if event == sg.WIN_CLOSED or event == 'Quit':
if changes:
if sg.popup_yes_no("You have unsaved changes! Save before you leave?", keep_on_top=True) == "No":
break
else:
changes = False
save_quiz(current_file_path)
break
break
if values['difficulty'] not in difficultyList:
mainWindow["difficulty"].update(3)
if event == 'Restart':
try:
subprocess.Popen(["/usr/bin/python", "quizcreator",])
except:
subprocess.Popen(["/usr/bin/python3", "quizcreator"])
quit()
if event == 'Clear':
if changes:
if sg.popup_yes_no("You have unsaved changes! Save before you clear?", keep_on_top=True) == "No":
pass
else:
changes = False
save_quiz(current_file_path)
pass
pass
questionList = []
mainWindow["quizquestionentry"].update(questionList)
mainWindow["quiz_name"].update("")
current_file_path = None
if event == 'New':
try:
subprocess.Popen(["/usr/bin/python", "quizcreator",])
except:
subprocess.Popen(["/usr/bin/python3", "quizcreator"])
if event == 'Edit Question':
try:
index = int(''.join(map(str, mainWindow["quizquestionentry"].get_indexes())))
quizQuestion = questionList[index]
except ValueError:
try:
quizQuestion = questionList[-1]
except IndexError:
Add()
continue
questionEditorWindow = make_questionEditorWindow()
questionEditorWindow['question'].update(quizQuestion.question)
questionEditorWindow['correct_answer'].update(quizQuestion.correctAnswer)
questionEditorWindow['wrong_answers'].update(','.join(str(e) for e in quizQuestion.wrongAnswers))
questionEditorWindow['time_given'].update(quizQuestion.timeout)
editorEvent, editorValues = questionEditorWindow.read()
if editorEvent == 'Add':
question = editorValues['question']
correct_answer = editorValues['correct_answer']
wrong_answers = editorValues['wrong_answers'].split(',')
try:
time_given = int(editorValues['time_given'])
except ValueError:
time_given = 15
newquestion = QuizQuestion(question, correct_answer, wrong_answers, time_given)
newquestion = QuizQuestion(question, correct_answer, wrong_answers, 15)
questionList[index] = newquestion
questionEditorWindow.close()
mainWindow["quizquestionentry"].update(questionList)
if editorEvent == 'Cancel':
questionEditorWindow.close()
if event == 'Add Question' or event == 'a':
Add()
if event == 'Duplicate Question' or event == 'd':
try:
index = int(''.join(map(str, mainWindow["quizquestionentry"].get_indexes())))
quizQuestion = questionList[index]
new_question = QuizQuestion(quizQuestion.question, quizQuestion.correctAnswer, quizQuestion.wrongAnswers, quizQuestion.timeout)
questionList.append(new_question)
mainWindow["quizquestionentry"].update(questionList)
except ValueError:
sg.Popup("Select a question to duplicate!", keep_on_top=True, auto_close=True, auto_close_duration=1.5)
if event == 'Save As' or event == 's':
changes = False
current_file_path = sg.popup_get_file('', save_as=True, keep_on_top=True, no_window=True, initial_folder="Quizzes",
file_types=(("All JSON Files", "*.json"), ("All Files", "*.*")))
if current_file_path:
save_quiz(current_file_path)
if event == 'Save':
changes = False
try:
save_quiz(current_file_path)
except:
pass
if event == 'Open' or event == 'o':
if changes:
if sg.popup_yes_no("You have unsaved changes! Save before you leave?", keep_on_top=True) == "No":
pass
else:
changes = False
save_quiz(current_file_path)
pass
pass
try:
filename = sg.popup_get_file("Open quiz", initial_folder="Quizzes", no_window=True)
if filename:
with open(filename, 'r') as file:
try:
quizDicts = json.load(file)
questionList = []
for q in quizDicts["listOfQuestions"]:
qq = QuizQuestion(**q)
questionList.append(qq)
mainWindow["quizquestionentry"].update(questionList)
titleofquiz = quizDicts["title"]
mainWindow["quiz_name"].update(titleofquiz)
try:
difficulty = quizDicts["difficulty"]
randomOrder = quizDicts["randomOrder"]
mainWindow["randomOrder"].update(randomOrder)
mainWindow["difficulty"].update(difficulty)
except:
pass
current_file_path = filename
except Exception as e:
sg.Popup(f"Error with this file! {e}", keep_on_top=True, auto_close=True, auto_close_duration=1.5)
except TypeError:
pass
if event == 'Delete Question' or event == 'Delete':
try:
index = int(''.join(map(str, mainWindow["quizquestionentry"].get_indexes())))
questionList.pop(index)
except ValueError:
sg.Popup("Select a message to delete!")
mainWindow["quizquestionentry"].update(questionList)
if event == 'Play':
if questionList is not None:
save_quiz(current_file_path)
changes = False
try:
subprocess.Popen(["/usr/bin/python", "quiz.py", f"-q{current_file_path}", "-gpractice", "-v0.0"])
except:
subprocess.Popen(["/usr/bin/python3", "quiz.py", f"-q{current_file_path}", "-gpractice", "-v0.0"])
else:
sg.Popup("Please make a quiz first!", keep_on_top=True, auto_close=True, auto_close_duration=1.5)
if event == 'Tutorials':
webbrowser.open("https://quizmaster-world.github.io/Tutorials/QuizMaster.html")
if event == 'QuizMaster Repository':
webbrowser.open("https://github.com/hermonochy/QuizMaster/")
if event == 'QuizMaster Organisation':
webbrowser.open("https://github.com/QuizMaster-world/")