ChinaHamRadioQuest/Quest.py

213 lines
8.3 KiB
Python
Raw Permalink 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 Generator
import Config
font = ('Microsoft YaHei', 13)
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()
self.is_submitted = True
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 = Config.quest_config[level]['time'] * 60 # 转换为秒
self.quests = Generator.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}")
self.update_nav_buttons()
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"
if self.current_quest_index == i:
color = "gray"
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"
color = "green"
if self.selected_answers[i] != quest.correct:
color = "red"
if self.current_quest_index == i:
if color == "green":
color = "dark green"
else:
color = "dark 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 = 0
for i, quest in enumerate(self.quests):
if self.selected_answers[i] == quest.correct:
correct_count += 1
Generator.reduce_weight(quest)
else:
Generator.enhance_weight(quest)
pass_score = Config.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)
elif self.is_submitted:
return
else:
self.submit_exam()
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()