Skip to main content

Scénarios runtime — configuration, réponses et évaluation

Rôle du système Scenario

Le système Scenario gère le contenu d'introduction/contexte, les questions, les réponses de segments et leur évaluation. Il ne doit pas être confondu avec :

  • Tutoriels — guides interactifs qui montrent l'UI et attendent des actions;
  • Timeline — séquences Unity/PlayableDirector audiovisuelles;
  • ScenarioStep — flags de progression persistés dans userDetails.
flowchart LR
SD[Static data / ScenarioPages] --> UI[ScenarioPanelControlBase]
UI --> Q[Questions / Segment grid]
Q --> SAVE[SaveScenarioAnswers / SaveEvalSegment]
SAVE --> EVAL[(evaluation.scenario)]
EVAL --> COMPUTE[compute_scenario_score / compute_segment_score]
COMPUTE --> SCORE[evaluation.scores]
SCORE --> CORRECT[ScenarioEval / corrected UI]
UI --> STEP[eFinishQuestions]
STEP --> USER[(userDetails.scenarioStep)]

Modèles principaux

Fichier Responsabilité
Scenario.cs Réponses booléennes et réponses de segments de l'étudiant.
ScenarioAnswer.cs Réponse attendue par UID.
ScenarioEval.cs Scenario + nombre de bonnes réponses scénario/segments.
ScenarioPages.cs ScriptableObject qui décrit les pages affichées.
ScenarioPanelControlBase.cs Moteur UI principal, navigation, validation et sauvegarde.
ScenarioSegGridControlBase.cs Base de la grille de segments.
EvalCorrectedPopupControl.cs Vue de correction.

ScenarioPages

Chaque PagesDefinition contient :

  • headerText;
  • segGridUid;
  • pages[];
  • questionsStartIndex;
  • numQuestions.

Chargement By Year

ScenarioPages = Resources.Load<ScenarioPages>(
    $"data_{GameUid}/ScenarioPages"
);

Ce chargement est fait dans StaticDataByYearController.Initialize().

Chargement By Module

string moduleUid = moduleByUid.Key.SnakeCaseToPascalCase();

ScenarioPages scenarioPages =
    Resources.Load<ScenarioPages>(
        $"data_{GameUid}/{moduleUid}ScenarioPages"
    );

StaticDataByModuleController charge donc un asset ScenarioPages distinct par module lorsqu'il existe.

Créer ou modifier un Scenario de A à Z

1. Définir le contenu et les réponses attendues

Les réponses des questions sont stockées sous des UIDs comme question_0, question_1, etc. Vérifier que questionsStartIndex et numQuestions correspondent aux réponses statiques attendues.

2. Modifier le bon ScenarioPages asset

  • By Year : data_<gameUid>/ScenarioPages;
  • By Module : data_<gameUid>/<ModuleUid>ScenarioPages.

ScenarioPagesEditor.cs masque la référence de segment grid lorsque useSegmentsInScenario est false.

3. Ajouter les textes

Ajouter les titres, paragraphes, questions et choix via le pipeline de localisation. Ne pas hardcoder le contenu dans ScenarioPanelControlBase.

4. Ajouter un composant game-specific si nécessaire

Le socle Scenario est commun, mais certains jeux possèdent des rendus propres :

  • MK1/MK2/HR1 : ScenarioSegGridControl;
  • MGT1 : tables scenario spécialisées pour segments, employés, features et discipline.

Un nouveau rendu métier reste sous Assets/GameSpecific/<gameUid>/Src/UI.

5. Vérifier InitRuntimePages()

ScenarioPanelControlBase.InitRuntimePages() construit les pages runtime. En By Year, il peut insérer les segments dans la séquence lorsque useSegmentsInScenario est activé.

6. Sauvegarder les réponses de questions

flowchart LR
UI[ScenarioPanelControlBase] --> STUD[Student.SaveScenarioAnswers]
STUD --> BE[BackEnd.SaveScenarioAnswers]
BE --> CMD[_command/save_scenario_answers]
CMD --> E[(evaluation.scenario.answers)]

save_scenario_answers.js merge les clés reçues dans evaluation.scenario.answers, puis sauvegarde le document evaluation.

7. Sauvegarder les segments

SaveEvalSegment appelle _command/save_eval_segment. Le script :

  1. écrit le segment dans evaluation.scenario[segmentUid];
  2. sauvegarde evaluation;
  3. envoie au professeur un message get_data qui devient update_eval.

8. Calculer les scores

Le client appelle les commandes game-specific :

  • <gameUid>_compute_scenario_score;
  • <gameUid>_compute_segment_score.

Elles délèguent au moteur Eval<Game>, sauvegardent dans evaluation.scores, puis retournent les informations utilisées par ScenarioEval.

9. Marquer la fin

Game.Student.SetScenarioStep(
    Scenario.eScenarioStep.eFinishQuestions
);

eFinishQuestions doit rester la valeur 1. Le commentaire du code indique que le serveur suppose explicitement cette valeur.

10. Tester la correction

Tester GetScenarioEvaluation, ScenarioEval.Deserialize(), la vue corrigée et la vue professeur. Ajouter une question sans corriger ce chemin laisse la feature incomplète.

ScenarioStep — progression persistée

Scenario.eScenarioStep est un enum de flags stocké sous forme de bitmask. Il suit la progression utilisateur, pas les réponses de Scenario.

Exemples :

  • eFinishQuestions;
  • eFinishFirstProduct;
  • eStudentAfterFirstResults;
  • eFinishFirstRealLaunch;
  • eStudentFirstModule;
  • eStudentFirstCorrection;
  • eByModuleHomepageTutorial;
  • eStudentFirstFormula;
  • eStudentFirstFormulaActivation.

Ajouter un ScenarioStep

  1. Ajouter un nouveau bit libre avec 1 << n.
  2. Ne jamais renuméroter un ancien bit déjà persisté.
  3. Tester IsScenarioStepDone() avant le flow concerné.
  4. À la fin, appeler SetScenarioStep().
  5. Si la séquence peut être rejouée volontairement, décider si UnSetScenarioStep() est nécessaire.

User.SetScenarioStep() OR le nouveau bit dans le masque local puis appelle _command/set_scenario_step, qui écrit le masque complet dans userDetails.scenarioStep.

States Scenario

  • StudentLoadScenarioState charge l'évaluation;
  • StudentPlayScenarioByYearState attend eFinishQuestions puis choisit le state suivant;
  • StudentPlayScenarioByModuleState lance le welcome By Module puis attend le même flag.

Scenario réouvert après le début

ScenarioPopupControl permet de consulter le scénario après le flow initial. Il conserve la dernière page consultée et réutilise ScenarioPanelControl. En By Module, ScenarioWindowControl adapte les titres selon le module et ses settings.

Debug Scenario

Symptôme Vérifier
Page absente Nom/path de ScenarioPages, pagesDefinitions, asset dans Resources.
Question visible mais non persistée question_N → SaveScenarioAnswers → evaluation.scenario.answers.
Segment non mis à jour chez le prof save_eval_segment → get_data/update_eval.
Score faux Good answers static data + Eval<Game>.
Étudiant bloqué après validation userDetails.scenarioStep et bit eFinishQuestions.
Correction vide get_scenario_evaluation, ScenarioEval, corrected popup.

Checklist avant merge

  • ScenarioPages au bon nom/path;
  • textes FR/EN;
  • réponses sauvegardées puis relues après relog;
  • segments synchronisés professeur;
  • score scenario correct;
  • score segments correct si utilisé;
  • correction correcte;
  • eFinishQuestions déclenche le bon state;
  • aucun ancien ScenarioStep renuméroté;
  • By Year / By Module testés selon le scope.