13,689 new quiz questions in 160 practice islands (grades 3-12), Question.figure, replay rotates the quiz, LaTeX removed from lesson/question text

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-12 11:58:18 +03:30
parent f9eea56895
commit dd10ff83f4
14 changed files with 259891 additions and 640 deletions

View File

@@ -0,0 +1,12 @@
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [('content', '0018_split_long_calculus_nodes')]
operations = [
migrations.AddField(
model_name='question',
name='figure',
field=models.JSONField(blank=True, null=True),
),
]

View File

@@ -0,0 +1,54 @@
"""
متنِ درس‌هایی که LaTeX خام داشتند (`\( \vec{a} \)`، `^{n}`) به متنِ ساده‌ی یونیکد برمی‌گردد.
فرانت LaTeX رندر نمی‌کند، پس دانش‌آموز بک‌اسلش و آکولاد می‌دید (درس‌های بردارِ دوازدهم).
فایل‌های seed همین تبدیل را گرفته‌اند، ولی `seed_content` متنِ مثال/قدم‌های درسِ موجود را
عوض نمی‌کند (فقط خانه‌ی خالی را پر می‌کند)، پس سرور بی‌این migration همان متنِ خراب را نگه می‌داشت.
تبدیل در `content/plain_math.py` است و idempotent: بار دوم هیچ‌چیز عوض نمی‌شود. معکوس ندارد
(متنِ قدیم بی‌فایده بود). نمودارها: فقط `FIGURE_TEXT_KEYS`، نه `expr`.
"""
import hashlib
from django.db import migrations
from content.plain_math import convert, convert_figures
def _h(text):
return hashlib.sha1((text or '').encode('utf-8')).hexdigest()
def _key(*parts):
return hashlib.sha1('\x1f'.join(('intro', *map(str, parts))).encode('utf-8')).hexdigest()
def forwards(apps, schema_editor):
Lesson = apps.get_model('content', 'Lesson')
SeedRecord = apps.get_model('content', 'SeedRecord')
qs = Lesson.objects.select_related('node__unit__grade')
for lesson in qs.iterator(chunk_size=500):
new = {
'intro_text': convert(lesson.intro_text),
'example': convert(lesson.example),
'steps': [convert(s) for s in (lesson.steps or [])],
'figures': convert_figures(lesson.figures or []),
}
changed = [f for f, v in new.items() if v != getattr(lesson, f)]
if not changed:
continue
old_intro = lesson.intro_text
for f in changed:
setattr(lesson, f, new[f])
lesson.save(update_fields=changed)
if 'intro_text' in changed:
# دفترِ seed «آخرین متنی که خودمان نوشتیم» را با هش نگه می‌دارد؛ هشِ قدیم بماند
# متنِ تازه «کارِ ادمین» حساب می‌شود و دیگر از فایل تازه نمی‌شود.
n = lesson.node
key = _key(n.unit.grade.title, n.unit.title, n.title, lesson.title)
SeedRecord.objects.filter(key=key, value=_h(old_intro)).update(value=_h(new['intro_text']))
class Migration(migrations.Migration):
dependencies = [('content', '0019_question_figure')]
operations = [migrations.RunPython(forwards, migrations.RunPython.noop)]