diff --git a/content/management/commands/gen_lesson_figures.py b/content/management/commands/gen_lesson_figures.py index 949a259..9ca3a61 100644 --- a/content/management/commands/gen_lesson_figures.py +++ b/content/management/commands/gen_lesson_figures.py @@ -20,15 +20,17 @@ from rag.services.generation import chat_model_for, completion_kwargs PROMPT = ( 'تو برای یک درسِ ریاضی (اپِ آموزشی) شکل‌های آموزشی می‌سازی. متنِ درس: «توضیح»، «مثال» و ' - '«قدم‌ها» (شماره از صفر). فقط جاهایی شکل بگذار که دیدنش مفهوم را روشن می‌کند (نمودار، ' + '«قدم‌ها» (شماره‌ی قدم‌ها از ۱، همان شماره‌ای که کاربر می‌بیند). فقط جاهایی شکل بگذار که دیدنش مفهوم را روشن می‌کند (نمودار، ' 'انتقال، تقارن، محور، جدول، هندسه)؛ هر شکل باید دقیقاً همان چیزی را نشان دهد که آن بخش ' 'می‌گوید، با همان اعداد. بخشِ بی‌نیاز شکل نمی‌گیرد؛ اگر هیچ‌جا لازم نبود []. حداکثر ۵ شکل.\n' 'خروجی فقط یک آرایه‌ی JSON: [{"where":"intro"|"example"|"step","index":0,"diagram":{...}}] ' - '(index فقط برای step). بدونِ توضیح و بدونِ ```.\n' + '(index فقط برای step و همان شماره‌ی ۱‌به‌بعدِ قدم). بدونِ توضیح و بدونِ ```.\n' 'مثال‌های کاتالوگ فقط قالب‌اند: نقطه، تابع یا آیتمی را که این درس لازم ندارد کپی نکن؛ فقط ' 'چیزهایی بگذار که همین شکل نشان می‌دهد (برای نمودارِ تابع معمولاً فقط items با type=function). نمودارِ خط‌شکسته یا تکه‌ای از نقطه‌ها را ' 'با type=segment بین نقطه‌های متوالی بکش، نه type=line (آن خطِ بی‌پایان است). نقطه‌هایی که ' - 'در items نمی‌آیند تعریف نکن.\n\n' + 'در items نمی‌آیند تعریف نکن. شکلِ هر قدم باید همان چیزی را نشان دهد که متنِ همان قدم می‌گوید ' + '(نه قدمِ قبل یا بعد). بازه‌ی x نمودارِ تابع را کوچک بگیر (مثلاً دو واحد دور از رأس/نقطه‌های مهم) تا ' + 'مقدارِ y از حدود ۹ بیشتر نشود و منحنی له نشود؛ marks فقط برای یک منحنی بگذار تا برچسب‌ها روی هم نیفتند.\n\n' ) @@ -57,7 +59,7 @@ class Command(BaseCommand): spent = prompt_t = out_t = 0 for lesson in lessons: body = (f'عنوان: {lesson.title}\nتوضیح: {lesson.intro_text}\nمثال: {lesson.example}\n' - + '\n'.join(f'قدم {i}: {s}' for i, s in enumerate(lesson.steps or []))) + + '\n'.join(f'قدم {i}: {s}' for i, s in enumerate(lesson.steps or [], 1))) r = client.chat.completions.create( model=model, **completion_kwargs(model), messages=[{'role': 'system', 'content': PROMPT + diagram_mod.DIAGRAM_SPEC}, @@ -80,11 +82,16 @@ class Command(BaseCommand): where = it.get('where') if isinstance(it, dict) else None spec = diagram_mod.validate(it.get('diagram')) if where else None idx = it.get('index') + if where == 'step' and isinstance(idx, int): + idx -= 1 # مدل ۱‌به‌بعد می‌نویسد؛ ذخیره از صفر if (spec is None or where not in ('intro', 'example', 'step') or (where == 'step' and not (isinstance(idx, int) and 0 <= idx < len(lesson.steps or []))) or (where == 'example' and not lesson.example)): dropped += 1 continue + for item in spec.get('items', []): + if item.get('type') == 'segment': + item.pop('ticks', None) # علامتِ «ضلع مساوی» روی نمودارِ تابع فقط شلوغی است figures.append({'where': where, **({'index': idx} if where == 'step' else {}), 'diagram': spec}) self.stdout.write(f'درس {lesson.id} «{lesson.title}»: {len(figures)} شکل، {dropped} ردشده') for f in figures: diff --git a/content/seed/curriculum.json b/content/seed/curriculum.json index 9c8425e..d806db4 100644 --- a/content/seed/curriculum.json +++ b/content/seed/curriculum.json @@ -20735,18 +20735,34 @@ "axes": true, "points": { "A": [ - -5.0, + -4.0, 0.0 ], "B": [ - -3.0, + -2.0, 1.0 ], "C": [ - -1.0, + 0.0, 1.0 ], "D": [ + 3.0, + 0.0 + ], + "A1": [ + -5.0, + 0.0 + ], + "B1": [ + -3.0, + 1.0 + ], + "C1": [ + -1.0, + 1.0 + ], + "D1": [ 2.0, 0.0 ] @@ -20769,19 +20785,42 @@ "point": "D" }, { - "type": "segment", - "from": "A", - "to": "B" + "type": "point", + "point": "A1", + "color": "red" + }, + { + "type": "point", + "point": "B1", + "color": "red" + }, + { + "type": "point", + "point": "C1", + "color": "red" + }, + { + "type": "point", + "point": "D1", + "color": "red" }, { "type": "segment", - "from": "B", - "to": "C" + "from": "A1", + "to": "B1", + "color": "red" }, { "type": "segment", - "from": "C", - "to": "D" + "from": "B1", + "to": "C1", + "color": "red" + }, + { + "type": "segment", + "from": "C1", + "to": "D1", + "color": "red" } ], "grid": true @@ -20789,25 +20828,41 @@ }, { "where": "step", - "index": 1, + "index": 2, "diagram": { "kind": "plane", "title": "انتقال نمودار به سمت پایین", "axes": true, "points": { - "A": [ + "A1": [ + -5.0, + 0.0 + ], + "B1": [ + -3.0, + 1.0 + ], + "C1": [ + -1.0, + 1.0 + ], + "D1": [ + 2.0, + 0.0 + ], + "A2": [ -5.0, -3.0 ], - "B": [ + "B2": [ -3.0, -2.0 ], - "C": [ + "C2": [ -1.0, -2.0 ], - "D": [ + "D2": [ 2.0, -3.0 ] @@ -20815,34 +20870,61 @@ "items": [ { "type": "point", - "point": "A" + "point": "A1", + "color": "red" }, { "type": "point", - "point": "B" + "point": "B1", + "color": "red" }, { "type": "point", - "point": "C" + "point": "C1", + "color": "red" }, { "type": "point", - "point": "D" + "point": "D1", + "color": "red" + }, + { + "type": "point", + "point": "A2", + "color": "blue" + }, + { + "type": "point", + "point": "B2", + "color": "blue" + }, + { + "type": "point", + "point": "C2", + "color": "blue" + }, + { + "type": "point", + "point": "D2", + "color": "blue" }, { "type": "segment", - "from": "A", - "to": "B" + "from": "A2", + "to": "B2", + "color": "blue" }, { "type": "segment", - "from": "B", - "to": "C" + "from": "B2", + "to": "C2", + "color": "blue" }, { "type": "segment", - "from": "C", - "to": "D" + "from": "C2", + "to": "D2", + "color": "blue" } ], "grid": true @@ -20861,6 +20943,145 @@ "به طور مثال، نقطه (-4,0) ابتدا به (-5,0) منتقل می‌شود و سپس به (-5,-3) می‌رسد.", "همین کار برای سایر نقاط انجام می‌شود و نمودار نهایی به دست می‌آید.", "✅ جواب: نقاط جدید: (-5,-3), (-3,-2), (-1,-2), (2,-3)" + ], + "figures": [ + { + "where": "example", + "diagram": { + "kind": "plane", + "title": "نمودار تابع f", + "axes": true, + "points": {}, + "items": [ + { + "type": "segment", + "from": [ + -4.0, + 0.0 + ], + "to": [ + -2.0, + 1.0 + ] + }, + { + "type": "segment", + "from": [ + -2.0, + 1.0 + ], + "to": [ + 0.0, + 1.0 + ] + }, + { + "type": "segment", + "from": [ + 0.0, + 1.0 + ], + "to": [ + 3.0, + 0.0 + ] + } + ], + "grid": true + } + }, + { + "where": "step", + "index": 0, + "diagram": { + "kind": "plane", + "title": "انتقال نمودار f به سمت چپ", + "axes": true, + "points": {}, + "items": [ + { + "type": "segment", + "from": [ + -5.0, + 0.0 + ], + "to": [ + -3.0, + 1.0 + ] + }, + { + "type": "segment", + "from": [ + -3.0, + 1.0 + ], + "to": [ + -1.0, + 1.0 + ] + }, + { + "type": "segment", + "from": [ + -1.0, + 1.0 + ], + "to": [ + 2.0, + 0.0 + ] + } + ], + "grid": true + } + }, + { + "where": "step", + "index": 2, + "diagram": { + "kind": "plane", + "title": "انتقال نمودار به سمت پایین", + "axes": true, + "points": {}, + "items": [ + { + "type": "segment", + "from": [ + -5.0, + -3.0 + ], + "to": [ + -3.0, + -2.0 + ] + }, + { + "type": "segment", + "from": [ + -3.0, + -2.0 + ], + "to": [ + -1.0, + -2.0 + ] + }, + { + "type": "segment", + "from": [ + -1.0, + -2.0 + ], + "to": [ + 2.0, + -3.0 + ] + } + ], + "grid": true + } + } ] }, { @@ -20871,7 +21092,7 @@ "where": "intro", "diagram": { "kind": "plane", - "title": "انتقال عمودی نمودار تابع", + "title": "انتقال عمودی تابع", "axes": true, "points": {}, "items": [ @@ -20926,15 +21147,15 @@ { "type": "function", "expr": "(x-2)^2", - "from": -3.0, - "to": 3.0, + "from": -1.0, + "to": 5.0, "marks": [ "vertex" ], "label": "y = g(x)" } ], - "grid": true + "grid": false } } ]