批量收录题目功能完成

This commit is contained in:
weiye.wang 2024-04-14 20:26:24 +08:00
parent 4c38b4cca4
commit ad0e31b495
4 changed files with 397 additions and 80 deletions

View File

@ -0,0 +1,131 @@
# -*- coding: utf-8 -*-
################################################################################
## Form generated from reading UI file '批量收录题目.ui'
##
## Created by: Qt User Interface Compiler version 6.6.2
##
## WARNING! All changes made in this file will be lost when recompiling UI file!
################################################################################
from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
QMetaObject, QObject, QPoint, QRect,
QSize, QTime, QUrl, Qt)
from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
QFont, QFontDatabase, QGradient, QIcon,
QImage, QKeySequence, QLinearGradient, QPainter,
QPalette, QPixmap, QRadialGradient, QTransform)
from PySide6.QtWidgets import (QApplication, QCheckBox, QHBoxLayout, QLabel,
QLineEdit, QPushButton, QSizePolicy, QSplitter,
QWidget)
class Ui_Form(object):
def setupUi(self, Form):
if not Form.objectName():
Form.setObjectName(u"Form")
Form.resize(342, 109)
self.pushButton_exec = QPushButton(Form)
self.pushButton_exec.setObjectName(u"pushButton_exec")
self.pushButton_exec.setGeometry(QRect(260, 10, 71, 91))
font = QFont()
font.setBold(True)
self.pushButton_exec.setFont(font)
self.splitter = QSplitter(Form)
self.splitter.setObjectName(u"splitter")
self.splitter.setGeometry(QRect(10, 10, 241, 88))
self.splitter.setOrientation(Qt.Vertical)
self.widget = QWidget(self.splitter)
self.widget.setObjectName(u"widget")
self.horizontalLayout = QHBoxLayout(self.widget)
self.horizontalLayout.setObjectName(u"horizontalLayout")
self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
self.label = QLabel(self.widget)
self.label.setObjectName(u"label")
self.horizontalLayout.addWidget(self.label)
self.lineEdit_startingid = QLineEdit(self.widget)
self.lineEdit_startingid.setObjectName(u"lineEdit_startingid")
self.lineEdit_startingid.setDragEnabled(False)
self.lineEdit_startingid.setReadOnly(False)
self.horizontalLayout.addWidget(self.lineEdit_startingid)
self.splitter.addWidget(self.widget)
self.layoutWidget = QWidget(self.splitter)
self.layoutWidget.setObjectName(u"layoutWidget")
self.horizontalLayout_2 = QHBoxLayout(self.layoutWidget)
self.horizontalLayout_2.setObjectName(u"horizontalLayout_2")
self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0)
self.label_2 = QLabel(self.layoutWidget)
self.label_2.setObjectName(u"label_2")
self.horizontalLayout_2.addWidget(self.label_2)
self.lineEdit_editor = QLineEdit(self.layoutWidget)
self.lineEdit_editor.setObjectName(u"lineEdit_editor")
self.horizontalLayout_2.addWidget(self.lineEdit_editor)
self.splitter.addWidget(self.layoutWidget)
self.layoutWidget_2 = QWidget(self.splitter)
self.layoutWidget_2.setObjectName(u"layoutWidget_2")
self.horizontalLayout_3 = QHBoxLayout(self.layoutWidget_2)
self.horizontalLayout_3.setObjectName(u"horizontalLayout_3")
self.horizontalLayout_3.setContentsMargins(0, 0, 0, 0)
self.label_3 = QLabel(self.layoutWidget_2)
self.label_3.setObjectName(u"label_3")
self.horizontalLayout_3.addWidget(self.label_3)
self.lineEdit_origin = QLineEdit(self.layoutWidget_2)
self.lineEdit_origin.setObjectName(u"lineEdit_origin")
self.horizontalLayout_3.addWidget(self.lineEdit_origin)
self.splitter.addWidget(self.layoutWidget_2)
self.layoutWidget_3 = QWidget(self.splitter)
self.layoutWidget_3.setObjectName(u"layoutWidget_3")
self.horizontalLayout_4 = QHBoxLayout(self.layoutWidget_3)
self.horizontalLayout_4.setObjectName(u"horizontalLayout_4")
self.horizontalLayout_4.setContentsMargins(0, 0, 0, 0)
self.label_4 = QLabel(self.layoutWidget_3)
self.label_4.setObjectName(u"label_4")
self.horizontalLayout_4.addWidget(self.label_4)
self.lineEdit_suffix = QLineEdit(self.layoutWidget_3)
self.lineEdit_suffix.setObjectName(u"lineEdit_suffix")
self.lineEdit_suffix.setEnabled(False)
self.horizontalLayout_4.addWidget(self.lineEdit_suffix)
self.checkBox_suffix = QCheckBox(self.layoutWidget_3)
self.checkBox_suffix.setObjectName(u"checkBox_suffix")
self.horizontalLayout_4.addWidget(self.checkBox_suffix)
self.splitter.addWidget(self.layoutWidget_3)
self.retranslateUi(Form)
QMetaObject.connectSlotsByName(Form)
# setupUi
def retranslateUi(self, Form):
Form.setWindowTitle(QCoreApplication.translate("Form", u"\u6279\u91cf\u6536\u5f55\u65b0\u9898", None))
self.pushButton_exec.setText(QCoreApplication.translate("Form", u"\u6536\u5f55\u65b0\u9898", None))
self.label.setText(QCoreApplication.translate("Form", u"\u8d77\u59cbID", None))
self.lineEdit_startingid.setInputMask("")
self.lineEdit_startingid.setPlaceholderText(QCoreApplication.translate("Form", u"\u6570\u5b57\u9898\u53f7(\u901a\u5e38\u662f10000n+1)", None))
self.label_2.setText(QCoreApplication.translate("Form", u"\u7f16\u8f91\u8005", None))
self.lineEdit_editor.setPlaceholderText(QCoreApplication.translate("Form", u"\u7f16\u8f91\u8005\u59d3\u540d", None))
self.label_3.setText(QCoreApplication.translate("Form", u"\u6765\u6e90", None))
self.lineEdit_origin.setText(QCoreApplication.translate("Form", u"\u81ea\u62df\u9898\u76ee", None))
self.lineEdit_origin.setPlaceholderText(QCoreApplication.translate("Form", u"\u9898\u76ee\u6765\u6e90, \u901a\u5e38\u4e3a \u81ea\u62df\u9898\u76ee", None))
self.label_4.setText(QCoreApplication.translate("Form", u"\u540e\u7f00", None))
self.lineEdit_suffix.setText(QCoreApplication.translate("Form", u"\u8bd5\u9898", None))
self.lineEdit_suffix.setPlaceholderText(QCoreApplication.translate("Form", u"\u901a\u5e38\u4e3a \u8bd5\u9898", None))
self.checkBox_suffix.setText(QCoreApplication.translate("Form", u"\u4f7f\u7528\u540e\u7f00", None))
# retranslateUi

View File

@ -54,8 +54,13 @@ def SaveTextFile(data,filepath): #写入文本格式的文件
return filepath #返回文件名
def AppendTextFile(string,filepath): #在文本文件后添加内容
try:
with open(filepath,"a",encoding = "u8") as f:
f.write(string.strip()+"\n\n")
except:
makedir(os.path.split(filepath)[0])
with open(filepath,"w",encoding = "u8") as f:
f.write(string.strip()+"\n\n")
return filepath #返回文件名
def SortDict(adict): #按字典项顺序排序字典
@ -272,9 +277,13 @@ def spareIDs(): #返回空闲题号, 已更新为适合mariadb的版本
return output #返回的是一个多行的字符串, 每一行中含有一个空闲题号的闭区间
def NextSpareID(num,adict): #返回adict中下一个空闲的题号
def NextSpareID(num): #返回adict中下一个空闲的题号
mydb = connect(hostname = "wwylss.synology.me", port = "13306", username="root", pwd="Wwy@0018705", db = "tikutest")
mycursor = mydb.cursor()
mycursor.execute("SELECT ID FROM problems;")
idlist = [ret[0] for ret in mycursor.fetchall()]
num = int(num)
while str(num).zfill(6) in adict:
while str(num).zfill(6) in idlist:
num += 1
return num
@ -385,41 +394,10 @@ def CreateNewProblem(id,content,origin,dict,editor): # 构建一道新题目的
return NewProblem # 返回一道新题目的字典, 已赋新的ID, 内容, 来源和编辑者
def AddProblemstoDict(startingid,raworigin,problems,editor,indexdescription,thedict): #将来自GenerateProblemListFromString的列表中的题目添加到thedict字典
id = int(startingid)
currentsuffix = problems[0][1]
problemindex = 0
for p_and_suffix in problems:
p, suffix = p_and_suffix
pid = str(id).zfill(6)
if pid in thedict:
print("ID %s 已被使用."%pid)
return 1
else:
if suffix == currentsuffix:
problemindex += 1
else:
problemindex = 1
currentsuffix = suffix
origin = raworigin + suffix + indexdescription.strip() + ("" if indexdescription.strip() == "" else str(problemindex))
newproblem = CreateNewProblem(pid,p.strip(),origin,thedict,GetDate() + "\t" + editor)
if "blank" in p:
newproblem["genre"] = "填空题"
newproblem["space"] = ""
elif "bracket" in p:
newproblem["genre"] = "选择题"
newproblem["space"] = ""
else:
newproblem["genre"] = "解答题"
newproblem["space"] = "4em"
thedict[pid] = newproblem
maxsim,argmaxsim = detectmaxsim(pid,[pid],thedict)
print("已收录题号: %s, 最接近题目: %s, 相似程度: %.3f, 题目类型: %s, 题目来源: %s, 题目内容: %s"%(pid,argmaxsim,maxsim,newproblem["genre"],origin,p))
id += 1
return 0
def AddProblemstoDict2024(startingid,raworigin,problems,editor,indexed,thedict): #将来自GenerateProblemListFromString的列表中的题目添加到thedict字典, 返回题号列表(包括用老题号替代的题目)
def AddProblemstoDict2024(startingid,raworigin,problems,editor,indexed): #将来自GenerateProblemListFromString的列表中的题目添加到thedict字典, 返回题号列表(包括用老题号替代的题目)
mydb = connect(hostname = "wwylss.synology.me", port = "13306", username="root", pwd="Wwy@0018705", db = "tikutest")
mycursor = mydb.cursor()
idlist = []
id = int(startingid)
currentsuffix = problems[0][1]
@ -427,10 +405,6 @@ def AddProblemstoDict2024(startingid,raworigin,problems,editor,indexed,thedict):
for p_and_suffix_and_meta in problems:
p, suffix, meta = p_and_suffix_and_meta
pid = str(id).zfill(6)
if pid in thedict:
print("ID %s 已被使用."%pid)
return 1
else:
if suffix == currentsuffix:
problemindex += 1
else:
@ -441,36 +415,50 @@ def AddProblemstoDict2024(startingid,raworigin,problems,editor,indexed,thedict):
else:
origin = {"来源": raworigin + suffix}
if not "rep" in meta:
newproblem = CreateNewProblem(pid,p.strip(),origin,thedict,GetDate() + "\t" + editor)
if "blank" in p:
newproblem["genre"] = "填空题"
newproblem["space"] = ""
genre = "填空题"
space = ""
elif "bracket" in p:
newproblem["genre"] = "选择题"
newproblem["space"] = ""
genre = "选择题"
space = ""
else:
newproblem["genre"] = "解答题"
newproblem["space"] = "4em"
genre = "解答题"
space = "4em"
sql = "INSERT INTO problems (ID,content,genre,origin,space) VALUE (%s,%s,%s,%s,%s);"
val = (pid,p.strip(),genre,json.dumps(origin,ensure_ascii=False),space)
mycursor.execute(sql,val)
sql = "INSERT INTO edit_history (ID,date,editor) VALUE (%s,%s,%s);"
val = (pid,GetDate(),editor.strip())
mycursor.execute(sql,val)
if "same" in meta:
sql = "INSERT INTO same (ID,SAME_ID) VALUE (%s,%s);"
for sid in meta["same"]:
thedict[sid]["same"].append(pid)
newproblem["same"].append(sid)
val = (pid, sid)
if pid > sid:
val = (sid, pid)
mycursor.execute(sql,val)
if "related" in meta:
for sid in meta["related"]:
thedict[sid]["related"].append(pid)
newproblem["related"].append(sid)
sql = "INSERT INTO related (ID,RELATED_ID) VALUE (%s,%s);"
for rid in meta["related"]:
val = (pid, rid)
if pid > rid:
val = (rid, pid)
mycursor.execute(sql,val)
if "unrelated" in meta:
for sid in meta["unrelated"]:
thedict[sid]["unrelated"].append(pid)
newproblem["unrelated"].append(sid)
thedict[pid] = newproblem
maxsim,argmaxsim = detectmaxsim(pid,[pid],thedict)
print("已收录题号: %s, 最接近题目: %s, 相似程度: %.3f, 题目类型: %s, 题目来源: %s, 题目内容: %s"%(pid,argmaxsim,maxsim,newproblem["genre"],origin,p))
sql = "INSERT INTO unrelated (ID,UNRELATED_ID) VALUE (%s,%s);"
for uid in meta["unrelated"]:
val = (pid, uid)
if pid > uid:
val = (uid, pid)
mycursor.execute(sql,val)
print(f"已收录题号: {pid}, 题目类型: {genre}, 题目来源: {origin['来源'] + ('试题'+str(origin['题号'])) if '题号' in origin else ''}, 题目内容: {p.strip()}")
id += 1
idlist.append(pid)
else:
idlist.append(meta["rep"])
print(f"该题 {idlist[-1]} {p} 已在题库中, 不必收录.")
mydb.commit()
mydb.close()
return idlist
def CreateIDLinks(old_id_list,new_id_list,*thedict): #建立已有id和新id之间的联系, thedict为可选, 选中的话即为当前字典, 会从new_id_list中排除当前字典中有的项

View File

@ -0,0 +1,51 @@
from PySide6.QtWidgets import QWidget, QApplication, QFileDialog
from Ui_批量收录题目 import Ui_Form
from database_tools_2 import *
class MyWindow(QWidget,Ui_Form):
def __init__(self):
super().__init__()
self.setupUi(self)
self.bind()
def bind(self):
self.suffix_checked = True
self.checkBox_suffix.toggled.connect(self.togglesuffix)
self.pushButton_exec.clicked.connect(self.exec)
def togglesuffix(self):
self.suffix_checked = self.checkBox_suffix.isChecked()
if self.suffix_checked:
self.lineEdit_suffix.setEnabled(True)
else:
self.lineEdit_suffix.setDisabled(True)
def exec(self):
starting_id = self.lineEdit_startingid.text().strip().zfill(6)
raworigin = self.lineEdit_origin.text().strip()
filename = "临时文件/新题比对.tex" #题目的来源.tex文件
editor = self.lineEdit_editor.text().strip()
if self.checkBox_suffix.isChecked():
Indexed = True
else:
Indexed = False
idlistpath = "文本文件/新题收录列表.txt"
problems = GenerateProblemListFromString2024(ReadTextFile(filename))
# pro_dict = load_dict("../题库0.3/Problems.json")
idlist = AddProblemstoDict2024(NextSpareID(starting_id),raworigin,problems,editor,Indexed)
# save_dict(SortDict(pro_dict),r"../题库0.3/Problems.json")
AppendTextFile(f"{GetDate()}-{GetTime()}\n{generate_exp(idlist)}",idlistpath)
os.system(f"code {idlistpath}")
if __name__ == '__main__':
app = QApplication([])
windows = MyWindow()
windows.show()
app.exec()

View File

@ -0,0 +1,147 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Form</class>
<widget class="QWidget" name="Form">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>342</width>
<height>109</height>
</rect>
</property>
<property name="windowTitle">
<string>批量收录新题</string>
</property>
<widget class="QPushButton" name="pushButton_exec">
<property name="geometry">
<rect>
<x>260</x>
<y>10</y>
<width>71</width>
<height>91</height>
</rect>
</property>
<property name="font">
<font>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>收录新题</string>
</property>
</widget>
<widget class="QSplitter" name="splitter">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>241</width>
<height>88</height>
</rect>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<widget class="QWidget" name="">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>起始ID</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineEdit_startingid">
<property name="inputMask">
<string/>
</property>
<property name="dragEnabled">
<bool>false</bool>
</property>
<property name="readOnly">
<bool>false</bool>
</property>
<property name="placeholderText">
<string>数字题号(通常是10000n+1)</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="layoutWidget">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>编辑者</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineEdit_editor">
<property name="placeholderText">
<string>编辑者姓名</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="layoutWidget_2">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>来源</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineEdit_origin">
<property name="text">
<string>自拟题目</string>
</property>
<property name="placeholderText">
<string>题目来源, 通常为 自拟题目</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="layoutWidget_3">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QLabel" name="label_4">
<property name="text">
<string>后缀</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineEdit_suffix">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>试题</string>
</property>
<property name="placeholderText">
<string>通常为 试题</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBox_suffix">
<property name="text">
<string>使用后缀</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</widget>
<resources/>
<connections/>
</ui>