Créer vos feuilles de tournoi avec jQuery Bracket

Magazine
Marque
Linux Pratique
HS n°
Numéro
44
|
Mois de parution
février 2019
|
Domaines


Résumé

Lorsque l’on organise des tournois, il est souvent intéressant de mettre les résultats en ligne et de pouvoir les modifier aisément. Dans cet article, nous allons utiliser la librairie jQuery Bracket pour publier des feuilles de tournoi. Nous ajouterons aussi notre propre code pour rendre l’utilisation de la librairie plus facile.


Body

 

resultat

 

Figure 1

1. Préparation de la page HTML

 

menu

 

Figure 2

Nous allons utiliser la librairie jQuery Bracket dont le site se trouve à l’adresse suivante : http://www.aropupu.fi/bracket/ [1]

Préparons notre environnement de travail et récupérons les librairies dont nous avons besoin :

$ mkdir tournoi

$ mkdir php
$ cd js
$ wget https://code.jquery.com/jquery-3.3.1.min.js
$ wget https://raw.githubusercontent.com/teijo/jquery-bracket/master/dist/jquery.bracket.min.js
$ touch tournoi.js
$ cd ../css
$ wget https://raw.githubusercontent.com/teijo/jquery-bracket/master/dist/jquery.bracket.min.css
$ cd ..

Cela nous donne donc la structure suivante (commande tree) :

.

├──css

│ └──jquery.bracket.min.css

├──index.html

├──js

│ ├──jquery-3.3.1.min.js

│ ├──jquery.bracket.min.js

│ └──tournoi.js

└──php

Tout est prêt, créons maintenant notre page HTML index.html :

01: <!DOCTYPE html>

03: <head>

04: <title>jQuery Bracket</title>

05: <meta charset="UTF-8">

06: <meta name="viewport" content="width=device-width, initial-scale=1.0">

07: <script type="text/javascript" src="js/jquery-3.3.1.min.js"></script>

08: <script type="text/javascript" src="js/jquery.bracket.min.js"></script>

09: <script type="text/javascript" src="js/tournoi.js"></script>

10: <link rel="stylesheet" type="text/css" href="css/jquery.bracket.min.css" />

11: </head>

12: <body>

13: <input type="text" id="participant" placeholder="Participant">

14: <button id="ajouter">Ajouter</button><br><br>

15: <button id="vider">Vider</button>

16: <button id="aleatoire">Tirage au sort + équilibrage</button>

17: <button id="enregistrer">Enregistrer</button>

18: <div id="tournoi"></div>

19: </body>

20: </html>

Voici les explications des lignes les plus importantes :

 

Lignes

Explication

7,8,9

Déclaration des librairies que nous utiliserons dans notre projet. Tout d’abord, la librairie jquery-3.3.1.min.js est un prérequis à la seconde librairie jquery.bracket.min.js (c’est la librairie qui nous intéresse). Pour finir, notre programme principal tounois.js qui pour le moment est vide.

13

Zone de texte permettant d’ajouter un joueur à notre tournoi.

14

Bouton permettant d’ajouter le joueur à notre tournoi.

15

Bouton permettant de réinitialiser notre feuille de tournoi.

16

Bouton permettant une fois tous les joueurs saisis de faire un tirage aléatoire.

17

Bouton permettant d’enregistrer notre feuille de tournoi.

18

Zone où sera affichée notre feuille de tournoi.

2. Affichage d’une feuille de tournoi

 

01

 

Figure 3

Tout d’abord, écrivons un fichier d’exemple pour notre tournoi js/resultats.json :

01: {

02: "teams":[

03: [ "Arnaud", "Sebastien" ],

04: [ "Emmanuel", "Cedric" ],

05: [ "Patrick", null ],

06: [ "Olivier", null ]

07: ],

08: "results":[]

09: }

Nous avons 6 joueurs et pas encore de résultats.

Attaquons-nous au programme principal js/tournoi.js :

01: infos={};

03: function sauver() {} // A suivre...

04: function ajoute_participant() {} // A suivre...

05: function tirage_aleatoire() {} // A suivre...

06: function enregistrer() {} // A suivre...

07: function vider() {} // A suivre…

09: function edit_fn(container, data, doneCb) { }

10: function render_fn(container, data, score, state) {

11: switch(state) {

12: case "empty-bye":

13: return;

14: case "empty-tbd":

15: container.append("à déterminer");

16: return;

17: case "entry-no-score":

18: case "entry-default-win":

19: case "entry-complete":

20: container.append(data);

21: return;

22: }

23: }

24:

25: function affiche_tournoi()

26: {

27: fr={"1st":"1er",

28: "2nd":"2nd",

29: "3rd":"3e",

30: "4th":"4e"};

31:

32: $('#tournoi').bracket(

33: { teamWidth: 90,

34: disableToolbar:true,

35: disableTeamEdit:true,

36: centerConnectors:true,

37: init: infos,

38: save:sauver ,

39: decorator: {edit: edit_fn, render: render_fn}

40: });

41:

42: $(".bubble").each(function(index,element){

43: $(element).html(fr[$(element).html()]);

44: });

45: }

46:

47: $(document).ready(function(){

48: $.ajaxSetup({ cache: false });

49: $.getJSON( "js/resultats.json", function( data ) {

50: infos=data;

51: affiche_tournoi();

52: });

53:

54: $("#ajouter").click(ajoute_participant);

55: $("#aleatoire").click(tirage_aleatoire);

56: $("#enregistrer").click(enregistrer);

57: $("#vider").click(vider);

58: });

Nous allons utiliser une variable globale pour maintenir nos informations de tournoi (i.e. joueurs et scores), il s’agit de la variable infos initialisée à vide en ligne 1.

Des lignes 03 à 07, nous définissons un certain nombre de fonctions que nous développerons plus tard, ici le corps de la fonction est vide pour éviter des erreurs dans la console JavaScript.

2.1 Le programme principal (lignes 47 à 60)

En ligne 47, nous attendons que notre page HTML soit prête (ready) pour exécuter notre programme.
En ligne 48, nous désactivons le cache sur les requêtes AJAX. En effet, les données relatives au tournoi seront stockées dans un fichier externe qui sera modifié régulièrement : resultats.json.
Des lignes 49 à 52, nous effectuons un appel AJAX pour accéder au fichier JSON précédemment cité. La réponse est stockée dans la variable infos, puis l’affichage est déclenché avec la fonction affiche_tournoi décrite plus loin.
Enfin, des lignes 54 à 57 nous associons des fonctions aux clics sur les différents boutons.

2.2 Affichage du tournoi (lignes 25 à 45)

Malheureusement, jQuery Bracket ne connaît pas le français, il faut donc faire quelques adaptations pour lui apprendre la langue. Des lignes 27 à 30, nous créons notre tableau de conversion anglais vers français. Nous nous servirons de ce tableau en lignes 42 à 44. Dans ces lignes, nous récupérons tous les éléments de la page HTML de la classe bubble et pour chaque élément trouvé nous effectuons la traduction.

 

langue

 

Figure 4

Les lignes 32 à 40 nous permettent d’afficher notre feuille de tournoi. Voici plus de détails :

 

Lignes

Explication

33

Élargissement de la largeur d’affichage des noms (certains prénoms dépassaient de la zone).

34

Désactivation de la barre d’outils incluse dans jQuery Bracket. (nous utiliserons la nôtre).

35

Désactivation de l’édition des noms saisis. Notre outil permettra d’ajouter des noms.

36

Centrage des connexions entre les différentes cases.

37

Informations à afficher, nous utiliserons notre variable globale infos.

38

Déclaration de la fonction à appeler lorsque l’on saisit un score dans le tableau, ici sauver.

39

Utilisation des fonctions permettant de personnaliser le visuel.

2.3 Personnalisation de l’affichage (lignes 9 à 23)

En ligne 9, la fonction edit_fn permet de personnaliser l’édition d’un score. Ici, nous ne voulons pas de personnalisation, nous allons donc laisser la fonction vide.

En ligne 10, la fonction render_fn permet de personnaliser le contenu des cases :

 

Ligne

Valeur par défaut

Remplacé par :

12

BYE

vide

15

TBD

« à déterminer »

 

langue_cases

 

Figure 5

3. Menu personnalisé

Les fonctions que nous allons déclarer dans cette section remplaceront les fonctions vides du fichier tournois.js.

3.1 Vider la feuille de tournoi

Voici le code permettant de vider la feuille de tournoi :

01: function vider() {

02: infos={"teams":[], "results":[]};

03: affiche_tournoi();

04: }

La fonction est très simple, on vide la liste des joueurs ainsi que les résultats et on réaffiche.

3.2 Ajouter un joueur

Voici le code permettant de rajouter un joueur à la feuille de tournoi :

01: function liste_participants() {

02: return infos.teams.flat().filter(function (el) {

03: return el !== null;

04: });

05: }

06:

07: function ajoute_participant() {

08: if ((infos.results.length !== 0) || ($("#participant").val()==="")) return;

09: if (infos.teams.length===0) {

10: infos.teams.push([$("#participant").val(),null]);

11: } else {

12: var participants=liste_participants();

13:

14: participants.push($("#participant").val());

15: var racine_2=Math.ceil(Math.log2(participants.length));

16:

17: var complement=Math.pow(2,racine_2)-participants.length;

18: for (i=0;i<complement;i++) {

19: participants.push(null);

20: }

21:

22: var retour=[];

23: for (i=0;i<participants.length;i=i+2) {

24: retour.push([participants[i],participants[i+1]]);

25: }

26:

27: infos.teams=retour;

28: }

29: affiche_tournoi();

30: $("#participant").val("");

31: }

 

Le problème principal de la librairie jQuery Bracket est qu’elle ne fonctionne qu’avec un nombre de joueurs étant un carré : 2n. Nous allons donc créer un programme qui accepte n’importe quel nombre de joueurs.

De la ligne 01 à 05, on crée la fonction liste_participants qui a pour but de créer une liste de participants à partir de la liste jQuery Bracket, exemple :

         [["Arnaud","Sebastien"],["Emmanuel","Cedric"],["Patrick",null],["Olivier",null]]
flat =>   ["Arnaud","Sebastien", "Emmanuel","Cedric", "Patrick",null, "Olivier",null]
filter => ["Arnaud","Sebastien", "Emmanuel","Cedric", "Patrick", "Olivier" ]

Examinons maintenant la fonction ajoute_participant :

 

Lignes

Explication

08

Dans le cas où il y a déjà des scores ou qu’il n’y a pas de nom à ajouter, on ne fait rien.

09,10

Si la liste est vide, créonsuneliste composéed’un joueur : [["nom_joueur",null]].

12

Création d’une liste simple avec tous les joueurs : participants.

14

Ajout du joueur saisi dans le formulaire à la fin de la liste participants.

15

Calcul de la valeur racine_2 tel que 2racine_2 ≥ nb(participants) > 2racine_2-1.

17

Calcul du nombre de joueurs manquants pour obtenir une puissance de 2 : complement.

18,19

Complément de la liste des joueurs avec des null à l’aide du complement.

22 à 25

Création d’une liste compréhensible par jQuery Bracket.

27

Mise à jour de la variable globale infos.teams.

29

Affichage de la feuille de tournoi pour tenir compte des modifications.

30

Suppression du nom du joueur dans le formulaire pour éviter les doublons.

Voici un exemple d’exécution :

Ligne 12 => ["Arnaud","Sebastien", "Emmanuel","Cedric", "Patrick","Olivier"]

Ligne 19 => ["Arnaud","Sebastien", "Emmanuel","Cedric", "Patrick","Olivier", null,null]

Ligne 27 => [["Arnaud","Sebastien"],["Emmanuel","Cedric"],["Patrick","Olivier"],[null,null]]

3.3 Tirage au sort des matchs

Attaquons-nous maintenant au code permettant de tirer au sort les différents matchs du tournoi :

01: function shuffle(a) {

02: var j, x, i;

03: for (i = a.length - 1; i > 0; i--) {

04: j = Math.floor(Math.random() * (i + 1));

05: x = a[i];

06: a[i] = a[j];

07: a[j] = x;

08: }

09: return a;

10: }

11:

12: function tirage_aleatoire()

13: {

14: if (infos.results.length !== 0) return;

15: var participants=liste_participants();

16: participants=shuffle(participants);

17:

18: var retour=[];

19: var nb_matchs=infos.teams.length;

20:

21: for (i=0;i<nb_matchs;i++)

22: {

23: if(participants[i+nb_matchs]) {

24: retour.push([participants[i],participants[i+nb_matchs]]);

25: } else {

26: retour.push([participants[i],null]);

27: }

28: }

29: infos.teams=retour;

30: affiche_tournoi();

31: }

En ligne 1, la fonction shuffle permet de mélanger les éléments d’un tableau JavaScript. Le code provient du site StackOverflow [2].

En ligne 12, la fonction tirage_aleatoire nous permet le tirage au sort des différents matchs. Voyons plus en détail son fonctionnement :

 

Lignes

Explication

14

S’il y a déjà des scores, il est impossible de modifier les matchs.

15,16

On récupère la liste des participants que l’on mélange aléatoirement à l’aide des fonctions liste_participants et shuffle.

18

Création de la variable qui contiendra le résultat du tirage au sort : retour.

19

Récupération du nombre de matchs dans la variable : nb_matchs.

21 à 28

Création de la feuille de tournoi au format jQuery Bracket (voir exemple après le tableau).

29,30

Enregistrement du résultat dans la variable globale infos et affichage affiche_tournoi().

Voici un exemple de la création de la feuille de tournoi au format jQuery Bracket (lignes 21 à 28) :

0 1 2 3 4 5
participants=["Arnaud","Sebastien","Emmanuel","Cedric","Patrick","Olivier"]
nb_matchs=4
i=0 => retour=[["Arnaud","Patrick"]] indices 0(i) et 4(i+nb_matchs)
i=1 => retour=[["Arnaud","Patrick"],["Sebastien","Olivier"]] indices 1(i) et 5(i+nb_matchs)
i=2 => retour=[["Arnaud","Patrick"],["Sebastien","Olivier"],["Emmanuel",null]]
i=3 => retour=[["Arnaud","Patrick"],["Sebastien","Olivier"],["Emmanuel",null],["Cedric",null]]

3.4 Enregistrer la feuille de tournoi

Voici le code permettant d’enregistrer les modifications de la feuille de tournoi :

1 function sauver(data) {

2 infos=data;

3 affiche_tournoi();

4 }

5

6 function enregistrer() {

7 $.ajax({

8 async:true,

9 type:"POST",

10 url:"/php/enregistre.php",

11 data:JSON.stringify(infos),

12 datatype:"json",

13 success: function(){alert("Enregistrement réussi");},

14 error: function(){alert("Impossible d'enregistrer");}

15 });

16 }

La fonction sauver récupère les données renvoyées par jQuery Bracket et les sauvegarde dans la variable globale infos, ensuite réaffichons la feuille de tournoi.

La fonction enregistrer effectue un POST HTTP sur l’url /php/enregistre.php et passe en argument les infos au format JSON à l’aide de la fonction JSON.stringify.

4. Enregistrer la feuille de tournoi côté serveur

Dans cette section, nous allons implémenter la partie serveur. Dans notre exemple, nous utiliserons PHP.
Cette partie étant en dehors de l’utilisation de la librairie jQuery Backet, nous allons nous contenter d’un « quick & dirty » (« vite fait, mal fait »).

Voici donc le code de php/enregistre.php :

1 <?php

2 /*****************************

3 * ATTENTION A SECURISER !!! *

4 * NE PAS UTILISER EN L'ETAT *

5 *****************************/

6

7 $params = file_get_contents("php://input");

8 $json=json_decode($params, true);

9

10 $file = '../js/resultats.json';

11 file_put_contents($file, $params);

12 ?>

Le programme récupère des données HTTP POST en ligne 7, les convertit au format JSON en ligne 8 et écrit le résultat dans le fichier ../js/reusltats.json en lignes 10 et 11.

Conclusion

 

production

 

Figure 6

Et voilà ! Nous avons créé tout le nécessaire pour pouvoir aisément réaliser notre feuille de tournoi à l’aide de notre formulaire.

Pour aller plus loin, je vous invite à lire la documentation officielle de jQuery Bracket [1], vous y apprendrez par exemple comment :

- personnaliser votre affichage ;

- ajouter une consolante à votre tournoi ;

- créer un tournoi à double élimination.

Pour finir, il ne faudra pas oublier de sécuriser php/enregistrer.php. Vous pourrez par exemple rajouter un accès authentifié et supprimer l’écriture fichier au profit d’un stockage en base de données.

Références

[1] Site officiel de jQuery Bracket : http://www.aropupu.fi/bracket/

[2] Comment mélanger un tableau JavaScript sur le site StackOverflow : https://stackoverflow.com/questions/6274339/how-can-i-shuffle-an-array

 

Sur le même sujet

C++ Moderne : C++17 (partie 2)

Magazine
Marque
GNU/Linux Magazine
Numéro
233
|
Mois de parution
janvier 2020
|
Domaines
Résumé

Dans le précédent article sur C++ 17, nous avons abordé les évolutions du langage et les évolutions de la STL orientées sur les types de bases. Continuons aujourd'hui notre découverte de C++ 17 !

Utiliser un outil de génération de documentation avec Doxygen

Magazine
Marque
Linux Pratique
Numéro
117
|
Mois de parution
janvier 2020
|
Domaines
Résumé

Documenter du code est souvent une partie d'un projet qui peut paraître longue, fastidieuse, voire ennuyeuse pour certains. Néanmoins, cette étape est cruciale pour la compréhension et la maintenabilité du code. Depuis longtemps, des outils permettant de faciliter cette tâche existent. Cet article a pour but de présenter Doxygen, l'un de ces outils de génération de documentation, et les atouts qu'il peut apporter à ses utilisateurs.

Coder une interface CLI avec des selectbox, des barres de progression, de la complétion… le tout en Python

Magazine
Marque
GNU/Linux Magazine
Numéro
233
|
Mois de parution
janvier 2020
|
Domaines
Résumé

Dans cet article, nous allons découvrir le module Python cleo qui permet de créer des consoles en CLI avec des couleurs, du formatage de texte et de tableaux, des selectbox, des champs de saisie avec complétion et un module de complétion pour bash/zsh, et même fish !

Les bases de la modélisation en UML

Magazine
Marque
GNU/Linux Magazine
HS n°
Numéro
106
|
Mois de parution
janvier 2020
|
Domaines
Résumé

Ah, l'UML et ses diagrammes qui font fuir certains développeurs, persuadés qu'il s'agit de documents inutiles : j'ai une idée, je code et ça marche… Certes, pour un petit script la technique fonctionne, mais pour un projet de plus grande envergure, il n'est pas inutile de travailler la modélisation !

Informatique quantique : l’empire des chats morts-vivants

Magazine
Marque
GNU/Linux Magazine
Numéro
233
|
Mois de parution
janvier 2020
|
Domaines
Résumé

Le célèbre paradoxe du chat, à la fois vivant et mort, expérience de pensée due à Erwin Schrödinger en 1935 [1], est très certainement la « bizarrerie » la plus connue, mais aussi la plus perturbante de la mécanique quantique. Elle avait pour but d’illustrer simplement les paradoxes de la mécanique quantique, à une époque où elle n’était pas encore acceptée par les scientifiques. Pour comprendre le passage du monde quantique (la boîte n’est pas ouverte et contient un chat mort-vivant) au monde classique (la boîte est ouverte et le chat est soit mort soit vivant), nous allons présenter les problèmes de cohérence et de mesure. Partons donc à la chasse aux chats morts-vivants.

Par le même auteur

Auto-héberger son agenda avec Baïkal

Magazine
Marque
Linux Pratique
HS n°
Numéro
46
|
Mois de parution
octobre 2019
|
Domaines
Résumé
Il est très utile de pouvoir avoir un calendrier partagé accessible à tout moment sur toute sorte de clients : PC, tablette, téléphone... La solution la plus simple est souvent d’utiliser Google Calendar. Dans cet article, nous allons voir qu’il n’est pas si compliqué d’héberger soi-même un calendrier partagé à l’aide de Baïkal. Nous aborderons l’installation et la configuration de Baïkal. Pour finir, nous découvrirons la configuration des clients Thunderbird, Android et iOS.

Contrôler vos modèles Lego PoweredUp au Joypad à l'aide de votre Raspberry Pi

Magazine
Marque
Hackable
Numéro
30
|
Mois de parution
juillet 2019
|
Domaines
Résumé
Dans cet article, nous allons voir comment piloter un robot Lego PoweredUp à l’aide d’un JoyPad, grâce à un Raspberry Pi. Nous allons installer tout le nécessaire sur notre Raspberry Pi pour pouvoir piloter notre modèle Lego PoweredUp. Nous utiliserons NodeJS, donc le langage JavaScript, pour piloter notre modèle Lego.

Contrôler vos modèles Lego au joypad à l'aide de BrickPi

Magazine
Marque
Hackable
Numéro
29
|
Mois de parution
avril 2019
|
Domaines
Résumé

Dexter Industries propose des cartes d’extension pour Raspberry Pi. Dans cet article, nous allons nous intéresser à la carte BrickPi permettant de piloter les moteurs et senseurs Lego MindStorms. Nous verrons comment piloter notre robot Lego à l’aide d’un joypad. Nous développerons notre programme grâce au langage Python.

Créer vos feuilles de tournoi avec jQuery Bracket

Magazine
Marque
Linux Pratique
HS n°
Numéro
44
|
Mois de parution
février 2019
|
Domaines
Résumé

Lorsque l’on organise des tournois, il est souvent intéressant de mettre les résultats en ligne et de pouvoir les modifier aisément. Dans cet article, nous allons utiliser la librairie jQuery Bracket pour publier des feuilles de tournoi. Nous ajouterons aussi notre propre code pour rendre l’utilisation de la librairie plus facile.

Créer son environnement de développement LAMP grâce à Docker Compose

Magazine
Marque
Linux Pratique
Numéro
111
|
Mois de parution
janvier 2019
|
Domaines
Résumé
Il est souvent chose ardue de maintenir son environnement de développement. Lors d’un travail d’équipe, on doit aussi s’assurer que tous les développeurs ont le même environnement. Aujourd’hui, les conteneurs offrent une solution élégante à ces problèmes récurrents. Nous allons voir dans cet article comment mettre en œuvre un environnement de développement LAMP (Linux+Apache+MySQL+PHP) à l’aide de Docker Compose.