- content.Subject + Unit.subject, /api/home?subject=, tutor grounded in the chosen book - 5 new books ingested; ~1150 hand-written questions, islands named by hand - node_split: islands over 7 lessons split into parts of <=6 (lesson ids and progress kept) - Lesson.figures hand-authored and visually checked for 653 lessons of the new books; gen_lesson_figures got --subject and survives network errors - seed files re-exported Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
610 lines
30 KiB
Python
610 lines
30 KiB
Python
"""
|
||
نقشهی فیزیکیِ فایلهای PDF کتابهای درسی در data/textbooks/.
|
||
|
||
چرا این فایل لازم است: `ingest_pdf` یک PDF را یکتکه و با یک نامِ فصل ingest
|
||
میکند. کتابِ کاملِ درسی چند فصل دارد، پس بدونِ نگاشتِ «فصل → بازهی صفحه»
|
||
همهی نقاطِ کتاب زیرِ یک فصلِ اشتباه ذخیره میشدند و فیلترِ `chapter` در
|
||
retrieval هیچوقت درست جواب نمیداد.
|
||
|
||
دو نکته که موقعِ افزودنِ کتابِ جدید باید حواستان باشد:
|
||
|
||
- `page_offset`: شمارهی صفحهای که روی کاغذ چاپ شده با شمارهی صفحه در PDF
|
||
یکی نیست (جلد، شناسنامه، فهرست و سخنی با معلم جلوترند). فهرستِ کتاب شمارهی
|
||
کاغذی میدهد، pdf2image شمارهی PDF میخواهد: pdf_page = book_page + offset.
|
||
- بازهها بر اساسِ فهرستِ خودِ کتاباند و شاملِ صفحهی جداکنندهی فصل هم
|
||
میشوند؛ صفحهی آخرِ هر فصل = یکی قبل از شروعِ فصلِ بعد.
|
||
|
||
مقادیرِ زیر با خواندنِ فهرست و بازبینیِ چشمیِ صفحههای مرزی از همان فایلها
|
||
درآمدهاند (۱۴۰۵/۰۶/۲۱).
|
||
"""
|
||
from dataclasses import dataclass
|
||
|
||
|
||
@dataclass(frozen=True)
|
||
class Section:
|
||
"""یک «درس» داخلِ فصل، همانطور که در فهرستِ کتاب آمده."""
|
||
|
||
number: int
|
||
title: str
|
||
first_page: int # شمارهی چاپشده روی کاغذ
|
||
last_page: int = 0 # از روی درسِ بعدی پر میشود؛ صفر یعنی «تا آخرِ فصل»
|
||
|
||
|
||
@dataclass(frozen=True)
|
||
class Chapter:
|
||
number: int
|
||
title: str # عنوانِ کاملِ فصل، دقیقاً همان رشتهای که در payload مینشیند
|
||
first_page: int # شمارهی چاپشده روی کاغذ
|
||
last_page: int
|
||
sections: tuple[Section, ...] = ()
|
||
|
||
def resolved_sections(self) -> tuple[Section, ...]:
|
||
"""درسها با last_page پرشده (هر درس تا یکی قبل از درسِ بعدی)."""
|
||
out = []
|
||
for index, section in enumerate(self.sections):
|
||
end = (
|
||
self.sections[index + 1].first_page - 1
|
||
if index + 1 < len(self.sections) else self.last_page
|
||
)
|
||
out.append(Section(section.number, section.title, section.first_page, end))
|
||
return tuple(out)
|
||
|
||
|
||
@dataclass(frozen=True)
|
||
class Textbook:
|
||
subject: str
|
||
grade: str # همان رشتهای که در نامِ collection میآید («نهم»)
|
||
grade_label: str # همان رشتهای که در payloadِ `grade` مینشیند
|
||
filename: str
|
||
page_offset: int
|
||
chapters: tuple[Chapter, ...]
|
||
|
||
@property
|
||
def key(self) -> str:
|
||
return f'{self.subject} {self.grade}'.strip()
|
||
|
||
def pdf_pages(self, chapter: Chapter) -> tuple[int, int]:
|
||
return chapter.first_page + self.page_offset, chapter.last_page + self.page_offset
|
||
|
||
def chapter(self, number: int) -> Chapter | None:
|
||
return next((c for c in self.chapters if c.number == number), None)
|
||
|
||
|
||
def _ch(*rows) -> tuple[Chapter, ...]:
|
||
"""rows: (number, title, first_page, last_page, [(sec_no, sec_title, sec_page), ...])"""
|
||
chapters = []
|
||
for row in rows:
|
||
number, title, first, last = row[:4]
|
||
sections = tuple(Section(*s) for s in (row[4] if len(row) > 4 else ()))
|
||
chapters.append(Chapter(number, title, first, last, sections))
|
||
return tuple(chapters)
|
||
|
||
|
||
MATH_3 = Textbook(
|
||
subject='ریاضی', grade='سوم', grade_label='سوم دبستان',
|
||
filename='', page_offset=0,
|
||
chapters=_ch(
|
||
(1, 'فصل ۱: الگوها', 0, 0),
|
||
(2, 'فصل ۲: عددهای چهار رقمی', 0, 0),
|
||
(3, 'فصل ۳: عددهای کسری', 0, 0),
|
||
(4, 'فصل ۴: ضرب و تقسیم', 0, 0),
|
||
(5, 'فصل ۵: محیط و مساحت', 0, 0),
|
||
(6, 'فصل ۶: جمع و تفریق', 0, 0),
|
||
(7, 'فصل ۷: آمار و احتمال', 0, 0),
|
||
(8, 'فصل ۸: ضرب عددها', 0, 0),
|
||
),
|
||
)
|
||
|
||
# چهارم و پنجم: درخواستِ دکتر (۲۰۲۶-۱۰-۰۳) که «از سوم به بعد» همهی پایهها باشند.
|
||
# فهرست و offset از خودِ PDFها خوانده شد: در چهارم PDF ۸ = صفحهی چاپیِ ۲، در
|
||
# پنجم (چاپِ تازهی ۱۴۰۵) شمارهی PDF همان شمارهی چاپی است. «حلِ مسئله»ی آغازِ
|
||
# هر فصل جزءِ درسِ اول حساب میشود (`_sectioned` درسِ اول را تا ابتدای فصل
|
||
# عقب میکشد) و «مرور فصل» جزءِ درسِ آخر.
|
||
MATH_4 = Textbook(
|
||
subject='ریاضی', grade='چهارم', grade_label='چهارم دبستان',
|
||
filename='ریاضی چهارم.pdf', page_offset=6,
|
||
chapters=_ch(
|
||
(1, 'فصل ۱: اعداد و الگوها', 1, 23, (
|
||
(1, 'عددنویسی', 4),
|
||
(2, 'الگوها', 8),
|
||
(3, 'ماشین ورودی ـ خروجی', 12),
|
||
(4, 'معرفی میلیون', 16),
|
||
)),
|
||
(2, 'فصل ۲: کسر', 24, 45, (
|
||
(1, 'شناخت کسرها', 26),
|
||
(2, 'جمع و تفریق کسرها', 30),
|
||
(3, 'تساوی کسرها', 34),
|
||
(4, 'ضرب عدد در کسر', 38),
|
||
)),
|
||
(3, 'فصل ۳: ضرب و تقسیم', 46, 75, (
|
||
(1, 'ضرب دو عدد دورقمی', 48),
|
||
(2, 'محاسبهٔ حاصلضرب', 52),
|
||
(3, 'محاسبههای تقریبی', 56),
|
||
(4, 'تقسیم و بخشپذیری', 60),
|
||
(5, 'تقسیم بر عددهای یکرقمی', 64),
|
||
(6, 'تقسیم بر عددهای دورقمی', 68),
|
||
)),
|
||
(4, 'فصل ۴: اندازهگیری', 76, 97, (
|
||
(1, 'زاویه', 78),
|
||
(2, 'اندازهگیری زاویه', 82),
|
||
(3, 'اندازهگیری زمان', 86),
|
||
(4, 'اندازهگیری طول', 90),
|
||
)),
|
||
(5, 'فصل ۵: عدد مخلوط و عدد اعشاری', 98, 119, (
|
||
(1, 'عدد مخلوط', 100),
|
||
(2, 'عدد اعشاری', 104),
|
||
(3, 'جمع و تفریق اعشاری', 108),
|
||
(4, 'ارزش مکانی عددهای اعشاری', 112),
|
||
)),
|
||
(6, 'فصل ۶: شکلهای هندسی', 120, 141, (
|
||
(1, 'عمود و موازی', 122),
|
||
(2, 'چهارضلعیها', 126),
|
||
(3, 'مساحت متوازیالاضلاع و مثلث', 130),
|
||
(4, 'محیط و مساحت', 134),
|
||
)),
|
||
(7, 'فصل ۷: آمار و احتمال', 142, 154, (
|
||
(1, 'نمودار خط شکسته', 144),
|
||
(2, 'احتمال', 148),
|
||
)),
|
||
),
|
||
)
|
||
|
||
# شروعِ هر فصل یک صفحه پیش از درسِ اولش گرفته شد (صفحهی جداکننده)؛ فقط برای
|
||
# فصل ۱ با چشم دیده شد (PDF ۱۱). جداکنندهی بقیه اگر دو صفحه باشد، یک صفحهی
|
||
# تصویریِ بیمسئله به درسِ آخرِ فصلِ قبل میافتد. ۲۰۷–۲۰۸ پشتِ جلد است.
|
||
MATH_5 = Textbook(
|
||
subject='ریاضی', grade='پنجم', grade_label='پنجم دبستان',
|
||
filename='ریاضی پنجم.pdf', page_offset=0,
|
||
chapters=_ch(
|
||
(1, 'فصل ۱: عددنویسی و الگوها', 11, 38, (
|
||
(1, 'یادآوری عددنویسی و محاسبات عددی', 12),
|
||
(2, 'معرفی میلیارد', 18),
|
||
(3, 'جمع و تفریق عددهای مرکب', 25),
|
||
(4, 'الگوها', 30),
|
||
)),
|
||
(2, 'فصل ۲: کسر', 39, 76, (
|
||
(1, 'کسرهای بزرگتر از واحد', 40),
|
||
(2, 'جمع و تفریق عددهای مخلوط', 46),
|
||
(3, 'ضرب کسرها', 53),
|
||
(4, 'تقسیم کسرها', 59),
|
||
(5, 'ضرب عددهای مخلوط', 66),
|
||
)),
|
||
(3, 'فصل ۳: نسبت، تناسب و درصد', 77, 102, (
|
||
(1, 'نسبت', 78),
|
||
(2, 'نسبتهای مساوی', 83),
|
||
(3, 'تناسب', 88),
|
||
(4, 'درصد', 93),
|
||
)),
|
||
(4, 'فصل ۴: تقارن و چندضلعیها', 103, 128, (
|
||
(1, 'تقارن محوری', 104),
|
||
(2, 'تقارن مرکزی', 110),
|
||
(3, 'زاویه و نیمساز', 113),
|
||
(4, 'چندضلعیها و مجموع زاویههای آنها', 118),
|
||
)),
|
||
(5, 'فصل ۵: عددهای اعشاری', 129, 156, (
|
||
(1, 'عددهای اعشاری', 130),
|
||
(2, 'جمع عددهای اعشاری', 139),
|
||
(3, 'تفریق عددهای اعشاری', 143),
|
||
(4, 'ضرب عددهای اعشاری', 147),
|
||
)),
|
||
(6, 'فصل ۶: اندازهگیری', 157, 184, (
|
||
(1, 'مساحت لوزی و ذوزنقه', 158),
|
||
(2, 'محیط دایره', 165),
|
||
(3, 'حجم', 170),
|
||
(4, 'گنجایش', 177),
|
||
)),
|
||
(7, 'فصل ۷: آمار و احتمال', 185, 206, (
|
||
(1, 'جمعآوری و نمایش دادهها', 186),
|
||
(2, 'میانگین', 193),
|
||
(3, 'احتمال', 197),
|
||
)),
|
||
),
|
||
)
|
||
|
||
# هشتم تنها کتابیست که هم PDF دارد و هم روی Qdrant نیست — یعنی فصلبندی و
|
||
# درسهایش کاملاً از فهرستِ خودِ کتاب میآید و ingest دقیقاً همین رشتهها را
|
||
# مینویسد. «مرور فصل» جزء آخرین درسِ هر فصل حساب شده است.
|
||
MATH_8 = Textbook(
|
||
subject='ریاضی', grade='هشتم', grade_label='هشتم',
|
||
filename='ریاضی هشتم.pdf', page_offset=8,
|
||
chapters=_ch(
|
||
(1, 'فصل ۱: عددهای صحیح و گویا', 1, 18, (
|
||
(1, 'یادآوری عددهای صحیح', 2),
|
||
(2, 'معرفی عددهای گویا', 6),
|
||
(3, 'جمع و تفریق عددهای گویا', 10),
|
||
(4, 'ضرب و تقسیم عددهای گویا', 14),
|
||
)),
|
||
(2, 'فصل ۲: عددهای اول', 19, 28, (
|
||
(1, 'یادآوری عددهای اول', 20),
|
||
(2, 'تعیین عددهای اول', 24),
|
||
)),
|
||
(3, 'فصل ۳: چندضلعیها', 29, 50, (
|
||
(1, 'چندضلعیها و تقارن', 30),
|
||
(2, 'توازی و تعامد', 34),
|
||
(3, 'چهارضلعیها', 38),
|
||
(4, 'زاویههای داخلی', 42),
|
||
(5, 'زاویههای خارجی', 46),
|
||
)),
|
||
(4, 'فصل ۴: جبر و معادله', 51, 68, (
|
||
(1, 'ساده کردن عبارتهای جبری', 52),
|
||
(2, 'پیدا کردن مقدار یک عبارت جبری', 56),
|
||
(3, 'تجزیه عبارتهای جبری', 60),
|
||
(4, 'معادله', 64),
|
||
)),
|
||
(5, 'فصل ۵: بردار و مختصات', 69, 82, (
|
||
(1, 'جمع بردارها', 70),
|
||
(2, 'ضرب عدد در بردار', 74),
|
||
(3, 'بردارهای واحد مختصات', 78),
|
||
)),
|
||
(6, 'فصل ۶: مثلث', 83, 100, (
|
||
(1, 'رابطهٔ فیثاغورس', 84),
|
||
(2, 'شکلهای همنهشت', 88),
|
||
(3, 'مثلثهای همنهشت', 92),
|
||
(4, 'همنهشتی مثلثهای قائمالزاویه', 96),
|
||
)),
|
||
(7, 'فصل ۷: توان و جذر', 101, 118, (
|
||
(1, 'توان', 102),
|
||
(2, 'تقسیم اعداد تواندار', 106),
|
||
(3, 'جذر تقریبی', 110),
|
||
(4, 'نمایش اعداد رادیکالی روی محور اعداد', 114),
|
||
(5, 'خواص ضرب و تقسیم رادیکالها', 115),
|
||
)),
|
||
(8, 'فصل ۸: آمار و احتمال', 119, 136, (
|
||
(1, 'دستهبندی دادهها', 120),
|
||
(2, 'میانگین دادهها', 124),
|
||
(3, 'احتمال یا اندازهگیری شانس', 128),
|
||
(4, 'بررسی حالتهای ممکن', 132),
|
||
)),
|
||
(9, 'فصل ۹: دایره', 137, 150, (
|
||
(1, 'خط و دایره', 138),
|
||
(2, 'زاویههای مرکزی', 142),
|
||
(3, 'زاویههای محاطی', 146),
|
||
)),
|
||
),
|
||
)
|
||
|
||
MATH_9 = Textbook(
|
||
subject='ریاضی', grade='نهم', grade_label='نهم',
|
||
filename='ریاضی نهم.pdf', page_offset=8,
|
||
chapters=_ch(
|
||
(1, 'فصل ۱: مجموعهها', 1, 17, (
|
||
(1, 'معرفی مجموعه', 2),
|
||
(2, 'مجموعههای برابر و نمایش مجموعهها', 6),
|
||
(3, 'اجتماع، اشتراک و تفاضلِ مجموعهها', 11),
|
||
(4, 'مجموعهها و احتمال', 15),
|
||
)),
|
||
(2, 'فصل ۲: عددهای حقیقی', 18, 31, (
|
||
(1, 'عددهای گویا', 19),
|
||
(2, 'عددهای حقیقی', 23),
|
||
(3, 'قدر مطلق و محاسبهٔ تقریبی', 28),
|
||
)),
|
||
(3, 'فصل ۳: استدلال و اثبات در هندسه', 32, 58, (
|
||
(1, 'استدلال', 33),
|
||
(2, 'آشنایی با اثبات در هندسه', 37),
|
||
(3, 'همنهشتی مثلثها', 44),
|
||
(4, 'حل مسئله در هندسه', 49),
|
||
(5, 'شکلهای متشابه', 53),
|
||
)),
|
||
(4, 'فصل ۴: توان و ریشه', 59, 77, (
|
||
(1, 'توان صحیح', 60),
|
||
(2, 'نماد علمی', 65),
|
||
(3, 'ریشهگیری', 68),
|
||
(4, 'جمع و تفریق رادیکالها', 73),
|
||
)),
|
||
(5, 'فصل ۵: عبارتهای جبری', 78, 94, (
|
||
(1, 'عبارتهای جبری و مفهوم اتحاد', 79),
|
||
(2, 'چند اتحاد دیگر، تجزیه و کاربردها', 86),
|
||
(3, 'نابرابریها و نامعادلهها', 90),
|
||
)),
|
||
(6, 'فصل ۶: خط و معادلههای خطی', 95, 112, (
|
||
(1, 'معادلهٔ خط', 96),
|
||
(2, 'شیب خط و عرض از مبدأ', 102),
|
||
(3, 'دستگاه معادلههای خطی', 108),
|
||
)),
|
||
(7, 'فصل ۷: عبارتهای گویا', 113, 129, (
|
||
(1, 'معرفی و ساده کردن عبارتهای گویا', 114),
|
||
(2, 'محاسبات عبارتهای گویا', 119),
|
||
(3, 'تقسیم چندجملهایها', 126),
|
||
)),
|
||
(8, 'فصل ۸: حجم و مساحت', 130, 143, (
|
||
(1, 'حجم و مساحت کره', 131),
|
||
(2, 'حجم هرم و مخروط', 135),
|
||
(3, 'سطح و حجم', 140),
|
||
)),
|
||
),
|
||
)
|
||
|
||
MATH_10 = Textbook(
|
||
subject='ریاضی', grade='دهم', grade_label='دهم',
|
||
filename='ریاضی دهم.pdf', page_offset=6,
|
||
chapters=_ch(
|
||
(1, 'فصل ۱: مجموعه، الگو و دنباله', 1, 27, (
|
||
(1, 'مجموعههای متناهی و نامتناهی', 2),
|
||
(2, 'متمم یک مجموعه', 8),
|
||
(3, 'الگو و دنباله', 14),
|
||
(4, 'دنبالههای حسابی و هندسی', 21),
|
||
)),
|
||
(2, 'فصل ۲: مثلثات', 28, 46, (
|
||
(1, 'نسبتهای مثلثاتی', 29),
|
||
(2, 'دایرهٔ مثلثاتی', 36),
|
||
(3, 'روابط بین نسبتهای مثلثاتی', 42),
|
||
)),
|
||
(3, 'فصل ۳: توانهای گویا و عبارتهای جبری', 47, 68, (
|
||
(1, 'ریشه و توان', 48),
|
||
(2, 'ریشهٔ nام', 54),
|
||
(3, 'توانهای گویا', 59),
|
||
(4, 'عبارتهای جبری', 62),
|
||
)),
|
||
(4, 'فصل ۴: معادلهها و نامعادلهها', 69, 93, (
|
||
(1, 'معادلهٔ درجه دوم و روشهای مختلف حل آن', 70),
|
||
(2, 'سهمی', 78),
|
||
(3, 'تعیین علامت', 83),
|
||
)),
|
||
(5, 'فصل ۵: تابع', 94, 117, (
|
||
(1, 'مفهوم تابع و بازنماییهای آن', 95),
|
||
(2, 'دامنه و برد توابع', 101),
|
||
(3, 'انواع تابع', 109),
|
||
)),
|
||
(6, 'فصل ۶: شمارش، بدون شمردن', 118, 140, (
|
||
(1, 'شمارش', 119),
|
||
(2, 'جایگشت', 127),
|
||
(3, 'ترکیب', 133),
|
||
)),
|
||
(7, 'فصل ۷: آمار و احتمال', 141, 170, (
|
||
(1, 'احتمال یا اندازهگیری شانس', 142),
|
||
(2, 'مقدمهای بر علم آمار، جامعه و نمونه', 152),
|
||
(3, 'متغیر و انواع آن', 159),
|
||
)),
|
||
),
|
||
)
|
||
|
||
# پایههای ششم و هفتم را تیمِ دیگر ingest کرده و روی Qdrant هستند؛ فایلِ PDF
|
||
# برایشان لازم نیست و بازهی صفحه هم نداریم (نقاطشان شمارهی صفحه ندارند). فقط
|
||
# فصلبندی ثبت میشود تا `seed_curriculum_from_textbook` بتواند برایشان برنامهی
|
||
# درسی بسازد؛ `filename` خالی یعنی «این کتاب از مسیرِ PDF ingest نمیشود».
|
||
MATH_6 = Textbook(
|
||
subject='ریاضی', grade='ششم', grade_label='ششم دبستان',
|
||
filename='', page_offset=0,
|
||
chapters=_ch(
|
||
(1, 'فصل ۱: عدد و الگوهای عددی', 0, 0),
|
||
(2, 'فصل ۲: کسر', 0, 0),
|
||
(3, 'فصل ۳: اعداد اعشاری', 0, 0),
|
||
(4, 'فصل ۴: تقارن و مختصات', 0, 0),
|
||
(5, 'فصل ۵: اندازه گیری', 0, 0),
|
||
(6, 'فصل ۶: تناسب و درصد', 0, 0),
|
||
(7, 'فصل ۷: تقریب', 0, 0),
|
||
),
|
||
)
|
||
|
||
MATH_7 = Textbook(
|
||
subject='ریاضی', grade='هفتم', grade_label='هفتم',
|
||
filename='', page_offset=0,
|
||
chapters=_ch(
|
||
(1, 'فصل ۱: راهبردهای حل مسئله', 0, 0),
|
||
(2, 'فصل ۲: عددهای صحیح', 0, 0),
|
||
(3, 'فصل ۳: جبر و معادله', 0, 0),
|
||
(4, 'فصل ۴: هندسه و استدلال', 0, 0),
|
||
(5, 'فصل ۵: شمارندهها و اعداد اول', 0, 0),
|
||
(6, 'فصل ۶: سطح و حجم', 0, 0),
|
||
(7, 'فصل ۷: توان و جذر', 0, 0),
|
||
(8, 'فصل ۸: بردار و مختصات', 0, 0),
|
||
(9, 'فصل ۹: آمار و احتمال', 0, 0),
|
||
),
|
||
)
|
||
|
||
# ── حسابان ─────────────────────────────────────────────────────────────
|
||
# «حسابان» کتابِ رشتهی ریاضیفیزیک است، نه «ریاضی» عمومی. subject عمداً
|
||
# «حسابان» است تا collection جدا بماند: همنامیِ آن با «ریاضی یازدهم»
|
||
# (کتابِ تجربی) دو کتابِ متفاوت را سرِ یک collection میانداخت.
|
||
# ⚠️ هر subjectِ تازهی ریاضیوار باید به known_collections.MATH_SUBJECTS هم
|
||
# اضافه شود، وگرنه retrieval آن را «درسِ متنی» میبیند و بهجای `chapter`
|
||
# روی `lesson_number` فیلتر میکند — یعنی بیسروصدا هیچوقت چیزی برنمیگرداند.
|
||
#
|
||
# بازهها از فهرستِ خودِ کتاب (PDF صفحهی ۵) درآمدهاند و page_offset با
|
||
# تطبیقِ صفحهی ۱ کتاب روی صفحهی ۷ PDF تأیید شده است.
|
||
CALCULUS_11 = Textbook(
|
||
subject='حسابان', grade='یازدهم', grade_label='یازدهم',
|
||
filename='حسابان یازدهم.pdf', page_offset=6,
|
||
chapters=_ch(
|
||
(1, 'فصل ۱: جبر و معادله', 1, 36, (
|
||
(1, 'مجموع جملههای دنبالههای حسابی و هندسی', 2),
|
||
(2, 'معادلههای درجه دوم', 7),
|
||
(3, 'معادلههای گویا و گنگ', 17),
|
||
(4, 'قدر مطلق و ویژگیهای آن', 23),
|
||
(5, 'آشنایی با هندسه تحلیلی', 29),
|
||
)),
|
||
(2, 'فصل ۲: تابع', 37, 70, (
|
||
(1, 'آشنایی بیشتر با تابع', 38),
|
||
(2, 'انواع توابع', 44),
|
||
(3, 'وارون تابع', 54),
|
||
(4, 'اعمال روی توابع', 63),
|
||
)),
|
||
(3, 'فصل ۳: توابع نمایی و لگاریتمی', 71, 90, (
|
||
(1, 'تابع نمایی', 72),
|
||
(2, 'تابع لگاریتمی و لگاریتم', 80),
|
||
(3, 'ویژگیهای لگاریتم و حل معادلههای لگاریتمی', 86),
|
||
)),
|
||
(4, 'فصل ۴: مثلثات', 91, 112, (
|
||
(1, 'رادیان', 92),
|
||
(2, 'نسبتهای مثلثاتی برخی زوایا', 98),
|
||
(3, 'توابع مثلثاتی', 105),
|
||
(4, 'روابط مثلثاتی مجموع و تفاضل زوایا', 110),
|
||
)),
|
||
(5, 'فصل ۵: حد و پیوستگی', 113, 151, (
|
||
(1, 'مفهوم حد و فرایندهای حدی', 114),
|
||
(2, 'حدهای یکطرفه (حد چپ و حد راست)', 123),
|
||
(3, 'قضایای حد', 130),
|
||
(4, 'محاسبه حد توابع کسری', 141),
|
||
(5, 'پیوستگی', 145),
|
||
)),
|
||
),
|
||
)
|
||
|
||
CALCULUS_12 = Textbook(
|
||
subject='حسابان', grade='دوازدهم', grade_label='دوازدهم',
|
||
filename='حسابان دوازدهم.pdf', page_offset=6,
|
||
chapters=_ch(
|
||
(1, 'فصل ۱: تابع', 1, 22, (
|
||
(1, 'تبدیل نمودار توابع', 2),
|
||
(2, 'تابع درجه سوم، توابع یکنوا و بخشپذیری و تقسیم', 13),
|
||
)),
|
||
(2, 'فصل ۲: مثلثات', 23, 44, (
|
||
(1, 'تناوب و تانژانت', 24),
|
||
(2, 'معادلههای مثلثاتی', 35),
|
||
)),
|
||
(3, 'فصل ۳: حدهای نامتناهی ـ حد در بینهایت', 45, 70, (
|
||
(1, 'حدهای نامتناهی', 46),
|
||
(2, 'حد در بینهایت', 59),
|
||
)),
|
||
(4, 'فصل ۴: مشتق', 71, 110, (
|
||
(1, 'آشنایی با مفهوم مشتق', 72),
|
||
(2, 'مشتقپذیری و پیوستگی', 84),
|
||
(3, 'آهنگ متوسط تغییر و آهنگ لحظهای تغییر', 102),
|
||
)),
|
||
(5, 'فصل ۵: کاربردهای مشتق', 111, 146, (
|
||
(1, 'اکسترممهای یک تابع و توابع صعودی و نزولی', 112),
|
||
(2, 'جهت تقعر نمودار یک تابع و نقطهی عطف آن', 127),
|
||
(3, 'رسم نمودار تابع', 137),
|
||
)),
|
||
),
|
||
)
|
||
|
||
|
||
# ── هندسه، آمار و احتمال، گسسته (۲۰۲۶-۱۰-۱۱؛ درخواستِ سینیور) ─────────────
|
||
# کتابهای رشتهی ریاضیفیزیک که کنارِ ریاضی/حسابانِ همان پایه میآیند، پس هر
|
||
# کدام subject و collectionِ خودش را دارد (همان دلیلِ «حسابان»).
|
||
# فهرست و آفست از خودِ PDFها خوانده شد (فهرست چشمی، آفست با تطبیقِ صفحهی بازکنندهی
|
||
# فصل با متنِ همان صفحهی PDF): هندسهها و گسسته چاپی=PDF (۰) و (۸)؛ آمار صفحهی ۱
|
||
# چاپی روی PDF ۷ است (آفست ۶، مثلِ حسابان). ⚠️ آخرین صفحهی هر فصل «یکی قبل از فصل
|
||
# بعد» است و آخرین فصل تا قبل از «منابع»؛ مرزها با ingest و شمارشِ chunk وارسی شوند.
|
||
GEOMETRY_10 = Textbook(
|
||
subject='هندسه', grade='دهم', grade_label='دهم',
|
||
filename='هندسه دهم.pdf', page_offset=0,
|
||
chapters=_ch(
|
||
(1, 'فصل ۱: ترسیمهای هندسی و استدلال', 9, 28, (
|
||
(1, 'ترسیمهای هندسی', 10),
|
||
(2, 'استدلال', 17),
|
||
)),
|
||
(2, 'فصل ۲: قضیهی تالس، تشابه و کاربردهای آن', 29, 52, (
|
||
(1, 'نسبت و تناسب در هندسه', 30),
|
||
(2, 'قضیهی تالس', 34),
|
||
(3, 'تشابه مثلثها', 38),
|
||
(4, 'کاربردهایی از قضیهی تالس و تشابه مثلثها', 45),
|
||
)),
|
||
(3, 'فصل ۳: چندضلعیها', 53, 76, (
|
||
(1, 'چندضلعیها و ویژگیهایی از آنها', 54),
|
||
(2, 'مساحت و کاربردهای آن', 65),
|
||
)),
|
||
(4, 'فصل ۴: تجسم فضایی', 77, 96, (
|
||
(1, 'خط، نقطه و صفحه', 78),
|
||
(2, 'تفکر تجسمی', 87),
|
||
)),
|
||
),
|
||
)
|
||
|
||
GEOMETRY_11 = Textbook(
|
||
subject='هندسه', grade='یازدهم', grade_label='یازدهم',
|
||
filename='هندسه یازدهم.pdf', page_offset=0,
|
||
chapters=_ch(
|
||
(1, 'فصل ۱: دایره', 9, 30, (
|
||
(1, 'مفاهیم اولیه و زاویهها در دایره', 10),
|
||
(2, 'رابطههای طولی در دایره', 18),
|
||
(3, 'چندضلعیهای محاطی و محیطی', 24),
|
||
)),
|
||
(2, 'فصل ۲: تبدیلهای هندسی و کاربردها', 31, 58, (
|
||
(1, 'تبدیلهای هندسی', 32),
|
||
(2, 'کاربرد تبدیلها', 50),
|
||
)),
|
||
(3, 'فصل ۳: روابط طولی در مثلث', 59, 80, (
|
||
(1, 'قضیهی سینوسها', 60),
|
||
(2, 'قضیهی کسینوسها', 64),
|
||
(3, 'قضیهی نیمسازهای زوایای داخلی و محاسبهی طول نیمسازها', 68),
|
||
(4, 'قضیهی هرون (محاسبهی ارتفاعها و مساحت مثلث)', 71),
|
||
)),
|
||
),
|
||
)
|
||
|
||
GEOMETRY_12 = Textbook(
|
||
subject='هندسه', grade='دوازدهم', grade_label='دوازدهم',
|
||
filename='هندسه دوازدهم.pdf', page_offset=0,
|
||
chapters=_ch(
|
||
(1, 'فصل ۱: ماتریس و کاربردها', 9, 32, (
|
||
(1, 'ماتریس و اعمال روی ماتریسها', 10),
|
||
(2, 'وارون ماتریس و دترمینان', 22),
|
||
)),
|
||
(2, 'فصل ۲: آشنایی با مقاطع مخروطی', 33, 60, (
|
||
(1, 'آشنایی با مقاطع مخروطی و مکان هندسی', 34),
|
||
(2, 'دایره', 40),
|
||
(3, 'بیضی و سهمی', 47),
|
||
)),
|
||
(3, 'فصل ۳: بردارها', 61, 86, (
|
||
(1, 'معرفی فضای R³', 62),
|
||
(2, 'ضرب داخلی و ضرب خارجی بردارها', 77),
|
||
)),
|
||
),
|
||
)
|
||
|
||
STATS_11 = Textbook(
|
||
subject='آمار و احتمال', grade='یازدهم', grade_label='یازدهم',
|
||
filename='آمار و احتمال یازدهم.pdf', page_offset=6,
|
||
chapters=_ch(
|
||
(1, 'فصل ۱: آشنایی با مبانی ریاضیات', 1, 34, (
|
||
(1, 'آشنایی با منطق ریاضی', 2),
|
||
(2, 'جبر مجموعهها', 16),
|
||
)),
|
||
(2, 'فصل ۲: احتمال', 35, 68, (
|
||
(1, 'مبانی احتمال', 36),
|
||
(2, 'احتمال غیرهمشانس', 44),
|
||
(3, 'احتمال شرطی', 48),
|
||
(4, 'پیشامدهای مستقل و وابسته', 63),
|
||
)),
|
||
(3, 'فصل ۳: آمار توصیفی', 69, 96, (
|
||
(1, 'توصیف و نمایش دادهها', 70),
|
||
(2, 'معیارهای گرایش به مرکز', 80),
|
||
(3, 'معیارهای پراکندگی', 87),
|
||
)),
|
||
(4, 'فصل ۴: آمار استنباطی', 97, 121, (
|
||
(1, 'گردآوری دادهها', 98),
|
||
(2, 'برآورد', 112),
|
||
)),
|
||
),
|
||
)
|
||
|
||
DISCRETE_12 = Textbook(
|
||
subject='گسسته', grade='دوازدهم', grade_label='دوازدهم',
|
||
filename='گسسته دوازدهم.pdf', page_offset=8,
|
||
chapters=_ch(
|
||
(1, 'فصل ۱: آشنایی با نظریهی اعداد', 1, 30, (
|
||
(1, 'استدلال ریاضی', 2),
|
||
(2, 'بخشپذیری در اعداد صحیح', 9),
|
||
(3, 'همنهشتی در اعداد صحیح و کاربردها', 18),
|
||
)),
|
||
(2, 'فصل ۲: گراف و مدلسازی', 31, 54, (
|
||
(1, 'معرفی گراف', 32),
|
||
(2, 'مدلسازی با گراف', 43),
|
||
)),
|
||
(3, 'فصل ۳: ترکیبیات (شمارش)', 55, 84, (
|
||
(1, 'مباحثی در ترکیبیات', 56),
|
||
(2, 'روشهایی برای شمارش', 73),
|
||
)),
|
||
),
|
||
)
|
||
|
||
|
||
TEXTBOOKS: dict[str, Textbook] = {
|
||
b.key: b for b in (MATH_3, MATH_4, MATH_5, MATH_6, MATH_7, MATH_8, MATH_9, MATH_10,
|
||
CALCULUS_11, CALCULUS_12, GEOMETRY_10, GEOMETRY_11, GEOMETRY_12,
|
||
STATS_11, DISCRETE_12)
|
||
}
|
||
|
||
# کتابهایی که واقعاً فایلِ PDF دارند و `rag_ingest_book` رویشان کار میکند.
|
||
INGESTABLE = {b.key: b for b in TEXTBOOKS.values() if b.filename}
|
||
|
||
|
||
def get_textbook(subject: str, grade: str) -> Textbook | None:
|
||
return TEXTBOOKS.get(f'{(subject or "").strip()} {(grade or "").strip()}')
|
||
|
||
|
||
def chapter_titles(book: Textbook) -> dict[int, str]:
|
||
return {c.number: c.title for c in book.chapters}
|