- Générateur d'exercices : bouton dans menu note → IA crée 5 exercices - Niveaux variés (facile/moyen/difficile) avec emojis 🟢🟡🔴 - Corrigés détaillés dans des toggles (cliquer pour révéler) - Callout warning pour le niveau - Notes créées dans le même carnet - Planning de révision : bouton dans barre carnet → IA crée planning - Choix date d'examen - Répétition espacée (première lecture → revoir → révision globale) - Rappels automatiques ajoutés aux notes (9h le jour J) - Vue chronologique avec activités et notes par jour - Services : exercise-generator.service.ts + study-planner.service.ts - Endpoints : /api/ai/generate-exercises + /api/ai/study-plan - i18n FR/EN complet
98 lines
2.9 KiB
TypeScript
98 lines
2.9 KiB
TypeScript
import { getChatProvider } from '../factory'
|
|
import { getSystemConfig } from '@/lib/config'
|
|
|
|
export interface GeneratedExercise {
|
|
question: string
|
|
difficulty: 'facile' | 'moyen' | 'difficile'
|
|
answer: string
|
|
}
|
|
|
|
export class ExerciseGeneratorService {
|
|
async generate(
|
|
noteTitle: string,
|
|
noteContent: string,
|
|
options: { count?: number; language?: string }
|
|
): Promise<GeneratedExercise[]> {
|
|
const count = options.count || 5
|
|
const lang = options.language || 'fr'
|
|
const langName = lang === 'fr' ? 'français' : lang === 'fa' ? 'فارسی' : 'English'
|
|
|
|
// Strip HTML to plain text for the AI
|
|
const plainText = noteContent
|
|
.replace(/<[^>]+>/g, ' ')
|
|
.replace(/ /g, ' ')
|
|
.replace(/\s+/g, ' ')
|
|
.trim()
|
|
.slice(0, 4000)
|
|
|
|
const prompt = `Tu es un professeur expert. Génère ${count} exercices basés sur ce cours.
|
|
|
|
COURS : "${noteTitle}"
|
|
CONTENU :
|
|
${plainText}
|
|
|
|
Langue : ${langName}
|
|
|
|
Génère ${count} exercices variés avec des niveaux de difficulté différents.
|
|
Pour chaque exercice : une question claire et détaillée, et un corrigé complet et expliqué.
|
|
|
|
FORMAT JSON UNIQUEMENT :
|
|
\`\`\`json
|
|
[
|
|
${Array.from({ length: count }, (_, i) => `{
|
|
"question": "Question détaillée numéro ${i + 1}...",
|
|
"difficulty": "${['facile', 'moyen', 'difficile'][i % 3]}",
|
|
"answer": "Corrigé complet et expliqué..."
|
|
}`).join(',\n ')}
|
|
]
|
|
\`\`\`
|
|
|
|
RÈGLES :
|
|
- Les questions doivent couvrir différents aspects du cours
|
|
- Mélange les types : application directe, analyse, synthèse
|
|
- Les corrigés doivent être détaillés avec les étapes
|
|
- Utilise des formules LaTeX avec la notation standard (\\frac, \\sum, etc.)`
|
|
|
|
const config = await getSystemConfig()
|
|
const provider = getChatProvider(config)
|
|
const raw = await provider.generateText(prompt)
|
|
|
|
return this.parseResponse(raw)
|
|
}
|
|
|
|
private parseResponse(raw: string): GeneratedExercise[] {
|
|
const jsonMatch = raw.match(/```json\s*([\s\S]+?)\s*```/)
|
|
let jsonStr = jsonMatch ? jsonMatch[1] : raw
|
|
|
|
const start = jsonStr.indexOf('[')
|
|
const end = jsonStr.lastIndexOf(']')
|
|
if (start >= 0 && end > start) {
|
|
jsonStr = jsonStr.slice(start, end + 1)
|
|
}
|
|
|
|
try {
|
|
const parsed = JSON.parse(jsonStr)
|
|
return parsed.map((e: any) => ({
|
|
question: String(e.question || ''),
|
|
difficulty: e.difficulty || 'moyen',
|
|
answer: String(e.answer || ''),
|
|
}))
|
|
} catch {
|
|
// Fix backslash escaping
|
|
try {
|
|
const fixed = jsonStr.replace(/\\(?!["\\\/bfnrtu])/g, '\\\\')
|
|
const parsed = JSON.parse(fixed)
|
|
return parsed.map((e: any) => ({
|
|
question: String(e.question || ''),
|
|
difficulty: e.difficulty || 'moyen',
|
|
answer: String(e.answer || ''),
|
|
}))
|
|
} catch {
|
|
throw new Error('Failed to parse exercises')
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
export const exerciseGeneratorService = new ExerciseGeneratorService()
|