Technologies avancées du eLearning 2/exercices/Élèves
De GBLL, TAL, ALAO, etc.
< Cours:Technologies avancées du eLearning 2Révision datée du 18 novembre 2020 à 11:28 par Loizbek (discussion | contributions) (Loizbek a déplacé la page Cours:Mathieu Loiseau/Cours/Master DDL — Parcours DILIPEM/M2 — technologies avancées du eLearning 2/exercices/Élèves vers Cours:Technologies avancées du eLearning 2/exercices/Élèves sans laisser de redirection)
Énoncé
On a un document HTML, qui contient une liste d’étudiant avec les notes obtenues lors du semestre, sous la forme suivante :
<h2>Facile</h2>
<ul id="fastoche">
<li>Maegan : 4, 8, 10, 12</li>
<li>Ajay : 15, 16, 12, 16</li>
<li>Sheri : 9, 10, 11, 15</li>
<li>Marianne : 10, 10, 10, 10</li>
</ul>
<h2>Moins facile</h2>
<ul id = "moyen">
<li>Gus : 4, 5.5, 9, 9.5, 10</li>
<li>Sammy : 3, 17</li>
<li>Belinda : 8.5, 11, 20</li>
</ul>
<h2>Très difficile</h2>
<ul id="chaud">
<li>Brayden: 12, 14 , 8.5 ; 12 ;</li>
<li>Kassidy : 13, 3.5 ;</li>
<li>Jonas : 18, 19, 16.5, 10.</li>
</ul>
On veut créer du code qui permette automatiquement de :
- Mettre en italiques le nom de l’élève ;
- Mettre en gras les notes supérieures à la moyenne ;
- Calculer et souligner la moyenne.
Informations utiles
DOMelt.children
→ renvoie un tableau avec la liste des enfants d’un élément ;mot.charAt(i)
→ (i+1)e caractère d’une chaine ;chaineOuTableau.length
→ nombre d’éléments ;Number("25")
→25
(en tant queNumber
).
Méthode 1 : une analyse descendante
On va procéder progressivement et créer un ensemble de fonctions que nous regrouperons ensuite :
function getEleves(id)
id
est une chaine de caractères contenant l'identifiant d'un élément du DOM ;- renvoie la liste des éléments contenus dans l'élément d'identifiant du DOM ;
function getPrenom(ligne)
ligne
est une chaine de caractères (telle que le contenu des<li>
ci-dessus ;- renvoie une chaine de caractères ne contenant que le prénom de l'élève ;
function getNotes(ligne)
ligne
est une chaine de caractères (telle que le contenu des<li>
ci-dessus ;- renvoie un tableau de
Number
avec toutes les notes ; - cette fonction nécessite une autre fonction :
function estNombre(caractere)
caractere
est un caractère (ou unestring
de longueur 1 ;- renvoie un booléen :
true
si le caractère peut être contenu dans l'écriture d'un nombre ;false
sinon ;
function moy(tabNotes)
tabNotes
est un tableau de notes (Number
) ;- renvoie un
Number
représentant la moyenne des nombres dans le tableau ;
function bilan(ligne)
ligne
est une chaine de caractères (telle que le contenu des<li>
ci-dessus ;- renvoie une chaine de caractère répondant aux contraintes de l'énoncé ;
function traite(id)
id
est un identifiant d'élément du DOM qui contient une liste d'élève ;- remplace le contenu de l'élément par les informations mises en forme.
Correction
Voir une correction
1 //pour savoir si un caractère est un nombre (ou peut en faire partie)
2 function estNombre(char){
3 var resultat;
4 switch(char){
5 case "0":
6 case "1":
7 case "2":
8 case "3":
9 case "4":
10 case "5":
11 case "6":
12 case "7":
13 case "8":
14 case "9":
15 case ".":
16 resultat = true;
17 break;
18 default:
19 resultat = false;
20 }
21 return resultat;
22 }
23
24 //Pour récupérer toutes les informations nécessaires
25 function traiterLigne(ligne){
26 var i=0;
27 var resultat = {"prenom":"",
28 "notes":[ ],
29 "moyenne":false};
30 while (i < ligne.length
31 && ligne.charAt(i) != " "
32 && ligne.charAt(i) != ":"){
33 resultat.prenom += ligne.charAt(i);
34 i++;
35 }
36 if(i==ligne.length){
37 resultat=false;
38 }
39 else{
40 let nbCourant = "",
41 somme = 0;
42 while(i <= ligne.length){
43 if (i < ligne.length
44 && estNombre(ligne.charAt(i))){
45 nbCourant += ligne.charAt(i); //chaine de caractère
46 }
47 else if(nbCourant!==""){
48 let laNote = Number(nbCourant);
49 somme += laNote ;
50 resultat.notes.push(laNote);
51 nbCourant = "";
52 }
53 i++;
54 }
55 if(resultat.notes.length>0){
56 resultat.moyenne = somme/resultat.notes.length
57 }
58 }
59 return resultat;
60 }
61
62 function ecrireLigne(semestre){
63 var resultat = "<i>" + semestre.prenom + "</i> : ";
64 for(let i=0; i<semestre.notes.length;i++){
65 if(i > 0){//pour les séparateurs
66 resultat = resultat +", "
67 }
68 if(semestre.notes[i]>=10){
69 resultat = resultat + "<b>" + semestre.notes[i] + "</b>";
70 }
71 else{
72 resultat = resultat + semestre.notes[i];
73 }
74 }
75 resultat = resultat + " → <u>" + semestre.moyenne + "</u>";
76 return resultat;
77 }
78
79 //prend un tableau du DOM et stocke les données extraites
80 //dans un tableau d'objets composites
81 function traiterClasse(id){
82 var elt = document.getElementById(id),
83 tableauDOM = elt.children;
84 for(let i=0;i<tableauDOM.length;i++){
85 tableauDOM[i].innerHTML = ecrireLigne(traiterLigne(tableauDOM[i].innerHTML));
86 }
87 }
88
89 //Programme principal
90 traiterClasse("fastoche");
91 traiterClasse("moyen");
92 traiterClasse("chaud");
Méthode 2 : création d'objets pour limiter le nombre de tours de boucles
Dans cette méthode, le code sera moins lisible car, en substance, les fonctions getPrenom()
, getNotes()
, moy()
seront traitées en une seule fonction.
function estNombre(caractere)
caractere
est un caractère (ou unestring
de longueur 1 ;- renvoie un booléen :
true
si le caractère peut être contenu dans l'écriture d'un nombre ;false
sinon ;
function traiterLigne(ligne)
est la fonction qui regroupe les traitements degetPrenom()
,getNotes()
etmoy()
.- cette fonction prendra en entrée une chaine de caractères contenant les informations non mises en forme ;
- elle renverra un objet composite muni de 3 attributs :
prenom
, le prénom de l'élève (string
) ;notes
, un tableau deNumber
avec les notes de l'élève ;moyenne
, unNumber
, sa moyenne ;
function ecrireLigne(semestre)
- prend un objet tel que celui renvoyé par
traiterLigne
; - et génère en conséquences une
string
mise en forme en HTML ;
- prend un objet tel que celui renvoyé par
- enfin
function traiterClasse(id)
:- prend
id
: une chaine de caractères contenant l'identifiant d'un élément du DOM ; - et modifie en conséquence cet élément du DOM.
- prend
Correction
https://codepen.io/lzbk/pen/OOBYJq
Voir une correction
1 //pour savoir si un caractère est un nombre (ou peut en faire partie)
2 function estNombre(char){
3 var resultat;
4 switch(char){
5 case "0":
6 case "1":
7 case "2":
8 case "3":
9 case "4":
10 case "5":
11 case "6":
12 case "7":
13 case "8":
14 case "9":
15 case ".":
16 resultat = true;
17 break;
18 default:
19 resultat = false;
20 }
21 return resultat;
22 }
23
24 //Pour récupérer toutes les informations nécessaires
25 function traiterLigne(ligne){
26 var i=0;
27 var resultat = {"prenom":"",
28 "notes":[ ],
29 "moyenne":false};
30 while (i < ligne.length
31 && ligne.charAt(i) != " "
32 && ligne.charAt(i) != ":"){
33 resultat.prenom += ligne.charAt(i);
34 i++;
35 }
36 if(i==ligne.length){
37 resultat=false;
38 }
39 else{
40 let nbCourant = "",
41 somme = 0;
42 while(i <= ligne.length){
43 if (i < ligne.length
44 && estNombre(ligne.charAt(i))){
45 nbCourant += ligne.charAt(i); //chaine de caractère
46 }
47 else if(nbCourant!==""){
48 let laNote = Number(nbCourant);
49 somme += laNote ;
50 resultat.notes.push(laNote);
51 nbCourant = "";
52 }
53 i++;
54 }
55 if(resultat.notes.length>0){
56 resultat.moyenne = somme/resultat.notes.length
57 }
58 }
59 return resultat;
60 }
61
62 function ecrireLigne(semestre){
63 var resultat = "<i>" + semestre.prenom + "</i> : ";
64 for(let i=0; i<semestre.notes.length;i++){
65 if(i > 0){//pour les séparateurs
66 resultat = resultat +", "
67 }
68 if(semestre.notes[i]>=10){
69 resultat = resultat + "<b>" + semestre.notes[i] + "</b>";
70 }
71 else{
72 resultat = resultat + semestre.notes[i];
73 }
74 }
75 resultat = resultat + " → <u>" + semestre.moyenne + "</u>";
76 return resultat;
77 }
78
79 //prend un tableau du DOM et stocke les données extraites
80 //dans un tableau d'objets composites
81 function traiterClasse(id){
82 var elt = document.getElementById(id),
83 tableauDOM = elt.children;
84 for(let i=0;i<tableauDOM.length;i++){
85 tableauDOM[i].innerHTML = ecrireLigne(traiterLigne(tableauDOM[i].innerHTML));
86 }
87 }
88
89 //Programme principal
90 traiterClasse("fastoche");
91 traiterClasse("moyen");
92 traiterClasse("chaud");
Méthode 3
Pour gagner en modularité et donc en maintenabilité, nous allons créer une classe d'objets Eleve
, qui encapsulera données et traitements.
NB : contrairement à ce qui a été dit en cours, il n'y a plus besoin du "use strict";
, pour utiliser les classes dans les navigateurs modernes.
La class Eleve
:
- devra faire figurer les trois attributs des objets de la méthode 2, qui seront initialisés dans son constructeur (
constructor(prenom)
) ; - elle possèdera un setter :
setNom(prenom)
: prend unestring
en entrée et la stocke dans l'attribut correspondant ;
- la méthode
ajouterNote(note)
prend un nombre et l'ajoute à la liste de notes, tout en mettant à jour la moyenne de l'élève en conséquence ; - et une liste de getters :
getNom()
: renvoie le nom de l'objetEleve
concerné ;getMoy()
: renvoie la moyenne de l'objetEleve
concerné ;getTabNotes()
: renvoie un tableau des notes de l'objetEleve
concerné ;getNbNotes()
: renvoie le nombre de notes obtenues par l'élève ;
- enfin la méthode
toString()
: transforme l'objet en chaine de caractère au format défini ci-dessus.
Pour tester la classe vous pourrez utiliser le code suivant :
//test du code
var meg = new Eleve("Megan");
console.log("¿Megan? → ",meg.getNom());
console.log("¿notes et moyenne quand il n'y en a pas encore? →",meg.getNotes(), meg.getNbNotes(), meg.getMoy());
meg.ajouterNote(12);
console.log("¿[12], 1, 12? →",meg.getNotes(), meg.getNbNotes(), meg.getMoy());
meg.ajouterNote(15.5);
console.log("¿[12,15.5], 2, 13.75? →",meg.getNotes(), meg.getNbNotes(), meg.getMoy());
meg.ajouterNote(13);
console.log("¿[12,15.5,13], 3, 13.5? →",meg.getNotes(), meg.getNbNotes(), meg.getMoy());
console.log("<li>"+meg+"</li>");
Quand cela sera fait vous pourrez modifier le constructeur pour qu'il puisse prendre une ligne ou un prénom :
constructor(prenomOuLigne, isLigne)
traite une ligne quand isLigne
est vrai, traite un prénom sinon.
Correction
Voir une correction
1 var msg = "Nooooooon, enfin… ",
2 msgs = ["C'est un peu tôt pour ",
3 "vous creuser les méninges. ",
4 "Mais on va y arriver. ",
5 "Là, il faut encore ",
6 "que je mette une correction. "
7 ];
8 for(var i=0; i<=msgs.length/2-1;i++){
9 if(i%2==0){
10 msg += msgs[i]+msgs[msgs.length-1-i];
11 }
12 else{
13 msg += msgs[msgs.length-1-i]+msgs[i];
14 }
15 }
16 if(i !== msgs.length/2){
17 msg = msg+msgs[i];
18 }
19 console.log(msg);
1 //pour savoir si un caractère est un nombre (ou peut en faire partie)
2 function estNombre(char){
3 /* cf. précédemment */
4 }
5
6 //La classe élève
7 class Eleve{
8 //prend une ligne et crée un élève en conséquence…
9 constructor(ligneOrPrenom, isLigne){
10 this.notes = [] ;
11 this.moy = false;
12 this.prenom = "";
13 if(typeof isLigne == "undefined" || isLigne === false){
14 //constructeur de base quand isLigne est indéfini ou faux
15 this.setNom(ligneOrPrenom) ;
16 }
17 else{//sinon cf. traiterLigne
18 var i=0;
19 while (i < ligneOrPrenom.length
20 && ligneOrPrenom.charAt(i) != " "
21 && ligneOrPrenom.charAt(i) != ":"){
22 this.prenom += ligneOrPrenom.charAt(i);
23 i++;
24 }
25 if(i<ligneOrPrenom.length){
26 let nbCourant = "";
27 while(i <= ligneOrPrenom.length){
28 if (i < ligneOrPrenom.length
29 && estNombre(ligneOrPrenom.charAt(i))){
30 nbCourant += ligneOrPrenom.charAt(i); //chaine de caractère
31 }
32 else if(nbCourant!==""){
33 this.ajouterNote(Number(nbCourant));
34 nbCourant="";
35 }
36 i++;
37 }
38 }
39 }
40 }
41
42 setNom(prenom){
43 this.prenom = prenom;
44 }
45
46 getNom(){
47 return this.prenom;
48 }
49
50 getNbNotes(){
51 return this.notes.length ;
52 }
53
54 getNotes(){
55 return this.notes;
56 }
57
58 getMoy(){
59 return this.moy ;
60 }
61
62 ajouterNote(note){
63 if(this.getNbNotes() > 0){
64 this.moy = (this.moy * this.getNbNotes() + note)/(this.getNbNotes()+1);
65 }
66 else{
67 this.moy = note ;
68 }
69 this.notes.push(note);
70 }
71
72 toString(){
73 var resultat = "<i>" + this.getNom() + "</i> : ";
74 for(let i=0; i<this.getNbNotes();i++){
75 if(i > 0){//pour les séparateurs
76 resultat = resultat +", "
77 }
78 if(this.notes[i]>=10){
79 resultat = resultat + "<b>" + this.notes[i] + "</b>";
80 }
81 else{
82 resultat = resultat + this.notes[i];
83 }
84 }
85 resultat = resultat + " → <u>" + this.getMoy() + "</u>";
86 return resultat;
87 }
88 }
89
90 //Le programme principal adapté
91 function traiterClasse(id){
92 var tableauDOM = document.getElementById(id).children;
93 for(let i=0;i<tableauDOM.length;i++){
94 tableauDOM[i].innerHTML = "" + new Eleve(tableauDOM[i].innerHTML, true);
95 //transcodé en string avec toString() automatiquement
96 }
97 }
98
99 //test de la classe
100 var meg = new Eleve("Megan");
101 console.log("¿Megan? → ",meg.getNom());
102 console.log("¿notes et moyenne quand il n'y en a pas encore? →",meg.getNotes(), meg.getNbNotes(), meg.getMoy());
103 meg.ajouterNote(12);
104 console.log("¿[12], 1, 12? →",meg.getNotes(), meg.getNbNotes(), meg.getMoy());
105 meg.ajouterNote(15.5);
106 console.log("¿[12,15.5], 2, 13.75? →",meg.getNotes(), meg.getNbNotes(), meg.getMoy());
107 meg.ajouterNote(13);
108 console.log("¿[12,15.5,13], 3, 13.5? →",meg.getNotes(), meg.getNbNotes(), meg.getMoy());
109 console.log("<li>"+meg+"</li>");
110
111 //Programme principal
112 traiterClasse("fastoche");
113 traiterClasse("moyen");
114 traiterClasse("chaud");