624 lines
29 KiB
Python
624 lines
29 KiB
Python
# Copyright (c) 2025 Jeffrey Hsu - JITToolBox
|
||
# #
|
||
# This program is free software: you can redistribute it and/or modify
|
||
# it under the terms of the GNU General Public License as published by
|
||
# the Free Software Foundation, either version 3 of the License, or
|
||
# (at your option) any later version.
|
||
# #
|
||
# This program is distributed in the hope that it will be useful,
|
||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
# GNU General Public License for more details.
|
||
# #
|
||
# You should have received a copy of the GNU General Public License
|
||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||
|
||
import datetime
|
||
import traceback
|
||
from typing import Optional, Callable
|
||
|
||
import openpyxl
|
||
from openpyxl.utils import get_column_letter, column_index_from_string
|
||
from openpyxl.workbook.workbook import Workbook
|
||
from openpyxl.worksheet.worksheet import Worksheet
|
||
from packaging import version
|
||
|
||
from module import LOGLEVEL, COMPATIBLE_VERSION
|
||
from module.schema import Performance
|
||
from utils.function import format_ranges, get_rank, min_score_people_name, get_class_index_range, check_version, \
|
||
gen_picture
|
||
|
||
|
||
class ExcelReader:
|
||
kpi_list: list[str]
|
||
hml_list: list[str]
|
||
kpi_number: int
|
||
file_path: str
|
||
course_name: str
|
||
course_teacher_name: str
|
||
total_class_str: str
|
||
class_list: list[str]
|
||
class_number: list[int]
|
||
course_objectives: list[str]
|
||
course_objectives_number: list[int]
|
||
evaluation_stage: list[tuple[Optional[str], Optional[str]]]
|
||
achievement_level: list[list[Performance]]
|
||
target_score: list[list[float]]
|
||
n_evaluation_methods: list[Optional[str]]
|
||
question_data: dict[str, list[tuple[str, int]]]
|
||
ignore_version_check: bool
|
||
pic_list: list
|
||
suggestion_template_list: list[Optional[str]]
|
||
|
||
def __init__(self, file_path: str, version_check: bool = False,
|
||
signal: Callable[[str, str], None] = lambda x, y: print(x)):
|
||
super().__init__()
|
||
self.file_path = file_path
|
||
self.kpi_list = []
|
||
self.class_list = []
|
||
self.class_number = []
|
||
self.course_objectives = []
|
||
self.course_objectives_number = []
|
||
self.course_name = ""
|
||
self.course_teacher_name = ""
|
||
self.course_lead_teacher_name = ""
|
||
self.evaluation_stage = []
|
||
self.achievement_level = []
|
||
self.kpi_number = 0
|
||
self.stu_kpi_achieve_list = []
|
||
self.target_score = []
|
||
self.n_evaluation_methods = []
|
||
self.total_class_str = ""
|
||
self.hml_list = []
|
||
self.question_data = {}
|
||
self.ignore_version_check = version_check
|
||
self.pic_list = []
|
||
self.signal = signal
|
||
self.suggestion_template_list = []
|
||
|
||
def parse_excel(self):
|
||
try:
|
||
wb: Workbook = openpyxl.load_workbook(self.file_path, read_only=True, data_only=True)
|
||
sheet: Worksheet = wb['初始录入']
|
||
# 读取版本号
|
||
e_version = sheet['V4'].value if sheet['V4'].value is not None else sheet['U4'].value
|
||
e_version = sheet['H1'].value if e_version is None else e_version
|
||
if e_version is None:
|
||
e_version = "0"
|
||
status, _ = check_version(e_version, COMPATIBLE_VERSION)
|
||
CUR_VERSION = version.parse(e_version)
|
||
if not status:
|
||
if not self.ignore_version_check:
|
||
raise NotImplementedError(f"版本不适配,当前表格版本:{e_version},适配版本:{COMPATIBLE_VERSION}")
|
||
self.signal("已忽略表格兼容性:您的表格版本不在适配版本中,可能导致未知错误。", LOGLEVEL.WARNING)
|
||
# 读取教学班级
|
||
self.total_class_str = sheet["D10"].value
|
||
# 读取课程名称
|
||
match CUR_VERSION:
|
||
case _ if CUR_VERSION <= version.parse("7.3"):
|
||
self.course_name = sheet["D6"].value
|
||
case _ if CUR_VERSION >= version.parse("7.4"):
|
||
self.course_name = sheet["D5"].value
|
||
# 读取任课教师
|
||
self.course_teacher_name = sheet["D7"].value
|
||
# 读取课程负责人
|
||
self.course_lead_teacher_name = sheet["D8"].value
|
||
|
||
# 读取班级和人数
|
||
max_class_size = 4
|
||
match CUR_VERSION:
|
||
case _ if CUR_VERSION <= version.parse("7.6"):
|
||
max_class_size = 3
|
||
|
||
for i in range(2, 2 + max_class_size):
|
||
name = sheet[f"K{i}"]
|
||
number = sheet[f"M{i}"]
|
||
if name.value is None or number.value is None:
|
||
break
|
||
self.class_list.append(name.value)
|
||
self.class_number.append(int(number.value))
|
||
# 读取课程指标个数
|
||
self.kpi_number = sheet["H8"].value
|
||
# 读取课程目标和指标点
|
||
hml_start = 22
|
||
match CUR_VERSION:
|
||
case _ if CUR_VERSION <= version.parse("7.6"):
|
||
hml_start = 21
|
||
for i in range(hml_start, hml_start + 5):
|
||
hml = sheet[f"H{i}"]
|
||
objective = sheet[f"I{i}"]
|
||
kpi = sheet[f"Q{i}"]
|
||
if kpi.value is None or objective.value is None:
|
||
break
|
||
self.hml_list.append(hml.value)
|
||
self.kpi_list.append(kpi.value)
|
||
self.course_objectives.append(objective.value)
|
||
# 读取考核方式及权重
|
||
k_start = 7
|
||
match CUR_VERSION:
|
||
case _ if CUR_VERSION <= version.parse("7.6"):
|
||
k_start = 6
|
||
for i in range(k_start, k_start + 6):
|
||
if i in (k_start + 1, k_start + 2, k_start + 4):
|
||
continue
|
||
way = sheet[f"K{i}"]
|
||
per = sheet[f"L{i}"]
|
||
self.evaluation_stage.append((way.value, per.value))
|
||
|
||
# 读取平时考核方式
|
||
end = k_start + 5
|
||
if CUR_VERSION >= version.parse("7.7"):
|
||
end += 1
|
||
for i in range(k_start, end):
|
||
val = sheet[f"M{i}"].value
|
||
self.n_evaluation_methods.append(val)
|
||
|
||
sheet = wb['达成度']
|
||
# 目标值表格列 | 目标X |
|
||
kpi_row_tuple = ( # | 平时 | 大作业 | 试卷 | 个人达成值 |
|
||
('D', 'E', 'F', 'G'), # 目标一 平均分 | |
|
||
('H', 'I', 'J', 'K'), # 目标二 得分率 | |
|
||
('L', 'M', 'N', 'O'), # 目标三 达成度 | |
|
||
('P', 'Q', 'R', 'S'), # 目标四
|
||
('T', 'U', 'V', 'W') # 目标五
|
||
)
|
||
# 获取达成度中的目标分值、班级平均分,得分率和达成度
|
||
for i in range(self.kpi_number):
|
||
# 目标分值
|
||
self.target_score.append([
|
||
sheet[kpi_row_tuple[i][0] + f"6"].value,
|
||
sheet[kpi_row_tuple[i][1] + f"6"].value,
|
||
sheet[kpi_row_tuple[i][2] + f"6"].value
|
||
])
|
||
base_row = 8
|
||
for j in range(len(self.class_number)):
|
||
# 平均分
|
||
avg = (
|
||
sheet[kpi_row_tuple[i][0] + f"{base_row + j * 3}"].value,
|
||
sheet[kpi_row_tuple[i][1] + f"{base_row + j * 3}"].value,
|
||
sheet[kpi_row_tuple[i][2] + f"{base_row + j * 3}"].value
|
||
)
|
||
# 得分率
|
||
per = (
|
||
sheet[kpi_row_tuple[i][0] + f"{base_row + 1 + j * 3}"].value,
|
||
sheet[kpi_row_tuple[i][1] + f"{base_row + 1 + j * 3}"].value,
|
||
sheet[kpi_row_tuple[i][2] + f"{base_row + 1 + j * 3}"].value
|
||
)
|
||
# 达成度
|
||
kpi_c = sheet[kpi_row_tuple[i][0] + f"{base_row + 2 + j * 3}"].value
|
||
if len(self.achievement_level) - 1 < j:
|
||
self.achievement_level.append([Performance(avg, per, kpi_c)])
|
||
else:
|
||
self.achievement_level[j].append(Performance(avg, per, kpi_c))
|
||
# 获取学生的各项目标值
|
||
# 读取 A18:O87 范围的数据
|
||
match CUR_VERSION:
|
||
case _ if CUR_VERSION <= version.parse("7.6"):
|
||
rows = sheet[f'B18:{kpi_row_tuple[self.kpi_number - 1][3]}{17 + sum(self.class_number)}']
|
||
case _:
|
||
rows = sheet[f'B21:{kpi_row_tuple[self.kpi_number - 1][3]}{20 + sum(self.class_number)}']
|
||
|
||
# 将数据按行保存到列表中
|
||
for row in rows:
|
||
row_data = [cell.value for cell in row]
|
||
self.stu_kpi_achieve_list.append(row_data)
|
||
|
||
# 获取试题信息
|
||
sheet = wb['成绩录入']
|
||
start_col = 'BC' # 起始列
|
||
row_keys = 9 # 键所在的行
|
||
row_values = [7, 8] # 值所在的行
|
||
|
||
# 确定终止列
|
||
col = start_col
|
||
while True:
|
||
if not sheet[col + str(row_keys)].value:
|
||
break
|
||
col = get_column_letter(column_index_from_string(col) + 1)
|
||
|
||
# 读取数据
|
||
for col_index in range(column_index_from_string(start_col),
|
||
column_index_from_string(col)):
|
||
col_letter = get_column_letter(col_index)
|
||
key = sheet[col_letter + str(row_keys)].value
|
||
if key: # 确保键不为空
|
||
values = tuple(sheet[col_letter + str(r)].value for r in row_values)
|
||
if key in self.question_data:
|
||
self.question_data[key].append(values)
|
||
else:
|
||
self.question_data[key] = [values]
|
||
|
||
# 读取建议模板
|
||
if CUR_VERSION >= version.parse("9.0"):
|
||
sheet = wb['初始录入']
|
||
|
||
for i in range(29, 34):
|
||
self.suggestion_template_list.append(sheet[f'I{i}'].value)
|
||
|
||
if len(self.suggestion_template_list) != 5:
|
||
for i in range(len(self.suggestion_template_list), 5):
|
||
self.suggestion_template_list.append(None)
|
||
|
||
self.validate_data()
|
||
self.gen_picture()
|
||
|
||
except Exception as e:
|
||
error_message = traceback.format_exc()
|
||
raise Exception(f"""
|
||
原始错误:
|
||
{error_message}
|
||
""")
|
||
|
||
def set_file_path(self, file_path: str):
|
||
self.file_path = file_path
|
||
|
||
def validate_data(self):
|
||
self.signal("正在验证数据", LOGLEVEL.INFO)
|
||
return 0
|
||
|
||
def run(self):
|
||
self.parse_excel()
|
||
|
||
def clear_all_data(self):
|
||
self.kpi_list = []
|
||
self.kpi_number = 0
|
||
self.file_path = ""
|
||
self.course_name = ""
|
||
self.course_teacher_name = []
|
||
self.class_list = []
|
||
self.class_number = []
|
||
self.course_objectives = []
|
||
self.course_objectives_number = []
|
||
self.evaluation_stage = []
|
||
self.achievement_level = []
|
||
self.kpi_number = 0
|
||
self.stu_kpi_achieve_list = []
|
||
self.target_score = []
|
||
self.n_evaluation_methods = []
|
||
self.hml_list = []
|
||
self.question_data = {}
|
||
self.pic_list = []
|
||
|
||
def set_version_check(self, version_check: bool):
|
||
self.ignore_version_check = version_check
|
||
|
||
def gen_picture(self):
|
||
self.signal("正在生成散点图", LOGLEVEL.INFO)
|
||
for i in range(len(self.class_list)):
|
||
l_index, r_index = get_class_index_range(self.class_number, i)
|
||
self.pic_list.append(gen_picture(
|
||
self.stu_kpi_achieve_list,
|
||
self.kpi_number,
|
||
l_index,
|
||
r_index
|
||
))
|
||
|
||
def get_word_template(self, class_index):
|
||
yield "课程目标"
|
||
for i in range(self.kpi_number):
|
||
yield f"课程目标{i + 1}({self.hml_list[i]})"
|
||
yield ("总成绩=\n{}".
|
||
format(
|
||
"\n+".join([f"{n if n != '试卷' else '期末'}成绩×{int(p * 100)}%" for n, p in self.evaluation_stage if
|
||
p is not None])))
|
||
for i in self.course_objectives:
|
||
yield i
|
||
yield "支撑毕业要求指标点"
|
||
for i in self.kpi_list:
|
||
yield i
|
||
yield "考核类型"
|
||
for i in range(self.kpi_number):
|
||
s_lst = self.achievement_level[class_index][i].scores
|
||
for index, (j, s) in enumerate(zip(self.evaluation_stage, s_lst)):
|
||
if s is None:
|
||
continue
|
||
if index == 2:
|
||
if len(self.n_evaluation_methods) == 6:
|
||
if self.n_evaluation_methods[5] == "试卷":
|
||
yield "期末考核\n(试卷)"
|
||
else:
|
||
yield "期末考核"
|
||
elif j[0] == "试卷":
|
||
yield "期末考核\n(试卷)"
|
||
else:
|
||
yield "期末考核"
|
||
else:
|
||
yield f"{j[0]}考核"
|
||
|
||
yield "目标分值(分)"
|
||
for i in self.target_score:
|
||
for j in i:
|
||
if j is None:
|
||
continue
|
||
yield j
|
||
yield "权重"
|
||
for i in range(self.kpi_number):
|
||
s_lst = self.achievement_level[class_index][i].scores
|
||
for j, s in zip(self.evaluation_stage, s_lst):
|
||
if s is None:
|
||
continue
|
||
yield j[1]
|
||
yield "学号"
|
||
yield "姓名"
|
||
for i in range(self.kpi_number):
|
||
s_lst = self.achievement_level[class_index][i].scores
|
||
for (index, j), s in zip(enumerate(self.evaluation_stage), s_lst):
|
||
if s is None:
|
||
continue
|
||
match index:
|
||
case 0:
|
||
yield "\n".join([x for x in self.n_evaluation_methods[:3] if x is not None])
|
||
case 1:
|
||
yield "\n".join([x for x in self.n_evaluation_methods[3:5] if x is not None])
|
||
case 2:
|
||
if len(self.n_evaluation_methods) == 6 and self.n_evaluation_methods[5] != "试卷":
|
||
yield self.n_evaluation_methods[5]
|
||
elif len(self.n_evaluation_methods) == 5 and self.evaluation_stage[2][0] != "试卷":
|
||
yield self.evaluation_stage[2][0]
|
||
else:
|
||
# 中文数字到数字的映射
|
||
chinese_num_map = {'一': 1, '二': 2, '三': 3,
|
||
'四': 4, '五': 5, '六': 6,
|
||
'七': 7, '八': 8, '九': 9}
|
||
q_lst = self.question_data[f'目标{i + 1}']
|
||
q_dict = {key: [item[1] for item in q_lst if item[0] == key] for key in
|
||
set(key for key, _ in q_lst)}
|
||
q_str_lst = [f"{k[0]}、{k[1:]}:{format_ranges(v)}" for k, v in q_dict.items()]
|
||
q_str_lst.sort(key=lambda x: chinese_num_map[x[0]])
|
||
q_str = "\n".join(q_str_lst)
|
||
yield q_str
|
||
case _:
|
||
yield "如果你能看到本行文字,请联系开发者"
|
||
|
||
l_range, r_range = get_class_index_range(self.class_number, class_index)
|
||
data = self.stu_kpi_achieve_list[l_range:r_range]
|
||
# 要移除的索引位置
|
||
remove_indices = [5, 9, 13, 17, 21]
|
||
# 更新后的数据
|
||
updated_data = [[item for j, item in enumerate(row) if j not in remove_indices] for row in data]
|
||
for i in updated_data:
|
||
for j in i:
|
||
if j is None:
|
||
continue
|
||
yield j
|
||
yield "平均得分"
|
||
for i in range(self.kpi_number):
|
||
avg_scores_lst = self.achievement_level[class_index][i].scores
|
||
for j in avg_scores_lst:
|
||
if j is None:
|
||
continue
|
||
yield j
|
||
yield "得分率"
|
||
for i in range(self.kpi_number):
|
||
per_scores_lst = self.achievement_level[class_index][i].rates
|
||
for j in per_scores_lst:
|
||
if j is None:
|
||
continue
|
||
yield j
|
||
yield "课程目标达成值"
|
||
for i in range(self.kpi_number):
|
||
yield f"课程目标{i + 1}达成值"
|
||
rates_lst = []
|
||
for x in range(self.kpi_number):
|
||
rates_lst.append(self.achievement_level[class_index][x].rates)
|
||
lst = [f"{r}×{p}" for (_, p), r in zip(self.evaluation_stage, rates_lst[i]) if r is not None]
|
||
total = sum(p for (_, p), r in zip(self.evaluation_stage, rates_lst[i]) if r is not None)
|
||
yield "({})/{}={}".format(
|
||
"+".join(lst),
|
||
total if total != 1 else 1,
|
||
self.achievement_level[class_index][i].achievement)
|
||
yield "考核材料清单"
|
||
|
||
y_str = (
|
||
f"1.{self.evaluation_stage[0][0]}成绩:{'、'.join([x for x in self.n_evaluation_methods[:3] if x is not None])};"
|
||
f"2.{self.evaluation_stage[1][0]}成绩:{'、'.join([x for x in self.n_evaluation_methods[3:5] if x is not None])};"
|
||
)
|
||
|
||
# 7.7
|
||
if len(self.n_evaluation_methods) == 6 and self.n_evaluation_methods[5] is not None:
|
||
y_str += f"3.{self.evaluation_stage[2][0]}成绩:{self.n_evaluation_methods[5]}"
|
||
else:
|
||
y_str += f"3.{self.evaluation_stage[2][0] if self.evaluation_stage[2][0] != '试卷' else '期末'}成绩:{self.evaluation_stage[2][0]}"
|
||
|
||
yield y_str
|
||
|
||
if len(self.class_list) == 1:
|
||
yield "课程目标达成值"
|
||
for i in range(self.kpi_number):
|
||
yield self.achievement_level[0][i].achievement
|
||
|
||
yield "课程目标达成结论"
|
||
for i in range(self.kpi_number):
|
||
if self.achievement_level[0][i].achievement >= 0.65:
|
||
yield "R达成(≥0.65) £未达成(<0.65)"
|
||
else:
|
||
yield "£达成(≥0.65) R未达成(<0.65)"
|
||
|
||
yield "结果分析"
|
||
|
||
analysis_results = f"1.总体目标:本门课程有{self.kpi_number}个课程目标,"
|
||
for index, p in enumerate(self.achievement_level[class_index]):
|
||
analysis_results += f"课程目标{index + 1}达成值为{p.achievement},"
|
||
if index + 1 == self.kpi_number:
|
||
analysis_results = analysis_results[:-1] + "。"
|
||
for i in range(self.kpi_number):
|
||
analysis_results += f"课程目标{i + 1}学生"
|
||
if self.achievement_level[class_index][i].rates[0] is not None:
|
||
analysis_results += \
|
||
(f"在{self.evaluation_stage[0][0]}环节中达到"
|
||
f"{get_rank(self.achievement_level[class_index][i].rates[0])}程度,")
|
||
|
||
if self.achievement_level[class_index][i].rates[1] is not None:
|
||
analysis_results += \
|
||
(f"在{self.evaluation_stage[1][0]}环节中"
|
||
f"表现{get_rank(self.achievement_level[class_index][i].rates[1])},")
|
||
|
||
if self.achievement_level[class_index][i].rates[2] is not None:
|
||
analysis_results += \
|
||
(f"在{self.evaluation_stage[2][0] if self.evaluation_stage[2][0] != '试卷' else '考试'}"
|
||
f"环节中为{get_rank(self.achievement_level[class_index][i].rates[2])}水平,")
|
||
|
||
analysis_results += f"总体目标{'达成' if self.achievement_level[class_index][i].achievement >= 0.65 else '未达成'};"
|
||
|
||
analysis_results = analysis_results[:-1] + "。"
|
||
c_lst = [x.achievement for x in self.achievement_level[class_index]]
|
||
min_index = min(enumerate(c_lst), key=lambda x: x[1])[0]
|
||
analysis_results += f"分析{self.kpi_number}个课程目标的达成值发现,课程目标{min_index + 1}的达成情况较差。"
|
||
analysis_results += "\n2.个体差异:"
|
||
for i in range(self.kpi_number):
|
||
l, r = get_class_index_range(self.class_number, class_index)
|
||
lst = min_score_people_name(self.stu_kpi_achieve_list, i, l, r)
|
||
analysis_results += f"对于课程目标{i + 1},"
|
||
if self.achievement_level[class_index][i].rates[0] is not None:
|
||
analysis_results += \
|
||
(f"{'、'.join(lst[0][:2])}{'等' if len(lst[0]) > 2 else ''}"
|
||
f"在{self.evaluation_stage[0][0]}考核中能力较弱,")
|
||
if self.achievement_level[class_index][i].rates[1] is not None:
|
||
analysis_results += \
|
||
(f"{'、'.join(lst[1][:2])}{'等' if len(lst[1]) > 2 else ''}"
|
||
f"在{self.evaluation_stage[1][0]}考核中能力较弱,")
|
||
if self.achievement_level[class_index][i].rates[2] is not None:
|
||
analysis_results += \
|
||
(f"{'、'.join(lst[2][:2])}{'等' if len(lst[2]) > 2 else ''}"
|
||
f"在{self.evaluation_stage[2][0] if self.evaluation_stage[2][0] != '试卷' else '考试'}中能力较弱;")
|
||
analysis_results = analysis_results[:-1] + "。"
|
||
yield analysis_results
|
||
yield "改进措施"
|
||
yield ("注:改进措施,包括课时分配、教材选用、教学方式、教学方法、教学内容、评分标准、过程评价及帮扶\n"
|
||
f"{self.suggestion_template_list[0] if self.suggestion_template_list[0] is not None else '\n\n\n在这填入您的改进措施\n\n\n'}")
|
||
for i in range(88888):
|
||
yield "如果您看到了本段文字,请联系开发者"
|
||
|
||
def get_word_template_part_2(self):
|
||
# self.get_word_template_part0()
|
||
yield "课程目标"
|
||
for i in range(self.kpi_number):
|
||
yield f"课程目标{i + 1} ({self.hml_list[i]})"
|
||
yield ("总成绩=\n{}".
|
||
format(
|
||
"\n+".join([f"{n if n != '试卷' else '期末'}成绩×{int(p * 100)}%" for n, p in self.evaluation_stage if
|
||
p is not None])))
|
||
for i in self.course_objectives:
|
||
yield i
|
||
yield "支撑毕业要求指标点"
|
||
for i in self.kpi_list:
|
||
yield i
|
||
yield "考核类型"
|
||
for i in range(self.kpi_number):
|
||
s_lst = self.achievement_level[0][i].scores
|
||
for index, (j, s) in enumerate(zip(self.evaluation_stage, s_lst)):
|
||
if s is None:
|
||
continue
|
||
if index == 2:
|
||
yield f"期末考核\n({j[0]})"
|
||
else:
|
||
yield f"{j[0]}考核"
|
||
|
||
yield "目标分值(分)"
|
||
for i in self.target_score:
|
||
for j in i:
|
||
if j is None:
|
||
continue
|
||
yield j
|
||
yield "权重"
|
||
for i in range(self.kpi_number):
|
||
s_lst = self.achievement_level[0][i].scores
|
||
for j, s in zip(self.evaluation_stage, s_lst):
|
||
if s is None:
|
||
continue
|
||
yield j[1]
|
||
min_rates = []
|
||
for index, i in enumerate(self.class_list):
|
||
yield i
|
||
for a_index, j in enumerate(self.achievement_level[index]):
|
||
if len(min_rates) - 1 < a_index:
|
||
min_rates.append(j.achievement)
|
||
else:
|
||
min_rates[a_index] = min(min_rates[a_index], j.achievement)
|
||
yield j.achievement
|
||
yield "课程目标达成值\n(取各班级最小值)"
|
||
for i in min_rates:
|
||
yield i
|
||
yield "课程目标达成结论"
|
||
for i in min_rates:
|
||
if i >= 0.65:
|
||
yield "R达成(≥0.65) £未达成(<0.65)"
|
||
else:
|
||
yield "£达成(≥0.65) R未达成(<0.65)"
|
||
yield "结果分析"
|
||
analysis_results = f"1.总体情况:\n 本门课程有{self.kpi_number}个课程目标,"
|
||
for i in range(self.kpi_number):
|
||
analysis_results += f"课程目标{i + 1}达成值为{min_rates[i]},"
|
||
analysis_results = analysis_results[:-1] + "。"
|
||
passed_c_lst = [f"课程目标{index + 1}" for index, x in enumerate(min_rates) if x >= 0.65]
|
||
not_passed_c_lst = [f"课程目标{index + 1}" for index, x in enumerate(min_rates) if x < 0.65]
|
||
if len(passed_c_lst) > 0:
|
||
analysis_results += (f"{'、'.join(passed_c_lst)}达到0.65的达成标准,"
|
||
f"表明学生在{'、'.join(passed_c_lst)}方面基本达到了本门课程提出的能力要求"
|
||
f"{';' if len(not_passed_c_lst) > 0 else '。'}")
|
||
if len(not_passed_c_lst) > 0:
|
||
analysis_results += (f"{'、'.join(not_passed_c_lst)}未达到0.65的达成标准,"
|
||
f"表明学生在{'、'.join(not_passed_c_lst)}方面未能达到课程提出的能力要求,"
|
||
f"学生能力还有待进一步加强。")
|
||
analysis_results += "\n2.班级差异:"
|
||
avg_c_lst = [sum(i.achievement for i in x) / len(x) for x in self.achievement_level]
|
||
top_index = max(enumerate(avg_c_lst), key=lambda x: x[1])[0]
|
||
bottom_index = min(enumerate(avg_c_lst), key=lambda x: x[1])[0]
|
||
analysis_results += (f"\n (1)班级对比:各班级之间比较而言,"
|
||
f"{self.class_list[top_index]}班的课程目标达成值相对较高,"
|
||
f"{self.class_list[bottom_index]}班的课程目标达成值较低。")
|
||
analysis_results += f"\n (2)同班级不同课程目标比较:分析{self.kpi_number}个课程目标的达成值发现,"
|
||
for i in range(len(self.class_list)):
|
||
min_p_rate_index = min(enumerate(self.achievement_level[i]), key=lambda x: x[1].achievement)[0]
|
||
o_c_str = [f'课程目标{x + 1}' for x in range(self.kpi_number) if x != min_p_rate_index]
|
||
analysis_results += (f"{self.class_list[i]}班的课程目标{min_p_rate_index + 1}达成情况最低,"
|
||
f"达成值为{self.achievement_level[i][min_p_rate_index].achievement},"
|
||
f"{'、'.join(o_c_str)}的达成情况较好;")
|
||
analysis_results = analysis_results[:-1] + "。"
|
||
analysis_results += ("\n3.结果分析: \n"
|
||
f"{self.suggestion_template_list[2] if self.suggestion_template_list[2] is not None else '\n\n\n在此填写您的结果分析\n\n\n'}")
|
||
yield analysis_results
|
||
yield "改进措施"
|
||
yield ("注:改进措施,包括课时分配、教材选用、教学方式、教学方法、教学内容、评分标准、过程评价及帮扶\n"
|
||
f"{self.suggestion_template_list[1] if self.suggestion_template_list[1] is not None else '\n\n\n在这填入您的改进措施\n\n\n'}")
|
||
for i in range(88888):
|
||
yield "如果您看到了本段文字,请联系开发者"
|
||
|
||
def get_word_template_part_3(self):
|
||
yield "课程目标达成情况合理性评价"
|
||
yield "评价样本的合理性"
|
||
yield "R全体样本 £抽样样本"
|
||
yield "评价依据的合理性"
|
||
yield "考核方法 R合适 £不合适 "
|
||
yield "考核内容是否支撑课程目标 R是 £否"
|
||
yield "评分标准 R明确 £不明确"
|
||
yield "计算过程的合理性"
|
||
yield "R合理正确 £合理但不够准确 £不合理"
|
||
yield "问题分析的合理性"
|
||
yield "R合理深入 £合理但不够深入 £不合理"
|
||
yield "改进措施的合理性"
|
||
yield "R合理可行 £合理但不太可行 £不合理"
|
||
yield "合理性评价结果"
|
||
yield "R合理 £基本合理 £不合理"
|
||
yield "专业负责人/系主任(签字)"
|
||
yield ("整改意见:\n"
|
||
"\n\n\n"
|
||
f"{self.suggestion_template_list[3] if self.suggestion_template_list[3] is not None else '\n\n\n'}"
|
||
f"\n\n\n\t\t\t\t\t\t\t\t\t签字:\t\t\t日期:{datetime.datetime.now().strftime("%Y-%m-%d")}\n")
|
||
yield "课程负责人(签字)"
|
||
yield ("拟整改计划与措施:\n"
|
||
"\n\n\n"
|
||
f"{self.suggestion_template_list[4] if self.suggestion_template_list[4] is not None else '\n\n\n'}"
|
||
f"\n\n\n\t\t\t\t\t\t\t\t\t签字:\t\t\t日期:{datetime.datetime.now().strftime("%Y-%m-%d")}\n")
|
||
for i in range(88888):
|
||
yield "如果您看到了本段文字,请联系开发者"
|
||
|
||
|
||
if __name__ == '__main__':
|
||
excel_reader = ExcelReader('../files/21工管-房屋建筑学-点名册-1227.xlsm')
|
||
excel_reader.parse_excel()
|
||
s, e = get_class_index_range(excel_reader.class_number, 1)
|
||
r = min_score_people_name(excel_reader.stu_kpi_achieve_list, 0, s, e)
|
||
gen_picture(excel_reader.stu_kpi_achieve_list, 3, s, e)
|
||
print()
|