新增错题记录功能,错题出现的频率会更高

This commit is contained in:
zhangyuheng 2024-10-21 15:02:58 +08:00
parent b37063d4f0
commit 2985fb833e
4 changed files with 96 additions and 35 deletions

1
.gitignore vendored
View File

@ -160,3 +160,4 @@ cython_debug/
# and can be added to the global gitignore or merged into this file. For a more nuclear # 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. # option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/ #.idea/
/*.dat

6
Config.py Normal file
View File

@ -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}
}

65
Generator.py Normal file
View File

@ -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

View File

@ -3,41 +3,13 @@ Quest.py
""" """
import os import os
import tkinter as tk import tkinter as tk
import random import Generator
import json import Config
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) 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: class ExamApp:
def __init__(self, root): def __init__(self, root):
self.next_btn = None self.next_btn = None
@ -70,8 +42,8 @@ class ExamApp:
def start_exam(self, level): def start_exam(self, level):
self.level = level self.level = level
self.time_left = quest_config[level]['time'] * 60 # 转换为秒 self.time_left = Config.quest_config[level]['time'] * 60 # 转换为秒
self.quests = generate_quests(level) self.quests = Generator.generate_quests(level)
self.current_quest_index = 0 self.current_quest_index = 0
self.selected_answers = {i: None for i in range(len(self.quests))} self.selected_answers = {i: None for i in range(len(self.quests))}
self.is_submitted = False self.is_submitted = False
@ -151,6 +123,7 @@ class ExamApp:
else: else:
# 显示正确答案 # 显示正确答案
self.correct_answer_label.config(text=f"正确答案: \n{quest.correct}") self.correct_answer_label.config(text=f"正确答案: \n{quest.correct}")
self.update_nav_buttons()
if self.current_quest_index == 0: if self.current_quest_index == 0:
self.prev_btn.config(state=tk.DISABLED) self.prev_btn.config(state=tk.DISABLED)
@ -167,13 +140,23 @@ class ExamApp:
if not self.is_submitted: if not self.is_submitted:
for i in range(len(self.quests)): for i in range(len(self.quests)):
color = "yellow" if self.selected_answers[i] else "white" 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, btn = tk.Button(self.ques_nav_frame, text=f"{i + 1}", bg=color,
command=lambda idx=i: self.jump_to_question(idx)) command=lambda idx=i: self.jump_to_question(idx))
btn.grid(row=i // 8, column=i % 8, sticky="nsew") btn.grid(row=i // 8, column=i % 8, sticky="nsew")
else: else:
for i in range(len(self.quests)): for i in range(len(self.quests)):
quest = self.quests[i] 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, btn = tk.Button(self.ques_nav_frame, text=f"{i + 1}", bg=color,
command=lambda idx=i: self.jump_to_question(idx)) command=lambda idx=i: self.jump_to_question(idx))
btn.grid(row=i // 8, column=i % 8, sticky="nsew") btn.grid(row=i // 8, column=i % 8, sticky="nsew")
@ -190,9 +173,15 @@ class ExamApp:
self.is_submitted = True self.is_submitted = True
self.update_question() self.update_question()
self.update_nav_buttons() 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 "未通过" result_text = "通过" if correct_count >= pass_score else "未通过"
self.timer_score_label.config(text=f"得分: {correct_count}/{len(self.quests)} - {result_text}") self.timer_score_label.config(text=f"得分: {correct_count}/{len(self.quests)} - {result_text}")