Listing de Qcm_Quiz_Go.htm

 

Vous trouverez ci-dessous le listing commenté de l'applicatif JavaScript Qcm-Quiz. Ce n'est pas forcément la dernière version, mais l'objectif est d'expliquer les grandes lignes et les stratégies mise en place (La dernière version est toujours celle contenue dans qcm_quiz_go.htm du dernier pack).


<HTML>
<HEAD>

<SCRIPT LANGUAGE="JavaScript" SRC="qcm_quiz_param.txt">
//=====================================================
// Il s'agit ici d'inclure les variables modifiables par le créateur de Qcm
// Afin de pouvoir suivre, ci-dessous le contenu utile du fichier
// DEBUT DU FICHIER qcm_quiz_param.txt:
// Nom qui s'affiche en haut dans la barre de note.
var NomDuQuiz = "DEMO DE BASE";
// Nombre de diapos sans la 1° ni la dernière soit nombre de questions x 2
var NbDiapo = 16;
// Si DurDur=0 les réponses fausses compte 0 point
// Si DurDur=1 les réponses fausses retirent des points
var DurDur = 0;
// Ci-dessous le  commentaire des feed-back en haut des diapos réponses
var SiBon  = "<B><font color='purple'>OUI, bonne réponse. </font></B><hr>";
var SiFaux = "<B><font color='red'>NON, lisez bien cette page de corrigé type :</font></B><hr>";
// Ci-dessous les commentaires de fin de QCM
var FeedBack00_05 = "<H2>Attention, une réponse fausse retire un point!</H2>";
var FeedBack06_09 = "<H2>C'est un début, recommencez pour dépasser la moyenne</H2>";
var FeedBack10_12 = "<H2>Correct, bon début, mais recommencez pour mieux installer vos connaissances</H2>";
var FeedBack13_16 = "<H2>Bien, recommencez une dernière fois pour dépasser le 16/20!</H2>";
var FeedBack17_18 = "<H1>Très bien,</H1><br><H2>recommencez dans un mois ou deux pour vérifier vos acquis</H2>";
var FeedBack19_20 = "<H1>E X C E L L E N T !</H1>";
// Ci-dessous la racine, la base du nom des fichiers Diapos
var BaseNomQcm = "qcmquiz";
// Variables en attentes pour développement futur et ... hypothétique ;o)
//  mélanger les items 
var Melange = 0;
// tirer au hasard les questions
var Aleatoire = 0; // FIN DU FICHIER qcm_quiz_param.txt: //===================================================== </SCRIPT> <SCRIPT LANGUAGE="JavaScript"> // ************************************** // * PARTIE "CODE" A NE JAMAIS MODIFIER * // ************************************** // Testé pour NS, iE et Mozilla var Commentaire = "SiBon ou SiFaux"; // Commentaire afficher en haut de chaque diapo-réponse var PremDiapo = 0; // la diapo 000 var NbQuestions = NbDiapo/2; var DiapoCourante = PremDiapo; var Score = 0; var ScoreMax = 0; var NomFicDiapo = BaseNomQcm + "000.htm"; // soit qcmquiz000.htm var ChronoDebut = new Date(); // Pour chronométré le Qcm ChronoDebut = ChronoDebut.getTime(); //************************************* // Met en forme 1->001 10->010 100->100 // Permet de formater le nom des fichiers diapos function FormatZero(iNum) { var sNum = ""+ iNum; while (sNum.length < 3) sNum = "0" + sNum; return sNum; } // ******************************************************* // Ajoute la fonction trim comme méthode de l'objet String // Utile pour si la réponse est un texte // Utilise les "EXPRESSIONS REGULIERES" String.prototype.trim = function() { return this.replace(/(^\s*)|(\s*$)/g, ""); } //******************** // Ajoute la focntion pasdaccent comme méthode de l'objet String // Supprime les accents // Utile si la réponse est un texte String.prototype.pasdaccent = function() { var temp =""; temp = this.replace(/[àâä]/gi,"a"); temp = temp.replace(/[éèêë]/gi,"e"); temp = temp.replace(/[îï]/gi,"i"); temp = temp.replace(/[ôö]/gi,"o"); temp = temp.replace(/[ùûü]/gi,"u"); return temp; } //************************* // Affiche la diapo demandée function AfficheDiapo(iIndex) { var sIndex = FormatZero(iIndex); NomFicDiapo = BaseNomQcm + sIndex + ".htm"; // iE4, iE5.0, attention un return false; doit être actif sinon le redirection ne fonctionne pas :o(
// frames[1].location.href = NomFicDiapo; ou //
frames["FrameDiapo"].location.href = NomFicDiapo; ou encore FrameDiapo.location.href = NomFicDiapo; DiapoCourante = iIndex; } //***************************** // Passe à la diapo courante + i function AvanceDe(iRel) { // a priori iRel = 1 c-a-d la diapo suivante var newI= parseInt(DiapoCourante) + parseInt(iRel); var numqI = parseInt(1 + DiapoCourante/2); if ( newI<= NbDiapo ) { // Affiche la diapo suivante AfficheDiapo(newI); // Met à jour le n° de la question FrameNavigation.document.forms[0].numq.value = numqI + '/' + NbQuestions; } else // Si on a dépassé le nombre de diapo, on affiche la dernière AfficheDiapo(999); } //******************* // lance le Qcm en mode durdur // utile si l'on désire que l'utilisateur choisisse lui-même function Severite (v_coef) { DurDur = v_coef; AvanceDe(1); } //********************************************** //Pré-interprète une réponse Numérique à 1% près function reponseN(v_point, v_rep, v_bon, v_url, v_tol) { //Si le % de tolérance n'est pas donné prendre 1% if (v_tol==void(0)) v_tol="1"; v_tol=v_tol+""; // force v_tol en string var tolerance = "r"; // r comme relatif var PosPlus = v_tol.indexOf("+"); // y-a-t-il le signe plus if (PosPlus != -1) tolerance="a"; // si oui a comme absolu v_tol = eval(v_tol*1); // force v_tol en numérique //Met au bon format décimal v_rep et v_bon var SepDec = "."; var NoSepDec = ","; if (isNaN(12.12)) { // en théorie, Javascript est toujours en point décimal alert("Problème interne, le point décimal n'est le standard JavaScript !!!"); SepDec = ","; NoSepDec = "."; }; var PosSepDec = 0; PosSepDec = v_rep.indexOf(NoSepDec); // Y-a-t-il une virgule ? // S'il y a une virgule, mettre à la place un point if (PosSepDec!=-1) v_rep = v_rep.slice(0, PosSepDec) + SepDec + v_rep.slice(PosSepDec+1, v_rep.length ); PosSepDec = v_bon.indexOf(NoSepDec); if (PosSepDec!=-1) v_bon = v_bon.slice(0, PosSepDec) + SepDec + v_bon.slice(PosSepDec+1, v_bon.length ); if (isNaN(v_rep)) { alert ("La saisie n'est pas un nombre!"); return true; }; //Analyse la réponse en fct de la tolérance +-v_tol% var val_rep = eval(v_rep); // passe en numérique mais garde v_rep en string. var val_bon= eval(v_bon); if (tolerance == "r") // Cas tolérance en relatif % { var val_bon_maxi = val_bon*(100+v_tol)/100; var val_bon_mini = val_bon*(100-v_tol)/100; } else // Sinon, tolérance en absolu + ou - { var val_bon_maxi = val_bon + v_tol; var val_bon_mini = val_bon - v_tol; }; // Si l'erreur est admise, forcer une réponse bonne if ((val_bon_maxi>=val_rep) && (val_bon_mini<=val_rep)) v_rep=v_bon; // Passe la main au module général d'interprétation des réponses reponse(v_point, v_rep, v_bon, v_url); } //************************************ //* Interprète la réponse * //* Module principal de l'applicatif * //************************************ function reponse(v_point, v_rep, v_bon, v_url) { v_rep = v_rep.toLowerCase(); // force en minuscules v_bon = v_bon.toLowerCase(); v_rep = v_rep.trim(); // supprime les espaces extrèmes v_bon = v_bon.trim(); v_rep=v_rep.pasdaccent(); // remplace les accents v_bon=v_bon.pasdaccent(); v_url = v_url + ""; // force en string // Détermine le type de questions var Qmultiple = 0; if (v_rep=="multi" && v_bon=="coches") Qmultiple=1; if (v_rep=="select" && v_bon=="one") Qmultiple=2; if (v_rep=="radio" && v_bon=="button") Qmultiple=3; // Teste si l'utilisateur à bien suivi le Qcm sans Zapper if (v_url.indexOf(NomFicDiapo) == -1) { //alert ("L'objectif est de faire tout le QCM-QUIZZ. Si vous voulez, vous pourrez recommencer à la fin ;o)"); AfficheDiapo(DiapoCourante); return true; }; ScoreMax = ScoreMax + v_point; // Cas classique, les param v_rep et v_bon sont directement interprétables if (Qmultiple==0) { if (v_rep == v_bon) { v_point = v_point; Commentaire = SiBon; } else { v_point = -1*v_point*DurDur; Commentaire = SiFaux; }; }; // Coches avec choix multiple possible // Il faut parcourir toutes les coches du formulaire pour faire l'analyse if (Qmultiple==1) { var v_nb_bon = 0; var v_nb_faux = 0; var i=0; for(i=0; i<FrameDiapo.document.forms[0].elements.length; i++) { // Pour tous les éléments du premier formulaire if (FrameDiapo.document.forms[0].elements[i].type == "checkbox") { // si l'élément du premier formulaire est une case à cocher // 1 et coché ... Ok +1 pt if (FrameDiapo.document.forms[0].elements[i].value==1 && FrameDiapo.document.forms[0].elements[i].checked==true) v_nb_bon++; // 0 et non-coché ... Rien sinon on gagne des points à ne rien répondre// 1 et non-coché ... Faux -1 pt if (FrameDiapo.document.forms[0].elements[i].value==1 && FrameDiapo.document.forms[0].elements[i].checked==false) v_nb_faux++; // 0 et non-coché ... Faux -1 pt if (FrameDiapo.document.forms[0].elements[i].value==0 && FrameDiapo.document.forms[0].elements[i].checked==true) v_nb_faux++; }; }; // Calcul des points en fonction de l'option DurDur v_point = parseInt( v_point*(v_nb_bon - v_nb_faux*DurDur)/(v_nb_bon+v_nb_faux) + 0.5); // Elaboration d'un commentaire approprié au résultat Commentaire=""; if (v_nb_faux == 0) Commentaire = SiBon ; if (v_nb_bon == 0) Commentaire = SiFaux ; Commentaire = Commentaire + v_nb_bon; // Gestions des pluriels "s" et "x" if (v_nb_bon>1) {Commentaire=Commentaire+" coches bonnes et "} else {Commentaire=Commentaire+" coche bonne et "}; Commentaire = Commentaire + v_nb_faux; if (v_nb_faux>1) {Commentaire=Commentaire+" coches fausses."} else {Commentaire=Commentaire+" coche fausse."}; }; // Choix dans des listes // La aussi on va parcourir tout le formulaire 0 // Cette partie ressemble à la précédente Qmultiple=1 mais le test est plus simple if (Qmultiple==2) { var v_nb_bon = 0; var v_nb_faux = 0; var i=0; var choix=0; for(i=0; i<FrameDiapo.document.forms[0].elements.length; i++) { // Pour tous les éléments du premier formulaire if (FrameDiapo.document.forms[0].elements[i].type == "select-one") { // Seule la sélection unique est gérée ici choix= FrameDiapo.document.forms[0].elements[i].selectedIndex; // un seul choix possible par liste et forcément au moins une bonne réponse if (FrameDiapo.document.forms[0].elements[i].options[choix].value==1) {v_nb_bon++;} else {v_nb_faux++;}; }; }; // Calcul des points en fonction de DurDur v_point = Math.floor( v_point*(v_nb_bon-v_nb_faux*DurDur)/(v_nb_bon+v_nb_faux) + 0.5); // Elaboration d'un commentaire adpaté Commentaire=""; if (v_nb_faux == 0) Commentaire = SiBon ; if (v_nb_bon == 0) Commentaire = SiFaux ; Commentaire = Commentaire + v_nb_bon; if (v_nb_bon>1) {Commentaire=Commentaire+" choix exacts et "} else {Commentaire=Commentaire+" choix exact et "}; Commentaire = Commentaire + v_nb_faux; if (v_nb_faux>1) {Commentaire=Commentaire+" choix erronés."} else {Commentaire=Commentaire+" choix erroné."}; }; //Boutons radio qui s'excluent mutuellement s'ils portent le même nom if (Qmultiple==3) { var v_nb_bon = 0; var v_nb_faux = 0; var v_trouver = 0; var i=0; for(i=0; i<FrameDiapo.document.forms[0].elements.length; i++) { // Pour tous les éléments du premier formulaire if (FrameDiapo.document.forms[0].elements[i].type == "radio") { // Seule le type radio est gérée ici if (FrameDiapo.document.forms[0].elements[i].value==1) { // si c'est une bonne réponse possible if( FrameDiapo.document.forms[0].elements[i].checked==true) {v_trouver = 1} ; }; }; }; if( v_trouver==1) {v_nb_bon++} else {v_nb_faux++} ; v_point = parseInt( v_point*(v_nb_bon - v_nb_faux*DurDur)/(v_nb_bon+v_nb_faux) + 0); if (v_nb_bon>v_nb_faux) {Commentaire = SiBon} else {Commentaire= SiFaux}; }; // Met à jour le score Score = Score + v_point; FrameNavigation.document.forms[0].note.value = Score+'/'+ScoreMax; // Passe à la diapo suivante: le corrigé type. AvanceDe(1); } //***************** // Fin de question function fin_question () { // affiche simplement le commentaire éléboré préalablement // document.frames["FrameDiapo"].document.write(Commentaire); ou // document.frames[1].document.write(Commentaire); ou encore FrameDiapo.document.write(Commentaire); } //*********** // Fin de qcm function fin_qcm () { // Calcul de la note /20 arrondi au point supérieur var NoteSur20 = 10; NoteSur20 = Score * 20 / ScoreMax; NoteSur20 = parseInt(NoteSur20+0.7); FrameDiapo.document.write(NoteSur20+'/20'); // Calcul de la durée var ChronoFin = new Date(); ChronoFin = ChronoFin.getTime(); var DureeQcm = (ChronoFin - ChronoDebut) /1000; DureeQcm = Math.floor(DureeQcm); FrameDiapo.document.write(" en "+Math.floor(DureeQcm/60)+" min et "+DureeQcm%60+" sec"); // Choix d'un commentaire approprié à la note var FeedBack = 'Ok'; FeedBack = FeedBack00_05; if (NoteSur20>5) FeedBack = FeedBack06_09; if (NoteSur20>9) FeedBack = FeedBack10_12; if (NoteSur20>12) FeedBack = FeedBack13_16; if (NoteSur20>16) FeedBack = FeedBack17_18; if (NoteSur20>18) FeedBack = FeedBack19_20; FrameDiapo.document.write(FeedBack); } // FIN du programme JavScript // Ensuite, ci-dessous on trouve la création des 2 frames avec appel de la diapo 000 // FrameNavigation : pour la barre du haut (score) // FrameDiapo : pour les diapos </SCRIPT> <TITLE>QCM-QUIZ</TITLE> </HEAD> <Frameset rows="40,*" cols="*" onLoad="AfficheDiapo(0)" framespacing=0 frameborder=0 MarginHeight=0 MarginWidth=0> <Frame src="qcm_quiz_nav.htm" framespacing=0 frameborder=yes scrolling="no" Name="FrameNavigation" MarginHeight=0 MarginWidth=0 border=1> <Frame src="qcm_quiz_not.htm" framespacing=0 frameborder=yes Name="FrameDiapo" border=0 > </Frameset> <NOFRAMES> <BODY> <a href="qcm_quiz_lst.htm">qcm_quiz_lst.htm</a> </BODY> </NOFRAMES> </HTML> Le dernier hyper-lien, non visible en Frame, permet au robot de référencement de suivre toutes les pages du Quiz