From f4834f462d2439a936a6a3783b139e72bfb2f504 Mon Sep 17 00:00:00 2001 From: wangweiye7840 Date: Mon, 15 Apr 2024 13:18:10 +0800 Subject: [PATCH] =?UTF-8?q?=E7=B3=BB=E5=88=97=E8=AE=B2=E4=B9=89=E7=94=9F?= =?UTF-8?q?=E6=88=90=20=E8=BF=81=E7=A7=BB=E5=AE=8C=E5=96=84=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 工具v3/Ui_系列讲义生成.py | 229 ++++++++++++++++++++++++++ 工具v3/database_tools_2.py | 130 ++++++++++++--- 工具v3/系列讲义生成.py | 160 ++++++++++++++++++ 工具v3/系列讲义生成.ui | 322 +++++++++++++++++++++++++++++++++++++ 4 files changed, 816 insertions(+), 25 deletions(-) create mode 100644 工具v3/Ui_系列讲义生成.py create mode 100644 工具v3/系列讲义生成.py create mode 100644 工具v3/系列讲义生成.ui diff --git a/工具v3/Ui_系列讲义生成.py b/工具v3/Ui_系列讲义生成.py new file mode 100644 index 00000000..56e670ec --- /dev/null +++ b/工具v3/Ui_系列讲义生成.py @@ -0,0 +1,229 @@ +# -*- 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, QRadioButton, QSizePolicy, + QVBoxLayout, QWidget) + +class Ui_Form(object): + def setupUi(self, Form): + if not Form.objectName(): + Form.setObjectName(u"Form") + Form.resize(511, 394) + self.lineEdit_regex = QLineEdit(Form) + self.lineEdit_regex.setObjectName(u"lineEdit_regex") + self.lineEdit_regex.setGeometry(QRect(100, 20, 231, 20)) + self.label = QLabel(Form) + self.label.setObjectName(u"label") + self.label.setGeometry(QRect(10, 20, 91, 16)) + self.label_2 = QLabel(Form) + self.label_2.setObjectName(u"label_2") + self.label_2.setGeometry(QRect(340, 20, 171, 16)) + self.pushButton_exec = QPushButton(Form) + self.pushButton_exec.setObjectName(u"pushButton_exec") + self.pushButton_exec.setGeometry(QRect(280, 250, 221, 131)) + font = QFont() + font.setBold(True) + self.pushButton_exec.setFont(font) + self.label_3 = QLabel(Form) + self.label_3.setObjectName(u"label_3") + self.label_3.setGeometry(QRect(10, 50, 61, 16)) + self.lineEdit_path = QLineEdit(Form) + self.lineEdit_path.setObjectName(u"lineEdit_path") + self.lineEdit_path.setGeometry(QRect(10, 70, 491, 20)) + self.pushButton_SelectPath = QPushButton(Form) + self.pushButton_SelectPath.setObjectName(u"pushButton_SelectPath") + self.pushButton_SelectPath.setGeometry(QRect(430, 40, 75, 24)) + self.verticalLayoutWidget = QWidget(Form) + self.verticalLayoutWidget.setObjectName(u"verticalLayoutWidget") + self.verticalLayoutWidget.setGeometry(QRect(10, 110, 81, 111)) + self.verticalLayout = QVBoxLayout(self.verticalLayoutWidget) + self.verticalLayout.setObjectName(u"verticalLayout") + self.verticalLayout.setContentsMargins(0, 0, 0, 0) + self.label_4 = QLabel(self.verticalLayoutWidget) + self.label_4.setObjectName(u"label_4") + self.label_4.setAlignment(Qt.AlignLeading|Qt.AlignLeft|Qt.AlignVCenter) + + self.verticalLayout.addWidget(self.label_4) + + self.radioButton_student = QRadioButton(self.verticalLayoutWidget) + self.radioButton_student.setObjectName(u"radioButton_student") + self.radioButton_student.setChecked(True) + + self.verticalLayout.addWidget(self.radioButton_student) + + self.radioButton_teacher = QRadioButton(self.verticalLayoutWidget) + self.radioButton_teacher.setObjectName(u"radioButton_teacher") + + self.verticalLayout.addWidget(self.radioButton_teacher) + + self.verticalLayoutWidget_2 = QWidget(Form) + self.verticalLayoutWidget_2.setObjectName(u"verticalLayoutWidget_2") + self.verticalLayoutWidget_2.setGeometry(QRect(110, 110, 151, 271)) + self.verticalLayout_2 = QVBoxLayout(self.verticalLayoutWidget_2) + self.verticalLayout_2.setObjectName(u"verticalLayout_2") + self.verticalLayout_2.setContentsMargins(0, 0, 0, 0) + self.label_5 = QLabel(self.verticalLayoutWidget_2) + self.label_5.setObjectName(u"label_5") + + self.verticalLayout_2.addWidget(self.label_5) + + self.checkBox_space = QCheckBox(self.verticalLayoutWidget_2) + self.checkBox_space.setObjectName(u"checkBox_space") + + self.verticalLayout_2.addWidget(self.checkBox_space) + + self.checkBox_ans = QCheckBox(self.verticalLayoutWidget_2) + self.checkBox_ans.setObjectName(u"checkBox_ans") + + self.verticalLayout_2.addWidget(self.checkBox_ans) + + self.checkBox_objs = QCheckBox(self.verticalLayoutWidget_2) + self.checkBox_objs.setObjectName(u"checkBox_objs") + self.checkBox_objs.setCheckable(True) + self.checkBox_objs.setTristate(False) + + self.verticalLayout_2.addWidget(self.checkBox_objs) + + self.checkBox_tags = QCheckBox(self.verticalLayoutWidget_2) + self.checkBox_tags.setObjectName(u"checkBox_tags") + + self.verticalLayout_2.addWidget(self.checkBox_tags) + + self.checkBox_solution = QCheckBox(self.verticalLayoutWidget_2) + self.checkBox_solution.setObjectName(u"checkBox_solution") + + self.verticalLayout_2.addWidget(self.checkBox_solution) + + self.checkBox_usages = QCheckBox(self.verticalLayoutWidget_2) + self.checkBox_usages.setObjectName(u"checkBox_usages") + + self.verticalLayout_2.addWidget(self.checkBox_usages) + + self.checkBox_origin = QCheckBox(self.verticalLayoutWidget_2) + self.checkBox_origin.setObjectName(u"checkBox_origin") + + self.verticalLayout_2.addWidget(self.checkBox_origin) + + self.checkBox_remark = QCheckBox(self.verticalLayoutWidget_2) + self.checkBox_remark.setObjectName(u"checkBox_remark") + + self.verticalLayout_2.addWidget(self.checkBox_remark) + + self.verticalLayoutWidget_3 = QWidget(Form) + self.verticalLayoutWidget_3.setObjectName(u"verticalLayoutWidget_3") + self.verticalLayoutWidget_3.setGeometry(QRect(280, 110, 222, 121)) + self.verticalLayout_usagepanel = QVBoxLayout(self.verticalLayoutWidget_3) + self.verticalLayout_usagepanel.setObjectName(u"verticalLayout_usagepanel") + self.verticalLayout_usagepanel.setContentsMargins(0, 0, 0, 0) + self.label_6 = QLabel(self.verticalLayoutWidget_3) + self.label_6.setObjectName(u"label_6") + + self.verticalLayout_usagepanel.addWidget(self.label_6) + + self.horizontalLayout = QHBoxLayout() + self.horizontalLayout.setObjectName(u"horizontalLayout") + self.label_9 = QLabel(self.verticalLayoutWidget_3) + self.label_9.setObjectName(u"label_9") + + self.horizontalLayout.addWidget(self.label_9) + + self.lineEdit_high = QLineEdit(self.verticalLayoutWidget_3) + self.lineEdit_high.setObjectName(u"lineEdit_high") + self.lineEdit_high.setEnabled(True) + + self.horizontalLayout.addWidget(self.lineEdit_high) + + self.label_10 = QLabel(self.verticalLayoutWidget_3) + self.label_10.setObjectName(u"label_10") + + self.horizontalLayout.addWidget(self.label_10) + + self.lineEdit_low = QLineEdit(self.verticalLayoutWidget_3) + self.lineEdit_low.setObjectName(u"lineEdit_low") + + self.horizontalLayout.addWidget(self.lineEdit_low) + + + self.verticalLayout_usagepanel.addLayout(self.horizontalLayout) + + self.label_7 = QLabel(self.verticalLayoutWidget_3) + self.label_7.setObjectName(u"label_7") + + self.verticalLayout_usagepanel.addWidget(self.label_7) + + self.lineEdit_grades = QLineEdit(self.verticalLayoutWidget_3) + self.lineEdit_grades.setObjectName(u"lineEdit_grades") + + self.verticalLayout_usagepanel.addWidget(self.lineEdit_grades) + + self.verticalLayoutWidget_4 = QWidget(Form) + self.verticalLayoutWidget_4.setObjectName(u"verticalLayoutWidget_4") + self.verticalLayoutWidget_4.setGeometry(QRect(10, 240, 81, 141)) + self.verticalLayout_3 = QVBoxLayout(self.verticalLayoutWidget_4) + self.verticalLayout_3.setObjectName(u"verticalLayout_3") + self.verticalLayout_3.setContentsMargins(0, 0, 0, 0) + self.label_8 = QLabel(self.verticalLayoutWidget_4) + self.label_8.setObjectName(u"label_8") + + self.verticalLayout_3.addWidget(self.label_8) + + self.checkBox_singlenote = QCheckBox(self.verticalLayoutWidget_4) + self.checkBox_singlenote.setObjectName(u"checkBox_singlenote") + + self.verticalLayout_3.addWidget(self.checkBox_singlenote) + + self.checkBox_seriesnote = QCheckBox(self.verticalLayoutWidget_4) + self.checkBox_seriesnote.setObjectName(u"checkBox_seriesnote") + self.checkBox_seriesnote.setChecked(True) + + self.verticalLayout_3.addWidget(self.checkBox_seriesnote) + + + self.retranslateUi(Form) + + QMetaObject.connectSlotsByName(Form) + # setupUi + + def retranslateUi(self, Form): + Form.setWindowTitle(QCoreApplication.translate("Form", u"\u7cfb\u5217\u8bb2\u4e49\u751f\u6210", None)) + self.label.setText(QCoreApplication.translate("Form", u"\u8bb2\u4e49\u7f16\u53f7\u8868\u8fbe\u5f0f", None)) + self.label_2.setText(QCoreApplication.translate("Form", u"\u7528 \",\" \u5206\u9694\u7684\u4e00\u7cfb\u5217\u6b63\u5219\u8868\u8fbe\u5f0f", None)) + self.pushButton_exec.setText(QCoreApplication.translate("Form", u"\u5f00\u59cb\u751f\u6210\u4e0e\u7f16\u8bd1", None)) + self.label_3.setText(QCoreApplication.translate("Form", u"\u6587\u4ef6\u8def\u5f84", None)) + self.pushButton_SelectPath.setText(QCoreApplication.translate("Form", u"\u9009\u62e9\u8def\u5f84", None)) + self.label_4.setText(QCoreApplication.translate("Form", u"\u7248\u5f0f\u9009\u62e9", None)) + self.radioButton_student.setText(QCoreApplication.translate("Form", u"\u5b66\u751f\u7248", None)) + self.radioButton_teacher.setText(QCoreApplication.translate("Form", u"\u6559\u5e08\u7248", None)) + self.label_5.setText(QCoreApplication.translate("Form", u"\u5185\u5bb9\u9009\u9879", None)) + self.checkBox_space.setText(QCoreApplication.translate("Form", u"\u9898\u540e\u7a7a\u95f4", None)) + self.checkBox_ans.setText(QCoreApplication.translate("Form", u"\u7b54\u6848", None)) + self.checkBox_objs.setText(QCoreApplication.translate("Form", u"\u8bfe\u65f6\u76ee\u6807", None)) + self.checkBox_tags.setText(QCoreApplication.translate("Form", u"\u9898\u76ee\u6807\u7b7e", None)) + self.checkBox_solution.setText(QCoreApplication.translate("Form", u"\u89e3\u7b54\u4e0e\u63d0\u793a", None)) + self.checkBox_usages.setText(QCoreApplication.translate("Form", u"\u4f7f\u7528\u8bb0\u5f55", None)) + self.checkBox_origin.setText(QCoreApplication.translate("Form", u"\u6765\u6e90", None)) + self.checkBox_remark.setText(QCoreApplication.translate("Form", u"\u5907\u6ce8", None)) + self.label_6.setText(QCoreApplication.translate("Form", u"\u4f7f\u7528\u8bb0\u5f55\u9009\u62e9(\u90fd\u7559\u7a7a\u4e3a\u5168\u663e\u793a)", None)) + self.label_9.setText(QCoreApplication.translate("Form", u"\u9ad8", None)) + self.label_10.setText(QCoreApplication.translate("Form", u"\u4f4e", None)) + self.label_7.setText(QCoreApplication.translate("Form", u"\u5c4a\u522b\u9009\u62e9(\u7528 \",\" \u5206\u9694, \u7559\u7a7a\u4e3a\u5168\u663e\u793a)", None)) + self.label_8.setText(QCoreApplication.translate("Form", u"\u7f16\u8bd1\u9009\u9879", None)) + self.checkBox_singlenote.setText(QCoreApplication.translate("Form", u"\u5355\u5f20\u7f16\u8bd1", None)) + self.checkBox_seriesnote.setText(QCoreApplication.translate("Form", u"\u5408\u96c6\u7f16\u8bd1", None)) + # retranslateUi + diff --git a/工具v3/database_tools_2.py b/工具v3/database_tools_2.py index c152b802..5dc596fd 100644 --- a/工具v3/database_tools_2.py +++ b/工具v3/database_tools_2.py @@ -939,7 +939,7 @@ def SortUsages(prodict): #对使用记录按字符串进行排序 def SortUsagesbyAverage(theusages): #根据使用记录每一条的平均值进行排序, 越高的在越前面 glossdifflist = [] for i in range(len(theusages)): - glossdiff = parseUsage(theusages[i])["glossdiff"] + glossdiff = np.mean([float(d) for d in theusages[i][2]]) if glossdiff <= 0.999: #去除全对的使用记录 glossdifflist = glossdifflist + [(i,glossdiff)] sortedglossdifflist = sorted(glossdifflist, key = lambda x:x[1], reverse = True) @@ -1064,16 +1064,16 @@ def XeLaTeXTest(editedid,adict,objdict,misc,templatepath,outdir,outfile): #对ad succ = XeLaTeXCompile(outdir,outfile) return succ -def GenerateSectionBodyString2024(problems,sectiontitles,pro_dict,obj_dict,bk_dict,misc,consecutivenumbering= True): #生成学生版的.tex文件的主体内容 +def GenerateSectionBodyStringfromMariaDB(cursor,problems,sectiontitles,misc,consecutivenumbering= True): #生成学生版的.tex文件的主体内容 bodystring = "" count = 0 for i in range(len(problems)): if problems[i][0] in "0123456789": - idlist = generate_number_set(problems[i],pro_dict) + idlist = generate_number_set(problems[i]) sectionstring = f"\\section{{{sectiontitles[i]}}}\n\\begin{{enumerate}}\n\\setcounter{{enumi}}{{{count if consecutivenumbering else 0}}}\n\n" for id in idlist: count += 1 - sectionstring += generateLaTeXBodyContent(id,pro_dict,obj_dict,misc) + sectionstring += generateLaTeXBodyContentfromMariaDB(cursor,id,misc) sectionstring += "\\end{enumerate}\n\n" bodystring += sectionstring if problems[i][0] == "K": @@ -1184,13 +1184,21 @@ def ChooseUsage(usages,topandbottomusagestuple): #生成题号对应的题目的 else: return (SortUsagesbyAverage(usages)[:top] + SortUsagesbyAverage(usages)[(len(usages)-bottom):]) # 返回排序后的最前面top个和最后面bottom个 -def GenerateUsageTexCode(id,prodict,topandbottomusagestuple): #根据topandbottomusagestuple的要求生成题号为id的题目的缩减版的使用记录列表, topandbottomusagestuple表示保留得分率最高的使用记录与最低的使用记录的个数, 有负数表示不排列, 两数之和大于记录数则从高到低排列后全部展示 - rawusages = prodict[id]["usages"].copy() - usages = ChooseUsage(rawusages,topandbottomusagestuple) - usagecode = re.sub("\\t([\d]\.[\d]{0,10})",GenerateValueColorCode,"\n\n".join(usages)) +def GenerateUsageTexCode(usage_list_raw,misc): #根据topandbottomusagestuple的要求生成题号为id的题目的缩减版的使用记录列表, topandbottomusagestuple表示保留得分率最高的使用记录与最低的使用记录的个数, 有负数表示不排列, 两数之和大于记录数则从高到低排列后全部展示 + grade = misc["字段显示设置"]["届别"] + topandbottomusagestuple = misc["字段显示设置"]["使用记录"] + usage_list = [] + for u in usage_list_raw: + for g in grade: + if re.findall(g,u[1]) != []: + usage_list.append(u) + break + usages = ChooseUsage(usage_list,topandbottomusagestuple) + usages_str = ["\t".join((u[0],u[1],("\t".join(u[2])))) for u in usages] + usagecode = re.sub("\\t([\d]\.[\d]{0,10})",GenerateValueColorCode,"\n\n".join(usages_str)) return usagecode #返回缩减后的使用记录列表 -def generateLaTeXBodyContent(id,adict,objdict,misc): #根据id,读取的json内容adict,和字典misc来生成讲义 +def generateLaTeXBodyContentfromMariaDB(cursor,id,misc): #根据id,读取的json内容adict,和字典misc来生成讲义 #misc 样例 #{ # "教师版": True, #如果设置为True则除了 题后空间 之外都进行判断并处理, 否则只处理 题后空间 和 答案 @@ -1208,44 +1216,117 @@ def generateLaTeXBodyContent(id,adict,objdict,misc): #根据id,读取的json内 # } # } id = str(id).zfill(6) + sql = "SELECT content,ans,solution,origin,space FROM problems WHERE ID = %s;" + val = (id,) + cursor.execute(sql,val) + content,ans,solution,raw_origin,space = cursor.fetchall()[0] + if ans is None: + ans = "" + if solution is None: + solution = "" + origin = json.loads(raw_origin) + #以下生成obj_list + sql = "SELECT obj_ID FROM objcorresp WHERE ID = %s;" + cursor.execute(sql,val) + obj_list = [] + for id_raw in cursor.fetchall(): + obj_id = id_raw[0] + sql = "SELECT obj_content FROM lessonobj WHERE objid = %s;" + objval = (obj_id,) + cursor.execute(sql,objval) + obj_list.append((obj_id,cursor.fetchall()[0][0])) + sql = "SELECT tagname FROM tagcorresp WHERE ID = %s;" + cursor.execute(sql,val) + tag_list = [t[0] for t in cursor.fetchall()] + sql = "SELECT date,remark_content FROM remarks WHERE ID = %s;" + cursor.execute(sql,val) + remark_list = sorted([f"{t[0]}\t{t[1]}" for t in cursor.fetchall()]) + sql = "SELECT date,classname,diff FROM usages WHERE ID = %s;" + cursor.execute(sql,val) + usages_raw = sorted([(t[0],t[1],json.loads(t[2])) for t in cursor.fetchall()]) if not "教师版" in misc or misc["教师版"] == False: - output = f"\n\\item {{\\tiny ({id})}} {adict[id]['content']}" + output = f"\n\\item {{\\tiny ({id})}} {content}" if "字段显示设置" in misc and "答案" in misc["字段显示设置"] and misc["字段显示设置"]["答案"] == True: - ans = adict[id]["ans"] if len(adict[id]["ans"]) > 0 else "暂无答案" + ans = ans if len(ans) > 0 else "暂无答案" output += f"\n\n答案: \\textcolor{{{('red' if ans != '暂无答案' else 'blue')}}}{{{ans}}}\n\n" if "字段显示设置" in misc and "题后空间" in misc["字段显示设置"] and misc["字段显示设置"]["题后空间"] == True: - space = f"\n\n\\vspace*{{{adict[id]['space']}}}\n\n" if len(adict[id]["space"]) > 0 else "" + space = f"\n\n\\vspace*{{{space}}}\n\n" if len(space) > 0 else "" output += space else: - output = f"\n\\item ({id}) {adict[id]['content']}" + output = f"\n\\item ({id}) {content}" if "备注" in misc["字段显示设置"] and misc["字段显示设置"]["备注"] == True: - remark = adict[id]["remark"] if len(adict[id]["remark"]) > 0 else "暂无备注" + remark = r"\\".join(remark_list) if len(remark_list) > 0 else "暂无备注" output += f"\n\n备注: \\textcolor[rgb]{{0,0.5,0.2}}{{{remark}}}\n\n" if "课时目标" in misc["字段显示设置"] and misc["字段显示设置"]["课时目标"] == True: - objs = f"\n\n目标:\n\n{GenerateObjTexCode(id,adict,objdict)}\n\n" + obj_string = '\n\n'.join(obj_list) + if obj_string.strip() == "": + obj_string = "暂无目标" + objs = f"\n\n目标:\n\n{obj_string}\n\n" output += objs if "题目标签" in misc["字段显示设置"] and misc["字段显示设置"]["题目标签"] == True: - tags_raw = adict[id]['tags'] - if len(tags_raw) == 0: + if len(tag_list) == 0: tags = "暂无标签" else: - tags = '; '.join(adict[id]['tags']) + tags = '; '.join(tag_list) output += f"\n\n标签: \\textcolor[rgb]{{0.5,0.6,0.8}}{{{tags}}}\n\n" if "答案" in misc["字段显示设置"] and misc["字段显示设置"]["答案"] == True: - ans = adict[id]["ans"] if len(adict[id]["ans"]) > 0 else "暂无答案" + ans = ans if len(ans) > 0 else "暂无答案" output += f"\n\n答案: \\textcolor{{{('red' if ans != '暂无答案' else 'blue')}}}{{{ans}}}\n\n" if "解答与提示" in misc["字段显示设置"] and misc["字段显示设置"]["解答与提示"] == True: - solution = adict[id]["solution"] if len(adict[id]["solution"]) > 0 else "暂无解答或提示" + solution = solution if len(solution) > 0 else "暂无解答或提示" output += f"\n\n解答或提示: \\textcolor{{magenta}}{{{solution}}}\n\n" if "使用记录" in misc["字段显示设置"] and type(misc["字段显示设置"]["使用记录"]) in (list,tuple) and not -2 in misc["字段显示设置"]["使用记录"]: - usages = f"\n\n使用记录:\n\n{GenerateUsageTexCode(id,adict,misc['字段显示设置']['使用记录'])}\n\n" + usages = f"\n\n使用记录:\n\n{GenerateUsageTexCode(usages_raw,misc)}\n\n" output += usages if "来源" in misc["字段显示设置"] and misc["字段显示设置"]["来源"] == True: - origin = generate_origin(adict[id]["origin"]) if len(adict[id]["origin"]) > 0 else "未记录来源" + origin = generate_origin(origin) if len(origin) > 0 else "未记录来源" output += f"\n\n来源: {origin}\n\n" return output + + + return content,ans,solution,origin,space,obj_list,tag_list,remark_list,usages_raw + + + # if not "教师版" in misc or misc["教师版"] == False: + # output = f"\n\\item {{\\tiny ({id})}} {adict[id]['content']}" + # if "字段显示设置" in misc and "答案" in misc["字段显示设置"] and misc["字段显示设置"]["答案"] == True: + # ans = adict[id]["ans"] if len(adict[id]["ans"]) > 0 else "暂无答案" + # output += f"\n\n答案: \\textcolor{{{('red' if ans != '暂无答案' else 'blue')}}}{{{ans}}}\n\n" + # if "字段显示设置" in misc and "题后空间" in misc["字段显示设置"] and misc["字段显示设置"]["题后空间"] == True: + # space = f"\n\n\\vspace*{{{adict[id]['space']}}}\n\n" if len(adict[id]["space"]) > 0 else "" + # output += space + # else: + # output = f"\n\\item ({id}) {adict[id]['content']}" + # if "备注" in misc["字段显示设置"] and misc["字段显示设置"]["备注"] == True: + # remark = adict[id]["remark"] if len(adict[id]["remark"]) > 0 else "暂无备注" + # output += f"\n\n备注: \\textcolor[rgb]{{0,0.5,0.2}}{{{remark}}}\n\n" + # if "课时目标" in misc["字段显示设置"] and misc["字段显示设置"]["课时目标"] == True: + # objs = f"\n\n目标:\n\n{GenerateObjTexCode(id,adict,objdict)}\n\n" + # output += objs + # if "题目标签" in misc["字段显示设置"] and misc["字段显示设置"]["题目标签"] == True: + # tags_raw = adict[id]['tags'] + # if len(tags_raw) == 0: + # tags = "暂无标签" + # else: + # tags = '; '.join(adict[id]['tags']) + # output += f"\n\n标签: \\textcolor[rgb]{{0.5,0.6,0.8}}{{{tags}}}\n\n" + # if "答案" in misc["字段显示设置"] and misc["字段显示设置"]["答案"] == True: + # ans = adict[id]["ans"] if len(adict[id]["ans"]) > 0 else "暂无答案" + # output += f"\n\n答案: \\textcolor{{{('red' if ans != '暂无答案' else 'blue')}}}{{{ans}}}\n\n" + # if "解答与提示" in misc["字段显示设置"] and misc["字段显示设置"]["解答与提示"] == True: + # solution = adict[id]["solution"] if len(adict[id]["solution"]) > 0 else "暂无解答或提示" + # output += f"\n\n解答或提示: \\textcolor{{magenta}}{{{solution}}}\n\n" + # if "使用记录" in misc["字段显示设置"] and type(misc["字段显示设置"]["使用记录"]) in (list,tuple) and not -2 in misc["字段显示设置"]["使用记录"]: + # usages = f"\n\n使用记录:\n\n{GenerateUsageTexCode(id,adict,misc['字段显示设置']['使用记录'])}\n\n" + # output += usages + # if "来源" in misc["字段显示设置"] and misc["字段显示设置"]["来源"] == True: + # origin = generate_origin(adict[id]["origin"]) if len(adict[id]["origin"]) > 0 else "未记录来源" + # output += f"\n\n来源: {origin}\n\n" + # return output + + def GenerateTeacherBodyString(problems,sectiontitles,prodict,objdict,consecutivenumbering = True,topandbottomusagestuple = (3,3),sectionname = "section", showobjs = True, showtags = True, showans = True, showsolution = True, showusages = True, showorigin = True, showremark = True, colored = False): #生成教师版的.tex文件的主体内容, 各项是否显示为可选 bodystring = "" GetAfterContent = TeachersGetAfterContentPlain if not colored else TeachersGetAfterContentColored @@ -1754,7 +1835,7 @@ def select_grade_from_pro_dict(prodict,grades): adict[id]["usages"] = new_usages.copy() return adict -def GenerateSingleLessonNote2024(id,notesdict,pro_dict,obj_dict,bk_dict,templatepath,outputfilepath,misc,consecutivenumbering = False): #20231215版讲义生成 +def GenerateSingleLessonNotefromMariaDB(cursor,id,notesdict,templatepath,outputfilepath,misc,consecutivenumbering = False): #20240415版讲义生成 notetitle = id + r" \ " + notesdict["notes"][id]["name"] structure = notesdict["structures"][id[0].upper()]["structure"] note_contents = notesdict["notes"][id] @@ -1765,8 +1846,7 @@ def GenerateSingleLessonNote2024(id,notesdict,pro_dict,obj_dict,bk_dict,template if not len(note_contents[key]) == 0: sections_list.append(key) problems_list.append(",".join(note_contents[key])) - rawoutput = GenerateSectionBodyString2024(problems=problems_list,sectiontitles=sections_list,pro_dict=pro_dict,obj_dict=obj_dict,bk_dict=bk_dict,misc=misc,consecutivenumbering= consecutivenumbering) - # rawoutput = GenerateStudentBodyString(problems=problems_list,sectiontitles=sections_list,pro_dict=metadict,consecutivenumbering= consecutivenumbering, answered= answered, spaceflag = True) + rawoutput = GenerateSectionBodyStringfromMariaDB(cursor = cursor, problems=problems_list,sectiontitles=sections_list,misc=misc,consecutivenumbering= consecutivenumbering) paragraphs = [p for p in rawoutput.split("\\section") if not p.strip() == ""] for item in paragraphs: sectionkey, content = re.findall(r"\{([\S]*)\}\n([\S\s]*)$",item)[0] diff --git a/工具v3/系列讲义生成.py b/工具v3/系列讲义生成.py new file mode 100644 index 00000000..57f1a6f6 --- /dev/null +++ b/工具v3/系列讲义生成.py @@ -0,0 +1,160 @@ +from PySide6.QtWidgets import QWidget, QApplication, QFileDialog +from Ui_系列讲义生成 import Ui_Form +from database_tools_2 import * +import os + +class MyWindow(QWidget,Ui_Form): + def __init__(self): + super().__init__() + self.setupUi(self) + self.bind() + + def bind(self): + self.outputpath = os.path.join(os.getcwd(),"临时文件") + self.lineEdit_path.setText(self.outputpath) + self.TeachersCheckBoxList = [self.checkBox_ans,self.checkBox_objs,self.checkBox_tags,self.checkBox_solution,self.checkBox_usages,self.checkBox_origin,self.checkBox_remark] + self.StudentsCheckBoxList = [self.checkBox_space,self.checkBox_ans] + self.ContnetCheckBoxList = [self.checkBox_ans,self.checkBox_objs,self.checkBox_tags,self.checkBox_solution,self.checkBox_usages,self.checkBox_origin,self.checkBox_remark,self.checkBox_space] + for widget in self.ContnetCheckBoxList: + widget.setDisabled(True) + self.studentlayout() + self.disableusagessetting() + self.radioButton_teacher.clicked.connect(self.teacherlayout) + self.radioButton_student.clicked.connect(self.studentlayout) + self.checkBox_usages.clicked.connect(self.toggleusagessetting) + self.radioButton_student.clicked.connect(self.toggleusagessetting) + self.radioButton_teacher.clicked.connect(self.toggleusagessetting) + self.pushButton_exec.clicked.connect(self.saveandbuild) + self.pushButton_SelectPath.clicked.connect(self.selectpath) + + + + def disableusagessetting(self): + self.lineEdit_high.setDisabled(True) + self.lineEdit_low.setDisabled(True) + self.lineEdit_grades.setDisabled(True) + def enableusagessetting(self): + self.lineEdit_high.setEnabled(True) + self.lineEdit_low.setEnabled(True) + self.lineEdit_grades.setEnabled(True) + def toggleusagessetting(self): + if self.checkBox_usages.isChecked() and self.radioButton_teacher.isChecked(): + self.enableusagessetting() + else: + self.disableusagessetting() + + def studentlayout(self): + for widget in self.TeachersCheckBoxList: + widget.setDisabled(True) + for widget in self.StudentsCheckBoxList: + widget.setEnabled(True) + + def selectpath(self): + self.outputpath = QFileDialog.getExistingDirectory(None, "选择文件夹") + self.lineEdit_path.setText(self.outputpath) + + def teacherlayout(self): + for widget in self.StudentsCheckBoxList: + widget.setDisabled(True) + for widget in self.TeachersCheckBoxList: + widget.setEnabled(True) + def generate_usages(self): + high = self.lineEdit_high.text().strip() + low = self.lineEdit_low.text().strip() + if self.checkBox_usages.isChecked() == False: + return [-2,-2] + elif self.checkBox_usages.isChecked() and high == "" and low == "": + return [-1,-1] + else: + if high == "": + high = "0" + if low == "": + low = "0" + return [int(high),int(low)] + + def saveandbuild(self): + patterns = self.lineEdit_regex.text().strip().split(",") + jsonpath = "../备课组" #有json文件的根目录, 文件名需为"校本材料.json" + jsondicts = [] + for loc,dirs,files in os.walk(jsonpath): + if "校本材料.json" in files: + jsondicts.append(load_dict(os.path.join(loc,"校本材料.json"))) + + mydb = connect(hostname = "wwylss.synology.me", port = "13306", username="root", pwd="Wwy@0018705", db = "tikutest") + mycursor = mydb.cursor() + # raw_pro_dict = load_dict("../题库0.3/Problems.json") + # obj_dict = load_dict("../题库0.3/LessonObj.json") + # basicknowledge_dict = load_dict("../题库0.3/BasicKnowledge.json") + if self.radioButton_teacher.isChecked() and self.checkBox_usages.isChecked() and not self.lineEdit_grades.text().strip() == "": + grades = self.lineEdit_grades.text().strip().split(",") + else: + grades = [] + # pro_dict = select_grade_from_pro_dict(raw_pro_dict,grades) + # dictionaries = {} #合并字典 + # for t in (obj_dict,basicknowledge_dict,pro_dict): + # dictionaries.update(t) + configjson = { + "教师版": self.radioButton_teacher.isChecked(), + "字段显示设置": { + "题后空间": self.checkBox_space.isChecked(), + "课时目标": self.checkBox_objs.isChecked(), + "题目标签": self.checkBox_tags.isChecked(), + "答案": self.checkBox_ans.isChecked(), + "解答与提示": self.checkBox_solution.isChecked(), + "使用记录": self.generate_usages(), + "来源": self.checkBox_origin.isChecked(), + "备注": self.checkBox_remark.isChecked(), + "届别": grades + }, + "编译单个文件": self.checkBox_singlenote.isChecked(), + "编译合集": self.checkBox_seriesnote.isChecked() + } + papernames = [] + multitexdata = [] + for notes_dict in jsondicts: + for lessonid in notes_dict["notes"]: + coincideflag = False + for lessonpattern in patterns: + if re.findall(lessonpattern,lessonid) != []: + coincideflag = True + break + if coincideflag: + filename = notes_dict["notes"][lessonid]["id"]+notes_dict["notes"][lessonid]["filename"]+".tex" + papertype = lessonid[0] + consecutivenumbering = notes_dict["structures"][papertype]["consecutivenumbering"] + texdata = GenerateSingleLessonNotefromMariaDB(cursor = mycursor, id = lessonid,notesdict=notes_dict,templatepath="./模板文件/讲义模板.txt",outputfilepath = os.path.join(self.outputpath,filename),misc=configjson,consecutivenumbering = consecutivenumbering) + papernames.append(notes_dict["notes"][lessonid]["id"]+" \\ "+notes_dict["notes"][lessonid]["name"]) + multitexdata.append(re.findall(r"\\begin{center}\n{\\bf\\large \\papername}\n\\end{center}([\s\S]*\\end\{enumerate\})",texdata)[0]) + # print(lessonid) + # print(configjson) + # print("\n".join(patterns)) + merged = "" + for i in range(len(papernames)): + merged += "\n\n\\chapter{"+papernames[i]+"}\n\n\n" + merged += multitexdata[i] + + mergedtext = StringSubstitute(r"<<待替换[\d]+>>",ReadTextFile("./模板文件/合集模板.txt"),[merged]) + if sys.platform != "win32": + mergedtext = re.sub(r"fontset[\s]*=[\s]*none","fontset = fandol",mergedtext) + mergedtext = re.sub(r"\\setCJKmainfont",r"% \\setCJKmainfont",mergedtext) + SaveTextFile(mergedtext,os.path.join(self.outputpath,f"合集{GetDate()}.tex")) + + # if not "编译合集" in configjson or configjson["编译合集"] == False: + # tocompile = input("需要编译合集吗?(Y/[N]):") + if configjson["编译合集"] == True: + XeLaTeXCompile(self.outputpath,f"合集{GetDate()}.tex") + startfile(self.outputpath) + + + + + + + + +if __name__ == '__main__': + app = QApplication([]) + windows = MyWindow() + windows.show() + app.exec() + diff --git a/工具v3/系列讲义生成.ui b/工具v3/系列讲义生成.ui new file mode 100644 index 00000000..0818d459 --- /dev/null +++ b/工具v3/系列讲义生成.ui @@ -0,0 +1,322 @@ + + + Form + + + + 0 + 0 + 511 + 394 + + + + 系列讲义生成 + + + + + 100 + 20 + 231 + 20 + + + + + + + 10 + 20 + 91 + 16 + + + + 讲义编号表达式 + + + + + + 340 + 20 + 171 + 16 + + + + 用 "," 分隔的一系列正则表达式 + + + + + + 280 + 250 + 221 + 131 + + + + + true + + + + 开始生成与编译 + + + + + + 10 + 50 + 61 + 16 + + + + 文件路径 + + + + + + 10 + 70 + 491 + 20 + + + + + + + 430 + 40 + 75 + 24 + + + + 选择路径 + + + + + + 10 + 110 + 81 + 111 + + + + + + + 版式选择 + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + 学生版 + + + true + + + + + + + 教师版 + + + + + + + + + 110 + 110 + 151 + 271 + + + + + + + 内容选项 + + + + + + + 题后空间 + + + + + + + 答案 + + + + + + + 课时目标 + + + true + + + false + + + + + + + 题目标签 + + + + + + + 解答与提示 + + + + + + + 使用记录 + + + + + + + 来源 + + + + + + + 备注 + + + + + + + + + 280 + 110 + 222 + 121 + + + + + + + 使用记录选择(都留空为全显示) + + + + + + + + + + + + + + + + true + + + + + + + + + + + + + + + + + + + 届别选择(用 "," 分隔, 留空为全显示) + + + + + + + + + + + + 10 + 240 + 81 + 141 + + + + + + + 编译选项 + + + + + + + 单张编译 + + + + + + + 合集编译 + + + true + + + + + + + + +