Transformer les erreurs en séance de révision

PythonBeginner
Pratiquer maintenant

Introduction

Sauvegardez des réponses stables et transformez uniquement les erreurs de cette partie en entraînement indépendant. Il faut connaître le quiz précédent ainsi que les fonctions, listes, dictionnaires, conditions et boucles Python. Cette unité prépare elle-même les trois règles précédentes ; elle ne dépend d'aucun fichier ni processus d'une autre unité.

Utilisez WebIDE Terminal → New Terminal (More dans une fenêtre étroite). Modifiez seulement logic.py ; conservez engine.py, quiz.py et bank.json. Lecture et pratique estimées : 35 minutes, sans chronométrage de débutants.

Sauvegarder les réponses envoyées en JSON

Dans cette étape, sauvegardez une vraie partie sans lier ses réponses aux positions affichées. Le moteur fourni renvoie une liste contenant uniquement les couples question_id/option_id envoyés. Il gère les retours et le score ; l'enregistrement ne déclare pas lui-même la justesse et ne contient pas de numéro affiché.

Commencez dans le terminal WebIDE :

cd /home/labex/project

json.dump écrit les listes et dictionnaires Python en JSON. with open(..., "w", encoding="utf-8") ouvre un fichier texte en écriture et le ferme ensuite. UTF-8 rend le texte portable ; ensure_ascii=False laisse Unicode lisible et indent=2 facilite la lecture. stream.write("\n") termine le fichier par un saut de ligne. L'enveloppe {"answers": answers} identifie la liste.

Le here-document complet conserve les trois règles préparées et ajoute la sauvegarde. > remplace logic.py ; <<'PY', entre guillemets, écrit le texte littéral jusqu'au dernier PY. La fonction d'entraînement sera ajoutée à l'étape suivante.

cat > logic.py <<'PY'
import json


def choose_questions(questions, count, rng):
    return rng.sample(questions, min(count, len(questions)))


def move_options(question, rng):
    options = question["options"].copy()
    rng.shuffle(options)
    return options


def read_answer(options, ask, tell):
    while True:
        text = ask("Answer (number or q): ").strip()
        if text.lower() == "q":
            return None
        for position, option in enumerate(options, start=1):
            if text == str(position):
                return option["option_id"]
        tell("Enter one displayed number, or q to stop.")


def save_answers(path, answers):
    with open(path, "w", encoding="utf-8") as stream:
        json.dump({"answers": answers}, stream, ensure_ascii=False, indent=2)
        stream.write("\n")
PY

--ordered conserve l'ordre connu des questions et choix ; --output désigne un nouvel enregistrement. Un chemin de sortie existant est refusé avant de jouer, protégeant les anciens fichiers. Répondez à deux questions : 1 pour sky (correct), puis 1 pour tide (incorrect).

python3 quiz.py bank.json --ordered --count 2 --output round.json
Score: 1/2 answered
Saved round.json

cat affiche le véritable enregistrement :

cat round.json

Il contient sky/sun et tide/sun. Le même identifiant d'option a un sens différent dans chaque question. Gardez cette partie originale. Si vous relancez par erreur, le refus de sortie existante est attendu : choisissez un autre nom pour vos essais sans l'écraser. Si le fichier source est mal nommé, consultez ls et relancez le bon chemin ; Quiz error: ... ne signifie pas qu'une partie a été sauvegardée.

Réviser uniquement les erreurs de cette partie

Dans cette étape, recalculez les erreurs à partir du véritable identifiant correct de chaque question. Un dictionnaire relie les questions répondues aux options choisies. Ne retenez une question que si elle a une réponse et que celle-ci diffère de son propre correct_option_id. Excluez les réponses correctes et les questions non répondues. La liste conserve des questions entières. Dans {answer["question_id"]: answer["option_id"] for answer in answers}, la partie après for parcourt les réponses et la partie clé/valeur précédente construit chaque entrée : c'est une compréhension de dictionnaire. Dans [question for question in questions if ...], for parcourt les questions et if ne garde que les objets correspondants : c'est une compréhension de liste. and exige les deux conditions : la réponse existe et elle est incorrecte. Une question non répondue ne devient donc pas une erreur. >> ajoute sans remplacer les règles existantes :

cat >> logic.py <<'PY'
def wrong_questions(questions, answers):
    selected = {answer["question_id"]: answer["option_id"] for answer in answers}
    return [question for question in questions
            if question["question_id"] in selected
            and selected[question["question_id"]] != question["correct_option_id"]]
PY

--practice lit la partie originale ; --output écrit un autre nouvel enregistrement. L'entraînement reprend toutes les erreurs de cette seule partie, sans historique cumulatif. Lancez :

python3 quiz.py bank.json --practice round.json --output retry.json

Seule la question tide apparaît. Sélectionnez le numéro affiché de Moon, qui peut changer de place. Le résultat est Score: 1/1 answered. Inspectez les deux enregistrements indépendants :

cat round.json retry.json

L'original conserve tide/sun ; la révision contient tide/moon. La banque n'a pas changé. Créez maintenant une partie entièrement correcte. Les nombres sont positifs et le tirage est plafonné par min(count, len(questions)) ; 100 pose chacune des trois questions une fois.

python3 quiz.py bank.json --ordered --count 100 --output perfect.json

Saisissez 1, 2, 2 pour sky, tide et roots. Entraînez-vous ensuite sur cette partie :

python3 quiz.py bank.json --practice perfect.json --output empty.json
No mistakes to practice.
Score: 0/0 answered
Saved empty.json

Un ensemble d'erreurs vide est valide. Enfin, lancez une nouvelle partie et saisissez q avant de répondre :

python3 quiz.py bank.json --output stopped.json

Le score est 0/0 et la liste answers de stopped.json est vide. Elle ne doit pas enregistrer comme incorrecte la question quittée. Gardez les cinq fichiers. Si une modification crée une erreur de syntaxe, répétez le bloc complet de l'étape ; comme l'étape 1 remplace le fichier, répétez ensuite le bloc d'ajout de l'étape 2. Conservez les enregistrements et utilisez de nouveaux noms pour d'autres parties.

Résumé

Vous avez sauvegardé les couples d'identifiants réellement envoyés, conservé la partie originale et créé un entraînement indépendant, y compris les cas valides vides et interrompus.