Lesson content complete: examples/steps for all 3,778 lessons, 1,775 lessons with fixed figures, 38 quiz fixes
- curriculum.json: example/steps for every real lesson, figures (2,224) hand-written and visually checked - questions.json: 3,703 questions (24 added, 14 keys fixed) - gen_lesson_figures: strict check, thin-figure filter, recheck, --max-usd; API figures limited to plane/fraction/numberline/solid Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,16 +1,28 @@
|
||||
"""
|
||||
شکلِ ثابتِ درسها را یک بار میسازد و در `Lesson.figures` مینویسد.
|
||||
|
||||
همان مسیرِ ارزانِ دستیار: همان مدلِ چت، همان کاتالوگِ <diagram>، همان
|
||||
اعتبارسنجِ `rag.services.diagram.validate`. فرقش این است که نتیجه ذخیره میشود و
|
||||
بعد از تأییدِ چشمی با `seed_content --export` به curriculum.json میرود.
|
||||
فقط درسهایی که شکل لازم دارند شکل میگیرند؛ مدل میتواند `[]` بدهد.
|
||||
آزموده نشده: درستیِ هندسی/ریاضیِ شکل؛ باید با چشم دید.
|
||||
همان مسیرِ ارزانِ دستیار: همان مدلِ چت، همان کاتالوگِ <diagram>، همان اعتبارسنجِ
|
||||
`rag.services.diagram.validate`. فرقش این است که نتیجه ذخیره میشود و بعد از تأییدِ چشمی با
|
||||
`seed_content --export` به curriculum.json میرود.
|
||||
|
||||
python manage.py gen_lesson_figures --grade 12 --limit 4 [--redo] [--dry-run]
|
||||
سه چیز که هزینه و خطا را پایین میآورد:
|
||||
1. **پیشصافیِ رایگان:** اگر متنِ درس به هیچ بخشِ کاتالوگ نمیخورد (حسابِ عددیِ ساده)، مدل صدا
|
||||
زده نمیشود و درس «بینیازِ شکل» ثبت میشود.
|
||||
2. **فقط بخشهای مربوطِ کاتالوگ** (نه کلِ آن، ~۳٬۵۰۰ توکن) کنارِ درس میرود.
|
||||
3. **گامِ وارسیِ مستقل:** هر شکلی که مدل ساخت، مدلِ دوم با متنِ درس مقایسه میکند؛ شکلی که
|
||||
همان چیزِ متن را نشان نمیدهد (عدد/برچسبِ ناهمخوان، قدمِ اشتباه) ذخیره نمیشود.
|
||||
|
||||
سقفِ هزینه با فرمولِ رسمیِ gpt-4.1-mini محاسبه میشود (۰٫۴۰ و ۱٫۶۰ دلار در هر میلیون توکن). صورتحسابِ
|
||||
واقعیِ GapGPT در سنجشهای قبلی چند برابر کمتر بود، پس سقف محافظهکارانه است. آزموده نشده: درستیِ
|
||||
هندسی/ریاضیِ شکل؛ وارسیِ مدلِ دوم جایگزینِ دیدنِ چشمی نیست.
|
||||
|
||||
python manage.py gen_lesson_figures --grade 12 --limit 20 --max-usd 2 --ledger fig_ledger.json
|
||||
"""
|
||||
import json
|
||||
import re
|
||||
import threading
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
from pathlib import Path
|
||||
|
||||
from django.core.management.base import BaseCommand, CommandError
|
||||
|
||||
@@ -18,85 +30,259 @@ from content.models import Lesson
|
||||
from rag.services import clients, diagram as diagram_mod
|
||||
from rag.services.generation import chat_model_for, completion_kwargs
|
||||
|
||||
USD_PER_M_IN = 0.40
|
||||
USD_PER_M_OUT = 1.60
|
||||
MAX_FIGURES = 3
|
||||
|
||||
PROMPT = (
|
||||
'تو برای یک درسِ ریاضی (اپِ آموزشی) شکلهای آموزشی میسازی. متنِ درس: «توضیح»، «مثال» و '
|
||||
'«قدمها» (شمارهی قدمها از ۱، همان شمارهای که کاربر میبیند). فقط جاهایی شکل بگذار که دیدنش مفهوم را روشن میکند (نمودار، '
|
||||
'انتقال، تقارن، محور، جدول، هندسه)؛ هر شکل باید دقیقاً همان چیزی را نشان دهد که آن بخش '
|
||||
'میگوید، با همان اعداد. بخشِ بینیاز شکل نمیگیرد؛ اگر هیچجا لازم نبود []. حداکثر ۵ شکل.\n'
|
||||
'خروجی فقط یک آرایهی JSON: [{"where":"intro"|"example"|"step","index":0,"diagram":{...}}] '
|
||||
'(index فقط برای step و همان شمارهی ۱بهبعدِ قدم). بدونِ توضیح و بدونِ ```.\n'
|
||||
'مثالهای کاتالوگ فقط قالباند: نقطه، تابع یا آیتمی را که این درس لازم ندارد کپی نکن؛ فقط '
|
||||
'چیزهایی بگذار که همین شکل نشان میدهد (برای نمودارِ تابع معمولاً فقط items با type=function). نمودارِ خطشکسته یا تکهای از نقطهها را '
|
||||
'با type=segment بین نقطههای متوالی بکش، نه type=line (آن خطِ بیپایان است). نقطههایی که '
|
||||
'در items نمیآیند تعریف نکن. شکلِ هر قدم باید همان چیزی را نشان دهد که متنِ همان قدم میگوید '
|
||||
'(نه قدمِ قبل یا بعد). بازهی x نمودارِ تابع را کوچک بگیر (مثلاً دو واحد دور از رأس/نقطههای مهم) تا '
|
||||
'مقدارِ y از حدود ۹ بیشتر نشود و منحنی له نشود؛ marks فقط برای یک منحنی بگذار تا برچسبها روی هم نیفتند.\n\n'
|
||||
'تو برای یک درسِ ریاضی (اپِ آموزشی) شکلهای آموزشی میسازی. متنِ درس: «توضیح»، «مثال» و «قدمها» '
|
||||
'(شمارهی قدمها از ۱، همان شمارهای که کاربر میبیند).\n'
|
||||
'قاعدهها:\n'
|
||||
f'- فقط جایی شکل بگذار که دیدنش مفهوم یا مسئله را روشن میکند؛ حداکثر {MAX_FIGURES} شکل. '
|
||||
'شکلِ تزیینی یا تکراری نساز. اگر هیچجا لازم نبود []. ترجیح با «example» و «step» است؛ '
|
||||
'«intro» فقط وقتی متنِ توضیح خودش عدد یا نمادِ مشخص میدهد.\n'
|
||||
'- هر شکل باید دقیقاً همان را نشان دهد که آن بخش میگوید، با همان اعداد و نامها؛ چیزی که در '
|
||||
'متن نیست اختراع نکن. برای بخشی که در متن نیست (مثال/قدم) شکل نساز.\n'
|
||||
'- نمودارِ خطشکسته یا تکهای را با type=segment بین نقطههای متوالی بکش، نه type=line. '
|
||||
'برای نمودارِ تابع بازهی x را کوچک بگیر (مقدارِ y از حدود ۹ بیشتر نشود) و فقط items لازم را بگذار؛ '
|
||||
'marks فقط برای یک منحنی. نقطههایی که در items نمیآیند تعریف نکن.\n'
|
||||
'- شکلِ فقطنقطه (چند نقطهی بیارتباط) نساز؛ نقطه را روی نمودار یا شکلِ مربوطش بگذار. ضابطهی تابع را '
|
||||
'عیناً از متن بردار (ضریب و انتقال را حذف نکن). برای مثلثِ متساویالاضلاع/متساویالساقین و مانندش '
|
||||
'طولها را با نوعش سازگار بده. نوعِ pattern/groups را فقط وقتی بگذار که خودِ متن شکل یا شمارشِ مشخصی میدهد.\n'
|
||||
'- شکلِ هر قدم همان را نشان دهد که متنِ همان قدم میگوید (نه قدمِ قبل یا بعد).\n'
|
||||
'- مثالهای کاتالوگ فقط قالباند؛ نقطه، تابع یا آیتمی را که این درس لازم ندارد کپی نکن.\n'
|
||||
'خروجی فقط یک آرایهی JSON: [{"where":"intro"|"example"|"step","index":1,"diagram":{...}}] '
|
||||
'(index فقط برای step و همان شمارهی ۱بهبعدِ قدم). بدونِ توضیح و بدونِ ```.\n\n'
|
||||
)
|
||||
|
||||
CHECK = (
|
||||
'بازبینِ سختگیرِ ریاضی هستی. یک درس و شکلهایی که برایش ساختهاند (هر شکل یک JSON) داده میشود. '
|
||||
'برای هر شکل ابتدا در یک جمله بنویس «shows»: دقیقاً چه چیزی میکشد (ضابطهی هر تابع، مختصات نقطهها، '
|
||||
'طول ضلعها و زاویهها، بازهها، عددهای جدول، موقعیت و برچسبها). بعد با متنِ همان بخشِ درس مقایسه کن. '
|
||||
'ok=false بده اگر: ضابطه یا عددی با متن نمیخواند (مثلاً ضریب یا انتقال گم شده)؛ شکل از نظر ریاضی/هندسی '
|
||||
'ناسازگار است (مثلاً مثلثِ متساویالاضلاع با ضلعهای نابرابر)؛ موقعیتِ نقطهها با برچسبشان نمیخواند؛ '
|
||||
'شکل مفهومِ اصلیِ آن بخش را نشان نمیدهد یا فقط نقطههای پراکنده/برچسبِ بیمعنی است؛ چیزی اختراع شده؛ '
|
||||
'شکلِ قدم به همان قدم مربوط نیست. هر شکِ جدی → ok=false. سلیقهای ایراد نگیر. '
|
||||
'خروجی فقط JSON: {"verdicts":[{"i":0,"shows":"...","ok":true|false,"why":"یک جمله"}]} به ترتیبِ شکلها.'
|
||||
)
|
||||
|
||||
|
||||
def _lesson_text(lesson: Lesson) -> str:
|
||||
steps = '\n'.join(f'قدم {i}: {s}' for i, s in enumerate(lesson.steps or [], 1))
|
||||
return f'عنوان: {lesson.title}\nتوضیح: {lesson.intro_text}\nمثال: {lesson.example}\n{steps}'
|
||||
|
||||
|
||||
def _spec_for(text: str) -> str:
|
||||
"""فقط بخشهایی از کاتالوگ که کلمههایشان در متن هست؛ بیبخش → '' (مدل صدا زده نمیشود)."""
|
||||
parts = [section for pattern, section in diagram_mod.SECTIONS if pattern.search(text)]
|
||||
return '\n'.join([diagram_mod._HEAD, *parts]) if parts else ''
|
||||
|
||||
|
||||
_SUBSTANTIVE = {'function', 'segment', 'line', 'ray', 'polygon', 'triangle', 'quad', 'regularPolygon', 'circle',
|
||||
'angle', 'exteriorAngle', 'arc', 'vector'}
|
||||
|
||||
|
||||
def _is_thin(diagram: dict) -> bool:
|
||||
"""
|
||||
شکلِ صفحهای که هیچ منحنی، پارهخط یا شکلی ندارد و فقط نقطهی پراکنده است چیزی نشان نمیدهد
|
||||
(مثلاً چند نقطهی A و B و C بیارتباط). نوعِ تازهای که این فهرست نمیشناسد «محتوادار» حساب میشود.
|
||||
"""
|
||||
if diagram.get('kind') != 'plane':
|
||||
return False
|
||||
items = diagram.get('items') or []
|
||||
if any(i.get('type') in _SUBSTANTIVE or i.get('type') not in ('point', 'label', None) for i in items):
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def _json_list(raw: str):
|
||||
raw = re.sub(r'^```(?:json)?|```$', '', (raw or '').strip()).strip()
|
||||
start = raw.index('[')
|
||||
items, _ = json.JSONDecoder().raw_decode(raw[start:])
|
||||
if not isinstance(items, list):
|
||||
raise ValueError('not a list')
|
||||
return items
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = 'ساختِ شکلِ ثابتِ درسها (یک بار، ذخیره در Lesson.figures).'
|
||||
|
||||
def add_arguments(self, p):
|
||||
p.add_argument('--grade', type=int, required=True)
|
||||
p.add_argument('--grade', type=int, help='بدونِ آن همهی پایهها')
|
||||
p.add_argument('--limit', type=int, default=4)
|
||||
p.add_argument('--lesson', type=int, help='فقط همین شناسه')
|
||||
p.add_argument('--redo', action='store_true', help='درسهایی که شکل دارند را هم بساز')
|
||||
p.add_argument('--redo', action='store_true', help='درسهایی که شکل دارند هم')
|
||||
p.add_argument('--dry-run', action='store_true')
|
||||
p.add_argument('--workers', type=int, default=4)
|
||||
p.add_argument('--max-usd', type=float, default=2.0, help='سقفِ هزینه (فرمولِ رسمی)؛ رسید، میایستد')
|
||||
p.add_argument('--ledger', help='JSON از درسهای بررسیشده ({id: نتیجه}) تا دوباره پول نگیرند')
|
||||
p.add_argument('--quiet', action='store_true')
|
||||
p.add_argument('--recheck', action='store_true',
|
||||
help='شکلهای ذخیرهشده را دوباره با وارسیِ سختگیر بسنج و ناموفقها را پاک کن (بیساخت)')
|
||||
p.add_argument('--no-check', action='store_true', help='گامِ وارسیِ مستقل را رد کن (فقط برای آزمایش)')
|
||||
|
||||
def handle(self, *a, **o):
|
||||
qs = Lesson.objects.filter(node__unit__grade__number=o['grade']).order_by(
|
||||
'node__unit__order', 'node__order', 'id')
|
||||
if o['recheck']:
|
||||
return self._recheck(o)
|
||||
qs = Lesson.objects.exclude(example='').order_by(
|
||||
'node__unit__grade__number', 'node__unit__order', 'node__order', 'id')
|
||||
if o['grade']:
|
||||
qs = qs.filter(node__unit__grade__number=o['grade'])
|
||||
if o['lesson']:
|
||||
qs = qs.filter(pk=o['lesson'])
|
||||
if not o['redo']:
|
||||
qs = qs.filter(figures=[])
|
||||
ledger_path = Path(o['ledger']) if o['ledger'] else None
|
||||
ledger = json.loads(ledger_path.read_text()) if ledger_path and ledger_path.exists() else {}
|
||||
if not o['redo']:
|
||||
qs = qs.exclude(pk__in=[int(k) for k in ledger])
|
||||
lessons = list(qs[:o['limit']])
|
||||
if not lessons:
|
||||
raise CommandError('درسی پیدا نشد.')
|
||||
|
||||
model = chat_model_for('')
|
||||
client = clients.get_openai_client()
|
||||
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 [], 1)))
|
||||
lock = threading.Lock()
|
||||
usage = {'in': 0, 'out': 0}
|
||||
stats = {'no_trigger': 0, 'none': 0, 'saved': 0, 'figures': 0, 'rejected': 0, 'invalid': 0, 'stopped': 0}
|
||||
|
||||
def spent():
|
||||
return usage['in'] / 1e6 * USD_PER_M_IN + usage['out'] / 1e6 * USD_PER_M_OUT
|
||||
|
||||
def ask(system, user, **extra):
|
||||
r = client.chat.completions.create(
|
||||
model=model, **completion_kwargs(model),
|
||||
messages=[{'role': 'system', 'content': PROMPT + diagram_mod.DIAGRAM_SPEC},
|
||||
{'role': 'user', 'content': body}])
|
||||
model=model, **completion_kwargs(model), **extra,
|
||||
messages=[{'role': 'system', 'content': system}, {'role': 'user', 'content': user}])
|
||||
u = getattr(r, 'usage', None)
|
||||
spent += (getattr(u, 'total_tokens', 0) or 0)
|
||||
prompt_t += (getattr(u, 'prompt_tokens', 0) or 0)
|
||||
out_t += (getattr(u, 'completion_tokens', 0) or 0)
|
||||
raw = re.sub(r'^```(?:json)?|```$', '', (r.choices[0].message.content or '').strip()).strip()
|
||||
with lock:
|
||||
usage['in'] += getattr(u, 'prompt_tokens', 0) or 0
|
||||
usage['out'] += getattr(u, 'completion_tokens', 0) or 0
|
||||
return r.choices[0].message.content or ''
|
||||
|
||||
def record(lesson, outcome):
|
||||
with lock:
|
||||
if ledger_path and not o['dry_run']:
|
||||
ledger[str(lesson.id)] = outcome
|
||||
ledger_path.write_text(json.dumps(ledger, ensure_ascii=False))
|
||||
|
||||
def work(lesson):
|
||||
text = _lesson_text(lesson)
|
||||
spec = _spec_for(text)
|
||||
if not spec:
|
||||
with lock:
|
||||
stats['no_trigger'] += 1
|
||||
record(lesson, 'no_trigger')
|
||||
return
|
||||
if spent() >= o['max_usd']:
|
||||
with lock:
|
||||
stats['stopped'] += 1
|
||||
return
|
||||
try:
|
||||
start = raw.index('[')
|
||||
items, _ = json.JSONDecoder().raw_decode(raw[start:])
|
||||
if not isinstance(items, list):
|
||||
raise ValueError('not a list')
|
||||
except ValueError as e:
|
||||
items = _json_list(ask(PROMPT + spec, text))
|
||||
except (ValueError, KeyError) as e:
|
||||
with lock:
|
||||
stats['invalid'] += 1
|
||||
self.stderr.write(f'درس {lesson.id}: خروجیِ نامعتبر ({e}); ذخیره نشد.')
|
||||
continue
|
||||
return
|
||||
figures, dropped = [], 0
|
||||
for it in items:
|
||||
for it in items[:MAX_FIGURES + 2]:
|
||||
where = it.get('where') if isinstance(it, dict) else None
|
||||
spec = diagram_mod.validate(it.get('diagram')) if where else None
|
||||
s = 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')
|
||||
if (s 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 _is_thin(s):
|
||||
dropped += 1
|
||||
continue
|
||||
for item in s.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:
|
||||
self.stdout.write(' ' + json.dumps(f, ensure_ascii=False))
|
||||
if figures and not o['dry_run']:
|
||||
lesson.figures = figures
|
||||
figures.append({'where': where, **({'index': idx} if where == 'step' else {}), 'diagram': s})
|
||||
figures = figures[:MAX_FIGURES]
|
||||
if not figures:
|
||||
with lock:
|
||||
stats['none'] += 1
|
||||
record(lesson, 'none' if not items else 'invalid_all')
|
||||
return
|
||||
kept, notes = figures, []
|
||||
if not o['no_check']:
|
||||
try:
|
||||
verdicts = json.loads(ask(CHECK, text + '\n\nشکلها:\n' + '\n'.join(
|
||||
f'{i}: ' + json.dumps(f, ensure_ascii=False) for i, f in enumerate(figures)),
|
||||
response_format={'type': 'json_object'})).get('verdicts', [])
|
||||
ok = {v.get('i'): v for v in verdicts if isinstance(v, dict)}
|
||||
kept = [f for i, f in enumerate(figures) if ok.get(i, {}).get('ok') is True]
|
||||
notes = [f"{i}: {v.get('why', '')}" for i, v in ok.items() if v.get('ok') is not True]
|
||||
except (ValueError, KeyError, AttributeError) as e:
|
||||
kept, notes = [], [f'وارسی ناموفق: {e}']
|
||||
with lock:
|
||||
stats['rejected'] += len(figures) - len(kept)
|
||||
stats['figures'] += len(kept)
|
||||
if kept:
|
||||
stats['saved'] += 1
|
||||
self.stdout.write(f'درس {lesson.id} «{lesson.title}»: {len(kept)} شکل از {len(figures)} '
|
||||
f'({dropped} ردشده در اعتبارسنج)' + (f' | رد: {"; ".join(notes)}' if notes else ''))
|
||||
if not o['quiet']:
|
||||
for f in kept:
|
||||
self.stdout.write(' ' + json.dumps(f, ensure_ascii=False))
|
||||
if kept and not o['dry_run']:
|
||||
lesson.figures = kept
|
||||
lesson.save(update_fields=['figures'])
|
||||
self.stdout.write(f'توکنِ مصرفی: {spent} (ورودی {prompt_t}، خروجی {out_t})')
|
||||
record(lesson, f'figures:{len(kept)}' if kept else 'rejected')
|
||||
|
||||
with ThreadPoolExecutor(max_workers=max(1, o['workers'])) as ex:
|
||||
list(ex.map(work, lessons))
|
||||
self.stdout.write(f'{stats}\nتوکن: ورودی {usage["in"]}، خروجی {usage["out"]}؛ هزینهی فرمولی ≈ ${spent():.3f}')
|
||||
|
||||
def _recheck(self, o):
|
||||
qs = Lesson.objects.exclude(figures=[]).order_by('node__unit__grade__number', 'id')
|
||||
if o['grade']:
|
||||
qs = qs.filter(node__unit__grade__number=o['grade'])
|
||||
lessons = list(qs[:o['limit']])
|
||||
model = chat_model_for('')
|
||||
client = clients.get_openai_client()
|
||||
lock = threading.Lock()
|
||||
usage = {'in': 0, 'out': 0}
|
||||
stats = {'lessons': 0, 'kept': 0, 'dropped': 0, 'errors': 0}
|
||||
|
||||
def work(lesson):
|
||||
figures = [f for f in lesson.figures if not _is_thin(f['diagram'])]
|
||||
thin = len(lesson.figures) - len(figures)
|
||||
text = _lesson_text(lesson)
|
||||
try:
|
||||
r = client.chat.completions.create(
|
||||
model=model, **completion_kwargs(model), response_format={'type': 'json_object'},
|
||||
messages=[{'role': 'system', 'content': CHECK}, {'role': 'user', 'content': text + '\n\nشکلها:\n' + '\n'.join(
|
||||
f'{i}: ' + json.dumps(f, ensure_ascii=False) for i, f in enumerate(figures))}])
|
||||
u = getattr(r, 'usage', None)
|
||||
ok = {v.get('i'): v for v in json.loads(r.choices[0].message.content or '{}').get('verdicts', [])
|
||||
if isinstance(v, dict)} if figures else {}
|
||||
except (ValueError, KeyError, AttributeError) as e:
|
||||
with lock:
|
||||
stats['errors'] += 1
|
||||
self.stderr.write(f'درس {lesson.id}: وارسی ناموفق ({e}); دست نخورد.')
|
||||
return
|
||||
kept = [f for i, f in enumerate(figures) if ok.get(i, {}).get('ok') is True]
|
||||
with lock:
|
||||
usage['in'] += getattr(u, 'prompt_tokens', 0) or 0
|
||||
usage['out'] += getattr(u, 'completion_tokens', 0) or 0
|
||||
stats['lessons'] += 1
|
||||
stats['kept'] += len(kept)
|
||||
stats['dropped'] += len(lesson.figures) - len(kept)
|
||||
why = '; '.join(f"{i}: {v.get('why', '')}" for i, v in ok.items() if v.get('ok') is not True)
|
||||
if len(kept) != len(lesson.figures) and not o['quiet']:
|
||||
self.stdout.write(f'درس {lesson.id} «{lesson.title}»: {len(kept)}/{len(lesson.figures)}'
|
||||
f' (بیمحتوا {thin}) | {why}')
|
||||
if len(kept) != len(lesson.figures) and not o['dry_run']:
|
||||
lesson.figures = kept
|
||||
lesson.save(update_fields=['figures'])
|
||||
|
||||
with ThreadPoolExecutor(max_workers=max(1, o['workers'])) as ex:
|
||||
list(ex.map(work, lessons))
|
||||
cost = usage['in'] / 1e6 * USD_PER_M_IN + usage['out'] / 1e6 * USD_PER_M_OUT
|
||||
self.stdout.write(f'{stats}\nتوکن: ورودی {usage["in"]}، خروجی {usage["out"]}؛ هزینهی فرمولی ≈ ${cost:.3f}')
|
||||
|
||||
101692
content/seed/curriculum.json
101692
content/seed/curriculum.json
File diff suppressed because it is too large
Load Diff
@@ -7232,15 +7232,15 @@
|
||||
"معادله",
|
||||
"حل معادله با استفاده از رسم شکل"
|
||||
],
|
||||
"prompt": "حاصل جمع پنج عدد متوالی طبیعی ۶۵ شده است. عدد وسط چه عددی است؟",
|
||||
"prompt": "جواب معادلهٔ ۵x + ۱۰ = ۶۵ کدام است؟",
|
||||
"type": "multiple_choice",
|
||||
"choices": [
|
||||
"۱۴",
|
||||
"۱۱",
|
||||
"۹",
|
||||
"۱۳",
|
||||
"۱۲",
|
||||
"۲۶"
|
||||
"۱۲"
|
||||
],
|
||||
"correct": 1
|
||||
"correct": 0
|
||||
},
|
||||
{
|
||||
"path": [
|
||||
@@ -7249,15 +7249,15 @@
|
||||
"معادله",
|
||||
"حل معادله با استفاده از روشهای نمادین"
|
||||
],
|
||||
"prompt": "حاصل جمع پنج عدد متوالی طبیعی ۶۵ شده است. عدد وسط چه عددی است؟",
|
||||
"prompt": "سه برابر عددی را با ۵ جمع کردهایم و ۲۰ شده است. آن عدد کدام است؟",
|
||||
"type": "multiple_choice",
|
||||
"choices": [
|
||||
"۱۳",
|
||||
"۱۴",
|
||||
"۲۶",
|
||||
"۱۲"
|
||||
"۴",
|
||||
"۵",
|
||||
"۶",
|
||||
"۱۵"
|
||||
],
|
||||
"correct": 0
|
||||
"correct": 1
|
||||
},
|
||||
{
|
||||
"path": [
|
||||
@@ -9187,7 +9187,7 @@
|
||||
"توان و جذر — گروه 1",
|
||||
"ترتیب انجام عملیات"
|
||||
],
|
||||
"prompt": "۲ × (۳۲ + ۲) = ؟",
|
||||
"prompt": "۲ × (۳² + ۲) = ؟",
|
||||
"type": "multiple_choice",
|
||||
"choices": [
|
||||
"۱۸",
|
||||
@@ -17194,13 +17194,13 @@
|
||||
"ضرب عددها — گروه 5",
|
||||
"محاسبه ضرب اعداد"
|
||||
],
|
||||
"prompt": "۲۰ × ۲۰ = ؟",
|
||||
"prompt": "۳۰ × ۴۰ = ؟",
|
||||
"type": "multiple_choice",
|
||||
"choices": [
|
||||
"۴۰",
|
||||
"۴۰۰",
|
||||
"۲۰۰",
|
||||
"۸۰"
|
||||
"۱۲۰",
|
||||
"۱۲۰۰",
|
||||
"۷۰",
|
||||
"۱۲٬۰۰۰"
|
||||
],
|
||||
"correct": 1
|
||||
},
|
||||
@@ -17670,15 +17670,15 @@
|
||||
"ضرب عددها — گروه 5",
|
||||
"محاسبه ضرب چند رقمی"
|
||||
],
|
||||
"prompt": "۸۰ × ۷۰ = ؟",
|
||||
"prompt": "۶۰ × ۹۰ = ؟",
|
||||
"type": "multiple_choice",
|
||||
"choices": [
|
||||
"۵۶۰",
|
||||
"۵۶۰۰",
|
||||
"۶۳۰۰",
|
||||
"۴۹۰۰"
|
||||
"۵۴۰",
|
||||
"۱۵۰",
|
||||
"۵۴۰۰",
|
||||
"۵۴٬۰۰۰"
|
||||
],
|
||||
"correct": 1
|
||||
"correct": 2
|
||||
},
|
||||
{
|
||||
"path": [
|
||||
@@ -20033,15 +20033,15 @@
|
||||
"معادله",
|
||||
"حل معادله با استفاده از حدس و آزمایش"
|
||||
],
|
||||
"prompt": "حاصل جمع پنج عدد متوالی طبیعی برابر ۶۵ است. عدد وسط کدام است؟",
|
||||
"prompt": "عددی که سه برابرش ۲۷ شود کدام است؟",
|
||||
"type": "multiple_choice",
|
||||
"choices": [
|
||||
"۱۱",
|
||||
"۱۳",
|
||||
"۶",
|
||||
"۱۲",
|
||||
"۱۴"
|
||||
"۹",
|
||||
"۸"
|
||||
],
|
||||
"correct": 1
|
||||
"correct": 2
|
||||
},
|
||||
{
|
||||
"path": [
|
||||
@@ -20050,13 +20050,13 @@
|
||||
"معادله",
|
||||
"حل معادله با استفاده از رسم شکل"
|
||||
],
|
||||
"prompt": "حاصل جمع پنج عدد متوالی طبیعی برابر ۶۵ است. عدد وسط کدام است؟",
|
||||
"prompt": "جواب معادلهٔ ۲x + ۳ = ۱۵ کدام است؟",
|
||||
"type": "multiple_choice",
|
||||
"choices": [
|
||||
"۱۱",
|
||||
"۱۳",
|
||||
"۱۲",
|
||||
"۱۴"
|
||||
"۹",
|
||||
"۶",
|
||||
"۸",
|
||||
"۷"
|
||||
],
|
||||
"correct": 1
|
||||
},
|
||||
@@ -20067,15 +20067,15 @@
|
||||
"معادله",
|
||||
"حل معادله با استفاده از روشهای نمادین"
|
||||
],
|
||||
"prompt": "حاصل جمع پنج عدد متوالی طبیعی برابر ۶۵ است. عدد وسط کدام است؟",
|
||||
"prompt": "اگر x − ۴ = ۹ باشد ، x کدام است؟",
|
||||
"type": "multiple_choice",
|
||||
"choices": [
|
||||
"۱۱",
|
||||
"۵",
|
||||
"۳۶",
|
||||
"۱۳",
|
||||
"۱۲",
|
||||
"۱۴"
|
||||
"−۵"
|
||||
],
|
||||
"correct": 1
|
||||
"correct": 2
|
||||
},
|
||||
{
|
||||
"path": [
|
||||
@@ -31576,15 +31576,15 @@
|
||||
"تناوب و تانژانت",
|
||||
"تشخیص درست یا نادرست بودن جملات مربوط به تابع تناوبی"
|
||||
],
|
||||
"prompt": "کدام یک از جملات زیر دربارهی توابع تناوبی درست است؟",
|
||||
"prompt": "آیا sin(x + ۲π) = sin x است؟",
|
||||
"type": "multiple_choice",
|
||||
"choices": [
|
||||
"تابع تناوبی در هر بازهی تعریفشده صعودی است",
|
||||
"تابع تناوبی در تمام دامنهاش صعودی است",
|
||||
"تابع تناوبی میتواند در بازهای نزولی باشد",
|
||||
"هر تابع تناوبی حتماً زوج است"
|
||||
"بله ، چون ۲π دورهٔ تناوب sin است",
|
||||
"خیر ، همیشه نادرست است",
|
||||
"فقط برای x = ۰ درست است",
|
||||
"فقط برای x = π درست است"
|
||||
],
|
||||
"correct": 2
|
||||
"correct": 0
|
||||
},
|
||||
{
|
||||
"path": [
|
||||
@@ -39464,15 +39464,15 @@
|
||||
"محاسبه حد توابع کسری",
|
||||
"محاسبه حد توابع مثلثاتی"
|
||||
],
|
||||
"prompt": "مقدار حدِ زیر را بیابید:\nlim (x→π/۲) (۱ - sin x) / cos x",
|
||||
"prompt": "مقدار lim(x→۰) tan x / x کدام است؟",
|
||||
"type": "multiple_choice",
|
||||
"choices": [
|
||||
"۰",
|
||||
"۱",
|
||||
"-۱",
|
||||
"وجود ندارد"
|
||||
"∞",
|
||||
"π"
|
||||
],
|
||||
"correct": 0
|
||||
"correct": 1
|
||||
},
|
||||
{
|
||||
"path": [
|
||||
@@ -39600,15 +39600,15 @@
|
||||
"پیوستگی",
|
||||
"رسم نمودار توابع با شرایط پیوستگی و نقاط تعریف نشده"
|
||||
],
|
||||
"prompt": "تابعی در x=۳ تعریف نشده، اما حدِ آن در x=۳ وجود دارد. این تابع در x=۳ چگونه است؟",
|
||||
"prompt": "مقدار lim(x→۱) (x² − ۱)/(x − ۱) کدام است؟",
|
||||
"type": "multiple_choice",
|
||||
"choices": [
|
||||
"پیوسته نیست، چون تعریف نشده است.",
|
||||
"پیوسته است، چون حد وجود دارد.",
|
||||
"پیوسته است، چون همهجا تعریف شده.",
|
||||
"نمیتوان گفت؛ نمودار لازم است."
|
||||
"۰",
|
||||
"۱",
|
||||
"۲",
|
||||
"وجود ندارد"
|
||||
],
|
||||
"correct": 0
|
||||
"correct": 2
|
||||
},
|
||||
{
|
||||
"path": [
|
||||
@@ -39787,15 +39787,15 @@
|
||||
"پیوستگی",
|
||||
"ارائه بازه پیوستگی تابع شامل رادیکال"
|
||||
],
|
||||
"prompt": "تابعِ f(x) = ۲ - √(۷-x) را در نظر بگیرید. کدامیک بازهای بسته است که تابع بر آن پیوسته باشد؟",
|
||||
"prompt": "تابع f(x) = √(x − ۳) − ۴ روی کدام بازه پیوسته است؟",
|
||||
"type": "multiple_choice",
|
||||
"choices": [
|
||||
"[-۲,۸]",
|
||||
"[۷,۱۰]",
|
||||
"[۸,۱۲]",
|
||||
"[-۲,۷]"
|
||||
"[−۳ ، ∞)",
|
||||
"(−∞ ، ۳]",
|
||||
"[۳ ، ∞)",
|
||||
"(−∞ ، ∞)"
|
||||
],
|
||||
"correct": 3
|
||||
"correct": 2
|
||||
},
|
||||
{
|
||||
"path": [
|
||||
@@ -40569,15 +40569,15 @@
|
||||
"جهت تقعر نمودار یک تابع و نقطهی عطف آن",
|
||||
"تشخیص درست یا نادرست بودن گزارههای مربوط به نقاط عطف"
|
||||
],
|
||||
"prompt": "کدام گزاره دربارهی نقطهی عطف نادرست است؟",
|
||||
"prompt": "نقطهٔ عطف f(x) = x³ − ۳x + ۲ کدام است؟",
|
||||
"type": "multiple_choice",
|
||||
"choices": [
|
||||
"تابعِ صعودیِ اکید عطف ندارد",
|
||||
"عطف به تغییرِ تقعر مربوط است",
|
||||
"تابع میتواند چند عطف داشته باشد",
|
||||
"در عطف علامتِ f'' تغییر میکند"
|
||||
"(۱ ، ۰)",
|
||||
"(۰ ، ۲)",
|
||||
"(−۱ ، ۴)",
|
||||
"(۰ ، ۰)"
|
||||
],
|
||||
"correct": 0
|
||||
"correct": 1
|
||||
},
|
||||
{
|
||||
"path": [
|
||||
@@ -54152,13 +54152,13 @@
|
||||
"ضرب عددهای مخلوط",
|
||||
"مقایسه کسرها و تعیین نادرستی"
|
||||
],
|
||||
"prompt": "کدام مقایسه درست است؟",
|
||||
"prompt": "آیا ۳/۵ از ۱/۲ بزرگتر است؟",
|
||||
"type": "multiple_choice",
|
||||
"choices": [
|
||||
"۵ و (۱)/(۳) < ۶",
|
||||
"۵ و (۱)/(۳) > ۶",
|
||||
"۵ و (۱)/(۳) = ۶",
|
||||
"۵ و (۱)/(۳) < ۵"
|
||||
"بله ، چون ۶/۱۰ > ۵/۱۰",
|
||||
"خیر ، چون ۳ < ۵",
|
||||
"برابرند",
|
||||
"نمیتوان مقایسه کرد"
|
||||
],
|
||||
"correct": 0
|
||||
},
|
||||
@@ -61972,13 +61972,13 @@
|
||||
"چهارضلعیها",
|
||||
"تشخیص و تکمیل ویژگیهای چهارضلعیها"
|
||||
],
|
||||
"prompt": "مستطیل علاوه بر ویژگیهای متوازیالاضلاع چه ویژگی دیگری دارد؟",
|
||||
"prompt": "کدام ویژگی در لوزی همیشه برقرار است؟",
|
||||
"type": "multiple_choice",
|
||||
"choices": [
|
||||
"همهی ضلعهایش برابر است",
|
||||
"همهی زاویههایش قائمه است",
|
||||
"فقط یک جفت ضلع موازی دارد",
|
||||
"سه ضلعش برابر است"
|
||||
"چهار زاویهٔ قائمه",
|
||||
"چهار ضلع برابر",
|
||||
"قطرهای برابر",
|
||||
"فقط یک جفت ضلع موازی"
|
||||
],
|
||||
"correct": 1
|
||||
},
|
||||
@@ -62542,6 +62542,414 @@
|
||||
"به طور حتم اتفاق نمیافتد"
|
||||
],
|
||||
"correct": 2
|
||||
},
|
||||
{
|
||||
"path": [
|
||||
"پایه ششم",
|
||||
"فصل ۱: عدد و الگوهای عددی",
|
||||
"عدد و الگوهای عددی — گروه 6",
|
||||
"رابطه بین تعداد مربعها و شماره شکلها"
|
||||
],
|
||||
"prompt": "شکل n از یک الگو ۲n مربع دارد. شکل پنجم چند مربع دارد؟",
|
||||
"type": "multiple_choice",
|
||||
"choices": [
|
||||
"۷",
|
||||
"۱۰",
|
||||
"۱۲",
|
||||
"۲۵"
|
||||
],
|
||||
"correct": 1
|
||||
},
|
||||
{
|
||||
"path": [
|
||||
"پایه ششم",
|
||||
"فصل ۴: تقارن و مختصات",
|
||||
"تقارن و مختصات — گروه 1",
|
||||
"بررسی تقارن چرخشی"
|
||||
],
|
||||
"prompt": "مربع را حول مرکزش حداقل چند درجه بچرخانیم تا روی خودش بیفتد؟",
|
||||
"type": "multiple_choice",
|
||||
"choices": [
|
||||
"۴۵",
|
||||
"۹۰",
|
||||
"۱۸۰",
|
||||
"۳۶۰"
|
||||
],
|
||||
"correct": 1
|
||||
},
|
||||
{
|
||||
"path": [
|
||||
"پایه ششم",
|
||||
"فصل ۴: تقارن و مختصات",
|
||||
"تقارن و مختصات — گروه 2",
|
||||
"تقارن محوری"
|
||||
],
|
||||
"prompt": "قرینهٔ نقطهٔ (۲ ، ۳) نسبت به محور y کدام است؟",
|
||||
"type": "multiple_choice",
|
||||
"choices": [
|
||||
"(۲ ، −۳)",
|
||||
"(−۲ ، ۳)",
|
||||
"(−۲ ، −۳)",
|
||||
"(۳ ، ۲)"
|
||||
],
|
||||
"correct": 1
|
||||
},
|
||||
{
|
||||
"path": [
|
||||
"پایه ششم",
|
||||
"فصل ۴: تقارن و مختصات",
|
||||
"تقارن و مختصات — گروه 2",
|
||||
"تقارن چرخشی"
|
||||
],
|
||||
"prompt": "مثلث متساویالاضلاع را حداقل چند درجه بچرخانیم تا روی خودش بیفتد؟",
|
||||
"type": "multiple_choice",
|
||||
"choices": [
|
||||
"۶۰",
|
||||
"۹۰",
|
||||
"۱۲۰",
|
||||
"۱۸۰"
|
||||
],
|
||||
"correct": 2
|
||||
},
|
||||
{
|
||||
"path": [
|
||||
"پایه ششم",
|
||||
"فصل ۴: تقارن و مختصات",
|
||||
"تقارن و مختصات — گروه 6",
|
||||
"یافتن نقطه تقارن"
|
||||
],
|
||||
"prompt": "نقطهای که وسط پارهخط به سرهای (۲ ، ۲) و (۶ ، ۴) است کدام است؟",
|
||||
"type": "multiple_choice",
|
||||
"choices": [
|
||||
"(۴ ، ۲)",
|
||||
"(۴ ، ۳)",
|
||||
"(۳ ، ۴)",
|
||||
"(۸ ، ۶)"
|
||||
],
|
||||
"correct": 1
|
||||
},
|
||||
{
|
||||
"path": [
|
||||
"پایه ششم",
|
||||
"فصل ۵: اندازه گیری",
|
||||
"اندازه گیری — گروه 3",
|
||||
"زاویههای متقابل به رأس"
|
||||
],
|
||||
"prompt": "دو خط متقاطع زاویهای ۵۰ درجه میسازند. زاویهٔ متقابل به رأس آن چند درجه است؟",
|
||||
"type": "multiple_choice",
|
||||
"choices": [
|
||||
"۵۰",
|
||||
"۱۳۰",
|
||||
"۴۰",
|
||||
"۳۱۰"
|
||||
],
|
||||
"correct": 0
|
||||
},
|
||||
{
|
||||
"path": [
|
||||
"پایه ششم",
|
||||
"فصل ۵: اندازه گیری",
|
||||
"اندازه گیری — گروه 6",
|
||||
"محاسبه مساحت اشکال ترکیبی"
|
||||
],
|
||||
"prompt": "شکلی از یک مستطیل ۶×۴ و یک مربع ۳×۳ (جدا از هم) ساخته شده است. مساحت کل چقدر است؟",
|
||||
"type": "multiple_choice",
|
||||
"choices": [
|
||||
"۳۰",
|
||||
"۲۷",
|
||||
"۳۳",
|
||||
"۶۰"
|
||||
],
|
||||
"correct": 2
|
||||
},
|
||||
{
|
||||
"path": [
|
||||
"پایه هفتم",
|
||||
"فصل ۳: جبر و معادله",
|
||||
"جبر و معادله — گروه 6",
|
||||
"نمودارهای ورودی و خروجی"
|
||||
],
|
||||
"prompt": "رابطهٔ ماشین y = ۲x + ۱ است. اگر ورودی ۵ باشد خروجی چند است؟",
|
||||
"type": "multiple_choice",
|
||||
"choices": [
|
||||
"۱۰",
|
||||
"۱۱",
|
||||
"۱۲",
|
||||
"۷"
|
||||
],
|
||||
"correct": 1
|
||||
},
|
||||
{
|
||||
"path": [
|
||||
"پایه هفتم",
|
||||
"فصل ۴: هندسه و استدلال",
|
||||
"هندسه و استدلال — گروه 4",
|
||||
"محاسبه زاویههای مثلث"
|
||||
],
|
||||
"prompt": "زاویههای یک مثلث ۳x ، ۴x و ۵x هستند. بزرگترین زاویه چند درجه است؟",
|
||||
"type": "multiple_choice",
|
||||
"choices": [
|
||||
"۶۰",
|
||||
"۴۵",
|
||||
"۹۰",
|
||||
"۷۵"
|
||||
],
|
||||
"correct": 3
|
||||
},
|
||||
{
|
||||
"path": [
|
||||
"پایه هفتم",
|
||||
"فصل ۶: سطح و حجم",
|
||||
"سطح و حجم — گروه 4",
|
||||
"گستردهسازی استوانه"
|
||||
],
|
||||
"prompt": "گستردهٔ یک استوانه از چه شکلهایی ساخته شده است؟",
|
||||
"type": "multiple_choice",
|
||||
"choices": [
|
||||
"یک دایره و یک مثلث",
|
||||
"دو دایره و یک مستطیل",
|
||||
"شش مربع",
|
||||
"دو مربع و دو مستطیل"
|
||||
],
|
||||
"correct": 1
|
||||
},
|
||||
{
|
||||
"path": [
|
||||
"پایه هفتم",
|
||||
"فصل ۶: سطح و حجم",
|
||||
"سطح و حجم — گروه 4",
|
||||
"مقاطع اشکال هندسی"
|
||||
],
|
||||
"prompt": "اگر مکعب را با صفحهای افقی ببریم ، مقطع چه شکلی است؟",
|
||||
"type": "multiple_choice",
|
||||
"choices": [
|
||||
"دایره",
|
||||
"مثلث",
|
||||
"مربع",
|
||||
"ذوزنقه"
|
||||
],
|
||||
"correct": 2
|
||||
},
|
||||
{
|
||||
"path": [
|
||||
"پایه هفتم",
|
||||
"فصل ۸: بردار و مختصات",
|
||||
"بردار و مختصات — گروه 5",
|
||||
"پاسخ به سوالات مختصات"
|
||||
],
|
||||
"prompt": "نقطهٔ A(۲ ، ۳) چقدر از محور y فاصله دارد؟",
|
||||
"type": "multiple_choice",
|
||||
"choices": [
|
||||
"۳",
|
||||
"۲",
|
||||
"۵",
|
||||
"۱"
|
||||
],
|
||||
"correct": 1
|
||||
},
|
||||
{
|
||||
"path": [
|
||||
"پایه هفتم",
|
||||
"فصل ۹: آمار و احتمال",
|
||||
"آمار و احتمال — گروه 4",
|
||||
"مقایسه دادهها"
|
||||
],
|
||||
"prompt": "میانگین نمرهٔ کلاس A برابر ۱۵ و کلاس B برابر ۱۷ است. میانگین کدام کلاس بیشتر است؟",
|
||||
"type": "multiple_choice",
|
||||
"choices": [
|
||||
"کلاس A",
|
||||
"کلاس B",
|
||||
"برابرند",
|
||||
"نمیتوان گفت"
|
||||
],
|
||||
"correct": 1
|
||||
},
|
||||
{
|
||||
"path": [
|
||||
"پایه سوم",
|
||||
"فصل ۱: الگوها",
|
||||
"الگوها — گروه 3",
|
||||
"جمع ذهنی دستهها"
|
||||
],
|
||||
"prompt": "در باغی ۱۲ سیب و ۸ پرتقال هست. تعداد کل میوهها چند است؟",
|
||||
"type": "multiple_choice",
|
||||
"choices": [
|
||||
"۴",
|
||||
"۹۶",
|
||||
"۲۰",
|
||||
"۱۸"
|
||||
],
|
||||
"correct": 2
|
||||
},
|
||||
{
|
||||
"path": [
|
||||
"پایه سوم",
|
||||
"فصل ۱: الگوها",
|
||||
"الگوها — گروه 3",
|
||||
"جمع رنگها در اشکال"
|
||||
],
|
||||
"prompt": "شکل اول ۳ مربع قرمز و ۲ مربع آبی و شکل دوم ۴ مربع قرمز و ۵ مربع آبی دارد. روی هم چند مربع قرمز داریم؟",
|
||||
"type": "multiple_choice",
|
||||
"choices": [
|
||||
"۹",
|
||||
"۷",
|
||||
"۱۴",
|
||||
"۱۲"
|
||||
],
|
||||
"correct": 1
|
||||
},
|
||||
{
|
||||
"path": [
|
||||
"پایه سوم",
|
||||
"فصل ۱: الگوها",
|
||||
"الگوها — گروه 5",
|
||||
"ماشین حساب ساده"
|
||||
],
|
||||
"prompt": "ماشینی هر عدد را ۵ تا افزایش میدهد. اگر ورودی ۷ باشد خروجی چند است؟",
|
||||
"type": "multiple_choice",
|
||||
"choices": [
|
||||
"۲",
|
||||
"۳۵",
|
||||
"۱۲",
|
||||
"۷"
|
||||
],
|
||||
"correct": 2
|
||||
},
|
||||
{
|
||||
"path": [
|
||||
"پایه سوم",
|
||||
"فصل ۱: الگوها",
|
||||
"الگوها — گروه 5",
|
||||
"شناسایی الگوهای عددی"
|
||||
],
|
||||
"prompt": "در الگوی ۲ ، ۴ ، ۶ ، ۸ ، … عدد بعدی کدام است؟",
|
||||
"type": "multiple_choice",
|
||||
"choices": [
|
||||
"۹",
|
||||
"۱۰",
|
||||
"۱۲",
|
||||
"۱۶"
|
||||
],
|
||||
"correct": 1
|
||||
},
|
||||
{
|
||||
"path": [
|
||||
"پایه سوم",
|
||||
"فصل ۳: عددهای کسری",
|
||||
"عددهای کسری — گروه 1",
|
||||
"اندازهگیری طول با کسر"
|
||||
],
|
||||
"prompt": "نواری ۸ سانتیمتری است و بخش رنگی آن ۲ سانتیمتر است. بخش رنگی چه کسری از نوار است؟",
|
||||
"type": "multiple_choice",
|
||||
"choices": [
|
||||
"۱/۲",
|
||||
"۳/۴",
|
||||
"۱/۴",
|
||||
"۱/۳"
|
||||
],
|
||||
"correct": 2
|
||||
},
|
||||
{
|
||||
"path": [
|
||||
"پایه سوم",
|
||||
"فصل ۳: عددهای کسری",
|
||||
"عددهای کسری — گروه 2",
|
||||
"تشخیص کسر از شکل"
|
||||
],
|
||||
"prompt": "در یک دایره ۸ بخش مساوی هست و ۳ بخش رنگی شده است. کسر بخش رنگی چیست؟",
|
||||
"type": "multiple_choice",
|
||||
"choices": [
|
||||
"۵/۸",
|
||||
"۳/۸",
|
||||
"۳/۵",
|
||||
"۸/۳"
|
||||
],
|
||||
"correct": 1
|
||||
},
|
||||
{
|
||||
"path": [
|
||||
"پایه سوم",
|
||||
"فصل ۵: محیط و مساحت",
|
||||
"محیط و مساحت — گروه 4",
|
||||
"محاسبه مساحت با شمارش مربعها"
|
||||
],
|
||||
"prompt": "مستطیلی با طول ۴ مربع و عرض ۳ مربع مساحتش چند مربع است؟",
|
||||
"type": "multiple_choice",
|
||||
"choices": [
|
||||
"۷",
|
||||
"۱۴",
|
||||
"۱۲",
|
||||
"۱۰"
|
||||
],
|
||||
"correct": 2
|
||||
},
|
||||
{
|
||||
"path": [
|
||||
"پایه سوم",
|
||||
"فصل ۷: آمار و احتمال",
|
||||
"آمار و احتمال — گروه 3",
|
||||
"تکمیل جدول و نمودار دایرهای"
|
||||
],
|
||||
"prompt": "۴ نفر رنگ آبی و ۴ نفر رنگ قرمز را دوست دارند. در نمودار دایرهای هر رنگ چه بخشی از دایره است؟",
|
||||
"type": "multiple_choice",
|
||||
"choices": [
|
||||
"یکچهارم",
|
||||
"نصف",
|
||||
"یکسوم",
|
||||
"سهچهارم"
|
||||
],
|
||||
"correct": 1
|
||||
},
|
||||
{
|
||||
"path": [
|
||||
"پایه سوم",
|
||||
"فصل ۷: آمار و احتمال",
|
||||
"آمار و احتمال — گروه 4",
|
||||
"رسم نمودار ستونی"
|
||||
],
|
||||
"prompt": "جدول: شنبه ۳ کتاب ، یکشنبه ۵ کتاب. در نمودار ستونی کدام روز ستون بلندتر دارد؟",
|
||||
"type": "multiple_choice",
|
||||
"choices": [
|
||||
"شنبه",
|
||||
"یکشنبه",
|
||||
"هر دو برابر",
|
||||
"هیچکدام"
|
||||
],
|
||||
"correct": 1
|
||||
},
|
||||
{
|
||||
"path": [
|
||||
"پایه سوم",
|
||||
"فصل ۷: آمار و احتمال",
|
||||
"آمار و احتمال — گروه 6",
|
||||
"نمایش دادهها با نمودار تصویری"
|
||||
],
|
||||
"prompt": "در نمودار تصویری هر 🙂 یعنی ۲ کتاب. برای ۴ کتاب چند 🙂 میگذاریم؟",
|
||||
"type": "multiple_choice",
|
||||
"choices": [
|
||||
"۴",
|
||||
"۲",
|
||||
"۱",
|
||||
"۸"
|
||||
],
|
||||
"correct": 1
|
||||
},
|
||||
{
|
||||
"path": [
|
||||
"پایه سوم",
|
||||
"فصل ۸: ضرب عددها",
|
||||
"ضرب عددها — گروه 2",
|
||||
"ضرب با استفاده از شکلهای نمایشی"
|
||||
],
|
||||
"prompt": "در یک باغ ۳ ردیف درخت هست و در هر ردیف ۴ درخت. روی هم چند درخت است؟",
|
||||
"type": "multiple_choice",
|
||||
"choices": [
|
||||
"۷",
|
||||
"۱۶",
|
||||
"۳۴",
|
||||
"۱۲"
|
||||
],
|
||||
"correct": 3
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user