From 2985fb833e4c12550d625c255f90c4a1815346f6 Mon Sep 17 00:00:00 2001 From: zhangyuheng Date: Mon, 21 Oct 2024 15:02:58 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E9=94=99=E9=A2=98=E8=AE=B0?= =?UTF-8?q?=E5=BD=95=E5=8A=9F=E8=83=BD=EF=BC=8C=E9=94=99=E9=A2=98=E5=87=BA?= =?UTF-8?q?=E7=8E=B0=E7=9A=84=E9=A2=91=E7=8E=87=E4=BC=9A=E6=9B=B4=E9=AB=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + Config.py | 6 +++++ Generator.py | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++ Quest.py | 59 +++++++++++++++++++---------------------------- 4 files changed, 96 insertions(+), 35 deletions(-) create mode 100644 Config.py create mode 100644 Generator.py diff --git a/.gitignore b/.gitignore index 82f9275..5489642 100644 --- a/.gitignore +++ b/.gitignore @@ -160,3 +160,4 @@ cython_debug/ # and can be added to the global gitignore or merged into this file. For a more nuclear # option (not recommended) you can uncomment the following to ignore the entire idea folder. #.idea/ +/*.dat diff --git a/Config.py b/Config.py new file mode 100644 index 0000000..653f588 --- /dev/null +++ b/Config.py @@ -0,0 +1,6 @@ +# 配置考卷 +quest_config = { + 'A': {'num': 30, 'time': 40, 'pass': 25}, + 'B': {'num': 50, 'time': 60, 'pass': 40}, + 'C': {'num': 80, 'time': 90, 'pass': 60} +} \ No newline at end of file diff --git a/Generator.py b/Generator.py new file mode 100644 index 0000000..c51685d --- /dev/null +++ b/Generator.py @@ -0,0 +1,65 @@ +import json +import os +import random +import Config + +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)) + +weight_path = 'weight.dat' + +def enhance_weight(quest: Quest): + with open(weight_path, 'r') as f: + weight = json.load(f) + if quest.code in weight: + weight[quest.code] += 10 + else: + weight[quest.code] = 10 + with open(weight_path, 'w') as f: + json.dump(weight, f, ensure_ascii=False, indent=4) + pass + +def reduce_weight(quest: Quest): + with open(weight_path, 'r') as f: + weight = json.load(f) + if quest.code in weight: + weight[quest.code] -= 1 + else: + weight[quest.code] = -1 + with open(weight_path, 'w') as f: + json.dump(weight, f, ensure_ascii=False, indent=4) + pass + +# 模拟加载题目 +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 = [Quest(obj) for obj in json_content] + # load weight + weights = {} + if not os.path.exists(weight_path): + with open(weight_path, 'w') as f: + json.dump({}, f) + else: + with open(weight_path, 'r') as f: + weights = json.load(f) + # 将 list_quest 分为有权重和无权重的两部分 + list_quest_weighted = [quest for quest in list_quest if quest.code in weights] + list_quest_unweighted = [quest for quest in list_quest if quest.code not in weights] + # 有权中的按权重排序 + list_quest_weighted.sort(key=lambda x: weights[x.code], reverse=True) + list_quest = list_quest_unweighted + list_quest_weighted + # 根据权重随机选取题目 80% 的题目来自权重前 40% 的题目 20% 的题目来自权重后 60% 的题目 + num = Config.quest_config[type_str]['num'] # 要生成的题目数量 + top = int(num * 0.8) + quests = random.sample(list_quest[:top], top) + random.sample(list_quest[top:], num - top) + # 对 quests 中的题目再次随机排序 + random.shuffle(quests) + return quests \ No newline at end of file diff --git a/Quest.py b/Quest.py index 4ccc44e..eb65c53 100644 --- a/Quest.py +++ b/Quest.py @@ -3,41 +3,13 @@ Quest.py """ import os import tkinter as tk -import random -import json -import time +import Generator +import Config -# 配置考卷 -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 @@ -70,8 +42,8 @@ class ExamApp: def start_exam(self, level): self.level = level - self.time_left = quest_config[level]['time'] * 60 # 转换为秒 - self.quests = generate_quests(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 @@ -151,6 +123,7 @@ class ExamApp: 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) @@ -167,13 +140,23 @@ class ExamApp: 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 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") @@ -190,9 +173,15 @@ class ExamApp: 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) + 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 = quest_config[self.level]['pass'] + 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}")