nex_math/backend/seed/catalog.py

390 lines
16 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

"""教材与在线课程种子数据(两张表分别写入)。
教材以《盖尔范德中学生数学思维丛书》(中国科学技术大学出版社)为基础;
书号 / 出版信息均核对公开书目信息,课程使用官方站点链接。
"""
from __future__ import annotations
from sqlalchemy.orm import Session
from models import Chapter, ChapterKnowledge, Course, Knowledge, Question, Textbook
from services.knowledge_service import (
ensure_knowledge_resource,
set_chapter_knowledge_names,
)
# 现有题库知识点与《函数和图像》章节的对应关系(按丛书内容就近归类)
KNOWLEDGE_CHAPTER_MAP = {
"函数概念": "引言",
"函数值": "引言",
"定义域": "引言",
"正负性": "引言",
"零点": "第4章 二次三项式",
"偶函数": "第6章 幂函数",
"奇函数": "第6章 幂函数",
"图像对称性": "第6章 幂函数",
}
DEFAULT_CHAPTER_KNOWLEDGE = {
"引言": ["函数概念", "函数值", "定义域", "正负性"],
"第4章 二次三项式": ["零点"],
"第6章 幂函数": ["偶函数", "奇函数", "图像对称性"],
"第1章 三角函数": ["三角函数"],
"第2章 三角形中的三角比": ["三角比", "直角三角形"],
"第3章 三角比之间的关系": ["三角恒等式", "同角关系"],
"第4章 三角形内的关系": ["正弦定理", "余弦定理"],
"第5章 角与旋转": ["任意角", "弧度制"],
"第6章 弧度法": ["弧度制", "弧长与扇形"],
"第7章 加法公式": ["和角公式", "差角公式"],
"第8章 三角恒等式": ["倍角公式", "三角恒等式"],
"第9章 三角函数的图形": ["三角函数图像", "周期函数"],
"第10章 反函数与三角方程": ["反三角函数", "三角方程"],
"点与直线:走进射影几何": ["点线面的基本关系", "几何变换"],
"平行线:走进仿射几何": ["平行与垂直"],
"面积:走进辛几何": ["面积与周长"],
"圆:走进欧氏几何": ["圆"],
"绪论": ["数轴", "平面直角坐标系"],
"第1章 直线上点的坐标": ["数轴", "实数", "两点间距离"],
"第2章 平面里点的坐标": [
"平面直角坐标系",
"两点间距离",
"曲线与方程",
],
"第3章 三维空间里点的坐标": ["平面直角坐标系", "点线面的基本关系"],
"第4章 引言": ["平面直角坐标系", "曲线与方程"],
"第5章 四维空间": ["平面直角坐标系", "曲线与方程"],
"第6章 四维方体": ["平面直角坐标系", "曲线与方程"],
}
# 在线课程 / 视频与知识点的默认关联(知识点 → 课程资源反向链接)。
COURSE_KNOWLEDGE_MAP = {
"Khan Academy · Algebra 1: Functions": [
"函数与图像",
"函数概念",
"函数值",
"定义域",
"值域",
"零点",
"单调性",
"奇偶性",
"偶函数",
"奇函数",
"图像对称性",
"一次函数",
"函数图像与变换",
],
"3Blue1Brown · Essence of Calculus": [
"极限与连续",
"导数与微分",
"一元函数积分",
],
"国家中小学智慧教育平台 · 高中数学(人教A版)": [
"二次函数",
"抛物线",
"幂函数",
"三角函数",
"任意角",
"弧度制",
"三角比",
"同角三角函数关系",
"和角与差角公式",
"三角恒等式",
"三角函数图像",
"解三角形",
"直线方程",
],
}
# 以正式出版目录为准的官方章节模板(中文书名/ISBN 来自中国科学技术大学出版社版本)。
OFFICIAL_PRIMARY_CHAPTERS = [
{"name": "引言", "summary": "函数、自变量、定义域与函数值:从真实图像理解函数。"},
{"name": "第1章 例子", "summary": "不同函数图像的直观例子与作图方法。"},
{"name": "第2章 线性函数", "summary": "一次函数的图像、斜率与直线。"},
{"name": "第3章 函数 y=|x|", "summary": "绝对值函数的图像与性质,关于 y 轴对称的典型例子。"},
{"name": "第4章 二次三项式", "summary": "二次函数图像、配方、判别式与零点。"},
{"name": "第5章 分式线性函数", "summary": "y=1/x 类函数图像与渐近行为。"},
{"name": "第6章 幂函数", "summary": "y=x、y=x²、y=x³ 等幂函数的奇偶性与对称性。"},
{"name": "第7章 有理函数", "summary": "更一般的有理函数图像与性质综合。"},
]
OFFICIAL_TRIG_CHAPTERS = [
{"name": "第1章 三角函数", "summary": "从角与旋转进入三角函数,建立正弦、余弦、正切的基本概念。"},
{"name": "第2章 三角形中的三角比", "summary": "在直角三角形中定义正弦、余弦与正切,理解锐角三角比。"},
{"name": "第3章 三角比之间的关系", "summary": "同角三角比的关系、互余关系与基本恒等式推导。"},
{"name": "第4章 三角形内的关系", "summary": "正弦定理、余弦定理以及三角形中边角关系的应用。"},
{"name": "第5章 角与旋转", "summary": "把角推广到任意旋转角,定义任意角的三角函数。"},
{"name": "第6章 弧度法", "summary": "引入弧度制,理解弧长、扇形与角度制换算。"},
{"name": "第7章 加法公式", "summary": "两角和与差的三角函数公式及其几何与代数证明。"},
{"name": "第8章 三角恒等式", "summary": "倍角、半角与和差化积等常用三角恒等式。"},
{"name": "第9章 三角函数的图形", "summary": "正弦、余弦、正切函数的图像、周期与变换。"},
{"name": "第10章 反函数与三角方程", "summary": "反三角函数的基本概念与三角方程的求解方法。"},
]
OFFICIAL_COORDINATE_CHAPTERS = [
{"name": "绪论", "summary": "用坐标把几何问题转化为代数问题的方法引言。"},
{"name": "第1章 直线上点的坐标", "summary": "数轴、数的绝对值与两点之间的距离。"},
{"name": "第2章 平面里点的坐标", "summary": "坐标平面、坐标间关系、距离公式、确定平面图形与其他坐标系。"},
{"name": "第3章 三维空间里点的坐标", "summary": "空间坐标轴与坐标平面,确定空间中的图形。"},
{"name": "第4章 引言", "summary": "从三维推广到四维空间的动机:几何、计算与物理。"},
{"name": "第5章 四维空间", "summary": "四维空间中的坐标轴、坐标平面与距离问题。"},
{"name": "第6章 四维方体", "summary": "球与方体的定义、四维方体的结构与相关问题。"},
]
OFFICIAL_GEOMETRY_CHAPTERS = [
{"name": "点与直线:走进射影几何", "summary": "从点与直线的位置关系出发理解射影几何的基本思想。"},
{"name": "平行线:走进仿射几何", "summary": "以平行关系为线索建立仿射几何的直观框架。"},
{"name": "面积:走进辛几何", "summary": "通过面积概念与保持面积变换认识辛几何。"},
{"name": "圆:走进欧氏几何", "summary": "以圆为核心回到经典欧氏几何的结构与性质。"},
]
COURSES = [
{
"name": "Khan Academy · Algebra 1: Functions",
"provider": "Khan Academy",
"url": "https://www.khanacademy.org/math/algebra/x2f8bb11595b61c86:functions",
"grade": "初中衔接 / 高中",
"description": (
"函数单元含函数求值、定义域值域、函数图像与性质等大量免费练习,"
"英文界面,适合配合盖尔范德丛书做自动化巩固。"
),
},
{
"name": "3Blue1Brown · Essence of Calculus",
"provider": "3Blue1Brown",
"url": "https://www.youtube.com/playlist?list=PLZHQObOWTQDMsr9K-rj53DwVRMYO3t5Yr",
"grade": "高中高年级 / 大学先修",
"description": (
"微积分本质系列:从几何直觉理解导数与积分,适合函数图像直觉建立后"
"进入微积分阶段使用。"
),
},
{
"name": "国家中小学智慧教育平台 · 高中数学(人教A版)",
"provider": "教育部教育技术与资源发展中心",
"url": "https://basic.smartedu.cn/syncClassroom",
"grade": "高中全学段",
"description": (
"官方免费同步课程与配套课件,可按教材版本与册次点播,"
"适合做课内进度对照。"
),
},
]
OFFICIAL_CHAPTERS_BY_ISBN = {}
CATALOG = [
{
"name": "函数和图像(盖尔范德中学生数学思维丛书)",
"author": "I. M. Gelfand, E. G. Glagoleva, E. E. Shnol 著;麻希南、胡长青 译",
"publisher": "中国科学技术大学出版社",
"isbn": "9787312050053",
"edition": "2020年12月第1版",
"grade": "初中至高中低年级",
"link": "",
"description": (
"本系统的主教材。以大量真实图像(地震图、心电图等)引入函数,"
"强调“画图就是看见公式”,系统训练函数概念、图像与性质直觉;"
"英译本 Functions and Graphs 由 Dover 出版。现有函数与对称性题库"
"以本书为依据。"
),
"chapters": [],
},
{
"name": "代数(盖尔范德中学生数学思维丛书)",
"author": "I. M. Gelfand, A. Shen 著;胡长青、麻希南 译",
"publisher": "中国科学技术大学出版社",
"isbn": "9787312048937",
"edition": "2020年第1版",
"grade": "初中至高中低年级",
"link": "",
"description": (
"用问题驱动的叙述串联自然数、负数、代数式与方程,"
"重视“为什么可以这样变形”的代数思维,适合作为代数学基础。"
),
"chapters": [],
},
{
"name": "几何(盖尔范德中学生数学思维丛书)",
"author": "I. M. Gelfand 等 著",
"publisher": "中国科学技术大学出版社",
"isbn": "9787312057793",
"edition": "2023年第1版",
"grade": "初中至高中低年级",
"link": "",
"description": (
"以直观可视的方式从图形构造逐步建立几何,突出“先看见、再证明”"
"的思维路线。"
),
"chapters": [],
},
{
"name": "三角函数(盖尔范德中学生数学思维丛书)",
"author": "I. M. Gelfand, M. Saul 著;王作勤 译",
"publisher": "中国科学技术大学出版社",
"isbn": "9787312046957",
"edition": "2020年第1版",
"grade": "初中至高中低年级",
"link": "",
"description": (
"从初等几何直觉进入正弦、余弦与正切,解释周期与波动现象的数学本质。"
),
"chapters": [],
},
{
"name": "坐标方法(盖尔范德中学生数学思维丛书)",
"author": "I. M. Gelfand, E. G. Glagoleva, A. A. Kirillov 著;王作勤 译",
"publisher": "中国科学技术大学出版社",
"isbn": "9787312050060",
"edition": "2020年12月第1版",
"grade": "初中至高中低年级",
"link": "",
"description": (
"讲解如何用坐标把几何问题转化为代数问题,是解析几何与函数图像"
"方法的基础。"
),
"chapters": [],
},
]
def ensure_catalog(db: Session, force_sync: bool = False) -> None:
"""仅在空库时写入默认目录;管理员后续可自由增删改并持久保留。"""
_ensure_courses(db)
if db.query(Textbook).count() > 0 and not force_sync:
# 存量库不覆盖用户修改,但会补齐新增的“官方正式目录”章节
for item in CATALOG:
textbook = (
db.query(Textbook)
.filter(Textbook.name == item["name"])
.first()
)
if textbook is None or not item["chapters"]:
continue
existing = {
chapter.name: chapter
for chapter in db.query(Chapter)
.filter(Chapter.textbook_id == textbook.id)
.all()
}
position = len(existing)
for chapter in item["chapters"]:
if chapter["name"] not in existing:
db.add(
Chapter(
textbook_id=textbook.id,
name=chapter["name"],
position=position,
summary=chapter["summary"],
)
)
position += 1
_sync_default_chapter_knowledge(db)
_sync_default_course_resources(db)
db.commit()
return
for position, item in enumerate(CATALOG):
textbook = db.query(Textbook).filter(Textbook.name == item["name"]).first()
if textbook is None:
textbook = Textbook(name=item["name"], position=position)
db.add(textbook)
db.flush()
textbook.author = item["author"]
textbook.publisher = item["publisher"]
textbook.isbn = item["isbn"]
textbook.edition = item["edition"]
textbook.grade = item["grade"]
textbook.link = item["link"]
textbook.description = item["description"]
textbook.position = position
existing = {
chapter.name: chapter
for chapter in db.query(Chapter)
.filter(Chapter.textbook_id == textbook.id)
.all()
}
for chapter_index, chapter in enumerate(item["chapters"]):
if chapter["name"] not in existing:
db.add(
Chapter(
textbook_id=textbook.id,
name=chapter["name"],
position=chapter_index,
summary=chapter["summary"],
)
)
# 按最新知识点-章节映射重新关联所有题目
primary = db.query(Textbook).filter(Textbook.name == CATALOG[0]["name"]).first()
if primary:
chapter_map = {
chapter.name: chapter
for chapter in db.query(Chapter)
.filter(Chapter.textbook_id == primary.id)
.all()
}
for question in db.query(Question).all():
chapter = chapter_map.get(
KNOWLEDGE_CHAPTER_MAP.get(question.knowledge_name, "")
)
question.chapter_id = chapter.id if chapter else None
_sync_default_chapter_knowledge(db)
_sync_default_course_resources(db)
db.commit()
def _sync_default_chapter_knowledge(db: Session) -> None:
"""仅为还没有知识点关联的章节写入默认知识点(不覆盖管理员维护)。"""
for chapter in db.query(Chapter).all():
linked = (
db.query(ChapterKnowledge)
.filter(ChapterKnowledge.chapter_id == chapter.id)
.count()
)
if linked:
continue
names = DEFAULT_CHAPTER_KNOWLEDGE.get(chapter.name, [])
if names:
set_chapter_knowledge_names(db, chapter.id, names)
def _ensure_courses(db: Session) -> None:
"""课程表为空时写入默认在线课程;管理员删掉后不再自动恢复。"""
if db.query(Course).count() > 0:
return
for position, item in enumerate(COURSES):
db.add(
Course(
name=item["name"],
provider=item["provider"],
url=item["url"],
grade=item["grade"],
description=item["description"],
position=position,
)
)
db.commit()
def _sync_default_course_resources(db: Session) -> None:
"""把在线课程 / 视频挂到对应知识点,作为知识点详情里的反向资源链接。"""
for course_name, knowledge_names in COURSE_KNOWLEDGE_MAP.items():
course = db.query(Course).filter(Course.name == course_name).first()
if course is None or not course.url:
continue
for name in knowledge_names:
knowledge = db.query(Knowledge).filter(Knowledge.name == name).first()
if knowledge is None:
continue
ensure_knowledge_resource(
db,
knowledge.id,
kind="video",
title=course.name,
url=course.url,
course_id=course.id,
)