TutorLoom
The learning platform for companies, colleges and training institutes. Free and open source, with an Enterprise edition.
翻譯準備中
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證製作者的介紹僅有上面的一句話。 更多詳情請閱讀儲存庫 README。 儲存庫 README ↗
正在載入完整 README。
檢視完整 README ↗Entraînement gratuit aux concours post-bac (commerce et ingénieur) sur annales officielles, avec correction, barème officiel appliqué et suivi de progression.
La source de vérité fonctionnelle est
docs/specifications-plateforme-qcm-annales-v1.2.md.
Les références §x.y de ce dépôt et des commentaires du code renvoient à ses
sections. Le module concours blancs de la prépa a ses propres spécifications,
docs/specifications-module-concours-blancs-v1.0.md ;
les commentaires qui s'y rapportent le disent explicitement
(« module concours blancs, §5 »).
Next.js 16 (App Router) · React 19 · TypeScript · Tailwind v4 · Supabase (PostgreSQL, Auth, Storage, RLS) · Recharts · SheetJS · Resend · Vercel.
npm install
cp .env.example .env.local # puis renseigner les valeurs
npm run dev
npm run build fonctionne sans clé Resend : les emails sont alors écrits dans
la console du serveur au lieu d'être envoyés, ce qui permet de dérouler tout le
parcours d'inscription en local. Un avertissement le rappelle au build.
| Commande | Effet |
|---|---|
npm run dev | serveur de développement |
npm run build | build de production (vérifie la configuration) |
npm test | tests unitaires du cœur métier (scoring, tirage, progression, KPI) |
npm run lint | ESLint |
# Créer un compte de back-office (seul chemin : l'inscription force le rôle élève)
node --env-file=.env.local scripts/creer-admin.mjs <email> <motdepasse> [admin|contributeur]
# Importer l'annale ACCÈS 2025 du POC
node --env-file=.env.local scripts/seed-acces-2025.mjs
# Importer l'annale Advance 2026 (anglais ; les PDF de maths sont archivés
# mais leurs pages sont des images, cf. commentaire en tête du script)
node --env-file=.env.local scripts/importer-advance-2026.mjs <dossier-des-pdf>
# Importer les annales Avenir 2025 et 2026 (anglais ; maths, sciences et
# physique archivés seulement, leur notation ne survit pas à l'extraction)
node --env-file=.env.local scripts/importer-avenir.mjs <dossier-des-pdf>
# Concours blancs : convertir les classeurs d'extraction au format Parkours
# et produire le cahier de relecture (aucun accès réseau, aucune écriture en base)
node scripts/preparer-concours-blancs.mjs <xlsx-ingenieurs> <xlsx-sesame> <dossier-images> <dossier-sortie>
# Concours blancs : recette de bout en bout (§9). Monte une session avec trois
# élèves fictifs, compare notes et rangs à une arithmétique posée à la main,
# puis supprime tout. --garder conserve les données pour inspection.
node --env-file=.env.local scripts/recette-concours-blancs.mjs
# Concours blancs : importer le CSV et ses images — même chemin de code que le
# back-office. Toujours passer par --simulation d'abord : rien n'est écrit.
node --env-file=.env.local scripts/importer-concours-blancs.mjs <fichier.csv> [zip-images...] --simulation
Trois concours importés, une même leçon : les épreuves de langue passent, les épreuves scientifiques non.
| Cas | Exemple | Verdict |
|---|---|---|
| Texte véritable, prose | anglais Advance et Avenir | extractible |
| Pages en images | maths Advance, affirmations Puissance Alpha | OCR nécessaire |
| Texte véritable, notation 2D | maths et sciences Avenir, QCM GEIPI | illisible une fois linéarisé |
Le troisième cas est le plus trompeur : le PDF contient du texte, le diagnostic
le déclare exploitable, mais u_n = (n³+1)/(2n³+5) ressort en fragments empilés
et 5,97×10²⁴ kg devient « 5,97.10kg ». Le QCM GEIPI y ajoute un doublement de
caractères (𝑥𝑥 pour x). Vérifier le rendu d'une question avant d'importer
une épreuve scientifique — le diagnostic automatique ne suffit pas.
Ces imports ont été faits directement en base (scripts service_role ad hoc, non committés) : contrairement au seed ACCÈS, ils ne sont pas reproductibles depuis le dépôt seul.
| Concours | Contenu | Modélisation · barème |
|---|---|---|
| GEIPI Polytech | QCM maths 2023-2026 (115 questions), reconstruit depuis les corrigés officiels | 1 affirmation = 1 question choix_unique Vrai/Faux ; +1/−1. Le plancher de points par exercice de GEIPI n'est pas exprimable (écart assumé). |
| Puissance Alpha | QCM maths : générale 2022 & 2025 (saisie manuelle depuis les corrigés), technologique 2024 (reconstruction partielle du texte extractible), banque « entraînement inédit » 2026 | Filières = épreuves distinctes ; +1/−0,5. Droits de reproduction autorisés par le responsable projet, à documenter (§8.9). |
| SÉSAME | QCM « aptitudes numériques » 2019 (30 questions), étiqueté entraînement | choix_unique à 4 options ; +1/0. |
Restent non importés : les épreuves rédactionnelles (type redaction, V2), les
affirmations Puissance Alpha générale restées en images (OCR requis pour la part
non saisie à la main) et tout exercice dépendant d'une figure absente.
Spécifications :
docs/specifications-module-concours-blancs-v1.0.md.
Les élèves de la prépa composent leurs concours blancs en ligne, la correction
est automatisée et le bilan de session est généré au format Parkours V10.
Étapes livrées à ce jour (§9 du module) : 9 — cohortes et rôles, 10 —
importeur CSV/XLSX Parkours, 11 — sessions et épreuves blanches, 12 — passage
élève, 13 — correction, 14 — bilans V10, 15 — oraux. Le module est
complet, recette de bout en bout comprise (scripts/recette-concours-blancs.mjs).
La banque contient les 490 questions de la session Noël, dont 104 en file de
relecture.
1. Une question de concours blanc vit dans la banque du socle, mais sous un
bloc sans annale. Le §6 du module demande d'ajouter des colonnes à
questions plutôt que de créer une table parallèle — on réutilise ainsi les
propositions, la file de relecture et la correction. Restait le rattachement :
une question descend d'un bloc, qui descend d'une annale, laquelle porte un
couple concours × année unique. Une épreuve blanche n'est pas une annale (il y
en a plusieurs par concours et par an). blocs.annale_id est donc devenu
facultatif, remplacé dans ce cas par blocs.epreuve_id_externe, avec une
contrainte d'exclusivité.
Conséquence à ne pas perdre de vue : le tirage de l'entraînement libre
sélectionne les blocs par épreuve et par statut, sans passer par l'annale. Sans
filtre, les sujets de concours blancs apparaîtraient côté public — avant même
que les élèves de la prépa aient composé. Trois requêtes écartent explicitement
les blocs sans annale (session-entrainement.ts, les deux pages
entrainement), le trigger de statut ne publie jamais un bloc de concours
blanc, et epreuves.visible_public masque les épreuves nées d'un import de
concours blanc.
2. Une affirmation vrai/faux est stockée comme un choix unique Vrai/Faux.
Le type vrai_faux du socle désigne autre chose : un énoncé suivi de
plusieurs affirmations, notées tout ou rien (§2.3). Une ligne vrai_faux du
format Parkours porte une affirmation. Pour ne pas confondre deux
granularités, l'affirmation devient un choix unique entre Vrai et Faux — même
notation (+/− par affirmation), et c'est déjà la convention des QCM GEIPI et
Puissance Alpha importés dans la banque.
3. L'import est idempotent, et ne défait pas une relecture. Le
rapprochement se fait sur id_question_externe et bloc_id_externe :
réimporter un fichier corrigé met à jour les questions au lieu de les
dupliquer. Une question déjà relue par un humain (relue_le renseigné) voit
son contenu mis à jour mais garde son statut : le fichier fait foi sur le
contenu, le relecteur sur la décision de publication.
4. L'épreuve blanche porte son propre barème, et non un lien vers baremes.
Écart assumé par rapport au §6 du module, pour deux raisons. baremes est
unique par (concours, épreuve) : elle ne peut pas porter deux barèmes
différents pour « Avenir / Mathématiques », alors que c'est déjà le cas (+3/−1
en 2025, +1/−1 en 2026, et le concours blanc a le sien). Et trois des quatre
barèmes relevés sur les sujets ne s'expriment pas par un triplet
bonne/mauvaise/abstention : plancher par exercice chez GEIPI, bonification par
exercice entièrement juste chez Puissance Alpha, tout ou rien par question en
analyse documentaire SÉSAME. D'où epreuves_cb.regles, un objet lu par la
correction, et bareme_source, qui conserve la consigne du sujet mot pour
mot. Les valeurs par défaut vivent dans src/lib/epreuves-cb.ts, avec leurs
tests.
5. L'ordre d'une question dans son épreuve est stocké, pas recalculé.
questions.ordre_epreuve reprend la colonne ordre du fichier d'import
(« 13.2 = sous-question 2 de la question 13 »). Sa partie entière groupe les
cases d'une question à trous, ce dont la correction tout ou rien de l'analyse
documentaire a besoin — et qu'aucune reconstruction depuis blocs.ordre ne
pouvait donner, les 29 questions de cette épreuve partageant le bloc qui porte
le corpus.
Les classeurs d'extraction ne sont pas au format Parkours (propositions dans
une seule cellule, pas de colonne ordre ni bloc_id, deux conventions de
colonnes selon le concours). scripts/preparer-concours-blancs.mjs fait la
conversion et produit deux fichiers : le CSV à importer, et un cahier de
relecture listant chaque endroit où la conversion a dû trancher seule (type
corrigé, clé relue dans la rétroaction, chapitre ajouté, figure à contrôler).
Ces questions arrivent en base avec statut_extraction = a_verifier, donc
dans la file de relecture, et ne sont pas servies telles quelles.
L'import lui-même se fait dans le back-office (Prépa → Import concours
blancs, fichier de questions + zip(s) d'images, bouton « Analyser » pour le
rapport sans écriture) ou en ligne de commande avec
scripts/importer-concours-blancs.mjs. Les deux chemins appellent les mêmes
modules — src/lib/import-cb.ts pour la lecture, import-cb-ecriture.ts
pour l'écriture — précisément pour qu'il n'y ait pas deux imports qui
divergent, ce que le dépôt a déjà connu avec les scripts ad hoc des annales.
Migrations dans supabase/migrations, appliquées avec :
npx supabase link --project-ref <ref>
npx supabase db push
1. Les élèves n'ont aucun accès direct à questions ni à
reponses_possibles. La colonne reponses_possibles.est_correcte contient le
corrigé : exposée via PostgREST, n'importe quel élève lirait la réponse avant de
répondre en interrogeant l'API avec son propre jeton. Le contenu jouable est
servi exclusivement par src/lib/session-entrainement.ts, qui retire
est_correcte et les explications non relues. La notation se fait côté serveur.
2. Le statut d'un bloc est dérivé, pas écrit à la main. Un bloc est tiré entier ou pas du tout (§2.2), donc il n'est jouable que si toutes ses questions le sont. Un trigger maintient cette invariante quel que soit le chemin d'écriture (seed, import, relecture, signalement).
| Variable | Rôle |
|---|---|
NEXT_PUBLIC_SUPABASE_URL | projet Supabase |
NEXT_PUBLIC_SUPABASE_ANON_KEY | clé publiable (rôle anon) |
SUPABASE_SERVICE_ROLE_KEY | secret — contourne la RLS, usage serveur uniquement |
RESEND_API_KEY | secret — envoi des emails transactionnels |
EMAIL_EXPEDITEUR | ex. Admissible <[email protected]> |
NEXT_PUBLIC_SITE_URL | URL publique, base des liens envoyés par email |
Le build échoue si l'une manque sur un déploiement de production
(VERCEL_ENV=production), ou si NEXT_PUBLIC_SITE_URL pointe encore vers
localhost. Sans clé Resend, un élève de moins de 15 ans resterait bloqué sans
que personne ne s'en aperçoive : c'est pourquoi le contrôle est bloquant.
Le bilan existe en deux rendus : BilanV10 pour l'écran et
bilan-pdf.tsx pour la pièce jointe de l'email, que l'impression du
navigateur ne peut pas produire côté serveur. Les deux doivent évoluer
ensemble ; ils partent des mêmes données, seule la présentation est
dupliquée, jamais un calcul.
xlsx est installé depuis le CDN de SheetJS et non depuis npm, où le paquet est
figé à une version vulnérable (pollution de prototype à l'ouverture d'un
fichier — soit exactement le chemin de l'import en masse). Le CI et la
plateforme de déploiement doivent pouvoir joindre cdn.sheetjs.com.
Ces points sont connus et documentés, aucun n'est un oubli :
Concours blancs : 104 questions en relecture sur 490. Le cahier
produit par preparer-concours-blancs.mjs les liste avec leur motif.
42 portent une réserve d'extraction héritée des scans (dont 24 sur
Puissance Alpha), 22 dépendent d'une figure à contrôler, 31 ont vu leur
type corrigé par la conversion, 7 ont vu leur clé relue dans la
rétroaction. Aucune n'est servie tant qu'elle n'est pas validée.
Concours blancs : rattachement des textes supports. Cinq documents (article d'anglais SÉSAME, encarts de français, texte LV2) ne sont rattachés qu'à la question qui les cite, alors qu'ils en servent plusieurs. La feuille « Documents » du cahier de relecture attend les questions couvertes.
Concours blancs : pondération des questions. Les classeurs
d'extraction ne portent pas de colonne points : tout est importé à 1.
Les barèmes officiels relevés sur les sujets (Avenir +3/−1, Advance et
Puissance Alpha +1/−0,5, plancher par exercice GEIPI, bonification PA)
sont à charger dans baremes à l'étape 11.
Concours blancs : LV2 non couvertes. Le fascicule SÉSAME contient aussi arabe, chinois, hébreu, italien, japonais, néerlandais, portugais et russe, sans clé de correction au référentiel. Seuls l'allemand et l'espagnol sont importés.
Barèmes — Avenir et Puissance Alpha sont sourcés et datés d'après leurs sujets officiels. Restent à vérifier : ACCÈS, SÉSAME, Advance, et le cas GEIPI ci-dessous. Écran : back-office → Barèmes et seuils.
GEIPI Polytech : le §2 des specs est faux sur deux points. Le sujet officiel 2026 décrit un QCM vrai/faux par affirmation (et non un choix unique) avec points négatifs (et non « pas de points négatifs »), plafonnés par la règle « pour chaque exercice, le total ne peut être strictement négatif ». Ce plancher par exercice n'est pas exprimable dans le modèle actuel, qui ne plafonne qu'au niveau de la session. Appliquer les points négatifs sans ce plancher surpénaliserait les élèves, donc le barème reste sans point négatif et non vérifié. À trancher : implémenter un plancher par bloc, ou assumer l'écart.
Pages légales — mentions légales, CGU et politique de confidentialité sont des trames. Les passages surlignés (raison sociale, SIRET, directeur de publication, hébergeur, durées de conservation, clause de responsabilité) doivent être complétés et l'ensemble relu par un conseil.
Les neuf étapes du §12 sont faites : socle et RLS, landing et pages légales, authentification avec parcours mineur et espace parent, back-office Annales, import en masse et file de relecture, mode entraînement, tableau de bord, sections Élèves et Pilotage avec exports, finitions et déploiement.
Hors périmètre V1, conformément au §3 : type choix_multiple (V1.5),
extraction automatique depuis les PDF (V1.5), mode Conditions réelles, type
redaction, générateur de variantes et sessions ciblées par chapitre (V2).
Droits de reproduction des annales — à sécuriser concours par concours (§8.9). La section propriété intellectuelle en dépend.
Délivrabilité — domaine vérifié chez Resend avec SPF/DKIM, sans quoi les emails d'autorisation parentale partiront en indésirables.
Comptes et données de test — supprimer admin.test@, eleve.test@,
contributeur.test@ et les sessions de démonstration.
Figures manquantes — 3 questions de l'annale ACCÈS 2025 exigent une illustration absente ; elles sont en file de relecture et non jouables.
Advance : deux questions « 22 » par test — le sujet source numérote deux fois la question 22 et n'a pas de 23, dans les trois tests d'anglais. Six questions sont en file de relecture : il faut décider laquelle prend quelle entrée du corrigé. L'une d'elles n'a par ailleurs que trois propositions et un corrigé désignant une quatrième inexistante.
Advance : mathématiques non transcrites — les deux PDF (spécialité et complémentaires, ~180 pages) ont des pages en images. Leur transcription demande un OCR de notation mathématique, hors périmètre V1 (§3), ou une saisie manuelle via l'import XLSX du back-office.
Avenir : droits de reproduction — les corrigés de la session 2025 portent « Propriété exclusive du Concours Avenir. Reproduction interdite. ». L'import a été autorisé explicitement par le responsable du projet, qui a déclaré disposer des droits. À documenter par écrit avant mise en ligne publique.
Avenir : barème variable selon la session — +3 / −1 en 2025, +1 / −1 en 2026,
les deux énoncés dans les sujets officiels. Le schéma ne portant qu'un
barème par concours × épreuve, c'est celui de 2026 qui s'applique à tout.
Si l'écart devient gênant, il faudra une dimension année sur baremes.
Avenir : mathématiques, sciences et physique non transcrites — leur notation scientifique ne survit pas à la linéarisation du texte et les figures sont absentes. PDF archivés, saisie manuelle à prévoir.