Cours:Technologies avancées du eLearning 2/exercices/Saisie de notes
De GBLL, TAL, ALAO, etc.
Énoncé dans le support de cours diapo 25
Une correction (ci-dessous la même sans le HTML).
Fonctions issues des exercices de saisie de nombres
function isDigit(caractere){
var result;
switch(caractere.toString()){
case "0":
case "1":
case "2":
case "3":
case "4":
case "5":
case "6":
case "7":
case "8":
case "9":
result = true;
break ;
default:
result = false;
}
return result;
}
//Prend une chaine de caractère et dit si c'est un nombre
function isNumber(word,min,max){
//déclaration de variables
//isFloat : booléen qui dit si le “word” comporte (déjà) une virgule
var isFloat = word.charAt(0)=="," || word.charAt(0)==".",
//result : booléen qui dit si le word est (pour le moment) un nombre
result = isDigit(word.charAt(0))
|| ( word.length > 1
&& (isFloat || word.charAt(0)=="-"));
//On initialise result à vrai si le premier caractère est un chiffre ou
//si c'est une virgule ou un moins, mais que le word contient d'autres caractères
/*On parcourt le reste du word (mais on s'arrête dès qu'on est sûr que ce n'est pas un
nombre. Dès que résultat sera faux, (result && i<word.length) sera faux.*/
for(let i=1;result && i<word.length;i++){
if(word.charAt(i)=="," || word.charAt(i)=="."){
if(isFloat){
result = false;
}
else{
isFloat = true;
}
}
else if(!isDigit(word.charAt(i))){
result = false;
}
}
//modification pour pouvoir demander un nombre compris entre min et max
if( (result!==false)
&& (typeof min != "undefined")//paramètre optionnel
&& (min !== false) // pas pris en compte s'il vaut faux
&& (Number(word) < min)){
result = false ;
}
if( (result!==false)
&& (typeof max != "undefined")//paramètre optionnel
&& (max !== false) // pas pris en compte s'il vaut faux
&& (Number(word) > max)){
result = false ;
}
return result;
}
function arrayToTable(theArray, tableId){
var elt = document.getElementById(tableId),
res = theArray;
if(elt == null){
//L'identifiant n'existe pas
console.error("arrayToTable : "+tableId + " n'existe pas dans le document.");
res = false;
}
else if(elt.tagName != "TABLE"){
//L'identifiant n'existe pas
console.error("arrayToTable : "+tableId + " n'est pas une table ("+elt.tagName+").");
res = false;
}
else{
//on crée du contenu
var line = document.createElement("tr");
for(let i=0;i<theArray.length;i++){
line.innerHTML += "<td>"+theArray[i]+"</td>";
}
//on le met dans l'élément
elt.appendChild(line);
}
return res;
}
Nouvelles Fonctions
//renvoie un nombre de notes (≥ 1) ou false
function getNbCount(){
var res = window.prompt("Combien y a-t-il eu de notes dans le trimestre ?");
//Tant que l'utilisateur saisit une valeur qui n'est pas un nombre ≥ 1 on continue
while(res != null && (res == "" || !isNumber(res,1)) ){
res = window.prompt("Combien y a-t-il eu de notes dans le trimestre ?");
}
if(res == null){
res = false;
}
else{
res = Number(res);
}
return res;
}
//Renvoie un nom (ou false)
function getName(){
var userText = window.prompt("Entrez le nom de l'élève");
//on renvoie faux si l'utilisateur dit stop (ou annuler)
if((userText == null) || (userText =="stop")){
userText = false;
}
return userText ;
}
//Récupère le nom et les notes
function getLine(nb){
var res = false,
userText = getName();
//si la saisie ne demande pas la fin du travail, on modifie res
if(userText!==false){
nb = Number(nb);
res = [] ;
res.push(userText);
//on ajoute les notes (on interrompt le travail si l'utilisateur appuie sur annuler)
while( (res.length <= nb) && (userText != null) ){
userText = window.prompt("Entrez la note n°"+res.length+"/"+nb+" de "+res[0]);
if(userText=="-"){
//autoriser les absences
res.push("-");
}
else if(isNumber(userText,0,20)){
//refuser les notes non comprises entre 0 et 20
res.push(Number(userText));
}
}
if(userText == null){
res = false;
}
}
return res ;
}
//Gère les interactions pour remplir la table
function fillTable(tableId){
var count = getNbCount();
if(count !== false){
line = getLine(count);
while(line !== false){
line.push(mean(line,false,1));
arrayToTable(line, tableId);
line = getLine(count);
}
}
}
Version avec les moyennes
//Remplit les tables et ajoute des moyennes
function fillTableWithMeans(tableId){
var count = getNbCount();
let completeTable = [] ;
if(count !== false){
line = getLine(count);
while(line !== false){
line.push(mean(line,false,1));
completeTable.push(line);
line = getLine(count);
}
let means=["Moyenne"];
for(let i=1;i<completeTable[0].length;i++){
means.push(mean(completeTable,i));
}
completeTable.push(means);
}
for(let i=0;i<completeTable.length;i++){
arrayToTable(completeTable[i], tableId);
}
}
/***************
* calcule une moyenne dans un tableau à une ou deux entrées
* entre les cases min et max
***
* anArray : le tableau dans lequel calculer la moyenne
* columnId : entier → indice de la colonne sur laquelle on calcule la moyenne
* false → calcul dans un tableau à 1 dimension
* min (optionnel) : entier → indice de la première case concernée
* (permet d'ignorer celles qui précèdent)
* max (optionnel) : entier → indice de la première case concernée
* (permet d'ignorer celles qui suivent ex: moyenne calculée)
**************/
function mean(anArray,columnId,min,max){
var res = 0,
nbNotes = 0;
if(typeof min=="undefined"){
//valeur par défaut de min
min = 0;
}
if(typeof max == 'undefined'){
//valeur par défaut de max
max = anArray.length;
}
//parcours en ligne
if(typeof columnId == "undefined" || columnId === false){
for (let i=min;i<max;i++){
if(typeof anArray[i] == "number" ){
res += anArray[i] ; // ←→ res + anArray[i]
nbNotes++;
}
}
}
else{//parcours en colonne, pour la colonne d'id columnId
for (let i=min;i<max;i++){
if(typeof anArray[i][columnId] == "number" ){
res += anArray[i][columnId] ; // ←→ res + anArray[i]
nbNotes++ ;
}
}
}
return res/nbNotes;
}
Version avec les tris
//Remplit les tables et ajoute des moyennes et trie la table
//selon l'algo (à définir) de la fonction de tri sortFunction
function fillSortedTableWithMeans(tableId,sortFunction){
var count = getNbCount();
let completeTable = [] ;
if(count !== false){
line = getLine(count);
while(line !== false){
line.push(mean(line,false,1));
completeTable.push(line);
line = getLine(count);
}
completeTable = sortFunction(completeTable) ;
let means=["Moyenne"];
//count = nb notes + 1 pour la moyenne générale
for(let i=1;i<=count+1;i++){
means.push(mean(completeTable,i));
}
completeTable.push(means);
}
for(let i=0;i<completeTable.length;i++){
arrayToTable(completeTable[i], tableId);
}
}
//La partie suivante utilise le fait que javascript
//traite les fonctions comme des variables normales
//cf. affectation d'événements
//voir aussi la notion de fonction anonyme
//https://ulea-wiki.univ-grenoble-alpes.fr/_/Utilisateur:Mathieu_Loiseau/Cours/Master_DDL_%e2%80%94_Parcours_DILIPEM/M2_%e2%80%94_technologies_avanc%c3%a9es_du_eLearning_2/TOUT_ce_qu'il_y_a_%c3%a0_savoir#Fonction_anonyme
//Comparaison alphabétique de 2 lignes de tableau telles que construites par notre programme
function compareAlpha(tr1, tr2){
var elt1 = tr1[0], //le nom est toujours dans la première case de la ligne
elt2 = tr2[0], //le nom est toujours dans la première case de la ligne
res = 0 ; //égalité des valeurs par défaut
if(elt1 < elt2){ //si le premier est inférieur au second valeur négative
res = -1 ;
}
else if(elt2 < elt1){//sinon valeur positive
res = 1 ;
}
return res ;
}
//Comparaison de la moyenne de 2 lignes de tableau telles que construites par notre programme
function compareMean(tr1, tr2){
var elt1 = tr1[tr1.length-1], //la moyenne est toujours dans la dernière case du tableau
elt2 = tr2[tr2.length-1], //la moyenne est toujours dans la dernière case du tableau
res = 0 ; //égalité des valeurs par défaut
if(elt1 < elt2){ //si le premier est inférieur au second valeur négative
res = -1 ;
}
else if(elt2 < elt1){ //sinon valeur positive
res = 1 ;
}
return res ;
}
//Interversion de deux cases d'indice i1 et i2 d'un tableau tab
function invertTr(tab, i1, i2){
//pour intervertir 2 cases, il faut une case intermédiaire
let tmp = tab[i1];
tab[i1]=tab[i2];
tab[i2]=tmp;
return tab;
}
function alphaSort(table){
//Pour un tri alphabétique, il faut une comparaison de la case des noms
return triMin(table, compareAlpha, invertTr);
}
function meanSort(table){
//Pour un tri par moyenne, il faut une comparaison de la case des moyennes
return triAlan(table, compareMean, invertTr);
}
/*Un tri par minimum :
* parcourt la partie non triée d'un tableau pour trouver la plus petite valeur
* la met dans la première case non triée
* recommence ce processus à partir de la case suivante
* Jusqu'à ce que le tableau soit trié*/
function triMin(table, comparaison, inversion){
var min,tmpElt;
for (var j=0;j<table.length;j++){
//par défaut la case minimale est la première case non triée
min = j;
for (var i=j+1;i<table.length;i++){
if(comparaison(table[min], table[i])>0){
//si la case i est plus petite que la cas min
//elle devient la case minimale
min=i;
}
}
console.log("Le plus petit élément à partir de l'index "+j+" est "+min+". On les inverse");
table = inversion(table, j, min);
}
return table;
}
alphaSort
/*Le tri d'Alan est un tri par bulle amélioré
*Le tri par bulle fait remonter la plus grande valeur à droite du tableau
* en comparant une case avec la suivante
* et en les intervertissant si la plus grande des deux n'est pas à droite
* à la fin du parcours, la plus grande valeur est à droite
*puis recommence avec la partie non-triée du tableau
*La version d'Alan garde triée la partie gauche du tableau en faisant redescendre
*jusqu'à sa position toute valeur intervertie*/
function triAlan(table, comparaison, inversion){
for (var i=0;i<table.length - 1;i++){
if(comparaison(table[i], table[i+1]) > 0){
//les cases i et i+1 ne sont pas dans le bon ordre
//on les intervertit.
table = inversion(table, i, i+1) ;
let j = i ;
//on vérifie que la case j+1 (devenue j) n'est pas
//plus grande que les cases précédentes
while(j > 0 && comparaison(table[j-1], table[j]) > 0){
//tant qu'elle est plus grande on l'échange avec
//avec la case précédente
table = inversion(table, j, j-1) ;
j--;
}
}
}
return table ;
}