Advertisement
Guest User

Untitled

a guest
Aug 19th, 2018
315
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. var express = require('express');
  2. var http = require('http');
  3. var path = require('path');
  4. var fs = require('fs');
  5. var url = require('url');
  6. var querystring = require('querystring');
  7. var mysql = require('mysql');
  8. var crypto = require('crypto');
  9. var email = require('emailjs');
  10. var captcha = require('svg-captcha');
  11. var sm = require('sitemap');
  12. var Discord = require('discord.js');
  13. var request = require('request');
  14. var Twitter = require('twitter');
  15.  
  16. https://id.twitch.tv/oauth2/authorize?client_id=8rmxyj662l8pv1zm1jalygibev9ye5&redirect_uri=https://www.worldwide-combos.com/oath_auth&response_type=code&scope=viewing_activity_read
  17.  
  18. var MAINTENANCE = -1;
  19. var LOCALHOST = 0;
  20.  
  21. var twitter = new Twitter({
  22.   consumer_key: '4BZDObWTRQauKfHQXlspX8DcZ',
  23.   consumer_secret: 'JwFVtbTaYpgoReEawFCe6VTp71z8fU2W1BfBduFzN8yljJdokY',
  24.   access_token_key: '874989960465657858-ggoT09qCxaNOHITPribPXbU4gzjIQzU',
  25.   access_token_secret: 'vpXN2qPQvzwDxCXoZKlvDgxbSISyQZjHekS4yOkGzZBHA'
  26. });
  27.  
  28. /*twitter.post('statuses/update', {status: 'another try to ignore'}, function(error, tweet, response) {
  29.   if (error) {
  30.       console.log(error);
  31.   }
  32. });*/
  33.  
  34. /*// Load your image
  35. var data = require('fs').readFileSync('fichiers/images/fond_etoiles.jpg');
  36.  
  37. // Make post request on media endpoint. Pass file data as media parameter
  38. twitter.post('media/upload', {media: data}, function(error, media, response) {
  39.  
  40.   if (!error) {
  41.  
  42.     // If successful, a media object will be returned.
  43.     console.log(media);
  44.  
  45.     // Lets tweet it
  46.     var status = {
  47.       status: 'another fancy try to ignore',
  48.       media_ids: media.media_id_string // Pass the media id string
  49.     }
  50.  
  51.     twitter.post('statuses/update', status, function(error, tweet, response) {
  52.       if (error) {
  53.         console.log(error);
  54.       }
  55.     });
  56.  
  57.   }
  58. });*/
  59.  
  60. /*fs.readFile(path.join(__dirname, 'nodejs.log'), 'utf-8', function (err,texte) {
  61.     j = 0;
  62.     n = texte.length;
  63.     total = 0;
  64.     stats = new Array(24);
  65.     for (var i = 0; i < 24; i++) { stats[i] = 0; }
  66.     console.log(n);
  67.     for (var i = 0; i = -1000000; i++) {
  68.         var mdr = '';
  69.         while (j < n && texte[j] != '\n') { mdr += texte[j]; j++; }
  70.         if (j == n) { break; }
  71.         j++;
  72.         if (mdr[2] == '/' && mdr[5] == '/' && parseInt(mdr.substring(3,5)) >= 0) {
  73.             stats[parseInt(mdr.substring(11,13))]++;
  74.             total++;
  75.         }
  76.     }
  77.     console.log(stats);
  78.     console.log(total);
  79. });*/
  80.  
  81. // numéro de version
  82. var json = JSON.parse(fs.readFileSync('package.json', 'utf8'));
  83. var version = json.version;
  84. console.log('Worldwide Combos ' + version);
  85.  
  86. // sitemap
  87. var sitemap = sm.createSitemap ({
  88.     hostname: 'https://www.worldwide-combos.com',
  89.     cacheTime: 600000,
  90.     urls: [
  91.         { url: '/',  changefreq: 'always', priority: 0.9 },
  92.         { url: '/rankings',  changefreq: 'hourly',  priority: 0.7 },
  93.         { url: '/wiki/how_to_play',  changefreq: 'monthly',  priority: 0.7 },
  94.         { url: '/privacy',  changefreq: 'monthly',  priority: 0.1 },
  95.         { url: '/thankyou',  changefreq: 'monthly',  priority: 0.2 },
  96.         { url: '/wiki',  changefreq: 'monthly',  priority: 0.4 },
  97.         { url: '/wiki/api',  changefreq: 'monthly',  priority: 0.2 },
  98.         { url: '/wiki/upcoming',  changefreq: 'monthly',  priority: 0.2 },
  99.         { url: '/compete',  changefreq: 'hourly',  priority: 0.8 },
  100.         { url: '/wiki/history',  changefreq: 'daily',  priority: 0.2 },
  101.         { url: '/wiki/contribute',  changefreq: 'monthly',  priority: 0.3 },
  102.         { url: '/start',  changefreq: 'monthly',  priority: 0.7 },
  103.         { url: '/live',  changefreq: 'always',  priority: 0.7 }
  104.     ]
  105. });
  106.  
  107. // connection au serveur pour les courriels
  108. var server_noreply = email.server.connect({
  109.    user:    "noreply@worldwide-combos.com",
  110.    password:"NOreply666",
  111.    host:    "mail.gandi.net",
  112.    ssl:     true
  113. });
  114.  
  115. // formatage de la date dans la console
  116. function getDateTime() {
  117.     var date = new Date();
  118.     var hour = date.getHours();
  119.     hour = (hour < 10 ? "0" : "") + hour;
  120.     var min  = date.getMinutes();
  121.     min = (min < 10 ? "0" : "") + min;
  122.     var sec  = date.getSeconds();
  123.     sec = (sec < 10 ? "0" : "") + sec;
  124.     var year = date.getFullYear();
  125.     var month = date.getMonth() + 1;
  126.     month = (month < 10 ? "0" : "") + month;
  127.     var day  = date.getDate();
  128.     day = (day < 10 ? "0" : "") + day;
  129.     return day+'/'+month+'/'+year+' '+hour+':'+min+':'+sec+' ';
  130. }
  131.  
  132. // pour la sécurité
  133. function escapeHtml(text) {
  134.     var map = {
  135.         '&': '&amp;',
  136.         '<': '&lt;',
  137.         '>': '&gt;',
  138.         '"': '&quot;',
  139.         "'": '&#039;'
  140.     };
  141.     return text.replace(/[&<>"']/g, function(m) { return map[m]; });
  142. }
  143.  
  144. // validation des adresses électroniques
  145. function valide_email(email) {
  146.     var re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
  147.     return re.test(email);
  148. }
  149.  
  150. // validation des adresses électroniques
  151. function valide_pseudo(pseudo) {
  152.     var re = /^[a-zA-Z\-0-9\._\s@+\[\]]*$/;
  153.     return re.test(pseudo);
  154. }
  155.  
  156. // pour mélanger un tableau
  157. function melanger(array) {
  158.     var currentIndex = array.length, temporaryValue, randomIndex;
  159.     while (0 !== currentIndex) {
  160.         randomIndex = Math.floor(Math.random() * currentIndex);
  161.         currentIndex -= 1;
  162.         temporaryValue = array[currentIndex];
  163.         array[currentIndex] = array[randomIndex];
  164.         array[randomIndex] = temporaryValue;
  165.     }
  166.     return array;
  167. }
  168.  
  169. var location = 0; // mettre à 1 pour tester Discord en local
  170.  
  171. function message_discord(salon, message) {
  172.     if (LOCALHOST == 0) {
  173.         channel = guilde.channels.find('name', salon);
  174.         if (channel != undefined) { channel.send(message); }
  175.     }
  176. }
  177.  
  178. /* DEBUT DISCORD */
  179. // gestion du serveur Discord
  180. const client = new Discord.Client();
  181. const token = 'MzM0Mjc5OTY1NjU2ODc1MDA4.DEZMJw.1D_hAcyFhX_d_yHOx4C_X-Dawj4';
  182. guilde = {};
  183. cp = {ALB: 'al', ALG: 'dz', AND: 'ad', ARG: 'ar', ARM: 'am', AUS: 'au', AUT: 'at', BEL: 'be', BLR: 'by', BOL: 'bo', BOS: 'ba',
  184. BRA: 'br', BUL: 'bg', CAM: 'kh', CAN: 'ca', CHI: 'cl', CHN: 'cn', CHY: 'cy', COL: 'no', CRO: 'hr', CZE: 'cz', DEN: 'dk', ECU: 'ec',
  185. EGY: 'eg', EST: 'ee', FIN: 'fi', FRA: 'fr', GEO: 'ge', GER: 'de', GRE: 'gr', HUN: 'hu', ICE: 'is', IDN: 'id', IRE: 'ie', ISR: 'il',
  186. ITA: 'it', JAP: 'jp', KOS: 'xk', LAT: 'lv', LEB: 'lb', LIT: 'lt', LUX: 'lu', MAL: 'my', MEX: 'mx', MOL: 'md', NED: 'nl', NOR: 'no',
  187. NZ: 'nz', PAR: 'py', PER: 'pe', PHI: 'ph', POL: 'pl', POR: 'pt', RUS: 'ru', SA: 'za', SIN: 'sg', SK: 'kr', SLK: 'sk', SLV: 'si',
  188. SPA: 'es', SWE: 'se', SWI: 'ch', TAI: 'tw', TUN: 'tn', TUR: 'tk', UK: 'gb', UKR: 'ua', URU: 'uy', USA: 'us', VEN: 'vn', VIE: 'vn',
  189. WHO: 'white'};
  190. pays_complet = {ALB: 'Albania', ALG: 'Algeria', AND: 'Andorra', ARG: 'Argentina', ARM: 'Armenia', AUS: 'Australia', BAH: "Bahamas", BEL: 'Belgium',
  191. BLR: 'Belarus', BOL: 'Bolivia', BOS: 'Bosnia and Herzegovina', BRA: 'Brazil', BUL: 'Bulgaria', CAM: 'Cambodia', CAN: 'Canada',
  192. CHI: 'Chile', CHN: 'China', CHY: 'Cyprus', CMR: 'Cameroun', COL: 'Columbia', COS: 'Costa Rica', COT: 'Côte d\'Ivoire', CRO: 'Croatia', CUB: 'Cuba', CZE: 'Czech Republic', DEN: 'Denmark', ECU: 'Ecuador',
  193. EGY: 'Egypt', EST: 'Estonia', FIN: 'Finland', FRA: 'France', GEO: 'Georgia', GER: 'Germany', GRE: 'Greece', GUA: 'Guatemala', GUY: 'Guyana', HON: 'Honduras', HUN: 'Hungary',
  194. ICE: 'Iceland', IND: 'India', IDN: 'Indonesia', IRE: 'Ireland', ISR: 'Israel', ITA: 'Italia', JAP: 'Japan', KOS: 'Kosovo', LAT: 'Latvia',
  195. LEB: 'Lebanon', LIT: 'Lituania', LUX: 'Luxemburg', MAL: 'Malaysia', MEX: 'Mexico', MOL: 'Moldova', NED: 'Netherlands', NOR: 'Norway',
  196. NZ: 'New Zealand', PAR: 'Paraguay', PER: 'Peru', PHI: 'Philippines', POL: 'Poland', POR: 'Portugal', RUS: 'Russia',
  197. SA: 'South Africa', SIN: 'Singapour', SK: 'South Korea', SLK: 'Slovakia', SLV: 'Slovenia', SPA: 'Spain', SWE: 'Sweden',
  198. SWI: 'Switzerland', TAI: 'Taiwan', TUN: 'Tunisia', TUR: 'Turkey', UK: 'United Kingdom', UKR: 'Ukraine', URU: 'Uruguay',
  199. USA: 'United States', VEN: 'Venezuela', VIE: 'Vietnam', WHO: 'Unknown'};
  200.  
  201. // confirmation que tout va bien
  202. client.on('ready', () => {
  203.     console.log(getDateTime() + 'Worldwide Supervisor est opérationnel.');
  204.     guilde = client.guilds.first();
  205.     dernierperdu = Date.now();
  206.     dernierperdant = 0;
  207.     client.user.setActivity('Worldwide Combos', {type: "WATCHING"});
  208. });
  209.  
  210. // messages en provenance de Discord
  211. client.on('message', message => {
  212.     var patt1 = /the game/i;
  213.     //var patt2 = /^(>multi)/i;
  214.     if (LOCALHOST == 0 && patt1.test(message.content) && (Date.now() - dernierperdu) > 3600000 && dernierperdant != message.author) {
  215.         dernierperdu = Date.now();
  216.         dernierperdant = message.author;
  217.         message.channel.send('I just lost.');
  218.     }
  219.     else if (message.content.substring(0, 2) == '>>' && message.author.id == 202423692083462144) {
  220.         channel = guilde.channels.find('name', 'general');
  221.         if (channel != undefined) { channel.send(message.content.substring(2, message.content.length)); }
  222.     }
  223.     else if (LOCALHOST == 0 && message.content.substring(0, 9) == '!devpolls') {
  224.         var membre = guilde.member(message.author.id).roles.keyArray();    
  225.         var roles = [], ml = membre.length, ok = 0;
  226.         for (var i = 0; i < ml; i++) {
  227.             if (membre[i] == '455425290055843840') { ok = 1; }
  228.             else { roles.push(membre[i]); }
  229.         }
  230.         if (ok == 0) { roles.push('455425290055843840') }
  231.         guilde.member(message.author.id).setRoles(roles);
  232.         if (ok == 1) { message.channel.send('You do not have the role anymore.'); }
  233.         else { message.channel.send('You now have the role. Thank you for caring about Worldwide Combos!'); }
  234.     }
  235.     else if (LOCALHOST == 0 && message.content.substring(0, 5) == '!help') {
  236.         var texte = "```PROFILE CARDS: !profile <username>\nSYNCHRONIZE YOUR ACCOUNT: !sync\n";
  237.         texte += "SOCIAL MEDIA: !facebook !twitter !youtube\n";
  238.         texte += "OTHER: !history !upcoming !online !members\nHELP: !help\n";
  239.         texte += "DEV SUBSCRIPTION: !devpolls```";
  240.         message.channel.send(texte);
  241.     }
  242.     else if (LOCALHOST == 0 && message.content.substring(0, 8) == '!history') {
  243.         message.channel.send('Previous updates\' changelog: https://www.worldwide-combos.com/wiki/history');
  244.     }
  245.     else if (LOCALHOST == 0 && message.content.substring(0, 9) == '!upcoming') {
  246.         message.channel.send('List of upcoming features: https://www.worldwide-combos.com/wiki/upcoming');
  247.     }
  248.     else if (LOCALHOST == 0 && message.content.substring(0, 7) == '!online') {
  249.         connection.query('SELECT pseudo, pays FROM membres WHERE derniereconnexion > DATE_SUB(NOW(), INTERVAL 5 MINUTE) ORDER BY pseudo', function (error, liste, fields) {
  250.             if (liste.length == 0) { message.channel.send('Nobody is currently online.'); }
  251.             else {
  252.                 var l = 'Current online members: ';
  253.                 for (var i = 0; i < liste.length-1; i++) {
  254.                     l += ':flag_'+cp[liste[i]['pays']]+': ' + liste[i]['pseudo'] + ', ';
  255.                 }
  256.                 l += ':flag_'+cp[liste[liste.length-1]['pays']]+': ' + liste[liste.length-1]['pseudo'] + '.';
  257.                 message.channel.send(l);
  258.             }
  259.         });
  260.     }
  261.     else if (LOCALHOST == 0 && message.content.substring(0, 8) == '!members') {
  262.         connection.query('SELECT COUNT(*) AS nb FROM membres WHERE typemembre = 1 OR typemembre = 2', function (error, nombre1, fields) {
  263.             connection.query('SELECT COUNT(*) AS nb FROM membres WHERE derniereconnexion > DATE_SUB(NOW(), INTERVAL 1 DAY)', function (error, nombre2, fields) {
  264.                 connection.query('SELECT COUNT(*) AS nb FROM membres WHERE derniereconnexion > DATE_SUB(NOW(), INTERVAL 1 MONTH)', function (error, nombre3, fields) {
  265.  
  266.                     var texte = "```Members with a validated account: "+nombre1[0]['nb']+"\n";
  267.                     texte += "Online users in the last 24 hours: "+nombre2[0]['nb']+"\n";
  268.                     texte += "Online users in the last month: "+nombre3[0]['nb']+"\n";
  269.                     texte += "Members on this Discord server: "+guilde.memberCount+"```";
  270.                     message.channel.send(texte);
  271.                     });
  272.             });
  273.         });
  274.     }
  275.     else if (LOCALHOST == 0 && message.content.substring(0, 8) == '!profile') {
  276.         var pseudo = message.content.substring(9, message.content.length);
  277.         connection.query('SELECT * FROM membres WHERE typemembre >= 0 AND pseudo = ?', [pseudo], function (error, verif, fields) {
  278.             if (verif.length == 1) {
  279.                 var infos = verif[0];
  280.                 data = new Discord.RichEmbed();
  281.                 data.setColor('GREY');
  282.                 //data.setThumbnail('https://www.worldwide-combos.com/images/favicon.png');
  283.                 data.setTitle(':flag_'+cp[infos['pays']]+': **'+infos['pseudo']+'**');
  284.                 //data.setFooter('more on https://www.worldwide-combos.com/profile?p='+infos['pseudo']);
  285.                 //var desc = ':flag_'+cp[infos['pays']]+': **'+infos['pseudo']+'**\n';
  286.                 var desc1 = '', desc2 = '', desc = '';
  287.                 if ((infos["prenom_afficher"] == 1 && infos["prenom"] != "") || (infos["nom_afficher"] == 1 && infos["nom"] != "")) { desc1 += '**Name**\n'; }
  288.                 if (infos["prenom_afficher"] == 1 && infos["prenom"] != "") { desc1 += infos["prenom"] + ' '; }
  289.                 if (infos["nom_afficher"] == 1 && infos["nom"] != "") { desc1 += infos["nom"] + '\n\n'; }
  290.                 if (infos["sexe_afficher"] == 1) { desc1 += '**Gender**\n';  
  291.                     if (infos["sexe"] == 0) { desc1 += 'male\n\n' }
  292.                     else if (infos["sexe"] == 1) { desc1 += 'female\n\n'; }
  293.                     else if (infos["sexe"] == 2) { desc1 += 'other\n\n'; }
  294.                 }
  295.                 desc1 += '**Registration date**\n' + infos["dateinscription"].toString().substring(0, 24) + '\n\n';
  296.                 desc1 += '**Last login**\n' + infos["derniereconnexion"].toString().substring(0, 24) + '\n\n';
  297.                 if (infos["twitch"] != "") { desc1 += '**Twitch channel**\nhttps://twitch.tv/' + infos["twitch"] + '\n\n'; }
  298.                 connection.query('SELECT 1+COUNT(*) AS cl FROM membres WHERE elo1 >= ? AND typemembre < 3 AND typemembre > 0 AND elo1 != 1000', [infos["elo1"]+0.01], function (error, elo1, fields) {
  299.                     connection.query('SELECT 1+COUNT(*) AS cl FROM membres WHERE elo2 >= ? AND typemembre < 3 AND typemembre > 0 AND elo2 != 1000', [infos["elo2"]+0.01], function (error, elo2, fields) {
  300.                         connection.query('SELECT 1+COUNT(*) AS cl FROM membres WHERE sprint > 0 AND sprint <= ? AND typemembre < 3 AND typemembre > 0', [infos["sprint"]-0.00001], function (error, sp40, fields) {
  301.                             connection.query('SELECT 1+COUNT(*) AS cl FROM membres WHERE tournoi > ? AND typemembre < 3 AND typemembre > 0', [infos["tournoi"]+0.00001], function (error, tournoi, fields) {
  302.                                 connection.query('SELECT 1+COUNT(*) AS cl FROM membres WHERE survivor > ? AND typemembre < 3 AND typemembre > 0', [infos["survivor"]+0.00001], function (error, survivor, fields) {
  303.                                     desc2 += '**Tournament points**\n';
  304.                                     if (infos["tournoi"] > 0) { desc2 += infos["tournoi"] + ' (rank: '+tournoi[0]['cl']+')'; } else { desc2 += '0' }  
  305.                                     desc2 += '\n\n**Multiplayer rating**\n';  
  306.                                     if (infos["elo2"] != 1000) { desc2 += infos["elo2"] + ' (rank: '+elo2[0]['cl']+')'; } else { desc2 += '1000'; }  
  307.                                     desc2 += '\n\n**Ghostbuster rating**\n';  
  308.                                     if (infos["elo1"] != 1000) { desc2 += infos["elo1"] + ' (rank: '+elo1[0]['cl']+')'; } else { desc2 += '1000'; }  
  309.        
  310.                                     var ms = Math.floor(parseFloat(infos["sprint"])/60000);
  311.                                     var ss = parseFloat(infos["sprint"])-60000*Math.floor(parseFloat(infos["sprint"])/60000);
  312.                                     if (ss < 10000) { var stc = ms + ":0" + ss/1000; }
  313.                                     else { var stc = ms + ":" + ss/1000; }
  314.        
  315.                                     desc2 += '\n\n**Sprint time**\n';
  316.                                     if (infos["sprint"] > 0) { desc2 += stc + ' (rank: '+sp40[0]['cl']+')'; } else { desc2 += 'none'; }
  317.                                     desc2 += '\n\n**';
  318.        
  319.                                     var ms2 = Math.floor(parseFloat(infos["survivor"])/60000);
  320.                                     var ss2 = parseFloat(infos["survivor"])-60000*Math.floor(parseFloat(infos["survivor"])/60000);
  321.                                     if (ms2 > 4) {
  322.                                         if (ss2 < 10000) { var stc2 = (ms2-4) + ":0" + ss2/1000; }
  323.                                         else { var stc2 = (ms2-4) + ":" + ss2/1000; }
  324.                                     }
  325.                                     else {
  326.                                         if (ss2 < 10000) { var stc2 = ms2 + ":0" + ss2/1000; }
  327.                                         else { var stc2 = ms2 + ":" + ss2/1000; }
  328.                                     }
  329.        
  330.                                     if (infos["survivor"] > 240000) { desc2 += 'Elite Survivor time'; } else { desc2 += 'Survivor time'; }
  331.                                     desc2 += '**\n';
  332.                                     if (infos["survivor"] > 0) { desc2 += stc2 + ' (rank: '+survivor[0]['cl']+')';  } else { desc2 += 'none'; }
  333.                                     data.addField('Information', desc1, true);
  334.                                     data.addField('Performances', desc2, true);
  335.                                     var pseudoCorrige = '', lp = infos['pseudo'].length;
  336.                                     for (var i = 0; i < lp; i++) {
  337.                                         if (infos['pseudo'].substring(i, i+1) == ' ') { pseudoCorrige += '%20'; }
  338.                                         else { pseudoCorrige += infos['pseudo'].substring(i, i+1); }
  339.                                     }
  340.                                     desc += 'Profile link: https://www.worldwide-combos.com/profile?p='+pseudoCorrige+'\n\n';
  341.                                     data.setDescription(desc);
  342.                                     message.channel.send('', data);                                    
  343.                                 });
  344.                             });
  345.                         });
  346.                     });
  347.                 });
  348.             }
  349.         });
  350.        
  351.     }
  352.     else if (LOCALHOST == 0 && message.content.substring(0, 9) == '!facebook') {
  353.         message.channel.send('https://www.facebook.com/worldwidecombos/');
  354.     }
  355.     else if (LOCALHOST == 0 && message.content.substring(0, 8) == '!twitter') {
  356.         message.channel.send('https://www.twitter.com/worldwidecombos/');
  357.     }
  358.     else if (LOCALHOST == 0 && message.content.substring(0, 8) == '!youtube') {
  359.         message.channel.send('https://www.youtube.com/channel/UCxSrPJKU5gOMvinEUWWm1Ww');
  360.     }
  361.     else if (LOCALHOST == 0 && message.content.substring(0, 5) == '!sync') {
  362.         var sf1 = parseInt(message.author.id.substring(0, 9)), sf2 = parseInt(message.author.id.substring(9, 18));
  363.         var r1 = '', r2 = '';
  364.         var alph = ['h', 'C', 'N', 'G', '3', 'P', 'O', 'F', 'D', 'S', '6', 'J', 'I', 'p', 'u', 'Z', '0', 'y', 'B', 'R', 'W', 'q', 'M', 'l', 's', 'g', 'U', 'c', '4', 'x', 'j', 'V', 'd', 'a', 'T', '2', 'Q', '7', 'K', '9', 'A', 'k', 'Y', 'f', 't', 'r', 'o', 'b', '1', 'n', 'z', 'X', 'E', 'w', '8', '5', 'i', 'H', 'e', 'v', 'm', 'L'];
  365.         while (sf1 > 0) {
  366.             r1 = r1 + alph[sf1%62];
  367.             sf1 = Math.floor(sf1/62);
  368.         }
  369.         while (sf2 > 0) {
  370.             r2 = r2 + alph[sf2%62];
  371.             sf2 = Math.floor(sf2/62);
  372.         }
  373.         message.channel.send('Alright, please check your PMs.');
  374.         message.author.send('Please go to https://www.worldwide-combos.com/options and paste the following code in the "Profile settings" tab: ``' + r2 + r1 + '``.\n\n Please note that this feature is only for people who have a validated account on the website.');
  375.     }
  376.     else if (0) {
  377.         /*guilde.createChannel('live_'+message.content.substring(4,message.content.length), 'text').then(channel => {
  378.             channel.setTopic('LIVE >> :flag_fr: **noelnadal** 0 - 0 :flag_us: **Chris** <<\nJanuary Monthly Tournament Quarter Final');
  379.             channel.setParent("362898198513319936");
  380.             channel.send('Hi everyone!\nThis is the live channel for the tournament match between :flag_fr: **noelnadal** and :flag_us: **Chris**.');
  381.             message.author.send('Salut, j\'ai bien fait ce que tu voulais. :smile:');
  382.         }).catch(console.error);*/
  383.     }  
  384. });
  385.  
  386. function prive_Discord(codeDiscord, message) {
  387.     //var codeDiscord = 'KRIAP0Aqfp';
  388.     var p2 = codeDiscord.substring(0, 5);
  389.     var p1 = codeDiscord.substring(5, 10);
  390.     var c1 = 0, c2 = 0;
  391.     var m = 1;
  392.     var alph = ['h', 'C', 'N', 'G', '3', 'P', 'O', 'F', 'D', 'S', '6', 'J', 'I', 'p', 'u', 'Z', '0', 'y', 'B', 'R', 'W', 'q', 'M', 'l', 's', 'g', 'U', 'c', '4', 'x', 'j', 'V', 'd', 'a', 'T', '2', 'Q', '7', 'K', '9', 'A', 'k', 'Y', 'f', 't', 'r', 'o', 'b', '1', 'n', 'z', 'X', 'E', 'w', '8', '5', 'i', 'H', 'e', 'v', 'm', 'L'];
  393.     for (var i = 0; i < 5; i++) {
  394.         var n = alph.indexOf(p1[i]);
  395.         c1 += m*n;
  396.         m *= 62;
  397.     }
  398.     m = 1;
  399.     for (var i = 0; i < 5; i++) {
  400.         var n = alph.indexOf(p2[i]);
  401.         c2 += m*n;
  402.         m *= 62;
  403.     }
  404.     if (c1 < 0 || c2 < 0) { return; }
  405.     c1 = c1.toString();
  406.     c2 = c2.toString();
  407.     while (c1.length < 9) { c1 = '0' + c1; }
  408.     while (c2.length < 9) { c2 = '0' + c2; }
  409.     console.log(c1 + c2);
  410.     //202423692083462144
  411.     client.fetchUser(c1 + c2).then(membre => {
  412.         membre.send(message);
  413.     });
  414. }
  415.  
  416. // nouveau membre sur Discord ! :D
  417. client.on('guildMemberAdd', member => {
  418.     channel = guilde.channels.find('name', 'general');
  419.     if (LOCALHOST == 0 && channel != undefined) { channel.send('Welcome to the Worldwide Combos server, '+member+'! :smile:'); }
  420. });
  421.  
  422. // quelqu'un est parti :(
  423. client.on('guildMemberRemove', member => {
  424.     channel = guilde.channels.find('name', 'general');
  425.     if (LOCALHOST == 0 && channel != undefined) { channel.send('**'+member.user.username+'** just left us. :frowning:'); }
  426. });
  427.  
  428. // déconnexion (j'espère que ça marche)
  429. client.on('error', function(err) {
  430.     client.login(token);
  431. });
  432.  
  433. // connexion à Discord
  434. if (LOCALHOST == 0) { client.login(token); }
  435.  
  436. /* FIN DISCORD */
  437.  
  438. var queue = {};
  439. var matches = {};
  440. var quickfire = {};
  441. //var qc = {};
  442. var direct = {};
  443. var match_socket = {};
  444.  
  445. function couplage_quickplay() {
  446.     var pseudos = Object.keys(queue)
  447.     if (pseudos.length == 1) {
  448.         /* à compléter... */
  449.     }
  450.     for (var x in queue) {
  451.         queue[x].tempsAttente++;
  452.         if ((Date.now() - queue[x].derniereFois) > 10000) {
  453.             if (queue[x].adversaire != '') {
  454.                 queue[queue[x].adversaire].adversaire = '';
  455.                 queue[queue[x].adversaire].pret = 0;
  456.             }
  457.             console.log(getDateTime() + 'Le membre ' + queue[x].pseudo + ' a été éjecté.');
  458.             message_discord('quickplay', ':flag_'+cp[queue[x].pays]+': '+queue[x].pseudo + ' left the queue.');
  459.             delete queue[x];
  460.         }
  461.     }
  462.     var possibilites = ['', '', 1000000];
  463.     for (var x in queue) {
  464.         if (queue[x].adversaire != '' || queue[x].tempsAttente < 3) { continue; }
  465.         for (var y in queue) {
  466.             if (x == y) { continue; }
  467.             if (queue[y].adversaire != '' || queue[y].tempsAttente < 3) { continue; }
  468.             if (Math.abs(queue[y].classement2-queue[x].classement2) <= 10*Math.max(queue[x].tempsAttente, queue[y].tempsAttente)) {
  469.                 if (possibilites[2] > Math.abs(queue[y].classement2-queue[x].classement2)) {
  470.                     possibilites = [x, y, Math.abs(queue[y].classement2-queue[x].classement2)];
  471.                 }
  472.             }
  473.         }
  474.     }
  475.     if (possibilites[2] < 1000000) {
  476.         queue[possibilites[1]].adversaire = possibilites[0];
  477.         queue[possibilites[0]].adversaire = possibilites[1];
  478.         console.log(getDateTime()+'Possibilité de couplage entre ' + possibilites[1] + ' et ' + possibilites[0] + '.');
  479.     }
  480.     // matches
  481.     connection.query('SELECT id, joueur1, joueur2 FROM matches WHERE datelimite > NOW() AND confirmation = 1', function (error, modif, fields) {
  482.         for (var i = 0; i < modif.length; i++) {
  483.             if (modif[i]['id'] in matches) { continue; }
  484.             matches[modif[i]['id']] = {};
  485.             matches[modif[i]['id']][modif[i]['joueur1']] = {adversaire: modif[i]['joueur2'], socket: {}, pret: 0};
  486.             matches[modif[i]['id']][modif[i]['joueur2']] = {adversaire: modif[i]['joueur1'], socket: {}, pret: 0};
  487.         }
  488.     });
  489. }
  490.  
  491. setInterval(couplage_quickplay, 1000);
  492.  
  493. var app = express();
  494.  
  495. var options = {
  496.     key: fs.readFileSync(path.join(__dirname,'sslcert/worldwide-combos.key'), 'utf8'),
  497.     cert: fs.readFileSync(path.join(__dirname,'sslcert/wc.crt'), 'utf8')
  498. };
  499.  
  500. // création du serveur
  501. var httpServer = http.createServer(app);
  502.  
  503. // connexion à la base de données
  504. if (LOCALHOST == 1) {
  505.     var connection = mysql.createConnection({
  506.         host     : 'localhost',
  507.         port     : '8889',
  508.         database : 'tb_worldwide',
  509.         //database : 'worldwide-combos',
  510.         user     : 'root',
  511.         password : 'root'
  512.     });
  513. }
  514. else {
  515.     var connection = mysql.createConnection({
  516.         socketPath: '/srv/run/mysqld/mysqld.sock',
  517.         database  : 'worldwide-combos',
  518.         user      : 'root',
  519.         password  : ''
  520.     });
  521. }
  522.  
  523. function bdd_connexion() {
  524.     connection.connect(function(err) {
  525.         if (err) {
  526.             console.error(getDateTime() + 'Erreur de connection : ' + err.stack);
  527.             return;
  528.         }
  529.         console.log(getDateTime() + 'Connection à la BDD réussie, avec l\'identifiant ' + connection.threadId + '.');
  530.         /*connection.query('SELECT email FROM membres WHERE typemembre >= 1 AND typemembre <= 2 AND infos2 = 1', function (error, liste, verdict) {
  531.             for (var i = 0; i < liste.length; i++) {
  532.                 setTimeout(envoyer_courriel_tournoi, 10000*(i+1), liste[i]['email']);
  533.             }
  534.         });*/
  535.     });
  536. }
  537.  
  538. connection.on('error', function(err) {
  539.     console.log('db error', err);
  540.     if(err.code === 'PROTOCOL_CONNECTION_LOST') { // Connection to the MySQL server is usually
  541.         bdd_connexion();                         // lost due to either server restart, or a
  542.     } else {                                      // connnection idle timeout (the wait_timeout
  543.       throw err;                                  // server variable configures this)
  544.     }
  545. });
  546.  
  547. bdd_connexion();
  548.  
  549. function envoyer_courriel_tournoi(email) {
  550.     var message = {
  551.         text:   "Hi!\n\nRegistration for betadashboard.ejs Tournament 3 on Worldwide Combos is now open: https://www.worldwide-combos.com/compete. The tournament starts on *May 21st, 00:00 UTC*.\n\nThe tournament rules did not change since the last tournament, that is: 2 minutes for one round, no KO limit.\n\nIt will feature two divisions, so that you will play against players that have approximately your level. All participants will be taking part in a pool round, and play against three or four players of various levels. After the pool round, players will be seeded in their division's single elimination bracket.\n\nSince the Tournament rankings is not very accurate yet, you will be able to choose in which Division to register. Here are a few tips if you don't know where to go.\n\n* If you can consistently Sub 40 in the Sprint mode (no matter where), you should definitely join the Division 1.\n* If you can hardly (or never) Sub 50 in the Sprint mode (no matter where), you should definitely join the Division 2.\n* If you are inbetween, then it is up to you, and to your multiplayer skills. If you really can't decide, please register in both divisions, and then I will choose your division for you.\n\nOf course, you will eventually take part in one division only. As for the previous betadashboard.ejs Tournaments, you will be asked to fill up a timetable, so that the server knows when you are available for playing and schedules your matches accordingly.\n\nPlease note that, this tournament is for people of all skill levels. Especially, if you are not a pro player, this is a rare opportunity to be able to face opponents while significantly reducing the probability of playing very unbalanced games.\n\nAll other informations are on the tournament pages: https://www.worldwide-combos.com/compete. Do not hesitate to contact me if you find any bugs or don't understand something. And do not forget to bring your friends, to make things even more fun!\n\n Good lunk and have fun! Link: https://www.worldwide-combos.com/compete.\n\n Noël Nadal (Worldwide Combos admin).\n\n P.S.: you received this e-mail because you are in the official tournament's diffusion list. To unsubscribe, go here: https://www.worldwide-combos.com/options, click on \"Profile settings\", and manage your newsletter preferences there.",
  552.         from:   "Worldwide Combos <noreply@worldwide-combos.com>",
  553.         to:     email,
  554.         subject:    "Register for Worldwide Combos betadashboard.ejs Tournament 3!",
  555.     };
  556.     server_noreply.send(message, function(err, message) { console.log(getDateTime() + 'Notification courriel envoyée à ' + email + ' (tournoi).'); });
  557. }
  558.  
  559. liste_twitch = {};
  560. refresh_twitch = '';
  561.  
  562. function rafraichir_twitch() {
  563.     clearInterval(intervalle_twitch, 60000);
  564.     request.post('https://id.twitch.tv/oauth2/token?client_id=8rmxyj662l8pv1zm1jalygibev9ye5&client_secret=yugsrzsy0p8mk85dgvfsmopipwpzlx&grant_type=refresh_token&redirect_uri=https://www.worldwide-combos.com/oath_auth&refresh_token='+refresh_twitch, function (error, response, body) {
  565.         //console.log(JSON.parse(body)['refresh_token'].toString());
  566.         refresh_twitch = JSON.parse(body)['refresh_token'].toString();
  567.         intervalle_twitch = setInterval(maj_twitch, 60000);
  568.     });
  569. }
  570.  
  571. function maj_twitch() {
  572.     var options = {
  573.         url: 'https://api.twitch.tv/helix/streams?game_id=502195',
  574.         headers: {
  575.             'Client-ID': '8rmxyj662l8pv1zm1jalygibev9ye5'
  576.         }
  577.     };
  578.     request(options, function (error, response, body) {
  579.         if (body == undefined) { return; }
  580.         var texte = JSON.parse(body);
  581.         if (!('data' in texte)) { return; }
  582.         var liste = texte['data'];
  583.         //if (liste.length > 0) { console.log(liste); }
  584.         for (var i = 0; i < liste.length; i++) {
  585.             var diffusion = liste[i];
  586.             if (liste_twitch[diffusion['started_at']] == undefined) {
  587.                 liste_twitch[diffusion['started_at']] = diffusion;
  588.                 options = {
  589.                     url: 'https://api.twitch.tv/helix/users?id='+diffusion['user_id'],
  590.                     headers: {
  591.                         'Client-ID': '8rmxyj662l8pv1zm1jalygibev9ye5'
  592.                     }
  593.                 };
  594.                 request(options, function (error, response, bm) {
  595.                     var textem = JSON.parse(bm);
  596.                     var membre = textem['data'];
  597.                     var texte = "**Streamer:** " + membre[0]['login'];
  598.                     texte += "\n\n**Title:** " + diffusion['title'];
  599.                     texte += '\n\n**Link:** https://twitch.tv/' + membre[0]['login'];
  600.                     data = new Discord.RichEmbed();
  601.                     data.setColor('DARK_PURPLE');
  602.                     //data.setThumbnail('https://www.worldwide-combos.com/images/favicon.png');
  603.                     data.setTitle('New Worldwide Combos stream!');
  604.                     data.setDescription(texte);
  605.                     data.setThumbnail(membre[0]['profile_image_url']);
  606.                     data.setImage(diffusion['thumbnail_url'].substring(0, diffusion['thumbnail_url'].length - 20) + '360x240.jpg')
  607.                     channel = guilde.channels.find('name', 'streams');
  608.                     if (LOCALHOST == 0 && channel != undefined) { channel.send('', data); }
  609.                 });
  610.             }
  611.         }
  612.     });
  613. }
  614.  
  615.  
  616. {
  617. // conseils dans Dashboard et Quickplay
  618. conseils = new Array(17);
  619. conseils[0] = "This website is entirely free, and does not rely on ad revenues. Your help is welcome! <form action=\"https://www.paypal.com/cgi-bin/webscr\" method=\"post\" target=\"_top\"><input type=\"hidden\" name=\"cmd\" value=\"_s-xclick\"><input type=\"hidden\" name=\"hosted_button_id\" value=\"FFNDD5M2ZTLG8\"><input type=\"image\" src=\"https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif\" border=\"0\" name=\"submit\" alt=\"PayPal - The safer, easier way to pay online!\"><img alt=\"\" border=\"0\" src=\"https://www.paypalobjects.com/fr_FR/i/scr/pixel.gif\" width=\"1\" height=\"1\"></form>";
  620. conseils[1] = "<br><br>This website is still looking for a decent logo. Feel free to send your proposals <a href=\"mailto:noel.nadal@worldwide-combos.com\">here</a>!";
  621. conseils[2] = "<br><br>Tip: can't find any suitable opponent in Quickplay? Invite people for <a href=\"customgames\">custom games</a>!";
  622. conseils[3] = "<br><br>Tip: if you want to train for multiplayer battles without ruining your elo rating, you may find what you are looking for in the <a href=\"training#ghostbuster\">ghostbuster mode</a>.";
  623. conseils[4] = "<br><br>Tip: if you would like to see how fast you can play compared to others, the <a href=\"training#sprint\">sprint mode</a> might be what you are looking for.";
  624. conseils[5] = "<br><br>Tip: you don't appear in the <a href=\"rankings\">official rankings</a> as long as you do not have an account with a validated e-mail address.";
  625. conseils[6] = "<br><br>Tip: if you don't want to receive e-mail notifications, you may receive Discord notifications instead, by changing your settings.";
  626. conseils[7] = "<br><br>Tip: you may set a flag next to your username. Be proud to represent your country!";
  627. conseils[8] = "<br><br>Tip: you need a validated account to play custom games.";
  628. conseils[9] = "<br><br>Tip: you need a validated account to take part in tournaments.";
  629. conseils[10] = "<br><br>Tip: remember you can change your key binds, either in the <a href=\"start\">tutorial mode</a>, or in the <a href=\"options\">options page</a>.";
  630. conseils[11] = "<br><br>Tip: remember you can change your speed tunings, either in the <a href=\"start\">tutorial mode</a>, or in the <a href=\"options\">options page</a>.";
  631. conseils[12] = "<br><br>Tip: willing to give another look to your blocks? You may set new colors for them in the <a href=\"options\">options page</a>.";
  632. conseils[13] = "<br><br>How good are you compared to other players? Check the <a href=\"rankings\">official rankings</a>!";
  633. conseils[13] = "<br><br>Tip: do not forget to <a href=\"training#warmup\">warm-up</a> your fingers before playing intense battles.";
  634. conseils[14] = "<br><br>Worldwide Combos has a <a href=\"http://discord.gg/wwc\">Discord server</a>. Join and get fresh updates about the game's advancement and news!";
  635. conseils[15] = "<br><br>Did you know? More than 20000 games have been played in total on this website!";
  636. conseils[16] = "<br><br>Did you know? You can make your blocks spawn one line higher in the <a href=\"rankings\">Options page</a>.";
  637. //conseils[17] = "<br><br><span style='color: lime'>Registration for betadashboard.ejs Tournament 3 is open!<br>Division 1: <a href=\"https://www.worldwide-combos.com/tournament?id=4\">https://www.worldwide-combos.com/tournament?id=4</a><br>Division 2: <a href=\"https://www.worldwide-combos.com/tournament?id=5\">https://www.worldwide-combos.com/tournament?id=5</a></span>"
  638. // rajouter parties en direct, nombre de membres, record lignes envoyées, nombre de parties jouées
  639. } // conseils
  640.  
  641. app.use(express.static(path.join(__dirname, 'fichiers')));
  642.  
  643. app.get('/newone', function(req, res) {
  644.     if (MAINTENANCE == -1) { res.render('newone.ejs', {}); }
  645.     else { res.render('maintenance.ejs', {}); }
  646. }); // newone
  647.  
  648. app.get('/newone_solo', function(req, res) {
  649.     if (MAINTENANCE == -1) { res.render('newone_solo.ejs', {}); }
  650.     else { res.render('maintenance.ejs', {}); }
  651. }); // newone_solo
  652.  
  653. app.get('/makeroom', function(req, res) {
  654.     var params = querystring.parse(url.parse(req.url).query);
  655.         var pseudo = '';
  656.         if ('p1' in params && 'p2' in params && 'firstto' in params && 'winby' in params && 'kolimit' in params && 'length' in params ) {
  657.             connection.query('SELECT id FROM membres WHERE pseudo = ?', [escapeHtml(params['p1'].toString())], function (error, id1, fields) {
  658.                 if (id1.length == 0) { res.status(200).send('params p1 p2 firstto winby kolimit length'); return; }
  659.                 connection.query('SELECT id FROM membres WHERE pseudo = ?', [escapeHtml(params['p2'].toString())], function (error, id2, fields) {
  660.                     if (id2.length == 0) { res.status(200).send('params p1 p2 firstto winby kolimit length'); return; }
  661.                     connection.query('INSERT INTO matches(confirmation, joueur1, joueur2, datedebut, debutmanche, datelimite, nb_manches, diff_manches, limite_ko, duree) VALUES(1, ?, ?, DATE_ADD(NOW(), INTERVAL 1 DAY), DATE_ADD(NOW(), INTERVAL 1 DAY), DATE_ADD(NOW(), INTERVAL 21 DAY), ?, ?, ?, ?)', [id1[0]['id'], id2[0]['id'], params['firstto'], params['winby'], params['kolimit'], params['length']], function (error, ok, body) {
  662.                         console.log(ok.insertId); matches[ok.insertId] = {}; matches[ok.insertId][id1[0]['id']] = {pret: 0, adversaire: id2[0]['id']}; matches[ok.insertId][id2[0]['id']] = {pret: 0, adversaire: id1[0]['id']};  
  663.                         res.status(200).send('OK '+ok.insertId);
  664.                     });
  665.                 });
  666.             });
  667.         }
  668. }); // newone_solo
  669.  
  670. app.get('/oath_auth', function(req, res) {
  671.     var params = querystring.parse(url.parse(req.url).query);
  672.     var code = escapeHtml(params['code'].toString());
  673.     console.log(code);
  674.    
  675.     request.post('https://id.twitch.tv/oauth2/token?client_id=8rmxyj662l8pv1zm1jalygibev9ye5&client_secret=yugsrzsy0p8mk85dgvfsmopipwpzlx&grant_type=authorization_code&redirect_uri=https://www.worldwide-combos.com/oath_auth&code='+code, function (error, response, body) {
  676.       //console.log(JSON.parse(body)['refresh_token'].toString());
  677.       refresh_twitch = JSON.parse(body)['refresh_token'].toString();
  678.       /*var options = {
  679.           url: 'https://api.twitch.tv/helix/streams?game_id=502195',
  680.           headers: {
  681.               'Client-ID': '8rmxyj662l8pv1zm1jalygibev9ye5'
  682.           }
  683.       };
  684.       request(options, function (error, response, body) {
  685.         console.log('body:', body);
  686.       });*/
  687.       intervalle_twitch = setInterval(maj_twitch, 60000);
  688.       setInterval(rafraichir_twitch, 3600000);
  689.    
  690.     //'https://api.twitch.tv/helix/streams?first=20'
  691.     // ID 502195 Worldwide Combos
  692.     });
  693.     res.status(200).send('Bien envoyé.');
  694.    
  695. }); // le truc relou qu'il faut faire à cause de Twitch...
  696.  
  697. app.get('/play', function(req, res) {
  698.     if (MAINTENANCE == -1) { res.render('redirection_play.ejs', {}); }
  699.     else { res.render('maintenance.ejs', {}); }
  700. }); // redirection /play
  701.  
  702. app.get('/play/', function(req, res) {
  703.     if (MAINTENANCE == -1) { res.render('redirection_play.ejs', {}); }
  704.     else { res.render('maintenance.ejs', {}); }
  705. }); // redirection /play/
  706.  
  707. app.get('/dashboard/', function(req, res) {
  708.     if (MAINTENANCE == -1) { res.render('redirection_play.ejs', {}); }
  709.     else { res.render('maintenance.ejs', {}); }
  710. }); // redirection /dashboard/
  711.  
  712. app.get('/api/profile', function(req, res) {
  713.     console.log(getDateTime() + 'Appel à /api/profile.');
  714.     if (MAINTENANCE == -1) {
  715.         var params = querystring.parse(url.parse(req.url).query);
  716.         var pseudo = '';
  717.         if ('username' in params) {
  718.             pseudo = escapeHtml(params['username'].toString());
  719.             console.log(pseudo);
  720.             connection.query('SELECT * FROM membres WHERE typemembre >= 0 AND pseudo = ?', [pseudo], function (error, verif, fields) {
  721.                 if (verif.length == 1) {
  722.                     connection.query('UPDATE membres SET vues = vues + 1 WHERE pseudo = ?', [pseudo], function (error, modif, fields) {});
  723.                     var infos = {};
  724.                     //infos['id'] = verif[0]['id'];
  725.                     infos['username'] = verif[0]['pseudo'];
  726.                     infos['country'] = pays_complet[verif[0]['pays']];
  727.                     //infos['typemembre'] = verif[0]['typemembre'];
  728.                     infos['registration_date'] = verif[0]['dateinscription'].toString().substring(0, verif[0]['dateinscription'].toString().search(" GMT"));
  729.                     infos['last_login'] = verif[0]['derniereconnexion'].toString().substring(0, verif[0]['derniereconnexion'].toString().search(" GMT"));
  730.                     infos['ghostbuster'] = verif[0]['elo1'];
  731.                     infos['multiplayer'] = verif[0]['elo2'];
  732.                     infos['tournament'] = verif[0]['tournoi'];
  733.                     infos['sprint'] = verif[0]['sprint']/1000;
  734.                     infos['survivor'] = verif[0]['survivor']/1000;
  735.                     infos['apm'] = parseFloat(60*verif[0]['coeff_force']).toFixed(2);
  736.                     if (verif[0]['twitch'] == '') { infos['twitch'] = ''; }
  737.                     else { infos['twitch'] = 'https://twitch.tv/'+verif[0]['twitch']; }
  738.                     if (verif[0]['sexe_afficher'] == 1) {
  739.                         if (verif[0]['sexe'] == 0) { infos['gender'] = 'Male'; }
  740.                         if (verif[0]['sexe'] == 1) { infos['gender'] = 'Female'; }
  741.                         if (verif[0]['sexe'] == 2) { infos['gender'] = 'Other'; }
  742.                     }
  743.                     else { infos['gender'] = 'Unknown'; }
  744.                     if (verif[0]['nom_afficher'] == 1) { infos['name'] = verif[0]['nom']; } else { infos['name'] = ''; }
  745.                     if (verif[0]['prenom_afficher'] == 1) { infos['surname'] = verif[0]['prenom']; } else { infos['surname'] = ''; }
  746.                     connection.query('SELECT 1+COUNT(*) AS cl FROM membres WHERE elo1 >= ? AND typemembre < 3 AND typemembre > 0 AND elo1 != 1000', [infos["ghostbuster"]+0.01], function (error, elo1, fields) {
  747.                         connection.query('SELECT 1+COUNT(*) AS cl FROM membres WHERE elo2 >= ? AND typemembre < 3 AND typemembre > 0 AND elo2 != 1000', [infos["multiplayer"]+0.01], function (error, elo2, fields) {
  748.                             connection.query('SELECT 1+COUNT(*) AS cl FROM membres WHERE sprint > 0 AND sprint <= ? AND typemembre < 3 AND typemembre > 0', [infos["sprint"]*1000-0.00001], function (error, sp40, fields) {
  749.                                 connection.query('SELECT 1+COUNT(*) AS cl FROM membres WHERE tournoi > ? AND typemembre < 3 AND typemembre > 0', [infos["tournament"]+0.00001], function (error, tournoi, fields) {
  750.                                     connection.query('SELECT 1+COUNT(*) AS cl FROM membres WHERE survivor > ? AND typemembre < 3 AND typemembre > 0', [infos["survivor"]*1000+0.00001], function (error, survivor, fields) {
  751.                                         if (infos['ghostbuster'] != 1000) { infos['ghostbuster_rank'] = elo1[0]['cl']; } else { infos['ghostbuster_rank'] = -1; }
  752.                                         if (infos['multiplayer'] != 1000) { infos['multiplayer_rank'] = elo2[0]['cl']; } else { infos['multiplayer_rank'] = -1; }
  753.                                         if (infos['tournament'] > 0) { infos['tournament_rank'] = tournoi[0]['cl']; } else { infos['tournament_rank'] = -1; }
  754.                                         if (infos['sprint'] > 0) { infos['sprint_rank'] = sp40[0]['cl']; } else { infos['sprint_rank'] = -1; }
  755.                                         if (infos['survivor'] > 0) { infos['survivor_rank'] = survivor[0]['cl']; } else { infos['survivor_rank'] = -1; }
  756.                                         res.json({error: "", profile: infos});
  757.                                     });
  758.                                 });
  759.                             });
  760.                         });
  761.                     });
  762.                 }
  763.                 else { res.json({error: "No player has this username."}); }
  764.             });
  765.         }
  766.         else { res.json({error: "No username given as an argument."}); }
  767.     }
  768.     else { res.json({error: "Worldwide Combos is currently under maintenance."}); }
  769. }); // api/profile
  770.  
  771. app.get('/api/online', function(req, res) {
  772.     console.log(getDateTime() + 'Appel à /api/online.');
  773.     if (MAINTENANCE == -1) {
  774.         connection.query('SELECT pseudo, pays FROM membres WHERE derniereconnexion > DATE_SUB(NOW(), INTERVAL 5 MINUTE) ORDER BY pseudo', function (error, liste, fields) {
  775.             var infos = [];
  776.             for (var i = 0; i < liste.length; i++) {
  777.                 var nv = {};
  778.                 nv['username'] = liste[i]['pseudo'];
  779.                 nv['country'] = pays_complet[liste[i]['pays']];
  780.                 infos.push(nv);
  781.             }
  782.             res.json({error: "", online_users_count: liste.length, online_users: infos});
  783.         });
  784.     }
  785.     else { res.json({error: "Worldwide Combos is currently under maintenance."}); }
  786. }); // api/online
  787.  
  788. app.get('/custom', function(req, res) {
  789.     console.log(getDateTime() + 'Page /custom chargée.');
  790.     if (MAINTENANCE == -1) {
  791.         var params = querystring.parse(url.parse(req.url).query);
  792.         if ('id' in params) {
  793.             var id_match = escapeHtml(params['id'].toString());
  794.             res.render('custom.ejs', {LOCALHOST: LOCALHOST, version: version, id_match: id_match});
  795.         }
  796.         else { res.render('betadashboard.ejs', {LOCALHOST: LOCALHOST, version: version, color: '', message: ''}); }
  797.     }
  798.     else { res.render('maintenance.ejs', {}); }
  799. }); // custom
  800.  
  801. app.get('/quickfire', function(req, res) {
  802.     console.log(getDateTime() + 'Page /quickfire chargée.');
  803.     if (MAINTENANCE == -1) {
  804.         var params = querystring.parse(url.parse(req.url).query);
  805.         if ('id' in params) {
  806.             var id_tournoi = escapeHtml(params['id'].toString());
  807.             res.render('quickfire.ejs', {LOCALHOST: LOCALHOST, version: version, id_tournoi: id_tournoi});
  808.         }
  809.         else { res.render('betadashboard.ejs', {LOCALHOST: LOCALHOST, version: version, color: '', message: ''}); }
  810.     }
  811.     else { res.render('maintenance.ejs', {}); }
  812. }); // custom
  813.  
  814. app.get('/validate', function(req, res) {
  815.     console.log(getDateTime() + 'Page /validate chargée.');
  816.     if (MAINTENANCE == -1) {
  817.         var params = querystring.parse(url.parse(req.url).query);
  818.         var message = 0, color = 'red';
  819.         if ('id' in params && 'token' in params) {
  820.             connection.query('UPDATE membres SET typemembre = 1 WHERE id = ? AND mdp = ? AND typemembre = 0', [escapeHtml(params['id']), escapeHtml(params['token'])], function (error, valider, fields) {
  821.                 if (valider.changedRows == 1) {
  822.                     console.log(getDateTime() + 'Le compte avec l\'identifiant ' + escapeHtml(params['id']) + ' a été validé. :-)');
  823.                     message = 'Your account has successfully been validated!';
  824.                     color = 'lime';
  825.                 }
  826.                 res.render('betadashboard.ejs', {LOCALHOST: LOCALHOST, message: message, color: color, version: version});
  827.             });
  828.         }
  829.         else { res.render('betadashboard.ejs', {LOCALHOST: LOCALHOST, message: message, color: color, version: version}); }
  830.     }
  831.     else { res.render('maintenance.ejs', {}); }
  832. }); // validate
  833.  
  834. app.get('/invite', function(req, res) {
  835.     console.log(getDateTime() + 'Page /invite chargée.');
  836.     if (MAINTENANCE == -1) {
  837.         var params = querystring.parse(url.parse(req.url).query);
  838.         var pseudoinvite = '#';
  839.         if ('pseudo' in params) { pseudoinvite = escapeHtml(params['pseudo']); }
  840.         res.render('invite.ejs', {LOCALHOST: LOCALHOST, pseudoinvite: pseudoinvite, version: version});
  841.     }
  842.     else { res.render('maintenance.ejs', {}); }
  843. }); // invite
  844.  
  845. app.get('/accept', function(req, res) {
  846.     console.log(getDateTime() + 'Page /accept chargée.');
  847.     if (MAINTENANCE == -1) {
  848.         var params = querystring.parse(url.parse(req.url).query);
  849.         var pseudoinvite = '#';
  850.         if ('pseudo' in params) { pseudoinvite = escapeHtml(params['pseudo']); }
  851.         console.log(pseudoinvite);
  852.         connection.query('SELECT pays FROM membres WHERE pseudo = ? AND (typemembre = 1 OR typemembre = 2)', [pseudoinvite], function(error, verdict, fields) {
  853.             if (verdict.length == 0) { res.render('accept.ejs', {LOCALHOST: LOCALHOST, pseudoinvite: '#', pays: 'WHO', version: version}); }
  854.             else { res.render('accept.ejs', {LOCALHOST: LOCALHOST, pseudoinvite: pseudoinvite, version: version, pays: verdict[0]['pays']}); }
  855.         });
  856.     }
  857.     else { res.render('maintenance.ejs', {}); }
  858. }); // accept
  859.  
  860. app.get('/refuse', function(req, res) {
  861.     console.log(getDateTime() + 'Page /refuse chargée.');
  862.     if (MAINTENANCE == -1) {
  863.         var params = querystring.parse(url.parse(req.url).query);
  864.         var pseudoinvite = '#';
  865.         if ('pseudo' in params) { pseudoinvite = escapeHtml(params['pseudo']); }
  866.         //console.log(pseudoinvite);
  867.         connection.query('SELECT pays FROM membres WHERE pseudo = ? AND (typemembre = 1 OR typemembre = 2)', [pseudoinvite], function(error, verdict, fields) {
  868.             //console.log(verdict.length);
  869.             if (verdict.length == 0) { res.render('refuse.ejs', {LOCALHOST: LOCALHOST, pseudoinvite: '#', pays: 'WHO', version: version}); }
  870.             else { res.render('refuse.ejs', {LOCALHOST: LOCALHOST, pseudoinvite: pseudoinvite, version: version, pays: verdict[0]['pays']}); }
  871.         });
  872.     }
  873.     else { res.render('maintenance.ejs', {}); }
  874. }); // refuse
  875.  
  876. app.get('/postpone', function(req, res) {
  877.     console.log(getDateTime() + 'Page /postpone chargée.');
  878.     if (MAINTENANCE == -1) {
  879.         var params = querystring.parse(url.parse(req.url).query);
  880.         var pseudo = '#', tournoi = -1;
  881.         if ('pseudo' in params && 'id' in params) { pseudo = escapeHtml(params['pseudo']); tournoi = escapeHtml(params['id']); }
  882.         connection.query('SELECT pays FROM membres WHERE pseudo = ? AND (typemembre = 1 OR typemembre = 2)', [pseudo], function(error, verdict, fields) {
  883.             //console.log(verdict.length);
  884.             if (verdict.length == 0) { res.render('postpone.ejs', {LOCALHOST: LOCALHOST, pseudo: '#', pays: 'WHO', tournoi: -1, version: version, tournoi: tournoi}); }
  885.             else { res.render('postpone.ejs', {LOCALHOST: LOCALHOST, pseudo: pseudo, version: version, pays: verdict[0]['pays'], tournoi: tournoi}); }
  886.         });
  887.     }
  888.     else { res.render('maintenance.ejs', {}); }
  889. }); // postpone - demander un report de match de tournoi
  890.  
  891. app.get('/postponing', function(req, res) {
  892.     console.log(getDateTime() + 'Page /postponing chargée.');
  893.     if (MAINTENANCE == -1) {
  894.         var params = querystring.parse(url.parse(req.url).query);
  895.         var rep = 0, tournoi = -1;
  896.         if ('r' in params && 'id' in params) {
  897.             rep = escapeHtml(params['r']); id = escapeHtml(params['id']);
  898.             if (rep == 0) {
  899.                 connection.query('UPDATE matches SET joueurreport = 0 WHERE id = ? AND datedebut > NOW()', [id], function (error, modif, fields) {
  900.                     res.render('betadashboard.ejs', {LOCALHOST: LOCALHOST, message: 'You successfully replied to the postponing request.', color: 'lime', version: version});
  901.                 });
  902.             }
  903.             else {
  904.                 connection.query('UPDATE matches SET datedebut = datereport, joueurreport = 0, debutmanche = datereport WHERE id = ? AND datedebut > NOW()', [id], function (error, modif, fields) {
  905.                     res.render('betadashboard.ejs', {LOCALHOST: LOCALHOST, message: 'You successfully replied to the postponing request.', color: 'lime', version: version});
  906.                 });
  907.             }
  908.         }
  909.         else { res.render('betadashboard.ejs', {LOCALHOST: LOCALHOST, message: 'An error occurred.', color: 'red', version: version}); }
  910.     }
  911.     else { res.render('maintenance.ejs', {}); }
  912. }); // postponing - répondre à une demande de report puis redirection dashboard
  913.  
  914. app.get('/rankings', function(req, res) {
  915.     console.log(getDateTime() + 'Page /rankings chargée.');
  916.     if (MAINTENANCE == -1) {
  917.         var params = querystring.parse(url.parse(req.url).query);
  918.         var type = '';
  919.         if ('type' in params) {
  920.             type = escapeHtml(params['type']);
  921.             if (type != 'tournament' && type != 'multiplayer' && type != 'ghostbuster' && type != 'sprint' && type != 'sprint10' && type != 'survivor') { type = 'multiplayer'; }
  922.         }
  923.         else { type = 'multiplayer'; }
  924.         res.render('rankings.ejs', {LOCALHOST: LOCALHOST, version: version, type: type});
  925.     }
  926.     else { res.render('maintenance.ejs', {}); }
  927. }); // rankings
  928.  
  929. app.get('/wiki/how_to_play', function(req, res) {
  930.     console.log(getDateTime() + 'Page /wiki/how_to_play chargée.');
  931.     res.render('help.ejs', {LOCALHOST: LOCALHOST, version: version});
  932. }); // wiki/how_to_play
  933.  
  934. app.get('/wiki/api', function(req, res) {
  935.     console.log(getDateTime() + 'Page /wiki/api chargée.');
  936.     res.render('api.ejs', {LOCALHOST: LOCALHOST, version: version});
  937. }); // wiki/api
  938.  
  939. app.get('/wiki/tournaments', function(req, res) {
  940.     console.log(getDateTime() + 'Page /wiki/tournaments chargée.');
  941.     res.render('tournaments.ejs', {LOCALHOST: LOCALHOST, version: version});
  942. }); // wiki/tournaments
  943.  
  944. app.get('/editprofile', function(req, res) {
  945.     console.log(getDateTime() + 'Page /editprofile chargée.');
  946.     res.render('editprofile.ejs', {LOCALHOST: LOCALHOST, version: version});
  947. }); // editprofile
  948.  
  949. app.get('/timetable', function(req, res) {
  950.     console.log(getDateTime() + 'Page /timetable chargée.');
  951.     res.render('timetable.ejs', {LOCALHOST: LOCALHOST, version: version});
  952. }); // timetable
  953.  
  954. app.get('/compete', function(req, res) {
  955.     console.log(getDateTime() + 'Page /compete chargée.');
  956.     res.render('compete.ejs', {LOCALHOST: LOCALHOST, version: version});
  957. }); // compete
  958.  
  959. app.get('/tournament', function(req, res) {
  960.     console.log(getDateTime() + 'Page /tournament chargée.');
  961.     if (MAINTENANCE == -1) {
  962.         var params = querystring.parse(url.parse(req.url).query);
  963.         var id = '', m = '', color = 'red', message = '';
  964.         if ('m' in params) {
  965.             m = escapeHtml(params['m'].toString());
  966.             if (m == 'valider') { message = 'In order to access this feature you first need to validate your account.'; }
  967.             else if (m == 'inscrire') { message = 'In order to access this feature you first need to sign up.'; }
  968.             else if (m == '1') { message = 'You successfully registered in this tournament.'; color = 'lime'; }
  969.         }
  970.         if ('id' in params) {
  971.             id = parseInt(escapeHtml(params['id']));
  972.             if (id >= 1 && id <= 9) {
  973.                 connection.query('SELECT * FROM tournois WHERE id = ?', [parseInt(id)], function (error, infos, fields) {
  974.                     res.render('tournament.ejs', {LOCALHOST: LOCALHOST, version: version, message: message, color: color, id_tournoi: parseInt(id), nom_tournoi: infos[0]['nom'], fini: infos[0]['fini'], typeTournoi: infos[0]['type'], datedebut: infos[0]['datedebut']});
  975.                 });
  976.             }
  977.             else { res.render('betadashboard.ejs', {LOCALHOST: LOCALHOST, version: version, message: '', color: ''}); }
  978.         }
  979.         else { res.render('betadashboard.ejs', {LOCALHOST: LOCALHOST, version: version, message: '', color: ''}); }
  980.     }
  981.     else { res.render('maintenance.ejs', {}); }
  982. }); // tournament
  983.  
  984. app.get('/register', function(req, res) {
  985.     console.log(getDateTime() + 'Page /register chargée.');
  986.     if (MAINTENANCE == -1) {
  987.         var params = querystring.parse(url.parse(req.url).query);
  988.         var id = '';
  989.         if ('id' in params) {
  990.             id = escapeHtml(params['id']);
  991.             if (id == '4' || id == '5') {
  992.                 connection.query('SELECT * FROM tournois WHERE id = ?', [parseInt(id)], function (error, infos, fields) {
  993.                     res.render('register.ejs', {LOCALHOST: LOCALHOST, version: version, id_tournoi: parseInt(id), nom_tournoi: infos[0]['nom']});
  994.                 });  
  995.             }          
  996.             else { res.render('compete.ejs', {LOCALHOST: LOCALHOST, version: version, message: '', color: ''}); }
  997.         }
  998.         else { res.render('compete.ejs', {LOCALHOST: LOCALHOST, version: version, message: '', color: ''}); }
  999.     }
  1000.     else { res.render('maintenance.ejs', {}); }
  1001. }); // register (tournois)
  1002.  
  1003. app.get('/cancelregistration', function(req, res) {
  1004.     console.log(getDateTime() + 'Page /cancelregistration chargée. :(');
  1005.     if (MAINTENANCE == -1) {
  1006.         var params = querystring.parse(url.parse(req.url).query);
  1007.         var id = '';
  1008.         if ('id' in params) {
  1009.             id = escapeHtml(params['id']);
  1010.             if (id == '4' || id == '5') {
  1011.                 connection.query('SELECT * FROM tournois WHERE id = ?', [parseInt(id)], function (error, infos, fields) {
  1012.                     res.render('cancelregistration.ejs', {LOCALHOST: LOCALHOST, version: version, id_tournoi: parseInt(id), nom_tournoi: infos[0]['nom']});
  1013.                 });
  1014.             }
  1015.             else { res.render('betadashboard.ejs', {LOCALHOST: LOCALHOST, version: version, message: '', color: ''}); }
  1016.         }
  1017.         else { res.render('betadashboard.ejs', {LOCALHOST: LOCALHOST, version: version, message: '', color: ''}); }
  1018.     }
  1019.     else { res.render('maintenance.ejs', {}); }
  1020. }); // cancelregistration (tournois)
  1021.  
  1022. app.get('/dashboard', function(req, res) {
  1023.     console.log(getDateTime() + 'Page /dashboard chargée.');
  1024.     if (MAINTENANCE == -1) {
  1025.         var params = querystring.parse(url.parse(req.url).query);
  1026.         var indice = Math.floor(Math.random() * conseils.length);
  1027.         var m = '', message = conseils[indice], color = 'rgba(210, 210, 210, 1)';
  1028.         if ('m' in params) {
  1029.             m = escapeHtml(params['m']);
  1030.             if (m == 'valider') { color = 'red'; message = 'In order to access this feature you first need to validate your account.'; }
  1031.             else if (m == 'inscrire') { color = 'red'; message = 'In order to access this feature you first need to sign up.'; }
  1032.             else if (m == 'reportok') { color = 'lime'; message = 'Your postponing request was successfully sent.'; }
  1033.             else if (m == 'erreur') { color = 'red'; message = 'An error occurred.'; }
  1034.         }
  1035.         res.render('betadashboard.ejs', {LOCALHOST: LOCALHOST, version: version, message: message, color: color});
  1036.     }
  1037.     else { res.render('maintenance.ejs', {}); }
  1038. }); // dashboard
  1039.  
  1040. app.get('/betadashboard', function(req, res) {
  1041.     console.log(getDateTime() + 'Page /betadashboard chargée.');
  1042.     if (MAINTENANCE == -1) {
  1043.         res.render('betadashboard.ejs', {LOCALHOST: LOCALHOST, version: version});
  1044.     }
  1045.     else { res.render('maintenance.ejs', {}); }
  1046. }); // betadashboard
  1047.  
  1048. /*app.get('/training', function(req, res) {
  1049.     console.log(getDateTime() + 'Page /training chargée.');
  1050.     if (MAINTENANCE == -1) {
  1051.         var params = querystring.parse(url.parse(req.url).query);
  1052.         var m = '', message = '', color = 'red';
  1053.         if ('m' in params) {
  1054.             m = escapeHtml(params['m']);
  1055.             if (m == 'valider') { message = 'In order to access this feature you first need to validate your account.'; }
  1056.             else if (m == 'inscrire') { message = 'In order to access this feature you first need to sign up.'; }
  1057.         }
  1058.         res.render('training.ejs', {LOCALHOST: LOCALHOST, version: version, message: message, color: color, });
  1059.     }
  1060.     else { res.render('maintenance.ejs', {}); }
  1061. }); // training*/
  1062.  
  1063. /*app.get('/options', function(req, res) {
  1064.     console.log(getDateTime() + 'Page /options chargée.');
  1065.     res.render('options.ejs', {LOCALHOST: LOCALHOST, version: version});
  1066. }); // options*/
  1067.  
  1068. /*app.get('/quickplay', function(req, res) {
  1069.     console.log(getDateTime() + 'Page /quickplay chargée.');
  1070.     var indice = Math.floor(Math.random() * conseils.length);
  1071.     var message = conseils[indice];
  1072.     res.render('quickplay.ejs', {LOCALHOST: LOCALHOST, version: version, message: message});
  1073. }); // quickplay*/
  1074.  
  1075. app.get('/start', function(req, res) {
  1076.     console.log(getDateTime() + 'Page /start chargée.');
  1077.     res.render('start.ejs', {LOCALHOST: LOCALHOST, version: version});
  1078. }); // start
  1079.  
  1080. app.get('/customgames', function(req, res) {
  1081.     console.log(getDateTime() + 'Page /customgames chargée.');
  1082.     var params = querystring.parse(url.parse(req.url).query);
  1083.     var message = '#', couleur = 'lime', idm = -1;
  1084.     if ('m' in params) { idm = parseInt(escapeHtml(params['m'])); }
  1085.     if (idm == 0) { couleur = 'red'; message = 'An error occurred.'; }
  1086.     else if (idm == 1) { message = 'You successfully confirmed the custom match.'; }
  1087.     else if (idm == 2) { message = 'You successfully cancelled the custom match.'; }
  1088.     else if (idm == 3) { message = 'You successfully sent the custom game invitation.'; }
  1089.     res.render('customs.ejs', {LOCALHOST: LOCALHOST, version: version, idm: idm, couleur: couleur, message: message});
  1090. }); // customs
  1091.  
  1092. app.get('/live', function(req, res) {
  1093.     console.log(getDateTime() + 'Page /live chargée.');
  1094.     if (MAINTENANCE == -1) {
  1095.         var params = querystring.parse(url.parse(req.url).query);
  1096.         var type = '';
  1097.         if ('t' in params && 'id' in params) {
  1098.             var id_direct = parseInt(escapeHtml(params['id'].toString())), type = escapeHtml(params['t'].toString());
  1099.             if (type == 'q') {
  1100.                 connection.query("SELECT m1.pays AS pays1, m2.pays AS pays2, m1.elo2 AS elo1_avant, m2.elo2 AS elo2_avant, m1.pseudo AS pseudo1, m2.pseudo AS pseudo2, parties.id AS id FROM parties INNER JOIN membres AS m1 ON m1.id = parties.joueur1  INNER JOIN membres AS m2 ON m2.id = parties.joueur2 WHERE parties.etat = -1 AND parties.id = ?", [id_direct], function (error, infos_direct, fields) {
  1101.                     if (infos_direct.length == 0) { res.render('live.ejs', {LOCALHOST: LOCALHOST, version: version, type: type, id_partie: -1, joueur1: 0, joueur2: 0, pays1: 0, pays2: 0, elo1: 0, elo2: 0}); }
  1102.                     else {
  1103.                         var temp = infos_direct[0];
  1104.                         res.render('live.ejs', {LOCALHOST: LOCALHOST, version: version, id_partie: id_direct, type: type, joueur1: temp['pseudo1'], joueur2: temp['pseudo2'], pays1: temp['pays1'], pays2: temp['pays2'], elo1: temp['elo1_avant'], elo2: temp['elo2_avant']});
  1105.                     }
  1106.                 });
  1107.             }
  1108.             else if (type == 'm') {
  1109.                 connection.query("SELECT m1.pays AS pays1, m2.pays AS pays2, m1.elo2 AS elo1_avant, m2.elo2 AS elo2_avant, m1.pseudo AS pseudo1, m2.pseudo AS pseudo2, matches.id AS id FROM matches INNER JOIN membres AS m1 ON m1.id = matches.joueur1 INNER JOIN membres AS m2 ON m2.id = matches.joueur2 WHERE matches.confirmation > 0 AND matches.id = ? AND prive = 0", [id_direct], function (error, infos_direct, fields) {
  1110.                     if (infos_direct.length == 0) { res.render('live.ejs', {LOCALHOST: LOCALHOST, version: version, type: type, id_partie: -1, joueur1: 0, joueur2: 0, pays1: 0, pays2: 0, elo1: 0, elo2: 0}); }
  1111.                     else {
  1112.                         var temp = infos_direct[0];
  1113.                         res.render('live.ejs', {LOCALHOST: LOCALHOST, version: version, id_partie: id_direct, type: type, joueur1: temp['pseudo1'], joueur2: temp['pseudo2'], pays1: temp['pays1'], pays2: temp['pays2'], elo1: temp['elo1_avant'], elo2: temp['elo2_avant']});
  1114.                     }
  1115.                 });
  1116.             }
  1117.             else { res.render('live.ejs', {LOCALHOST: LOCALHOST, version: version, type: type, id_partie: -1, joueur1: 0, joueur2: 0, pays1: 0, pays2: 0, elo1: 0, elo2: 0}); }
  1118.         }
  1119.         else { res.render('live.ejs', {LOCALHOST: LOCALHOST, version: version, type: 'a', id_partie: -1, joueur1: 0, joueur2: 0, pays1: 0, pays2: 0, elo1: 0, elo2: 0}); }
  1120.     }
  1121.     else { res.render('maintenance.ejs', {}); }
  1122. }); // live
  1123.  
  1124. app.get('/replay', function(req, res) {
  1125.     console.log(getDateTime() + 'Page /replay chargée.');
  1126.     if (MAINTENANCE == -1) {
  1127.         var params = querystring.parse(url.parse(req.url).query);
  1128.         var type = '', idp = 0, score = '', prochain = -1;
  1129.         if ('s' in params) { score = escapeHtml(params['s'].toString()); }
  1130.         if ('p' in params) { prochain = parseInt(escapeHtml(params['p'].toString())); }
  1131.         if ('t' in params && 'id' in params) {
  1132.             type = escapeHtml(params['t'].toString());
  1133.             idp = parseInt(escapeHtml(params['id'].toString()));
  1134.             if (type == 's') { // sprint
  1135.                 connection.query('SELECT sprint.id, sprint.fantome, membres.pseudo, membres.pays FROM sprint LEFT JOIN membres ON membres.id = sprint.id_membre WHERE sprint.id = ?', [idp], function (error, verdict, fields) {
  1136.                     if (verdict.length == 1) {
  1137.                         fs.readFile(path.join(__dirname, '/parties/'+verdict[0]['fantome']+'.txt'), 'utf8', function (err,partie) {
  1138.                             //console.log(err);
  1139.                             console.log(getDateTime() + 'Partie sprint de ' + verdict[0]['pseudo'] + ' (id : ' + verdict[0]['id'] + ') chargée.');
  1140.                             var donnees = partie.split('\n');
  1141.                             verdict[0]['handicap'] = 0;
  1142.                             connection.query('SELECT ligne_suppl AS ls FROM fantomes WHERE id = ?', [verdict[0]['fantome']], function (error, ls, fields) {
  1143.                                 res.render('replay.ejs', {LOCALHOST: LOCALHOST, version: version, p1: donnees[0], p2: donnees[1], p3: donnees[2], p4: donnees[3], p11: donnees[0], p12: donnees[1], p13: donnees[2], p14: donnees[3], p15: '', p21: donnees[0], p22: donnees[1], p23: donnees[2], p24: donnees[3], p25: '', type: type, infos: verdict[0], ls1: ls[0]['ls'], ls2: ls[0]['ls'], score: score, prochain: prochain});
  1144.                             });
  1145.                             connection.query('UPDATE sprint SET vues = vues + 1 WHERE id = ?', [idp], function (error, modif, fields) {});
  1146.                         });
  1147.                     }
  1148.                     else { res.render('betadashboard.ejs', {LOCALHOST: LOCALHOST, version: version, message: 'Sorry, an error occurred.', color: 'red'}); }
  1149.                 });
  1150.             }
  1151.             else if (type == 'rs') { // sprint
  1152.                 connection.query('SELECT id FROM sprint WHERE id_membre = ? ORDER BY temps LIMIT 0, 1', [idp], function (error, selection, fields) {
  1153.                     if (selection.length == 0) { res.render('betadashboard.ejs', {LOCALHOST: LOCALHOST, version: version, message: 'Sorry, an error occurred.', color: 'red'}); }
  1154.                     connection.query('SELECT sprint.id, sprint.fantome, membres.pseudo, membres.pays FROM sprint LEFT JOIN membres ON membres.id = sprint.id_membre WHERE sprint.id = ?', [selection[0]['id']], function (error, verdict, fields) {
  1155.                         if (verdict.length == 1) {
  1156.                             fs.readFile(path.join(__dirname, '/parties/'+verdict[0]['fantome']+'.txt'), 'utf8', function (err,partie) {
  1157.                                 //console.log(err);
  1158.                                console.log(getDateTime() + 'Partie sprint de ' + verdict[0]['pseudo'] + ' (id : ' + verdict[0]['id'] + ') chargée.');
  1159.                                 var donnees = partie.split('\n');
  1160.                                 verdict[0]['handicap'] = 0;
  1161.                                 connection.query('SELECT ligne_suppl AS ls FROM fantomes WHERE id = ?', [verdict[0]['fantome']], function (error, ls, fields) {
  1162.                                     res.render('replay.ejs', {LOCALHOST: LOCALHOST, version: version, p1: donnees[0], p2: donnees[1], p3: donnees[2], p4: donnees[3], p11: donnees[0], p12: donnees[1], p13: donnees[2], p14: donnees[3], p15: '', p21: donnees[0], p22: donnees[1], p23: donnees[2], p24: donnees[3], p25: '', type: 's', infos: verdict[0], ls1: ls[0]['ls'], ls2: ls[0]['ls'], score: score, prochain: prochain});
  1163.                                 });
  1164.                                 connection.query('UPDATE sprint SET vues = vues + 1 WHERE id = ?', [selection[0]['id']], function (error, modif, fields) {});
  1165.                             });
  1166.                         }
  1167.                         else { res.render('betadashboard.ejs', {LOCALHOST: LOCALHOST, version: version, message: 'Sorry, an error occurred.', color: 'red'}); }
  1168.                     });
  1169.                 });
  1170.             }
  1171.             else if (type == 'sv') { // survivor
  1172.                 connection.query('SELECT survivor.id, survivor.fantome, survivor.temps, membres.pseudo, membres.pays FROM survivor LEFT JOIN membres ON membres.id = survivor.id_membre WHERE survivor.id = ?', [idp], function (error, verdict, fields) {
  1173.                     if (verdict.length == 1) {
  1174.                         fs.readFile(path.join(__dirname, '/parties/'+verdict[0]['fantome']+'.txt'), 'utf8', function (err,partie) {
  1175.                             //console.log(err);
  1176.                             console.log(getDateTime() + 'Partie survivor de ' + verdict[0]['pseudo'] + ' (id : ' + verdict[0]['id'] + ') chargée.');
  1177.                             var donnees = partie.split('\n');
  1178.                             var temps = donnees[2].split('/');
  1179.                             var chrono = parseInt(temps[temps.length - 2]);
  1180.                             console.log(chrono, verdict[0]['temps']);
  1181.                             if (Math.abs(chrono - verdict[0]['temps']) > 10000) { verdict[0]['handicap'] = 2; }
  1182.                             else { verdict[0]['handicap'] = 1; }
  1183.                             connection.query('SELECT ligne_suppl AS ls FROM fantomes WHERE id = ?', [verdict[0]['fantome']], function (error, ls, fields) {
  1184.                                 res.render('replay.ejs', {LOCALHOST: LOCALHOST, version: version, p1: donnees[0], p2: donnees[1], p3: donnees[2], p4: donnees[3], p11: donnees[0], p12: donnees[1], p13: donnees[2], p14: donnees[3], p15: donnees[4], p21: donnees[0], p22: donnees[1], p23: donnees[2], p24: donnees[3], p25: '', type: type, infos: verdict[0], ls1: ls[0]['ls'], ls2: ls[0]['ls'], score: score, prochain: prochain});
  1185.                             });
  1186.                             connection.query('UPDATE survivor SET vues = vues + 1 WHERE id = ?', [idp], function (error, modif, fields) {});
  1187.                         });
  1188.                     }
  1189.                     else { res.render('betadashboard.ejs', {LOCALHOST: LOCALHOST, version: version, message: 'Sorry, an error occurred.', color: 'red'}); }
  1190.                 });
  1191.             }
  1192.             else if (type == 'rsv') { // survivor
  1193.                 connection.query('SELECT id FROM survivor WHERE id_membre = ? ORDER BY temps DESC LIMIT 0, 1', [idp], function (error, selection, fields) {
  1194.                     if (selection.length == 0) { res.render('betadashboard.ejs', {LOCALHOST: LOCALHOST, version: version, message: 'Sorry, an error occurred.', color: 'red'}); }
  1195.                     connection.query('SELECT survivor.id, survivor.fantome, survivor.temps, membres.pseudo, membres.pays FROM survivor LEFT JOIN membres ON membres.id = survivor.id_membre WHERE survivor.id = ?', [selection[0]['id']], function (error, verdict, fields) {
  1196.                         if (verdict.length == 1) {
  1197.                             fs.readFile(path.join(__dirname, '/parties/'+verdict[0]['fantome']+'.txt'), 'utf8', function (err,partie) {
  1198.                                 //console.log(err);
  1199.                                 console.log(getDateTime() + 'Partie survivor de ' + verdict[0]['pseudo'] + ' (id : ' + verdict[0]['id'] + ') chargée.');
  1200.                                 var donnees = partie.split('\n');
  1201.                                 var temps = donnees[2].split('/');
  1202.                                 var chrono = parseInt(temps[temps.length - 2]);
  1203.                                 if (Math.abs(chrono - verdict[0]['temps']) > 10000) { verdict[0]['handicap'] = 2; }
  1204.                                 else { verdict[0]['handicap'] = 1; }
  1205.                                 connection.query('SELECT ligne_suppl AS ls FROM fantomes WHERE id = ?', [verdict[0]['fantome']], function (error, ls, fields) {
  1206.                                     res.render('replay.ejs', {LOCALHOST: LOCALHOST, version: version, p1: donnees[0], p2: donnees[1], p3: donnees[2], p4: donnees[3], p11: donnees[0], p12: donnees[1], p13: donnees[2], p14: donnees[3], p15: donnees[4], p21: donnees[0], p22: donnees[1], p23: donnees[2], p24: donnees[3], p25: '', type: 'sv', infos: verdict[0], ls1: ls[0]['ls'], ls2: ls[0]['ls'], score: score, prochain: prochain});
  1207.                                 });
  1208.                                 connection.query('UPDATE survivor SET vues = vues + 1 WHERE id = ?', [selection[0]['id']], function (error, modif, fields) {});
  1209.                             });
  1210.                         }
  1211.                         else { res.render('betadashboard.ejs', {LOCALHOST: LOCALHOST, version: version, message: 'Sorry, an error occurred.', color: 'red'}); }
  1212.                     });
  1213.                 });
  1214.             }
  1215.             else if (type == 'p') { // partie multijoueur
  1216.                 connection.query('SELECT parties.id, m1.pseudo AS pseudo1, m1.pays AS pays1, m2.pseudo AS pseudo2, m2.pays AS pays2, fantome1, fantome2, handicap FROM parties LEFT JOIN membres AS m1 ON m1.id = parties.joueur1 LEFT JOIN membres AS m2 ON m2.id = parties.joueur2 WHERE parties.id = ? AND fantome1 > 0 AND fantome2 > 0', [idp], function (error, verdict, fields) {
  1217.                     if (verdict.length == 1) {
  1218.                         fs.readFile(path.join(__dirname, '/parties/'+verdict[0]['fantome1']+'.txt'), 'utf8', function (err,partie1) {
  1219.                             console.log(getDateTime() + 'Partie multijoueur de ' + verdict[0]['pseudo1'] + ' (id : ' + verdict[0]['id'] + ') chargée.');
  1220.                             var donnees1 = partie1.split('\n');
  1221.                             fs.readFile(path.join(__dirname, '/parties/'+verdict[0]['fantome2']+'.txt'), 'utf8', function (err,partie2) {
  1222.                                 console.log(getDateTime() + 'Partie multijoueur de ' + verdict[0]['pseudo2'] + ' (id : ' + verdict[0]['id'] + ') chargée.');
  1223.                                 var donnees2 = partie2.split('\n');
  1224.                                 // gérer le cas qui marche pas
  1225.                                 connection.query('SELECT ligne_suppl AS ls FROM fantomes WHERE id = ?', [verdict[0]['fantome2']], function (error, ls2, fields) {
  1226.                                     connection.query('SELECT ligne_suppl AS ls FROM fantomes WHERE id = ?', [verdict[0]['fantome1']], function (error, ls1, fields) {
  1227.                                         res.render('replay.ejs', {LOCALHOST: LOCALHOST, version: version, p1: donnees1[0], p2: donnees1[1], p3: donnees1[2], p4: donnees1[3], p11: donnees1[0], p12: donnees1[1], p13: donnees1[2], p14: donnees1[3], p15: donnees1[4], p21: donnees2[0], p22: donnees2[1], p23: donnees2[2], p24: donnees2[3], p25: donnees2[4], type: type, infos: verdict[0], ls1: ls1[0]['ls'], ls2: ls2[0]['ls'], score: score, prochain: prochain});
  1228.                                     });
  1229.                                 });
  1230.                                 connection.query('UPDATE parties SET vues = vues + 1 WHERE id = ?', [idp], function (error, modif, fields) {});
  1231.                             });
  1232.                         });
  1233.                     }
  1234.                     else { res.render('betadashboard.ejs', {LOCALHOST: LOCALHOST, version: version, message: 'Sorry, an error occurred.', color: 'red'}); }
  1235.                 });
  1236.             }
  1237.             else if (type == 'g') { // partie ghostbuster
  1238.                 connection.query('SELECT solo.id, solo.handicap AS handicap, m1.pseudo AS pseudo1, m1.pays AS pays1, m2.pseudo AS pseudo2, m2.pays AS pays2, fantome, id_partie FROM solo LEFT JOIN membres AS m1 ON m1.id = solo.id_membre LEFT JOIN fantomes AS f ON f.id = solo.id_partie LEFT JOIN membres AS m2 ON m2.id = f.id_membre WHERE solo.id = ? AND fantome > 0', [idp], function (error, verdict, fields) {
  1239.                     if (verdict.length == 1) {
  1240.                         fs.readFile(path.join(__dirname, '/parties/'+verdict[0]['fantome']+'.txt'), 'utf8', function (err,partie1) {
  1241.                             console.log(getDateTime() + 'Partie ghostbuster de ' + verdict[0]['pseudo1'] + ' (id : ' + verdict[0]['id'] + ') chargée.');
  1242.                             var donnees1 = partie1.split('\n');
  1243.                             fs.readFile(path.join(__dirname, '/parties/'+verdict[0]['id_partie']+'.txt'), 'utf8', function (err,partie2) {
  1244.                                 console.log(getDateTime() + 'Fantôme de ' + verdict[0]['pseudo2'] + ' (id : ' + verdict[0]['id_partie'] + ') chargé.');
  1245.                                 var donnees2 = partie2.split('\n');
  1246.                                 verdict[0]['handicap'] = 0;
  1247.                                 // gérer le cas qui marche pas
  1248.                                 connection.query('SELECT ligne_suppl AS ls FROM fantomes WHERE id = ?', [verdict[0]['id_partie']], function (error, ls2, fields) {
  1249.                                     connection.query('SELECT ligne_suppl AS ls FROM fantomes WHERE id = ?', [verdict[0]['fantome']], function (error, ls1, fields) {
  1250.                                         res.render('replay.ejs', {LOCALHOST: LOCALHOST, version: version, p1: donnees1[0], p2: donnees1[1], p3: donnees1[2], p4: donnees1[3], p11: donnees1[0], p12: donnees1[1], p13: donnees1[2], p14: donnees1[3], p15: '', p21: donnees2[0], p22: donnees2[1], p23: donnees2[2], p24: donnees2[3], p25: '', type: type, infos: verdict[0], ls1: ls1[0]['ls'], ls2: ls2[0]['ls'], score: score, prochain: prochain});
  1251.                                     });
  1252.                                 });
  1253.                                 connection.query('UPDATE solo SET vues = vues + 1 WHERE id = ?', [idp], function (error, modif, fields) {});
  1254.                             });
  1255.                         });
  1256.                     }
  1257.                     else { res.render('betadashboard.ejs', {LOCALHOST: LOCALHOST, version: version, message: 'Sorry, an error occurred.', color: 'red'}); }
  1258.                 });
  1259.             }
  1260.             else if (type == 'm') { // match complet
  1261.                 connection.query('SELECT matches.id AS id, tournois.nom AS nom_tournoi, m1.pseudo AS pseudo1, m1.pays AS pays1, m2.pseudo AS pseudo2, m2.pays AS pays2, matches.tournoi, nb_manches, diff_manches, matches.limite_ko, matches.diff_victoire, matches.duree, matches.handicap, matches.debutmanche, score1, score2 FROM matches LEFT JOIN membres AS m1 ON m1.id = matches.joueur1 LEFT JOIN membres AS m2 ON m2.id = matches.joueur2 LEFT JOIN tournois ON tournois.id = matches.tournoi WHERE confirmation = 2 AND matches.id = ?', [idp], function (error, verif, fields) {
  1262.                     if (verif.length == 1) {
  1263.                         connection.query('SELECT parties.id AS id, KO1, KO2, lignes1, lignes2, hauteur1, hauteur2, date, fantome1, fantome2, fantomes.etat AS duree FROM parties LEFT JOIN fantomes ON fantomes.id = parties.fantome1 WHERE id_match = ? AND parties.etat = 1 ORDER BY date', [idp], function (error, manches, fields) {
  1264.                             var p1 = 0, p2 = 0;
  1265.                             prochain = Math.max(prochain, 0);
  1266.                             for (i = 0; i < prochain; i++) {
  1267.                                 if ((100000*manches[i]["KO1"]+100*manches[i]["lignes1"]-manches[i]["hauteur1"]) > (100000*manches[i]["KO2"]+100*manches[i]["lignes2"]-manches[i]["hauteur2"])) { p1++; }
  1268.                                 else if ((100000*manches[i]["KO1"]+100*manches[i]["lignes1"]-manches[i]["hauteur1"]) < (100000*manches[i]["KO2"]+100*manches[i]["lignes2"]-manches[i]["hauteur2"])) { p2++; }
  1269.                             }
  1270.                             if (manches[prochain] == undefined) { res.render('betadashboard.ejs', {LOCALHOST: LOCALHOST, version: version, message: 'Sorry, an error occurred.', color: 'red'}); }
  1271.                             else if (manches[prochain]['fantome1'] > 0 && manches[prochain]['fantome2'] > 0) {
  1272.                                 score = p1 + ' - ' + p2;
  1273.                                 fs.readFile(path.join(__dirname, '/parties/'+manches[prochain]['fantome1']+'.txt'), 'utf8', function (err,partie1) {
  1274.                                     console.log(getDateTime() + 'Match de ' + verif[0]['pseudo1'] + ' (id : ' + verif[0]['id'] + ', manche : ' + (prochain+1) + ') chargé.');
  1275.                                     var donnees1 = partie1.split('\n');
  1276.                                     fs.readFile(path.join(__dirname, '/parties/'+manches[prochain]['fantome2']+'.txt'), 'utf8', function (err,partie2) {
  1277.                                         console.log(getDateTime() + 'Match de ' + verif[0]['pseudo2'] + ' (id : ' + verif[0]['id'] + ', manche : ' + (prochain+1) + ') chargé.');
  1278.                                         var donnees2 = partie2.split('\n');
  1279.                                         // gérer le cas qui marche pas
  1280.                                         connection.query('SELECT ligne_suppl AS ls FROM fantomes WHERE id = ?', [manches[prochain]['fantome2']], function (error, ls2, fields) {
  1281.                                             connection.query('SELECT ligne_suppl AS ls FROM fantomes WHERE id = ?', [manches[prochain]['fantome1']], function (error, ls1, fields) {
  1282.                                                 if (manches.length == prochain+1) { prochain = -1; }
  1283.                                                 res.render('replay.ejs', {LOCALHOST: LOCALHOST, version: version, p1: donnees1[0], p2: donnees1[1], p3: donnees1[2], p4: donnees1[3], p11: donnees1[0], p12: donnees1[1], p13: donnees1[2], p14: donnees1[3], p15: donnees1[4], p21: donnees2[0], p22: donnees2[1], p23: donnees2[2], p24: donnees2[3], p25: donnees2[4], type: type, infos: verif[0], ls1: ls1[0]['ls'], ls2: ls2[0]['ls'], score: score, prochain: prochain});
  1284.                                             });
  1285.                                         });
  1286.                                         connection.query('UPDATE matches SET vues = vues + 1 WHERE id = ?', [idp], function (error, modif, fields) {});
  1287.                                     });
  1288.                                 });
  1289.                             }
  1290.                             else { res.render('betadashboard.ejs', {LOCALHOST: LOCALHOST, version: version, message: 'Sorry, an error occurred.', color: 'red'}); }
  1291.                         });
  1292.                     }
  1293.                     else { res.render('betadashboard.ejs', {LOCALHOST: LOCALHOST, version: version, message: 'Sorry, an error occurred.', color: 'red'}); }
  1294.                 });
  1295.             }
  1296.             else { res.render('betadashboard.ejs', {LOCALHOST: LOCALHOST, version: version, message: 'Sorry, an error occurred.', color: 'red'}); }
  1297.             // penser à rajouter m/match un jour
  1298.         }
  1299.         else { res.render('betadashboard.ejs', {LOCALHOST: LOCALHOST, version: version, message: 'Sorry, an error occurred.', color: 'red'}); }
  1300.     }
  1301.     else { res.render('maintenance.ejs', {}); }
  1302. }); // replay
  1303.  
  1304. function recup_discord(codeDiscord) {
  1305.     var p2 = codeDiscord.substring(0, 5);
  1306.     var p1 = codeDiscord.substring(5, 10);
  1307.     var c1 = 0, c2 = 0;
  1308.     var m = 1;
  1309.     var alph = ['h', 'C', 'N', 'G', '3', 'P', 'O', 'F', 'D', 'S', '6', 'J', 'I', 'p', 'u', 'Z', '0', 'y', 'B', 'R', 'W', 'q', 'M', 'l', 's', 'g', 'U', 'c', '4', 'x', 'j', 'V', 'd', 'a', 'T', '2', 'Q', '7', 'K', '9', 'A', 'k', 'Y', 'f', 't', 'r', 'o', 'b', '1', 'n', 'z', 'X', 'E', 'w', '8', '5', 'i', 'H', 'e', 'v', 'm', 'L'];
  1310.     for (var i = 0; i < 5; i++) {
  1311.         var n = alph.indexOf(p1[i]);
  1312.         c1 += m*n;
  1313.         m *= 62;
  1314.     }
  1315.     m = 1;
  1316.     for (var i = 0; i < 5; i++) {
  1317.         var n = alph.indexOf(p2[i]);
  1318.         c2 += m*n;
  1319.         m *= 62;
  1320.     }
  1321.     if (c1 < 0 || c2 < 0) { return ''; }
  1322.     c1 = c1.toString();
  1323.     c2 = c2.toString();
  1324.     while (c1.length < 9) { c1 = '0' + c1; }
  1325.     while (c2.length < 9) { c2 = '0' + c2; }
  1326.     return c1+c2;
  1327. }
  1328.  
  1329. app.get('/profile', function(req, res) {
  1330.     console.log(getDateTime() + 'Page /profile chargée.');
  1331.     if  (MAINTENANCE == -1) {
  1332.         var params = querystring.parse(url.parse(req.url).query);
  1333.         var pseudo = '';
  1334.         if ('p' in params) {
  1335.             pseudo = escapeHtml(params['p'].toString());
  1336.             console.log(pseudo);
  1337.             connection.query('SELECT * FROM membres WHERE typemembre >= 0 AND pseudo = ?', [pseudo], function (error, verif, fields) {
  1338.                 if (verif.length == 1) {
  1339.                     connection.query('UPDATE membres SET vues = vues + 1 WHERE pseudo = ?', [pseudo], function (error, modif, fields) {});
  1340.                     var infos = {};
  1341.                     infos['id'] = verif[0]['id'];
  1342.                     infos['pseudo'] = verif[0]['pseudo'];
  1343.                     infos['pays'] = verif[0]['pays'];
  1344.                     infos['typemembre'] = verif[0]['typemembre'];
  1345.                     infos['dateinscription'] = verif[0]['dateinscription'].toString().substring(0, verif[0]['dateinscription'].toString().search(" GMT"));
  1346.                     infos['derniereconnexion'] = verif[0]['derniereconnexion'].toString().substring(0, verif[0]['derniereconnexion'].toString().search(" GMT"));
  1347.                     infos['elo1'] = verif[0]['elo1'];
  1348.                     infos['elo2'] = verif[0]['elo2'];
  1349.                     infos['tournoi'] = verif[0]['tournoi'];
  1350.                     infos['sprint'] = verif[0]['sprint'];
  1351.                     infos['sprint10'] = verif[0]['sprint10'];
  1352.                     infos['survivor'] = verif[0]['survivor'];
  1353.                     infos['twitch'] = verif[0]['twitch'];
  1354.                     infos['apm'] = parseFloat(60*verif[0]['coeff_force']).toFixed(2);
  1355.                     if (verif[0]['sexe_afficher'] == 1) { infos['sexe'] = verif[0]['sexe']; } else { infos['sexe'] = -1; }
  1356.                     if (verif[0]['nom_afficher'] == 1) { infos['nom'] = verif[0]['nom']; } else { infos['nom'] = ''; }
  1357.                     if (verif[0]['prenom_afficher'] == 1) { infos['prenom'] = verif[0]['prenom']; } else { infos['prenom'] = ''; }
  1358.                     infos['discord'] = '';
  1359.                     if (LOCALHOST == 0) { var sf = recup_discord(verif[0]['discord']); } else { var sf = ''; }
  1360.                     if (sf == '') {
  1361.                         res.render('profile.ejs', {LOCALHOST: LOCALHOST, version: version, infos: infos});
  1362.                     }
  1363.                     else {
  1364.                         client.fetchUser(sf).then(membre => {
  1365.                             if (verif[0]['discord_afficher'] == 1) { infos['discord'] = membre.tag; }
  1366.                             res.render('profile.ejs', {LOCALHOST: LOCALHOST, version: version, infos: infos});
  1367.                         });
  1368.                     }
  1369.                 }
  1370.                 else { res.render('betadashboard.ejs', {LOCALHOST: LOCALHOST, version: version, message: 'Sorry, an error occurred.', color: 'red'}); }
  1371.             });
  1372.         }
  1373.         else { res.render('betadashboard.ejs', {LOCALHOST: LOCALHOST, version: version, message: 'Sorry, an error occurred.', color: 'red'}); }
  1374.     }
  1375.     else { res.render('maintenance.ejs', {}); }
  1376. }); // profile
  1377.  
  1378. app.get('/listgames', function(req, res) {
  1379.     console.log(getDateTime() + 'Page /listgames chargée.');
  1380.     if (MAINTENANCE == -1) {
  1381.         var params = querystring.parse(url.parse(req.url).query);
  1382.         var pseudo = '';
  1383.         if ('p' in params && 't' in params) {
  1384.             pseudo = escapeHtml(params['p'].toString());
  1385.             type = escapeHtml(params['t'].toString());
  1386.             var desc = '';
  1387.             console.log(pseudo, type);
  1388.             connection.query('SELECT pays, id FROM membres WHERE pseudo = ?', [pseudo], function (error, drp, fields) {
  1389.                 if (drp.length == 0) { res.render('betadashboard.ejs', {LOCALHOST: LOCALHOST, version: version, message: 'Sorry, an error occurred.', color: 'red'}); }
  1390.                 else {
  1391.                     if (type == 's') {
  1392.                         desc = 'sprint games';
  1393.                         connection.query('SELECT sprint.id, temps, blocs, date, fantome FROM sprint LEFT JOIN membres ON membres.id = sprint.id_membre WHERE id_membre = ? ORDER BY temps', [drp[0]['id']], function (error, liste, fields) {
  1394.                             res.render('listgames.ejs', {LOCALHOST: LOCALHOST, version: version, pseudo: pseudo, pays: drp[0]['pays'], type: type, liste: liste, desc: desc});
  1395.                         });
  1396.                     }
  1397.                     else if (type == 'sv') {
  1398.                         desc = 'survivor games';
  1399.                         connection.query('SELECT survivor.id, temps, date, fantome FROM survivor LEFT JOIN membres ON membres.id = survivor.id_membre WHERE id_membre = ? ORDER BY temps DESC', [drp[0]['id']], function (error, liste, fields) {
  1400.                             res.render('listgames.ejs', {LOCALHOST: LOCALHOST, version: version, pseudo: pseudo, pays: drp[0]['pays'], type: type, liste: liste, desc: desc});
  1401.                         });
  1402.                     }
  1403.                     else if (type == 'p') {
  1404.                         desc = 'quickplay games';
  1405.                         connection.query('SELECT date, KO1, KO2, lignes1, lignes2, m1.pays AS pays1, m2.pays AS pays2, elo1_avant, elo2_avant, elo1_apres, elo2_apres, m1.pseudo AS pseudo1, m2.pseudo AS pseudo2, parties.id AS id FROM parties INNER JOIN membres AS m1 ON m1.id = parties.joueur1 INNER JOIN membres AS m2 ON m2.id = parties.joueur2 WHERE parties.id_match = 0 AND (joueur1 = ? OR joueur2 = ?) AND etat = 1 ORDER BY date DESC', [drp[0]['id'], drp[0]['id']], function (error, liste, fields) {
  1406.                             res.render('listgames.ejs', {LOCALHOST: LOCALHOST, version: version, pseudo: pseudo, pays: drp[0]['pays'], type: type, liste: liste, desc: desc});
  1407.                         });
  1408.                     }
  1409.                     else if (type == 'm') {
  1410.                         desc = 'matches';
  1411.                         connection.query('SELECT datedebut, score1, score2, m1.pays AS pays1, m2.pays AS pays2, m1.elo2 AS elo1_avant, m2.elo2 AS elo2_avant, m1.pseudo AS pseudo1, m2.pseudo AS pseudo2, matches.id AS id FROM matches INNER JOIN membres AS m1 ON m1.id = matches.joueur1 INNER JOIN membres AS m2 ON m2.id = matches.joueur2 WHERE matches.confirmation = 2 AND (joueur1 = ? OR joueur2 = ?) AND (score1+score2) > 0 ORDER BY debutmanche DESC', [drp[0]['id'], drp[0]['id']], function (error, liste, fields) {
  1412.                             res.render('listgames.ejs', {LOCALHOST: LOCALHOST, version: version, pseudo: pseudo, pays: drp[0]['pays'], type: type, liste: liste, desc: desc});
  1413.                         });
  1414.                     }
  1415.                     else if (type == 'g') {
  1416.                         desc = 'ghostbuster games';
  1417.                         connection.query('SELECT solo.id, KO1, KO2, lignes1, lignes2, elo1_avant, elo1_apres, date FROM solo LEFT JOIN membres ON membres.id = solo.id_membre WHERE id_membre = ? AND etat = 1 ORDER BY date DESC', [drp[0]['id']], function (error, liste, fields) {
  1418.                             res.render('listgames.ejs', {LOCALHOST: LOCALHOST, version: version, pseudo: pseudo, pays: drp[0]['pays'], type: type, liste: liste, desc: desc});
  1419.                         });
  1420.                     }
  1421.                     else { res.render('betadashboard.ejs', {LOCALHOST: LOCALHOST, version: version, message: 'Sorry, an error occurred.', color: 'red'}); }
  1422.                 }
  1423.             });
  1424.         }
  1425.         else { res.render('betadashboard.ejs', {LOCALHOST: LOCALHOST, version: version, message: 'Sorry, an error occurred.', color: 'red'}); }
  1426.     }
  1427.     else { res.render('maintenance.ejs', {}); }
  1428. }); // listgames
  1429.  
  1430. app.get('/match', function(req, res) {
  1431.     console.log(getDateTime() + 'Page /match chargée.');
  1432.     if (MAINTENANCE == -1) {
  1433.         var params = querystring.parse(url.parse(req.url).query);
  1434.         var idm = '';
  1435.         if ('id' in params) {
  1436.             idm = escapeHtml(params['id'].toString());
  1437.             connection.query('SELECT tournois.nom AS nom_tournoi, m1.pseudo AS pseudo1, m1.pays AS pays1, m2.pseudo AS pseudo2, m2.pays AS pays2, matches.tournoi, nb_manches, diff_manches, matches.limite_ko, matches.diff_victoire, matches.duree, matches.handicap, matches.debutmanche, score1, score2 FROM matches LEFT JOIN membres AS m1 ON m1.id = matches.joueur1 LEFT JOIN membres AS m2 ON m2.id = matches.joueur2 LEFT JOIN tournois ON tournois.id = matches.tournoi WHERE confirmation = 2 AND matches.id = ?', [idm], function (error, verif, fields) {
  1438.                 if (verif.length == 1) {
  1439.                     connection.query('SELECT parties.id AS id, KO1, KO2, lignes1, lignes2, hauteur1, hauteur2, date, fantome1, fantome2, fantomes.etat AS duree FROM parties LEFT JOIN fantomes ON fantomes.id = parties.fantome1 WHERE id_match = ? AND parties.etat = 1 ORDER BY date', [idm], function (error, liste, fields) {
  1440.                         res.render('match.ejs', {LOCALHOST: LOCALHOST, version: version, match: verif[0], manches: liste, match_id: idm});
  1441.                     });
  1442.                 }
  1443.                 else { res.render('betadashboard.ejs', {LOCALHOST: LOCALHOST, version: version, message: 'Sorry, an error occurred.', color: 'red'}); }
  1444.             });
  1445.         }
  1446.         else { res.render('betadashboard.ejs', {LOCALHOST: LOCALHOST, version: version, message: 'Sorry, an error occurred.', color: 'red'}); }
  1447.     }
  1448.     else { res.render('maintenance.ejs', {}); }
  1449. }); // match
  1450.  
  1451. app.get('/news/:id', function(req, res) {
  1452.     var idart = escapeHtml(req.params.id);
  1453.     console.log(getDateTime() + 'Page /news/'+idart+' chargée.');
  1454.     connection.query('SELECT articles.id AS id, MID(articles.datecreation, 1, 10) AS datecreation, MID(articles.datemodification, 1, 10) AS datemodification, membres.pseudo AS pseudo, membres.pays AS pays, articles.titre AS titre, articles.contenu AS contenu FROM articles INNER JOIN membres ON articles.id_membre = membres.id WHERE articles.id = ?', [idart], function (error, article, fields) {
  1455.         if (article.length == 1) { res.render('news.ejs', {LOCALHOST: LOCALHOST, version: version, article: article[0]}); }
  1456.         else {
  1457.             res.setHeader('Content-Type', 'text/html');
  1458.             res.render('404error.ejs', {LOCALHOST: LOCALHOST, version: version});
  1459.         }
  1460.     });
  1461. }); // news
  1462.  
  1463. app.get('/wiki/history', function(req, res) {
  1464.     console.log(getDateTime() + 'Page /wiki/history chargée.');
  1465.     res.render('history.ejs', {LOCALHOST: LOCALHOST, version: version});
  1466. }); // wiki/history
  1467.  
  1468. app.get('/wiki', function(req, res) {
  1469.     console.log(getDateTime() + 'Page /wiki chargée.');
  1470.     res.render('wiki.ejs', {LOCALHOST: LOCALHOST, version: version});
  1471. }); // wiki
  1472.  
  1473. app.get('/wiki/upcoming', function(req, res) {
  1474.     console.log(getDateTime() + 'Page /wiki/upcoming chargée.');
  1475.     res.render('upcoming.ejs', {LOCALHOST: LOCALHOST, version: version});
  1476. }); // wiki/upcoming
  1477.  
  1478. app.get('/wiki/contribute', function(req, res) {
  1479.     console.log(getDateTime() + 'Page /wiki/contribute chargée.');
  1480.     res.render('contribute.ejs', {LOCALHOST: LOCALHOST, version: version});
  1481. }); // wiki/contribute
  1482.  
  1483. app.get('/wiki/game_modes', function(req, res) {
  1484.     console.log(getDateTime() + 'Page /wiki/game_modes chargée.');
  1485.     res.render('game_modes.ejs', {LOCALHOST: LOCALHOST, version: version});
  1486. }); // wiki/game_modes
  1487.  
  1488. app.get('/wiki/game_mechanics', function(req, res) {
  1489.     console.log(getDateTime() + 'Page /wiki/game_mechanics chargée.');
  1490.     res.render('game_mechanics.ejs', {LOCALHOST: LOCALHOST, version: version});
  1491. }); // wiki/game_mechanics
  1492.  
  1493. app.get('/wiki/stats', function(req, res) {
  1494.     if (MAINTENANCE == -1) {
  1495.         console.log(getDateTime() + 'Page /wiki/stats chargée.');
  1496.         connection.query('SELECT COUNT(*) AS nb FROM membres WHERE typemembre = 1 OR typemembre = 2', function (error, nombre1, fields) {
  1497.             connection.query('SELECT COUNT(*) AS nb FROM membres WHERE derniereconnexion > DATE_SUB(NOW(), INTERVAL 1 DAY)', function (error, nombre2, fields) {
  1498.                 connection.query('SELECT COUNT(*) AS nb FROM membres WHERE derniereconnexion > DATE_SUB(NOW(), INTERVAL 1 MONTH)', function (error, nombre3, fields) {
  1499.                     if (LOCALHOST == 0) { var nombre4 = guilde.memberCount; } else { var nombre4 = 0; }
  1500.                     connection.query('SELECT pays, COUNT(*) AS nb FROM membres GROUP BY pays HAVING pays != "WHO" ORDER BY nb DESC', function (error, pays, fields) {
  1501.                         res.render('stats.ejs', {LOCALHOST: LOCALHOST, version: version, nombre1: nombre1[0]['nb'], nombre2: nombre2[0]['nb'], nombre3: nombre3[0]['nb'], nombre4: nombre4, pays: pays});
  1502.                     });
  1503.                 });
  1504.             });
  1505.         });
  1506.     }
  1507.     else { res.render('maintenance.ejs', {}); }
  1508. }); // wiki/stats
  1509.  
  1510. app.get('/privacy', function(req, res) {
  1511.     console.log(getDateTime() + 'Page /privacy chargée.');
  1512.     res.render('privacy.ejs', {LOCALHOST: LOCALHOST, version: version});
  1513. }); // privacy
  1514.  
  1515. app.get('/thankyou', function(req, res) {
  1516.     console.log(getDateTime() + 'Page /thankyou chargée.');
  1517.     res.render('thankyou.ejs', {LOCALHOST: LOCALHOST, version: version});
  1518. }); // thankyou
  1519.  
  1520. app.get('/sitemap.xml', function(req, res) {
  1521.     console.log(getDateTime() + 'Page /sitemap.xml chargée.');
  1522.     sitemap.toXML( function (err, xml) {
  1523.         if (err) { return res.status(500).end(); }
  1524.         res.header('Content-Type', 'application/xml');
  1525.         res.send(xml);
  1526.     });
  1527. }); // sitemap
  1528.  
  1529. function maj_elo_multi(indice) {
  1530.     connection.query('SELECT parties.*, matches.tournoi AS mt FROM parties LEFT JOIN matches ON parties.id_match = matches.id WHERE parties.id = ?', [indice], function (error, multi, fields) {
  1531.         if (multi.length == 0) {  
  1532.             if (LOCALHOST == 0) {
  1533.                 channel = guilde.channels.find('name', 'general');
  1534.                 if (channel != undefined) { channel.send('Multiplayer ratings have been successfully recalculated! :smile:'); }
  1535.             }
  1536.             console.log(getDateTime() + "FIN CALCULS QUICKPLAY");
  1537.             maj_elo_solo(1);
  1538.         }
  1539.         else if (multi[0]['handicap'] == 0) {
  1540.             connection.query('UPDATE parties SET etat = 0 WHERE id = ?', [indice], function (error, ok, fields) {
  1541.                 maj_elo_multi(indice+1);
  1542.             });
  1543.         }
  1544.         else if (multi[0]['id_match'] > 0 && multi[0]['mt'] == 0) { maj_elo_multi(indice+1); }
  1545.         else if (multi[0]['id_match'] > 0 && multi[0]['etat'] == 0) { maj_elo_multi(indice+1); }
  1546.         else if (multi[0]['fantome1'] > 0 && multi[0]['fantome2'] > 0) {
  1547.             connection.query('SELECT etat AS duree FROM fantomes WHERE id = ?', [multi[0]['fantome1']], function (error, fantome, fields) {
  1548.                 connection.query('SELECT elo2, bonus2 FROM membres WHERE id = ?', [multi[0]['joueur2']], function (error, cl2, fields) {
  1549.                     connection.query('SELECT elo2, bonus2 FROM membres WHERE id = ?', [multi[0]['joueur1']], function (error, cl1, fields) {
  1550.                         if (fantome[0]['duree'] < 10) { maj_elo_multi(indice+1); return; }
  1551.                         var bonus1 = 0; var bonus2 = 0;
  1552.                         var resultat = 0, duree = 120;
  1553.                         var KO1 = multi[0]['KO1'], KO2 = multi[0]['KO2'];
  1554.                         if (multi[0]['etat'] != 1) {
  1555.                             if (multi[0]['deco1'] == 1 && multi[0]['deco2'] == 1) { resultat = 0.5; }
  1556.                             else if (multi[0]['deco1'] == 1)  { resultat = 1; }
  1557.                             else if (multi[0]['deco2'] == 1) { resultat = 0; }
  1558.                             else { resultat = -1; }
  1559.                         }
  1560.                         else if (KO1 == KO2 && multi[0]['lignes1'] == multi[0]['lignes2'] && multi[0]['hauteur1'] == multi[0]['hauteur2']) { resultat = 0.5; }
  1561.                         else if (KO1 == KO2 && multi[0]['lignes1'] == multi[0]['lignes2'] && multi[0]['hauteur1'] < multi[0]['hauteur2']) { resultat = 0.6; }
  1562.                         else if (KO1 == KO2 && multi[0]['lignes1'] == multi[0]['lignes2'] && multi[0]['hauteur1'] > multi[0]['hauteur2']) { resultat = 0.4; }
  1563.                         else if (KO1 == KO2 && multi[0]['lignes1'] > multi[0]['lignes2']) { resultat = 0.7; }
  1564.                         else if (KO1 == KO2 && multi[0]['lignes1'] < multi[0]['lignes2']) { resultat = 0.3; }
  1565.                         else if (KO1 < KO2) { resultat = 0.3 - 0.3*Math.min(Math.log(1+KO2-KO1)/Math.log(21), 1); }
  1566.                         else if (KO1 > KO2) { resultat = 0.7 + 0.3*Math.min(Math.log(1+KO1-KO2)/Math.log(21), 1); }
  1567.                         var nv_elo1 = Math.round(100*(cl1[0]['elo2'] + 20*(resultat - 1/(1 + Math.pow(10, (cl2[0]['elo2'] - cl1[0]['elo2'])/400)))))/100;
  1568.                         var nv_elo2 = Math.round(100*(cl2[0]['elo2'] + 20*((1-resultat) - 1/(1 + Math.pow(10, (cl1[0]['elo2'] - cl2[0]['elo2'])/400)))))/100;
  1569.                         if (nv_elo1 > cl1[0]['elo2']) {
  1570.                             bonus1 = Math.min(cl1[0]['bonus2'], nv_elo1-cl1[0]['elo2']);
  1571.                             nv_elo1 += bonus1;
  1572.                         }
  1573.                         if (nv_elo2 > cl2[0]['elo2']) {
  1574.                             bonus2 = Math.min(cl2[0]['bonus2'], nv_elo2-cl2[0]['elo2']);
  1575.                             nv_elo2 += bonus2;
  1576.                         }
  1577.                         if (resultat == -1) { maj_elo_multi(indice+1); }
  1578.                         else {
  1579.                             connection.query('SELECT COUNT(*) AS nb FROM membres WHERE elo1 > ? AND typemembre >= 1 AND typemembre <= 2 AND elo2 != 1000 AND dateinscription < ? AND id != ? AND id != ?', [nv_elo1+0.001, multi[0]['date'], multi[0]['joueur1'], multi[0]['joueur2']], function (error, nv_cl1, fields) {
  1580.                             connection.query('SELECT COUNT(*) AS nb FROM membres WHERE elo1 > ? AND typemembre >= 1 AND typemembre <= 2 AND elo2 != 1000 AND dateinscription < ? AND id != ? AND id != ?', [nv_elo2+0.001, multi[0]['date'], multi[0]['joueur1'], multi[0]['joueur2']], function (error, nv_cl2, fields) {
  1581.                             if (nv_elo2 > nv_elo1) { nv_cl1[0]['nb']++; } else { nv_cl2[0]['nb']++; }
  1582.                             connection.query('UPDATE parties SET KO1 = ?, KO2 = ?, elo1_avant = ?, elo2_avant = ?, elo1_apres = ?, elo2_apres = ?, classement1 = ?, classement2 = ? WHERE id = ?', [KO1, KO2, cl1[0]['elo2'], cl2[0]['elo2'], nv_elo1, nv_elo2, 1+nv_cl1[0]['nb'], 1+nv_cl2[0]['nb'], indice], function (error, modif1, fields) {
  1583.                                 connection.query('UPDATE membres SET elo2 = ?, bonus2 = ? WHERE id = ?', [nv_elo1, cl1[0]['bonus2']-bonus1, multi[0]['joueur1']], function (error, modif2, fields) {
  1584.                                     connection.query('UPDATE membres SET elo2 = ?, bonus2 = ? WHERE id = ?', [nv_elo2, cl2[0]['bonus2']-bonus2, multi[0]['joueur2']], function (error, modif3, fields) {
  1585.                                         connection.query('UPDATE fantomes SET elo = ?, ok = ? WHERE id = ?', [nv_elo1, 1 - multi[0]['handicap'], multi[0]['fantome1']], function (error, modif4, fields) {
  1586.                                             connection.query('UPDATE fantomes SET elo = ?, ok = ? WHERE id = ?', [nv_elo2, 1 - multi[0]['handicap'], multi[0]['fantome2']], function (error, modif5, fields) {
  1587.                                                 maj_elo_multi(indice+1);
  1588.                                             });
  1589.                                         });
  1590.                                     });
  1591.                                 });
  1592.                             });
  1593.                             });
  1594.                             });
  1595.                         }
  1596.                     });
  1597.                 });
  1598.             });
  1599.         }
  1600.         else {
  1601.             connection.query('SELECT elo2, bonus2 FROM membres WHERE id = ?', [multi[0]['joueur2']], function (error, cl2, fields) {
  1602.                 connection.query('SELECT elo2, bonus2 FROM membres WHERE id = ?', [multi[0]['joueur1']], function (error, cl1, fields) {
  1603.                     var bonus1 = 0; var bonus2 = 0;
  1604.                     var resultat = 0, duree = 120;
  1605.                     var KO1 = multi[0]['KO1'], KO2 = multi[0]['KO2'];
  1606.                     if (multi[0]['etat'] != 1) {
  1607.                         if (multi[0]['deco1'] == 1 && multi[0]['deco2'] == 1) { resultat = 0.5; }
  1608.                         else if (multi[0]['deco1'] == 1)  { resultat = 1; }
  1609.                         else if (multi[0]['deco2'] == 1) { resultat = 0; }
  1610.                         else { resultat = -1; }
  1611.                     }
  1612.                     else if (KO1 == KO2 && multi[0]['lignes1'] == multi[0]['lignes2'] && multi[0]['hauteur1'] == multi[0]['hauteur2']) { resultat = 0.5; }
  1613.                     else if (KO1 == KO2 && multi[0]['lignes1'] == multi[0]['lignes2'] && multi[0]['hauteur1'] < multi[0]['hauteur2']) { resultat = 0.6; }
  1614.                     else if (KO1 == KO2 && multi[0]['lignes1'] == multi[0]['lignes2'] && multi[0]['hauteur1'] > multi[0]['hauteur2']) { resultat = 0.4; }
  1615.                     else if (KO1 == KO2 && multi[0]['lignes1'] > multi[0]['lignes2']) { resultat = 0.7; }
  1616.                     else if (KO1 == KO2 && multi[0]['lignes1'] < multi[0]['lignes2']) { resultat = 0.3; }
  1617.                     else if (KO1 < KO2) { resultat = 0.3 - 0.3*Math.min(Math.log(1+KO2-KO1)/Math.log(21), 1); }
  1618.                     else if (KO1 > KO2) { resultat = 0.7 + 0.3*Math.min(Math.log(1+KO1-KO2)/Math.log(21), 1); }
  1619.                     var nv_elo1 = Math.round(100*(cl1[0]['elo2'] + 20*(resultat - 1/(1 + Math.pow(10, (cl2[0]['elo2'] - cl1[0]['elo2'])/400)))))/100;
  1620.                     var nv_elo2 = Math.round(100*(cl2[0]['elo2'] + 20*((1-resultat) - 1/(1 + Math.pow(10, (cl1[0]['elo2'] - cl2[0]['elo2'])/400)))))/100;
  1621.                     if (nv_elo1 > cl1[0]['elo2']) {
  1622.                         bonus1 = Math.min(cl1[0]['bonus2'], nv_elo1-cl1[0]['elo2']);
  1623.                         nv_elo1 += bonus1;
  1624.                     }
  1625.                     if (nv_elo2 > cl2[0]['elo2']) {
  1626.                         bonus2 = Math.min(cl2[0]['bonus2'], nv_elo2-cl2[0]['elo2']);
  1627.                         nv_elo2 += bonus2;
  1628.                     }
  1629.                     if (resultat == -1) { maj_elo_multi(indice+1); }
  1630.                     else {
  1631.                         connection.query('SELECT COUNT(*) AS nb FROM membres WHERE elo1 > ? AND typemembre >= 1 AND typemembre <= 2 AND elo2 != 1000 AND dateinscription < ? AND id != ? AND id != ?', [nv_elo1+0.001, multi[0]['date'], multi[0]['joueur1'], multi[0]['joueur2']], function (error, nv_cl1, fields) {
  1632.                         connection.query('SELECT COUNT(*) AS nb FROM membres WHERE elo1 > ? AND typemembre >= 1 AND typemembre <= 2 AND elo2 != 1000 AND dateinscription < ? AND id != ? AND id != ?', [nv_elo2+0.001, multi[0]['date'], multi[0]['joueur1'], multi[0]['joueur2']], function (error, nv_cl2, fields) {
  1633.                         if (nv_elo2 > nv_elo1) { nv_cl1[0]['nb']++; } else { nv_cl2[0]['nb']++; }
  1634.                         connection.query('UPDATE parties SET KO1 = ?, KO2 = ?, elo1_avant = ?, elo2_avant = ?, elo1_apres = ?, elo2_apres = ?, classement1 = ?, classement2 = ? WHERE id = ?', [KO1, KO2, cl1[0]['elo2'], cl2[0]['elo2'], nv_elo1, nv_elo2, 1+nv_cl1[0]['nb'], 1+nv_cl2[0]['nb'], indice], function (error, modif1, fields) {
  1635.                             connection.query('UPDATE membres SET elo2 = ?, bonus2 = ? WHERE id = ?', [nv_elo1, cl1[0]['bonus2']-bonus1, multi[0]['joueur1']], function (error, modif2, fields) {
  1636.                                 connection.query('UPDATE membres SET elo2 = ?, bonus2 = ? WHERE id = ?', [nv_elo2, cl2[0]['bonus2']-bonus2, multi[0]['joueur2']], function (error, modif3, fields) {
  1637.                                     connection.query('UPDATE fantomes SET elo = ?, ok = ? WHERE id = ?', [nv_elo1, 1 - multi[0]['handicap'], multi[0]['fantome1']], function (error, modif4, fields) {
  1638.                                         connection.query('UPDATE fantomes SET elo = ?, ok = ? WHERE id = ?', [nv_elo2, 1 - multi[0]['handicap'], multi[0]['fantome2']], function (error, modif5, fields) {
  1639.                                             maj_elo_multi(indice+1);
  1640.                                         });
  1641.                                     });
  1642.                                 });
  1643.                             });
  1644.                         });
  1645.                         });
  1646.                         });
  1647.                     }
  1648.                 });
  1649.             });
  1650.         }
  1651.     });
  1652. }
  1653.  
  1654. function maj_elo_solo(indice) {
  1655.     connection.query('SELECT * FROM solo WHERE id = ?', [indice], function (error, solo, fields) {
  1656.         if (solo.length == 0) {  
  1657.             if (LOCALHOST == 0) {
  1658.                 channel = guilde.channels.find('name', 'general');
  1659.                 if (channel != undefined) { channel.send('Ghostbuster ratings have been successfully recalculated! :smile:'); }
  1660.                 connection.query('SELECT fantome1, fantome2 FROM parties WHERE handicap = 1', function (error, liste, fields) {
  1661.                     for (var i = 0; i < liste.length; i++) {
  1662.                         connection.query('UPDATE fantomes SET ok = 0 WHERE id = ?', [liste[i]['fantome1']], function (error, ok1, fields) {});
  1663.                         connection.query('UPDATE fantomes SET ok = 0 WHERE id = ?', [liste[i]['fantome2']], function (error, ok1, fields) {});
  1664.                     }
  1665.                 });
  1666.             }
  1667.             console.log(getDateTime() + "FIN CALCULS GHOSTBUSTER");
  1668.         }
  1669.         else if (solo[0]['KO1'] > 40) {
  1670.             connection.query('SELECT elo1 FROM membres WHERE id = ?', [solo[0]['id_membre']], function (error, cl, fields) {
  1671.                 connection.query('UPDATE fantomes SET elo = ? WHERE id = ?', [cl[0]['elo1'], solo[0]['fantome']], function (error, modif, fields) {
  1672.                     connection.query('UPDATE solo SET etat = 0 WHERE id = ?', [indice], function (error, ok, fields) {
  1673.                         maj_elo_solo(indice+1);
  1674.                     });
  1675.                 });
  1676.             });
  1677.         }
  1678.         else if (solo[0]['fantome'] > 0) {
  1679.             connection.query('SELECT id_membre, etat AS duree FROM fantomes WHERE id = ?', [solo[0]['fantome']], function (error, fantome, fields) {
  1680.                 connection.query('SELECT id_membre, elo FROM fantomes WHERE id = ?', [solo[0]['id_partie']], function (error, adv_fantome, fields) {
  1681.                     connection.query('SELECT elo1, bonus1 FROM membres WHERE id = ?', [solo[0]['id_membre']], function (error, cl, fields) {
  1682.                         //if (fantome[0]['duree'] < 60 && solo[0]['elo1_avant'] < solo[0]['elo1_apres']) { maj_elo_solo(indice+1); return; }
  1683.                         if (fantome[0]['duree'] <= 40) {
  1684.                             connection.query('UPDATE solo SET etat = 1, elo1_avant = 0, elo1_apres = 0 WHERE id = ?', [indice], function (error, ok, fields) {
  1685.                                 maj_elo_solo(indice+1);
  1686.                             });
  1687.                             return;
  1688.                         }
  1689.                         if (fantome[0]['id_membre'] == adv_fantome[0]['id_membre']) {
  1690.                             connection.query('UPDATE solo SET etat = 0 WHERE id = ?', [indice], function (error, ok, fields) {
  1691.                                 maj_elo_solo(indice+1);
  1692.                             });
  1693.                             return;
  1694.                         }
  1695.                         if (Math.abs(adv_fantome[0]['elo']-cl[0]['elo1']) >= 200) {
  1696.                             connection.query('UPDATE solo SET etat = 0 WHERE id = ?', [indice], function (error, ok, fields) {
  1697.                                 maj_elo_solo(indice+1);
  1698.                             });
  1699.                             return;
  1700.                         }
  1701.                         var bonus = 1, duree = 120;
  1702.                         var KO2 = solo[0]['KO2'];
  1703.                         if (solo[0]['etat'] != 1) { resultat = 0; }
  1704.                         else if (solo[0]['KO1'] == KO2 && solo[0]['lignes1'] == solo[0]['lignes2'] && solo[0]['hauteur1'] == solo[0]['hauteur2']) { resultat = 0.5; }
  1705.                         else if (solo[0]['KO1'] == KO2 && solo[0]['lignes1'] == solo[0]['lignes2'] && solo[0]['hauteur1'] < solo[0]['hauteur2']) { resultat = 0.6; }
  1706.                         else if (solo[0]['KO1'] == KO2 && solo[0]['lignes1'] == solo[0]['lignes2'] && solo[0]['hauteur1'] > solo[0]['hauteur2']) { resultat = 0.4; }
  1707.                         else if (solo[0]['KO1'] == KO2 && solo[0]['lignes1'] > solo[0]['lignes2']) { resultat = 0.7; }
  1708.                         else if (solo[0]['KO1'] == KO2 && solo[0]['lignes1'] < solo[0]['lignes2']) { resultat = 0.3; }
  1709.                         else if (solo[0]['KO1'] < KO2) { resultat = 0.3 - 0.3*Math.min(Math.log(1+KO2-solo[0]['KO1'])/Math.log(21), 1); }
  1710.                         else if (solo[0]['KO1'] > KO2) { resultat = 0.7 + 0.3*Math.min(Math.log(1+solo[0]['KO1']-KO2)/Math.log(21), 1); }
  1711.                         var nv_elo1 = Math.round(100*(cl[0]['elo1'] + 20*(resultat - 1/(1 + Math.pow(10, (adv_fantome[0]['elo'] - cl[0]['elo1'])/400)))))/100;
  1712.                         var nv_elo2 = Math.round(100*(adv_fantome[0]['elo'] + 20*((1-resultat) - 1/(1 + Math.pow(10, (cl[0]['elo1'] - adv_fantome[0]['elo'])/400)))))/100;
  1713.                         if (nv_elo1 > cl[0]['elo1']) {
  1714.                             bonus = Math.min(cl[0]['bonus1'], nv_elo1-cl[0]['elo1']);
  1715.                             nv_elo1 += bonus;
  1716.                         }
  1717.                         connection.query('SELECT COUNT(*) AS nb FROM membres WHERE elo1 > ? AND typemembre >= 1 AND typemembre <= 2 AND elo1 != 1000 AND dateinscription < ? AND id != ?', [nv_elo1+0.001, solo[0]['date'], solo[0]['id_membre']], function (error, nv_cl, fields) {
  1718.                         connection.query('UPDATE solo SET KO2 = ?, elo1_avant = ?, elo2_avant = ?, elo1_apres = ?, elo2_apres = ?, classement = ? WHERE id = ?', [KO2, cl[0]['elo1'], adv_fantome[0]['elo'], nv_elo1, nv_elo2, 1+nv_cl[0]['nb'], indice], function (error, modif1, fields) {
  1719.                             connection.query('UPDATE membres SET elo1 = ?, bonus1 = ? WHERE id = ?', [nv_elo1, cl[0]['bonus1']-bonus, solo[0]['id_membre']], function (error, modif2, fields) {
  1720.                                 connection.query('UPDATE fantomes SET elo = ? WHERE id = ?', [nv_elo1, solo[0]['fantome']], function (error, modif3, fields) {
  1721.                                     connection.query('UPDATE fantomes SET elo = ? WHERE id = ?', [nv_elo2, solo[0]['id_partie']], function (error, modif4, fields) {
  1722.                                         maj_elo_solo(indice+1);
  1723.                                     });
  1724.                                 });
  1725.                             });
  1726.                         });
  1727.                         });
  1728.                     });
  1729.                 });
  1730.             });
  1731.         }
  1732.         else {
  1733.             connection.query('SELECT elo FROM fantomes WHERE id = ?', [solo[0]['id_partie']], function (error, adv_fantome, fields) {
  1734.                 connection.query('SELECT elo1, bonus1 FROM membres WHERE id = ?', [solo[0]['id_membre']], function (error, cl, fields) {
  1735.                     if (Math.abs(adv_fantome[0]['elo']-cl[0]['elo1']) >= 200) {
  1736.                         connection.query('UPDATE solo SET etat = 0 WHERE id = ?', [indice], function (error, ok, fields) {
  1737.                             maj_elo_solo(indice+1);
  1738.                         });
  1739.                         return;
  1740.                     }
  1741.                     if (solo[0]['id_membre'] == adv_fantome[0]['id_membre']) {
  1742.                         connection.query('UPDATE solo SET etat = 0 WHERE id = ?', [indice], function (error, ok, fields) {
  1743.                              maj_elo_solo(indice+1);
  1744.                         });
  1745.                         return;
  1746.                     }
  1747.                     var bonus = 0, duree = 120;
  1748.                     var KO2 = solo[0]['KO2'];
  1749.                     if (solo[0]['etat'] != 1) { resultat = 0; }
  1750.                     else if (solo[0]['KO1'] == KO2 && solo[0]['lignes1'] == solo[0]['lignes2'] && solo[0]['hauteur1'] == solo[0]['hauteur2']) { resultat = 0.5; }
  1751.                     else if (solo[0]['KO1'] == KO2 && solo[0]['lignes1'] == solo[0]['lignes2'] && solo[0]['hauteur1'] < solo[0]['hauteur2']) { resultat = 0.6; }
  1752.                     else if (solo[0]['KO1'] == KO2 && solo[0]['lignes1'] == solo[0]['lignes2'] && solo[0]['hauteur1'] > solo[0]['hauteur2']) { resultat = 0.4; }
  1753.                     else if (solo[0]['KO1'] == KO2 && solo[0]['lignes1'] > solo[0]['lignes2']) { resultat = 0.7; }
  1754.                     else if (solo[0]['KO1'] == KO2 && solo[0]['lignes1'] < solo[0]['lignes2']) { resultat = 0.3; }
  1755.                     else if (solo[0]['KO1'] < KO2) { resultat = 0.3 - 0.3*Math.min(Math.log(1+KO2-solo[0]['KO1'])/Math.log(21), 1); }
  1756.                     else if (solo[0]['KO1'] > KO2) { resultat = 0.7 + 0.3*Math.min(Math.log(1+solo[0]['KO1']-KO2)/Math.log(21), 1); }
  1757.                     var nv_elo1 = Math.round(100*(cl[0]['elo1'] + 20*(resultat - 1/(1 + Math.pow(10, (adv_fantome[0]['elo'] - cl[0]['elo1'])/400)))))/100;
  1758.                     var nv_elo2 = Math.round(100*(adv_fantome[0]['elo'] + 20*((1-resultat) - 1/(1 + Math.pow(10, (cl[0]['elo1'] - adv_fantome[0]['elo'])/400)))))/100;
  1759.                     if (nv_elo1 > cl[0]['elo1']) {
  1760.                         bonus = Math.min(cl[0]['bonus1'], nv_elo1-cl[0]['elo1']);
  1761.                         nv_elo1 += bonus;
  1762.                     }
  1763.                     connection.query('SELECT COUNT(*) AS nb FROM membres WHERE elo1 > ? AND typemembre >= 1 AND typemembre <= 2 AND elo1 != 1000 AND dateinscription < ? AND id != ?', [nv_elo1+0.001, solo[0]['date'], solo[0]['id_membre']], function (error, nv_cl, fields) {
  1764.                     connection.query('UPDATE solo SET KO2 = ?, elo1_avant = ?, elo2_avant = ?, elo1_apres = ?, elo2_apres = ?, classement = ? WHERE id = ?', [KO2, cl[0]['elo1'], adv_fantome[0]['elo'], nv_elo1, nv_elo2, indice, 1+nv_cl[0]['nb']], function (error, modif1, fields) {
  1765.                         connection.query('UPDATE membres SET elo1 = ?, bonus1 = ? WHERE id = ?', [nv_elo1, cl[0]['bonus1']-bonus, solo[0]['id_membre']], function (error, modif2, fields) {
  1766.                             connection.query('UPDATE fantomes SET elo = ? WHERE id = ?', [nv_elo1, solo[0]['fantome']], function (error, modif3, fields) {
  1767.                                 connection.query('UPDATE fantomes SET elo = ? WHERE id = ?', [nv_elo2, solo[0]['id_partie']], function (error, modif4, fields) {
  1768.                                     maj_elo_solo(indice+1);
  1769.                                 });
  1770.                             });
  1771.                         });
  1772.                     });
  1773.                     });
  1774.                 });
  1775.             });
  1776.         }
  1777.     });
  1778. }
  1779.  
  1780. app.get('/changer/elo', function(req, res) {
  1781.         if (LOCALHOST == 0) {
  1782.             channel = guilde.channels.find('name', 'general');
  1783.             if (channel != undefined) { channel.send('Ratings are currently being recalculated. Hence the game might be slowed down. Thank you for your understanding!'); }
  1784.         }
  1785.         console.log(getDateTime() + "DÉBUT RECALCULATION ELO");
  1786.         connection.query('UPDATE membres SET elo1 = 1000, elo2 = 1000, bonus1 = 200, bonus2 = 200', function (error, ok, fields) {
  1787.             connection.query('UPDATE fantomes SET elo = 1000', function (error, ok2, fields) {
  1788.                 connection.query('UPDATE parties SET joueur1 = 1, etat = 0, deco1 = 1, deco2 = 1 WHERE joueur1 = 0', function (error, ok3, fields) {
  1789.                     maj_elo_multi(1);
  1790.                     res.status(200).send('Ok, début de l\'opération.');
  1791.                 });
  1792.             });
  1793.         });
  1794. }); // changer/elo
  1795.  
  1796. function maj_sprint_pps(indice) {
  1797.     if (indice > 9000) { console.log(getDateTime() + "FIN SPRINT CALCUL"); return; }
  1798.     connection.query('SELECT id_membre, temps, fantome FROM sprint WHERE id = ?', [indice], function (error, sprint, fields) {
  1799.         if (sprint.length == 0) { maj_sprint_pps(indice+1); }
  1800.         else {
  1801.             fs.readFile(path.join(__dirname, '/parties/'+sprint[0]['fantome']+'.txt'), 'utf8', function (err, donnees) {
  1802.                 var liste = donnees.split('\n')[1];
  1803.                 var ll = liste.length;
  1804.                 var compteur = 0;
  1805.                 for (var i = 0; i < ll; i++) {
  1806.                     if (liste[i] == 's') { compteur++; }
  1807.                 }
  1808.                 connection.query('SELECT sprint FROM membres WHERE id = ?', [sprint[0]['id_membre']], function (error, sp, fields) {
  1809.                     if (sp[0]['sprint'] == 0 || sp[0]['sprint'] > sprint[0]['temps']) {
  1810.                         connection.query('UPDATE membres SET sprint = ? WHERE id = ?', [sprint[0]['temps'], sprint[0]['id_membre']], function (error, ok, fields) {});
  1811.                     }
  1812.                     connection.query('SELECT COUNT(*) AS nb FROM membres WHERE sprint < ? AND id != ? AND sprint != 0', [sprint[0]['temps']-0.00001, sprint[0]['id_membre']], function (error, nv_cl, fields) {
  1813.                         connection.query('UPDATE sprint SET blocs = ?, classement = ? WHERE id = ?', [compteur, 1 + nv_cl[0]['nb'], indice], function (error, ok, fields) { maj_sprint_pps(indice+1); });
  1814.                     });
  1815.                 });
  1816.             });  
  1817.         }
  1818.     });
  1819. }
  1820.  
  1821. function maj_survivor(indice) {
  1822.     if (indice > 9000) { console.log(getDateTime() + "FIN SURVIVOR CALCUL"); return; }
  1823.     connection.query('SELECT id_membre, temps, fantome FROM survivor WHERE id = ?', [indice], function (error, sprint, fields) {
  1824.         if (sprint.length == 0) { maj_survivor(indice+1); }
  1825.         else {
  1826.             fs.readFile(path.join(__dirname, '/parties/'+sprint[0]['fantome']+'.txt'), 'utf8', function (err, donnees) {
  1827.                 var liste = donnees.split('\n')[1];
  1828.                 var ll = liste.length;
  1829.                 var compteur = 0;
  1830.                 for (var i = 0; i < ll; i++) {
  1831.                     if (liste[i] == 's') { compteur++; }
  1832.                 }
  1833.                 connection.query('SELECT survivor FROM membres WHERE id = ?', [sprint[0]['id_membre']], function (error, sp, fields) {
  1834.                     if (sp[0]['survivor'] == 0 || sp[0]['survivor'] < sprint[0]['temps']) {
  1835.                         connection.query('UPDATE membres SET survivor = ? WHERE id = ?', [sprint[0]['temps'], sprint[0]['id_membre']], function (error, ok, fields) {});
  1836.                     }
  1837.                     connection.query('SELECT COUNT(*) AS nb FROM membres WHERE survivor < ? AND id != ? AND sprint != 0', [sprint[0]['temps']-0.00001, sprint[0]['id_membre']], function (error, nv_cl, fields) {
  1838.                         connection.query('UPDATE survivor SET classement = ? WHERE id = ?', [1 + nv_cl[0]['nb'], indice], function (error, ok, fields) { maj_survivor(indice+1); });
  1839.                     });
  1840.                 });
  1841.             });  
  1842.         }
  1843.     });
  1844. }
  1845.  
  1846. function maj_sprint10(indice) {
  1847.     if (indice > 9000) { console.log(getDateTime() + "FIN SPRINT10 CALCUL"); return; }
  1848.     connection.query('SELECT id FROM membres WHERE id = ?', [indice], function (error, verif, fields) {
  1849.         if (verif.length == 0) { maj_sprint10(indice+1); }
  1850.         else {
  1851.             connection.query('SELECT temps FROM sprint WHERE id_membre = ? ORDER BY temps LIMIT 0, 10', [indice], function (error, liste, fields) {
  1852.                 var sprint10 = 0;
  1853.                 if (liste.length == 10) {
  1854.                     for (var i = 0; i < 10; i++) {
  1855.                         sprint10 += liste[i]['temps'];
  1856.                     }
  1857.                 }
  1858.                 connection.query('UPDATE membres SET sprint10 = ? WHERE id = ?', [sprint10, indice], function (error, ok, fields) { maj_sprint10(indice+1); });
  1859.             });
  1860.         }
  1861.     });
  1862. }
  1863.  
  1864. app.get('/sprint/pps', function(req, res) {
  1865.     console.log(getDateTime() + "DÉBUT SPRINT CALCUL");
  1866.     connection.query('UPDATE membres SET sprint = 0, sprint10 = 0, survivor = 0', function (error, ok, fields) {});
  1867.     maj_sprint_pps(1);
  1868.     maj_sprint10(1);
  1869.     maj_survivor(1);
  1870.     res.status(200).send('Ok, début de l\'opération.');
  1871. }); // sprint/pps
  1872.  
  1873. app.get('/perdu/maintenance', function(req, res) {
  1874.     if (MAINTENANCE <= 0 && LOCALHOST == 0) {
  1875.         channel = guilde.channels.find('name', 'general');
  1876.         if (channel != undefined) { channel.send('Worldwide Combos is under maintenance. Sorry for that!'); }
  1877.     }
  1878.     MAINTENANCE += 10; // rajouter écriture dans fichier
  1879.     console.log(getDateTime() + "DÉBUT MAINTENANCE");
  1880.     res.status(200).send('Ok, rajout de 10 minutes.');
  1881. }); // perdu/maintenance
  1882.  
  1883. app.get('/gagne/maintenance', function(req, res) {
  1884.     if (MAINTENANCE > 0 && LOCALHOST == 0) {
  1885.         channel = guilde.channels.find('name', 'general');
  1886.         if (channel != undefined) { channel.send('You may now play Worldwide Combos again! :smiley:'); }
  1887.     }
  1888.     MAINTENANCE = 0;
  1889.     console.log(getDateTime() + "FIN MAINTENANCE");
  1890.     res.status(200).send('Ok, fin de la maintenance.');
  1891. }); // gagne/maintenance
  1892.  
  1893. app.get('/allnews', function(req, res) {
  1894.     console.log(getDateTime() + 'Page / chargée.');
  1895.     connection.query("SELECT  MID(datecreation, 1, 10) AS datecreation, titre, id FROM articles ORDER BY datecreation DESC", function(error, articles, fields) {
  1896.         res.render('allnews.ejs', {articles: articles, LOCALHOST: LOCALHOST, version: version});
  1897.     });
  1898. }); // allnews
  1899.  
  1900. app.get('/', function(req, res) {
  1901.     console.log(getDateTime() + 'Page / chargée.');
  1902.     connection.query("SELECT  MID(datecreation, 1, 10) AS datecreation, titre, id FROM articles ORDER BY datecreation DESC LIMIT 0, 5", function(error, articles, fields) {
  1903.         connection.query('SELECT pseudo, pays, elo2 FROM membres WHERE typemembre > 0 ORDER BY elo2 DESC LIMIT 0, 5', function (error, elo2, fields) {
  1904.             connection.query('SELECT * FROM tournois WHERE fini = 0 AND datedebut < NOW()', function (error, direct, fields) {
  1905.                 connection.query('SELECT * FROM tournois WHERE datedebut > NOW()', function (error, prochains, fields) {
  1906.                     res.render('index.ejs', {articles: articles, LOCALHOST: LOCALHOST, version: version, classements: elo2, direct: direct, prochains: prochains});
  1907.                 });
  1908.             });
  1909.         });
  1910.     });
  1911. }); // index
  1912.  
  1913. app.use(function(req, res, next){
  1914.     if (req.url != '/404error') { console.log(getDateTime() + 'Quelqu\'un s\'est pris une erreur 404 dans la tronche ('+req.url+').'); }
  1915.     res.render('404error.ejs', {LOCALHOST: LOCALHOST, version: version});
  1916. }); // erreur 404
  1917.  
  1918. var io = require('socket.io')(httpServer);
  1919.  
  1920. // communication avec les joueurs
  1921. io.sockets.on('connection', function (socket) {
  1922.  
  1923.     socket.classement1 = 1000;
  1924.     socket.classement2 = 1000;
  1925.     socket.pseudo = '#';
  1926.     socket.identifiant = -1;
  1927.     socket.adv = -1;
  1928.     socket.lieu = -1;
  1929.     socket.derniereFois = 0;
  1930.     socket.id_match = '#';
  1931.        
  1932.     /* DEBUT PARTIES SOLO */ {
  1933.    
  1934.     // pour vérifier que le joueur a joué jusqu'au bout
  1935.     function solo_deco() {
  1936.         connection.query('SELECT solo.id AS id, solo.id_partie AS id_partie, fantomes.elo AS elo, fantomes.nb_parties AS nb_parties FROM solo INNER JOIN fantomes on fantomes.id = solo.id_partie WHERE solo.id_membre = ? AND solo.etat = -1 AND date < DATE_SUB(NOW(), INTERVAL 2 MINUTE)', [socket.identifiant], function(error, fantome, fields) {
  1937.             if (fantome.length > 0) {
  1938.                 var nelo = Math.round(100*(socket.classement1 + 20*(0 - 1/(1 + Math.pow(10, (fantome[0]['elo'] - socket.classement1)/400)))))/100;
  1939.                 var elo_adv = Math.round(100*(fantome[0]['elo'] + 20*(1 - 1/(1 + Math.pow(10, (socket.classement1 - fantome[0]['elo'])/400)))))/100;
  1940.                 socket.classement1 = nelo;
  1941.                 connection.query('UPDATE solo SET elo2_avant = ?, elo1_apres = ?, elo2_apres = ?, etat = 0 WHERE id = ?',
  1942.                     [fantome[0]['elo'], nelo, elo_adv, fantome[0]['id']], function (error, inutile, fields) {});
  1943.                 connection.query('UPDATE fantomes SET nb_parties = ?, elo = ? WHERE id = ?', [fantome[0]['nb_parties']+1, elo_adv, fantome[0]['id_partie']], function (error, modif1, fields) {});
  1944.                 connection.query('UPDATE membres SET elo1 = ? WHERE id = ?', [nelo, socket.identifiant], function (error, modif2, fields) {});
  1945.                 socket.emit('elo_solo_cache', nelo);
  1946.             }
  1947.         });
  1948.     }
  1949.    
  1950.     // quand le joueur lance une partie solo
  1951.     socket.on('partie_solo_debut', function (message) {
  1952.         // chargement d'une partie enregistrée  
  1953.         if (socket.pseudo == '#') { socket.emit('deconnexion', ''); }
  1954.         else {
  1955.             connection.query('SELECT fantomes.id AS id, fantomes.elo AS elo, fantomes.nb_parties AS nb_parties, fantomes.ligne_suppl, membres.pseudo AS pseudo, membres.pays AS pays FROM fantomes INNER JOIN membres ON fantomes.id_membre = membres.id INNER JOIN solo ON solo.fantome = fantomes.id WHERE fantomes.etat >= ? AND fantomes.ok = 1 AND fantomes.id_membre != ? ORDER BY ABS(?+50*?-elo) LIMIT 0, 10',
  1956.             [Math.min(600, 60*socket.duree_solo), socket.identifiant, socket.classement1, socket.handicap_solo], function (error, liste, fields) {
  1957.                 liste.sort(function(a, b) {
  1958.                     if (a['nb_parties'] < b['nb_parties']) { return -1; }
  1959.                     else if (a['nb_parties'] > b['nb_parties']) { return 1; }
  1960.                     else { return 0; }
  1961.                 });
  1962.                 socket.adv = liste[0]['id'];
  1963.                 connection.query('INSERT INTO solo(id_membre, id_partie, handicap, KO1, KO2, lignes1, lignes2, hauteur1, hauteur2, date, elo1_avant, elo2_avant, elo1_apres, elo2_apres, etat) VALUES(?,?,?,?,?,?,?,?,?,NOW(),?,?,?,?,?)',
  1964.                 [socket.identifiant, liste[0]['id'], socket.handicap_solo, 0, 0, 0, 0, 0, 0, socket.classement1, liste[0]['elo'], 0, 0, -1], function (error, np, fields) { console.log(error);
  1965.                     socket.solo = np.insertId;
  1966.                     console.log(getDateTime() + socket.pseudo + ' commence une partie solo contre ' + liste[0]['pseudo'] + ' (id : ' + liste[0]['id'] + ', elo : ' + liste[0]['elo'] + ')');
  1967.                     fs.readFile(path.join(__dirname, '/parties/'+liste[0]['id']+'.txt'), 'utf8', function (err,donnees) {
  1968.                         socket.emit('partie_solo_debut', {donnees: donnees, pseudo_adv: liste[0]['pseudo'], elo_adv: liste[0]['elo']-50*socket.handicap_solo, pays_adv: liste[0]['pays'], ligne_suppl: liste[0]['ligne_suppl']});
  1969.                         setTimeout(solo_deco, 60000*socket.duree+12000);
  1970.                     });  
  1971.                 });
  1972.             });
  1973.         }
  1974.     });
  1975.    
  1976.     // quand la partie solo vient de finir
  1977.     socket.on('partie_solo_fin', function (message) {
  1978.         if ('mdp' in message && 'pseudo' in message) {
  1979.             var mdp = crypto.createHash('sha1');
  1980.             var entree = escapeHtml(message['mdp'].toString()), pseudo = escapeHtml(message['pseudo'].toString());
  1981.             mdp.update('combo'+entree);
  1982.             var res_mdp = mdp.digest('hex');
  1983.             connection.query('SELECT * FROM membres WHERE pseudo = ? AND mdp = ?', [pseudo, res_mdp], function (error, verdict, fields) {
  1984.                 if (verdict.length == 0) { socket.emit('deconnexion', ''); return 0; }
  1985.                 else if (verdict.length == 1) {
  1986.                     socket.pseudo = verdict[0]['pseudo'];
  1987.                     socket.fuseau = verdict[0]['fuseau'];
  1988.                     socket.classement1 = verdict[0]['elo1'];
  1989.                     socket.classement2 = verdict[0]['elo2'];
  1990.                     socket.identifiant = verdict[0]['id'];
  1991.                     socket.pays = verdict[0]['pays'];
  1992.                     socket.typemembre = verdict[0]['typemembre'];
  1993.                     socket.email = verdict[0]['email'];
  1994.                     socket.sprint = verdict[0]['sprint'];
  1995.                     socket.sprint10 = verdict[0]['sprint10'];
  1996.                     socket.survivor = verdict[0]['survivor'];
  1997.                     socket.mdp = verdict[0]['mdp'];
  1998.                     socket.duree_solo = verdict[0]['duree_solo'];
  1999.                     socket.limite_ko_solo = verdict[0]['limite_ko_solo'];
  2000.                     socket.handicap_solo = verdict[0]['handicap_solo'];
  2001.                     socket.ligne_suppl = verdict[0]['ligne_suppl'];
  2002.                     connection.query('SELECT elo2_avant, handicap FROM solo WHERE id = ?', [socket.solo], function (error, elo, fields) {
  2003.                         if (elo.length == 0) { return; }
  2004.                         var ancien_elo = elo[0]['elo2_avant'];
  2005.                         var type_handicap = elo[0]['handicap'];
  2006.                         var resultat = 0, duree = 40*Math.ceil(message['chrono']/40);
  2007.                         if (message['res_match'] == 0) {
  2008.                             //if ((1 + message['KO1']+Math.floor((message['chrono']-1)/40)) > message['KO2']) { duree = Math.max(duree, 120); }
  2009.                             var KO2 = Math.max(message['KO2'], 21 + message['KO1']);
  2010.                             var KO1 = message['KO1'];
  2011.                         }
  2012.                         else if (message['res_match'] == 1) {
  2013.                             //if ((1 + message['KO2']+Math.floor((message['chrono']-1)/40)) > message['KO1']) { duree = Math.max(duree, 120); }
  2014.                             var KO1 = Math.max(message['KO1'], 21 + message['KO2']);
  2015.                             var KO2 = message['KO2'];
  2016.                         }
  2017.                         else { KO1 = message['KO1']; KO2 = message['KO2']; }
  2018.                         if (KO1 == KO2 && message['lignes1'] == message['lignes2'] && message['hauteur1'] == message['hauteur2']) { resultat = 0.5; }
  2019.                         else if (KO1 == KO2 && message['lignes1'] == message['lignes2'] && message['hauteur1'] < message['hauteur2']) { resultat = 0.6; }
  2020.                         else if (KO1 == KO2 && message['lignes1'] == message['lignes2'] && message['hauteur1'] > message['hauteur2']) { resultat = 0.4; }
  2021.                         else if (KO1 == KO2 && message['lignes1'] > message['lignes2']) { resultat = 0.7; }
  2022.                         else if (KO1 == KO2 && message['lignes1'] < message['lignes2']) { resultat = 0.3; }
  2023.                         else if (KO1 < KO2) { resultat = 0.3 - 0.3*Math.min(Math.log(1+KO2-KO1)/Math.log(21), 1); }
  2024.                         else if (KO1 > KO2) { resultat = 0.7 + 0.3*Math.min(Math.log(1+KO1-KO2)/Math.log(21), 1); }
  2025.                         var nv_elo1 = Math.round(100*(socket.classement1 + 20*(resultat - 1/(1 + Math.pow(10, (ancien_elo - socket.classement1)/400)))))/100;
  2026.                         var nv_elo2 = Math.round(100*(ancien_elo + 20*((1-resultat) - 1/(1 + Math.pow(10, (socket.classement1 - ancien_elo)/400)))))/100;
  2027.                         if (socket.duree_solo != 2 || socket.limite_ko_solo != 0) { nv_elo1 = socket.classement1; nv_elo2 = ancien_elo; }
  2028.                         /*else if (KO1 < KO2) { resultat = 0.3 - 0.3*Math.min((KO2-KO1)/Math.ceil((message['chrono']-1)/40), 1); }
  2029.                         else if (KO1 > KO2) { resultat = 0.7 + 0.3*Math.min((KO1-KO2)/Math.ceil((message['chrono']-1)/40), 1); }
  2030.                         var nv_elo1 = Math.round(100*(socket.classement2 + 7*(1 + Math.sqrt(duree+120)/210)*Math.log(1.2+Math.max(2/3, duree/60))*(resultat - 1/(1 + Math.pow(10, (ancien_elo - socket.classement2)/400)))))/100;
  2031.                         var nv_elo2 = Math.round(100*(ancien_elo + 7*(1 + Math.sqrt(duree+120)/210)*Math.log(1.2+Math.max(2/3, duree/60))*((1-resultat) - 1/(1 + Math.pow(10, (socket.classement2 - ancien_elo)/400)))))/100;*/
  2032.                         connection.query('INSERT INTO fantomes(elo, id_membre, ligne_suppl, etat, ok) VALUES(?,?,?,?,?)', [nv_elo1, socket.identifiant, socket.ligne_suppl, message['chrono'], 1-Math.max(type_handicap, 1)], function (error, id_max, fields) {
  2033.                             fs.writeFile(path.join(__dirname, '/parties/'+id_max.insertId+'.txt'), message['Partie'], function(err) {
  2034.                                 console.log(getDateTime() + 'Partie ghostbuster de ' + socket.pseudo + ' enregistrée dans ' + path.join(__dirname, '/parties/'+id_max.insertId+'.txt'));
  2035.                             });
  2036.                             connection.query('SELECT bonus1 FROM membres WHERE id = ?', [socket.identifiant], function (error, b1, fields) {
  2037.                                 if (nv_elo1 > socket.classement2) { var bonus1 = Math.min(b1[0]['bonus1'], nv_elo1 - socket.classement1); } else { var bonus1 = 0; }
  2038.                                 connection.query('UPDATE membres SET elo1 = ?, bonus1 = ? WHERE id = ?', [nv_elo1+bonus1, b1[0]['bonus2']-bonus1, socket.identifiant], function (error, rien, fields) {
  2039.                                     connection.query('SELECT COUNT(*) AS nb FROM membres WHERE elo1 > ? AND typemembre >= 1 AND typemembre <= 2 AND id != ? AND id != ?', [nv_elo1+bonus1+0.001, socket.identifiant, socket.adv], function (error, nv_cl, fields) {
  2040.                                         if (nv_elo2 > nv_elo1) { nv_cl[0]['nb']++; }
  2041.                                         connection.query('UPDATE solo SET KO1 = ?, KO2 = ?, lignes1 = ?, lignes2 = ?, hauteur1 = ?, hauteur2 = ?, elo1_apres = ?, elo2_apres = ?, etat = 1, fantome = ?, classement = ? WHERE id = ?',
  2042.                                         [KO1, KO2, message['lignes1'], message['lignes2'], message['hauteur1'], message['hauteur2'], nv_elo1+bonus1, nv_elo2, id_max.insertId, nv_cl[0]['nb'], socket.solo], function (error, inutile, fields) {  
  2043.                                             socket.classement1 = nv_elo1+bonus1;
  2044.                                             socket.emit('partie_multi_fin', {res: resultat, joueur1: nv_elo1+bonus1, joueur2: nv_elo2, bonus1: bonus1, bonus2: 0});
  2045.                                             //socket.broadcast.to(socket.lieu).emit('partie_multi_fin', {res: message['res_match'], joueur2: nelo, joueur1: elo_adv, bonus1: bonus2, bonus2: bonus1});
  2046.                                             socket.leave(socket.lieu);    
  2047.                                             delete direct[socket.lieu];
  2048.                                             socket.lieu = -1;
  2049.                                         });
  2050.                                     });
  2051.                                 });
  2052.                             });
  2053.                         });
  2054.                     });  
  2055.                 }
  2056.             });
  2057.         }
  2058.     });
  2059.    
  2060.     // fin d'une partie de sprint
  2061.     socket.on('fin_sprint', function (infos) { // c'est moyen la sécurité là
  2062.         if (socket.pseudo == '#') { socket.emit('deconnexion', ''); }
  2063.         else if ('temps' in infos && 'Partie' in infos && 'blocs' in infos) {
  2064.             connection.query('INSERT INTO fantomes(elo, id_membre, etat, ok, ligne_suppl) VALUES(1000,?,?,0,?)', [socket.identifiant, Math.floor(infos['temps']/1000), socket.ligne_suppl], function (error, fini, fields) {
  2065.                 fs.writeFile(path.join(__dirname, '/parties/'+fini.insertId+'.txt'), infos['Partie'], function(err) {
  2066.                     console.log(getDateTime() + 'Partie sprint de ' + socket.pseudo + ' (' + infos['temps']/1000 + ') enregistrée dans ' + path.join(__dirname, '/parties/'+fini.insertId+'.txt'));
  2067.                 });
  2068.                 connection.query('SELECT COUNT(*) AS nb FROM membres WHERE sprint < ? AND typemembre >= 1 AND typemembre <= 2 AND id != ?', [infos['temps']-0.00001, socket.identifiant], function (error, nv_cl, fields) {
  2069.                     connection.query('INSERT INTO sprint(id_membre, temps, blocs, date, classement, fantome) VALUES(?, ?, ?, NOW(), ?, ?)', [socket.identifiant, infos['temps'], infos['blocs'], nv_cl[0]['nb']+1, fini.insertId], function (error, ok, fields) {});
  2070.                 });
  2071.                 connection.query('SELECT temps FROM sprint WHERE id_membre = ? ORDER BY temps LIMIT 0, 10', [socket.identifiant], function (error, liste, fields) {
  2072.                     socket.sprint10 = 0;
  2073.                     if (liste.length == 10) {
  2074.                         for (var i = 0; i < 10; i++) {
  2075.                             socket.sprint10 += liste[i]['temps'];
  2076.                         }
  2077.                     }
  2078.                     connection.query('UPDATE membres SET sprint10 = ? WHERE id = ?', [socket.sprint10, socket.identifiant], function (error, ok, fields) {});
  2079.                     if (socket.sprint == 0 || socket.sprint > infos['temps']) {
  2080.                         connection.query('UPDATE membres SET sprint = ? WHERE id = ?', [infos['temps'], socket.identifiant], function (error, ok, fields) {
  2081.                             console.log(getDateTime() + 'Nouveau record ! ' + infos['temps']/1000);
  2082.                             socket.sprint = infos['temps'];
  2083.                         });
  2084.                     }
  2085.                 });
  2086.             });
  2087.         }
  2088.     });
  2089.    
  2090.     socket.on('fin_survivor', function (infos) {
  2091.         if (socket.pseudo == '#') { socket.emit('deconnexion', ''); }
  2092.         else if (socket.pseudo != 'itzmist' && 'temps' in infos && 'Partie' in infos) {
  2093.             connection.query('INSERT INTO fantomes(elo, id_membre, etat, ok, ligne_suppl) VALUES(1000,?,?,0,?)', [socket.identifiant, Math.floor(infos['temps']/1000), socket.ligne_suppl], function (error, fini, fields) {
  2094.                 fs.writeFile(path.join(__dirname, '/parties/'+fini.insertId+'.txt'), infos['Partie'], function(err) {
  2095.                     console.log(getDateTime() + 'Partie survivor de ' + socket.pseudo  + ' (' + infos['temps']/1000 + ') enregistrée dans ' + path.join(__dirname, '/parties/'+fini.insertId+'.txt'));
  2096.                 });
  2097.                 connection.query('SELECT COUNT(*) AS nb FROM membres WHERE survivor > ? AND typemembre >= 1 AND typemembre <= 2 AND id != ?', [infos['temps']+0.00001, socket.identifiant], function (error, nv_cl, fields) {
  2098.                     connection.query('INSERT INTO survivor(id_membre, temps, date, fantome, classement, division) VALUES(?, ?, NOW(), ?, ?, 1)', [socket.identifiant, infos['temps'], nv_cl[0]['nb']+1, fini.insertId], function (error, ok, fields) {});
  2099.                 });
  2100.                 if (socket.survivor == 0 || socket.survivor < infos['temps']) {
  2101.                     connection.query('UPDATE membres SET survivor = ? WHERE id = ?', [infos['temps'], socket.identifiant], function (error, ok, fields) {
  2102.                         console.log(getDateTime() + 'Nouveau record ! ' + infos['temps']/1000);
  2103.                         socket.survivor = infos['temps'];
  2104.                     });
  2105.                 }
  2106.             });
  2107.         }
  2108.     });
  2109.    
  2110.     } /* FIN PARTIES SOLO */
  2111.    
  2112.     /* DEBUT FILE D'ATTENTE */ {
  2113.    
  2114.     socket.on('entrer_queue', function (message) {
  2115.         if (socket.pseudo == '#') {
  2116.             socket.emit('deconnexion', '');
  2117.         }
  2118.         else if (!(socket.pseudo in queue))  {
  2119.             socket.lieu = 0;
  2120.             console.log(getDateTime() + 'Entrée de ' + socket.pseudo + ' dans la file d\'attente.');
  2121.             queue[socket.pseudo] = socket;
  2122.             queue[socket.pseudo].derniereFois = Date.now();
  2123.             queue[socket.pseudo].tempsAttente = 0;
  2124.             queue[socket.pseudo].pret = 0;
  2125.             queue[socket.pseudo].adversaire = '';
  2126.             message_discord('quickplay', ':flag_'+cp[socket.pays]+': '+queue[socket.pseudo].pseudo + ' ('+socket.classement2+') entered the queue.');
  2127.         }
  2128.     });
  2129.    
  2130.     socket.on('joueurs_quickplay', function () {
  2131.         var total = 0, minimum = 40;
  2132.         for (var x in queue) {
  2133.             if (x == socket.pseudo) { continue; }
  2134.             total++;
  2135.             minimum = Math.min(minimum, Math.floor(Math.abs(queue[x].classement2-socket.classement2)/10));
  2136.         }
  2137.         connection.query("SELECT COUNT(*) AS nb FROM parties WHERE parties.etat = -1 AND parties.id_match = 0", function (error, nb, fields) {
  2138.             socket.emit('joueurs_quickplay', {total: total+2*nb[0]['nb'], minimum: minimum});
  2139.         });
  2140.     });
  2141.    
  2142.     // quand le joueur se barre de la queue
  2143.     socket.on('quitter_queue', function (message) {
  2144.         if (socket.pseudo in queue) {
  2145.             message_discord('quickplay', ':flag_'+cp[socket.pays]+': '+queue[socket.pseudo].pseudo+' left the queue.');
  2146.             delete queue[socket.pseudo];
  2147.             //delete qc[socket.pseudo];
  2148.             //if (socket.lieu == 0) { socket.lieu = -1; }
  2149.             console.log(getDateTime() + 'Départ de ' + socket.pseudo + ' de la file d\'attente.');
  2150.             //socket.broadcast.to('queue').emit('partant_queue', socket.pseudo);
  2151.             //socket.leave('queue');
  2152.         }
  2153.     });
  2154.    
  2155.     // tirage au sort des prochains blocs
  2156.     function tirage() {
  2157.         var blocs = '';
  2158.         for (i = 0; i < 100; i++) {
  2159.             var sac = melanger(['0', '1', '2', '3', '4', '5', '6']);
  2160.             for(j = 0; j < 7; j++) { blocs += sac[j]; }
  2161.         }
  2162.         return blocs;
  2163.     }
  2164.    
  2165.     function nouvelle_partie(joueur1, joueur2) {
  2166.         delete queue[joueur1.pseudo];
  2167.         delete queue[joueur2.pseudo];
  2168.         var j1 = {}, j2 = {};
  2169.         j1['typePartie'] = 2;
  2170.         j1['pseudo'] = joueur1.pseudo;
  2171.         j1['pays'] = joueur1.pays;
  2172.         j1['classement2'] = joueur1.classement2;
  2173.         j2['typePartie'] = 1;
  2174.         j2['pseudo'] = joueur2.pseudo;
  2175.         j2['pays'] = joueur2.pays;
  2176.         j2['classement2'] = joueur2.classement2;
  2177.         j1['maintenant'] = Date.now();
  2178.         j2['maintenant'] = Date.now();
  2179.         socket.adv = joueur2.pseudo;
  2180.         socket.adv_elo = joueur2.classement2;
  2181.         socket.adv_contact = joueur2;
  2182.         message_discord('quickplay', ':flag_'+cp[joueur1.pays]+': '+joueur1.pseudo+' left the queue.');
  2183.         message_discord('quickplay', ':flag_'+cp[joueur2.pays]+': '+joueur2.pseudo+' left the queue.');
  2184.         // générer les blocs à refaire
  2185.         var blocs = tirage();
  2186.         socket.adv_contact.emit('liste_blocs_multi', blocs);
  2187.         socket.emit('liste_blocs_multi', blocs);
  2188.         connection.query('INSERT INTO parties(id_match, joueur1, joueur2, handicap, KO1, KO2, lignes1, lignes2, hauteur1, hauteur2, date, elo1_avant, elo2_avant, elo1_apres, elo2_apres, etat) VALUES(?,?,?,?,?,?,?,?,?,?,NOW(),?,?,?,?,?)',
  2189.         [socket.id_match, socket.identifiant, joueur2.identifiant, 1, 0, 0, 0, 0, 0, 0, socket.classement2, joueur2.classement2, 0, 0, -1], function (error, inutile, fields) {
  2190.             socket.lieu = inutile.insertId;
  2191.             direct[socket.lieu] = new Array('', new Array(), new Array(), Date.now(), 2, 0, 1, -1, 0, 0);
  2192.             socket.join(socket.lieu);
  2193.             console.log(getDateTime() + 'Début de la partie entre ' + socket.pseudo +  ' et ' + socket.adv + ' (lieu : ' + socket.lieu + ').');
  2194.             socket.emit('valeur_lieu_partie', socket.lieu);
  2195.             j1['lieu'] = socket.lieu;
  2196.             j2['lieu'] = socket.lieu;
  2197.             joueur1.emit('nouvelle_partie', j2);
  2198.             joueur2.emit('nouvelle_partie', j1);
  2199.             setTimeout(multi_deco, 132000);
  2200.             socket.typejoueur = 1;
  2201.             message_discord('quickplay', 'A new Quickplay round is starting between :flag_' + cp[socket.pays] + ': ' + socket.pseudo +  ' (' + socket.classement2 + ') and :flag_' + cp[joueur2.pays] + ': ' + socket.adv + ' (' + socket.adv_elo.toFixed(2) + ').\nLink: https://www.worldwide-combos.com/live?t=q&id='+socket.lieu+'.');
  2202.         });
  2203.     }
  2204.    
  2205.     // pour vérifier que le joueur est toujours là
  2206.     socket.on('toujours_en_queue', function(message) {
  2207.         if (socket.pseudo in queue) {
  2208.             queue[socket.pseudo].derniereFois = Date.now();
  2209.             if (queue[socket.pseudo].adversaire != '') {
  2210.                 queue[socket.pseudo].pret = 1;
  2211.                 if (queue[queue[socket.pseudo].adversaire].pret == 1) {
  2212.                     nouvelle_partie(queue[socket.pseudo], queue[queue[socket.pseudo].adversaire]);
  2213.                 }
  2214.             }
  2215.             //socket.emit('liste_queue', {liste: qc, classement: qc[socket.pseudo]['classement']});
  2216.         }
  2217.         else if (socket.pseudo != '#') {
  2218.             socket.lieu = 0;
  2219.             console.log(getDateTime() + 'Entrée de ' + socket.pseudo + ' dans la file d\'attente.');
  2220.             queue[socket.pseudo] = socket;
  2221.             queue[socket.pseudo].derniereFois = Date.now();
  2222.             queue[socket.pseudo].tempsAttente = 0;
  2223.             queue[socket.pseudo].pret = 0;
  2224.             queue[socket.pseudo].adversaire = '';
  2225.             message_discord('quickplay', ':flag_'+cp[socket.pays]+': '+queue[socket.pseudo].pseudo + ' ('+socket.classement2+') entered the queue.');
  2226.         }
  2227.     });
  2228.    
  2229.     // OBSOLETE quand le joueur a un adversaire potentiel
  2230.     socket.on('proposition_partie_multi', function (adversaire) {
  2231.         if (socket.id_match == '#' && (socket.pseudo == '#' || !(socket.pseudo in queue))) { socket.emit('deconnexion', ''); }
  2232.         else if (socket.id_match != '#' && adversaire['pseudo'] in match_socket) {
  2233.             socket.adv = adversaire['pseudo'];
  2234.             socket.adv_contact = match_socket[adversaire['pseudo']];
  2235.             console.log(getDateTime() + socket.pseudo + ' tente de commencer une manche avec ' + adversaire['pseudo']);
  2236.             match_socket[adversaire['pseudo']].emit('proposition_partie_multi', {pseudo: socket.pseudo, pays: adversaire['pays'], longueurPartie: adversaire['longueurPartie'], limite_ko: adversaire['limite_ko'], handicap: adversaire['handicap']});
  2237.         }
  2238.         else if (adversaire['pseudo'] in queue) {
  2239.             socket.adv = adversaire['pseudo'];
  2240.             socket.adv_pays = adversaire['pays'];
  2241.             socket.adv_elo = adversaire['adv_elo'];
  2242.             socket.adv_contact = queue[adversaire['pseudo']];
  2243.             console.log(getDateTime() + socket.pseudo + ' tente de lancer une partie avec ' + adversaire['pseudo']);
  2244.             queue[adversaire['pseudo']].emit('proposition_partie_multi', {pseudo: socket.pseudo, pays: adversaire['pays'], longueurPartie: adversaire['longueurPartie'], limite_ko: adversaire['limite_ko'], handicap: adversaire['handicap']});
  2245.         }
  2246.     });
  2247.    
  2248.     // OBSOLETE quand ça a réussi
  2249.     socket.on('proposition_partie_multi_succes', function (infos) {
  2250.         if (socket.id_match != '#') {
  2251.             socket.lieu = infos['lieu'];
  2252.             socket.join(infos['lieu']);
  2253.             delete match_socket[socket.pseudo];
  2254.             direct[socket.lieu][0] = infos['blocs'];
  2255.             socket.adv_contact.emit('liste_blocs_multi', {blocs: infos['blocs']});
  2256.             connection.query('UPDATE parties SET joueur1 = ?, elo1_avant = ? WHERE id = ?', [socket.identifiant, socket.classement2, socket.lieu], function (error, inutile, fields) {  
  2257.                 connection.query('UPDATE matches SET debutmanche = NOW() WHERE id = ?', [socket.id_match], function (error, maj, fields) {    
  2258.                     socket.typejoueur = 1;
  2259.                     console.log(getDateTime() + 'Début de la manche entre ' + socket.pseudo +  ' et ' + socket.adv + ' (lieu : ' + socket.lieu + ').');
  2260.                 });
  2261.             });
  2262.         }
  2263.         else if (socket.pseudo in queue) {
  2264.             socket.lieu = infos['lieu'];
  2265.             socket.join(socket.lieu);
  2266.             if (LOCALHOST == 0) {
  2267.                 channel = guilde.channels.find('name', 'quickplay');
  2268.                 if (channel != undefined) { channel.send(':flag_'+cp[socket.pays]+': '+queue[socket.pseudo].pseudo + ' left the queue.'); }
  2269.             }
  2270.             delete queue[socket.pseudo];
  2271.             delete qc[socket.pseudo];
  2272.             direct[socket.lieu][0] = infos['blocs'];
  2273.             socket.adv_contact.emit('liste_blocs_multi', {blocs: infos['blocs']});
  2274.             connection.query('UPDATE parties SET joueur1 = ?, elo1_avant = ? WHERE id = ?', [socket.identifiant, socket.classement2, socket.lieu], function (error, inutile, fields) {  
  2275.                 socket.broadcast.to('queue').emit('partant_queue', socket.pseudo);
  2276.                 socket.typejoueur = 1;
  2277.                 console.log(getDateTime() + 'Début de la partie entre ' + socket.pseudo +  ' et ' + socket.adv + ' (lieu : ' + socket.lieu + ').');
  2278.                 socket.leave('queue');
  2279.             });
  2280.         }
  2281.     });
  2282.    
  2283.     // message dans Discord pour dire que ça va commencer (match)
  2284.     socket.on('message_debut_partie_match', function (infos) {
  2285.         if (LOCALHOST == 0) {
  2286.             connection.query('SELECT tournoi FROM matches WHERE id = ?', [socket.id_match], function (error, idt, fields) {
  2287.                 if (idt.length == 1 && idt[0]['tournoi'] == 0) {
  2288.                     channel = guilde.channels.find('name', 'live-scores');
  2289.                     if (channel != undefined) { channel.send('**LIVE UPDATE** Custom match\n:flag_' + cp[socket.pays] + ': ' + socket.pseudo + ' ' + infos['score1'] + ' - ' + infos['score2'] + ' :flag_' + cp[infos['pays']] + ': ' + socket.adv + '\nLink: https://www.worldwide-combos.com/live?t=m&id='+socket.id_match+'.'); }
  2290.                 }
  2291.                 else {
  2292.                     connection.query('SELECT nom FROM tournois WHERE id = ?', [idt[0]['tournoi']], function (error, trn, fields) {
  2293.                         if (trn.length == 1) {
  2294.                             channel = guilde.channels.find('name', 'live-scores');
  2295.                             if (channel != undefined) { channel.send('**LIVE UPDATE** '+trn[0]['nom']+'\n:flag_' + cp[socket.pays] + ': ' + socket.pseudo + ' ' + infos['score1'] + ' - ' + infos['score2'] + ' :flag_' + cp[infos['pays']] + ': ' + socket.adv + '\nLink: https://www.worldwide-combos.com/live?t=m&id='+socket.id_match+'.'); }
  2296.                         }
  2297.                     });
  2298.                 }
  2299.             });
  2300.         }
  2301.     });
  2302.    
  2303.     // OBSOLETE réponse à une demande
  2304.     socket.on('reponse_partie_multi', function (reponse) {
  2305.         if (socket.id_match != '#' && reponse['verdict'] == 1) {
  2306.             socket.adv_lp = reponse['longueurPartie'];
  2307.             connection.query('INSERT INTO parties(id_match, joueur1, joueur2, handicap, KO1, KO2, lignes1, lignes2, hauteur1, hauteur2, date, elo1_avant, elo2_avant, elo1_apres, elo2_apres, etat) VALUES(?,?,?,?,?,?,?,?,?,?,NOW(),?,?,?,?,?)',
  2308.             [socket.id_match, 0, socket.identifiant, reponse['handicap'], 0, 0, 0, 0, 0, 0, 0, socket.classement2, 0, 0, -1], function (error, inutile, fields) {
  2309.                 socket.lieu = inutile.insertId;
  2310.                 direct[socket.lieu] = new Array('', new Array(), new Array(), Date.now(), reponse['longueurPartie'], reponse['limite_ko'], reponse['handicap'], socket.id_match, 0, 0);
  2311.                 socket.join(socket.lieu);
  2312.                 socket.adv = reponse['adversaire'];
  2313.                 socket.adv_contact = match_socket[reponse['adversaire']];
  2314.                 delete match_socket[socket.pseudo];
  2315.                 console.log(getDateTime() + 'Réponse positive de ' + socket.pseudo + ' à ' + socket.adv);
  2316.                 match_socket[reponse['adversaire']].emit('reponse_partie_multi', socket.lieu);
  2317.                 socket.emit('valeur_lieu_partie', socket.lieu);
  2318.                 var maintenant = Date.now();
  2319.                 socket.adv_contact.emit('debut_partie_multi', {debut: maintenant+7000, pays: socket.pays});
  2320.                 socket.emit('debut_partie_multi', {debut: maintenant+7000, pays: reponse['pays']});
  2321.                 setTimeout(multi_deco, socket.adv_lp*60000+12000);
  2322.                 socket.typejoueur = 2;
  2323.             });
  2324.         }
  2325.         else if (socket.pseudo in queue && reponse['adversaire'] in queue && reponse['verdict'] == 1) {
  2326.             //socket.adv_lp = reponse['longueurPartie'];
  2327.             connection.query('INSERT INTO parties(joueur1, joueur2, KO1, KO2, lignes1, lignes2, hauteur1, hauteur2, date, elo1_avant, elo2_avant, elo1_apres, elo2_apres, etat) VALUES(?,?,?,?,?,?,?,?,NOW(),?,?,?,?,?)',
  2328.             [0, socket.identifiant, 0, 0, 0, 0, 0, 0, 0, socket.classement2, 0, 0, -1], function (error, inutile, fields) {
  2329.                 socket.lieu = inutile.insertId;
  2330.                 /* 0 : blocs
  2331.                 1 : joueur 1
  2332.                 2 : joueur 2
  2333.                 3 : date de début
  2334.                 4 : durée
  2335.                 5 : limite KO
  2336.                 6 : type handicap
  2337.                 7 : id match
  2338.                 8 : score joueur 1
  2339.                 9 : score joueur 2 */
  2340.                 direct[socket.lieu] = new Array('', new Array(), new Array(), Date.now(), reponse['longueurPartie'], reponse['limite_ko'], reponse['handicap'], 0, 0, 0);
  2341.                 socket.join(socket.lieu);
  2342.                 socket.adv = reponse['adversaire'];
  2343.                 socket.adv_contact = queue[reponse['adversaire']];
  2344.                 if (LOCALHOST == 0) {
  2345.                     channel = guilde.channels.find('name', 'quickplay');
  2346.                     if (channel != undefined) { channel.send(':flag_'+cp[socket.pays]+': '+queue[socket.pseudo].pseudo + ' left the queue.'); }
  2347.                 }
  2348.                 delete queue[socket.pseudo];
  2349.                 delete qc[socket.pseudo];
  2350.                 console.log(getDateTime() + 'Réponse positive de ' + socket.pseudo + ' à ' + socket.adv);
  2351.                 queue[reponse['adversaire']].emit('reponse_partie_multi', socket.lieu);
  2352.                 socket.emit('valeur_lieu_partie', socket.lieu);
  2353.                 var maintenant = Date.now();
  2354.                 socket.adv_contact.emit('debut_partie_multi', {debut: maintenant+7000, pays: socket.pays});
  2355.                 socket.emit('debut_partie_multi', {debut: maintenant+7000, pays: reponse['pays']});
  2356.                 setTimeout(multi_deco, socket.adv_lp*60000+12000);
  2357.                 socket.leave('queue');  
  2358.                 socket.typejoueur = 2;
  2359.                 socket.broadcast.to('queue').emit('partant_queue', socket.pseudo);        
  2360.             });
  2361.         }
  2362.         else if (queue[reponse['adversaire']] != undefined) { queue[reponse['adversaire']].emit('reponse_partie_multi', 0); }
  2363.     });
  2364.     } /* FIN FILE D'ATTENTE */
  2365.    
  2366.     /* DEBUT PARTIE MULTIJOUEUR */ {
  2367.     // quand on communique pendant une partie... une petite fonction pour l'homme, un bond de géant pour Worldwide Combos
  2368.     socket.on('partie_multi_infos', function (infos) {
  2369.         if (socket.lieu in direct && socket.typejoueur in direct[socket.lieu]) {
  2370.             direct[socket.lieu][socket.typejoueur].push(infos);
  2371.             socket.broadcast.to(socket.lieu).emit('partie_multi_infos', infos);
  2372.         }
  2373.         else if ('type' in infos && 'lieu' in infos) {
  2374.             socket.lieu = infos['lieu'];
  2375.             socket.join(socket.lieu);
  2376.             console.log(getDateTime() + socket.lieu + '-' + infos['type']);
  2377.             if (socket.lieu in direct) {
  2378.                 console.log('ok reconnexion');
  2379.                 if (infos['type'] == 1 || infos['type'] == 6) { socket.typejoueur = 1; socket.emit('infos_reconnection', direct[socket.lieu][2]); }
  2380.                 else { socket.typejoueur = 2; socket.emit('infos_reconnection', direct[socket.lieu][1]); }
  2381.                 direct[socket.lieu][socket.typejoueur].push(infos);
  2382.                 socket.broadcast.to(socket.lieu).emit('partie_multi_infos', infos);
  2383.             }
  2384.         }
  2385.     });
  2386.    
  2387.     // affichage des parties avec une place de libre
  2388.     socket.on('liste_libre_custom', function() {
  2389.         connection.query('SELECT matches.*, m1.pays AS pays1, m1.pseudo AS pseudo1, m1.coeff_force AS coeff_force1 FROM matches INNER JOIN membres AS m1 ON m1.id = matches.joueur1  WHERE matches.confirmation = 3 AND matches.debutmanche > NOW() AND matches.tournoi = 0 AND matches.prive = 0 AND matches.joueur1 != ? ORDER BY coeff_force1 DESC', [socket.identifiant], function (error, mc, fields) {
  2390.             socket.emit('liste_libre_custom', mc);      
  2391.         });
  2392.     });
  2393.    
  2394.     // affichage de la liste des directs
  2395.     socket.on('liste_directs', function() {
  2396.         liste = {};
  2397.         var okt = 0, okc = 0, okq = 0;
  2398.         connection.query("SELECT id, nom FROM tournois WHERE fini = 0", function (error, tournois, fields) {
  2399.             var ok = 0;
  2400.             for (var i = 0; i < tournois.length; i++) {
  2401.                 liste[tournois[i]['id']] = {nom: tournois[i]['nom'], matches: {}};
  2402.                 connection.query('SELECT ? AS indice FROM articles WHERE id = 1', [i], function (error, indice, fields) {
  2403.                     connection.query('SELECT matches.*, m1.pays AS pays1, m2.pays AS pays2, m1.pseudo AS pseudo1, m2.pseudo AS pseudo2 FROM matches INNER JOIN membres AS m1 ON m1.id = matches.joueur1  INNER JOIN membres AS m2 ON m2.id = matches.joueur2 WHERE matches.confirmation = 1 AND matches.debutmanche < DATE_ADD(NOW(), INTERVAL 10 MINUTE) AND matches.tournoi = ? AND matches.prive = 0', [tournois[indice[0]['indice']]['id']], function (error, mt, fields) {
  2404.                         liste[tournois[indice[0]['indice']]['id']]['matches'] = mt;
  2405.                         ok++;
  2406.                         if (ok == tournois.length) { okt = 1; }
  2407.                         if (okt == 1 && okc == 1 && okq == 1) { socket.emit('liste_directs', liste); }
  2408.                     });
  2409.                 });
  2410.             }
  2411.             if (tournois.length == 0) { okt = 1; }
  2412.         });
  2413.         liste[0] = {nom: "Custom games", matches: {}};
  2414.         liste[-1] = {nom: "Quickplay games", matches: {}};
  2415.         connection.query('SELECT matches.*, m1.pays AS pays1, m2.pays AS pays2, m1.pseudo AS pseudo1, m2.pseudo AS pseudo2 FROM matches INNER JOIN membres AS m1 ON m1.id = matches.joueur1  INNER JOIN membres AS m2 ON m2.id = matches.joueur2 WHERE matches.confirmation = 1 AND matches.debutmanche < DATE_ADD(NOW(), INTERVAL 10 MINUTE) AND matches.tournoi = 0 AND matches.prive = 0', function (error, mc, fields) {
  2416.             liste[0]['matches'] = mc;
  2417.             okc = 1;  
  2418.             if (okt == 1 && okc == 1 && okq == 1) { socket.emit('liste_directs', liste); }      
  2419.         });
  2420.         connection.query("SELECT parties.*, m1.elo2 AS elo1, m2.elo2 AS elo2, m1.pays AS pays1, m2.pays AS pays2, m1.elo2 AS elo1_avant, m2.elo2 AS elo2_avant, m1.pseudo AS pseudo1, m2.pseudo AS pseudo2, parties.id AS id FROM parties INNER JOIN membres AS m1 ON m1.id = parties.joueur1  INNER JOIN membres AS m2 ON m2.id = parties.joueur2 WHERE parties.etat = -1 AND parties.id_match = 0", function (error, pq, fields) {
  2421.             liste[-1]['matches'] = pq;
  2422.             okq = 1;  
  2423.             if (okt == 1 && okc == 1 && okq == 1) { socket.emit('liste_directs', liste); }      
  2424.         });
  2425.     });
  2426.    
  2427.     // quand quelqu'un s'apprête à regarder une partie en direct
  2428.     socket.on('regarder_direct', function(infos) {
  2429.         if ('id' in infos && 'type' in infos) {
  2430.             var id_partie = escapeHtml(infos['id'].toString()), type = escapeHtml(infos['type'].toString());
  2431.             if (type == 'q' && id_partie in direct) { // Quickplay
  2432.                 socket.join(id_partie);                
  2433.                 socket.emit('infos_direct', direct[id_partie]);
  2434.             }
  2435.             else if (type == 'm') { // Custom
  2436.                 connection.query('SELECT id FROM parties WHERE id_match = ? ORDER BY date DESC LIMIT 0, 1', [id_partie], function (error, verdict, fields) {
  2437.                     connection.query("SELECT m1.pays AS pays1, m2.pays AS pays2, m1.elo2 AS elo1_avant, m2.elo2 AS elo2_avant, m1.pseudo AS pseudo1, m2.pseudo AS pseudo2, matches.*, IF(debutmanche > NOW(), 1, 0) AS statut FROM matches LEFT JOIN membres AS m1 ON m1.id = matches.joueur1 LEFT JOIN membres AS m2 ON m2.id = matches.joueur2 WHERE matches.confirmation > 0 AND matches.id = ?", [id_partie], function (error, verif, fields) {
  2438.                         if (verdict.length == 1 && verif.length == 1 && verdict[0]['id'] in direct) {
  2439.                             socket.join(verdict[0]['id']);
  2440.                             socket.emit('infos_direct', direct[verdict[0]['id']]);
  2441.                             socket.emit('score_direct', {score1: verif[0]['score1'], score2: verif[0]['score2']});
  2442.                         }
  2443.                         else if (verif.length == 1) { socket.emit('pas_encore_commence', verif[0]); }
  2444.                     });
  2445.                 });
  2446.             }
  2447.         }
  2448.     });
  2449.    
  2450.     socket.on('verifier_attente_direct', function(idp) {
  2451.         var id_partie = parseInt(escapeHtml(idp.toString()));
  2452.         connection.query('SELECT id FROM parties WHERE id_match = ? ORDER BY date DESC LIMIT 0, 1', [id_partie], function (error, verdict, fields) {
  2453.             if (verdict.length == 1 && verdict[0]['id'] in direct) { socket.emit('fin_attente_direct', ''); }
  2454.         });
  2455.     });
  2456.    
  2457.     // le joueur 1 fait enregistrer les scores
  2458.     socket.on('partie_multi_fin_1', function (message) {
  2459.         if ('mdp' in message && 'pseudo' in message) {
  2460.             var mdp = crypto.createHash('sha1');
  2461.             var entree = escapeHtml(message['mdp'].toString()), pseudo = escapeHtml(message['pseudo'].toString());
  2462.             mdp.update('combo'+entree);
  2463.             var res_mdp = mdp.digest('hex');
  2464.             connection.query('SELECT * FROM membres WHERE pseudo = ? AND mdp = ?', [pseudo, res_mdp], function (error, verdict, fields) {
  2465.                 if (verdict.length == 0) { socket.emit('deconnexion', ''); return 0; }
  2466.                 else if (verdict.length == 1) {
  2467.                     socket.pseudo = verdict[0]['pseudo'];
  2468.                     socket.fuseau = verdict[0]['fuseau'];
  2469.                     socket.classement1 = verdict[0]['elo1'];
  2470.                     socket.classement2 = verdict[0]['elo2'];
  2471.                     socket.identifiant = verdict[0]['id'];
  2472.                     socket.pays = verdict[0]['pays'];
  2473.                     socket.typemembre = verdict[0]['typemembre'];
  2474.                     socket.email = verdict[0]['email'];
  2475.                     socket.sprint = verdict[0]['sprint'];
  2476.                     socket.sprint10 = verdict[0]['sprint10'];
  2477.                     socket.survivor = verdict[0]['survivor'];
  2478.                     socket.mdp = verdict[0]['mdp'];
  2479.                     socket.duree_solo = verdict[0]['duree_solo'];
  2480.                     socket.handicap_solo = verdict[0]['handicap_solo'];
  2481.                     socket.ligne_suppl = verdict[0]['ligne_suppl'];
  2482.                     // fin de partie (à modifier pour la sécurité)
  2483.                     // faudra penser à la sauvegarde, un jour
  2484.                     connection.query('SELECT elo2_avant, handicap FROM parties WHERE id = ?', [socket.lieu], function (error, elo, fields) {
  2485.                         if (elo.length == 0) { return; }
  2486.                         var ancien_elo = elo[0]['elo2_avant'];
  2487.                         var type_handicap = elo[0]['handicap'];
  2488.                         var resultat = 0, duree = 40*Math.ceil(message['chrono']/40);
  2489.                         if (message['res_match'] == 0) {
  2490.                             //if ((1 + message['KO1']+Math.floor((message['chrono']-1)/40)) > message['KO2']) { duree = Math.max(duree, 120); }
  2491.                             var KO2 = Math.max(message['KO2'], 21 + message['KO1']);
  2492.                             var KO1 = message['KO1'];
  2493.                         }
  2494.                         else if (message['res_match'] == 1) {
  2495.                             //if ((1 + message['KO2']+Math.floor((message['chrono']-1)/40)) > message['KO1']) { duree = Math.max(duree, 120); }
  2496.                             var KO1 = Math.max(message['KO1'], 21 + message['KO2']);
  2497.                             var KO2 = message['KO2'];
  2498.                         }
  2499.                         else { KO1 = message['KO1']; KO2 = message['KO2']; }
  2500.                         if (KO1 == KO2 && message['lignes1'] == message['lignes2'] && message['hauteur1'] == message['hauteur2']) { resultat = 0.5; }
  2501.                         else if (KO1 == KO2 && message['lignes1'] == message['lignes2'] && message['hauteur1'] < message['hauteur2']) { resultat = 0.6; }
  2502.                         else if (KO1 == KO2 && message['lignes1'] == message['lignes2'] && message['hauteur1'] > message['hauteur2']) { resultat = 0.4; }
  2503.                         else if (KO1 == KO2 && message['lignes1'] > message['lignes2']) { resultat = 0.7; }
  2504.                         else if (KO1 == KO2 && message['lignes1'] < message['lignes2']) { resultat = 0.3; }
  2505.                         else if (KO1 < KO2) { resultat = 0.3 - 0.3*Math.min(Math.log(1+KO2-KO1)/Math.log(21), 1); }
  2506.                         else if (KO1 > KO2) { resultat = 0.7 + 0.3*Math.min(Math.log(1+KO1-KO2)/Math.log(21), 1); }
  2507.                         var nv_elo1 = Math.round(100*(socket.classement2 + 20*(resultat - 1/(1 + Math.pow(10, (ancien_elo - socket.classement2)/400)))))/100;
  2508.                         var nv_elo2 = Math.round(100*(ancien_elo + 20*((1-resultat) - 1/(1 + Math.pow(10, (socket.classement2 - ancien_elo)/400)))))/100;
  2509.                         /*else if (KO1 < KO2) { resultat = 0.3 - 0.3*Math.min((KO2-KO1)/Math.ceil((message['chrono']-1)/40), 1); }
  2510.                         else if (KO1 > KO2) { resultat = 0.7 + 0.3*Math.min((KO1-KO2)/Math.ceil((message['chrono']-1)/40), 1); }
  2511.                         var nv_elo1 = Math.round(100*(socket.classement2 + 7*(1 + Math.sqrt(duree+120)/210)*Math.log(1.2+Math.max(2/3, duree/60))*(resultat - 1/(1 + Math.pow(10, (ancien_elo - socket.classement2)/400)))))/100;
  2512.                         var nv_elo2 = Math.round(100*(ancien_elo + 7*(1 + Math.sqrt(duree+120)/210)*Math.log(1.2+Math.max(2/3, duree/60))*((1-resultat) - 1/(1 + Math.pow(10, (socket.classement2 - ancien_elo)/400)))))/100;*/
  2513.                         connection.query('INSERT INTO fantomes(elo, id_membre, ligne_suppl, etat, ok) VALUES(?,?,?,?,?)', [nv_elo1, socket.identifiant, socket.ligne_suppl, message['chrono'], 1-type_handicap], function (error, id_max, fields) {
  2514.                             fs.writeFile(path.join(__dirname, '/parties/'+id_max.insertId+'.txt'), message['Partie'], function(err) {
  2515.                                 console.log(getDateTime() + 'Partie de ' + socket.pseudo + ' enregistrée dans ' + path.join(__dirname, '/parties/'+id_max.insertId+'.txt'));
  2516.                             });
  2517.                             connection.query('SELECT bonus2 FROM membres WHERE id = ?', [socket.identifiant], function (error, b1, fields) {
  2518.                                 if (nv_elo1 > socket.classement2) { var bonus1 = Math.min(b1[0]['bonus2'], nv_elo1 - socket.classement2); } else { var bonus1 = 0; }
  2519.                                 connection.query('SELECT bonus2 FROM membres WHERE pseudo = ?', [socket.adv], function (error, b2, fields) {
  2520.                                     if (nv_elo2 > ancien_elo) { var bonus2 = Math.min(b2[0]['bonus2'], nv_elo2 - ancien_elo); } else { var bonus2 = 0; }
  2521.                                     connection.query('UPDATE membres SET elo2 = ?, bonus2 = ? WHERE id = ?', [nv_elo1+bonus1, b1[0]['bonus2']-bonus1, socket.identifiant], function (error, rien, fields) {
  2522.                                         connection.query('SELECT COUNT(*) AS nb FROM membres WHERE elo2 > ? AND typemembre >= 1 AND typemembre <= 2 AND id != ? AND id != ?', [nv_elo1+bonus1+0.001, socket.identifiant, socket.adv], function (error, nv_cl, fields) {
  2523.                                             if (nv_elo2 > nv_elo1) { nv_cl[0]['nb']++; }
  2524.                                             connection.query('UPDATE parties SET KO1 = ?, KO2 = ?, lignes1 = ?, lignes2 = ?, hauteur1 = ?, hauteur2 = ?, elo1_apres = ?, etat = 1, fantome1 = ?, classement1 = ? WHERE id = ?',
  2525.                                             [KO1, KO2, message['lignes1'], message['lignes2'], message['hauteur1'], message['hauteur2'], nv_elo1+bonus1, id_max.insertId, nv_cl[0]['nb'], socket.lieu], function (error, inutile, fields) {  
  2526.                                                 socket.classement2 = nv_elo1+bonus1;
  2527.                                                 socket.emit('partie_multi_fin', {res: resultat, joueur1: nv_elo1, joueur2: nv_elo2, bonus1: bonus1, bonus2: bonus2});
  2528.                                                 //socket.broadcast.to(socket.lieu).emit('partie_multi_fin', {res: message['res_match'], joueur2: nelo, joueur1: elo_adv, bonus1: bonus2, bonus2: bonus1});
  2529.                                                 socket.leave(socket.lieu);    
  2530.                                                 console.log(getDateTime() + 'Partie ' + socket.lieu + ' sauvegardée');
  2531.                                                 delete direct[socket.lieu];
  2532.                                                 socket.lieu = -1;
  2533.                                             });
  2534.                                         });
  2535.                                     });
  2536.                                 });
  2537.                             });
  2538.                         });
  2539.                     });  
  2540.                 }
  2541.             });
  2542.         }
  2543.         else {  socket.emit('deconnexion', ''); }
  2544.     });
  2545.    
  2546.    
  2547.     // manche_fin_1, joueur 1 à la fin d'une manche
  2548.     socket.on('manche_fin_1', function (message) {
  2549.         if ('mdp' in message && 'pseudo' in message) {
  2550.             var mdp = crypto.createHash('sha1');
  2551.             var entree = escapeHtml(message['mdp'].toString()), pseudo = escapeHtml(message['pseudo'].toString());
  2552.             mdp.update('combo'+entree);
  2553.             var res_mdp = mdp.digest('hex');
  2554.             connection.query('SELECT * FROM membres WHERE pseudo = ? AND mdp = ?', [pseudo, res_mdp], function (error, verdict, fields) {
  2555.                 if (verdict.length == 0) { socket.emit('deconnexion', ''); return 0; }
  2556.                 else if (verdict.length == 1) {
  2557.                     socket.pseudo = verdict[0]['pseudo'];
  2558.                     socket.fuseau = verdict[0]['fuseau'];
  2559.                     socket.classement1 = verdict[0]['elo1'];
  2560.                     socket.classement2 = verdict[0]['elo2'];
  2561.                     socket.identifiant = verdict[0]['id'];
  2562.                     socket.pays = verdict[0]['pays'];
  2563.                     socket.typemembre = verdict[0]['typemembre'];
  2564.                     socket.email = verdict[0]['email'];
  2565.                     socket.sprint = verdict[0]['sprint'];
  2566.                     socket.sprint10 = verdict[0]['sprint10'];
  2567.                     socket.survivor = verdict[0]['survivor'];
  2568.                     socket.mdp = verdict[0]['mdp'];
  2569.                     socket.duree_solo = verdict[0]['duree_solo'];
  2570.                     socket.handicap_solo = verdict[0]['handicap_solo'];
  2571.                     socket.ligne_suppl = verdict[0]['ligne_suppl'];
  2572.                     connection.query('SELECT id_match FROM parties WHERE id = ?', [socket.lieu], function (error, res, fields) {
  2573.                         if (res.length == 1) {
  2574.                             socket.id_match = res[0]['id_match'];
  2575.                             connection.query('UPDATE matches SET debutmanche = DATE_ADD(NOW(), INTERVAL 21 SECOND) WHERE id = ?', [socket.id_match], function (error, md, fields) {});
  2576.                             if (message['res_match'] > 0.5) {
  2577.                                 connection.query('UPDATE matches SET score1 = score1 + 1 WHERE id = ?', [socket.id_match], function (error, md, fields) {});
  2578.                             }
  2579.                             connection.query('INSERT INTO fantomes(elo, id_membre, ligne_suppl, etat) VALUES(?,?,?,?)', [socket.classement2, socket.identifiant, socket.ligne_suppl, message['chrono']], function (error, id_max, fields) {
  2580.                                 fs.writeFile(path.join(__dirname, '/parties/'+id_max.insertId+'.txt'), message['Partie'], function(err) {
  2581.                                     console.log(getDateTime() + 'Partie de ' + socket.pseudo + ' enregistrée dans ' + path.join(__dirname, '/parties/'+id_max.insertId+'.txt'));
  2582.                                 });
  2583.                                 connection.query('UPDATE parties SET KO1 = ?, KO2 = ?, lignes1 = ?, lignes2 = ?, hauteur1 = ?, hauteur2 = ?, elo1_apres = ?, etat = 1, fantome1 = ? WHERE id = ?',
  2584.                                 [message['KO1'], message['KO2'], message['lignes1'], message['lignes2'], message['hauteur1'], message['hauteur2'], socket.classement2, id_max.insertId, socket.lieu], function (error, inutile, fields) {  
  2585.                                     socket.leave(socket.lieu);        
  2586.                                     connection.query('SELECT * FROM matches WHERE id = ?', [socket.id_match], function (error, infos, fields) {
  2587.                                         if (verif_match_termine(infos[0]) == 0) { socket.emit('manche_fin', ''); }
  2588.                                         else {
  2589.                                             connection.query('SELECT joueur1, joueur2, score1, score2, matches.tournoi, membres.pays AS adv_pays FROM matches LEFT JOIN membres ON membres.id = matches.joueur2 WHERE matches.id = ?', [socket.id_match], function (error, donnees, fields) {
  2590.                                                 connection.query('UPDATE matches SET confirmation = 2 WHERE id = ?', [socket.id_match], function (error, fini, fields) {
  2591.                                                     console.log(getDateTime() + 'Fin du match!');
  2592.                                                     if (LOCALHOST == 0) {
  2593.                                                         if (donnees[0]['tournoi'] == 0) {
  2594.                                                             channel = guilde.channels.find('name', 'live-scores');
  2595.                                                             if (channel != undefined) { channel.send('**MATCH ENDED** Custom match\n:flag_' + cp[socket.pays] + ': ' + socket.pseudo + ' ' + donnees[0]['score1'] + ' - ' + donnees[0]['score2'] + ' :flag_' + cp[donnees[0]['adv_pays']] + ': ' + socket.adv + '\nMatch report: https://www.worldwide-combos.com/match?id='+socket.id_match+'.'); }
  2596.                                                         }
  2597.                                                         else {
  2598.                                                             connection.query('SELECT nom FROM tournois WHERE id = ?', [donnees[0]['tournoi']], function (error, trn, fields) {
  2599.                                                                 if (trn.length == 1) {
  2600.                                                                     channel = guilde.channels.find('name', 'live-scores');
  2601.                                                                     if (channel != undefined) { channel.send('**MATCH ENDED** '+trn[0]['nom']+'\n:flag_' + cp[socket.pays] + ': ' + socket.pseudo + ' ' + donnees[0]['score1'] + ' - ' + donnees[0]['score2'] + ' :flag_' + cp[donnees[0]['adv_pays']] + ': ' + socket.adv + '\nMatch report: https://www.worldwide-combos.com/match?id='+socket.id_match+'.'); }
  2602.                                                                 }
  2603.                                                             });
  2604.                                                         }
  2605.                                                     }
  2606.                                                     socket.emit('fin_match', donnees[0]);
  2607.                                                 });
  2608.                                             });
  2609.                                         }
  2610.                                     });
  2611.                                     console.log(getDateTime() + 'Partie ' + socket.lieu + ' sauvegardée');
  2612.                                     delete direct[socket.lieu];
  2613.                                     socket.lieu = -1;
  2614.                                 });
  2615.                             });
  2616.                         }
  2617.                     });
  2618.                 }
  2619.             });
  2620.         }
  2621.         else {  socket.emit('deconnexion', ''); }
  2622.     });
  2623.    
  2624.     // le joueur 2 enregistre quelques données également
  2625.     socket.on('partie_multi_fin_2', function (message) {
  2626.         console.log(message['KO1'], message['KO2']);
  2627.         if ('mdp' in message && 'pseudo' in message) {
  2628.             var mdp = crypto.createHash('sha1');
  2629.             var entree = escapeHtml(message['mdp'].toString()), pseudo = escapeHtml(message['pseudo'].toString());
  2630.             mdp.update('combo'+entree);
  2631.             var res_mdp = mdp.digest('hex');
  2632.             connection.query('SELECT * FROM membres WHERE pseudo = ? AND mdp = ?', [pseudo, res_mdp], function (error, verdict, fields) {
  2633.                 if (verdict.length == 0) { socket.emit('deconnexion', ''); return 0; }
  2634.                 else if (verdict.length == 1) {
  2635.                     socket.pseudo = verdict[0]['pseudo'];
  2636.                     socket.fuseau = verdict[0]['fuseau'];
  2637.                     socket.classement1 = verdict[0]['elo1'];
  2638.                     socket.classement2 = verdict[0]['elo2'];
  2639.                     socket.identifiant = verdict[0]['id'];
  2640.                     socket.pays = verdict[0]['pays'];
  2641.                     socket.typemembre = verdict[0]['typemembre'];
  2642.                     socket.email = verdict[0]['email'];
  2643.                     socket.sprint = verdict[0]['sprint'];
  2644.                     socket.sprint10 = verdict[0]['sprint10'];
  2645.                     socket.survivor = verdict[0]['survivor'];
  2646.                     socket.mdp = verdict[0]['mdp'];
  2647.                     socket.duree_solo = verdict[0]['duree_solo'];
  2648.                     socket.handicap_solo = verdict[0]['handicap_solo'];
  2649.                     socket.ligne_suppl = verdict[0]['ligne_suppl'];
  2650.                     // fin de partie (à modifier pour la sécurité)
  2651.                     connection.query('SELECT pseudo, elo1_avant, handicap FROM parties LEFT JOIN membres ON membres.id = parties.joueur1 WHERE parties.id = ?', [socket.lieu], function (error, elo, fields) {
  2652.                         if (elo.length == 0) { return; }
  2653.                         socket.adv = elo[0]['pseudo'];
  2654.                         var ancien_elo = elo[0]['elo1_avant'];
  2655.                         var type_handicap = elo[0]['handicap'];
  2656.                         var resultat = 0, duree = 40*Math.ceil(message['chrono']/40);
  2657.                          if (message['res_match'] == 0) {
  2658.                             //if ((1 + message['KO1']+Math.floor((message['chrono']-1)/40)) > message['KO2']) { duree = Math.max(duree, 120); }
  2659.                             var KO2 = Math.max(message['KO2'], 21 + message['KO1']);
  2660.                             var KO1 = message['KO1'];
  2661.                         }
  2662.                         else if (message['res_match'] == 1) {
  2663.                             //if ((1 + message['KO2']+Math.floor((message['chrono']-1)/40)) > message['KO1']) { duree = Math.max(duree, 120); }
  2664.                             var KO1 = Math.max(message['KO1'], 21 + message['KO2']);
  2665.                             var KO2 = message['KO2'];
  2666.                         }
  2667.                         else { KO1 = message['KO1']; KO2 = message['KO2']; }
  2668.                         if (KO1 == KO2 && message['lignes1'] == message['lignes2'] && message['hauteur1'] == message['hauteur2']) { resultat = 0.5; }
  2669.                         else if (KO1 == KO2 && message['lignes1'] == message['lignes2'] && message['hauteur1'] < message['hauteur2']) { resultat = 0.6; }
  2670.                         else if (KO1 == KO2 && message['lignes1'] == message['lignes2'] && message['hauteur1'] > message['hauteur2']) { resultat = 0.4; }
  2671.                         else if (KO1 == KO2 && message['lignes1'] > message['lignes2']) { resultat = 0.7; }
  2672.                         else if (KO1 == KO2 && message['lignes1'] < message['lignes2']) { resultat = 0.3; }
  2673.                         else if (KO1 < KO2) { resultat = 0.3 - 0.3*Math.min(Math.log(1+KO2-KO1)/Math.log(21), 1); }
  2674.                         else if (KO1 > KO2) { resultat = 0.7 + 0.3*Math.min(Math.log(1+KO1-KO2)/Math.log(21), 1); }
  2675.                         var nv_elo1 = Math.round(100*(socket.classement2 + 20*(resultat - 1/(1 + Math.pow(10, (ancien_elo - socket.classement2)/400)))))/100;
  2676.                         var nv_elo2 = Math.round(100*(ancien_elo + 20*((1-resultat) - 1/(1 + Math.pow(10, (socket.classement2 - ancien_elo)/400)))))/100;
  2677.                         /*else if (KO1 < KO2) { resultat = 0.3 - 0.3*Math.min((KO2-KO1)/Math.ceil((message['chrono']-1)/40), 1); }
  2678.                         else if (KO1 > KO2) { resultat = 0.7 + 0.3*Math.min((KO1-KO2)/Math.ceil((message['chrono']-1)/40), 1); }
  2679.                         var nv_elo1 = Math.round(100*(socket.classement2 + 7*(1 + Math.sqrt(duree+120)/210)*Math.log(1.2+Math.max(2/3, duree/60))*(resultat - 1/(1 + Math.pow(10, (ancien_elo - socket.classement2)/400)))))/100;
  2680.                         var nv_elo2 = Math.round(100*(ancien_elo + 7*(1 + Math.sqrt(duree+120)/210)*Math.log(1.2+Math.max(2/3, duree/60))*((1-resultat) - 1/(1 + Math.pow(10, (socket.classement2 - ancien_elo)/400)))))/100;*/
  2681.                         connection.query('INSERT INTO fantomes(elo, id_membre, ligne_suppl, etat, ok) VALUES(?,?,?,?,?)', [nv_elo1, socket.identifiant, socket.ligne_suppl, message['chrono'], 1-type_handicap], function (error, id_max, fields) {
  2682.                             fs.writeFile(path.join(__dirname, '/parties/'+id_max.insertId+'.txt'), message['Partie'], function(err) {
  2683.                                 console.log(getDateTime() + 'Partie de ' + socket.pseudo + ' enregistrée dans ' + path.join(__dirname, '/parties/'+id_max.insertId+'.txt'));
  2684.                             });
  2685.                             connection.query('SELECT bonus2 FROM membres WHERE id = ?', [socket.identifiant], function (error, b1, fields) {
  2686.                                 if (nv_elo1 > socket.classement2) { var bonus1 = Math.min(b1[0]['bonus2'], nv_elo1 - socket.classement2); } else { var bonus1 = 0; }
  2687.                                 connection.query('SELECT bonus2 FROM membres WHERE pseudo = ?', [socket.adv], function (error, b2, fields) {
  2688.                                     if (nv_elo2 > ancien_elo) { var bonus2 = Math.min(b2[0]['bonus2'], nv_elo2 - ancien_elo); } else { var bonus2 = 0; }
  2689.                                     connection.query('UPDATE membres SET elo2 = ?, bonus2 = ? WHERE id = ?', [nv_elo1+bonus1, b1[0]['bonus2']-bonus1, socket.identifiant], function (error, rien, fields) {
  2690.                                         connection.query('SELECT COUNT(*) AS nb FROM membres WHERE elo2 > ? AND typemembre >= 1 AND typemembre <= 2 AND id != ? AND id != ?', [nv_elo1+bonus1+0.001, socket.identifiant, socket.adv], function (error, nv_cl, fields) {
  2691.                                             if (nv_elo2 > nv_elo1) { nv_cl[0]['nb']++; }
  2692.                                             connection.query('UPDATE parties SET elo2_apres = ?, fantome2 = ?, classement2 = ? WHERE id = ?', [nv_elo1+bonus1, id_max.insertId, nv_cl[0]['nb'], socket.lieu], function (error, rien2, fields) {
  2693.                                                 socket.leave(socket.lieu);
  2694.                                                 socket.lieu = -1;
  2695.                                                 socket.classement2 = nv_elo1+bonus1;
  2696.                                                 socket.emit('partie_multi_fin', {res: message['res_match'], joueur1: nv_elo1, joueur2: nv_elo2, bonus1: bonus1, bonus2: bonus2});
  2697.                                             });
  2698.                                         });
  2699.                                     });
  2700.                                 });
  2701.                             });
  2702.                         });
  2703.                     });
  2704.                 }
  2705.             });
  2706.         }
  2707.         else {  socket.emit('deconnexion', ''); }
  2708.     });
  2709.    
  2710.     // le joueur 2 enregistre quelques données également
  2711.     socket.on('manche_fin_2', function (message) {
  2712.         if ('mdp' in message && 'pseudo' in message) {
  2713.             var mdp = crypto.createHash('sha1');
  2714.             var entree = escapeHtml(message['mdp'].toString()), pseudo = escapeHtml(message['pseudo'].toString());
  2715.             mdp.update('combo'+entree);
  2716.             var res_mdp = mdp.digest('hex');
  2717.             connection.query('SELECT * FROM membres WHERE pseudo = ? AND mdp = ?', [pseudo, res_mdp], function (error, verdict, fields) {
  2718.                 if (verdict.length == 0) { socket.emit('deconnexion', ''); return 0; }
  2719.                 else if (verdict.length == 1) {
  2720.                     socket.pseudo = verdict[0]['pseudo'];
  2721.                     socket.fuseau = verdict[0]['fuseau'];
  2722.                     socket.classement1 = verdict[0]['elo1'];
  2723.                     socket.classement2 = verdict[0]['elo2'];
  2724.                     socket.identifiant = verdict[0]['id'];
  2725.                     socket.pays = verdict[0]['pays'];
  2726.                     socket.typemembre = verdict[0]['typemembre'];
  2727.                     socket.email = verdict[0]['email'];
  2728.                     socket.sprint = verdict[0]['sprint'];
  2729.                     socket.sprint10 = verdict[0]['sprint10'];
  2730.                     socket.survivor = verdict[0]['survivor'];
  2731.                     socket.mdp = verdict[0]['mdp'];
  2732.                     socket.duree_solo = verdict[0]['duree_solo'];
  2733.                     socket.handicap_solo = verdict[0]['handicap_solo'];
  2734.                     connection.query('SELECT id_match FROM parties WHERE id = ?', [socket.lieu], function (error, res, fields) {
  2735.                         if (res.length == 1) {
  2736.                             socket.id_match = res[0]['id_match'];
  2737.                             if (message['res_match'] > 0.5) {
  2738.                                 connection.query('UPDATE matches SET score2 = score2 + 1 WHERE id = ?', [socket.id_match], function (error, md, fields) {});
  2739.                             }
  2740.                             // fin de partie (à modifier pour la sécurité)
  2741.                             connection.query('INSERT INTO fantomes(elo, id_membre, ligne_suppl, etat) VALUES(?,?,?,?)', [socket.classement2, socket.identifiant, socket.ligne_suppl, message['chrono']], function (error, id_max, fields) {
  2742.                                 fs.writeFile(path.join(__dirname, '/parties/'+id_max.insertId+'.txt'), message['Partie'], function(err) {
  2743.                                     console.log(getDateTime() + 'Partie de ' + socket.pseudo + ' enregistrée dans ' + path.join(__dirname, '/parties/'+id_max.insertId+'.txt'));
  2744.                                 });
  2745.                                 connection.query('UPDATE parties SET elo2_apres = ?, fantome2 = ? WHERE id = ?', [socket.classement2, id_max.insertId, socket.lieu], function (error, rien2, fields) {
  2746.                                     socket.leave(socket.lieu);
  2747.                                     socket.lieu = -1;
  2748.                                     connection.query('SELECT * FROM matches WHERE id = ?', [socket.id_match], function (error, infos, fields) {
  2749.                                         if (verif_match_termine(infos[0]) == 0) { socket.emit('manche_fin', ''); }
  2750.                                         else {
  2751.                                             connection.query('SELECT joueur1, joueur2, score1, score2 FROM matches WHERE id = ?', [socket.id_match], function (error, donnees, fields) {
  2752.                                                 connection.query('UPDATE matches SET confirmation = 2 WHERE id = ?', [socket.id_match], function (error, fini, fields) {
  2753.                                                     socket.emit('fin_match', donnees[0]);
  2754.                                                 });
  2755.                                             });
  2756.                                         }
  2757.                                     });
  2758.                                 });
  2759.                             });
  2760.                         }
  2761.                     });
  2762.                 }
  2763.             });
  2764.         }
  2765.         else {  socket.emit('deconnexion', ''); }
  2766.     });
  2767.  
  2768.     // pénalité en cas de déconnexion volontaire
  2769.     function multi_deco() {
  2770.         connection.query('SELECT id, id_match, joueur1, joueur2, elo1_avant, elo2_avant, deco1, deco2 FROM parties WHERE id_match = 0 AND etat = -1 AND (joueur1 = ? OR joueur2 = ?) AND date < DATE_SUB(NOW(), INTERVAL 2 MINUTE)', [socket.identifiant, socket.identifiant], function (error, verdict, fields) {
  2771.             if (verdict.length > 0 && verdict[0]['id_match'] == 0) {
  2772.                 delete direct[verdict[0]['id']];
  2773.                 if (verdict[0]['deco1'] == 1 && verdict[0]['deco2'] == 1) {
  2774.                     connection.query('UPDATE parties SET elo1_apres = elo1_avant, elo2_apres = elo2_avant, etat = 0 WHERE id = ?', [verdict[0]['id']], function (error, rien, fields) {});
  2775.                 }
  2776.                 else if (verdict[0]['deco1'] == 1 && verdict[0]['joueur1'] == socket.identifiant) {
  2777.                     var ancien_elo = verdict[0]['elo2_avant'];
  2778.                     var nelo = Math.round(100*(socket.classement2 + 20*(1 - 1/(1 + Math.pow(10, (ancien_elo - socket.classement2)/400)))))/100;
  2779.                     var elo_adv = Math.round(100*(ancien_elo + 20*(0 - 1/(1 + Math.pow(10, (socket.classement2 - ancien_elo)/400)))))/100;
  2780.                     socket.classement2 = nelo;
  2781.                     connection.query('UPDATE parties SET elo1_apres = ?, elo2_apres = ?, etat = 0 WHERE id = ?', [nelo, elo_adv, verdict[0]['id']], function (error, rien, fields) {
  2782.                         connection.query('UPDATE membres SET elo2 = ? WHERE id = ?', [nelo, socket.identifiant], function (error, rien2, fields) {});
  2783.                         connection.query('UPDATE membres SET elo2 = ? WHERE id = ?', [elo_adv, verdict[0]['joueur2']], function (error, rien2, fields) {});
  2784.                         socket.emit('elo_multi_cache', nelo);
  2785.                     });
  2786.                 }
  2787.                 else if (verdict[0]['deco1'] == 1 && verdict[0]['joueur2'] == socket.identifiant) {
  2788.                     var ancien_elo = verdict[0]['elo1_avant'];
  2789.                     var nelo = Math.round(100*(socket.classement2 + 20*(0 - 1/(1 + Math.pow(10, (ancien_elo - socket.classement2)/400)))))/100;
  2790.                     var elo_adv = Math.round(100*(ancien_elo + 20*(1 - 1/(1 + Math.pow(10, (socket.classement2 - ancien_elo)/400)))))/100;
  2791.                     socket.classement2 = nelo;
  2792.                     connection.query('UPDATE parties SET elo1_apres = ?, elo2_apres = ?, etat = 0 WHERE id = ?', [elo_adv, nelo, verdict[0]['id']], function (error, rien, fields) {
  2793.                         connection.query('UPDATE membres SET elo2 = ? WHERE id = ?', [nelo, socket.identifiant], function (error, rien2, fields) {});
  2794.                         connection.query('UPDATE membres SET elo2 = ? WHERE id = ?', [elo_adv, verdict[0]['joueur1']], function (error, rien2, fields) {});
  2795.                         socket.emit('elo_multi_cache', nelo);
  2796.                     });
  2797.                 }
  2798.                 else if (verdict[0]['deco2'] == 1 && verdict[0]['joueur1'] == socket.identifiant) {
  2799.                     var ancien_elo = verdict[0]['elo2_avant'];
  2800.                     var nelo = Math.round(100*(socket.classement2 + 20*(0 - 1/(1 + Math.pow(10, (ancien_elo - socket.classement2)/400)))))/100;
  2801.                     var elo_adv = Math.round(100*(ancien_elo + 20*(1 - 1/(1 + Math.pow(10, (socket.classement2 - ancien_elo)/400)))))/100;
  2802.                     socket.classement2 = nelo;
  2803.                     connection.query('UPDATE parties SET elo1_apres = ?, elo2_apres = ?, etat = 0 WHERE id = ?', [nelo, elo_adv, verdict[0]['id']], function (error, rien, fields) {
  2804.                         connection.query('UPDATE membres SET elo2 = ? WHERE id = ?', [nelo, socket.identifiant], function (error, rien2, fields) {});
  2805.                         connection.query('UPDATE membres SET elo2 = ? WHERE id = ?', [elo_adv, verdict[0]['joueur2']], function (error, rien2, fields) {});
  2806.                         socket.emit('elo_multi_cache', nelo);
  2807.                     });
  2808.                 }
  2809.                 else if (verdict[0]['deco2'] == 1 && verdict[0]['joueur2'] == socket.identifiant) {
  2810.                     var ancien_elo = verdict[0]['elo1_avant'];
  2811.                     var nelo = Math.round(100*(socket.classement2 + 20*(1 - 1/(1 + Math.pow(10, (ancien_elo - socket.classement2)/400)))))/100;
  2812.                     var elo_adv = Math.round(100*(ancien_elo + 20*(0 - 1/(1 + Math.pow(10, (socket.classement2 - ancien_elo)/400)))))/100;
  2813.                     socket.classement2 = nelo;
  2814.                     connection.query('UPDATE parties SET elo1_apres = ?, elo2_apres = ?, etat = 0 WHERE id = ?', [elo_adv, nelo, verdict[0]['id']], function (error, rien, fields) {
  2815.                         connection.query('UPDATE membres SET elo2 = ? WHERE id = ?', [nelo, socket.identifiant], function (error, rien2, fields) {});
  2816.                         connection.query('UPDATE membres SET elo2 = ? WHERE id = ?', [elo_adv, verdict[0]['joueur1']], function (error, rien2, fields) {});
  2817.                         socket.emit('elo_multi_cache', nelo);
  2818.                     });
  2819.                 }
  2820.                 else if (verdict[0]['joueur2'] == socket.identifiant) {
  2821.                     var ancien_elo = verdict[0]['elo1_avant'];
  2822.                     var nelo = Math.round(100*(socket.classement2 + 20*(0.5 - 1/(1 + Math.pow(10, (ancien_elo - socket.classement2)/400)))))/100;
  2823.                     var elo_adv = Math.round(100*(ancien_elo + 20*(0.5 - 1/(1 + Math.pow(10, (socket.classement2 - ancien_elo)/400)))))/100;
  2824.                     socket.classement2 = nelo;
  2825.                     connection.query('UPDATE parties SET elo1_apres = ?, elo2_apres = ?, etat = 0 WHERE id = ?', [elo_adv, nelo, verdict[0]['id']], function (error, rien, fields) {
  2826.                         connection.query('UPDATE membres SET elo2 = ? WHERE id = ?', [nelo, socket.identifiant], function (error, rien2, fields) {});
  2827.                         connection.query('UPDATE membres SET elo2 = ? WHERE id = ?', [elo_adv, verdict[0]['joueur1']], function (error, rien2, fields) {});
  2828.                         socket.emit('elo_multi_cache', nelo);
  2829.                     });
  2830.                 }
  2831.                 else if (verdict[0]['joueur1'] == socket.identifiant) {
  2832.                     var ancien_elo = verdict[0]['elo2_avant'];
  2833.                     var nelo = Math.round(100*(socket.classement2 + 20*(0.5 - 1/(1 + Math.pow(10, (ancien_elo - socket.classement2)/400)))))/100;
  2834.                     var elo_adv = Math.round(100*(ancien_elo + 20*(0.5 - 1/(1 + Math.pow(10, (socket.classement2 - ancien_elo)/400)))))/100;
  2835.                     socket.classement2 = nelo;
  2836.                     connection.query('UPDATE parties SET elo1_apres = ?, elo2_apres = ?, etat = 0 WHERE id = ?', [nelo, elo_adv, verdict[0]['id']], function (error, rien, fields) {
  2837.                         connection.query('UPDATE membres SET elo2 = ? WHERE id = ?', [nelo, socket.identifiant], function (error, rien2, fields) {});
  2838.                         connection.query('UPDATE membres SET elo2 = ? WHERE id = ?', [elo_adv, verdict[0]['joueur2']], function (error, rien2, fields) {});
  2839.                         socket.emit('elo_multi_cache', nelo);
  2840.                     });
  2841.                 }
  2842.             }
  2843.         });
  2844.     }
  2845.    
  2846.     // déconnexion intempestive
  2847.     socket.on('partie_multi_deco', function (type) {
  2848.         if (type == 1 || type == 6) {
  2849.             connection.query('UPDATE parties SET deco1 = 1 WHERE id = ?', [socket.lieu], function (error, rien, fields) {});
  2850.         }
  2851.         else if (type == 2 || type == 7) {
  2852.             connection.query('UPDATE parties SET deco2 = 1 WHERE id = ?', [socket.lieu], function (error, rien, fields) {});
  2853.         }
  2854.         setTimeout(multi_deco, 3000);
  2855.         socket.leave(socket.lieu);
  2856.         socket.lieu = -1;
  2857.         socket.emit('reponse_partie_multi_deco', '');
  2858.     });
  2859.     } /* FIN PARTIE MULTIJOUEUR */
  2860.    
  2861.     /* DEBUT PARTIE CUSTOM */ {
  2862.    
  2863.     // pour voir si le match est terminé ou pas
  2864.     function verif_match_termine(infos) {
  2865.         if ('diff_manches' in infos) {
  2866.             if (infos['nb_manches'] == 0) { return 0; }
  2867.             else if (infos['diff_manches'] == 1) {
  2868.                 if (infos['score1'] == infos['nb_manches'] || infos['score2'] == infos['nb_manches']) { return 1; }
  2869.                 else { return 0; }
  2870.             }
  2871.             else {
  2872.                 if (infos['score1'] >= infos['nb_manches'] && infos['score1'] - infos['score2'] > 1) { return 1; }
  2873.                 else if (infos['score2'] >= infos['nb_manches'] && infos['score2'] - infos['score1'] > 1) { return 1; }
  2874.                 else { return 0; }
  2875.             }
  2876.         }
  2877.     }
  2878.      
  2879.     // horreur et putréfaction (sert à rien ?)
  2880.     socket.on('manche_tout_seul', function (type) {
  2881.         if (type == 1) {
  2882.             connection.query('UPDATE matches SET score1 = score1 + 1, debutmanche = DATE_ADD(NOW(), INTERVAL 2 MINUTE) WHERE id = ?', [socket.id_match], function (error, modif, fields) {
  2883.                 connection.query('SELECT * FROM matches WHERE id = ?', [socket.id_match], function (error, infos, fields) {
  2884.                     connection.query('INSERT INTO parties(id_match, etat, deco1, deco2, joueur1, joueur2, date) VALUES (?, 1, 1, 0, ?, ?, DATE_SUB(NOW(), INTERVAL 1 SECOND))', [socket.id_match, infos[0]['joueur1'], infos[0]['joueur2']], function (error, faux, fields) {
  2885.                         if (verif_match_termine(infos[0]) == 0) { socket.emit('manche_fin', ''); }
  2886.                         else {
  2887.                             connection.query('UPDATE matches SET confirmation = 2 WHERE id = ?', [socket.id_match], function (error, fini, fields) {
  2888.                                 socket.emit('fin_match', infos[0]);
  2889.                             });
  2890.                         }
  2891.                     });
  2892.                 });
  2893.             });
  2894.         }
  2895.         else {
  2896.             connection.query('UPDATE matches SET score2 = score2 + 1, debutmanche = DATE_ADD(NOW(), INTERVAL 2 MINUTE) WHERE id = ?', [socket.id_match], function (error, modif, fields) {
  2897.                 connection.query('SELECT * FROM matches WHERE id = ?', [socket.id_match], function (error, infos, fields) {
  2898.                     connection.query('INSERT INTO parties(id_match, etat, deco1, deco2, joueur1, joueur2, date) VALUES (?, 1, 0, 1, ?, ?, DATE_SUB(NOW(), INTERVAL 1 SECOND))', [socket.id_match, infos[0]['joueur1'], infos[0]['joueur2']], function (error, faux, fields) {
  2899.                         if (verif_match_termine(infos[0]) == 0) { socket.emit('manche_fin', ''); }
  2900.                         else {
  2901.                             connection.query('UPDATE matches SET confirmation = 2 WHERE id = ?', [socket.id_match], function (error, fini, fields) {
  2902.                                 socket.emit('fin_match', infos[0]);
  2903.                             });
  2904.                         }
  2905.                     });
  2906.                 });
  2907.             });
  2908.         }
  2909.     });
  2910.        
  2911.     // vérifications lorsqu'une manche a déjà débuté
  2912.     function verif_manche_multi(id_manche, typejoueur) {
  2913.         connection.query('SELECT * FROM parties WHERE id = ?', [id_manche], function (error, manche, fields) {
  2914.             if (manche[0]['deco1'] == manche[0]['deco2']) { // manche annulée
  2915.                 connection.query('UPDATE matches SET debutmanche = DATE_ADD(NOW(), INTERVAL 2 MINUTE) WHERE id = ?', [manche[0]['id_match']], function (error, modif, fields) {
  2916.                     connection.query('SELECT * FROM matches WHERE id = ?', [manche[0]['id_match']], function (error, don, fields) {
  2917.                         var donnees = don[0];
  2918.                         donnees['typejoueur'] = typejoueur;
  2919.                         socket.emit('donnees_match', donnees);
  2920.                     });
  2921.                 });
  2922.             }
  2923.             else if (manche[0]['deco1'] == 0 && typejoueur == 2) { // un point pour le joueur 2
  2924.                 connection.query('UPDATE parties SET KO2 = 3, etat = 1 WHERE id = ?', [id_manche], function (error, ok, fields) {});
  2925.                 connection.query('UPDATE matches SET score2 = score2+1 WHERE id = ?', [manche[0]['id_match']], function (error, modif, fields) {
  2926.                     if (verif_match_termine(manche[0]) == 0) {
  2927.                         connection.query('UPDATE matches SET debutmanche = DATE_ADD(NOW(), INTERVAL 2 MINUTE) WHERE id = ?', [manche[0]['id_match']], function (error, modif, fields) {
  2928.                             connection.query('SELECT * FROM matches WHERE id = ?', [manche[0]['id_match']], function (error, don, fields) {
  2929.                                 var donnees = don[0];
  2930.                                 donnees['typejoueur'] = typejoueur;
  2931.                                 socket.emit('donnees_match', donnees);
  2932.                             });
  2933.                         });
  2934.                     }
  2935.                     else {
  2936.                         connection.query('UPDATE matches SET confirmation = 2 WHERE id = ?', [id_manche], function (error, fini, fields) {
  2937.                             socket.emit('fin_match', manche[0]);
  2938.                         });
  2939.                     }
  2940.                 });
  2941.             }
  2942.             else if (manche[0]['deco2'] == 0 && typejoueur == 1) { // un point pour le joueur 1
  2943.                 connection.query('UPDATE parties SET KO1 = 3, etat = 1 WHERE id = ?', [id_manche], function (error, ok, fields) {});
  2944.                 connection.query('UPDATE matches SET score1 = score1+1 WHERE id = ?', [manche[0]['id_match']], function (error, modif, fields) {
  2945.                     if (verif_match_termine(manche[0]) == 0) {
  2946.                         connection.query('UPDATE matches SET debutmanche = DATE_ADD(NOW(), INTERVAL 21 SECOND) WHERE id = ?', [manche[0]['id_match']], function (error, modif, fields) {
  2947.                             connection.query('SELECT * FROM matches WHERE id = ?', [manche[0]['id_match']], function (error, don, fields) {
  2948.                                 var donnees = don[0];
  2949.                                 donnees['typejoueur'] = typejoueur;
  2950.                                 socket.emit('donnees_match', donnees);
  2951.                             });
  2952.                         });
  2953.                     }
  2954.                     else {
  2955.                         connection.query('UPDATE matches SET confirmation = 2 WHERE id = ?', [id_manche], function (error, fini, fields) {
  2956.                             socket.emit('fin_match', manche[0]);
  2957.                         });
  2958.                     }
  2959.                 });
  2960.             }
  2961.             else if (manche[0]['deco1'] == 0 && typejoueur == 1) { socket.emit('manche_fin', ''); }
  2962.             else if (manche[0]['deco2'] == 0 && typejoueur == 2) { socket.emit('manche_fin', ''); }
  2963.         });
  2964.     }
  2965.    
  2966.     // vérifier si un match est valide ou pas
  2967.     socket.on('verifier_match', function(id_match) {
  2968.         var idm = parseInt(escapeHtml(id_match.toString()));
  2969.         connection.query('SELECT * FROM matches WHERE confirmation = 1 AND id = ?', [idm], function (error, verif, fields) {
  2970.   console.log(error);          if (verif.length == 0) { socket.emit('connexion_automatique_echouee', '') }
  2971.             else if (verif[0]['joueur1'] != socket.identifiant && verif[0]['joueur2'] != socket.identifiant) { socket.emit('connexion_automatique_echouee', '') }
  2972.             else if (verif_match_termine(verif[0]) == 1) {
  2973.                 connection.query('UPDATE matches SET confirmation = 2 WHERE id = ?', [idm], function (error, fini, fields) {
  2974.                     socket.emit('fin_match', verif[0]);
  2975.                 });
  2976.             }
  2977.             else {
  2978.                 var infos = verif[0];
  2979.                 socket.join('M'+infos['id']);
  2980.                 socket.id_match = infos['id'];
  2981.                 match_socket[socket.pseudo] = socket;
  2982.                 if (infos['joueur1'] == socket.identifiant) {
  2983.                     infos['typejoueur'] = 1;
  2984.                     connection.query('SELECT * FROM membres WHERE id = ?', [infos['joueur2']], function (error, adv, fields) {
  2985.                         socket.emit('infos_adversaire', adv[0]);
  2986.                     });
  2987.                 }
  2988.                 else {
  2989.                     infos['typejoueur'] = 2;
  2990.                     connection.query('SELECT * FROM membres WHERE id = ?', [infos['joueur1']], function (error, adv, fields) {
  2991.                         socket.emit('infos_adversaire', adv[0]);
  2992.                     });
  2993.                 }
  2994.                 var maintenant = new Date();
  2995.                 if (infos['debutmanche'] <= maintenant) {
  2996.                     connection.query('SELECT * FROM parties WHERE id_match = ? AND etat != 1 ORDER BY date DESC', [infos['id']], function (error, manche, fields) {
  2997.                         if (manche.length == 0) {
  2998.                             connection.query('UPDATE matches SET debutmanche = DATE_ADD(NOW(), INTERVAL 21 SECOND) WHERE id = ?', [infos['id']], function (error, modif, fields) {
  2999.                                 connection.query('SELECT * FROM matches WHERE id = ?', [infos['id']], function (error, don, fields) {
  3000.                                     var donnees = don[0];
  3001.                                     if (donnees['joueur1'] == socket.identifiant) { donnees['typejoueur'] = 1; }
  3002.                                     else { donnees['typejoueur'] = 2; }
  3003.                                     socket.emit('donnees_match', donnees);
  3004.                                 });
  3005.                             });
  3006.                         }
  3007.                         else if (manche[0]['deco1'] == 0 || manche[0]['deco2'] == 0) { setTimeout(verif_manche_multi, 7000, manche[0]['id'], infos['typejoueur']); }
  3008.                         else { verif_manche_multi(manche[0]['id'], infos['typejoueur']); }
  3009.                     });
  3010.                 }
  3011.                 else { socket.emit('donnees_match', infos); }
  3012.             }
  3013.         });
  3014.     });
  3015.    
  3016.     // message pour dire qu'on est prêt
  3017.     socket.on('message_pret', function(message) {
  3018.         var mess = parseInt(escapeHtml(message.toString()));
  3019.         if (mess == 1 || mess == 0) { socket.broadcast.to('M'+socket.id_match).emit('message_pret', message); }
  3020.     });
  3021.    
  3022.     } /* FIN PARTIE CUSTOM */
  3023.    
  3024.     /* DEBUT PARTIES INVITATIONS */
  3025.    
  3026.     socket.on('demander_calendrier', function (donnees) {
  3027.         var fuseau_actuel = parseInt(escapeHtml(donnees['fuseau'].toString()));
  3028.         var ajd = new Date(escapeHtml(donnees['debut'].toString()));
  3029.         var mois = ajd.getMonth(), annee = ajd.getFullYear(), jour = ajd.getDate();
  3030.         connection.query('SELECT fuseau FROM membres WHERE id = ?', [socket.identifiant], function (error, fuseau, fields) {
  3031.             if (fs.existsSync(path.join(__dirname, 'calendrier/'+socket.identifiant+'/'+annee+'-'+mois+'-'+jour+'.txt'))) {
  3032.                 fs.readFile(path.join(__dirname, 'calendrier/'+socket.identifiant+'/'+annee+'-'+mois+'-'+jour+'.txt'), 'utf8', function (err,calendrier) {
  3033.                     var diff = fuseau_actuel - fuseau[0]['fuseau'];
  3034.                     if (diff > 0) {
  3035.                         for (i = 6; i >= 0; i--) {
  3036.                             for (j = 23; j >= 0; j--) {
  3037.                                 if (i*24+j+diff >= 168) { continue; }
  3038.                                 calendrier[i*24+j+diff] = calendrier[i*24+j];
  3039.                             }
  3040.                         }
  3041.                     }
  3042.                     else {
  3043.                         for (i = 0; i < 7; i++) {
  3044.                             for (j = 0; j < 24; j++) {
  3045.                                 if (i*24+j+diff < 0) { continue; }
  3046.                                 calendrier[i*24+j+diff] = calendrier[i*24+j];
  3047.                             }
  3048.                         }
  3049.                     }
  3050.                     socket.emit('recuperer_calendrier', {date: ajd, cal: calendrier});
  3051.                 });
  3052.             }
  3053.             else { socket.emit('recuperer_calendrier', {date: ajd, cal: '0'.repeat(168)}); }
  3054.         });
  3055.     });
  3056.    
  3057.     socket.on('sauver_calendrier', function (infos) {
  3058.         if ('date' in infos && 'cal' in infos && 'fuseau' in infos) {
  3059.             var ts = new Date(parseInt(infos['date']));
  3060.             var mois = ts.getMonth(), annee = ts.getFullYear(), jour = ts.getDate();
  3061.             var ajd = new Date();
  3062.             var ca = ajd.getFullYear();
  3063.             var fuseau = parseInt(infos['fuseau'].toString());
  3064.             console.log(annee, mois, jour, socket.identifiant, fuseau);
  3065.             if (Math.abs(ca-annee) <= 1 && fuseau >= -11 && fuseau <= 14) {
  3066.                 if (!fs.existsSync(path.join(__dirname, 'calendrier/'+socket.identifiant+'/'))) { fs.mkdirSync(path.join(__dirname, 'calendrier/'+socket.identifiant+'/')); }
  3067.                 connection.query('UPDATE membres SET fuseau = ? WHERE id = ?', [fuseau, socket.identifiant], function (error, ok, fields) {});
  3068.                 fs.writeFile(path.join(__dirname, 'calendrier/'+socket.identifiant+'/'+annee+'-'+mois+'-'+jour+'.txt'), infos['cal'], function (err) { socket.emit('succes_calendrier', ''); });
  3069.             }
  3070.             else { socket.emit('echec_calendrier', ''); }
  3071.         }
  3072.     });
  3073.    
  3074.     // récupérations des informations d'un match que l'on veut éditer
  3075.     socket.on('infos_match', function(pseudo) {
  3076.         var pseudoinvite = escapeHtml(pseudo.toString());
  3077.         var informations = {date: '', heure: '', nb_manches: 7, diff_manches: 2, limite_ko: 0, duree: 2};
  3078.         connection.query('SELECT id FROM membres WHERE pseudo = ? AND (typemembre = 1 OR typemembre = 2)', [pseudoinvite], function(error, v, fields) {
  3079.             if (v.length == 1) {
  3080.                 // peut-être une faille de sécurité si quelqu'un crée un match avant que le précédent ne soit terminé
  3081.                 connection.query('SELECT * FROM matches WHERE tournoi = 0 AND datedebut > NOW() AND (joueur1 = ? OR joueur2 = ?) AND (joueur1 = ? OR joueur2 = ?) AND confirmation = 0', [socket.identifiant, socket.identifiant, v[0]['id'], v[0]['id']], function (error, infos, fields) {
  3082.                     if (infos.length == 1) {
  3083.                         informations = infos[0];
  3084.                         var annee = infos[0]['datedebut'].getFullYear();
  3085.                         var mois = 1+infos[0]['datedebut'].getMonth();
  3086.                         if (mois < 10) { mois = '0' + mois; }
  3087.                         var jour = infos[0]['datedebut'].getDate();
  3088.                         if (jour < 10) { jour = '0' + jour; }
  3089.                         var heure =  infos[0]['datedebut'].getHours();
  3090.                         if (heure < 10) { heure = '0' + heure; }
  3091.                         var minute = infos[0]['datedebut'].getMinutes();
  3092.                         if (minute < 10) { minute = '0' + minute; }
  3093.                         informations['date'] = annee + '-' + mois + '-' + jour;
  3094.                         informations['heure'] = heure + ':' + minute;
  3095.                     }
  3096.                     socket.emit('infos_match', informations);
  3097.                 });
  3098.             }
  3099.             else { socket.emit('infos_match', informations); }
  3100.         });
  3101.     });
  3102.    
  3103.     // nouvelle invitation
  3104.     socket.on('invitation_match', function (donnees) {
  3105.         if (socket.pseudo == '#') { socket.emit('deconnexion', ''); }
  3106.         else if (socket.typemembre >= 1 && socket.typemembre <= 2 && 'offset' in donnees && 'pseudo' in donnees && 'date' in donnees && 'heure' in donnees && 'nb_manches' in donnees && 'diff_manches' in donnees && 'limite_ko' in donnees && 'duree' in donnees && 'prive' in donnees) {
  3107.             var pseudo = escapeHtml(donnees['pseudo'].toString()), date = escapeHtml(donnees['date'].toString()), heure = escapeHtml(donnees['heure'].toString());
  3108.             var nb_manches = parseInt(escapeHtml(donnees['nb_manches'].toString())), diff_manches = parseInt(escapeHtml(donnees['diff_manches'].toString())), limite_ko = parseInt(escapeHtml(donnees['limite_ko'].toString())), duree = parseFloat(escapeHtml(donnees['duree'].toString()));
  3109.             var prive = parseInt(escapeHtml(donnees['prive'].toString())), offset = parseInt(escapeHtml(donnees['offset'].toString()));
  3110.             var erreurs = '';
  3111.             date = escapeHtml(donnees['date'].toString()), heure = escapeHtml(donnees['heure'].toString());
  3112.             dateMatch = new Date(date + ' ' + heure + ':00');
  3113.             dateMatch.setHours(dateMatch.getDate()-offset);
  3114.             if (date == '' && heure == '') { dateMatch = new Date(); }
  3115.             dateMatch.setDate(dateMatch.getDate()+7);
  3116.             if (isNaN(dateMatch.getTime())) { erreurs += 'Your starting date and time are not valid. '; }
  3117.             else if (dateMatch.getYear()+1900 > 2042 || dateMatch.getYear()+1900 < 2016) { erreurs += 'Your starting date and time are not valid. '; }
  3118.             else {
  3119.                 //dateMin = new Date();
  3120.                 //dateMin.setMinutes(dateMin.getMinutes()+10);
  3121.                 dateLim = new Date(dateMatch);
  3122.                 dateLim.setDate(dateLim.getDate()+14);
  3123.                 if (0) { erreurs += 'Your match should start in more than 10 minutes from now. '; }
  3124.                 else {
  3125.                     if (diff_manches != 1 && diff_manches != 2) { erreurs += 'Your match should either be win by 1 or win by 2. '; }
  3126.                     if (duree < 0) { erreurs += 'Your match\'s length has to be non-negative. '; }
  3127.                     if (duree > 10) { erreurs += 'Your match\'s length cannot exceed 10 minutes. '; }
  3128.                     if (limite_ko < 0) { erreurs += 'Your match\'s KO limit has to be non-negative. '; }
  3129.                     if (nb_manches < 0) { erreurs += 'The round limit has to be non-negative. '; }
  3130.                     if (duree+limite_ko == 0) { erreurs += 'You need to set either a KO or a time limit. '; }
  3131.                     if (prive < 0 || prive > 1) { erreurs += 'Something weird happened. '; }
  3132.                     if (erreurs == '') {
  3133.                         connection.query('SELECT id, infos3, discord3, email, discord FROM membres WHERE pseudo = ? AND (typemembre = 1 OR typemembre = 2) AND id != ?', [pseudo, socket.identifiant], function (error, verif0, fields) {
  3134.                             if (verif0.length == 0) { erreurs += 'No validated user has this username. '; }
  3135.                             else {
  3136.                                 connection.query('SELECT matches.id AS id, joueur1, joueur2, confirmation, membres.pseudo AS pseudo FROM matches INNER JOIN membres AS membres ON matches.joueur1 = membres.id WHERE debutmanche > NOW() AND matches.tournoi = 0 AND (joueur1 = ? OR joueur2 = ?) AND (joueur1 = ? OR joueur2 = ?)', [socket.identifiant, socket.identifiant, verif0[0]['id'], verif0[0]['id']], function (error, matches, fields) {
  3137.                                     if (matches.length > 0 && matches[0]['confirmation'] < 2) {
  3138.                                         var match = matches[0];
  3139.                                         if (match['confirmation'] == 1) { erreurs += 'There is already a custom match which was confirmed between you and ' + pseudo + '. Please cancel it, then make a new invitation. '; }
  3140.                                         else if (match['confirmation'] == 0) {
  3141.                                             connection.query('UPDATE matches SET joueur1 = ?, joueur2 = ?, debutmanche = ?, datedebut = ?, datelimite = ?, nb_manches = ?, diff_manches = ?, limite_ko = ?, duree = ? WHERE id = ?', [socket.identifiant, verif0[0]['id'], dateMatch, dateMatch, dateLim, nb_manches, diff_manches, limite_ko, duree, match['id']], function (error, maj, fields) {
  3142.                                                 if (match['joueur2'] == socket.identifiant) {
  3143.                                                     var message1 = "Hi!\n\n" + socket.pseudo + " replied to your invitation. Even though it wasn't accepted as it was, you got a counter-proposition from this player, which seems to be better for him. In order to view this new invitation, click here: https://www.worldwide-combos.com/customgames.\n\nBest regards,\n\n Noël Nadal (Worldwide Combos admin).";
  3144.                                                     if (verif0[0]['infos3'] == 1) {
  3145.                                                         var message = {
  3146.                                                             text:   message1,
  3147.                                                             from:   "Worldwide Combos <noreply@worldwide-combos.com>",
  3148.                                                             to:     verif0[0]['email'],
  3149.                                                             subject:    "You got a reply from " + socket.pseudo,
  3150.                                                             attachment:
  3151.                                                             [
  3152.                                                                {data:"<html>Hi!<br><br>" + socket.pseudo + " replied to your invitation. Even though it wasn't accepted as it was, you got a counter-proposition from this player, which seems to be better for him. In order to view this new invitation, click <a href='https://www.worldwide-combos.com/customgames'>here</a>.<br><br>Best regards,<br><br>Noël Nadal (Worldwide Combos admin).</html>", alternative:true}
  3153.                                                             ]
  3154.                                                         };
  3155.                                                         server_noreply.send(message, function(err, message) { console.log(getDateTime() + 'Notification courriel envoyée à ' + pseudo + ' (contre-proposition).'); });
  3156.                                                     }
  3157.                                                     if (verif0[0]['discord3'] == 1) { prive_Discord(verif0[0]['discord'], message1); }
  3158.                                                 }
  3159.                                                 socket.emit('succes_invitation', '');
  3160.                                             });
  3161.                                         }
  3162.                                     }
  3163.                                     else {
  3164.                                         connection.query('INSERT INTO matches(joueur1, joueur2, debutmanche, datedebut, datelimite, nb_manches, diff_manches, limite_ko, duree, prive) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', [socket.identifiant, verif0[0]['id'], dateMatch, dateMatch, dateLim, nb_manches, diff_manches, limite_ko, duree, prive], function (error, nv, fields) {
  3165.                                             var message1 = "Hi!\n\n" + socket.pseudo + " sent you an invitation. This player wants to play against you in a custom game! In order to view it, click here: https://www.worldwide-combos.com/customgames.\n\nBest regards,\n\n Noël Nadal (Worldwide Combos admin).";
  3166.                                             if (verif0[0]['infos3'] == 1) {
  3167.                                                 var message = {
  3168.                                                     text:   message1,
  3169.                                                     from:   "Worldwide Combos <noreply@worldwide-combos.com>",
  3170.                                                     to:     verif0[0]['email'],
  3171.                                                     subject:    "You got a new invitation!",
  3172.                                                     attachment:
  3173.                                                     [
  3174.                                                         {data:"<html>Hi!<br><br>" + socket.pseudo + " sent you an invitation. This player wants to play against you in a custom game! In order to view it, click <a href='https://www.worldwide-combos.com/customgames'>here</a>.<br><br>Best regards,<br><br>Noël Nadal (Worldwide Combos admin).</html>", alternative:true}
  3175.                                                     ]
  3176.                                                 };
  3177.                                                 server_noreply.send(message, function(err, message) { console.log(getDateTime() + 'Notification courriel envoyée à ' + pseudo + ' (nouvelle invitation).'); });
  3178.                                             }
  3179.                                             if (verif0[0]['discord3'] == 1) { prive_Discord(verif0[0]['discord'], message1); }
  3180.                                             socket.emit('succes_invitation', '');
  3181.                                         });
  3182.                                     }
  3183.                                 });
  3184.                             }
  3185.                         });
  3186.                     }
  3187.                 }
  3188.             }
  3189.             if (erreurs != '') { socket.emit('echec_invitation', erreurs); }            
  3190.         }
  3191.     });
  3192.    
  3193.     // pour confirmer un match
  3194.     socket.on('confirmation_match', function (pseudo) {
  3195.         var pseudoinvite = escapeHtml(pseudo.toString());
  3196.         var informations = {date: '', heure: '', nb_manches: 7, diff_manches: 2, limite_ko: 0, duree: 2};
  3197.         connection.query('SELECT id, infos3, discord3, discord, email FROM membres WHERE pseudo = ? AND (typemembre = 1 OR typemembre = 2)', [pseudoinvite], function(error, v, fields) {
  3198.             if (v.length == 1) {
  3199.                 // peut-être une faille de sécurité si quelqu'un crée un match avant que le précédent ne soit terminé
  3200.                 connection.query('SELECT * FROM matches WHERE tournoi = 0 AND datedebut > NOW() AND (joueur1 = ? OR joueur2 = ?) AND (joueur1 = ? OR joueur2 = ?) AND confirmation = 0', [socket.identifiant, socket.identifiant, v[0]['id'], v[0]['id']], function (error, infos, fields) {
  3201.                     if (infos.length == 1) {
  3202.                         var annee = infos[0]['datedebut'].getFullYear();
  3203.                         var mois = 1+infos[0]['datedebut'].getMonth();
  3204.                         if (mois < 10) { mois = '0' + mois; }
  3205.                         var jour = infos[0]['datedebut'].getDate();
  3206.                         if (jour < 10) { jour = '0' + jour; }
  3207.                         var heure =  infos[0]['datedebut'].getHours();
  3208.                         if (heure < 10) { heure = '0' + heure; }
  3209.                         var minute = infos[0]['datedebut'].getMinutes();
  3210.                         if (minute < 10) { minute = '0' + minute; }
  3211.                         var limite_ko = infos[0]['limite_ko'];
  3212.                         if (limite_ko == 0) { limite_ko = "unlimited"; }
  3213.                         var duree = infos[0]['duree'];
  3214.                         if (duree == 0) { duree = "unlimited"; }
  3215.                         else if (duree == 1) { duree = "1 minute"; }
  3216.                         else { duree = duree + " minutes"; }
  3217.                         connection.query('UPDATE matches SET confirmation = 1 WHERE id = ?', [infos[0]['id']], function(error, fini, fields) {
  3218.                             var message1 = "Hi!\n\n" + socket.pseudo + " replied positively to your invitation. Here are the informations concerning this custom match:\n\n> Starting time: " + annee + "-" + mois + "-" + jour + " " + heure + ':' + minute + " *UTC*</li><li>First to " + infos[0]['nb_manches'] + ", win by " + infos[0]['diff_manches'] + "\n>Length of a round: " + duree + "\n>KO limit: " + limite_ko + "\n\nHave fun on Worldwide Combos!\n\nBest regards,\n\n Noël Nadal (Worldwide Combos admin).";
  3219.                             if (v[0]['infos3'] == 1) {
  3220.                                 var message = {
  3221.                                     text:   message1,
  3222.                                     from:   "Worldwide Combos <noreply@worldwide-combos.com>",
  3223.                                     to:     v[0]['email'],
  3224.                                     subject:    "Your invitation has been accepted!",
  3225.                                     attachment:
  3226.                                     [
  3227.                                         {data:"<html>Hi!<br><br>" + socket.pseudo + " replied positively to your invitation. Here are the informations concerning this custom match:<ul><li>Starting time: " + annee + "-" + mois + "-" + jour + " " + heure + ':' + minute + " <b>UTC</b></li><li>First to " + infos[0]['nb_manches'] + ", win by " + infos[0]['diff_manches'] + "</li><li>Length of a round: " + duree + "</li><li>KO limit: " + limite_ko + "</li></ul>Have fun on Worldwide Combos!<br><br>Best regards,<br><br>Noël Nadal (Worldwide Combos admin).</html>", alternative:true}
  3228.                                     ]
  3229.                                 };
  3230.                                 server_noreply.send(message, function(err, message) { console.log(getDateTime() + 'Notification courriel envoyée à ' + pseudo + ' (confirmation match).'); });
  3231.                             }
  3232.                             if (v[0]['discord3'] == 1) { prive_Discord(v[0]['discord'], message1); }
  3233.                         });
  3234.                     }
  3235.                     socket.emit('confirmation_ok', '');
  3236.                 });
  3237.             }
  3238.             else { socket.emit('confirmation_pasok', ''); }
  3239.         });
  3240.     });
  3241.    
  3242.     // pour annuler une invitation
  3243.     socket.on('annulation_match', function (pseudo) {
  3244.         var pseudoinvite = escapeHtml(pseudo.toString());
  3245.         var informations = {date: '', heure: '', nb_manches: 7, diff_manches: 2, limite_ko: 0, duree: 2};
  3246.         connection.query('SELECT id, infos3, discord3, discord, email FROM membres WHERE pseudo = ? AND (typemembre = 1 OR typemembre = 2)', [pseudoinvite], function(error, v, fields) {
  3247.             if (v.length == 1) {
  3248.                 // peut-être une faille de sécurité si quelqu'un crée un match avant que le précédent ne soit terminé
  3249.                 connection.query('SELECT * FROM matches WHERE tournoi = 0 AND datedebut > NOW() AND (joueur1 = ? OR joueur2 = ?) AND (joueur1 = ? OR joueur2 = ?) AND confirmation = 0', [socket.identifiant, socket.identifiant, v[0]['id'], v[0]['id']], function (error, infos, fields) {
  3250.                     if (infos.length == 1) {
  3251.                         connection.query('DELETE FROM matches WHERE id = ?', [infos[0]['id']], function(error, fini, fields) {
  3252.                             var message1 = "Hi!\n\n" + socket.pseudo + " cancelled your custom match against him. Hopefully you will find another opponent to play against!\n\nBest regards,\n\n Noël Nadal (Worldwide Combos admin).";
  3253.                             if (v[0]['infos3'] == 1) {
  3254.                                 var message = {
  3255.                                     text:   message1,
  3256.                                     from:   "Worldwide Combos <noreply@worldwide-combos.com>",
  3257.                                     to:     v[0]['email'],
  3258.                                     subject:    "Your match was cancelled",
  3259.                                     attachment:
  3260.                                     [
  3261.                                         {data:"<html>Hi!<br><br>" + socket.pseudo + " cancelled your custom match against him. Hopefully you will find another opponent to play against!<br><br>Have fun on Worldwide Combos!<br><br>Best regards,<br><br>Noël Nadal (Worldwide Combos admin).</html>", alternative:true}
  3262.                                     ]
  3263.                                 };
  3264.                                 server_noreply.send(message, function(err, message) { console.log(getDateTime() + 'Notification courriel envoyée à ' + pseudo + ' (annulation match).'); });
  3265.                             }
  3266.                             if (v[0]['discord3'] == 1) { console.log(v[0]['discord']);  prive_Discord(v[0]['discord'], message1); }
  3267.                         });
  3268.                     }
  3269.                     socket.emit('annulation_ok', '');
  3270.                 });
  3271.             }
  3272.             else { socket.emit('annulation_pasok', ''); }
  3273.         });
  3274.     });
  3275.     /* FIN PARTIES INVITATIONS */
  3276.    
  3277.     /* DEBUT CONNEXION / INSCRIPTION / OPTIONS */ {
  3278.    
  3279.     // renvoyer le courriel de validation
  3280.     socket.on('renvoyer_courriel', function (email) {
  3281.         var nemail = escapeHtml(email);
  3282.         connection.query('SELECT typemembre, mdp FROM membres WHERE pseudo = ?', [socket.pseudo], function (error, renvoyer, fields) {
  3283.             if (renvoyer.length == 1 && renvoyer[0]['typemembre'] == 0) {
  3284.                 var message = {
  3285.                     text:   "Hi!\n\nThank you for making an account on Worldwide-Combos. In order to validate your e-mail address, please open the following link in your browser: https://www.worldwide-combos.com/validate?id="+socket.identifiant+"&token="+renvoyer[0]['mdp']+". We are looking forward seeing you play with us!\n\nBest regards,\n\n Noël Nadal (Worldwide-Combos admin).",
  3286.                     from:   "Worldwide-Combos <noreply@worldwide-combos.com>",
  3287.                     to:     nemail,
  3288.                     subject:    "Validate your Worldwide-Combos account",
  3289.                     attachment:
  3290.                     [
  3291.                         {data:"<html>Hi!<br><br>Thank you for making an account on Worldwide-Combos. In order to validate your e-mail address, please click <a href='https://www.worldwide-combos.com/validate?id="+socket.identifiant+"&token="+renvoyer[0]['mdp']+"'>here</a>. We are looking forward seeing you play with us!<br><br>Best regards,<br><br>Noël Nadal (Worldwide-Combos admin).</html>", alternative:true}
  3292.                     ]
  3293.                 };
  3294.                 server_noreply.send(message, function(err, message) { console.log(getDateTime() + 'Courriel de validation de compte envoyé à ' + socket.pseudo + '.'); });
  3295.                 connection.query('SELECT id FROM membres WHERE email = ? and pseudo != ?', [nemail, socket.pseudo], function (error, verification, fields) {
  3296.                     if (verification.length == 0) {
  3297.                         connection.query('UPDATE membres SET email = ? WHERE pseudo = ?', [nemail, socket.pseudo], function (error, inutile, fields) {});
  3298.                         socket.emit('renvoi_reussi', '');
  3299.                     }
  3300.                     else { socket.emit('renvoi_echoue', ''); }
  3301.                 });
  3302.             }
  3303.         });
  3304.     });
  3305.    
  3306.     // tentative de connexion automatique grâce aux cookies
  3307.     socket.on('connexion_automatique', function (infos) {
  3308.         var mdp = crypto.createHash('sha1');
  3309.         var entree = escapeHtml(infos['mdp'].toString()), pseudo = escapeHtml(infos['pseudo'].toString());
  3310.         mdp.update('combo'+entree);
  3311.         var res_mdp = mdp.digest('hex');
  3312.         connection.query('SELECT * FROM membres WHERE pseudo = ? AND mdp = ?', [pseudo, res_mdp], function (error, verdict, fields) {
  3313.             if (verdict.length == 0) { socket.emit('connexion_automatique_echouee', ''); }
  3314.             else if (verdict.length == 1) {
  3315.                 socket.pseudo = verdict[0]['pseudo'];
  3316.                 socket.fuseau = verdict[0]['fuseau'];
  3317.                 socket.classement1 = verdict[0]['elo1'];
  3318.                 socket.classement2 = verdict[0]['elo2'];
  3319.                 socket.identifiant = verdict[0]['id'];
  3320.                 socket.pays = verdict[0]['pays'];
  3321.                 socket.typemembre = verdict[0]['typemembre'];
  3322.                 socket.email = verdict[0]['email'];
  3323.                 socket.sprint = verdict[0]['sprint'];
  3324.                 socket.sprint10 = verdict[0]['sprint10'];
  3325.                 socket.survivor = verdict[0]['survivor'];
  3326.                 socket.ligne_suppl = verdict[0]['ligne_suppl'];
  3327.                 socket.mdp = verdict[0]['mdp'];
  3328.                 socket.duree_solo = verdict[0]['duree_solo'];
  3329.                 socket.duree_multi = verdict[0]['duree_multi'];
  3330.                 socket.limite_ko_multi = verdict[0]['limite_ko_multi'];
  3331.                 socket.handicap_solo = verdict[0]['handicap_solo'];
  3332.                 socket.handicap_multi = verdict[0]['handicap_multi'];
  3333.                 solo_deco();
  3334.                 multi_deco();
  3335.                 if (socket.typemembre == 0) { socket.emit('annonce_validation', verdict[0]['email']); }
  3336.                 socket.emit('connexion_automatique', {pseudo: pseudo, mdp: entree});
  3337.                 console.log(getDateTime() + socket.pseudo + ' se connecte automatiquement sur le site.');
  3338.                 connection.query('UPDATE membres SET derniereconnexion = NOW() WHERE pseudo = ?', [pseudo], function (error, maj, fields) {
  3339.                     socket.emit('connexion_reussie', verdict[0]);
  3340.                 });
  3341.             }
  3342.         });
  3343.     });
  3344.    
  3345.     // formulaire de connexion reçu
  3346.     socket.on('tentative_connexion', function (infos) {
  3347.         var mdp = crypto.createHash('sha1');
  3348.         var entree = escapeHtml(infos['mdp'].toString()), pseudo = escapeHtml(infos['pseudo'].toString());
  3349.         var connexion = escapeHtml(infos['connexion'].toString());
  3350.         mdp.update('combo'+entree);
  3351.         var res_mdp = mdp.digest('hex');
  3352.         if (valide_pseudo(pseudo)) {
  3353.             connection.query('SELECT * FROM membres WHERE pseudo = ? AND mdp = ? AND typemembre >= 0', [pseudo, res_mdp], function (error, verdict, fields) {
  3354.                 if (verdict.length == 0) { socket.emit('connexion_echouee', ''); }
  3355.                 else if (verdict.length == 1) {
  3356.                     socket.pseudo = verdict[0]['pseudo'];
  3357.                     socket.fuseau = verdict[0]['fuseau'];
  3358.                     socket.classement1 = verdict[0]['elo1'];
  3359.                     socket.classement2 = verdict[0]['elo2'];
  3360.                     socket.identifiant = verdict[0]['id'];
  3361.                     socket.pays = verdict[0]['pays'];
  3362.                     socket.typemembre = verdict[0]['typemembre'];
  3363.                     socket.email = verdict[0]['email'];
  3364.                     socket.sprint = verdict[0]['sprint'];
  3365.                     socket.sprint10 = verdict[0]['sprint10'];
  3366.                     socket.survivor = verdict[0]['survivor'];
  3367.                     socket.ligne_suppl = verdict[0]['ligne_suppl'];
  3368.                     socket.mdp = verdict[0]['mdp'];
  3369.                     socket.duree_solo = verdict[0]['duree_solo'];
  3370.                     socket.handicap_solo = verdict[0]['handicap_solo'];
  3371.                     solo_deco();
  3372.                     multi_deco();
  3373.                     if (connexion == 1) { socket.emit('connexion_automatique', {pseudo: pseudo, mdp: entree}); }
  3374.                     if (socket.typemembre == 0) { socket.emit('annonce_validation', verdict[0]['email']); }
  3375.                     console.log(getDateTime() + socket.pseudo + ' se connecte sur le site.');
  3376.                     connection.query('UPDATE membres SET derniereconnexion = NOW() WHERE pseudo = ?', [pseudo], function (error, maj, fields) {
  3377.                         socket.emit('connexion_reussie', verdict[0]);
  3378.                     });
  3379.                 }
  3380.             });
  3381.         }
  3382.     });
  3383.    
  3384.     // connexion en tant qu'invité
  3385.     socket.on('connexion_invite', function(infos) {
  3386.         var pseudo = escapeHtml(infos['pseudo'].toString()), ok = 1, erreurs = '';
  3387.         console.log(getDateTime() + pseudo + ' tente de s\'inscrire sur le site en tant qu\'invité.');
  3388.         if (ok == 0) {
  3389.             console.log(getDateTime() + 'C\'est raté pour cette fois...');
  3390.             socket.emit('invitation_echec', erreurs);
  3391.         }
  3392.         else {
  3393.             pseudo = pseudo.substring(0, Math.min(30, pseudo.length)) + '#' + Math.floor(10000*Math.random()).toString();
  3394.             var mdph = crypto.createHash('sha1');
  3395.             mdph.update('combo#');
  3396.             var res_mdp = mdph.digest('hex');
  3397.             connection.query('INSERT INTO membres(pseudo, mdp, email, dateinscription, derniereconnexion, typemembre) VALUES(?,?,"",NOW(),NOW(), -1)', [pseudo, res_mdp], function (error, inscrit, fields) {
  3398.                 socket.pseudo = pseudo;
  3399.                 socket.classement1 = 1000;
  3400.                 socket.classement2 = 1000;
  3401.                 socket.identifiant = inscrit.insertId;
  3402.                 socket.pays = 'WHO';
  3403.                 socket.typemembre = -1;
  3404.                 socket.email = '';
  3405.                 socket.sprint = 0;
  3406.                 socket.survivor = 0;
  3407.                 socket.ligne_suppl = 0;
  3408.                 socket.mdp = res_mdp;
  3409.                 socket.duree_solo = 2;
  3410.                 socket.handicap_solo = 0;
  3411.                 console.log(getDateTime() + pseudo + ' s\'est inscrit sur le site en tant qu\'invité ! :D');
  3412.                 socket.emit('connexion_automatique', {pseudo: pseudo, mdp: '#'});
  3413.                 socket.emit('invitation_reussie', {pseudo: pseudo, pays: socket.pays});
  3414.             });
  3415.         }
  3416.     });
  3417.    
  3418.     // déconnexion (sans blague)
  3419.     socket.on('deconnexion', function() {
  3420.         console.log(getDateTime() + 'Déconnexion de ' + socket.pseudo + '.');
  3421.         socket.pseudo = '#';
  3422.         socket.classement1 = 1000;
  3423.         socket.classement2 = 1000;
  3424.         socket.identifiant = -1;
  3425.         socket.pays = 'WHO';
  3426.     });
  3427.    
  3428.     // nouveau mot de passe
  3429.     socket.on('nouveau_mdp', function(courriel) {
  3430.         var email = escapeHtml(courriel.toString());
  3431.         var mdph1 = crypto.createHash('sha1');
  3432.         mdph1.update(Math.random().toString());
  3433.         var mdp1 = mdph1.digest('hex').substring(0,8);
  3434.         var mdph2 = crypto.createHash('sha1');
  3435.         mdph2.update(mdp1);
  3436.         var mdp2 = mdph2.digest('hex');
  3437.         var mdph3 = crypto.createHash('sha1');
  3438.         mdph3.update('combo'+mdp2);
  3439.         var mdp3 = mdph3.digest('hex');
  3440.         connection.query('SELECT id FROM membres WHERE email = ?', [email], function (error, recherche, fields) {
  3441.             if (recherche.length == 1) {
  3442.                 var message = {
  3443.                     text:   "Hi!\n\nHere is your new password: "+mdp1+". You can modify it in Dashboard > Settings.\nWe are looking forward seeing you play with us!\n\nBest regards,\n\n Noël Nadal (Worldwide Combos admin).",
  3444.                     from:   "Worldwide Combos <noreply@worldwide-combos.com>",
  3445.                     to:     email,
  3446.                     subject:    "Your new Worldwide Combos password",
  3447.                     attachment:
  3448.                     [
  3449.                        {data:"<html>Hi!<br><br>Here is your new password: "+mdp1+". You can modify it in Dashboard > Settings.<br>We are looking forward seeing you play with us!<br><br>Best regards,<br><br>Noël Nadal (Worldwide Combos admin).</html>", alternative:true}
  3450.                     ]
  3451.                 };
  3452.                 server_noreply.send(message, function(err, message) { console.log(getDateTime() + 'Courriel de nouveau mot de passe envoyé à l\'adresse suivante : ' + email + '.'); });
  3453.                 connection.query('UPDATE membres SET mdp = ? WHERE id = ?', [mdp3, recherche[0]['id']], function (error, rien, fields) {});
  3454.             }
  3455.         });              
  3456.     });
  3457.    
  3458.     socket.on('maj_profil', function(infos) {
  3459.         if ('pseudo' in infos && 'mdp_actuel' in infos && 'nouveau_mdp' in infos && 'nouveau_mdp2' in infos && 'nom_afficher' in infos && 'prenom_afficher' in infos && 'nom' in infos && 'prenom' in infos && 'infos1' in infos && 'infos2' in infos && 'infos3' in infos && 'infos4' in infos && 'infos5' in infos && 'discord1' in infos && 'discord2' in infos && 'discord3' in infos && 'discord4' in infos && 'discord5' in infos && 'discord' in infos && 'afficher_discord' in infos && 'afficher_email' in infos && 'pays' in infos && 'sexe' in infos && 'sexe_afficher' in infos && 'email' in infos && 'email2' in infos && 'twitch' in infos) {
  3460.             var pseudo = escapeHtml(infos['pseudo'].toString()), nom = escapeHtml(infos['nom'].toString()), prenom = escapeHtml(infos['prenom'].toString()), email = escapeHtml(infos['email'].toString()), email2 = escapeHtml(infos['email2'].toString()), twitch = escapeHtml(infos['twitch'].toString());
  3461.             var pays = escapeHtml(infos['pays'].toString()), sexe = escapeHtml(infos['sexe'].toString()), sexe_afficher = escapeHtml(infos['sexe_afficher'].toString()), prenom_afficher = escapeHtml(infos['prenom_afficher'].toString()), nom_afficher = escapeHtml(infos['nom_afficher'].toString());
  3462.             var afficher_discord = escapeHtml(infos['afficher_discord'].toString()), afficher_email = escapeHtml(infos['afficher_email'].toString()), discord = escapeHtml(infos['discord'].toString());
  3463.             var mdp_actuel = escapeHtml(infos['mdp_actuel'].toString()), nouveau_mdp = escapeHtml(infos['nouveau_mdp'].toString()), nouveau_mdp2 = escapeHtml(infos['nouveau_mdp2'].toString());
  3464.             var infos1 = escapeHtml(infos['infos1'].toString()), infos2 = escapeHtml(infos['infos2'].toString()), infos3 = escapeHtml(infos['infos3'].toString()), infos4 = escapeHtml(infos['infos4'].toString()), infos5 = escapeHtml(infos['infos5'].toString());
  3465.             var discord1 = escapeHtml(infos['discord1'].toString()), discord2 = escapeHtml(infos['discord2'].toString()), discord3 = escapeHtml(infos['discord3'].toString()), discord4 = escapeHtml(infos['discord4'].toString()), discord5 = escapeHtml(infos['discord5'].toString());
  3466.             var mdp = crypto.createHash('sha1');
  3467.             mdp.update('combo'+mdp_actuel);
  3468.             var res_mdp = mdp.digest('hex');
  3469.             var erreurs = '';
  3470.             var typemembre = socket.typemembre;
  3471.             if (pseudo.length < 3 || pseudo.length > 30) { erreurs += 'Your username should contain between 3 and 30 characters. '; }
  3472.             else if (!(valide_pseudo(pseudo))) { erreurs += 'The username is invalid. Please use alphanumeric characters. '; }
  3473.             if (nom.length > 200) { erreurs += 'Sorry, your last name is too long. '; }
  3474.             else if (!(valide_pseudo(nom))) { erreurs += 'The last name is invalid. Please use alphanumeric characters. '; }
  3475.             if (prenom.length > 200) { erreurs += 'Sorry, your first name is too long. '; }
  3476.             else if (!(valide_pseudo(twitch))) { erreurs += 'The Twitch username is invalid. Please use alphanumeric characters. '; }
  3477.             if (twitch.length > 200) { erreurs += 'Sorry, your Twitch username is too long. '; }
  3478.             else if (!(valide_pseudo(prenom))) { erreurs += 'The first name is invalid. Please use alphanumeric characters. '; }
  3479.             if (email.length > 200) { erreurs += 'Sorry, your e-mail is too long. '; }
  3480.             else if (!(valide_email(email))) { erreurs += 'The e-mail address is invalid. '; }
  3481.             if (email != socket.email && email != email2) { erreurs += 'The two e-mail addresses to not match. '; }
  3482.             else if (email != socket.email) { typemembre = 0; }
  3483.             if (nouveau_mdp != 'da39a3ee5e6b4b0d3255bfef95601890afd80709' && nouveau_mdp != nouveau_mdp2) { erreurs += 'Your two passwords do not match. '; }
  3484.             else if (nouveau_mdp != 'da39a3ee5e6b4b0d3255bfef95601890afd80709' && socket.mdp != res_mdp) { erreurs += 'You didn\'t type your current password correctly '; }
  3485.             if (erreurs == '') {
  3486.                 if (nouveau_mdp != 'da39a3ee5e6b4b0d3255bfef95601890afd80709') {
  3487.                     var mdp2 = crypto.createHash('sha1');
  3488.                     mdp2.update('combo'+nouveau_mdp);
  3489.                     var res_mdp2 = mdp2.digest('hex');
  3490.                 }
  3491.                 else { var res_mdp2 = socket.mdp; }
  3492.                 connection.query('UPDATE membres SET pseudo = ?, email = ?, twitch = ?, typemembre = ?, nom = ?, prenom = ?, nom_afficher = ?, prenom_afficher = ?, pays = ?, sexe = ?, sexe_afficher = ?, mdp = ?, infos1 = ?, infos2 = ?, infos3 = ?, infos4 = ?, infos5 = ?, discord1 = ?, discord2 = ?, discord3 = ?, discord4 = ?, discord5 = ?, discord = ?, discord_afficher = ?, email_afficher = ? WHERE id = ? AND typemembre >= 1', [pseudo, email, twitch, typemembre, nom, prenom, nom_afficher, prenom_afficher, pays, sexe, sexe_afficher, res_mdp2, infos1, infos2, infos3, infos4, infos5, discord1, discord2, discord3, discord4, discord5, discord, afficher_discord, afficher_email, socket.identifiant], function (error, ok, fields) {
  3493.                     if (ok.affectedRows == 1) {
  3494.                     connection.query('SELECT * FROM membres WHERE id = ?', [socket.identifiant], function (error, verdict, fields) {
  3495.                         socket.pseudo = verdict[0]['pseudo'];
  3496.                         socket.fuseau = verdict[0]['fuseau'];
  3497.                         socket.identifiant = verdict[0]['id'];
  3498.                         socket.pays = verdict[0]['pays'];
  3499.                         socket.typemembre = verdict[0]['typemembre'];
  3500.                         socket.mdp = verdict[0]['mdp'];
  3501.                         if (email != socket.email) {
  3502.                             var message = {
  3503.                                 text:   "Hi!\n\nThank you for using Worldwide Combos. In order to validate your new e-mail address, please open the following link in your browser: https://www.worldwide-combos.com/validate?id="+socket.identifiant+"&token="+res_mdp2+". We are looking forward seeing you play with us!\n\nBest regards,\n\n Noël Nadal (Worldwide Combos admin).",
  3504.                                 from:   "Worldwide Combos <noreply@worldwide-combos.com>",
  3505.                                 to:     email,
  3506.                                 subject:    "Validate your Worldwide Combos account",
  3507.                                 attachment:
  3508.                                 [
  3509.                                     {data:"<html>Hi!<br><br>Thank you for using Worldwide Combos. In order to validate your new e-mail address, please click <a href='https://www.worldwide-combos.com/validate?id="+socket.identifiant+"&token="+res_mdp2+"'>here</a>. We are looking forward seeing you play with us!<br><br>Best regards,<br><br>Noël Nadal (Worldwide Combos admin).</html>", alternative:true}
  3510.                                 ]
  3511.                             };
  3512.                             server_noreply.send(message, function(err, message) { console.log(getDateTime() + 'Courriel de validation de compte envoyé à ' + socket.pseudo + '.'); });
  3513.                         }
  3514.                         socket.email = verdict[0]['email'];
  3515.                         socket.duree_solo = verdict[0]['duree_solo'];
  3516.                                 socket.handicap_solo = verdict[0]['handicap_solo'];
  3517.                             solo_deco();
  3518.                         multi_deco();
  3519.                         socket.emit('succes_maj_profil', verdict);
  3520.                     });
  3521.                     }
  3522.                 });
  3523.             }
  3524.             else { socket.emit('echec_maj_profil', erreurs); }
  3525.         }
  3526.     });
  3527.    
  3528.    
  3529.     // modification des options de jeu
  3530.     socket.on('maj_options', function(infos) {
  3531.         if ('lr' in infos && 'ld' in infos && 'vr' in infos && 'vd' in infos && 'sifflet' in infos && 'ligne_suppl' in infos && 'design' in infos && 'duree_solo' in infos && 'limite_ko_solo' in infos && 'handicap_solo' in infos && 'gauche' in infos && 'droite' in infos && 'bas1' in infos && 'bas2' in infos && 'rotation1' in infos && 'rotation2' in infos && 'rotation3' in infos && 'hold' in infos && 'pret' in infos && 'r1' in infos && 'g1' in infos && 'b1' in infos && 'a1' in infos && 'r2' in infos && 'g2' in infos && 'b2' in infos && 'a2' in infos && 'r3' in infos && 'g3' in infos && 'b3' in infos && 'a3' in infos && 'r4' in infos && 'g4' in infos && 'b4' in infos && 'a4' in infos && 'r5' in infos && 'g5' in infos && 'b5' in infos && 'a5' in infos && 'r6' in infos && 'g6' in infos && 'b6' in infos && 'a6' in infos && 'r7' in infos && 'g7' in infos && 'b7' in infos && 'a7' in infos && 'rj' in infos && 'gj' in infos && 'bj' in infos && 'aj' in infos && 'rh' in infos && 'gh' in infos && 'bh' in infos && 'ah' in infos) {
  3532.             var lr = parseInt(escapeHtml(infos['lr'].toString())), ld = parseInt(escapeHtml(infos['ld'].toString())), vr = parseInt(escapeHtml(infos['vr'].toString())), vd = parseInt(escapeHtml(infos['vd'].toString()));
  3533.             var droite = escapeHtml(infos['droite'].toString()), gauche = escapeHtml(infos['gauche'].toString()), bas1 = escapeHtml(infos['bas1'].toString()), bas2 = escapeHtml(infos['bas2'].toString());
  3534.             var rotation1 = escapeHtml(infos['rotation1'].toString()), rotation2 = escapeHtml(infos['rotation2'].toString()), rotation3 = escapeHtml(infos['rotation3'].toString());
  3535.             var hold = escapeHtml(infos['hold'].toString()), pret = escapeHtml(infos['pret'].toString());
  3536.             var duree_solo = escapeHtml(infos['duree_solo'].toString());
  3537.             var limite_ko_solo = escapeHtml(infos['limite_ko_solo'].toString());
  3538.             var handicap_solo = escapeHtml(infos['handicap_solo'].toString());
  3539.             var sifflet = parseInt(escapeHtml(infos['sifflet'].toString())), ligne_suppl = parseInt(escapeHtml(infos['ligne_suppl'].toString())), design = parseInt(escapeHtml(infos['design'].toString()));
  3540.             var r1 = parseInt(escapeHtml(infos['r1'].toString())), g1 = parseInt(escapeHtml(infos['g1'].toString())), b1 = parseInt(escapeHtml(infos['b1'].toString())), a1 = parseFloat(escapeHtml(infos['a1'].toString())), r2 = parseInt(escapeHtml(infos['r2'].toString())), g2 = parseInt(escapeHtml(infos['g2'].toString())), b2 = parseInt(escapeHtml(infos['b2'].toString())), a2 = parseFloat(escapeHtml(infos['a2'].toString())), r3 = parseInt(escapeHtml(infos['r3'].toString())), g3 = parseInt(escapeHtml(infos['g3'].toString())), b3 = parseInt(escapeHtml(infos['b3'].toString())), a3 = parseFloat(escapeHtml(infos['a3'].toString())), r4 = parseInt(escapeHtml(infos['r4'].toString())), g4 = parseInt(escapeHtml(infos['g4'].toString())), b4 = parseInt(escapeHtml(infos['b4'].toString())), a4 = parseFloat(escapeHtml(infos['a4'].toString())), r5 = parseInt(escapeHtml(infos['r5'].toString())), g5 = parseInt(escapeHtml(infos['g5'].toString())), b5 = parseInt(escapeHtml(infos['b5'].toString())), a5 = parseFloat(escapeHtml(infos['a5'].toString())), r6 = parseInt(escapeHtml(infos['r6'].toString())), g6 = parseInt(escapeHtml(infos['g6'].toString())), b6 = parseInt(escapeHtml(infos['b6'].toString())), a6 = parseFloat(escapeHtml(infos['a6'].toString())), r7 = parseInt(escapeHtml(infos['r7'].toString())), g7 = parseInt(escapeHtml(infos['g7'].toString())), b7 = parseInt(escapeHtml(infos['b7'].toString())), a7 = parseFloat(escapeHtml(infos['a7'].toString())), rj = parseInt(escapeHtml(infos['rj'].toString())), gj = parseInt(escapeHtml(infos['gj'].toString())), bj = parseInt(escapeHtml(infos['bj'].toString())), aj = parseFloat(escapeHtml(infos['aj'].toString())), rh = parseInt(escapeHtml(infos['rh'].toString())), gh = parseInt(escapeHtml(infos['gh'].toString())), bh = parseInt(escapeHtml(infos['bh'].toString())), ah = parseFloat(escapeHtml(infos['ah'].toString()));
  3541.             if (lr >= 0 && ld >= 0 && vr >= 0 && vd >= 0 && lr <= 1000 && ld <= 1000 && vr <= 1000 && vd <= 1000 && duree_solo >= 1 && duree_solo <= 10 && limite_ko_solo >= 0 && handicap_solo >= 0  && handicap_solo <= 2 && handicap_solo != 1) {
  3542.                 connection.query('UPDATE membres SET lr = ?, ld = ?, vr = ?, vd = ?, sifflet = ?, ligne_suppl = ?, design = ?, droite = ?, gauche = ?, bas1 = ?, bas2 = ?, rotation1 = ?, rotation2 = ?, rotation3 = ?, hold = ?, pret = ?, duree_solo = ?, limite_ko_solo = ?, handicap_solo = ?, r1 = ?, g1 = ?, b1 = ?, a1 = ?, r2 = ?, g2 = ?, b2 = ?, a2 = ?, r3 = ?, g3 = ?, b3 = ?, a3 = ?, r4 = ?, g4 = ?, b4 = ?, a4 = ?, r5 = ?, g5 = ?, b5 = ?, a5 = ?, r6 = ?, g6 = ?, b6 = ?, a6 = ?, r7 = ?, g7 = ?, b7 = ?, a7 = ?, rj = ?, gj = ?, bj = ?, aj = ?, rh = ?, gh = ?, bh = ?, ah = ? WHERE id = ?', [lr, ld, vr, vd, sifflet, ligne_suppl, design, droite, gauche, bas1, bas2, rotation1, rotation2, rotation3, hold, pret, duree_solo, limite_ko_solo, handicap_solo, r1, g1, b1, a1, r2, g2, b2, a2, r3, g3, b3, a3, r4, g4, b4, a4, r5, g5, b5, a5, r6, g6, b6, a6, r7, g7, b7, a7, rj, gj, bj, aj, rh, gh, bh, ah, socket.identifiant], function (error, modif, fields) {
  3543.                     connection.query('SELECT * FROM membres WHERE id = ?', [socket.identifiant], function (error, donnees, fields) {
  3544.                         socket.emit('succes_maj_options', donnees[0]);
  3545.                     });
  3546.                 });
  3547.             }
  3548.             else { socket.emit('echec_maj_options', ''); }
  3549.         }
  3550.         else { console.log(infos); }
  3551.     });
  3552.    
  3553.     // pour l'affichage du formulaire d'inscription, on génère un captcha
  3554.     socket.on('demande_inscription', function () {
  3555.         console.log(getDateTime() + socket.pseudo + ' ouvre le formulaire d\'inscription.');
  3556.         var c = captcha.create();
  3557.         socket.captcha = c.text;
  3558.         socket.emit('donnees_inscription', c.data);
  3559.     });
  3560.    
  3561.     // formulaire d'inscription reçu :D
  3562.     socket.on('tentative_inscription', function (infos) {
  3563.         var erreurs = '', ok = 1, mdp = escapeHtml(infos['mdp'].toString()), mdp2 = escapeHtml(infos['mdp2'].toString());
  3564.         var pseudo = escapeHtml(infos['pseudo'].toString()), email = escapeHtml(infos['email'].toString()), captcha = escapeHtml(infos['captcha'].toString());
  3565.         if (mdp != mdp2) { ok = 0; erreurs += 'The two passwords do not match. '; }
  3566.         if (captcha != socket.captcha) { ok = 0; erreurs += 'You misread the captcha. '; }
  3567.         console.log(getDateTime() + pseudo + ' tente de s\'inscrire sur le site.');
  3568.         connection.query('SELECT pseudo FROM membres WHERE pseudo = ?', [pseudo], function (error, verdict, fields) {
  3569.             if (verdict.length > 0) { ok = 0; erreurs += 'This username is already taken. '; }
  3570.             else if (pseudo.length < 3 || pseudo.length > 30) {
  3571.                 ok = 0; erreurs += 'The username\'s length should be between 3 and 30 inclusive. ';
  3572.             }
  3573.             else if (!(valide_pseudo(pseudo))) { ok = 0; erreurs += 'This username contains forbidden characters. '; }
  3574.             connection.query('SELECT email FROM membres WHERE email = ?', [email], function (error, verdict2, fields) {
  3575.                 if (verdict2.length > 0) { ok = 0; erreurs += 'This e-mail address is already taken. '; }
  3576.                 else if (email.length > 200) { ok = 0; erreurs += 'This e-mail address is too long.'; }
  3577.                 else if (!(valide_email(email))) { ok = 0; erreurs += 'This e-mail address is not valid.'; }
  3578.                 if (ok == 0) {
  3579.                     console.log(getDateTime() + 'C\'est raté pour cette fois...');
  3580.                     socket.emit('inscription_echouee', erreurs);
  3581.                 }
  3582.                 else {
  3583.                     var mdph = crypto.createHash('sha1');
  3584.                     mdph.update('combo'+mdp);
  3585.                     var res_mdp = mdph.digest('hex');
  3586.                     connection.query('UPDATE membres SET pseudo = ?, mdp = ?, email = ?, typemembre = 0 WHERE id = ?', [pseudo, res_mdp, email, socket.identifiant], function (error, inscrit, fields) {
  3587.                         connection.query('SELECT * FROM membres WHERE id = ?', [socket.identifiant], function (error, verdict, fields) {
  3588.                             if (verdict.length == 0) { erreurs = 'Something weird happened. Please refresh the page.'; socket.emit('inscription_echouee', erreurs); return; }
  3589.                             socket.pseudo = verdict[0]['pseudo'];
  3590.                             socket.fuseau = verdict[0]['fuseau'];
  3591.                             socket.classement1 = verdict[0]['elo1'];
  3592.                             socket.classement2 = verdict[0]['elo2'];
  3593.                             socket.identifiant = verdict[0]['id'];
  3594.                             socket.pays = verdict[0]['pays'];
  3595.                             socket.sprint = verdict[0]['sprint'];
  3596.                             socket.sprint10 = verdict[0]['sprint10'];
  3597.                             socket.survivor = verdict[0]['survivor'];
  3598.                             socket.ligne_suppl = verdict[0]['ligne_suppl'];
  3599.                             socket.typemembre = verdict[0]['typemembre'];
  3600.                             socket.email = verdict[0]['email'];
  3601.                             socket.mdp = verdict[0]['mdp'];
  3602.                             socket.duree_solo = verdict[0]['duree_solo'];
  3603.                                             socket.handicap_solo = verdict[0]['handicap_solo'];
  3604.                                     console.log(getDateTime() + pseudo + ' s\'est inscrit sur le site ! :D');
  3605.                             var message = {
  3606.                                 text:   "Hi!\n\nThank you for making an account on Worldwide Combos. In order to validate your e-mail address, please open the following link in your browser: https://www.worldwide-combos.com/validate?id="+socket.identifiant+"&token="+res_mdp+". We are looking forward seeing you play with us!\n\nBest regards,\n\n Noël Nadal (Worldwide Combos admin).",
  3607.                                 from:   "Worldwide Combos <noreply@worldwide-combos.com>",
  3608.                                 to:     email,
  3609.                                 subject:    "Validate your Worldwide Combos account",
  3610.                                 attachment:
  3611.                                 [
  3612.                                     {data:"<html>Hi!<br><br>Thank you for making an account on Worldwide Combos. In order to validate your e-mail address, please click <a href='https://www.worldwide-combos.com/validate?id="+socket.identifiant+"&token="+res_mdp+"'>here</a>. We are looking forward seeing you play with us!<br><br>Best regards,<br><br>Noël Nadal (Worldwide Combos admin).</html>", alternative:true}
  3613.                                 ]
  3614.                             };
  3615.                             server_noreply.send(message, function(err, message) { console.log(getDateTime() + 'Courriel de validation de compte envoyé à ' + pseudo + '.'); });
  3616.                             socket.emit('inscription_reussie', verdict[0]);
  3617.                         });
  3618.                     });
  3619.                 }
  3620.             });
  3621.         });
  3622.     });
  3623.     } /* FIN CONNEXION / INSCRIPTION / OPTIONS */
  3624.    
  3625.     /* DEBUT STATISTIQUES */ {
  3626.     socket.on('demander_stats', function(pseudostats) {
  3627.         var pseudo = escapeHtml(pseudostats);
  3628.         connection.query('SELECT * FROM membres WHERE pseudo = ?', [pseudo], function (error, membres, fields) {
  3629.             if (membres.length == 0) { socket.emit('livraison_stats', {verdict: 0}); }
  3630.             else {
  3631.                 connection.query('SELECT * FROM solo WHERE id_membre = ? ORDER BY date', [membres[0]['id']], function (error, solo, fields) {
  3632.                     connection.query('SELECT parties.joueur1 AS joueur1, parties.date AS date, parties.elo1_avant AS elo1_avant, parties.elo2_avant AS elo2_avant, parties.elo1_apres AS elo1_apres, parties.elo2_apres AS elo2_apres, membres.pseudo AS adv_pseudo, membres.pays AS adv_pays FROM parties INNER JOIN membres ON (membres.id = parties.joueur2 OR membres.id = parties.joueur1) AND membres.id != ? WHERE joueur1 = ? OR joueur2 = ? ORDER BY date', [membres[0]['id'], membres[0]['id'], membres[0]['id']], function (error, parties, fields) {
  3633.                         socket.emit('livraison_stats', {verdict: 1, membres: membres[0], solo: solo, parties: parties});
  3634.                     });
  3635.                 });
  3636.             }
  3637.         });
  3638.     });
  3639.    
  3640.     // classements
  3641.     socket.on('stats_classements', function(typeClassement) {
  3642.         if (typeClassement == 'multiplayer') {
  3643.             connection.query('SELECT MIN(classement1) AS mcl FROM parties LEFT JOIN matches ON matches.id = parties.id_match WHERE parties.joueur1 = ? AND date < DATE_SUB(NOW(), INTERVAL 2 MINUTE) AND (id_match = 0 OR tournoi > 0) AND classement1 > 0', [socket.identifiant], function (error, cla, fields) {
  3644.                 connection.query('SELECT MIN(classement2) AS mcl FROM parties LEFT JOIN matches ON matches.id = parties.id_match WHERE parties.joueur2 = ? AND date < DATE_SUB(NOW(), INTERVAL 2 MINUTE) AND (id_match = 0 OR tournoi > 0) AND classement1 > 0', [socket.identifiant], function (error, clb, fields) {
  3645.                     connection.query('SELECT elo1_apres AS elo, date FROM parties LEFT JOIN matches ON matches.id = parties.id_match WHERE parties.joueur1 = ? AND date < DATE_SUB(NOW(), INTERVAL 1 DAY) AND (id_match = 0 OR tournoi > 0) ORDER BY date DESC LIMIT 0, 1', [socket.identifiant], function (error, elo24a, fields) {
  3646.                         connection.query('SELECT elo2_apres AS elo, date FROM parties LEFT JOIN matches ON matches.id = parties.id_match WHERE parties.joueur2 = ? AND date < DATE_SUB(NOW(), INTERVAL 1 DAY) AND (id_match = 0 OR tournoi > 0) ORDER BY date DESC LIMIT 0, 1', [socket.identifiant], function (error, elo24b, fields) {
  3647.                             connection.query('SELECT elo1_apres AS elo, date FROM parties LEFT JOIN matches ON matches.id = parties.id_match WHERE parties.joueur1 = ? AND date < DATE_SUB(NOW(), INTERVAL 1 MONTH) AND (id_match = 0 OR tournoi > 0) ORDER BY date DESC LIMIT 0, 1', [socket.identifiant], function (error, elo1a, fields) {
  3648.                                 connection.query('SELECT elo2_apres AS elo, date FROM parties LEFT JOIN matches ON matches.id = parties.id_match WHERE parties.joueur2 = ? AND date < DATE_SUB(NOW(), INTERVAL 1 MONTH) AND (id_match = 0 OR tournoi > 0) ORDER BY date DESC LIMIT 0, 1', [socket.identifiant], function (error, elo1b, fields) {
  3649.                                     connection.query('SELECT classement1 AS cl, date FROM parties LEFT JOIN matches ON matches.id = parties.id_match WHERE parties.joueur1 = ? AND date < DATE_SUB(NOW(), INTERVAL 1 DAY) AND (id_match = 0 OR tournoi > 0) AND classement1 > 0 ORDER BY date DESC LIMIT 0, 1', [socket.identifiant], function (error, cl24a, fields) {
  3650.                                         connection.query('SELECT classement2 AS cl, date FROM parties LEFT JOIN matches ON matches.id = parties.id_match WHERE parties.joueur2 = ? AND date < DATE_SUB(NOW(), INTERVAL 1 DAY) AND (id_match = 0 OR tournoi > 0) AND classement2 > 0 ORDER BY date DESC LIMIT 0, 1', [socket.identifiant], function (error, cl24b, fields) {
  3651.                                             connection.query('SELECT classement1 AS cl, date FROM parties LEFT JOIN matches ON matches.id = parties.id_match WHERE parties.joueur1 = ? AND date < DATE_SUB(NOW(), INTERVAL 1 MONTH) AND (id_match = 0 OR tournoi > 0) AND classement1 > 0 ORDER BY date DESC LIMIT 0, 1', [socket.identifiant], function (error, cl1a, fields) {
  3652.                                                 connection.query('SELECT classement2 AS cl, date FROM parties LEFT JOIN matches ON matches.id = parties.id_match WHERE parties.joueur2 = ? AND date < DATE_SUB(NOW(), INTERVAL 1 MONTH) AND (id_match = 0 OR tournoi > 0) AND classement2 > 0 ORDER BY date DESC LIMIT 0, 1', [socket.identifiant], function (error, cl1b, fields) {
  3653.                                                     if (elo24a.length > 0 && (elo24b.length == 0 || elo24a[0]['date'] > elo24b[0]['date'])) { var elo24 = elo24a[0]['elo']; } else if (elo24b.length == 0) { var elo24 = 1000; } else { var elo24 = elo24b[0]['elo']; }
  3654.                                                     if (elo1a.length > 0 && (elo1b.length == 0 || elo1a[0]['date'] > elo1b[0]['date'])) { var elo1 = elo1a[0]['elo']; } else if (elo1b.length == 0) { var elo1 = 1000; } else { var elo1 = elo1b[0]['elo']; }
  3655.                                                     if (cl24a.length > 0 && (cl24b.length == 0 || cl24a[0]['date'] > cl24b[0]['date'])) { var cl24 = cl24a[0]['cl']; } else if (cl24b.length == 0) { var cl24 = 1000; } else { var cl24 = cl24b[0]['cl']; }
  3656.                                                     if (cl1a.length > 0 && (cl1b.length == 0 || cl1a[0]['date'] > cl1b[0]['date'])) { var cl1 = cl1a[0]['cl']; } else if (cl1b.length == 0) { var cl1 = 1000; } else { var cl1 = cl1b[0]['cl']; }
  3657.                                                     if (cla.length+clb.length == 0) { var cl = 0; }
  3658.                                                     else if (cla.length == 0) { var cl = clb[0]['mcl']; }
  3659.                                                     else if (clb.length == 0) { var cl = cla[0]['mcl']; }
  3660.                                                     else { var cl = Math.min(cla[0]['mcl'], clb[0]['mcl']); }
  3661.                                                     socket.emit('stats_classements', {typeClassement: 'multiplayer', cl: cl, elo24: elo24, elo1: elo1, cl24: cl24, cl1: cl1});
  3662.                                                 });
  3663.                                             });
  3664.                                         });
  3665.                                     });
  3666.                                 });
  3667.                             });
  3668.                         });
  3669.                     });
  3670.                 });
  3671.             });
  3672.         }
  3673.         else if (typeClassement == 'ghostbuster') {
  3674.             connection.query('SELECT MIN(classement) AS mcl FROM solo WHERE id_membre = ? AND date < DATE_SUB(NOW(), INTERVAL 2 MINUTE) AND classement > 0', [socket.identifiant], function (error, cl, fields) {
  3675.                 connection.query('SELECT elo1_apres AS elo, date FROM solo WHERE id_membre = ? AND date < DATE_SUB(NOW(), INTERVAL 1 DAY) ORDER BY date DESC LIMIT 0, 1', [socket.identifiant], function (error, elo24, fields) {
  3676.                     connection.query('SELECT elo1_apres AS elo, date FROM solo WHERE id_membre = ? AND date < DATE_SUB(NOW(), INTERVAL 1 MONTH) ORDER BY date DESC LIMIT 0, 1', [socket.identifiant], function (error, elo1, fields) {
  3677.                         connection.query('SELECT classement AS cl, date FROM solo WHERE id_membre = ? AND date < DATE_SUB(NOW(), INTERVAL 1 DAY) AND classement > 0 ORDER BY date DESC LIMIT 0, 1', [socket.identifiant], function (error, cl24, fields) {
  3678.                             connection.query('SELECT classement AS cl, date FROM solo WHERE id_membre = ? AND date < DATE_SUB(NOW(), INTERVAL 1 MONTH) AND classement > 0 ORDER BY date DESC LIMIT 0, 1', [socket.identifiant], function (error, cl1, fields) {
  3679.                                 if (cl.length == 0) { var vcl = 0; } else { var vcl = cl[0]['mcl']; }
  3680.                                 if (elo24.length == 0) { var velo24 = 1000; } else { var velo24 = elo24[0]['elo']; }
  3681.                                 if (elo1.length == 0) { var velo1 = 1000; } else { var velo1 = elo1[0]['elo']; }
  3682.                                 if (cl24.length == 0) { var vcl24 = 0; } else { var vcl24 = cl24[0]['cl']; }
  3683.                                 if (cl1.length == 0) { var vcl1 = 0; } else { var vcl1 = cl1[0]['cl']; }
  3684.                                 socket.emit('stats_classements', {typeClassement: 'ghostbuster', cl: vcl, elo24: velo24, elo1: velo1, cl24: vcl24, cl1: vcl1});
  3685.                             });
  3686.                         });
  3687.                     });
  3688.                 });
  3689.             });
  3690.         }
  3691.         else if (typeClassement == 'sprint') {
  3692.             connection.query('SELECT MIN(classement) AS mcl FROM sprint WHERE id_membre = ? AND date < DATE_SUB(NOW(), INTERVAL 2 MINUTE) AND classement > 0', [socket.identifiant], function (error, cl, fields) {
  3693.                 connection.query('SELECT MIN(temps) AS elo, date FROM sprint WHERE id_membre = ? AND date < DATE_SUB(NOW(), INTERVAL 1 DAY) ORDER BY date DESC LIMIT 0, 1', [socket.identifiant], function (error, elo24, fields) {
  3694.                     connection.query('SELECT MIN(temps) AS elo, date FROM sprint WHERE id_membre = ? AND date < DATE_SUB(NOW(), INTERVAL 1 MONTH) ORDER BY date DESC LIMIT 0, 1', [socket.identifiant], function (error, elo1, fields) {
  3695.                         connection.query('SELECT classement AS cl, date FROM sprint WHERE id_membre = ? AND date < DATE_SUB(NOW(), INTERVAL 1 DAY) AND classement > 0 ORDER BY date DESC LIMIT 0, 1', [socket.identifiant], function (error, cl24, fields) {
  3696.                             connection.query('SELECT classement AS cl, date FROM sprint WHERE id_membre = ? AND date < DATE_SUB(NOW(), INTERVAL 1 MONTH) AND classement > 0 ORDER BY date DESC LIMIT 0, 1', [socket.identifiant], function (error, cl1, fields) {
  3697.                                 if (cl.length == 0) { var vcl = 0; } else { var vcl = cl[0]['mcl']; }
  3698.                                 if (elo24.length == 0) { var velo24 = 0; } else { var velo24 = elo24[0]['elo']; }
  3699.                                 if (elo1.length == 0) { var velo1 = 0; } else { var velo1 = elo1[0]['elo']; }
  3700.                                 if (cl24.length == 0) { var vcl24 = 0; } else { var vcl24 = cl24[0]['cl']; }
  3701.                                 if (cl1.length == 0) { var vcl1 = 0; } else { var vcl1 = cl1[0]['cl']; }
  3702.                                 socket.emit('stats_classements', {typeClassement: 'sprint', cl: vcl, elo24: velo24, elo1: velo1, cl24: vcl24, cl1: vcl1});
  3703.                             });
  3704.                         });
  3705.                     });
  3706.                 });
  3707.             });
  3708.         }
  3709.         else if (typeClassement == 'survivor') {
  3710.             connection.query('SELECT MIN(classement) AS mcl FROM survivor WHERE id_membre = ? AND date < DATE_SUB(NOW(), INTERVAL 2 MINUTE) AND classement > 0', [socket.identifiant], function (error, cl, fields) {
  3711.                 connection.query('SELECT MAX(temps) AS elo, date FROM survivor WHERE id_membre = ? AND date < DATE_SUB(NOW(), INTERVAL 1 DAY) ORDER BY date DESC LIMIT 0, 1', [socket.identifiant], function (error, elo24, fields) {
  3712.                     connection.query('SELECT MAX(temps) AS elo, date FROM survivor WHERE id_membre = ? AND date < DATE_SUB(NOW(), INTERVAL 1 MONTH) ORDER BY date DESC LIMIT 0, 1', [socket.identifiant], function (error, elo1, fields) {
  3713.                         connection.query('SELECT classement AS cl, date FROM survivor WHERE id_membre = ? AND date < DATE_SUB(NOW(), INTERVAL 1 DAY) AND classement > 0 ORDER BY date DESC LIMIT 0, 1', [socket.identifiant], function (error, cl24, fields) {
  3714.                             connection.query('SELECT classement AS cl, date FROM survivor WHERE id_membre = ? AND date < DATE_SUB(NOW(), INTERVAL 1 MONTH) AND classement > 0 ORDER BY date DESC LIMIT 0, 1', [socket.identifiant], function (error, cl1, fields) {
  3715.                                 if (cl.length == 0) { var vcl = 0; } else { var vcl = cl[0]['mcl']; }
  3716.                                 if (elo24.length == 0) { var velo24 = 0; } else { var velo24 = elo24[0]['elo']; }
  3717.                                 if (elo1.length == 0) { var velo1 = 0; } else { var velo1 = elo1[0]['elo']; }
  3718.                                 if (cl24.length == 0) { var vcl24 = 0; } else { var vcl24 = cl24[0]['cl']; }
  3719.                                 if (cl1.length == 0) { var vcl1 = 0; } else { var vcl1 = cl1[0]['cl']; }
  3720.                                 socket.emit('stats_classements', {typeClassement: 'survivor', cl: vcl, elo24: velo24, elo1: velo1, cl24: vcl24, cl1: vcl1});
  3721.                             });
  3722.                         });
  3723.                     });
  3724.                 });
  3725.             });
  3726.         }
  3727.     });
  3728.    
  3729.     // classements
  3730.     socket.on('demander_classements', function(elo) {
  3731.         if ('1' in elo && '2' in elo && '3' in elo && '4' in elo && '5' in elo && '6' in elo) {
  3732.             var rat1 = parseFloat(elo['1'].toString()), rat2 = parseFloat(elo['2'].toString()), st40 = parseFloat(elo['3'].toString()), trn = parseFloat(elo['4'].toString()), sv = parseFloat(elo['5'].toString()), s10 = parseFloat(elo['6'].toString());
  3733.             connection.query('SELECT COUNT(*) AS cl FROM membres WHERE elo1 >= ? AND typemembre < 3 AND typemembre > 0 AND elo1 != 1000', [rat1+0.001], function (error, elo1, fields) {
  3734.                 connection.query('SELECT COUNT(*) AS cl FROM membres WHERE elo2 >= ? AND typemembre < 3 AND typemembre > 0 AND elo2 != 1000', [rat2+0.001], function (error, elo2, fields) {
  3735.                    connection.query('SELECT COUNT(*) AS cl FROM membres WHERE sprint > 0 AND sprint <= ? AND typemembre < 3 AND typemembre > 0', [st40-0.00001], function (error, sp40, fields) {
  3736.                         connection.query('SELECT COUNT(*) AS cl FROM membres WHERE tournoi > ? AND typemembre < 3 AND typemembre > 0', [trn+0.00001], function (error, tournoi, fields) {
  3737.                             connection.query('SELECT COUNT(*) AS cl FROM membres WHERE survivor > ? AND typemembre < 3 AND typemembre > 0', [sv+0.00001], function (error, survivor, fields) {
  3738.                                 connection.query('SELECT COUNT(*) AS cl FROM membres WHERE sprint10 > 0 AND sprint10 <= ? AND typemembre < 3 AND typemembre > 0', [s10-0.00001], function (error, sp10, fields) {
  3739.                                     socket.emit('livraison_classements', {c1: 1+elo1[0]['cl'], c2: 1+elo2[0]['cl'], c3: 1+sp40[0]['cl'], c4: 1+tournoi[0]['cl'], c5: 1+survivor[0]['cl'], c6: 1+sp10[0]['cl']});
  3740.                                 });
  3741.                             });
  3742.                         });
  3743.                     });
  3744.                 });
  3745.             });
  3746.         }
  3747.     });
  3748.    
  3749.     // classements complets
  3750.     socket.on('demander_classements_complets', function(requete) {
  3751.         if ('type' in requete && 'debut' in requete) {
  3752.             var type = escapeHtml(requete['type'].toString());
  3753.             var debut = parseInt(escapeHtml(requete['debut'].toString()));
  3754.             if (type == 'multiplayer') {
  3755.                 connection.query('SELECT pseudo, pays, elo2 AS elo, IF(pays = "WHO", 0, 1) AS ap FROM membres WHERE typemembre < 3 AND typemembre > 0 && elo2 != 1000 ORDER BY elo DESC, ap DESC LIMIT ?, 20', [debut], function (error, elo2, fields) {
  3756.                     socket.emit('livraison_classements_complets', elo2);
  3757.                 });
  3758.             }
  3759.             else if (type == 'ghostbuster') {
  3760.                 connection.query('SELECT pseudo, pays, elo1 AS elo, IF(pays = "WHO", 0, 1) AS ap FROM membres WHERE typemembre < 3 AND typemembre > 0 && elo1 != 1000 ORDER BY elo DESC, ap DESC LIMIT ?, 20', [debut], function (error, elo1, fields) {
  3761.                     socket.emit('livraison_classements_complets', elo1);
  3762.                 });
  3763.             }
  3764.             else if (type == 'sprint') {
  3765.                 connection.query('SELECT membres.id, membres.pseudo, membres.pays, membres.typemembre, sprint/1000 AS elo, IF(pays = "WHO", 0, 1) AS ap FROM membres WHERE membres.typemembre < 3 AND membres.typemembre > 0 AND sprint > 0 ORDER BY elo, ap DESC LIMIT ?, 20', [debut], function (error, sprint, fields) {
  3766.                     socket.emit('livraison_classements_complets', sprint);
  3767.                 });
  3768.             }
  3769.             else if (type == 'tournament') {
  3770.                 connection.query('SELECT pseudo, pays, tournoi AS elo, IF(pays = "WHO", 0, 1) AS ap FROM membres WHERE typemembre < 3 AND typemembre > 0 && tournoi != 0 ORDER BY elo DESC, ap DESC LIMIT ?, 20', [debut], function (error, tournoi, fields) {
  3771.                     socket.emit('livraison_classements_complets', tournoi);
  3772.                 });
  3773.             }
  3774.             else if (type == 'survivor') {
  3775.                 connection.query('SELECT membres.id, pseudo, pays, survivor/1000 AS elo, IF(pays = "WHO", 0, 1) AS ap FROM membres WHERE typemembre < 3 AND typemembre > 0 && survivor > 0 ORDER BY elo DESC, ap DESC LIMIT ?, 20', [debut], function (error, survivor, fields) {
  3776.                     socket.emit('livraison_classements_complets', survivor);
  3777.                 });
  3778.             }
  3779.             else if (type == 'sprint10') {
  3780.                 connection.query('SELECT membres.id, membres.pseudo, membres.pays, membres.typemembre, sprint10/1000 AS elo, IF(pays = "WHO", 0, 1) AS ap FROM membres WHERE membres.typemembre < 3 AND membres.typemembre > 0 AND sprint10 > 0 ORDER BY elo, ap DESC LIMIT ?, 20', [debut], function (error, sprint, fields) {
  3781.                     socket.emit('livraison_classements_complets', sprint);
  3782.                 });
  3783.             }
  3784.         }
  3785.     });
  3786.  
  3787.     // vérifier la validité d'un compte
  3788.     socket.on('verifier_pseudo', function(pseudonyme) {
  3789.         var pseudo = escapeHtml(pseudonyme.toString());
  3790.         connection.query('SELECT id FROM membres WHERE (typemembre = 1 OR typemembre = 2) AND pseudo = ?', [pseudo], function(error, v, fields) {
  3791.             socket.emit('verdict_verification_pseudo', {pseudo: pseudo, verdict: v.length});
  3792.         });
  3793.     });
  3794.    
  3795.     // suggestions pour inviter les joueurs avec le même niveau
  3796.     socket.on('suggestions_invitation', function() {
  3797.         if (socket.pseudo == '#') { socket.emit('deconnexion', ''); }
  3798.         else {
  3799.             connection.query('SELECT coeff_force FROM membres WHERE id = ?', [socket.identifiant], function (error, cf, fields) {
  3800.                 connection.query('SELECT pseudo, pays, ABS(? - coeff_force) AS moyenne FROM membres WHERE id != ? AND (typemembre = 1 OR typemembre = 2) AND derniereconnexion >= DATE_SUB(NOW(), INTERVAL 1 MONTH) ORDER BY moyenne LIMIT 0, 5', [cf[0]['coeff_force'], socket.identifiant], function (error, stats, fields) {
  3801.                     connection.query('SELECT membres.pseudo AS pseudo, membres.pays AS pays, matches.nb_manches AS nb_manches, matches.diff_manches AS diff_manches, matches.limite_ko AS limite_ko, matches.diff_victoire AS diff_victoire, matches.duree AS duree, matches.datedebut AS datedebut FROM matches INNER JOIN membres ON membres.id = joueur1 WHERE datedebut > NOW() AND joueur2 = ? AND confirmation = 0 AND matches.tournoi = 0 ORDER BY datedebut', [socket.identifiant], function (error1, recu, fields) {
  3802.                         connection.query('SELECT membres.pseudo AS pseudo, membres.pays AS pays, matches.nb_manches AS nb_manches, matches.diff_manches AS diff_manches, matches.limite_ko AS limite_ko, matches.diff_victoire AS diff_victoire, matches.duree AS duree, matches.datedebut AS datedebut FROM matches INNER JOIN membres ON membres.id = joueur2 WHERE datedebut > NOW() AND joueur1 = ? AND confirmation = 0 AND matches.tournoi = 0 ORDER BY datedebut', [socket.identifiant], function (error2, envoye, fields) {
  3803.                             connection.query('SELECT matches.id AS id, membres.pseudo AS pseudo, membres.pays AS pays, matches.nb_manches AS nb_manches, matches.diff_manches AS diff_manches, matches.limite_ko AS limite_ko, matches.diff_victoire AS diff_victoire, matches.duree AS duree, matches.datedebut AS datedebut FROM matches INNER JOIN membres ON (membres.id = joueur1 OR membres.id = joueur2) AND membres.id != ? WHERE (joueur1 = ? OR joueur2 = ?) AND confirmation = 1 AND matches.tournoi = 0 ORDER BY datedebut', [socket.identifiant, socket.identifiant, socket.identifiant], function (error3, confirme, fields) {
  3804.                                 //socket.emit('livraison_suggestions', {stats: stats, recu: recu, envoye: envoye, confirme: confirme});
  3805.                                 socket.emit('livraison_suggestions', {stats: stats, recu: recu, envoye: envoye, confirme: confirme});
  3806.                                 console.log(getDateTime());
  3807.                                 console.log(stats);
  3808.                             });
  3809.                         });
  3810.                     });
  3811.                 });
  3812.             });
  3813.         }
  3814.     });
  3815.    
  3816.     // prochains matches custom/tournois
  3817.     socket.on('prochains_matches', function() {
  3818.         connection.query('SELECT tournois.nom AS nom_tournoi, matches.id AS id, membres.pseudo AS pseudo, membres.pays AS pays, matches.tournoi AS tournoi, matches.nb_manches AS nb_manches, matches.diff_manches AS diff_manches, matches.limite_ko AS limite_ko, matches.diff_victoire AS diff_victoire, matches.duree AS duree, matches.datedebut AS datedebut FROM matches INNER JOIN membres ON (membres.id = joueur1 OR membres.id = joueur2) AND membres.id != ? LEFT JOIN tournois ON tournois.id = matches.tournoi WHERE (joueur1 = ? OR joueur2 = ?) AND confirmation = 1 ORDER BY datedebut', [socket.identifiant, socket.identifiant, socket.identifiant], function (error, confirme, fields) {
  3819.             socket.emit('prochains_matches', confirme);
  3820.         });
  3821.     });
  3822.    
  3823.     // prochains tournois
  3824.     socket.on('prochains_tournois', function() {
  3825.         connection.query('SELECT * FROM tournois WHERE datedebut > NOW() ORDER BY datedebut', function (error, confirme, fields) {
  3826.             socket.emit('prochains_tournois', confirme);
  3827.         });
  3828.     });
  3829.    
  3830.     // tournois en cours
  3831.     socket.on('direct_tournois', function() {
  3832.         connection.query('SELECT * FROM tournois WHERE fini = 0 AND datedebut < NOW() ORDER BY datedebut DESC', function (error, direct, fields) {
  3833.             socket.emit('direct_tournois', direct);
  3834.         });
  3835.     });
  3836.    
  3837.     // tournois déjà terminés
  3838.     socket.on('precedents_tournois', function() {
  3839.         connection.query('SELECT * FROM tournois WHERE fini = 1 ORDER BY datedebut DESC', function (error, passe, fields) {
  3840.             socket.emit('precedents_tournois', passe);
  3841.         });
  3842.     });
  3843.    
  3844.     // vérifier si quelqu'un s'est déjà inscrit au tournoi en question (ATTENTION MARCHE QUE POUR LE TOURNOI 1)
  3845.     socket.on('verifier_inscription', function(id_tournoi) {
  3846.         connection.query('SELECT datedebut FROM tournois WHERE id = ?', [parseInt(id_tournoi.toString())], function (error, date, fields) {
  3847.             if (date.length == 1) {
  3848.                 var ajd = new Date(date[0]['datedebut']);
  3849.                 var jour_semaine = ajd.getDay();
  3850.                 jour_semaine = (jour_semaine + 6) % 7;
  3851.                 ajd.setDate(ajd.getDate()-jour_semaine);
  3852.                 var mois = ajd.getMonth(), annee = ajd.getFullYear(), jour = ajd.getDate();
  3853.                 console.log(annee, mois, jour);
  3854.                 var verdict = 1;
  3855.                 fs.readFile(path.join(__dirname, 'calendrier/'+socket.identifiant+'/'+annee+'-'+mois+'-'+jour+'.txt'), 'utf8', function (err,donnees) {
  3856.                     if (donnees == undefined) { verdict = 0; }
  3857.                     else {
  3858.                     var ct = 0, jr = 0;
  3859.                     var okj = new Array(0, 0, 0, 0, 0, 0, 0), cj = 0;
  3860.                     for (var i = 0; i < 24; i++) {
  3861.                         for (j = 0; j < 7; j++) {
  3862.                             if (donnees[24*j+i] > 0) { okj[j] = 1; ct++; }
  3863.                         }
  3864.                     }
  3865.                     for (j = 0; j < 7; j++) { cj += okj[j]; }
  3866.                     if (ct < 21 || cj < 2) { verdict = 0; }     }
  3867.                 });
  3868.                 ajd.setDate(ajd.getDate()+7);
  3869.                 mois = ajd.getMonth(), annee = ajd.getFullYear(), jour = ajd.getDate();
  3870.                 console.log(annee, mois, jour);
  3871.                 fs.readFile(path.join(__dirname, 'calendrier/'+socket.identifiant+'/'+annee+'-'+mois+'-'+jour+'.txt'), 'utf8', function (err,donnees) {
  3872.                     if (donnees == undefined) { verdict = 0; }
  3873.                     else {
  3874.                     var ct = 0, jr = 0;
  3875.                     var okj = new Array(0, 0, 0, 0, 0, 0, 0), cj = 0;
  3876.                     for (var i = 0; i < 24; i++) {
  3877.                         for (j = 0; j < 7; j++) {
  3878.                             if (donnees[24*j+i] > 0) { okj[j] = 1; ct++; }
  3879.                         }
  3880.                     }
  3881.                     for (j = 0; j < 7; j++) { cj += okj[j]; }
  3882.                     if (ct < 21 || cj < 2) { verdict = 0; }  }  
  3883.                 });
  3884.                 ajd.setDate(ajd.getDate()+7);
  3885.                 mois = ajd.getMonth(), annee = ajd.getFullYear(), jour = ajd.getDate();
  3886.                 console.log(annee, mois, jour);
  3887.                 fs.readFile(path.join(__dirname, 'calendrier/'+socket.identifiant+'/'+annee+'-'+mois+'-'+jour+'.txt'), 'utf8', function (err,donnees) {
  3888.                     if (donnees == undefined) { verdict = 0; }
  3889.                     else {
  3890.                     var ct = 0, jr = 0;
  3891.                     var okj = new Array(0, 0, 0, 0, 0, 0, 0), cj = 0;
  3892.                     for (var i = 0; i < 24; i++) {
  3893.                         for (j = 0; j < 7; j++) {
  3894.                             if (donnees[24*j+i] > 0) { okj[j] = 1; ct++; }
  3895.                         }
  3896.                     }
  3897.                     for (j = 0; j < 7; j++) { cj += okj[j]; }
  3898.                     if (ct < 21 || cj < 2) { verdict = 0; } }    
  3899.                 });
  3900.                 ajd.setDate(ajd.getDate()+7);
  3901.                 mois = ajd.getMonth(), annee = ajd.getFullYear(), jour = ajd.getDate();
  3902.                 console.log(annee, mois, jour);
  3903.                 fs.readFile(path.join(__dirname, 'calendrier/'+socket.identifiant+'/'+annee+'-'+mois+'-'+jour+'.txt'), 'utf8', function (err,donnees) {
  3904.                     if (donnees == undefined) { verdict = 0; }
  3905.                     else {
  3906.                     var ct = 0, jr = 0;
  3907.                     var okj = new Array(0, 0, 0, 0, 0, 0, 0), cj = 0;
  3908.                     for (var i = 0; i < 24; i++) {
  3909.                         for (j = 0; j < 7; j++) {
  3910.                             if (donnees[24*j+i] > 0) { okj[j] = 1; ct++; }
  3911.                         }
  3912.                     }
  3913.                     for (j = 0; j < 7; j++) { cj += okj[j]; }
  3914.                     if (ct < 21 || cj < 2) { verdict = 0; }    
  3915.                      }
  3916.                      socket.emit('verdict_inscription', verdict);
  3917.                 });
  3918.             }
  3919.         });
  3920.        
  3921.         connection.query('SELECT id FROM inscriptions WHERE id_membre = ? AND id_tournoi = ?', [socket.identifiant, parseInt(id_tournoi.toString())], function (error, verdict, fields) {
  3922.             if (verdict.length == 0) { socket.emit('verifier_inscription', 0); }
  3923.             else { socket.emit('verifier_inscription', 1); }
  3924.         });
  3925.     });
  3926.    
  3927.     socket.on('liste_sprint_profil', function(id_membre) {
  3928.         var idm = parseInt(escapeHtml(id_membre.toString()));
  3929.         connection.query('SELECT id, temps, blocs, date, fantome FROM sprint WHERE id_membre = ? ORDER BY temps LIMIT 0, 5', [idm], function (error, liste, fields) {
  3930.             socket.emit('liste_sprint_profil', liste);
  3931.         });
  3932.     });
  3933.    
  3934.     socket.on('liste_survivor_profil', function(id_membre) {
  3935.         var idm = parseInt(escapeHtml(id_membre.toString()));
  3936.         connection.query('SELECT id, temps, date, fantome FROM survivor WHERE id_membre = ? ORDER BY temps DESC LIMIT 0, 5', [idm], function (error, liste, fields) {
  3937.             socket.emit('liste_survivor_profil', liste);
  3938.         });
  3939.     });
  3940.    
  3941.     socket.on('liste_matches_profil', function(id_membre) {
  3942.         var idm = parseInt(escapeHtml(id_membre.toString()));
  3943.         connection.query("SELECT datedebut, score1, score2, m1.pays AS pays1, m2.pays AS pays2, m1.elo2 AS elo1_avant, m2.elo2 AS elo2_avant, m1.pseudo AS pseudo1, m2.pseudo AS pseudo2, matches.id AS id FROM matches INNER JOIN membres AS m1 ON m1.id = matches.joueur1 INNER JOIN membres AS m2 ON m2.id = matches.joueur2 WHERE matches.confirmation = 2 AND (joueur1 = ? OR joueur2 = ?) AND (score1+score2) > 0 ORDER BY debutmanche DESC LIMIT 0, 5", [idm, idm], function (error, liste, fields) {
  3944.             socket.emit('liste_matches_profil', liste);
  3945.         });
  3946.     });
  3947.    
  3948.     socket.on('liste_ghostbuster_profil', function(id_membre) {
  3949.         var idm = parseInt(escapeHtml(id_membre.toString()));
  3950.         connection.query("SELECT id, KO1, KO2, lignes1, lignes2, elo1_avant, elo1_apres, date FROM solo WHERE id_membre = ? AND etat = 1 ORDER BY date DESC LIMIT 0, 5", [idm], function (error, liste, fields) {
  3951.             socket.emit('liste_ghostbuster_profil', liste);
  3952.         });
  3953.     });
  3954.    
  3955.     socket.on('liste_quickplay_profil', function(id_membre) {
  3956.         var idm = parseInt(escapeHtml(id_membre.toString()));
  3957.         connection.query("SELECT date, KO1, KO2, lignes1, lignes2, m1.pays AS pays1, m2.pays AS pays2, elo1_avant, elo2_avant, elo1_apres, elo2_apres, m1.pseudo AS pseudo1, m2.pseudo AS pseudo2, parties.id AS id FROM parties INNER JOIN membres AS m1 ON m1.id = parties.joueur1 INNER JOIN membres AS m2 ON m2.id = parties.joueur2 WHERE parties.id_match = 0 AND (joueur1 = ? OR joueur2 = ?) AND etat = 1 ORDER BY date DESC LIMIT 0, 5", [idm, idm], function (error, liste, fields) {
  3958.             socket.emit('liste_quickplay_profil', liste);
  3959.         });
  3960.     });
  3961.    
  3962.     } /* FIN STATISTIQUES */
  3963.    
  3964.     /* DEBUT COMMENTAIRES */
  3965.    
  3966.     // commentaires d'un article
  3967.     socket.on('demander_commentaires', function(id_article) {
  3968.         connection.query('SELECT membres.pays, membres.pseudo, contenu, MID(commentaires.datepublication, 1, 10) AS datepublication FROM commentaires LEFT JOIN membres ON membres.id = commentaires.id_membre WHERE id_article = ?', [escapeHtml(id_article.toString())], function(error, liste, fields) {
  3969.             socket.emit('liste_commentaires', liste);
  3970.         });
  3971.     });
  3972.    
  3973.     // nouveau commentaire
  3974.     socket.on('nouveau_commentaire', function(donnees) {
  3975.         if ('commentaire' in donnees && 'id_article' in donnees && socket.typemembre >= 1 && socket.typemembre <= 2) {
  3976.             var com = escapeHtml(donnees['commentaire'].toString());
  3977.             if (com.length < 3) { socket.emit('commentaire_refuse', 'Your comment is too short.'); }
  3978.             else if (com.length > 50000) { socket.emit('commentaire_refuse', 'Your comment has to be at most 50000 characters long.'); }
  3979.             else {
  3980.                 connection.query('INSERT INTO commentaires(id_membre, id_article, datepublication, contenu) VALUES (?, ?, NOW(), ?)', [socket.identifiant, escapeHtml(donnees['id_article'].toString()), com], function (error, ins, fields) {
  3981.                     socket.emit('commentaire_accepte', '');
  3982.                 });
  3983.             }
  3984.         }
  3985.     });
  3986.     /* FIN COMMENTAIRES
  3987.    
  3988.     /* DEBUT TOURNOIS */
  3989.    
  3990.     // informations sur un match de tournoi
  3991.     socket.on('infos_match_tournoi', function(pseudo) {
  3992.         var pseudoinvite = escapeHtml(pseudo.toString());
  3993.         var informations = {date: '', heure: '', nb_manches: 7, diff_manches: 2, limite_ko: 0, duree: 2};
  3994.         connection.query('SELECT id FROM membres WHERE pseudo = ? AND (typemembre = 1 OR typemembre = 2)', [pseudoinvite], function(error, v, fields) {
  3995.             if (v.length == 1) {
  3996.                 // peut-être une faille de sécurité si quelqu'un crée un match avant que le précédent ne soit terminé
  3997.                 connection.query('SELECT * FROM matches WHERE tournoi > 1 AND confirmation = 1 AND (joueur1 = ? OR joueur2 = ?) AND (joueur1 = ? OR joueur2 = ?)', [socket.identifiant, socket.identifiant, v[0]['id'], v[0]['id']], function (error, infos, fields) {
  3998.                     if (infos.length == 1) {
  3999.                         informations = infos[0];
  4000.                         var annee = infos[0]['datedebut'].getFullYear();
  4001.                         var mois = 1+infos[0]['datedebut'].getMonth();
  4002.                         if (mois < 10) { mois = '0' + mois; }
  4003.                         var jour = infos[0]['datedebut'].getDate();
  4004.                         if (jour < 10) { jour = '0' + jour; }
  4005.                         var heure =  infos[0]['datedebut'].getHours();
  4006.                         if (heure < 10) { heure = '0' + heure; }
  4007.                         var minute = infos[0]['datedebut'].getMinutes();
  4008.                         if (minute < 10) { minute = '0' + minute; }
  4009.                         informations['date'] = annee + '-' + mois + '-' + jour;
  4010.                         informations['heure'] = heure + ':' + minute;
  4011.                     }
  4012.                     socket.emit('infos_match_tournoi', informations);
  4013.                 });
  4014.             }
  4015.             else { socket.emit('infos_match_tournoi', informations); }
  4016.         });
  4017.     });
  4018.    
  4019.     // demander à ce qu'un match soit reporté
  4020.     socket.on('demander_report', function (donnees) {
  4021.         var pseudotournoi = escapeHtml(donnees['pseudo'].toString());
  4022.         var date = escapeHtml(donnees['date'].toString()), heure = escapeHtml(donnees['heure'].toString());
  4023.         dateMatch = new Date(date + ' ' + heure + ':00');
  4024.         var informations = {date: '', heure: '', nb_manches: 7, diff_manches: 2, limite_ko: 0, duree: 2};
  4025.         connection.query('SELECT id, infos4, email FROM membres WHERE pseudo = ? AND (typemembre = 1 OR typemembre = 2)', [pseudotournoi], function(error, v, fields) {
  4026.             if (v.length == 1) {
  4027.                 connection.query('SELECT * FROM matches WHERE confirmation = 1 AND datedebut > NOW() AND (joueur1 = ? OR joueur2 = ?) AND (joueur1 = ? OR joueur2 = ?) AND tournoi > 1', [socket.identifiant, socket.identifiant, v[0]['id'], v[0]['id']], function (error, infos, fields) {
  4028.                     if (infos.length == 1) {
  4029.                         var jr;
  4030.                         if (infos[0]['joueur1'] == socket.identifiant) { jr = 1; } else { jr = 2; }
  4031.                         connection.query('UPDATE matches SET datereport = ?, joueurreport = ? WHERE id = ?', [dateMatch, jr, infos[0]['id']], function(error, fini, fields) {
  4032.                             if (1 == 1) {
  4033.                                 var message = {
  4034.                                     text:   "Hi!\n\n" + socket.pseudo + "  wants to postpone the match between you two, in the betadashboard.ejs Tournament 2. The new date would be: "+ dateMatch +" *UTC*.\nIf order to accept this request, click here: https://www.worldwide-combos.com/postponing?r=1&id="+infos[0]['id']+".\nIf order to decline this request, click here: https://www.worldwide-combos.com/postponing?r=2&id="+infos[0]['id']+".\n\nHave fun on Worldwide Combos!\n\nBest regards,\n\n Noël Nadal (Worldwide Combos admin).",
  4035.                                     from:   "Worldwide Combos <noreply@worldwide-combos.com>",
  4036.                                     to:     v[0]['email'],
  4037.                                     subject:    "Match postponing request",
  4038.                                     attachment:
  4039.                                     [
  4040.                                         {data:"<html>Hi!<br><br>" + socket.pseudo + " wants to postpone the match between you two, in the betadashboard.ejs Tournament 2. The new date would be: "+ dateMatch +" <b>UTC</b>.<br>If order to accept this request, click <a href='https://www.worldwide-combos.com/postponing?r=1&id="+infos[0]['id']+"'>here</a>.<br>If order to decline this request, click <a href='https://www.worldwide-combos.com/postponing?r=2&id="+infos[0]['id']+"'>here</a><br><br>Have fun on Worldwide Combos!<br><br>Best regards,<br><br>Noël Nadal (Worldwide Combos admin).</html>", alternative:true}
  4041.                                     ]
  4042.                                 };
  4043.                                 server_noreply.send(message, function(err, message) { console.log(getDateTime() + 'Notification courriel envoyée à ' + pseudotournoi + ' (demande de report de match).'); });
  4044.                             }
  4045.                         });
  4046.                     }
  4047.                     socket.emit('report_ok', '');
  4048.                 });
  4049.             }
  4050.             else { socket.emit('report_pasok', ''); }
  4051.         });
  4052.    
  4053.     });
  4054.    
  4055.     function nouvelle_partie_match(joueur1, joueur2, id_match) {
  4056.         var j1 = {}, j2 = {};
  4057.         j1['typePartie'] = 7;
  4058.         j1['pseudo'] = joueur1.pseudo;
  4059.         j1['pays'] = joueur1.pays;
  4060.         j1['classement2'] = joueur1.classement2;
  4061.         j2['typePartie'] = 6;
  4062.         j2['pseudo'] = joueur2.pseudo;
  4063.         j2['pays'] = joueur2.pays;
  4064.         j2['classement2'] = joueur2.classement2;
  4065.         j1['maintenant'] = Date.now();
  4066.         j2['maintenant'] = Date.now();
  4067.         socket.adv = joueur2.pseudo;
  4068.         socket.adv_elo = joueur2.classement2;
  4069.         socket.adv_contact = joueur2;
  4070.         // générer les blocs à refaire
  4071.         var blocs = tirage();
  4072.         console.log(joueur1, joueur2, id_match);
  4073.         console.log(socket.adv_contact);
  4074.         socket.adv_contact.emit('liste_blocs_multi', blocs);
  4075.         socket.emit('liste_blocs_multi', blocs);
  4076.         connection.query('INSERT INTO parties(id_match, joueur1, joueur2, handicap, KO1, KO2, lignes1, lignes2, hauteur1, hauteur2, date, elo1_avant, elo2_avant, elo1_apres, elo2_apres, etat) VALUES(?,?,?,?,?,?,?,?,?,?,NOW(),?,?,?,?,?)',
  4077.         [id_match, socket.identifiant, joueur2.identifiant, 1, 0, 0, 0, 0, 0, 0, socket.classement2, joueur2.classement2, 0, 0, -1], function (error, inutile, fields) {
  4078.             socket.lieu = inutile.insertId;
  4079.             direct[socket.lieu] = new Array('', new Array(), new Array(), Date.now(), 2, 0, 1, -1, 0, 0);
  4080.             socket.join(socket.lieu);
  4081.             console.log(getDateTime() + 'Début de la manche entre ' + socket.pseudo +  ' et ' + socket.adv + ' (lieu : ' + socket.lieu + ').');
  4082.             j1['lieu'] = socket.lieu;
  4083.             j2['lieu'] = socket.lieu;
  4084.             joueur1.emit('nouvelle_partie', j2);
  4085.             joueur2.emit('nouvelle_partie', j1);
  4086.             socket.typejoueur = 1;
  4087.         });
  4088.     }
  4089.    
  4090.     socket.on('message_pret_custom', function(message) {
  4091.         if ('mdp' in message && 'pseudo' in message && 'id_match' in message && 'pret' in message) {
  4092.             var mdp = crypto.createHash('sha1');
  4093.             var entree = escapeHtml(message['mdp'].toString()), pseudo = escapeHtml(message['pseudo'].toString());
  4094.             mdp.update('combo'+entree);
  4095.             var res_mdp = mdp.digest('hex');
  4096.             connection.query('SELECT * FROM membres WHERE pseudo = ? AND mdp = ?', [pseudo, res_mdp], function (error, verdict, fields) {
  4097.                 if (verdict.length == 0) { socket.emit('deconnexion', ''); return 0; }
  4098.                 else if (verdict.length == 1) {
  4099.                     socket.identifiant = verdict[0]['id'];
  4100.                     socket.pseudo = verdict[0]['pseudo'];
  4101.                     socket.fuseau = verdict[0]['fuseau'];
  4102.                     socket.classement1 = verdict[0]['elo1'];
  4103.                     socket.classement2 = verdict[0]['elo2'];
  4104.                     socket.identifiant = verdict[0]['id'];
  4105.                     socket.pays = verdict[0]['pays'];
  4106.                     socket.typemembre = verdict[0]['typemembre'];
  4107.                     socket.email = verdict[0]['email'];
  4108.                     socket.sprint = verdict[0]['sprint'];
  4109.                     socket.sprint10 = verdict[0]['sprint10'];
  4110.                     socket.survivor = verdict[0]['survivor'];
  4111.                     socket.mdp = verdict[0]['mdp'];
  4112.                     socket.duree_solo = verdict[0]['duree_solo'];
  4113.                     socket.handicap_solo = verdict[0]['handicap_solo'];
  4114.                     socket.ligne_suppl = verdict[0]['ligne_suppl'];
  4115.                     matches[message['id_match']][socket.identifiant]['pret'] = message['pret'];
  4116.                     matches[message['id_match']][socket.identifiant]['socket'] = socket;
  4117.                     if (matches[message['id_match']][socket.identifiant]['pret'] == 1 && matches[message['id_match']][matches[message['id_match']][socket.identifiant]['adversaire']]['pret'] == 1) {
  4118.                         nouvelle_partie_match(matches[message['id_match']][socket.identifiant]['socket'], matches[message['id_match']][matches[message['id_match']][socket.identifiant]['adversaire']]['socket'], message['id_match']);
  4119.                     }
  4120.                     /*if (quickfire[socket.identifiant]['date'] < Date.now()) {
  4121.                          connection.query('SELECT id, joueur1, joueur2 FROM matches WHERE datedebut < NOW() && tournoi > 0 && (joueur1 = ? OR joueur2 = ?) ORDER BY datedebut DESC', [socket.identifiant, socket.identifiant], function (error, match_annule, fields) {
  4122.                              if (match_annule.length == 0) { return; }
  4123.                              if (match_annule[0]['joueur1'] == socket.identifiant) {
  4124.                                  connection.query('UPDATE matches SET score1 = 1, confirmation = 2 WHERE id = ?', [match_annule[0]['id']], function (error, ok, fields) {});
  4125.                              }
  4126.                              else {
  4127.                                  connection.query('UPDATE matches SET score2 = 1, confirmation = 2 WHERE id = ?', [match_annule[0]['id']], function (error, ok, fields) {});
  4128.                              }
  4129.                          });
  4130.                     }*/
  4131.                 }
  4132.             });
  4133.         }
  4134.     });
  4135.    
  4136.     socket.on('verifier_quickfire', function(message) {
  4137.         if ('mdp' in message && 'pseudo' in message) {
  4138.             var mdp = crypto.createHash('sha1');
  4139.             var entree = escapeHtml(message['mdp'].toString()), pseudo = escapeHtml(message['pseudo'].toString());
  4140.             mdp.update('combo'+entree);
  4141.             var res_mdp = mdp.digest('hex');
  4142.             connection.query('SELECT * FROM membres WHERE pseudo = ? AND mdp = ?', [pseudo, res_mdp], function (error, verdict, fields) {
  4143.                 if (verdict.length == 0) { socket.emit('deconnexion', ''); return 0; }
  4144.                 else if (verdict.length == 1) {
  4145.                     socket.identifiant = verdict[0]['id'];
  4146.                     socket.pseudo = verdict[0]['pseudo'];
  4147.                     socket.fuseau = verdict[0]['fuseau'];
  4148.                     socket.classement1 = verdict[0]['elo1'];
  4149.                     socket.classement2 = verdict[0]['elo2'];
  4150.                     socket.identifiant = verdict[0]['id'];
  4151.                     socket.pays = verdict[0]['pays'];
  4152.                     socket.typemembre = verdict[0]['typemembre'];
  4153.                     socket.email = verdict[0]['email'];
  4154.                     socket.sprint = verdict[0]['sprint'];
  4155.                     socket.sprint10 = verdict[0]['sprint10'];
  4156.                     socket.survivor = verdict[0]['survivor'];
  4157.                     socket.mdp = verdict[0]['mdp'];
  4158.                     socket.duree_solo = verdict[0]['duree_solo'];
  4159.                     socket.handicap_solo = verdict[0]['handicap_solo'];
  4160.                     socket.ligne_suppl = verdict[0]['ligne_suppl'];
  4161.                     connection.query('SELECT id FROM inscriptions WHERE id_tournoi = ? AND id_membre = ?', [message['id_tournoi'], socket.identifiant], function (error, verif1, fields) {
  4162.                         if (verif1.length == 1) {
  4163.                             connection.query('SELECT id FROM matches WHERE datedebut > NOW() AND tournoi = ? AND (joueur1 = ? OR joueur2 = ?)', [message['id_tournoi'], socket.identifiant, socket.identifiant], function (error, verif2, fields) {
  4164.                                 if (verif2.length >= 1) {
  4165.                                     socket.emit('prochain_match_quickfire', 1);
  4166.                                 }
  4167.                                 else { socket.emit('erreur_quickfire', '#'); }
  4168.                             });
  4169.                         }
  4170.                         else {
  4171.                             socket.emit('erreur_quickfire', '#');
  4172.                         }
  4173.                     });
  4174.                 }
  4175.             });
  4176.         }
  4177.     });
  4178.    
  4179.     // pour s'inscrire :D
  4180.     socket.on('inscription_tournoi', function(donnees) {
  4181.         if ('pays' in donnees && 'id_tournoi' in donnees && 'ok1' in donnees && 'ok2' in donnees) {
  4182.             var pays = escapeHtml(donnees['pays'].toString());
  4183.             var id_tournoi = parseInt(escapeHtml(donnees['id_tournoi'].toString()));
  4184.             var ok1 = parseInt(escapeHtml(donnees['ok1'].toString())), ok2 = parseInt(escapeHtml(donnees['ok2'].toString()));
  4185.             var erreurs = '';
  4186.             if (ok1 == 0 || ok2 == 0) { erreurs += 'You must agree with the two last sentences. '; socket.emit('echec_inscription', erreurs); }
  4187.             else {
  4188.                 if (erreurs == '') {
  4189.                     connection.query('UPDATE membres SET pays = ? WHERE id = ?', [pays, socket.identifiant], function (error, maj, fields) {});
  4190.                     connection.query('SELECT id FROM inscriptions WHERE id_membre = ? AND id_tournoi = ?', [socket.identifiant, id_tournoi], function (error, verif2, fields) {
  4191.                         if (verif2.length == 1) {
  4192.                             socket.emit('succes_inscription', 1);
  4193.                             console.log('Modification de l\'inscription de ' + socket.pseudo + ' à un tournoi.');
  4194.                         }
  4195.                         else {
  4196.                             connection.query('INSERT inscriptions(id_membre, id_tournoi, fuseau, dateinscription) VALUES(?, ?, -1, NOW())', [socket.identifiant, id_tournoi], function (error, ajout, fields) {
  4197.                                 socket.emit('succes_inscription', 1);
  4198.                                 console.log('Inscription de ' + socket.pseudo + ' à un tournoi (id : ' + id_tournoi + ').');
  4199.                             });
  4200.                         }
  4201.                     });
  4202.                 }
  4203.                 else { socket.emit('echec_inscription', erreurs); }
  4204.             }
  4205.         }
  4206.     });
  4207.    
  4208.     socket.on('inscription_quickfire', function(message) {
  4209.         if ('mdp' in message && 'pseudo' in message) {
  4210.             var mdp = crypto.createHash('sha1');
  4211.             var entree = escapeHtml(message['mdp'].toString()), pseudo = escapeHtml(message['pseudo'].toString());
  4212.             mdp.update('combo'+entree);
  4213.             var res_mdp = mdp.digest('hex');
  4214.             connection.query('SELECT * FROM membres WHERE pseudo = ? AND mdp = ?', [pseudo, res_mdp], function (error, verdict, fields) {
  4215.                 if (verdict.length == 0) { socket.emit('deconnexion', ''); return 0; }
  4216.                 else if (verdict.length == 1) {
  4217.                     socket.identifiant = verdict[0]['id'];
  4218.                     socket.pseudo = verdict[0]['pseudo'];
  4219.                     socket.fuseau = verdict[0]['fuseau'];
  4220.                     socket.classement1 = verdict[0]['elo1'];
  4221.                     socket.classement2 = verdict[0]['elo2'];
  4222.                     socket.identifiant = verdict[0]['id'];
  4223.                     socket.pays = verdict[0]['pays'];
  4224.                     socket.typemembre = verdict[0]['typemembre'];
  4225.                     socket.email = verdict[0]['email'];
  4226.                     socket.sprint = verdict[0]['sprint'];
  4227.                     socket.sprint10 = verdict[0]['sprint10'];
  4228.                     socket.survivor = verdict[0]['survivor'];
  4229.                     socket.mdp = verdict[0]['mdp'];
  4230.                     socket.duree_solo = verdict[0]['duree_solo'];
  4231.                     socket.handicap_solo = verdict[0]['handicap_solo'];
  4232.                     socket.ligne_suppl = verdict[0]['ligne_suppl'];
  4233.                     connection.query('SELECT id FROM inscriptions WHERE id_tournoi = ? AND id_membre = ?', [message['id_tournoi'], socket.identifiant], function (error, verif1, fields) {
  4234.                         if (verif1.length == 0) {
  4235.                             connection.query('SELECT id FROM tournois WHERE datedebut > NOW() AND datedebut < DATE_ADD(NOW(), INTERVAL 1 HOUR) AND id = ?', [message['id_tournoi']], function (error, verif2, fields) {
  4236.                                 if (verif2.length == 1) {
  4237.                                     connection.query('INSERT INTO inscriptions(id_membre, id_tournoi, dateinscription) VALUES(?, ?, NOW())', [socket.identifiant, message['id_tournoi']], function (error, ok, fields) {
  4238.                                         socket.emit('verifier_inscription', 1);
  4239.                                     });
  4240.                                 }
  4241.                             });
  4242.                         }
  4243.                         else {
  4244.                             connection.query('SELECT id FROM tournois WHERE datedebut > NOW() AND datedebut < DATE_ADD(NOW(), INTERVAL 1 HOUR) AND id = ?', [message['id_tournoi']], function (error, verif2, fields) {
  4245.                                 if (verif2.length == 1) {
  4246.                                     connection.query('DELETE FROM inscriptions WHERE id_tournoi = ? AND id_membre = ?', [message['id_tournoi'], socket.identifiant], function (error, ok, fields) {
  4247.                                         socket.emit('verifier_inscription', 0);
  4248.                                     });
  4249.                                 }
  4250.                             });
  4251.                         }
  4252.                     });
  4253.                 }
  4254.             });
  4255.         }
  4256.     });
  4257.    
  4258.     socket.on('annuler_inscription', function(id_tournoi) {
  4259.         var idt = parseInt(escapeHtml(id_tournoi.toString()));
  4260.         connection.query('DELETE FROM inscriptions WHERE id_membre = ? AND id_tournoi = ?', [socket.identifiant, idt], function (error, suppr, fields) {
  4261.             socket.emit('succes_annulation', '');
  4262.         });
  4263.     });
  4264.    
  4265.     // liste des inscrits
  4266.     socket.on('liste_inscrits', function(id_tournoi) {
  4267.         var idt = parseInt(escapeHtml(id_tournoi.toString()));
  4268.         connection.query('SELECT fini FROM tournois WHERE id = ?', [idt], function (error, tournoi, fields) {
  4269.             if (tournoi.length == 1 && tournoi[0]['fini'] >= 0) {
  4270.                 connection.query('SELECT membres.id AS id, membres.pseudo AS pseudo, membres.pays AS pays FROM inscriptions LEFT JOIN membres ON membres.id = inscriptions.id_membre WHERE id_tournoi = ?', [idt], function (error, membres, fields) {
  4271.                     fs.readFile(path.join(__dirname, '/tournois/inscrits_'+idt+'.txt'), 'utf8', function (err, donnees) {
  4272.                         socket.emit('liste_inscrits', {donnees: donnees, membres: membres});
  4273.                     });
  4274.                 });
  4275.             }
  4276.             else if (tournoi.length == 1) {
  4277.                 connection.query('SELECT membres.pseudo AS pseudo, membres.pays AS pays, membres.tournoi AS tournoi FROM inscriptions LEFT JOIN membres ON membres.id = inscriptions.id_membre WHERE id_tournoi = ? ORDER BY tournoi DESC, elo2 DESC, elo1 DESC, survivor DESC, sprint, inscriptions.dateinscription', [idt], function (error, membres, fields) {
  4278.                     socket.emit('liste_inscrits_provisoire', membres);
  4279.                 });
  4280.             }
  4281.         });
  4282.     });
  4283.    
  4284.     // liste des poules
  4285.     socket.on('liste_poules', function(id_tournoi) {
  4286.         var idt = parseInt(escapeHtml(id_tournoi.toString()));
  4287.         connection.query('SELECT membres.id AS id, membres.pseudo AS pseudo, membres.pays AS pays FROM inscriptions LEFT JOIN membres ON membres.id = inscriptions.id_membre WHERE id_tournoi = ?', [idt], function (error, membres, fields) {
  4288.             fs.readFile(path.join(__dirname, '/tournois/poules_'+idt+'.txt'), 'utf8', function (err,donnees) {
  4289.                 socket.emit('liste_poules', {donnees: donnees, membres: membres});
  4290.             });
  4291.         });
  4292.     });
  4293.    
  4294.     // fichiers de tableau
  4295.     socket.on('fichier_tableau', function(nom_tableau) {
  4296.         var nt = escapeHtml(nom_tableau.toString());
  4297.         connection.query('SELECT membres.id AS id, membres.pseudo AS pseudo, membres.pays AS pays FROM inscriptions LEFT JOIN membres ON membres.id = inscriptions.id_membre WHERE id_tournoi = ?', [nt], function (error, membres, fields) {
  4298.             fs.readFile(path.join(__dirname, '/tournois/tableau_'+nt+'.txt'), 'utf8', function (err,donnees) {
  4299.                  socket.emit('fichier_tableau', {donnees: donnees, membres: membres});
  4300.             });
  4301.         });
  4302.     });
  4303.    
  4304.     // classement final
  4305.     socket.on('classement_tournoi', function(id_tournoi) {
  4306.         var idt = parseInt(escapeHtml(id_tournoi.toString()));
  4307.         connection.query('SELECT membres.id AS id, membres.pseudo AS pseudo, membres.pays AS pays FROM inscriptions LEFT JOIN membres ON membres.id = inscriptions.id_membre WHERE id_tournoi = ?', [idt], function (error, membres, fields) {
  4308.             fs.readFile(path.join(__dirname, '/tournois/classement_'+idt+'.txt'), 'utf8', function (err,donnees) {
  4309.                 socket.emit('classement_tournoi', {donnees: donnees, membres: membres});
  4310.             });
  4311.         });
  4312.     });
  4313.     /* FIN TOURNOIS */
  4314.    
  4315. /*SELECT membres.pseudo AS pseudo, membres.pays AS pays, (IF(COUNT(solo.id) = 0, 0, SUM(solo.lignes1)) + IF(COUNT(m1.id) = 0, 0, SUM(m1.lignes1)) + IF(COUNT(m2.id) = 0, 0, SUM(m2.lignes2))) / ( IF(COUNT(fantomes.id) = 0, 1, SUM(fantomes.ok))) AS moyenne
  4316. FROM membres
  4317. LEFT JOIN solo ON solo.id_membre = membres.id AND solo.fantome > 0 AND solo.date > DATE_SUB(NOW(), INTERVAL 1 MONTH)
  4318. LEFT JOIN parties AS m1 ON m1.joueur1 = membres.id AND m1.fantome1 > 0 AND m1.date > DATE_SUB(NOW(), INTERVAL 1 MONTH)
  4319. LEFT JOIN parties AS m2 ON m2.joueur2 = membres.id AND m2.fantome2 > 0 AND m2.date > DATE_SUB(NOW(), INTERVAL 1 MONTH)
  4320. LEFT JOIN fantomes ON (fantomes.id_membre = membres.id)
  4321. WHERE membres.id != 1 AND (typemembre = 1 OR typemembre = 2)
  4322. AND membres.derniereconnexion >= DATE_SUB(NOW(), INTERVAL 1 MONTH) GROUP BY membres.id
  4323. ORDER BY ABS(150 - 60*(IF(COUNT(solo.id) = 0, 0, SUM(solo.lignes1)) + IF(COUNT(m1.id) = 0, 0, SUM(m1.lignes1)) + IF(COUNT(m2.id) = 0, 0, SUM(m2.lignes2))) / ( IF(COUNT(fantomes.id) = 0, 1, SUM(fantomes.ok))))
  4324.   */  
  4325. });
  4326.  
  4327. /* DEBUT VERIFICATIONS AUTOMATIQUES */
  4328.  
  4329. function verifications_auto_10s() {
  4330.     /*
  4331.     // pour vérifier que les joueurs en file d'attente sont toujours là
  4332.     for (x in queue) {
  4333.         if ((Date.now() - queue[x].derniereFois) > 7000) {
  4334.             if (LOCALHOST == 0) {
  4335.                 connection.query('SELECT pays FROM membres WHERE pseudo = ?', [queue[x].pseudo], function (error, pays, fields) {
  4336.                     channel = guilde.channels.find('name', 'quickplay');
  4337.                     if (channel != undefined && queue[x] != undefined) { channel.send(':flag_'+cp[pays[0]['pays']] + ': ' + queue[x].pseudo + ' left the queue.'); }
  4338.                     delete queue[x];
  4339.                     delete qc[x];
  4340.                 });
  4341.             }
  4342.             else {
  4343.                 delete queue[x];
  4344.                 delete qc[x];
  4345.             }
  4346.             console.log(getDateTime() + 'Départ de ' + x + ' de la file d\'attente.');
  4347.         }
  4348.     }*/
  4349.    
  4350.     // pour les conseils
  4351.     connection.query('SELECT COUNT(*) AS nb FROM solo', function (error, solo, fields) {
  4352.         connection.query('SELECT COUNT(*) AS nb FROM parties', function (error, parties, fields) {
  4353.             connection.query('SELECT COUNT(*) AS nb FROM sprint', function (error, sprint, fields) {
  4354.                 connection.query('SELECT COUNT(*) AS nb FROM survivor', function (error, survivor, fields) {
  4355.                     conseils[15] = "<br><br>Did you know? More than " + (solo[0]['nb']+parties[0]['nb']+sprint[0]['nb']+survivor[0]['nb']) + " games have been played in total on this website!"
  4356.                 });
  4357.             });
  4358.         });
  4359.     });
  4360.    
  4361.     // mise à jour coefficients de force des joueurs
  4362.     connection.query('SELECT MAX(id) AS maxid FROM membres', function (error, calcul, fields) {
  4363.         var aleat = 1 + Math.floor(calcul[0]['maxid']*Math.random());
  4364.         connection.query('SELECT id FROM membres WHERE id = ?', [aleat], function (error, verif, fields) {
  4365.             if (verif.length == 1) {
  4366.                 connection.query('SELECT IF(COUNT(solo.id) = 0, 0, SUM(solo.lignes1)) AS moyenne1, IF(COUNT(solo.id) = 0, 0, SUM(fantomes.etat)) AS somme1 FROM solo LEFT JOIN fantomes ON (fantomes.id = solo.fantome) WHERE solo.id_membre = ? AND solo.date > DATE_SUB(NOW(), INTERVAL 1 MONTH) AND solo.etat = 1 AND solo.fantome > 0', [aleat], function (error, calcul1, fields) {
  4367.                     connection.query('SELECT IF(COUNT(parties.id) = 0, 0, SUM(parties.lignes1)) AS moyenne2, IF(COUNT(parties.id) = 0, 0, SUM(fantomes.etat)) AS somme2 FROM parties LEFT JOIN fantomes ON (fantomes.id = parties.fantome1) WHERE parties.joueur1 = ? AND parties.date > DATE_SUB(NOW(), INTERVAL 1 MONTH) AND parties.etat = 1 AND parties.fantome1 > 0', [aleat], function (error, calcul2, fields) {
  4368.                         connection.query('SELECT IF(COUNT(parties.id) = 0, 0, SUM(parties.lignes2)) AS moyenne3, IF(COUNT(parties.id) = 0, 0, SUM(fantomes.etat)) AS somme3 FROM parties LEFT JOIN fantomes ON (fantomes.id = parties.fantome2) WHERE parties.joueur2 = ? AND parties.date > DATE_SUB(NOW(), INTERVAL 1 MONTH) AND parties.etat = 1 AND parties.fantome2 > 0', [aleat], function (error, calcul3, fields) {
  4369.                             if ((calcul1[0]['somme1']+calcul2[0]['somme2']+calcul3[0]['somme3']) > 0) {
  4370.                                 connection.query('UPDATE membres SET coeff_force = ? WHERE id = ?', [(calcul1[0]['moyenne1']+calcul2[0]['moyenne2']+calcul3[0]['moyenne3']) / (calcul1[0]['somme1']+calcul2[0]['somme2']+calcul3[0]['somme3']), aleat], function (error, ok, fields) {});
  4371.                             }
  4372.                         });
  4373.                     });
  4374.                 });
  4375.             }
  4376.         });
  4377.     });
  4378.    
  4379.     // équilibrage ghostbuster
  4380.     connection.query('SELECT MAX(id) AS mid FROM solo', function (error, mid, fields) {
  4381.         var d1 = 1 + Math.floor(Math.random()*mid[0]['mid']);
  4382.         var d2 = 1 + Math.floor(Math.random()*mid[0]['mid']);
  4383.         connection.query('SELECT lignes1, elo1_apres AS elo, fantome FROM solo WHERE id = ?', [d1], function (error, f1, fields) {
  4384.             if (f1.length == 0) { return; }
  4385.             connection.query('SELECT lignes1, elo1_apres AS elo, fantome FROM solo WHERE id = ?', [d2], function (error, f2, fields) {
  4386.                 if (f2.length == 0) { return; }
  4387.                 var a1 = f1[0]['fantome'];
  4388.                 var a2 = f2[0]['fantome'];
  4389.                 if (f1[0]['elo'] > f2[0]['elo']) {
  4390.                     if (f1[0]['lignes1'] < f2[0]['lignes1']) {
  4391.                         connection.query('SELECT nb_parties AS nb FROM fantomes WHERE id = ?', [a1], function (error, n1, fields) {
  4392.                             if (n1.length == 0) { return; }
  4393.                             connection.query('SELECT nb_parties AS nb FROM fantomes WHERE id = ?', [a2], function (error, n2, fields) {
  4394.                                 if (n2.length == 0) { return; }
  4395.                                 var nb = n1[0]['nb'] + n2[0]['nb'];
  4396.                                 connection.query('UPDATE fantomes SET elo = ? WHERE id = ?', [nb/(nb+1)*f1[0]['elo']+f2[0]['elo']/(nb+1), a1], function (error, ok1, fields) {});
  4397.                                 connection.query('UPDATE fantomes SET elo = ? WHERE id = ?', [nb/(nb+1)*f2[0]['elo']+f1[0]['elo']/(nb+1), a2], function (error, ok2, fields) {});
  4398.                             });
  4399.                         });
  4400.                     }
  4401.                 }
  4402.                 else if (f1[0]['elo'] < f2[0]['elo']) {
  4403.                     if (f1[0]['lignes1'] > f2[0]['lignes1']) {
  4404.                         connection.query('SELECT nb_parties AS nb FROM fantomes WHERE id = ?', [a1], function (error, n1, fields) {
  4405.                             if (n1.length == 0) { return; }
  4406.                             connection.query('SELECT nb_parties AS nb FROM fantomes WHERE id = ?', [a2], function (error, n2, fields) {
  4407.                                 if (n2.length == 0) { return; }
  4408.                                 var nb = n1[0]['nb'] + n2[0]['nb'];
  4409.                                 connection.query('UPDATE fantomes SET elo = ? WHERE id = ?', [nb/(nb+1)*f1[0]['elo']+f2[0]['elo']/(nb+1), a1], function (error, ok1, fields) {});
  4410.                                 connection.query('UPDATE fantomes SET elo = ? WHERE id = ?', [nb/(nb+1)*f2[0]['elo']+f1[0]['elo']/(nb+1), a2], function (error, ok2, fields) {});
  4411.                             });
  4412.                         });
  4413.                     }
  4414.                 }
  4415.             });
  4416.         });
  4417.     });
  4418.    
  4419.     // pour le robot Discord, histoire qu'il ne se déconnecte pas
  4420.     if (client.user) { client.user.setActivity('Worldwide Combos', {type: "WATCHING"}); }
  4421. }
  4422.  
  4423. function verifications_auto_60s() {
  4424.     // gestion maintenance
  4425.     fs.readFile(path.join(__dirname, 'maintenance.txt'), 'utf8', function (err, donnees) {
  4426.         if (donnees != undefined && MAINTENANCE >= 0) { MAINTENANCE = Math.max(MAINTENANCE, parseInt(donnees[0])); }
  4427.         if (MAINTENANCE == 0 && LOCALHOST == 0) {
  4428.             channel = guilde.channels.find('name', 'general');
  4429.             if (channel != undefined) { channel.send('You may now play Worldwide Combos again! :smile:'); }
  4430.             console.log("FIN MAINTENANCE");
  4431.             MAINTENANCE = -1;
  4432.         }
  4433.         MAINTENANCE -= 1;
  4434.         MAINTENANCE = Math.max(-1, MAINTENANCE);
  4435.         fs.writeFile(path.join(__dirname, 'maintenance.txt'), Math.max(MAINTENANCE,0), function (err) {});
  4436.     });
  4437.    
  4438.     // matches avec aucun joueur présent (hum hum)
  4439.     // faudra faire attention avec les tournois toussa
  4440.     connection.query('SELECT id, score1, score2 FROM matches WHERE datelimite < NOW() AND confirmation = 1', function (error, matches, fields) {
  4441.         for(i = 0; i < matches.length; i++) {
  4442.             var match = matches[0];
  4443.             connection.query('UPDATE matches SET confirmation = 2 WHERE id = ?', [match['id']], function (error, fini, fields) {});
  4444.         }  
  4445.     });
  4446.    
  4447.     // nettoyage des parties qui posent problème
  4448.     connection.query('SELECT solo.id_partie AS id, ok FROM solo LEFT JOIN fantomes ON fantomes.id = solo.id_partie WHERE KO1 > 32 GROUP BY id_partie HAVING ok = 1', function(error, parties, fields) {
  4449.         var n = parties.length;
  4450.         if (n == 1) { console.log(getDateTime() + n + " fantôme douteux repéré."); }
  4451.         else if (n > 0) { console.log(getDateTime() + n + " fantômes douteux repérés."); }
  4452.         for(var i = 0; i < n; i++) {
  4453.             connection.query('UPDATE fantomes SET ok = 0 WHERE id = ?', [parties[i]['id']], function(error, v, fields) {});
  4454.         }
  4455.     });
  4456.    
  4457.     // notifications 24 heures
  4458.     connection.query('SELECT joueur1, joueur2, matches.tournoi AS tournoi, nb_manches, diff_manches, limite_ko, duree, handicap, diff_victoire, datedebut, m1.pseudo AS pseudo1, m1.discord AS code1, m2.pseudo AS pseudo2, m2.discord AS code2, m1.infos4 AS infos1, m1.discord4 AS discord1, m2.infos4 AS infos2, m2.discord4 AS discord2, m1.email AS email1, m2.email AS email2 FROM matches LEFT JOIN membres AS m1 ON matches.joueur1 = m1.id LEFT JOIN membres AS m2 ON matches.joueur2 = m2.id WHERE datedebut > DATE_ADD(NOW(), INTERVAL 1 DAY) AND datedebut < DATE_ADD(DATE_ADD(NOW(), INTERVAL 1 DAY), INTERVAL 1 MINUTE) AND confirmation = 1', function(error, prochains, fields) {
  4459.         //console.log(prochains.length);
  4460.         for(i = 0; i < prochains.length; i++) {
  4461.             var match = prochains[i];
  4462.             if (match['tournoi'] == 0) { match['type'] = 'custom'; match['Type'] = 'Custom'; } else { match['type'] = 'tournament'; match['Type'] = 'Tournament'; }
  4463.             var annee = match['datedebut'].getFullYear();
  4464.             var mois = 1+match['datedebut'].getMonth();
  4465.             if (mois < 10) { mois = '0' + mois; }
  4466.             var jour = match['datedebut'].getDate();
  4467.             if (jour < 10) { jour = '0' + jour; }
  4468.             var heure = match['datedebut'].getHours();
  4469.             if (heure < 10) { heure = '0' + heure; }
  4470.             var minute = match['datedebut'].getMinutes();
  4471.             if (minute < 10) { minute = '0' + minute; }
  4472.             var limite_ko = match['limite_ko'];
  4473.             if (limite_ko == 0) { limite_ko = "unlimited"; }
  4474.             var duree = match['duree'];
  4475.             if (duree == 0) { duree = "unlimited"; }
  4476.             else if (duree == 1) { duree = "1 minute"; }
  4477.             else { duree = duree + " minutes"; }
  4478.             var message1 = "Hi!\n\nRemember that you have a " + match['type'] + " match against " + match['pseudo2'] + " in less than 24 hours.Here are the informations concerning this match:\n\n> Starting time: " + annee + "-" + mois + "-" + jour + " " + heure + ':' + minute + " *UTC*\n>First to " + match['nb_manches'] + ", win by " + match['diff_manches'] + "\n>Length of a round: " + duree + "\n>KO limit: " + limite_ko + "\n\nTen minutes before this match starts, you will be able to join your room from the website's Dashboard.\n\nHave fun on Worldwide Combos!\n\nBest regards,\n\n Noël Nadal (Worldwide Combos admin).";
  4479.             var message2 = "Hi!\n\nRemember that you have a " + match['type'] + " match against " + match['pseudo1'] + " in less than 24 hours.Here are the informations concerning this match:\n\n> Starting time: " + annee + "-" + mois + "-" + jour + " " + heure + ':' + minute + " *UTC*\n>First to " + match['nb_manches'] + ", win by " + match['diff_manches'] + "\n>Length of a round: " + duree + "\n>KO limit: " + limite_ko + "\n\nTen minutes before this match starts, you will be able to join your room from the website's Dashboard.\n\nHave fun on Worldwide Combos!\n\nBest regards,\n\n Noël Nadal (Worldwide Combos admin).";
  4480.             if (match['infos1'] == 1 || match['tournoi'] > 0) {
  4481.                 var message = {
  4482.                     text:   message1,
  4483.                     from:   "Worldwide Combos <noreply@worldwide-combos.com>",
  4484.                     to:     match['email1'],
  4485.                     subject:    match['Type'] + " match reminder",
  4486.                     attachment:
  4487.                     [
  4488.                         {data:"<html>Hi!<br><br>Remember that you have a " + match['type'] + " match against " + match['pseudo2'] + " in less than 24 hours. Here are the informations concerning this match:<ul><li>Starting time: " + annee + "-" + mois + "-" + jour + " " + heure + ':' + minute + " <b>UTC</b></li><li>First to " + match['nb_manches'] + ", win by " + match['diff_manches'] + "</li><li>Length of a round: " + duree + "</li><li>KO limit: " + limite_ko + "</li></ul>Ten minutes before this match starts, you will be able to join your room from the website's Dashboard.<br><br>Have fun on Worldwide Combos!<br><br>Best regards,<br><br>Noël Nadal (Worldwide Combos admin).</html>", alternative:true}
  4489.                     ]
  4490.                 };
  4491.                 server_noreply.send(message, function(err, message) { console.log(getDateTime() + 'Notification courriel envoyée à ' + match['pseudo1'] + ' (notification 24 heures).'); });  
  4492.             }
  4493.             if (match['infos2'] == 1 || match['tournoi'] > 0) {
  4494.                 var message = {
  4495.                     text:   message2,
  4496.                     from:   "Worldwide Combos <noreply@worldwide-combos.com>",
  4497.                     to:     match['email2'],
  4498.                     subject:    match['Type'] + " match reminder",
  4499.                     attachment:
  4500.                     [
  4501.                         {data:"<html>Hi!<br><br>Remember that you have a " + match['type'] + " match against " + match['pseudo1'] + " in less than 24 hours. Here are the informations concerning this match:<ul><li>Starting time: " + annee + "-" + mois + "-" + jour + " " + heure + ':' + minute + " <b>UTC</b></li><li>First to " + match['nb_manches'] + ", win by " + match['diff_manches'] + "</li><li>Length of a round: " + duree + "</li><li>KO limit: " + limite_ko + "</li></ul>Ten minutes before this match starts, you will be able to join your room from the website's Dashboard.<br><br>Have fun on Worldwide Combos!<br><br>Best regards,<br><br>Noël Nadal (Worldwide Combos admin).</html>", alternative:true}
  4502.                     ]
  4503.                 };
  4504.                 server_noreply.send(message, function(err, message) { console.log(getDateTime() + 'Notification courriel envoyée à ' + match['pseudo2'] + ' (notification 24 heures).'); });  
  4505.             }
  4506.             if (match['discord1'] == 1 || match['tournoi'] > 0) { prive_Discord(match['code1'], message1); }
  4507.             if (match['discord2'] == 1 || match['tournoi'] > 0) { prive_Discord(match['code2'], message2); }
  4508.         }
  4509.     });
  4510.    
  4511.     // notifications 30 minutes
  4512.     connection.query('SELECT joueur1, joueur2, matches.tournoi AS tournoi, nb_manches, diff_manches, limite_ko, duree, handicap, diff_victoire, datedebut, m1.pseudo AS pseudo1, m1.discord AS code1, m2.pseudo AS pseudo2, m2.discord AS code2, m1.infos5 AS infos1, m1.discord5 AS discord1, m2.infos5 AS infos2, m2.discord5 AS discord2, m1.email AS email1, m2.email AS email2 FROM matches LEFT JOIN membres AS m1 ON matches.joueur1 = m1.id LEFT JOIN membres AS m2 ON matches.joueur2 = m2.id WHERE datedebut > DATE_ADD(NOW(), INTERVAL 30 MINUTE) AND datedebut < DATE_ADD(DATE_ADD(NOW(), INTERVAL 30 MINUTE), INTERVAL 1 MINUTE) AND confirmation = 1', function(error, prochains, fields) {
  4513.         for(i = 0; i < prochains.length; i++) {
  4514.             var match = prochains[i];
  4515.             if (match['tournoi'] == 0) { match['type'] = 'custom'; } else { match['type'] = 'tournament'; }
  4516.             var annee = match['datedebut'].getFullYear();
  4517.             var mois = 1+match['datedebut'].getMonth();
  4518.             if (mois < 10) { mois = '0' + mois; }
  4519.             var jour = match['datedebut'].getDate();
  4520.             if (jour < 10) { jour = '0' + jour; }
  4521.             var heure = match['datedebut'].getHours();
  4522.             if (heure < 10) { heure = '0' + heure; }
  4523.             var minute = match['datedebut'].getMinutes();
  4524.             if (minute < 10) { minute = '0' + minute; }
  4525.             var limite_ko = match['limite_ko'];
  4526.             if (limite_ko == 0) { limite_ko = "unlimited"; }
  4527.             var duree = match['duree'];
  4528.             if (duree == 0) { duree = "unlimited"; }
  4529.             else if (duree == 1) { duree = "1 minute"; }
  4530.             else { duree = duree + " minutes"; }
  4531.             var message1 = "Hi!\n\nYour " + match['type'] + " match against " + match['pseudo2'] + " is starting in 30 minutes! Here are the informations concerning this match:\n\n>Starting time: " + annee + "-" + mois + "-" + jour + " " + heure + ':' + minute + " *UTC*\n>First to " + match['nb_manches'] + ", win by " + match['diff_manches'] + "\n>Length of a round: " + duree + "\n>KO limit: " + limite_ko + "\n\nTen minutes before this match starts, you will be able to join your room from the website's Dashboard.\n\nHave fun on Worldwide Combos!\n\nBest regards,\n\n Noël Nadal (Worldwide Combos admin).";
  4532.             var message2 = "Hi!\n\nYour " + match['type'] + " match against " + match['pseudo1'] + " is starting in 30 minutes! Here are the informations concerning this match:\n\n>Starting time: " + annee + "-" + mois + "-" + jour + " " + heure + ':' + minute + " *UTC*\n>First to " + match['nb_manches'] + ", win by " + match['diff_manches'] + "\n>Length of a round: " + duree + "\n>KO limit: " + limite_ko + "\n\nTen minutes before this match starts, you will be able to join your room from the website's Dashboard.\n\nHave fun on Worldwide Combos!\n\nBest regards,\n\n Noël Nadal (Worldwide Combos admin).";
  4533.             if (match['infos1'] == 1 || match['tournoi'] > 0) {
  4534.                 var message = {
  4535.                     text:   message1,
  4536.                     from:   "Worldwide Combos <noreply@worldwide-combos.com>",
  4537.                     to:     match['email1'],
  4538.                     subject:    "Get ready for your " + match['type'] + " match!",
  4539.                     attachment:
  4540.                     [
  4541.                         {data:"<html>Hi!<br><br>Your " + match['type'] + " match against " + match['pseudo2'] + " is starting in 30 minutes! Here are the informations concerning this match:<ul><li>Starting time: " + annee + "-" + mois + "-" + jour + " " + heure + ':' + minute + " <b>UTC</b></li><li>First to " + match['nb_manches'] + ", win by " + match['diff_manches'] + "</li><li>Length of a round: " + duree + "</li><li>KO limit: " + limite_ko + "</li></ul>Ten minutes before this match starts, you will be able to join your room from the website's Dashboard.<br><br>Have fun on Worldwide Combos!<br><br>Best regards,<br><br>Noël Nadal (Worldwide Combos admin).</html>", alternative:true}
  4542.                     ]
  4543.                 };
  4544.                 server_noreply.send(message, function(err, message) { console.log(getDateTime() + 'Notification courriel envoyée à ' + match['pseudo1'] + ' (notification 30 minutes).'); });  
  4545.             }
  4546.             if (match['infos2'] == 1 || match['tournoi'] > 0) {
  4547.                 var message = {
  4548.                     text:   message2,
  4549.                     from:   "Worldwide Combos <noreply@worldwide-combos.com>",
  4550.                     to:     match['email2'],
  4551.                     subject:    "Get ready for your " + match['type'] + " match!",
  4552.                     attachment:
  4553.                     [
  4554.                         {data:"<html>Hi!<br><br>Your " + match['type'] + " match against " + match['pseudo1'] + " is starting in 30 minutes! Here are the informations concerning this match:<ul><li>Starting time: " + annee + "-" + mois + "-" + jour + " " + heure + ':' + minute + " <b>UTC</b></li><li>First to " + match['nb_manches'] + ", win by " + match['diff_manches'] + "</li><li>Length of a round: " + duree + "</li><li>KO limit: " + limite_ko + "</li></ul>Ten minutes before this match starts, you will be able to join your room from the website's Dashboard.<br><br>Have fun on Worldwide Combos!<br><br>Best regards,<br><br>Noël Nadal (Worldwide Combos admin).</html>", alternative:true}
  4555.                     ]
  4556.                 };
  4557.                 server_noreply.send(message, function(err, message) { console.log(getDateTime() + 'Notification courriel envoyée à ' + match['pseudo2'] + ' (notification 30 minutes).'); });  
  4558.             }
  4559.             if (match['discord1'] == 1 || match['tournoi'] > 0) { prive_Discord(match['code1'], message1); }
  4560.             if (match['discord2'] == 1 || match['tournoi'] > 0) { prive_Discord(match['code2'], message2); }
  4561.         }
  4562.     });
  4563.    
  4564.     // notifications 10 minutes
  4565.     connection.query('SELECT joueur1, joueur2, matches.tournoi AS tournoi, nb_manches, diff_manches, limite_ko, duree, handicap, diff_victoire, datedebut, m1.pseudo AS pseudo1, m1.discord AS code1, m2.pseudo AS pseudo2, m2.discord AS code2, m1.email AS email1, m2.email AS email2 FROM matches LEFT JOIN membres AS m1 ON matches.joueur1 = m1.id LEFT JOIN membres AS m2 ON matches.joueur2 = m2.id WHERE datedebut > DATE_ADD(NOW(), INTERVAL 10 MINUTE) AND datedebut < DATE_ADD(DATE_ADD(NOW(), INTERVAL 10 MINUTE), INTERVAL 1 MINUTE) AND confirmation = 1', function(error, prochains, fields) {
  4566.         //console.log('10 ' + prochains.length);
  4567.         for(i = 0; i < prochains.length; i++) {
  4568.             var match = prochains[i];
  4569.             if (match['tournoi'] == 0) { match['type'] = 'custom'; } else { match['type'] = 'tournament'; }
  4570.             var annee = match['datedebut'].getFullYear();
  4571.             var mois = 1+match['datedebut'].getMonth();
  4572.             if (mois < 10) { mois = '0' + mois; }
  4573.             var jour = match['datedebut'].getDate();
  4574.             if (jour < 10) { jour = '0' + jour; }
  4575.             var heure = match['datedebut'].getHours();
  4576.             if (heure < 10) { heure = '0' + heure; }
  4577.             var minute = match['datedebut'].getMinutes();
  4578.             if (minute < 10) { minute = '0' + minute; }
  4579.             var limite_ko = match['limite_ko'];
  4580.             if (limite_ko == 0) { limite_ko = "unlimited"; }
  4581.             var duree = match['duree'];
  4582.             if (duree == 0) { duree = "unlimited"; }
  4583.             else if (duree == 1) { duree = "1 minute"; }
  4584.             else { duree = duree + " minutes"; }
  4585.             var message1 = "Hi!\n\nYour " + match['type'] + " match against " + match['pseudo2'] + " is starting in 10 minutes! It is now time to join your room from the website's Dashboard: find your match in the list of upcoming matches and click on \"PLAY\".\n\nHave fun on Worldwide Combos!\n\nBest regards,\n\n Noël Nadal (Worldwide Combos admin).";
  4586.             var message2 = "Hi!\n\nYour " + match['type'] + " match against " + match['pseudo1'] + " is starting in 10 minutes! It is now time to join your room from the website's Dashboard: find your match in the list of upcoming matches and click on \"PLAY\".\n\nHave fun on Worldwide Combos!\n\nBest regards,\n\n Noël Nadal (Worldwide Combos admin).";
  4587.             if (match['tournoi'] > 0) {
  4588.                 var message = {
  4589.                     text:   message1,
  4590.                     from:   "Worldwide Combos <noreply@worldwide-combos.com>",
  4591.                     to:     match['email1'],
  4592.                     subject:    "Your tournament match is starting!",
  4593.                     attachment:
  4594.                     [
  4595.                         {data:"<html>Hi!<br><br>Your " + match['type'] + " match against " + match['pseudo2'] + " is starting in 10 minutes! It is now time to join your room from the website's Dashboard: find your match in the list of upcoming matches and click on \"PLAY\".<br><br>Have fun on Worldwide Combos!<br><br>Best regards,<br><br>Noël Nadal (Worldwide Combos admin).</html>", alternative:true}
  4596.                     ]
  4597.                 };
  4598.                 server_noreply.send(message, function(err, message) { console.log(getDateTime() + 'Notification courriel envoyée à ' + match['pseudo1'] + ' (notification 10 minutes).'); });  
  4599.             }
  4600.             if (match['tournoi'] > 0) {
  4601.                 var message = {
  4602.                     text:   message2,
  4603.                     from:   "Worldwide Combos <noreply@worldwide-combos.com>",
  4604.                     to:     match['email2'],
  4605.                     subject:    "Your tournament match is starting!",
  4606.                     attachment:
  4607.                     [
  4608.                         {data:"<html>Hi!<br><br>Your " + match['type'] + " match against " + match['pseudo1'] + " is starting in 10 minutes! It is now time to join your room from the website's Dashboard: find your match in the list of upcoming matches and click on \"PLAY\".<br><br>Have fun on Worldwide Combos!<br><br>Best regards,<br><br>Noël Nadal (Worldwide Combos admin).</html>", alternative:true}
  4609.                     ]
  4610.                 };
  4611.                 server_noreply.send(message, function(err, message) { console.log(getDateTime() + 'Notification courriel envoyée à ' + match['pseudo2'] + ' (notification 10 minutes).'); });  
  4612.             }
  4613.             if (match['tournoi'] > 0) { prive_Discord(match['code1'], message1); }
  4614.             if (match['tournoi'] > 0) { prive_Discord(match['code2'], message2); }
  4615.         }
  4616.     });
  4617.    
  4618.     // notification tournoi 24 heures
  4619.     connection.query('SELECT id, nom FROM tournois WHERE datedebut > DATE_ADD(NOW(), INTERVAL 1 DAY) AND datedebut < DATE_ADD(DATE_ADD(NOW(), INTERVAL 1 DAY), INTERVAL 1 MINUTE) AND fini = -1', function (error, prochains_tournois, fields) {
  4620.         for (var i = 0; i < prochains_tournois.length; i++) {
  4621.             message_discord('general', 'Less than 24 hours left before registration for ' + prochains_tournois[i]['nom'] + ' closes!\nInformations and registration here: https://www.worldwide-combos.com/tournament?id='+id_tournoi+'.');
  4622.         }
  4623.     });
  4624.    
  4625.     // retirer les points de tournoi
  4626.     connection.query('SELECT id, id_membre, points FROM points_tournois WHERE datelimite < DATE_SUB(NOW(), INTERVAL 1 YEAR) AND actif = 1', function (error, retirer, fields) {
  4627.         for (var i = 0; i < retirer.length; i++) {
  4628.             connection.query('UPDATE membres SET tournoi = tournoi - ? WHERE id = ?', [retirer[i]['points'], retirer[i]['id_membre']], function (error, ok1, fields) {
  4629.                 connection.query('UPDATE points_tournois SET actif = 0 WHERE id = ?', [retirer[i]['id']], function (error, ok2, fields) {
  4630.                     console.log(getDateTime() + retirer[i]['points'] + ' points retirés (id_membre : ' + retirer[i]['id_membre'] + ').');
  4631.                 });
  4632.             });
  4633.         }
  4634.     });
  4635.    
  4636.     function ecrire_poules(texte_poule, id_tournoi) {
  4637.         fs.writeFile(path.join(__dirname, '/tournois/poules_'+id_tournoi+'.txt'), texte_poule, function (err) {
  4638.             console.log(getDateTime() + 'C\'est bon pour les poules.');
  4639.             message_discord('general', 'Pools are now available: https://www.worldwide-combos.com/tournament?id='+id_tournoi+'. Good luck and have fun!');
  4640.         });
  4641.     }
  4642.    
  4643.     function arranger_match_14(joueur1, joueur2, id_tournoi) {
  4644.         var zero = '0'.repeat(168), res = new Array(168*1);
  4645.         var ajd = new Date(), proch = new Date('2018-05-21');
  4646.         ajd = new Date(proch);
  4647.         //console.log(ajd);
  4648.         //ajd.setDate(ajd.getDate()+7);
  4649.         var mois = ajd.getMonth(), annee = ajd.getFullYear(), jour = ajd.getDate();
  4650.         var cal1 = new Array(168*1), cal2 = new Array(168*1);
  4651.         for (var i = 0; i < 168*1; i++) { cal1[i] = '0'; cal2[i] = '0'; }
  4652.         fs.readFile(path.join(__dirname, 'calendrier/'+joueur1['id']+'/'+annee+'-'+mois+'-'+jour+'.txt'), 'utf8', function (err,donnees11) {
  4653.             if (donnees11 == undefined) { donnees11 = zero; }
  4654.             if (joueur1['fuseau'] >= 0) {
  4655.                 for (i = joueur1['fuseau']; i < 168; i++) {
  4656.                     cal1[i-joueur1['fuseau']] = donnees11[i];
  4657.                 }
  4658.             }
  4659.             else {
  4660.                 for (var i = 0; i < 168; i++) {
  4661.                     cal1[i-joueur1['fuseau']] = donnees11[i];
  4662.                 }
  4663.             }
  4664.             fs.readFile(path.join(__dirname, 'calendrier/'+joueur2['id']+'/'+annee+'-'+mois+'-'+jour+'.txt'), 'utf8', function (err,donnees21) {
  4665.                 if (donnees21 == undefined) { donnees21 = zero; }
  4666.                 if (joueur2['fuseau'] >= 0) {
  4667.                     for (i = joueur2['fuseau']; i < 168; i++) {
  4668.                         cal2[i-joueur2['fuseau']] = donnees21[i];
  4669.                     }
  4670.                 }
  4671.                 else {
  4672.                     for (var i = 0; i < 168; i++) {
  4673.                         cal2[i-joueur2['fuseau']] = donnees21[i];
  4674.                     }
  4675.                 }
  4676.                 //console.log(cal2);
  4677.                 //console.log(" ");
  4678.                 ajd.setDate(ajd.getDate()+7);
  4679.                 mois = ajd.getMonth(), annee = ajd.getFullYear(), jour = ajd.getDate();
  4680.                 fs.readFile(path.join(__dirname, 'calendrier/'+joueur1['id']+'/'+annee+'-'+mois+'-'+jour+'.txt'), 'utf8', function (err,donnees12) {
  4681.                     if (donnees12 == undefined) { donnees12 = zero; }
  4682.                     if (joueur1['fuseau'] >= 0) {
  4683.                         for (var i = 0; i < 168; i++) {
  4684.                             cal1[168+i-joueur1['fuseau']] = donnees12[i];
  4685.                         }
  4686.                     }
  4687.                     else {
  4688.                         for (var i = 0; i < 168+joueur1['fuseau']; i++) {
  4689.                             cal1[168+i-joueur1['fuseau']] = donnees12[i];
  4690.                         }
  4691.                     }
  4692.                     //console.log(cal1);
  4693.                     //console.log(" ");
  4694.                     fs.readFile(path.join(__dirname, 'calendrier/'+joueur2['id']+'/'+annee+'-'+mois+'-'+jour+'.txt'), 'utf8', function (err,donnees22) {
  4695.                         if (donnees22 == undefined) { donnees22 = zero; }
  4696.                         if (joueur2['fuseau'] >= 0) {
  4697.                             for (var i = 0; i < 168; i++) {
  4698.                                 cal2[168+i-joueur2['fuseau']] = donnees22[i];
  4699.                             }
  4700.                         }
  4701.                         else {
  4702.                             for (var i = 0; i < 168+joueur2['fuseau']; i++) {
  4703.                                 cal2[168+i-joueur2['fuseau']] = donnees22[i];
  4704.                             }
  4705.                         }
  4706.                         for (var i = 0; i < 168*1; i++) {
  4707.                             if (cal1[i] == '2' && cal2[i] == '1') { res[i] = 100000; }
  4708.                             else if (cal1[i] == '1' && cal2[i] == '2') { res[i] = 200000; }
  4709.                             else if (cal1[i] == '1' && cal2[i] == '1') { res[i] = 300000; }
  4710.                             else if (cal1[i] == '2' && cal2[i] == '0') { res[i] = 400000; }
  4711.                             else if (cal1[i] == '0' && cal2[i] == '2') { res[i] = 500000; }
  4712.                             else if (cal1[i] == '1' && cal2[i] == '0') { res[i] = 600000; }
  4713.                             else if (cal1[i] == '0' && cal2[i] == '1') { res[i] = 700000; }
  4714.                             else if (cal1[i] == '0' && cal2[i] == '0') { res[i] = 800000; }
  4715.                         }
  4716.                         for (var i = 0; i < 48; i++) {
  4717.                             res[i] += 100000*(48-i);
  4718.                         }
  4719.                         connection.query('SELECT datedebut FROM matches WHERE (joueur1 = ? OR joueur2 = ? OR joueur1 = ? OR joueur2 = ?) AND datedebut >= NOW() AND datedebut <= DATE_ADD(NOW(), INTERVAL 14 DAY) ORDER BY datedebut', [joueur1['id'], joueur1['id'], joueur2['id'], joueur2['id']], function (error, liste, fields) {
  4720.                             var i = 0;
  4721.                             var dt = new Date(proch);
  4722.                             for (var j = 0; j < liste.length; j++) {
  4723.                                 console.log(liste.length);
  4724.                                 var dm = new Date(liste[j]['datedebut']);
  4725.                                 dm.setMinutes(0);
  4726.                                 dm.setSeconds(0);
  4727.                                 while (dt.getDate() != dm.getDate() || dt.getHours() != dm.getHours()) {
  4728.                                     i++;
  4729.                                     dt.setHours(dt.getHours()+1);
  4730.                                     if (i == 168*2) { console.log(dt, dm); break; }
  4731.                                 }
  4732.                                 for (var k = 0; k < 24; k++) {
  4733.                                     if (i-k > 0) { res[i-k] += 2400000-100000*k; }
  4734.                                     if (i+k < 168*2) { res[i+k] += 24000000-100000*k; }
  4735.                                 }
  4736.                             }
  4737.                             //var minimum = res[(stop+2)%(168*1)], indice = (stop+2)%(168*1);
  4738.                             var minimum = res[24], indice = 24;
  4739.                             //i = (stop+2)%(168*1);
  4740.                             i = 24;
  4741.                             while (i < 168*2) {
  4742.                                 //console.log(i);
  4743.                                 if (res[i] < minimum) { minimum = res[i]; indice = i; }
  4744.                                 i++;
  4745.                                 //if (i == 168*1) { i = 0; }
  4746.                             }
  4747.                             proch.setHours(proch.getHours()+indice); // heure du match
  4748.                             stop = indice;
  4749.                             ajd.setDate(ajd.getDate()+7); // date limite
  4750.                             console.log(joueur1['id'], joueur2['id']);
  4751.                             console.log(proch);
  4752.                             //connection.query('DELETE FROM matches WHERE joueur1 = ? AND joueur2 = ?', [joueur1['id'], joueur2['id']], , function (error, ok, fields) { console.log(error); }
  4753.                             connection.query('INSERT INTO matches(joueur1, joueur2, debutmanche, datedebut, datelimite, tournoi, nb_manches, diff_manches, limite_ko, duree, confirmation) VALUES(?,?,?,?,?,?,5,1,0,2,1)', [joueur1['id'], joueur2['id'], proch, proch, ajd, id_tournoi], function (error, ok, fields) {});
  4754.                         });
  4755.                     });
  4756.                 });
  4757.             });
  4758.         });
  4759.     }
  4760.   /*  stop = 168*1-1;
  4761.     var t1 = [395, 395];
  4762.     var t2 = [618, 253];
  4763.     var t3 = {253: 1, 395: 11, 618: 11};    
  4764.     for(i = 0; i < 2; i++) {
  4765.         setTimeout(arranger_match_14, 200*i, {id: t1[i], fuseau: t3[t1[i]]}, {id: t2[i], fuseau: t3[t2[i]]}, 3);
  4766.     } */
  4767.    
  4768.     function lancer_tournoi(id_tournoi) {
  4769.         connection.query('SELECT nom FROM tournoi WHERE id = ?', [id_tournoi['id']], function (error, nom_tournoi, fields) {
  4770.         connection.query('SELECT id_membre AS id, membres.tournoi AS tournoi FROM inscriptions LEFT JOIN membres ON membres.id = inscriptions.id_membre WHERE id_tournoi = ? ORDER BY membres.tournoi DESC, membres.elo2 DESC, membres.survivor DESC, IF(membres.sprint = 0, 1000000000, membres.sprint), inscriptions.dateinscription ', [id_tournoi['id']], function (error, liste_participants, fields) {
  4771.             connection.query('UPDATE tournois SET fini = 0 WHERE id = ?', [id_tournoi['id']], function (error, ok, fields) {});
  4772.             var lp = liste_participants;
  4773.             var np = lp.length; // nombre de participants
  4774.             var inscrits = '';
  4775.             for (j = 0; j < np; j++) {
  4776.                 inscrits += lp[i]['id'] + ' ' + lp[i]['tournoi'] + '\n';
  4777.             }
  4778.             fs.writeFile(path.join(__dirname, '/tournois/inscrits_'+id_tournoi+'.txt'), texte_poule, function (err) {
  4779.                 console.log(getDateTime() + 'C\'est bon pour la liste des inscrits.');
  4780.             });
  4781.             // randomisation deux par deux
  4782.             for (j = 0; j < Math.floor(np/2); j += 2) {
  4783.                 var aleat = Math.floor(Math.random()*2);
  4784.                 if (aleat == 1) {
  4785.                     var c = lp[j];
  4786.                     lp[j] = lp[j+1];
  4787.                     lp[j+1] = c;
  4788.                 }
  4789.             }
  4790.             // création des poules
  4791.             var joueurs_par_poule = 5;
  4792.             var nombre_poules = 1 + Math.floor((np-1)/joueurs_par_poule);
  4793.             message_discord('general', 'Registration for ' + nom_tournoi[0]['nom'] + ' is now closed. Pools are now going to be created. Estimated time: ' + 1+Math.floor(nombre_poules*0.4*joueurs_par_poule*joueurs_par_poule) + ' seconds.');  
  4794.             poules = new Array(nombre_poules);
  4795.             for (l = 0; l < nombre_poules; l++) { poules[l] = new Array(); }
  4796.             var z = 1, k = 0;
  4797.             texte_poule = '0 ' + nombre_poules + '\n';
  4798.             for (l = 0; l < np; l++) {
  4799.                 poules[k].push(lp[l]);
  4800.                 k += z;
  4801.                 if (k == nombre_poules) { z = -1; k--; }
  4802.                 else if (k == -1) { z = 1; k++; }
  4803.             }
  4804.             var texte = '0 ' + nombre_poules + '\n';
  4805.             for (l = 0; l < nombre_poules; l++) {
  4806.                 texte += poules[l].length + ' ';
  4807.             }
  4808.             texte += '\n';
  4809.             for (l = 0; l < nombre_poules; l++) {
  4810.                 var currentIndex = poules[l].length, temporaryValue, randomIndex;
  4811.                 while (0 !== currentIndex) {
  4812.                     randomIndex = Math.floor(Math.random() * currentIndex);
  4813.                     currentIndex -= 1;
  4814.                     temporaryValue = poules[l][currentIndex];
  4815.                     poules[l][currentIndex] = poules[l][randomIndex];
  4816.                     poules[l][randomIndex] = temporaryValue;
  4817.                 }
  4818.                 for (a1 = 0; a1 < poules[l].length; a1++) {
  4819.                     texte += poules[l][a1]['id'] + ' ';
  4820.                     for (a2 = 0; a2 < poules[l].length; a2++) {
  4821.                         if (a1 == a2) { texte += 'x '; }
  4822.                         else { texte += '? '; }
  4823.                     }
  4824.                     texte += '\n';
  4825.                 }
  4826.                 for (a1 = 0; a1 < poules[l].length-1; a1++) {
  4827.                     for (a2 = a1+1; a2 < poules[l].length; a2++) {
  4828.                         console.log(a1, a2);
  4829.                         setTimeout(arranger_match_14, 400*(a1*(joueurs_par_poule-1)+a2), poules[l][a1], poules[l][a2], id_tournoi['id']);
  4830.                         texte += '?' + ' ' + poules[l][a1]['id'] + ' ' + poules[l][a2]['id'] + '\n'; // remplacer
  4831.                     }
  4832.                 }
  4833.             }
  4834.             setTimeout(ecrire_poules, nombre_poules*400*joueurs_par_poule*joueurs_par_poule, texte, id_tournoi['id']);
  4835.         });
  4836.         });
  4837.     }
  4838.    
  4839.     function quickfire_fichier(id_tournoi) {
  4840.         connection.query('SELECT * FROM matches WHERE tournoi = ? ORDER BY datedebut', [id_tournoi], function (error, liste, fields) {
  4841.             var texte = '';
  4842.             for (var i = 0; i < liste.length; i++) {
  4843.                 var match = liste[i];
  4844.                 if (match['confirmation'] == 2) {
  4845.                     texte += match['id'] + ' ' + match['joueur1'] + ' ' + match['joueur2'] + ' ' + match['score1'] + ' ' + match['score2'] + '\n';
  4846.                 }
  4847.                 else {
  4848.                     texte += match['id'] + ' ' + match['joueur1'] + ' ' + match['joueur2'] + ' ? ?\n';
  4849.                 }
  4850.             }
  4851.             fs.writeFile(path.join(__dirname, '/tournois/poules_'+id_tournoi+'.txt'), texte, function (err) {
  4852.                 console.log(getDateTime() + 'C\'est bon pour les poules.');
  4853.                 //message_discord('general', 'The Quickfire is now beginning: https://www.worldwide-combos.com/tournament?id='+id_tournoi+'. Good luck and have fun!');
  4854.             });
  4855.         });
  4856.     }
  4857.    
  4858.     function quickfire_poules(id_tournoi) {
  4859.         // ATTENTION ATTENTION ATTENTION
  4860.         //setInterval(quickfire_finale, 3*60000, id_tournoi['id']); // remplacer par 47
  4861.         setInterval(quickfire_fichier, 60000, id_tournoi['id']);
  4862.         connection.query('SELECT nom, datedebut FROM tournois WHERE id = 6', /*[id_tournoi['id']], */function (error, nom_tournoi, fields) { console.log(error);
  4863.             connection.query('SELECT id_membre AS id, membres.tournoi AS tournoi FROM inscriptions LEFT JOIN membres ON membres.id = inscriptions.id_membre WHERE id_tournoi = ? ORDER BY membres.tournoi DESC, membres.elo2 DESC, membres.survivor DESC, IF(membres.sprint = 0, 1000000000, membres.sprint), inscriptions.dateinscription ', [id_tournoi['id']], function (error, liste_participants, fields) {
  4864.                 console.log(error);
  4865.                 connection.query('UPDATE tournois SET fini = 0 WHERE id = ?', [id_tournoi['id']], function (error, ok, fields) {});
  4866.                 var participants = liste_participants;
  4867.                 var p = participants.length; // nombre de participants
  4868.                 var inscrits = '';
  4869.                 for (j = 0; j < p; j++) {
  4870.                     inscrits += participants[j]['id'] + ' ' + participants[j]['tournoi'] + '\n';
  4871.                 }
  4872.                 fs.writeFile(path.join(__dirname, '/tournois/inscrits_'+id_tournoi+'.txt'), inscrits, function (err) {
  4873.                     console.log(getDateTime() + 'C\'est bon pour la liste des inscrits.');
  4874.                 });
  4875.                 // randomisation deux par deux
  4876.                 var p = participants.length;
  4877.                 p += p%2;
  4878.                 participants.push({id: -1});
  4879.                 var total = 16;
  4880.                 var liste = new Array();
  4881.                 while (total > 0) {
  4882.                     liste.push(Math.min(total, p-1));
  4883.                     total -= Math.min(total, p-1);
  4884.                 }
  4885.                 var lg = liste.length;
  4886.                 var v = 0;
  4887.                 var datematch = new Date(nom_tournoi[0]['datedebut']);
  4888.                 datematch.setMinutes(datematch.getMinutes()+1);
  4889.                 for (var i = 0; i < lg; i++) {
  4890.                     melanger(participants);
  4891.                     var matches = participants;
  4892.                     for (var j = 0; j < liste[i]; j++) {
  4893.                         v++;
  4894.                         if (v == 9) { datematch.setMinutes(datematch.getMinutes()+5); }
  4895.                         for (var k = p; k > 0; k -= 2) {
  4896.                             quickfire[matches[k-1]['id']] = {adversaire: matches[p-k]['id'], socket: {}, pret: 0, datematch: datematch};
  4897.                             quickfire[matches[p-k]['id']] = {adversaire: matches[k-1]['id'], socket: {}, pret: 0, datematch: datematch};
  4898.                             if (matches[k-1]['id'] > 0 && matches[p-k]['id'] > 0) {
  4899.                                 console.log(matches[k-1]['id'], matches[p-k]['id']);
  4900.                                 connection.query('INSERT INTO matches(tournoi, nb_manches, diff_manches, limite_ko, duree, debutmanche, datedebut, joueur1, joueur2, confirmation) VALUES(?, 1, 1, 0, 2, ?, ?, ?, ?, 1)',
  4901.                                 [0, datematch, datematch, matches[k-1]['id'], matches[p-k]['id']], function (error, ok, fields) { console.log(error); });
  4902.                             }
  4903.                         }
  4904.                         var c = matches[p-1];
  4905.                         for (var k = p-1; k > 1; k--) {
  4906.                             matches[k] = matches[k-1];
  4907.                         }
  4908.                         matches[1] = c;
  4909.                         datematch.setMinutes(datematch.getMinutes()+2);
  4910.                         datematch.setSeconds(datematch.getSeconds()+30);
  4911.                     }
  4912.                 }
  4913.             });
  4914.         });
  4915.     }
  4916.    
  4917.     // vérifier début tournoi
  4918.     connection.query('SELECT id, type FROM tournois WHERE datedebut > NOW() AND datedebut < DATE_ADD(NOW(), INTERVAL 1 MINUTE)', function (error, prochains_tournois, fields) {
  4919.         for (var i = 0; i < prochains_tournois.length; i++) {
  4920.             if (prochains_tournois[i]['type'] == 0) {
  4921.                 setTimeout(lancer_tournoi, 60000*i, prochains_tournois[i]);
  4922.             }
  4923.             else {
  4924.                 setTimeout(quickfire_poules, 60000*i, prochains_tournois[i]);
  4925.             }
  4926.         }
  4927.     });
  4928.  
  4929. }
  4930.  
  4931. var verifications60s = setInterval(verifications_auto_60s, 60000);
  4932. var verifications10s = setInterval(verifications_auto_10s, 10000);
  4933.    
  4934. /* FIN VERIFICATIONS AUTOMATIQUES */
  4935. httpServer.timeout = 0;
  4936. if (LOCALHOST == 1) { httpServer.listen(8080); }
  4937. else { httpServer.listen(process.env.PORT); }  
  4938.  
  4939. // "AIzaSyD_q21yH4b3OIRiQQEpMIDdS5gvNLpFocw"
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement