Subjects per grade (math, calculus, geometry, stats, discrete), 5 new textbooks, 202 new islands, long islands split, hand-written figures and lesson texts for the new books
- 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>
This commit is contained in:
23
content/migrations/0014_subject.py
Normal file
23
content/migrations/0014_subject.py
Normal file
@@ -0,0 +1,23 @@
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
"""مرحلهی ۱ از ۴ (جدولِ کتابها). چهار مرحلهی جدا چون PostgreSQL اجازه نمیدهد در یک تراکنش
|
||||
هم داده نوشت و هم همان جدول را ALTER کرد (pending trigger events)."""
|
||||
|
||||
dependencies = [('content', '0013_alter_userlessoncompletion_created_at_and_more')]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Subject',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('key', models.SlugField(max_length=30, unique=True)),
|
||||
('title', models.CharField(max_length=50, unique=True)),
|
||||
('icon', models.CharField(blank=True, max_length=100)),
|
||||
('color', models.CharField(blank=True, max_length=10)),
|
||||
('order', models.PositiveSmallIntegerField(default=0)),
|
||||
],
|
||||
options={'ordering': ['order', 'id']},
|
||||
),
|
||||
]
|
||||
24
content/migrations/0015_seed_subjects.py
Normal file
24
content/migrations/0015_seed_subjects.py
Normal file
@@ -0,0 +1,24 @@
|
||||
from django.db import migrations
|
||||
|
||||
# رنگها جدا از رنگِ پایهها (Grade.color) و از هماند تا دکمههای نوارِ کتابها در نقشه
|
||||
# بهچشم یک مسیرِ جدا بیایند. آیکونها نامِ lucideاند (همان فهرستی که نقشه میشناسد).
|
||||
SUBJECTS = [
|
||||
('math', 'ریاضی', 'Sigma', '#ED6956', 1),
|
||||
('calculus', 'حسابان', 'LineChart', '#00BCD4', 2),
|
||||
('geometry', 'هندسه', 'Compass', '#9B7BFF', 3),
|
||||
('stats', 'آمار و احتمال', 'BarChart3', '#FF7A3D', 4),
|
||||
('discrete', 'گسسته', 'Network', '#5FBF8F', 5),
|
||||
]
|
||||
|
||||
|
||||
def create_subjects(apps, schema_editor):
|
||||
Subject = apps.get_model('content', 'Subject')
|
||||
for key, title, icon, color, order in SUBJECTS:
|
||||
Subject.objects.get_or_create(
|
||||
key=key, defaults={'title': title, 'icon': icon, 'color': color, 'order': order},
|
||||
)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [('content', '0014_subject')]
|
||||
operations = [migrations.RunPython(create_subjects, migrations.RunPython.noop)]
|
||||
20
content/migrations/0016_unit_subject.py
Normal file
20
content/migrations/0016_unit_subject.py
Normal file
@@ -0,0 +1,20 @@
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
import content.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [('content', '0015_seed_subjects')]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='unit',
|
||||
name='subject',
|
||||
field=models.ForeignKey(
|
||||
default=content.models.default_subject_pk,
|
||||
on_delete=django.db.models.deletion.PROTECT,
|
||||
related_name='units', to='content.subject',
|
||||
),
|
||||
),
|
||||
]
|
||||
19
content/migrations/0017_calculus_units.py
Normal file
19
content/migrations/0017_calculus_units.py
Normal file
@@ -0,0 +1,19 @@
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
def mark_calculus(apps, schema_editor):
|
||||
"""
|
||||
فصلهای پایهی یازدهم و دوازدهمِ موجود از کتابِ «حسابان»اند (`CALCULUS_11/12`)، نه ریاضیِ عمومی.
|
||||
۰۰۱۶ همه را «ریاضی» گذاشت؛ اینجا درست میشود. پایه از `number` شناخته میشود، نه از id.
|
||||
بررسینشده: دیتابیسی که در آن فصلِ یازدهم/دوازدهم از کتابی جز حسابان آمده باشد (روی سرور و
|
||||
لپتاپ نیست؛ هیچ کتابِ دیگری برای آن پایهها پیش از این migration ingest نشده بود).
|
||||
"""
|
||||
Subject = apps.get_model('content', 'Subject')
|
||||
Unit = apps.get_model('content', 'Unit')
|
||||
calculus = Subject.objects.get(key='calculus')
|
||||
Unit.objects.filter(grade__number__in=(11, 12)).update(subject=calculus)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [('content', '0016_unit_subject')]
|
||||
operations = [migrations.RunPython(mark_calculus, migrations.RunPython.noop)]
|
||||
25
content/migrations/0018_split_long_calculus_nodes.py
Normal file
25
content/migrations/0018_split_long_calculus_nodes.py
Normal file
@@ -0,0 +1,25 @@
|
||||
from django.db import migrations
|
||||
|
||||
from content.node_split import split_long_nodes
|
||||
|
||||
|
||||
def split(apps, schema_editor):
|
||||
"""
|
||||
جزیرههای بلندِ (بیش از ۷ درس) پایههای سوم تا دوازدهم را به جزیرههای حداکثر ۶ درسی میشکند (`content/node_split.py`).
|
||||
روی دیتابیسِ خالی (تست، سرورِ تازه) هیچ کاری نمیکند؛ آنجا `seed_content` از فایلِ بازساختهشده میسازد.
|
||||
"""
|
||||
Unit = apps.get_model('content', 'Unit')
|
||||
stats = split_long_nodes(
|
||||
Node=apps.get_model('content', 'Node'),
|
||||
Lesson=apps.get_model('content', 'Lesson'),
|
||||
UserNodeCompletion=apps.get_model('content', 'UserNodeCompletion'),
|
||||
NodeProgress=apps.get_model('content', 'NodeProgress'),
|
||||
units=Unit.objects.filter(grade__number__in=range(3, 13)).order_by('id'),
|
||||
)
|
||||
if stats['nodes_split']:
|
||||
print(f'\n split_long_nodes: {stats}')
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [('content', '0017_calculus_units')]
|
||||
operations = [migrations.RunPython(split, migrations.RunPython.noop)]
|
||||
Reference in New Issue
Block a user