Projet

Général

Profil

Version 5.0

Cette 5° version du logiciel sera la première a être développée en QT/C++

99%

308 demandes   (305 fermées3 ouvertes)

Espace de développement en QT/C++ de ALLER version 5.0

En 2011 nous lançons le re-développement de ALLER en QT/C++. La 1ère décision a été de choisir le nom du logiciel, ça sera donc ALLER version 5.0, la dernière en TCL/TK étant 4.x :)

Utilisation de AbulEduStateMachineV1

Principe de base

Lors des travaux de Juillet 2011 à Concots, il a été décidé de porter Aller 5.0 sur le nouveau (pour nous) paradigme de QStateMachine. Les deux classes AbulEduStateMachineV1 et AbulEduCommonStatesV1 constituent le moteur du logiciel. Elles gèrent le déroulement de la séquence d'exercices (eux-mêmes composés de questions).
Le schéma de fonctionnement de AbulEduStateMachine est visible ici Boite A OutilsV1

Récupérer le code

Attention, le dépot utilise le plugin bzr-externals pour savoir comment l'installer, aller ici

puis faire en console :

bzr branch http://redmine.ryxeo.com/code/leterrier-aller/version-5.0

h3. Créer une nouvelle séquence

On peut s'inspirer d'une séquence déjà créée comme exerciceordrealpha1. Sinon, j'ai ajouter dans le dépôt les fichiers maquette.cpp et .h qui peuvent servir de démarrage. Pensez à bien les renommer et à modifier toutes les références à maquette dans ces deux fichiers ;-)

Il va falloir ajouter au bon endroit les élèments constitutifs de votre séquence.

Le constructeur

À cet endroit, on va créer, initialiser les objets qui vont servir par la suite comme des ZoneEtiquette (ici gv_listeMot) ou des DropZone (gv_tableau).
Il faut le faire à cet endroit sinon ils risquent dêtre initialiser plusieurs fois, et ça va couiner !

AbulEduMaquette::AbulEduMaquette() :
    AbulEduOutilsV1()
{

    setWindowTitle(abeApp->getAbeApplicationLongName()+"--"+trUtf8("Ordre Alphabétique"));

    m_prefixeTetes="pingouin"; // A adapter en fonction des têtes désirées
    m_tailleTetes = 0;
    gv_listeMot = new ZoneEtiquette(QRectF(0,100,100,100)); // exemple à supprimer
    gv_listeMot->setBrush(QColor(Qt::gray)); // exemple à supprimer

    gv_tableau = new DropZone(QRectF(0,100,100,100)); // exemple à supprimer

    sequenceMachine->start();
}

La ligne sequenceMachine->start(); lance la séquence et hop !

On entre dans le vif du sujet : Préparation de la séquence

C'est dans les différents slots appelés par la AbulEduStateMachine sous-jacente que l'on va pouvoir insérer toute l'intelligence métier (pédagogique)!
Le premier slot disponible est SlotSequenceEntered() normalement, on n'y passe qu'une fois tout de suite après le démarrage de la StateMachine.
C'est le bon endroit pour définir des variables d'ordre général, entre autre celle servant au push des log utilisateur.


void ExerciceOrdreAlpha1::slotSequenceEntered()
{
    qDebug()<<"               AbulEduOrdreAlpha1::slotSequenceEntered()";

    setAbeLevel("niveau 1");
    setAbeNbExercices(2);

    //on lance directement le 1er exo de la sequence
    setAbeExerciceName("Ordre Alphabétique - Exercice 1");
    setAbeNbTotalQuestions(1);

    //Quelques customisations
    ui->btnAccueilDemo->setVisible(false);
    teConsigne->setFixedSize(400,200);
    teConsigne->setStyleSheet("background-color:qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(214, 214, 214, 255), stop:1 rgba(167, 165, 164, 255))");

    // Determine si on présente la séquence ou pas.
    onPeutPresenterSequence = true;
    // Determine si on présente l'exercice ou pas.
    onPeutPresenterExercice = true;
    // Determine si on affiche le bilan de l'exercice
    onPeutPresenterBilanExercice = true;

    // Préparation des exercices
    JEVEUXCOLORIERETIQUETTESMALPLACEES=1;
    AbulEduCommonStatesV1::slotSequenceEntered(); // ligne à conserver

    m_prefixeTetes="pingouin";
    m_tailleTetes = 64;
    ui->gvPrincipale->scene()->addItem(gv_listeMot); // exemple à supprimer
    ui->gvPrincipale->scene()->addItem(gv_tableau); // exemple à supprimer
    gv_listeMot->setVisible(false); // exemple à supprimer
    gv_tableau->setVisible(false); // exemple à supprimer

D'une manière générale, toutes les lignes faisant appel à AbulEduCommonStates::Slot... ou AbulEduStateMachine::Slot... sont à conserver !

Présentation de la séquence

La variable booléenne onPeutPresenterSequence décidera d'afficher ou non la présentation de la séquence qui se fait comme suit :

void ExerciceOrdreAlpha1::slotPresenteSequenceEntered()
{
    qDebug()<<"               AbulEduOrdreAlpha1::slotPresenteSequenceEntered();";

    // Normalement, on n'efface pas cette ligne, sinon tant pis
    AbulEduCommonStatesV1::slotPresenteSequenceEntered();

    teConsigne->setHtml(trUtf8("Ici, on affiche les consignes générales de la séquence\n" 
                               "On peut mettre du html avec des images, des tableaux..."));
}

L'animation visible à ce moment peut être modifiée dans AbulEduCommonStates, c'est une classe prévue pour cela. Si on les modifie dans AbulEduCommonStates, elles le seront pour toutes les séquences. Elles doivent aussi pouvoir être redéfinies pour une seule séquence, mais il faut trouver le bon endroit ;-)

Présentation des exercices

La variable booléenne onPeutPresenterExercice décidera d'afficher ou non la présentation de la séquence qui se fait comme suit :


void ExerciceOrdreAlpha1::slotPresentationExerciceEntered()
{
    qDebug()<<"               AbulEduOrdreAlpha1::slotPresenteExoEntered();------";

    teConsigne->setHtml(trUtf8("<font color=#ff0000>Affichage des consignes de l'exercice</font>"));

    AbulEduCommonStatesV1::slotPresentationExerciceEntered();
}

Si l'on veut que cette présentation ne se fasse qu'une fois, il faut mettre onPeutPresenterExercice à false comme ci-dessous

On y est presque : préparation de la question

Ici on va préparer les questions : initialisation des variables liées à la question qui va être proposée.

void ExerciceOrdreAlpha1::slotInitQuestionEntered()
{
    qDebug()<<"               AbulEduOrdreAlpha1::slotInitQuestionEntered();";
    onPeutPresenterExercice = false;

    m_listeMots = m_listeExo.value(m_numExercice); // exemple à supprimer

    AbulEduCommonStatesV1::slotInitQuestionEntered(); // Ne pas enlever sinon...

    afficheMots(); // exemple à supprimer
    gv_listeMot->setVisible(true); // exemple à supprimer
    gv_tableau->setVisible(true); // exemple à supprimer
}

On entre dans l'exercice proprement dit Enfin !

C'est à ce moment qu'il va falloir insérer tout le code permettant la réalisation de l'exercice par l'utilisateur. L'autre partie essentielle vient juste après, c'est la vérification de la réponse proposée.

void ExerciceOrdreAlpha1::slotQuestionEntered()
{qDebug()<<"              AbulEduOrdreAlpha1::slotQuestionEntered()";
    setDimensionsWidgets(); // Place les Widgets à leur place

    AbulEduCommonStatesV1::slotQuestionEntered();
    ui->pbarQuestion->setVisible(false); // Je cache un des widgets fournis par défaut
}

Bon, oui, d'accord, là il n'y a pas de code pour l'exercice. C'est parce que les éléments que j'ai déposés au préalable sont suffisament intelligents pour se débrouiller tout seul !

Sinon, je vous conseille d'insérer dans ce bloc une fonction qui déportera le code exercice plus bas. Cela permet de garder de la lisibilité, mais vous faites comme vous voulez !

Vérifions tout cela !

Quand l'utilisateur aura cliqué sur le bouton vérifier, on entrera dans le slot ci-dessous :

void ExerciceOrdreAlpha1::slotVerificationQuestionEntered()
{
    qDebug()<<"               AbulEduOrdreAlpha1::slotVerificationQuestionEntered()";

    int rep = verifieReponse(); // Le code de vérification est déporté plus bas

    //et on passe au parent pour qu'il s'occupe de l'enchaînement
    //si on souhaite beneficier de l'enchainement par defaut, sinon on
    //implemente ici les sequenceMachine->postEvent(new StringEvent("Questionredo"));
    //and co ad-hoc et on commente la ligne ci-dessous

        AbulEduStateMachineV1::slotVerificationQuestionEntered();

//    if(verifieReponse()==0)
//    {
//        sequenceMachine->postEvent(new StringEvent("Questionsdone"));
//    }
//    else
//    {
//        sequenceMachine->postEvent(new StringEvent("Questionredo"));
//    }
}

Ici, il y a quelques subtilités : la fonction verifieReponse() retourne un entier représentant le nombre d'erreur : 0 pas d'erreur, on passe à la suite.

L'appel à AbulEduStateMachineV1::slotVerificationQuestionEntered(); permet de passer à la question suivante s'il y en a encore, sinon on passe à l'exercice suivant s'il en reste sinon, on s'oriente vers la sortie !

Mais ce comportement ne convient pas forcément à tous les types d'exercice : par exemple, si la réponse n'est pas bonne, l'utilisateur doit modifier sa réponse juste qu'à ce que le résultat soit celui attendu.
C'est ce que l'on fait en appelant sequenceMachine->postEvent(new StringEvent("Questionredo")); dans le cas contraire, on appelle : sequenceMachine->postEvent(new StringEvent("Questionloop")); ou sequenceMachine->postEvent(new StringEvent("Questionsdone")); s'il n'y a plus de question dans l'exercice. Dans mon cas, j'appelle directement "Questionsdone" car il n'y a qu'une question par exercice !

C'est l'heure des bilans

Il y a deux types de bilans : ceux des exercices et celui de la séquence. Le contenu de ces bilan est à votre charge, non mais ! faut travailler un peu !


void ExerciceOrdreAlpha1::slotBilanExerciceEntered()
{
    qDebug()<<"               AbulEduOrdreAlpha1::slotBilanExerciceEntered();";

    gv_listeMot->setVisible(false);  //exemple à supprimer
    gv_tableau->setVisible(false);  //exemple à supprimer

    boiteTetes->setEtatTete(m_numExercice, 1); // affichage des têtes pour évaluation
    AbulEduCommonStatesV1::slotBilanExerciceEntered();
}

void ExerciceOrdreAlpha1::slotBilanSequenceEntered()
{
    qDebug()<<"               AbulEduOrdreAlpha1::slotBilanSequenceEntered();------";
    teBilan->setHtml(trUtf8("BILAN DE LA SÉQUENCE")+"\n");

    AbulEduCommonStatesV1::slotBilanSequenceEntered();
}

Rien de bien complexe ici. Il faudra cependant consulter la doc de AbulEduTeteV1 pour l'utiliser correctement !

A vous de jouer !

Pour toute demande de fonctionnalité ou rapport de bug, cliquez en haut de page sur nouvelle demande et hop !
ou écrivez un mail à

Suivi du temps
Temps estimé 196.25 heures
Demandes par
Bug

170/170

Feature - Fonctionnalité

30/32

Task - Tâche

105/106

Redmine Appliance - Powered by TurnKey Linux