Actions

Cours

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 ;
}