Actions

Cours

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

De GBLL, TAL, ALAO, etc.

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 :

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

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(){
      this.scoreElt.innerHTML = this.score;
   }

   getScore(){
      return this.score;
   }

   getNom(){
      return this.nom;
   }

   addShot(type){
      if(type=="FT"){
         this.score += 1;
      }
      else if(type=="2pts"){
         this.score += 2;
      }
      else if(type=="3pts"){
         this.score += 3;
      }
      else{
         console.error("Basket type error : " + type);
      }
      this.displayScore();
   }
}

class Match{
   constructor(equipe1, equipe2){
      this.equipes = [equipe1, equipe2];
      this.leader = false;
      this.leadChanges = 0;
      var shots = ["FT", "2pts", "3pts"] ;
      var eltClasses = [".ft", ".two", ".three"] ;
      //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.
      //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;

      for(let i=0;i<shots.length;i++){
         for(let j=0; j<this.equipes.length; j++){
            this.equipes[j].returnElt().querySelector(eltClasses[i]).onclick = function(){
               self.equipes[j].addShot(shots[i]);
               self.showVainqueur();
            };
         }
      }
      this.vainqueurElt = document.getElementById("vainqueur").querySelector("p");

      document.getElementById("vainqueur").querySelector("menu").onclick = function(){self.showVainqueur();};
   }

   showVainqueur(){
      if(this.equipes[0].getScore() > this.equipes[1].getScore()){
         if((this.leader !== 0) && (this.leader !== false)){
            this.leadChanges++ ;
         }
         this.leader = 0;
         this.vainqueurElt.innerHTML = this.equipes[0].getNom()+
         "<br /><emph>" + this.leadChanges + "</emph> <i>lead changes</i>";
      }
      else if(this.equipes[0].getScore() < this.equipes[1].getScore()){
         if((this.leader !== 1) && (this.leader !== false)){
            this.leadChanges++ ;
         }
         this.leader = 1;
         this.vainqueurElt.innerHTML = this.equipes[1].getNom()+
         "<br /><emph>" + this.leadChanges + "</emph> <i>lead changes</i>";
      }
      else{
         this.vainqueurElt.innerHTML = "Match nul"+
         "<br /><emph>" + this.leadChanges + "</emph> <i>lead changes</i>";
         this.leader = -1;
      }
   }

   leadChanges(){
      return this.leadChanges;
   }
}

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