Files
report-admin/backend/app/engines/scoring_engine.py
T
lofyerandfactory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> 71db82393a Initial commit
Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
2026-07-13 15:38:41 +08:00

851 lines
34 KiB
Python

"""
赋分引擎:将原始题目回答按赋分规则转换为分数
基于赋分整理表的规则,实现各类赋分函数
"""
import pandas as pd
import numpy as np
from typing import Dict, List, Optional, Tuple
import logging
import re
from ..config import DIMENSION_FRAMEWORK, SUBJECTS
from .data_engine import DataEngine
logger = logging.getLogger(__name__)
class ScoringEngine:
"""
赋分引擎
赋分逻辑基于"高中课程实施监测指标、题目、赋分整理0127.xlsx"
核心策略:按维度分组,从原始数据中提取相关字段,按规则赋分,
然后将赋分结果交给统计引擎做PCA合成
"""
def __init__(self, data_engine: DataEngine):
self.data_engine = data_engine
def score_all_schools(self) -> Dict[str, Dict[str, List[float]]]:
"""
对所有学校的所有维度进行赋分
返回: {
school_name: {
sub_dimension_name: [score1, score2, ...]
}
}
"""
result = {}
for school in self.data_engine.schools:
logger.info(f"正在对 {school} 进行赋分...")
result[school] = self._score_school(school)
return result
def _score_school(self, school: str) -> Dict[str, List[float]]:
"""对单个学校进行全维度赋分"""
scores = {}
# 课程领导力
scores["国家标准遵循"] = self._score_national_standard(school)
scores["课程结构建设"] = self._score_course_structure(school)
scores["课程规范落实"] = self._score_course_norms(school)
# 教学变革力
scores["教学方式变革"] = self._score_teaching_reform(school)
scores["作业设计与管理变革"] = self._score_homework_reform(school)
# 学生发展指导力
scores["学科发展的个性化辅导"] = self._score_personalized_tutoring(school)
scores["学生生涯发展指导"] = self._score_career_guidance(school)
# 教师发展支持力
scores["培训支持"] = self._score_training_support(school)
scores["教研支持"] = self._score_research_support(school)
scores["项目支持"] = self._score_project_support(school)
# 教育质量评估力
scores["科学评价观"] = self._score_scientific_evaluation(school)
scores["学业质量评估"] = self._score_academic_evaluation(school)
scores["综合素质评估"] = self._score_comprehensive_evaluation(school)
scores["实践活动评估"] = self._score_practice_evaluation(school)
# 教育条件保障力
scores["区域推进"] = self._score_regional_promotion(school)
scores["环境支持"] = self._score_environment_support(school)
scores["资源支持"] = self._score_resource_support(school)
# 数字化赋能力
scores["教学方式创新"] = self._score_digital_teaching(school)
scores["评价精准化与个性化"] = self._score_digital_evaluation(school)
scores["课程迭代优化"] = self._score_digital_curriculum(school)
return scores
# ========== 课程领导力 ==========
def _score_national_standard(self, school: str) -> List[float]:
"""
国家标准遵循:开足开齐国家课程
赋分:必修课程学分低于标准=0,高于标准=1,与标准一致=2
选必/选修课程:低于标准=0,达到标准=1
"""
scores = []
hours_df = self.data_engine.get_weekly_hours(school)
if len(hours_df) == 0:
return [1.0] # 默认中等
# 按课程类型汇总
for course_type, field_name in [
("必修", "学科必修课周课时"),
("选必", "学科选择性必修课周课时"),
("选修", "学科类选修课周课时"),
]:
type_df = hours_df[hours_df["字段名称"] == field_name]
if len(type_df) == 0:
scores.append(0.5)
continue
# 按学科汇总总课时
total = type_df.groupby("学科")["字段取值"].sum()
has_courses = (total > 0).sum()
total_hours = total.sum()
if course_type == "必修":
# 必修课:与标准一致=2,高于=1,低于=0
# 简化处理:有多少学科开了课
exam_subjects = ["语文", "数学", "英语", "物理", "化学", "生物学",
"历史", "地理", "思想政治"]
opened = sum(1 for s in exam_subjects if s in total.index and total.get(s, 0) > 0)
if opened >= len(exam_subjects):
scores.append(2.0)
elif opened >= 6:
scores.append(1.0)
else:
scores.append(0.0)
else:
# 选必/选修:达到标准=1,低于=0
if total_hours > 0:
scores.append(1.0)
else:
scores.append(0.0)
return scores if scores else [1.0]
def _score_course_structure(self, school: str) -> List[float]:
"""
课程结构建设:学科类课程结构、校本特色课程结构、综合实践活动与劳动
赋分:按照离差百分比和填报数值
"""
scores = []
hours_df = self.data_engine.get_weekly_hours(school)
if len(hours_df) > 0:
# 1. 学科类课程结构:各学科三类课程的离差
by_subject = hours_df.groupby(["学科", "字段名称"])["字段取值"].sum().unstack(fill_value=0)
if len(by_subject) > 0:
total_per_subject = by_subject.sum(axis=1)
overall_total = total_per_subject.sum()
if overall_total > 0:
proportions = total_per_subject / overall_total
mean_prop = proportions.mean()
deviation = np.abs(proportions - mean_prop).sum()
# 离差越小越好,标准化到0-3分
structure_score = max(0, 3 - deviation * 10)
scores.append(structure_score)
else:
scores.append(1.0)
else:
scores.append(1.0)
# 2. 校本特色课程:跨学科选修课门数、综合主题选修课门数
course_df = self.data_engine.get_school_course_data(school)
for field in ["跨学科选修课门数", "综合主题选修课门数", "综合实践选修课门数"]:
vals = course_df[course_df["字段名称"] == field]["字段取值"]
if len(vals) > 0:
try:
v = float(vals.iloc[0])
scores.append(min(v / 5, 3.0)) # 归一化
except (ValueError, TypeError):
scores.append(0.5)
# 3. 综合实践活动与劳动
for field in ["三年应完成的研究性学习数量", "三年社会考察个数", "三年志愿服务时长"]:
vals = course_df[course_df["字段名称"] == field]["字段取值"]
if len(vals) > 0:
try:
v = float(vals.iloc[0])
scores.append(min(v / 10, 3.0))
except (ValueError, TypeError):
scores.append(0.5)
return scores if scores else [1.0]
def _score_course_norms(self, school: str) -> List[float]:
"""
课程规范落实:建设规范文本 + 档案规范
赋分:有=2,无=0
"""
scores = []
norms = self.data_engine.get_course_norms(school)
norm_score = 0
archive_score = 0
norm_count = 0
archive_count = 0
for n in norms:
name = str(n.get("字段名称", ""))
val = str(n.get("字段取值", ""))
if "建设规范文本" in name:
norm_count += 1
if val and val not in ["0", "nan", "None", ""]:
norm_score += 2
elif "档案" in name:
archive_count += 1
if "已经建成并使用" in name and val == "1":
archive_score += 2
elif "已经建成" in name and val == "1":
archive_score += 1
if norm_count > 0:
scores.append(norm_score / norm_count * 2)
if archive_count > 0:
scores.append(archive_score / archive_count * 2)
return scores if scores else [1.0]
# ========== 教学变革力 ==========
def _score_teaching_reform(self, school: str) -> List[float]:
"""
教学方式变革:认识程度 + 落实程度 + 实施方式
赋分:量表题4/3/2/1分;多选每项1分加总
"""
scores = []
subject_df = self.data_engine.get_school_subject_data(school)
for subject in SUBJECTS:
sub_df = subject_df[subject_df["学科"] == subject]
sub_scores = []
# 认识程度类题目
for keyword in ["认识程度", "认识"]:
rows = sub_df[sub_df["字段名称"].str.contains(keyword, na=False)]
for _, row in rows.iterrows():
s = self._score_likert(row["字段取值"], reverse=False)
if s is not None:
sub_scores.append(s)
# 落实程度类题目
for keyword in ["落实程度", "落实"]:
rows = sub_df[sub_df["字段名称"].str.contains(keyword, na=False)]
for _, row in rows.iterrows():
s = self._score_likert(row["字段取值"], reverse=False)
if s is not None:
sub_scores.append(s)
# 实施方式(多选,体现形式类)
form_rows = sub_df[sub_df["字段名称"].str.contains("体现形式", na=False)]
if len(form_rows) > 0:
form_count = (form_rows["字段取值"].astype(str) == "1").sum()
sub_scores.append(min(form_count, 6))
if sub_scores:
scores.append(np.mean(sub_scores))
return scores if scores else [2.0]
def _score_homework_reform(self, school: str) -> List[float]:
"""
作业设计与管理变革:作业设计 + 作业管理
"""
scores = []
subject_df = self.data_engine.get_school_subject_data(school)
for subject in SUBJECTS:
sub_df = subject_df[subject_df["学科"] == subject]
sub_scores = []
# 作业设计:实践类/表现类/跨学科/团队合作作业是否布置
for hw_type in ["实践类作业_有布置", "表现类作业_有布置", "跨学科作业_有布置", "团队合作类作业_有布置"]:
rows = sub_df[sub_df["字段名称"] == hw_type]
if len(rows) > 0 and str(rows.iloc[0]["字段取值"]) == "1":
sub_scores.append(1.0)
else:
sub_scores.append(0.0)
# 作业属性标注(多选)
attr_rows = sub_df[sub_df["字段名称"].str.contains("作业属性标注", na=False)]
if len(attr_rows) > 0:
attr_count = (attr_rows["字段取值"].astype(str) == "1").sum()
sub_scores.append(min(attr_count, 5))
# 作业管理:时长控制、批改、评价
for field, score_map in [
("回家作业时长控制_学校控制", 3),
("回家作业时长控制_教研组负责", 2),
("作业批改范围_全部批改", 3),
("作业批改范围_部分练习", 1),
]:
rows = sub_df[sub_df["字段名称"] == field]
if len(rows) > 0 and str(rows.iloc[0]["字段取值"]) == "1":
sub_scores.append(score_map)
if sub_scores:
scores.append(np.mean(sub_scores))
return scores if scores else [1.5]
# ========== 学生发展指导力 ==========
def _score_personalized_tutoring(self, school: str) -> List[float]:
"""个性化辅导"""
scores = []
subject_df = self.data_engine.get_school_subject_data(school)
for subject in SUBJECTS:
sub_df = subject_df[subject_df["学科"] == subject]
# 辅导时长
for field, val in [
("个别辅导时长_每周>2h", 4),
("个别辅导时长_每周1~2h", 3),
("个别辅导时长_每周<1h", 2),
("个别辅导时长_几乎无", 1),
]:
rows = sub_df[sub_df["字段名称"] == field]
if len(rows) > 0 and str(rows.iloc[0]["字段取值"]) == "1":
scores.append(val)
break
# 辅导方式
for field, val in [
("个别辅导实施方式_分散辅导", 3),
("个别辅导实施方式_分组统一辅导", 2),
("个别辅导实施方式_班级统一辅导", 1),
]:
rows = sub_df[sub_df["字段名称"] == field]
if len(rows) > 0 and str(rows.iloc[0]["字段取值"]) == "1":
scores.append(val)
break
return scores if scores else [2.0]
def _score_career_guidance(self, school: str) -> List[float]:
"""生涯发展指导"""
scores = []
course_df = self.data_engine.get_school_course_data(school)
# 生涯指导实施方式
for field, val in [
("生涯指导实施方式_专设课程", 3),
("生涯指导实施方式_社会考察和志愿服务", 2),
]:
rows = course_df[course_df["字段名称"] == field]
if len(rows) > 0 and str(rows.iloc[0]["字段取值"]) == "1":
scores.append(val)
# 覆盖率
rows = course_df[course_df["字段名称"] == "完成生涯指导的学生占比_90%+"]
if len(rows) > 0 and str(rows.iloc[0]["字段取值"]) == "1":
scores.append(4)
else:
scores.append(2)
# 教师构成
for field, val in [
("生涯指导教师构成_本校和外聘结合", 4),
("生涯指导教师构成_本校为主", 3),
]:
rows = course_df[course_df["字段名称"] == field]
if len(rows) > 0 and str(rows.iloc[0]["字段取值"]) == "1":
scores.append(val)
break
# 资源支持
for resource in ["生涯指导的校外资源支持程度", "生涯指导的校内资源支持程度"]:
rows = course_df[course_df["字段名称"] == resource]
if len(rows) > 0:
s = self._score_resource_level(rows.iloc[0]["字段取值"])
if s is not None:
scores.append(s)
return scores if scores else [2.0]
# ========== 教师发展支持力 ==========
def _score_training_support(self, school: str) -> List[float]:
"""培训支持"""
scores = []
subject_df = self.data_engine.get_school_subject_data(school)
for subject in SUBJECTS:
sub_df = subject_df[subject_df["学科"] == subject]
# 提供外校培训的教师人数
rows = sub_df[sub_df["字段名称"] == "提供外校培训的教师人数"]
if len(rows) > 0:
try:
v = float(rows.iloc[0]["字段取值"])
scores.append(min(v, 5))
except (ValueError, TypeError):
pass
# 区域培训指导人数
rows = sub_df[sub_df["字段名称"] == "区域培训指导人数"]
if len(rows) > 0:
try:
v = float(rows.iloc[0]["字段取值"])
scores.append(min(v, 5))
except (ValueError, TypeError):
pass
return scores if scores else [1.0]
def _score_research_support(self, school: str) -> List[float]:
"""教研支持"""
scores = []
subject_df = self.data_engine.get_school_subject_data(school)
for subject in SUBJECTS:
sub_df = subject_df[subject_df["学科"] == subject]
# 教研活动次数
rows = sub_df[sub_df["字段名称"] == "学科教研组每学期活动次数"]
if len(rows) > 0:
try:
v = float(rows.iloc[0]["字段取值"])
scores.append(min(v / 3, 4)) # 归一化
except (ValueError, TypeError):
pass
# 教研活动时长
rows = sub_df[sub_df["字段名称"] == "学科教研组平均每次活动时长"]
if len(rows) > 0:
try:
v = float(rows.iloc[0]["字段取值"])
scores.append(min(v / 30, 4)) # 30分钟为基准
except (ValueError, TypeError):
pass
# 教研计划
rows = sub_df[sub_df["字段名称"] == "学科教研工作计划_有"]
if len(rows) > 0 and str(rows.iloc[0]["字段取值"]) == "1":
scores.append(2)
# 校级展示
for field in ["学科教研组校级展示_有", "学科教研组区域展示_有", "学科教研组成果发表_有"]:
rows = sub_df[sub_df["字段名称"] == field]
if len(rows) > 0 and str(rows.iloc[0]["字段取值"]) == "1":
scores.append(2)
return scores if scores else [1.0]
def _score_project_support(self, school: str) -> List[float]:
"""项目支持"""
scores = []
subject_df = self.data_engine.get_school_subject_data(school)
course_df = self.data_engine.get_school_course_data(school)
# 学科层面的项目
for subject in SUBJECTS:
sub_df = subject_df[subject_df["学科"] == subject]
for field in ["学科承担的市级教改项目个数", "学科承担的区级教改项目个数", "学科承担的校级教改项目个数"]:
rows = sub_df[sub_df["字段名称"] == field]
if len(rows) > 0:
try:
v = float(rows.iloc[0]["字段取值"])
scores.append(min(v, 5))
except (ValueError, TypeError):
pass
# 学校层面的项目
for field in ["学校负责的市级教改项目个数", "学校参与的市级教改项目个数",
"学校负责的区级教改项目个数", "学校参与的区级教改项目个数",
"校级教改项目个数"]:
rows = course_df[course_df["字段名称"] == field]
if len(rows) > 0:
try:
v = float(rows.iloc[0]["字段取值"])
scores.append(min(v, 5))
except (ValueError, TypeError):
pass
return scores if scores else [0.5]
# ========== 教育质量评估力 ==========
def _score_scientific_evaluation(self, school: str) -> List[float]:
"""科学评价观"""
scores = []
subject_df = self.data_engine.get_school_subject_data(school)
for subject in SUBJECTS:
sub_df = subject_df[subject_df["学科"] == subject]
# 作业评价关注点(多选,关注素养发展的项目越多越好)
eval_items = sub_df[sub_df["字段名称"].str.contains("作业评价关注点|课堂表现评价关注点|学科实践活动评价关注点", na=False)]
if len(eval_items) > 0:
focus_count = (eval_items["字段取值"].astype(str) == "1").sum()
scores.append(min(focus_count / 3, 4))
return scores if scores else [2.0]
def _score_academic_evaluation(self, school: str) -> List[float]:
"""学业质量评估"""
scores = []
subject_df = self.data_engine.get_school_subject_data(school)
for subject in SUBJECTS:
sub_df = subject_df[subject_df["学科"] == subject]
# 评价工具建成
for field, val in [
("作业评价工具_已经建成并使用", 2),
("课堂表现评价工具_已经建成并使用", 2),
("作业评价工具_已经建成尚未使用", 1),
("作业评价工具_尚未建成和使用", 0),
]:
rows = sub_df[sub_df["字段名称"] == field]
if len(rows) > 0 and str(rows.iloc[0]["字段取值"]) == "1":
scores.append(val)
break
# 考试分析
for field, val in [
("学期考试分析_执行分析并存档", 3),
("学期考试分析_执行分析,不要求存档", 2),
("学期考试分析_教师自己决定", 1),
]:
rows = sub_df[sub_df["字段名称"] == field]
if len(rows) > 0 and str(rows.iloc[0]["字段取值"]) == "1":
scores.append(val)
break
# 表现性评价应用
for field, val in [
("表现性评价应用程度_经常", 4),
("表现性评价应用程度_有时", 3),
("表现性评价应用程度_总是", 4),
("表现性评价应用程度_从不", 1),
]:
rows = sub_df[sub_df["字段名称"] == field]
if len(rows) > 0 and str(rows.iloc[0]["字段取值"]) == "1":
scores.append(val)
break
return scores if scores else [2.0]
def _score_comprehensive_evaluation(self, school: str) -> List[float]:
"""综合素质评估"""
scores = []
course_df = self.data_engine.get_school_course_data(school)
# 综评评价体系
for field, val in [
("综评评价体系_已经建成并使用", 3),
("综评评价体系_已经建成尚未使用", 2),
("综评评价体系_未建成", 1),
("综评评价体系_不准备建设", 0),
]:
rows = course_df[course_df["字段名称"] == field]
if len(rows) > 0 and str(rows.iloc[0]["字段取值"]) == "1":
scores.append(val)
break
# 综评信息化
for field, val in [
("综评信息化实现_自建平台支持", 2),
("综评信息化实现_借助第三方平台支持", 1),
]:
rows = course_df[course_df["字段名称"] == field]
if len(rows) > 0 and str(rows.iloc[0]["字段取值"]) == "1":
scores.append(val)
break
# 综评结果使用(多选)
result_uses = course_df[course_df["字段名称"].str.contains("综评结果使用|综评应用", na=False)]
if len(result_uses) > 0:
use_count = (result_uses["字段取值"].astype(str) == "1").sum()
scores.append(min(use_count, 6))
return scores if scores else [1.0]
def _score_practice_evaluation(self, school: str) -> List[float]:
"""实践活动评估"""
scores = []
course_df = self.data_engine.get_school_course_data(school)
# 研究性学习评价
for field, val in [
("研究性学习评价工具_已经建成并使用", 2),
("研究性学习评价工具_尚未建成和使用", 0),
]:
rows = course_df[course_df["字段名称"] == field]
if len(rows) > 0 and str(rows.iloc[0]["字段取值"]) == "1":
scores.append(val)
break
# 社会考察评价
for field, val in [
("社会考察评价工具_已经建成并使用", 2),
("社会考察评价工具_尚未建成和使用", 0),
]:
rows = course_df[course_df["字段名称"] == field]
if len(rows) > 0 and str(rows.iloc[0]["字段取值"]) == "1":
scores.append(val)
break
# 学科实践活动评价
subject_df = self.data_engine.get_school_subject_data(school)
for subject in SUBJECTS[:5]: # 抽样几个学科
sub_df = subject_df[subject_df["学科"] == subject]
for field, val in [
("学科实践活动工具_已经建成并使用", 2),
("学科实践活动工具_已经建成尚未使用", 1),
("学科实践活动工具_尚未建成和使用", 0),
]:
rows = sub_df[sub_df["字段名称"] == field]
if len(rows) > 0 and str(rows.iloc[0]["字段取值"]) == "1":
scores.append(val)
break
return scores if scores else [1.0]
# ========== 教育条件保障力 ==========
def _score_regional_promotion(self, school: str) -> List[float]:
"""区域推进"""
scores = []
course_df = self.data_engine.get_school_course_data(school)
# 工作会频率
for field, val in [
("区域工作会参与_一月4次以上", 7),
("区域工作会参与_一月1次", 5),
("区域工作会参与_二月1次", 3),
("区域工作会参与_三月1次", 1),
]:
rows = course_df[course_df["字段名称"] == field]
if len(rows) > 0 and str(rows.iloc[0]["字段取值"]) == "1":
scores.append(val)
break
# 区域推进措施(多选)
measures = course_df[course_df["字段名称"].str.contains("区域推进措施", na=False)]
if len(measures) > 0:
measure_count = (measures["字段取值"].astype(str) == "1").sum()
scores.append(min(measure_count, 5))
return scores if scores else [2.0]
def _score_environment_support(self, school: str) -> List[float]:
"""环境支持:硬件+信息化"""
scores = []
course_df = self.data_engine.get_school_course_data(school)
# 场馆供给
for field, val in [
("场馆供给_能满足需要", 3),
("场馆供给_基本满足需要", 2),
("场馆供给_难以满足需要", 1),
]:
rows = course_df[course_df["字段名称"] == field]
if len(rows) > 0 and str(rows.iloc[0]["字段取值"]) == "1":
scores.append(val)
break
# 专用教室供给
for field, val in [
("专用教室供给_能满足需要", 3),
("专用教室供给_基本满足需要", 2),
]:
rows = course_df[course_df["字段名称"] == field]
if len(rows) > 0 and str(rows.iloc[0]["字段取值"]) == "1":
scores.append(val)
break
# 信息化平台功能(多选)
info_funcs = course_df[course_df["字段名称"].str.contains("信息化平台功能", na=False)]
if len(info_funcs) > 0:
func_count = (info_funcs["字段取值"].astype(str) == "1").sum()
scores.append(min(func_count / 3, 5))
return scores if scores else [2.0]
def _score_resource_support(self, school: str) -> List[float]:
"""资源支持:校内资源 + 校外资源 + 师资配置"""
scores = []
subject_df = self.data_engine.get_school_subject_data(school)
for subject in SUBJECTS:
sub_df = subject_df[subject_df["学科"] == subject]
# 校内资源支持程度
for field in ["必修课校内资源支持程度", "选择性必修课校内资源支持程度"]:
rows = sub_df[sub_df["字段名称"] == field]
if len(rows) > 0:
s = self._score_resource_level(rows.iloc[0]["字段取值"])
if s is not None:
scores.append(s)
# 校外资源支持程度
for field in ["必修课校外资源支持程度", "选择性必修课校外资源支持程度"]:
rows = sub_df[sub_df["字段名称"] == field]
if len(rows) > 0:
s = self._score_resource_level(rows.iloc[0]["字段取值"])
if s is not None:
scores.append(s)
# 师资:教研组总人数、高级教师比例等
rows = sub_df[sub_df["字段名称"] == "学科教研组总人数"]
if len(rows) > 0:
try:
total = float(rows.iloc[0]["字段取值"])
scores.append(min(total / 3, 4))
except (ValueError, TypeError):
pass
return scores if scores else [2.0]
# ========== 数字化赋能力 ==========
def _score_digital_teaching(self, school: str) -> List[float]:
"""教学方式创新"""
scores = []
subject_df = self.data_engine.get_school_subject_data(school)
for subject in SUBJECTS:
sub_df = subject_df[subject_df["学科"] == subject]
# 信息技术融合认识
for field in ["信息技术与教学融合的认识_所有人可做到"]:
rows = sub_df[sub_df["字段名称"] == field]
if len(rows) > 0 and str(rows.iloc[0]["字段取值"]) == "1":
scores.append(4)
break
else:
rows = sub_df[sub_df["字段名称"] == "信息技术与教学融合的认识_个别人可做到"]
if len(rows) > 0 and str(rows.iloc[0]["字段取值"]) == "1":
scores.append(1)
# 信息化终端使用比例
for field, val in [
("信息化终端使用比例_80%+", 4),
("信息化终端使用比例_60~79%", 3),
("信息化终端使用比例_30~59%", 2),
("信息化终端使用比例_30%-", 1),
]:
rows = sub_df[sub_df["字段名称"] == field]
if len(rows) > 0 and str(rows.iloc[0]["字段取值"]) == "1":
scores.append(val)
break
return scores if scores else [2.0]
def _score_digital_evaluation(self, school: str) -> List[float]:
"""评价精准化与个性化"""
scores = []
subject_df = self.data_engine.get_school_subject_data(school)
course_df = self.data_engine.get_school_course_data(school)
# 学业评价信息化
for subject in SUBJECTS:
sub_df = subject_df[subject_df["学科"] == subject]
for field, val in [
("学业评价信息化实现_自建平台支持", 3),
("学业评价信息化实现_借助第三方平台支持", 2),
("学业评价信息化实现_没有平台支持", 0),
]:
rows = sub_df[sub_df["字段名称"] == field]
if len(rows) > 0 and str(rows.iloc[0]["字段取值"]) == "1":
scores.append(val)
break
# 学校层面的信息化支持
for field, val in [
("学校信息系统对选课支持程度", None),
("学校信息系统对排课支持程度", None),
]:
rows = course_df[course_df["字段名称"] == field]
if len(rows) > 0:
s = self._score_resource_level(rows.iloc[0]["字段取值"])
if s is not None:
scores.append(s)
return scores if scores else [1.5]
def _score_digital_curriculum(self, school: str) -> List[float]:
"""课程迭代优化"""
scores = []
course_df = self.data_engine.get_school_course_data(school)
# 数据连通
for field, val in [
("数据连通_有数据能互通", 3),
("数据连通_有数据不互通", 1),
]:
rows = course_df[course_df["字段名称"] == field]
if len(rows) > 0 and str(rows.iloc[0]["字段取值"]) == "1":
scores.append(val)
break
# 管理业务信息化
for field, val in [
("管理业务的信息化应用_绝大部分", 4),
("教学业务的信息化应用_绝大部分", 4),
]:
rows = course_df[course_df["字段名称"] == field]
if len(rows) > 0 and str(rows.iloc[0]["字段取值"]) == "1":
scores.append(val)
# 已完成网络课程数
rows = course_df[course_df["字段名称"] == "已完成的网络课程门数"]
if len(rows) > 0:
try:
v = float(rows.iloc[0]["字段取值"])
scores.append(min(v / 3, 4))
except (ValueError, TypeError):
pass
return scores if scores else [1.5]
# ========== 辅助赋分函数 ==========
@staticmethod
def _score_likert(value, scale: int = 4, reverse: bool = False) -> Optional[float]:
"""
量表题赋分
value格式可能是 "1" 或 "2(有一些支持)" 等
"""
try:
val_str = str(value).strip()
# 提取数字部分
match = re.match(r'^(\d+)', val_str)
if match:
v = int(match.group(1))
if reverse:
return float(scale + 1 - v)
return float(v)
except (ValueError, TypeError):
pass
return None
@staticmethod
def _score_resource_level(value) -> Optional[float]:
"""资源支持程度赋分:几乎没有=1, 有一些=2, 有足够=3"""
val_str = str(value).strip()
match = re.match(r'^(\d+)', val_str)
if match:
v = int(match.group(1))
return float(v)
if "足够" in val_str or "3" in val_str:
return 3.0
elif "一些" in val_str or "2" in val_str:
return 2.0
elif "没有" in val_str or "1" in val_str:
return 1.0
return None