ChinaHamRadioQuest/Quest.py
2024-10-19 00:42:09 +08:00

219 lines
8.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
Quest.py
"""
import os
import tkinter as tk
import random
import json
import time
# 配置考卷
quest_config = {
'A': {'num': 30, 'time': 40, 'pass': 25},
'B': {'num': 50, 'time': 60, 'pass': 40},
'C': {'num': 80, 'time': 90, 'pass': 60}
}
font = ('Microsoft YaHei', 13)
# 模拟加载题目
def generate_quests(type_str):
# 模拟从JSON文件加载题目
with open(f'quests/quests_{type_str}.json', 'r', encoding='utf-8') as f:
json_content = json.load(f)
list_quest = []
for obj in json_content:
list_quest.append(Quest(obj))
return random.sample(list_quest, quest_config[type_str]['num'])
class Quest:
def __init__(self, json_obj):
self.index = json_obj['index']
self.question = json_obj['Q']
self.code = json_obj['I']
self.correct = json_obj['A']
self.options = [json_obj['A'], json_obj['B'], json_obj['C'], json_obj['D']]
self.random_options = random.sample(self.options, len(self.options))
class ExamApp:
def __init__(self, root):
self.next_btn = None
self.prev_btn = None
self.submit_restart_btn = None
self.ques_nav_frame = None
self.timer_score_label = None
self.correct_answer_label = None
self.option_buttons = None
self.options_var = None
self.question_label = None
self.root = root
self.root.title("模拟考试")
self.level = None
self.time_left = 0
self.current_quest_index = 0
self.quests = []
self.selected_answers = {}
self.is_submitted = False
# 初始化主界面
self.init_main_menu()
def init_main_menu(self):
self.clear_screen()
tk.Label(self.root, text="选择考试级别").pack(pady=20)
for level in ['A', 'B', 'C']:
tk.Button(self.root, text=f"级别 {level}", command=lambda l=level: self.start_exam(l)).pack(pady=10)
def start_exam(self, level):
self.level = level
self.time_left = quest_config[level]['time'] * 60 # 转换为秒
self.quests = generate_quests(level)
self.current_quest_index = 0
self.selected_answers = {i: None for i in range(len(self.quests))}
self.is_submitted = False
self.init_exam_screen()
def init_exam_screen(self):
self.clear_screen()
# 左边显示考题
left_frame = tk.Frame(self.root, borderwidth=2, relief=tk.GROOVE)
left_frame.pack(side=tk.LEFT, padx=20, pady=20, fill=tk.BOTH, expand=True)
left_frame.pack_propagate(False)
# 上一题、下一题按钮
page_frame = tk.Frame(left_frame)
self.prev_btn = tk.Button(page_frame, text="上一题", command=lambda: self.jump_to_question(self.current_quest_index - 1))
self.prev_btn.pack(side=tk.LEFT, padx=20, pady=20, anchor=tk.NW)
self.next_btn = tk.Button(page_frame, text="下一题", command=lambda: self.jump_to_question(self.current_quest_index + 1))
self.next_btn.pack(side=tk.LEFT, padx=20, pady=20, anchor=tk.NE)
exit_btn = tk.Button(page_frame, text="退出", command=self.init_main_menu)
exit_btn.pack(side=tk.RIGHT, padx=20, pady=20, anchor=tk.NE)
page_frame.pack(fill=tk.X)
self.question_label = tk.Label(left_frame, text="", width=400, wraplength=400, anchor=tk.W
, justify=tk.LEFT, font=font
, borderwidth=2, relief=tk.GROOVE)
self.question_label.pack(pady=20, padx=20)
self.question_label.pack_propagate(False)
self.options_var = tk.StringVar(value="")
self.option_buttons = []
for i in range(4):
btn = tk.Radiobutton(left_frame, text="", variable=self.options_var, value="", command=self.save_answer
, anchor=tk.W, font=font
, justify=tk.LEFT, wraplength=380)
btn.pack(anchor=tk.W, padx=20)
self.option_buttons.append(btn)
self.correct_answer_label = tk.Label(left_frame, text="", width=400, wraplength=400, anchor=tk.W, font=font
, justify=tk.LEFT)
self.correct_answer_label.pack(pady=20, padx=20)
self.correct_answer_label.pack_propagate(False)
# 右边显示考试状态
right_frame = tk.Frame(self.root, borderwidth=2, relief=tk.GROOVE, width=300)
right_frame.pack(side=tk.RIGHT, padx=20, pady=20, fill=tk.Y)
right_frame.pack_propagate(False)
self.timer_score_label = tk.Label(right_frame, text="剩余时间00:00")
self.timer_score_label.pack(pady=10)
self.ques_nav_frame = tk.Frame(right_frame)
self.ques_nav_frame.pack(pady=10)
self.update_timer()
self.update_question()
self.submit_restart_btn = tk.Button(right_frame, text="交卷", command=self.submit_exam)
self.submit_restart_btn.pack(pady=10)
def update_question(self):
quest = self.quests[self.current_quest_index]
self.question_label.config(text=f"Q{self.current_quest_index + 1} - ({quest.code})\n"
f"{quest.question}\n")
self.options_var.set(self.selected_answers[self.current_quest_index])
for i, opt in enumerate(quest.random_options):
self.option_buttons[i].config(text=opt, value=opt)
if self.options_var.get() == opt:
self.option_buttons[i].select()
else:
self.option_buttons[i].deselect()
if self.is_submitted:
self.option_buttons[i].config(state=tk.DISABLED)
if not self.is_submitted:
self.update_nav_buttons()
else:
# 显示正确答案
self.correct_answer_label.config(text=f"正确答案: \n{quest.correct}")
if self.current_quest_index == 0:
self.prev_btn.config(state=tk.DISABLED)
else:
self.prev_btn.config(state=tk.NORMAL)
if self.current_quest_index == len(self.quests) - 1:
self.next_btn.config(state=tk.DISABLED)
else:
self.next_btn.config(state=tk.NORMAL)
def update_nav_buttons(self):
for widget in self.ques_nav_frame.winfo_children():
widget.destroy()
if not self.is_submitted:
for i in range(len(self.quests)):
color = "yellow" if self.selected_answers[i] else "white"
btn = tk.Button(self.ques_nav_frame, text=f"{i + 1}", bg=color,
command=lambda idx=i: self.jump_to_question(idx))
btn.grid(row=i // 8, column=i % 8, sticky="nsew")
else:
for i in range(len(self.quests)):
quest = self.quests[i]
color = "green" if self.selected_answers[i] == quest.correct else "red"
btn = tk.Button(self.ques_nav_frame, text=f"{i + 1}", bg=color,
command=lambda idx=i: self.jump_to_question(idx))
btn.grid(row=i // 8, column=i % 8, sticky="nsew")
def save_answer(self):
self.selected_answers[self.current_quest_index] = self.options_var.get()
self.update_nav_buttons()
def jump_to_question(self, index):
self.current_quest_index = index
self.update_question()
def submit_exam(self):
self.is_submitted = True
self.update_question()
self.update_nav_buttons()
correct_count = sum(1 for i, quest in enumerate(self.quests) if self.selected_answers[i] == quest.correct)
pass_score = quest_config[self.level]['pass']
result_text = "通过" if correct_count >= pass_score else "未通过"
self.timer_score_label.config(text=f"得分: {correct_count}/{len(self.quests)} - {result_text}")
self.submit_restart_btn.config(text="重新开始", command=self.init_main_menu)
def update_timer(self):
if self.time_left > 0 and not self.is_submitted:
self.time_left -= 1
mins, secs = divmod(self.time_left, 60)
self.timer_score_label.config(text=f"剩余时间:{mins:02}:{secs:02}")
self.root.after(1000, self.update_timer)
def clear_screen(self):
for widget in self.root.winfo_children():
widget.destroy()
if __name__ == '__main__':
os.path.abspath(os.path.dirname(__file__))
root = tk.Tk()
app = ExamApp(root)
root.geometry("800x600")
root.minsize(800, 600)
root.resizable(True, True)
root.mainloop()