Créer vos feuilles de tournoi avec jQuery Bracket

Magazine
Marque
Linux Pratique
HS n°
Numéro
44
Mois de parution
février 2019
Spécialité(s)


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

 



Article rédigé par

Par le(s) même(s) auteur(s)

Contrôler vos modèles LEGO Powered Up au Nunchuk à l'aide de votre Arduino

Magazine
Marque
Hackable
Numéro
33
Mois de parution
avril 2020
Spécialité(s)
Résumé

Dans cet article, nous allons voir comment piloter un robot LEGO Powered Up à l’aide d’un Nintendo Nunchuk, grâce à un Arduino. Nous allons installer les librairies nécessaires pour pouvoir piloter notre modèle Powered Up et accéder aux informations du Nunchuk. Nous développerons ensuite notre programme de contrôle en C.

Auto-héberger son agenda avec Baïkal

Magazine
Marque
Linux Pratique
HS n°
Numéro
46
Mois de parution
octobre 2019
Spécialité(s)
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
Spécialité(s)
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.

Les derniers articles Premiums

Les derniers articles Premium

Sécurisez vos applications web : comment Symfony vous protège des menaces courantes

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

Les frameworks tels que Symfony ont bouleversé le développement web en apportant une structure solide et des outils performants. Malgré ces qualités, nous pouvons découvrir d’innombrables vulnérabilités. Cet article met le doigt sur les failles de sécurité les plus fréquentes qui affectent même les environnements les plus robustes. De l’injection de requêtes à distance à l’exécution de scripts malveillants, découvrez comment ces failles peuvent mettre en péril vos applications et, surtout, comment vous en prémunir.

Bash des temps modernes

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

Les scripts Shell, et Bash spécifiquement, demeurent un standard, de facto, de notre industrie. Ils forment un composant primordial de toute distribution Linux, mais c’est aussi un outil de prédilection pour implémenter de nombreuses tâches d’automatisation, en particulier dans le « Cloud », par eux-mêmes ou conjointement à des solutions telles que Ansible. Pour toutes ces raisons et bien d’autres encore, savoir les concevoir de manière robuste et idempotente est crucial.

Présentation de Kafka Connect

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

Un cluster Apache Kafka est déjà, à lui seul, une puissante infrastructure pour faire de l’event streaming… Et si nous pouvions, d’un coup de baguette magique, lui permettre de consommer des informations issues de systèmes de données plus traditionnels, tels que les bases de données ? C’est là qu’intervient Kafka Connect, un autre composant de l’écosystème du projet.

Le combo gagnant de la virtualisation : QEMU et KVM

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

C’est un fait : la virtualisation est partout ! Que ce soit pour la flexibilité des systèmes ou bien leur sécurité, l’adoption de la virtualisation augmente dans toutes les organisations depuis des années. Dans cet article, nous allons nous focaliser sur deux technologies : QEMU et KVM. En combinant les deux, il est possible de créer des environnements de virtualisation très robustes.

Les listes de lecture

9 article(s) - ajoutée le 01/07/2020
Vous désirez apprendre le langage Python, mais ne savez pas trop par où commencer ? Cette liste de lecture vous permettra de faire vos premiers pas en découvrant l'écosystème de Python et en écrivant de petits scripts.
11 article(s) - ajoutée le 01/07/2020
La base de tout programme effectuant une tâche un tant soit peu complexe est un algorithme, une méthode permettant de manipuler des données pour obtenir un résultat attendu. Dans cette liste, vous pourrez découvrir quelques spécimens d'algorithmes.
10 article(s) - ajoutée le 01/07/2020
À quoi bon se targuer de posséder des pétaoctets de données si l'on est incapable d'analyser ces dernières ? Cette liste vous aidera à "faire parler" vos données.
Voir les 125 listes de lecture

Abonnez-vous maintenant

et profitez de tous les contenus en illimité

Je découvre les offres

Déjà abonné ? Connectez-vous