#!/usr/bin/env node const { Op } = require('sequelize'); const { sequelize } = require('../utils/sequelize.js'); const VocabGrammarExercise = require('../models/community/vocab_grammar_exercise.js'); function parseArgs(argv) { const args = { apply: false, ids: [] }; argv.forEach((a) => { if (a === '--apply') args.apply = true; if (/^\d+$/.test(a)) args.ids.push(Number(a)); }); return args; } function tryParse(json) { if (!json) return null; try { return typeof json === 'string' ? JSON.parse(json) : json; } catch (_) { return null; } } async function main() { const args = parseArgs(process.argv.slice(2)); if (!args.ids.length) { console.error('Usage: node repair-fix-body-mc.cjs [--apply]'); process.exit(2); } await sequelize.authenticate(); const rows = await VocabGrammarExercise.findAll({ where: { id: { [Op.in]: args.ids } } }); if (!rows.length) { console.log('No exercises found for ids', args.ids); process.exit(0); } const fixes = []; for (const r of rows) { const q = tryParse(r.questionData) || {}; const a = tryParse(r.answerData) || {}; const type = String(q.type || a.type || '').trim(); if (type !== 'multiple_choice') { console.log('skipping id', r.id, 'type', type); continue; } const options = Array.isArray(q.options) ? q.options.map((o) => String(o).trim()) : []; const correctIndex = Number(a.correctAnswer); const target = 'tutunlan'; const foundIndex = options.findIndex((opt) => opt.toLowerCase() === target.toLowerCase()); if (foundIndex === -1) { console.log('id', r.id, 'options do not contain', target, '->', options.join(', ')); continue; } if (correctIndex === foundIndex) { console.log('id', r.id, 'already correct (index', correctIndex, ')'); continue; } fixes.push({ id: r.id, lessonId: r.lessonId, old: correctIndex, next: foundIndex, options }); } if (!fixes.length) { console.log('No fixes necessary'); process.exit(0); } console.log('Planned fixes:'); fixes.forEach((f) => console.log(` id ${f.id} (lesson ${f.lessonId}): ${f.old} -> ${f.next} options: [${f.options.join(', ')}]`)); if (!args.apply) { console.log('\nDry run complete. Re-run with --apply to persist changes.'); process.exit(0); } for (const f of fixes) { const r = await VocabGrammarExercise.findByPk(f.id); if (!r) continue; const a = tryParse(r.answerData) || {}; a.correctAnswer = f.next; r.answerData = JSON.stringify(a); await r.save(); console.log('Updated id', f.id, '-> correctAnswer', f.next); } console.log('All done'); process.exit(0); } main().catch((err) => { console.error(err); process.exit(2); });