Actions

Cours

Technologies avancées du eLearning 2/exercices/Score basketball

De GBLL, TAL, ALAO, etc.

< Cours:Technologies avancées du eLearning 2

Dans cet exercice, on veut créer une interface pour faire l'affichage des scores d'un match de basket.

Spécifications

Pour gérer le match de basket, on va créer 2 classes :

Basket classes.svg

Ces deux classes vont permettre d'associer un nom à chaque équipe et d'avoir une liste de boutons pour chaque équipe pour chaque point qu'elles marquent. Il peut s'agir :

  • d'un lancer franc : 1 point ;
  • d'un panier normal : 2 points ;
  • d'un panier à 3 points : 3 points.

À chaque fois qu'une équipe marque un panier, il faudra mettre à jour le score du match.

Une statistique utilisée est le nombre de « changements d'avantage » ou lead changes. Le premier panier du match ne compte pas comme un lead changes. Sinon, à chaque fois qu'une équipe qui ne menait pas au score marque et prend l'avantage, on considère qu'il y a un lead change.

Code

code de départ à modifier pour satisfaire les spécifications

correction

  • Questions subsidiaires (ne faisant pas partie de l'exercice) :
    • Comment changerait-on le nom des équipes ?
    • Comment changerait-on leur couleur ?

Fichier html

<!doctype html>
<html>
   <head>
      <meta charset="utf-8" />
      <script type="text/javascript" src="classes.js"></script>
      <link type="text/css" rel="stylesheet" href="style.css" />
      <script type="text/javascript">
function init(){
   var match = new Match(new Equipe("team1", "La première équipe"),
   new Equipe("team2", "La seconde équipe"));
}

window.onload = init;
      </script>
   </head>
   <body>
      <main><article id="team1">
            <h1>Nom Équipe 1</h1>
            <menu><table><tr><td class="ft">LF</td><td class="two">2pts</td><td class="three">3pts</td></tr></table></menu>
            <div class="score">79</div>
         </article><!--
      --><article id="team2">
            <h1>Nom Équipe 2</h1>
            <menu><table><tr><td class="ft">LF</td><td class="two">2pts</td><td class="three">3pts</td></tr></table></menu>
            <div class="score">77</div>
         </article></main>
      <article id="vainqueur"><menu>Vainqueur</menu>
         <p></p>
      </article>
   </body>
</html>

JavaScript à modifier

class Equipe{
   constructor(id, nom){
      this.elt = document.getElementById(id) ;
      this.nom = nom;
      this.elt.querySelector("h1").innerHTML = this.nom ;
      this.score = 0;
      this.scoreElt = this.elt.querySelector(".score");
      this.displayScore();
   }

   returnElt(){
      return this.elt;
   }

   displayScore(){
      //affiche le score dans l'élément contenu dans l'attribut scoreElt
   }

   getScore(){
      //renvoie le score
   }

   getNom(){
      //renvoie le nom de l'équipe
   }

   addShot(type){
      //si type est "FT" (lancé franc), ajouter 1 point au score
      //si type est "2pts", ajouter 2 points au score
      //si type est "3pts", ajouter 3 points au score
   }
}

class Match{
   constructor(equipe1, equipe2){
      //À modifier, pour que l'équipe qui est devant soit automatiquement mise à jour à chaque fois qu'on ajoute des points à une équipe.
      this.equipes = [equipe1, equipe2];
      //pour la déclaration des “listeners” la liste des paramètres de la fonction addShot et la liste des classes des éléments qui vont appeler la fonction
      var shots = ["FT", "2pts", "3pts"] ;
      var eltClasses = [".ft", ".two", ".three"] ;
      //Dans les fonctions déclenchées par les fonctions déclarées ci-dessous (qui ne sont pas des méthodes des objets en question), this se référera à l'objet DOM qui aura déclenché l'événement click.
      //pour éviter l'erreur qui se produirait, on stocke le présent objet temporairement dans une variable et on utilise celle-ci au sein de la fonction.
      let self = this;
      //création des fonctions et des listeners associés
      for(let i=0;i<shots.length;i++){
         for(let j=0; j<this.equipes.length; j++){
            //déclaration d'une fonction associée à l'événement “onclick” pour chaque bouton du tableau de chaque équipe
            this.equipes[j].returnElt().querySelector(eltClasses[i]).onclick = function(){self.equipes[j].addShot(shots[i]);};
         }
      }
      //attribut où on va stocker l'élément qui contiendra le nom de l'équipe qui mène
      this.vainqueurElt = document.getElementById("vainqueur").querySelector("p");
      //déclaration du listener pour le bouton qui doit afficher l'équipe qui mène.
      document.getElementById("vainqueur").querySelector("menu").onclick = function(){self.showVainqueur();};
   }

   showVainqueur(){
      //détecte l'équipe qui est devant et affiche le nom de son équipe dans l'élément contenu dans l'attribut vainqueurElt
   }

   leadChanges(){
      //renvoie le nombre de “lead changes” dans le match.
      //Une fois que le premier point (panier ou lancer franc) a été marqué on considère qu'un “lead change” se produit à chaque fois qu'une équipe marque et passe devant l'autre (que le score ait été équitable ou en faveur de l'autre équipe juste avant.)
   }
}

Voir une correction

 1 class Equipe{
 2    constructor(id, nom){
 3       this.elt = document.getElementById(id) ;
 4       this.nom = nom;
 5       this.elt.querySelector("h1").innerHTML = this.nom ;
 6       this.score = 0;
 7       this.scoreElt = this.elt.querySelector(".score");
 8       this.displayScore();
 9    }
10 
11    returnElt(){
12       return this.elt;
13    }
14 
15    displayScore(){
16       this.scoreElt.innerHTML = this.score;
17    }
18 
19    getScore(){
20       return this.score;
21    }
22 
23    getNom(){
24       return this.nom;
25    }
26 
27    addShot(type){
28       if(type=="FT"){
29          this.score += 1;
30       }
31       else if(type=="2pts"){
32          this.score += 2;
33       }
34       else if(type=="3pts"){
35          this.score += 3;
36       }
37       else{
38          console.error("Basket type error : " + type);
39       }
40       this.displayScore();
41    }
42 }
43 
44 class Match{
45    constructor(equipe1, equipe2){
46       this.equipes = [equipe1, equipe2];
47       this.leader = false;
48       this.leadChanges = 0;
49       var shots = ["FT", "2pts", "3pts"] ;
50       var eltClasses = [".ft", ".two", ".three"] ;
51       //Dans les fonctions déclenchées par les fonctions ci-dessous (qui ne sont pas des méthodes des objets en question), this se référera à l'objet DOM qui aura déclenché l'événement click.
52       //pour éviter l'erreur qui se produirait, on stocke le présent objet temporairement dans une variable et on utilise celle-ci au sein de la fonction.
53       let self = this;
54 
55       for(let i=0;i<shots.length;i++){
56          for(let j=0; j<this.equipes.length; j++){
57             this.equipes[j].returnElt().querySelector(eltClasses[i]).onclick = function(){
58                self.equipes[j].addShot(shots[i]);
59                self.showVainqueur();
60             };
61          }
62       }
63       this.vainqueurElt = document.getElementById("vainqueur").querySelector("p");
64 
65       document.getElementById("vainqueur").querySelector("menu").onclick = function(){self.showVainqueur();};
66    }
67 
68    showVainqueur(){
69       if(this.equipes[0].getScore() > this.equipes[1].getScore()){
70          if((this.leader !== 0) && (this.leader !== false)){
71             this.leadChanges++ ;
72          }
73          this.leader = 0;
74          this.vainqueurElt.innerHTML = this.equipes[0].getNom()+
75          "<br /><emph>" + this.leadChanges + "</emph> <i>lead changes</i>";
76       }
77       else if(this.equipes[0].getScore() < this.equipes[1].getScore()){
78          if((this.leader !== 1) && (this.leader !== false)){
79             this.leadChanges++ ;
80          }
81          this.leader = 1;
82          this.vainqueurElt.innerHTML = this.equipes[1].getNom()+
83          "<br /><emph>" + this.leadChanges + "</emph> <i>lead changes</i>";
84       }
85       else{
86          this.vainqueurElt.innerHTML = "Match nul"+
87          "<br /><emph>" + this.leadChanges + "</emph> <i>lead changes</i>";
88          this.leader = -1;
89       }
90    }
91 
92    leadChanges(){
93       return this.leadChanges;
94    }
95 }

Feuille de style

body{
   margin:0;
   padding:0;
}
main{
   position:relative;
   background-color: lightgrey;
   margin-right:auto;
   margin-left:auto;
   padding:1em;
}
[id^=team]{
   display: inline-block;
   width:50%;
   margin:0;
   padding:1em;
   position:relative;
   text-align: center;
   box-sizing: border-box;
}
#team1{
   color:blue;
}
#team2{
   color:red;
}

[id^=team] .score{
   position:absolute;
   font-size:25px;
   font-weight:bold;
   text-align:center;
   line-height: 50px;
   height:50px;
   width:100px;
   top:0;
   color:white;
}

#team1 .score{
   right:2em;
   background-color:blue;
}

#team2 .score{
   left:2em;
   background-color:red;
}

table{
   margin-left: auto;
   margin-right: auto;
}

#team1 td{
   background-color:blue;
}

#team2 td{
   background-color:red;
}

[id^=team] td{
   width:50px;
   text-align:center;
   font-weight:bold;
   color:white;
}

td:active, #vainqueur menu:active {
   filter: invert(100%);
}

menu{
   cursor:pointer;
   padding:0;
}

#vainqueur{
   font-weight: bold;
   padding:0;
   text-align:center;
}

#vainqueur menu{
   background-color:darkgrey;
   color:white;
   padding:1em;
   width:250px;
   margin-left:auto;
   margin-right:auto;
}