"""教材与在线课程种子数据(两张表分别写入)。 教材以《盖尔范德中学生数学思维丛书》(中国科学技术大学出版社)为基础; 书号 / 出版信息均核对公开书目信息,课程使用官方站点链接。 """ 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, )