Version 5.0
Cette 5° version du logiciel sera la première a être développée en QT/C++
99%
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 :)
- Interface principale
- Interface des exercices
- Développement des classes de base
- Développement du module Phrase Sans Espaces
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 à dev@abuledu.org