nex_math/backend/services/learning_profile.py

77 lines
2.4 KiB
Python

"""学习账号初始化与清理(用户掌握度按全局 Knowledge 节点记录)。"""
from __future__ import annotations
from sqlalchemy.orm import Session
from sqlalchemy import text
from models import (
AttemptItem,
AttemptSession,
DailyCompletion,
ErrorEntry,
Role,
User,
UserKnowledge,
UserRole,
)
from seed.rbac import DEFAULT_USERS
def user_has_admin_role(db: Session, user_id: int) -> bool:
return (
db.query(Role.id)
.join(UserRole, UserRole.role_id == Role.id)
.filter(Role.code == "admin", UserRole.user_id == user_id)
.first()
is not None
)
def ensure_profile(db: Session, user_id: int) -> None:
"""新学习账号无需预置掌握度:从第一次章节测试起由答题结果生成。"""
db.commit()
def ensure_default_profiles(db: Session) -> None:
"""默认学生账号同样从空学习记录开始,管理员不建学习档案。"""
for username, _, _, _ in DEFAULT_USERS:
user = db.query(User).filter(User.username == username).first()
if user is None or user_has_admin_role(db, user.id):
continue
ensure_profile(db, user.id)
def remove_unused_admin_profile(db: Session, user_id: int) -> None:
"""管理员不保留学习数据。"""
db.query(UserKnowledge).filter(UserKnowledge.user_id == user_id).delete()
db.query(ErrorEntry).filter(ErrorEntry.user_id == user_id).delete()
db.query(AttemptItem).filter(AttemptItem.user_id == user_id).delete()
db.query(AttemptSession).filter(AttemptSession.user_id == user_id).delete()
db.query(DailyCompletion).filter(DailyCompletion.user_id == user_id).delete()
db.commit()
def reset_user_learning(db: Session, user_id: int) -> None:
remove_unused_admin_profile(db, user_id)
def reset_all_learning(db: Session) -> None:
db.query(UserKnowledge).delete()
db.query(ErrorEntry).delete()
db.query(AttemptItem).delete()
db.query(AttemptSession).delete()
db.query(DailyCompletion).delete()
db.execute(text("DROP TABLE IF EXISTS knowledge_points"))
for table_name, column in (
("chapters", "knowledge_names"),
("questions", "knowledge_names"),
):
try:
db.execute(
text(f"ALTER TABLE {table_name} DROP COLUMN {column}")
)
except Exception:
# 新库本来就没有这些旧文本列,忽略
pass
db.commit()