Brendan Abolivier 9 anos atrás
pai
commit
431548d394

+ 21
- 0
web/multi/README Ver arquivo

@@ -0,0 +1,21 @@
1
+Installation de nodejs :
2
+https://github.com/joyent/node/wiki/Installing-Node.js-via-package-manager
3
+
4
+Installation du servveur temps réel :
5
+	+ Créer un répertoire
6
+	+ Copier les fichiers server/server.js et server/package.json
7
+	+ Se placer dans le répertoire
8
+	+ Taper la commande : # npm install
9
+	+ C'est tout !!
10
+
11
+Lancer le serveur temps réel :
12
+	+ Se placer dans le répertoire du serveur
13
+	+ Taper la commande : # node server.js
14
+
15
+
16
+Côté client :
17
+	+ Copier le contenu du répertoire "client" à la racine de votre serveur web ou dans un répertoire
18
+	+ Le client sera accessible avec l'URL http://127.0.0.1 ou http://127.0.0.1/repertoire si vous avez opté pour la seconde solution
19
+	+ Lancer deux clients pour comprendre le fonctionnement du serveur temps réel (et donc des websockets mise en oeuvre avec socket.io)
20
+
21
+La base de la communication est mise en oeuvre dans l'exemple.

+ 30
- 0
web/multi/client/index.html Ver arquivo

@@ -0,0 +1,30 @@
1
+<!DOCTYPE html>
2
+<html>
3
+    <head>
4
+        <meta charset="utf-8" />
5
+        <title>Burger</title>
6
+        <style type="text/css">
7
+          .good-answer {
8
+            color:green;
9
+          }
10
+          .wrong-answer {
11
+            color:red;
12
+          }
13
+        </style>
14
+    </head>
15
+
16
+    <body>
17
+        <h1>Burger temps réel !</h1>
18
+
19
+        <div id="game">
20
+        </div>
21
+
22
+        <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
23
+        <script src="http://localhost:8000/socket.io/socket.io.js"></script>
24
+        <script src="js/game.js"></script>
25
+        <script>
26
+            init();
27
+
28
+        </script>
29
+    </body>
30
+</html>

+ 231
- 0
web/multi/client/js/game.js Ver arquivo

@@ -0,0 +1,231 @@
1
+/**************************************************
2
+** GAME VARIABLES
3
+**************************************************/
4
+var socket;			// Socket
5
+var gameInfos;
6
+
7
+/**************************************************
8
+** GAME INITIALISATION
9
+**************************************************/
10
+function init() {
11
+
12
+    // Connexion à socket.io
13
+    socket = io.connect('http://localhost:8000');
14
+
15
+    // Gestion des evenements
16
+    setEventHandlers();
17
+
18
+    // On demande le pseudo a l'utilisateur, on l'envoie au serveur et on l'affiche dans le titre
19
+    $("#game").html("<input type=\"text\" id=\"pseudo\" /><input type=\"submit\" id=\"start\" value=\"Valider\" />");
20
+    $("#start").on("click", function() {
21
+      socket.emit('nouveau', $("#pseudo").val());
22
+      document.title = $("#pseudo").val() + ' - ' + document.title;
23
+      $("#game").html("Recherche d'un adversare...");
24
+    });
25
+};
26
+
27
+/**************************************************
28
+** GAME EVENT HANDLERS
29
+**************************************************/
30
+var setEventHandlers = function() {
31
+	socket.on("message", onMessage);
32
+	socket.on("autres", onAutres);
33
+  socket.on("game", onGame);
34
+  socket.on("questions", play);
35
+};
36
+
37
+function onGame(game) {
38
+  gameInfos = game;
39
+  $("#game").html("Adversaire trouvé : "+game[0]+"<br />Début de la partie dans 5s.");
40
+  window.setTimeout(function() {
41
+    socket.emit('start', gameInfos[1])
42
+  }, 5000);
43
+}
44
+
45
+function onMessage(message) {
46
+    alert(message);
47
+};
48
+
49
+function onAutres(pseudo) {
50
+    alert("Voici un nouveau joueur : " + pseudo);
51
+};
52
+
53
+/**************************************************
54
+** GAME ENGINE (SORT OF)
55
+**************************************************/
56
+
57
+// IDs
58
+var id_cat = 0, id_theme = 0, id_quest = 0;
59
+// Shortcuts
60
+var json, category, theme;
61
+// Timer
62
+var timing = 5, secRestantes, timer;
63
+var baseWidth;
64
+
65
+var score = 0;
66
+var reponseUser = -1, bonneReponse;
67
+
68
+function apiReq() {
69
+  $.ajax({
70
+    async: false,
71
+    url: "../../api/",
72
+    dataType: 'json',
73
+    success: function(data) {
74
+      json = data;
75
+    }
76
+  });
77
+}
78
+
79
+function loadCat(id) {
80
+  if(id === 0) category = json.cat1;
81
+  if(id === 1) category = json.cat2;
82
+  console.log(category);
83
+  $("#game").html("<p id=\"category\">Catégorie : "+category.nom_cat+"</p>");
84
+  $("#game").append("<div id=\"theme\"></div>");
85
+  $("#game").append("<div id=\"timer\" style=\"width:100%;height:20px;background:green\"></div>");
86
+  $("#game").append("<div id=\"score\"></div>");
87
+  loadTheme(id_theme);
88
+}
89
+
90
+function loadTheme(id) {
91
+  theme = category.themes[id];
92
+  $("#theme").html("<p id=\"question\"></p>");
93
+  $("#theme").append("<ul id=\"answers\"><li id=\"rep1\">"+theme.reponse1+"</li>"
94
+    +"<li id=\"rep2\">"+theme.reponse2+"</li><li id=\"both\">Les deux</li></ul>");
95
+  quest(id_quest);
96
+}
97
+
98
+function quest(id) {
99
+  $("#question").html(theme.questions[id].intitule);
100
+  startTimer();
101
+  bonneReponse = parseInt(theme.questions[id].bonneReponse);
102
+  console.info('Question ' + (id_quest + 1) + '/' + theme.questions.length + ' : '
103
+    +theme.questions[id].intitule);
104
+  $("#rep1").off('click');
105
+  $("#rep1").on("click", function() { reponseUser = 1; checkAnswer(); });
106
+  $("#rep2").off('click');
107
+  $("#rep2").on("click", function() { reponseUser = 2; checkAnswer(); });
108
+  $("#both").off('click');
109
+  $("#both").on("click", function() { reponseUser = 0; checkAnswer(); });
110
+}
111
+
112
+function checkAnswer() {
113
+  stopTimer();
114
+  if(reponseUser == bonneReponse) {
115
+    score += secRestantes+1;
116
+  }
117
+  $("#score").html("Score : "+score);
118
+  switch(bonneReponse) {
119
+    case 0:   $("#rep1").addClass("wrong-answer");
120
+              $("#rep2").addClass("wrong-answer");
121
+              $("#both").addClass("good-answer");
122
+              break;
123
+    case 1:   $("#rep1").addClass("good-answer");
124
+              $("#rep2").addClass("wrong-answer");
125
+              $("#both").addClass("wrong-answer");
126
+              break;
127
+    case 2:   $("#rep1").addClass("wrong-answer");
128
+              $("#rep2").addClass("good-answer");
129
+              $("#both").addClass("wrong-answer");
130
+              break;
131
+  }
132
+  window.setTimeout(nextQuestion, 2000);
133
+}
134
+
135
+function nextQuestion() {
136
+  $("#rep1").removeClass();
137
+  $("#rep2").removeClass();
138
+  $("#both").removeClass();
139
+  // Dernière question du thème en cours
140
+  if((id_quest+1) == theme.questions.length)  {
141
+    // Dernier thème de la catégorie en cours
142
+    if((id_theme+1) == category.themes.length) {
143
+      // Dernière catégorie
144
+      if((id_cat+1) == 2) {
145
+        endGame();
146
+      } else {
147
+        id_quest = 0;
148
+        id_theme = 0;
149
+        id_cat++;
150
+        loadCat(id_cat);
151
+      }
152
+    } else {
153
+      id_quest = 0;
154
+      id_theme++;
155
+      loadTheme(id_theme);
156
+    }
157
+  } else {
158
+    id_quest++;
159
+    quest(id_quest);
160
+  }
161
+}
162
+
163
+function play(questions) {
164
+  console.log(questions);
165
+  json = questions;
166
+  loadCat(id_cat);
167
+}
168
+
169
+function startTimer() {
170
+  $("#timer").css("width", "100%");
171
+  baseWidth = $("#timer").width();
172
+  $("#timer").animate({'width' : '0%'}, timing*1000);
173
+  timer = window.setTimeout(checkAnswer, timing*1000);
174
+}
175
+
176
+function stopTimer() {
177
+  window.clearTimeout(timer);
178
+  $("#timer").stop();
179
+  secRestantes = Math.round($("#timer").width()/baseWidth*timing);
180
+}
181
+
182
+function endGame() {
183
+  $("#game").html("<h2 id=\"score\">Vous avez marqué "+score+" miams</h2>"
184
+  +"<p id=\"registerScore\">Enregistrez votre score : <input type=\"text\" id=\"login\" placeholder=\"Nom ou pseudonyme\" />"
185
+  +"<input type=\"submit\" id=\"sendScore\" value=\"Valider\" /></p>");
186
+  $("#sendScore").click(function() {
187
+    addScore($("#login").val(), score);
188
+    var message = json.message;
189
+    $("#registerScore").fadeOut();
190
+    console.log(message);
191
+    if(message == "score_add_success") {
192
+      $("#registerScore").addClass("success");
193
+      $("#registerScore").html("Votre score a bien été enregistré<br />"+
194
+      "<a href=\"palmares.htm\">Voir les meilleurs scores</a>");
195
+    } else {
196
+      $("#registerScore").addClass("error");
197
+      if(message === "higher_score_present") {
198
+        $("#registerScore").html("Un score supérieur ou égal existe déjà avec ce pseudonyme<br />"+
199
+        "<a href=\"palmares.htm\">Voir les meilleurs scores</a>");
200
+      } else {
201
+        $("#registerScore").html("Une erreur est survenue ("+status.message+")<br />"+
202
+        "<a href=\"palmares.htm\">Voir les meilleurs scores</a>");
203
+      }
204
+    }
205
+    $("#registerScore").fadeIn();
206
+  });
207
+}
208
+
209
+function addScore(userLogin, userScore) {
210
+  $.ajax({
211
+    async: false,
212
+    url: "../../api/?page=palmares",
213
+    type: "POST",
214
+    dataType: 'json',
215
+    data: {login: userLogin, score: userScore},
216
+    success: function(data) {
217
+      json = data;
218
+    }
219
+  });
220
+}
221
+
222
+function displayScores() {
223
+  $.get("./api/?page=palmares", function(data) {
224
+    var list = "<ol>";
225
+    for(var i = 0; i < 10; i++) {
226
+      list += "<li>"+data[i].login+" - "+data[i].score+"</li>";
227
+    }
228
+    list += "</ol>";
229
+    $("#palmares").html(list);
230
+  });
231
+}

+ 142
- 0
web/multi/server/npm-debug.log Ver arquivo

@@ -0,0 +1,142 @@
1
+0 info it worked if it ends with ok
2
+1 verbose cli [ '/usr/bin/node', '/usr/bin/npm', 'install', '-g', 'socket' ]
3
+2 info using npm@1.4.28
4
+3 info using node@v0.10.38
5
+4 verbose node symlink /usr/bin/node
6
+5 verbose cache add [ 'socket', null ]
7
+6 verbose cache add name=undefined spec="socket" args=["socket",null]
8
+7 verbose parsed url { protocol: null,
9
+7 verbose parsed url   slashes: null,
10
+7 verbose parsed url   auth: null,
11
+7 verbose parsed url   host: null,
12
+7 verbose parsed url   port: null,
13
+7 verbose parsed url   hostname: null,
14
+7 verbose parsed url   hash: null,
15
+7 verbose parsed url   search: null,
16
+7 verbose parsed url   query: null,
17
+7 verbose parsed url   pathname: 'socket',
18
+7 verbose parsed url   path: 'socket',
19
+7 verbose parsed url   href: 'socket' }
20
+8 silly lockFile 897d2105-socket socket
21
+9 verbose lock socket /home/brendan/.npm/897d2105-socket.lock
22
+10 silly lockFile 897d2105-socket socket
23
+11 silly lockFile 897d2105-socket socket
24
+12 verbose addNamed [ 'socket', '' ]
25
+13 verbose addNamed [ null, '*' ]
26
+14 silly lockFile 45707214-socket socket@
27
+15 verbose lock socket@ /home/brendan/.npm/45707214-socket.lock
28
+16 silly addNameRange { name: 'socket', range: '*', hasData: false }
29
+17 verbose request where is /socket
30
+18 verbose request registry https://registry.npmjs.org/
31
+19 verbose request id 0558e27cbe45aabf
32
+20 verbose url raw /socket
33
+21 verbose url resolving [ 'https://registry.npmjs.org/', './socket' ]
34
+22 verbose url resolved https://registry.npmjs.org/socket
35
+23 verbose request where is https://registry.npmjs.org/socket
36
+24 info trying registry request attempt 1 at 13:27:20
37
+25 http GET https://registry.npmjs.org/socket
38
+26 http 200 https://registry.npmjs.org/socket
39
+27 silly registry.get cb [ 200,
40
+27 silly registry.get   { server: 'CouchDB/1.5.0 (Erlang OTP/R16B03)',
41
+27 silly registry.get     etag: '"368QAD6FWDSRRSF0K2VF00IA6"',
42
+27 silly registry.get     'content-type': 'application/json',
43
+27 silly registry.get     'cache-control': 'max-age=60',
44
+27 silly registry.get     'content-length': '1522',
45
+27 silly registry.get     'accept-ranges': 'bytes',
46
+27 silly registry.get     date: 'Tue, 02 Jun 2015 11:27:21 GMT',
47
+27 silly registry.get     via: '1.1 varnish',
48
+27 silly registry.get     age: '0',
49
+27 silly registry.get     connection: 'keep-alive',
50
+27 silly registry.get     'x-served-by': 'cache-ams4143-AMS',
51
+27 silly registry.get     'x-cache': 'MISS',
52
+27 silly registry.get     'x-cache-hits': '0',
53
+27 silly registry.get     'x-timer': 'S1433244440.474316,VS0,VE665',
54
+27 silly registry.get     vary: 'Accept' } ]
55
+28 silly addNameRange number 2 { name: 'socket', range: '*', hasData: true }
56
+29 silly addNameRange versions [ 'socket', [ '0.0.1' ] ]
57
+30 verbose addNamed [ 'socket', '0.0.1' ]
58
+31 verbose addNamed [ '0.0.1', '0.0.1' ]
59
+32 silly lockFile ccbb8590-socket-0-0-1 socket@0.0.1
60
+33 verbose lock socket@0.0.1 /home/brendan/.npm/ccbb8590-socket-0-0-1.lock
61
+34 silly lockFile 22226b48-pmjs-org-socket-socket-0-0-1-tgz https://registry.npmjs.org/socket/-/socket-0.0.1.tgz
62
+35 verbose lock https://registry.npmjs.org/socket/-/socket-0.0.1.tgz /home/brendan/.npm/22226b48-pmjs-org-socket-socket-0-0-1-tgz.lock
63
+36 verbose addRemoteTarball [ 'https://registry.npmjs.org/socket/-/socket-0.0.1.tgz',
64
+36 verbose addRemoteTarball   '29ac6549f15a65b19f3444a4178d537a8c161a8b' ]
65
+37 info retry fetch attempt 1 at 13:27:21
66
+38 verbose fetch to= /tmp/npm-8234-gbXXtqf5/registry.npmjs.org/socket/-/socket-0.0.1.tgz
67
+39 http GET https://registry.npmjs.org/socket/-/socket-0.0.1.tgz
68
+40 http 200 https://registry.npmjs.org/socket/-/socket-0.0.1.tgz
69
+41 silly lockFile 22226b48-pmjs-org-socket-socket-0-0-1-tgz https://registry.npmjs.org/socket/-/socket-0.0.1.tgz
70
+42 silly lockFile 22226b48-pmjs-org-socket-socket-0-0-1-tgz https://registry.npmjs.org/socket/-/socket-0.0.1.tgz
71
+43 silly lockFile ccbb8590-socket-0-0-1 socket@0.0.1
72
+44 silly lockFile ccbb8590-socket-0-0-1 socket@0.0.1
73
+45 silly lockFile 45707214-socket socket@
74
+46 silly lockFile 45707214-socket socket@
75
+47 silly resolved [ { name: 'socket',
76
+47 silly resolved     description: 'Socket is a connect clone for simple socket based applications',
77
+47 silly resolved     version: '0.0.1',
78
+47 silly resolved     author:
79
+47 silly resolved      { name: 'Richard S Allinson',
80
+47 silly resolved        email: 'rsa@mounitainmansoftware.com' },
81
+47 silly resolved     main: 'index',
82
+47 silly resolved     engines: { node: '>= 0.6.0 < 0.7.0' },
83
+47 silly resolved     dependencies: { microtime: '=0.2.0' },
84
+47 silly resolved     repository: { type: 'git', url: 'git://github.com/capecodehq/socket.git' },
85
+47 silly resolved     license: 'MIT',
86
+47 silly resolved     _npmUser:
87
+47 silly resolved      { name: 'mountainmansoftware',
88
+47 silly resolved        email: 'npm@mountainmansoftware.com' },
89
+47 silly resolved     _id: 'socket@0.0.1',
90
+47 silly resolved     devDependencies: {},
91
+47 silly resolved     optionalDependencies: {},
92
+47 silly resolved     _engineSupported: true,
93
+47 silly resolved     _npmVersion: '1.1.0-3',
94
+47 silly resolved     _nodeVersion: 'v0.6.9',
95
+47 silly resolved     _defaultsLoaded: true,
96
+47 silly resolved     dist:
97
+47 silly resolved      { shasum: '29ac6549f15a65b19f3444a4178d537a8c161a8b',
98
+47 silly resolved        tarball: 'http://registry.npmjs.org/socket/-/socket-0.0.1.tgz' },
99
+47 silly resolved     maintainers: [ [Object] ],
100
+47 silly resolved     directories: {},
101
+47 silly resolved     _shasum: '29ac6549f15a65b19f3444a4178d537a8c161a8b',
102
+47 silly resolved     _from: 'socket@',
103
+47 silly resolved     _resolved: 'https://registry.npmjs.org/socket/-/socket-0.0.1.tgz' } ]
104
+48 info install socket@0.0.1 into /usr/lib
105
+49 info installOne socket@0.0.1
106
+50 warn engine socket@0.0.1: wanted: {"node":">= 0.6.0 < 0.7.0"} (current: {"node":"0.10.38","npm":"1.4.28"})
107
+51 verbose lib/node_modules/socket unbuild
108
+52 verbose tar unpack /home/brendan/.npm/socket/0.0.1/package.tgz
109
+53 silly lockFile 7a52a8a4-tar-usr-lib-node-modules-socket tar:///usr/lib/node_modules/socket
110
+54 verbose lock tar:///usr/lib/node_modules/socket /home/brendan/.npm/7a52a8a4-tar-usr-lib-node-modules-socket.lock
111
+55 silly lockFile 4bd988a6-dan-npm-socket-0-0-1-package-tgz tar:///home/brendan/.npm/socket/0.0.1/package.tgz
112
+56 verbose lock tar:///home/brendan/.npm/socket/0.0.1/package.tgz /home/brendan/.npm/4bd988a6-dan-npm-socket-0-0-1-package-tgz.lock
113
+57 silly gunzTarPerm modes [ '775', '664' ]
114
+58 error Error: EACCES, mkdir '/usr/lib/node_modules/socket'
115
+58 error  { [Error: EACCES, mkdir '/usr/lib/node_modules/socket']
116
+58 error   errno: 3,
117
+58 error   code: 'EACCES',
118
+58 error   path: '/usr/lib/node_modules/socket',
119
+58 error   fstream_type: 'Directory',
120
+58 error   fstream_path: '/usr/lib/node_modules/socket',
121
+58 error   fstream_class: 'DirWriter',
122
+58 error   fstream_stack:
123
+58 error    [ '/usr/lib/node_modules/npm/node_modules/fstream/lib/dir-writer.js:36:23',
124
+58 error      '/usr/lib/node_modules/npm/node_modules/mkdirp/index.js:46:53',
125
+58 error      'Object.oncomplete (fs.js:108:15)' ] }
126
+59 error Please try running this command again as root/Administrator.
127
+60 error System Linux 3.13.0-32-generic
128
+61 error command "/usr/bin/node" "/usr/bin/npm" "install" "-g" "socket"
129
+62 error cwd /home/brendan/Documents/multi/server
130
+63 error node -v v0.10.38
131
+64 error npm -v 1.4.28
132
+65 error path /usr/lib/node_modules/socket
133
+66 error fstream_path /usr/lib/node_modules/socket
134
+67 error fstream_type Directory
135
+68 error fstream_class DirWriter
136
+69 error code EACCES
137
+70 error errno 3
138
+71 error stack Error: EACCES, mkdir '/usr/lib/node_modules/socket'
139
+72 error fstream_stack /usr/lib/node_modules/npm/node_modules/fstream/lib/dir-writer.js:36:23
140
+72 error fstream_stack /usr/lib/node_modules/npm/node_modules/mkdirp/index.js:46:53
141
+72 error fstream_stack Object.oncomplete (fs.js:108:15)
142
+73 verbose exit [ 3, true ]

+ 9
- 0
web/multi/server/package.json Ver arquivo

@@ -0,0 +1,9 @@
1
+{
2
+    "name": "burger",
3
+    "version": "0.1.0",
4
+    "dependencies": {
5
+        "socket.io": "~1.3.5"
6
+    },
7
+    "author": "Yann <yann.le-ru@isen-bretagne.fr>",
8
+    "description": "Burger two players"
9
+} 

+ 79
- 0
web/multi/server/server.js Ver arquivo

@@ -0,0 +1,79 @@
1
+var io = require('socket.io'); // Chargement du module pour mettre en place les websockets
2
+var http = require('http');
3
+var json;
4
+// Variables
5
+var server; // Le socket
6
+
7
+var lobby = [];
8
+var games = [];
9
+// Gestion des evenements
10
+// Attend l'évènement "connection"
11
+// Le client génère cet évènement lorsque la connexion est établie avec le serveur (voir l'établissement de connexion côté client)
12
+// En cas de connexion appel à la fonctione onSocketConnection
13
+// Un paramètre est envoyé en paramètre de l'évènement "connection" : ce paramètre représente le client
14
+var setEventHandlers = function() {
15
+    server.sockets.on("connection", onSocketConnection);
16
+};
17
+
18
+
19
+function apiReq() {
20
+  http.get("http://localhost/burger-quizz/web/api/", function(res) {
21
+    var data = "";
22
+    res.on("data", function(returned) {
23
+      data += returned;
24
+    })
25
+    res.on("end", function() {
26
+      json = JSON.parse(data.toString());
27
+    })
28
+  });
29
+}
30
+// Fonction prenant en paramètre le client (voir ci-dessus)
31
+// Réception ou envoi d'évènement à partir de cet objet : client
32
+function onSocketConnection(client) {
33
+
34
+    // Attente de l'évènement "new"
35
+    // Dans cet exemple l'évènement "new" est envoyé avec un paramètre "pseudo"
36
+    client.on('nouveau', function(pseudo) {
37
+        // Log pour debug
38
+        console.log('Nouveau joueur : '+ pseudo +' !');
39
+        // Envoi d'un message au client
40
+        //client.emit('message', 'bien reçu !!');
41
+
42
+        if(lobby.length > 0) {
43
+          games.push({joueur1: lobby[0], joueur2: {login: pseudo, socket: client}, idGame: games.length, json: ''});
44
+          games[games.length-1].joueur1.socket.emit("game", [games[games.length-1].joueur2.login, games[games.length-1].idGame]);
45
+          games[games.length-1].joueur2.socket.emit("game", [games[games.length-1].joueur1.login, games[games.length-1].idGame]);
46
+          lobby = [];
47
+        } else {
48
+          lobby.push({login: pseudo, socket: client});
49
+        }
50
+        // Envoi d'un message aux autres clients connectés
51
+        //client.broadcast.emit('autres', pseudo);
52
+    });
53
+    client.on('error', function(err) {
54
+      console.log(err);
55
+    });
56
+    client.on('start', function(gameID) {
57
+      if(!games[gameID].json) {
58
+        console.log("slt");
59
+        apiReq();
60
+        games[gameID].json = json;
61
+      }
62
+      console.log(json);
63
+      client.emit('questions', games[gameID].json);
64
+    });
65
+
66
+};
67
+
68
+// Initialisation
69
+function init() {
70
+    // Le server temps réel écoute sur le port 8000
71
+    server = io.listen(8000);
72
+
73
+    // Gestion des évènements
74
+    setEventHandlers();
75
+
76
+};
77
+
78
+// Lance l'initialisation
79
+init();