ldc-babyweb/index.php
2021-02-12 02:37:40 +01:00

461 lines
16 KiB
PHP

<?php
require_once 'Db.php';
$db = new Database('localhost', 'babyweb', 'root', '');
$ranking = $db->requestAll("SELECT * FROM players ORDER BY score DESC");
$players = $db->requestAll("SELECT * FROM players ORDER BY name");
?>
<html>
<head>
<title>BabyWeb</title>
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@500&display=swap" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<!-- development version, includes helpful console warnings -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<!-- production version, optimized for size and speed -->
<!--<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>-->
<style>
body {
padding: 0;
margin: 0;
font-family: 'Montserrat', sans-serif;
}
.ranking table {
font-size: 40px;
text-align: center;
}
.ranking th, .ranking td {
padding: 10px;
}
.ranking tr:nth-child(2) {
color: gold;
}
.ranking tr:nth-child(3) {
color: silver;
}
.ranking tr:nth-child(4) {
color: saddlebrown;
}
.main {
height: 100vh;
display: flex;
justify-content: center;
}
.ranking, .add-match {
padding-top: 5vh;
display: flex;
justify-content: center;
flex: 1;
}
.add-match {
flex-direction: column;
align-items: center;
justify-content: flex-start;
}
.match_type {
margin-bottom: 25px;
font-size: 2.5vw;
font-weight: bold;
}
.add-btn {
height: 50px;
width: 100px;
font-size: 15px;
border: 2px solid;
border-radius: 5px;
font-weight: bold;
}
.score-input {
height: 40px;
width: 80px;
font-size: 1.5vw;
text-align: center;
text-align-last: center;
-moz-text-align-last: center;
}
.blue {
color: blue;
font-weight: bold;
}
.red {
color: red;
font-weight: bold;
}
.add-match table td {
font-size: 2.3vw;
padding: 0 20px;
text-align: center;
}
.add-match table th {
font-size: 2.5vw;
padding: 0 20px;
}
.player-select {
height: 40px;
width: 20vw;
font-size: 1.5vw;
text-align: center;
text-align-last: center;
-moz-text-align-last: center;
}
</style>
</head>
<body>
<div id="app">
<section class="main">
<div class="ranking" style="background-color: lightcoral">
<table>
<tr>
<th>#</th>
<th>Player</th>
<th>Score</th>
</tr>
<tr v-for="(rank, i) in ranking">
<td>{{ i + 1 }}</td>
<td>{{ rank.name }}</td>
<td>{{ rank.score }}</td>
</tr>
</table>
</div>
<div class="add-match" style="background-color: lightblue">
<div v-if="error.length">
<b>{{ error }}</b>
</div>
<div class="match_type">
<label for="1v1" style="margin-right: 30px;">
<input id="1v1" type="radio" v-model="match_type" value="1v1">
1 vs 1
</label>
<label for="2v2">
<input id="2v2" type="radio" v-model="match_type" value="2v2">
2 vs 2
</label>
</div>
<table>
<tr>
<th class="red">Joueur 1</th>
<th class="blue">Joueur 1</th>
</tr>
<tr>
<td>
<select class="player-select" v-model="red_p1">
<option v-for="player in players" :value="player.id">{{ player.name }}</option>
</select>
</td>
<td>
<select class="player-select" v-model="blue_p1">
<option v-for="player in players" :value="player.id">{{ player.name }}</option>
</select>
</td>
</tr>
</table>
<table v-show="match_type === '2v2'" style="margin-top: 20px;">
<tr>
<th class="red">Joueur 2</th>
<th class="blue">Joueur 2</th>
</tr>
<tr>
<td>
<select class="player-select" v-model="red_p2">
<option value="NULL">Vide.</option>
<option v-for="player in players" :value="player.id">{{ player.name }}</option>
</select>
</td>
<td>
<select class="player-select" v-model="blue_p2">
<option value="NULL">Vide.</option>
<option v-for="player in players" :value="player.id">{{ player.name }}</option>
</select>
</td>
</tr>
</table>
<br><br>
<div>
<label style="margin-right: 20px;font-size: 2.3vw;">
<span class="red">Score</span>
<input class="score-input" type="number" v-model="red_score" min="-11" max="15">
</label>
<label style="font-size: 2.3vw">
<input class="score-input" type="number" v-model="blue_score" min="-11" max="15">
<span class="blue">Score</span>
</label>
</div>
<br>
<input class="add-btn" type="submit" value="AJOUTER" @click="addMatch">
</div>
</section>
</div>
<script>
let app = new Vue({
el: '#app',
data: {
players: <?= json_encode($players); ?>,
ranking: <?= json_encode($ranking); ?>,
match_type: '1v1',
red_p1: '',
red_p2: 'NULL',
blue_p1: '',
blue_p2: 'NULL',
red_score: 0,
blue_score: 0,
error: '',
messages: {
'missing.red_p2': {
error: 'Selectionnez joueur rouge 2',
speech: 'Aqueu coucou bob !'
},
'missing.blue_p2': {
error: 'Selectionnez joueur bleu 2',
speech: 'Il manque la bleusaille !'
},
'missing.red_p1': {
error: 'Selectionnez joueur rouge 1',
speech: 'Rejoins le coté obscure de la force !'
},
'missing.blue_p1': {
error: 'Selectionnez joueur bleu 1',
speech: 'Aller les bleu !'
},
'need2differentplayers': {
error: 'Selectionnez des joueurs différents !',
speech: 'Un traitre se cache parmis vous !'
},
'needdifferentplayers': {
error: 'Selectionnez deux joueurs différents !',
speech: 'Même Chuck Norris ne sais pas jouer contre lui même !'
},
'noequals': {
error: 'Les égalités ne sont pas tolérés !',
speech: 'Il n\'en restera qu\'un ! Voici une balle, battez vous !'
},
'1v1': {
'forthewinner': [
'Le gagnant est :winner.',
':winner paye sa tournée !',
':winner peut gagner sans toucher les manettes !',
':winner as battu :looser !',
'Le baby aime :winner, ça cache quelque chose.',
'Avec les :winnercolor :winner est imbattable !'
],
'forthelooser': [
'Tu as perdu :looser !',
'Dommage :looser, essaye encore !',
':looser n\'est pas dans son assiette on dirais, réconforte le :winner',
'Laisse tomber les :loosercolor :looser, ça te porte pas chance !',
],
},
'2v2': {
'forthewinner': [
'C\'est gagné pour :winners !',
'Les :winnercolor ont gagné !',
'Monster kill !'
],
'forthelooser': [
'La team :loosers a perdu !',
'Les :loosercolor ont perdu !',
'La team :loosercolor craint !'
]
}
}
},
watch: {
match_type() {
if (this.match_type === '1v1') {
this.red_p2 = 'NULL';
this.blue_p2 = 'NULL';
}
}
},
computed: {
redP1: function() {
let player = this.getPlayer(this.red_p1);
if(player) {
return player.name.slice(0, -3);
}
return '';
},
redP2: function() {
let player = this.getPlayer(this.red_p2);
if(player) {
return player.name.slice(0, -3);
}
return '';
},
blueP1: function() {
let player = this.getPlayer(this.blue_p1);
if(player) {
return player.name.slice(0, -3);
}
return '';
},
blueP2: function() {
let player = this.getPlayer(this.blue_p2);
if(player) {
return player.name.slice(0, -3);
}
return '';
},
winner: function() {
return this.red_score > this.blue_score ?
this.redP1 : this.blueP1;
},
looser: function() {
return this.red_score < this.blue_score ?
this.redP1 : this.blueP1;
},
winners: function() {
return this.red_score > this.blue_score ?
this.redP1 + (this.redP2.length && this.redP1 !== this.redP2 ? ' et ' + this.redP2 : ''):
this.blueP1 + (this.blueP2.length && this.blueP1 !== this.blueP2 ? ' et ' + this.blueP2 : '');
},
loosers: function() {
return this.red_score < this.blue_score ?
this.redP1 + (this.redP2.length && this.redP1 !== this.redP2 ? ' et ' + this.redP2 : ''):
this.blueP1 + (this.blueP2.length && this.blueP1 !== this.blueP2 ? ' et ' + this.blueP2 : '');
},
winnercolor: function() {
return this.red_score > this.blue_score ? 'rouge' : 'bleu';
},
loosercolor: function() {
return this.red_score < this.blue_score ? 'rouge' : 'bleu';
},
},
methods: {
checkSubmission() {
this.error = '';
switch(this.match_type) {
case '2v2':
if(this.red_p2 === '') {
this.sendMessage('missing.red_p2');
return false;
}
if(this.blue_p2 === '') {
this.sendMessage('missing.blue_p2');
return false;
}
if(this.red_p1 === '') {
this.sendMessage('missing.red_p1');
return false;
}
if(this.blue_p1 === '') {
this.sendMessage('missing.blue_p1');
return false;
}
if(
(this.red_p1 === this.blue_p1 || this.red_p1 === this.blue_p2 ||
this.red_p2 === this.blue_p1 || this.red_p2 === this.blue_p2) &&
this.blue_p2 !== 'NULL' && this.red_p2 !== 'NULL'
) {
this.sendMessage('need2differentplayers');
return false;
}
default:
if(this.red_p1 === '') {
this.sendMessage('missing.red_p1');
return false;
}
if(this.blue_p1 === '') {
this.sendMessage('missing.blue_p1');
return false;
}
if(this.red_p1 === this.blue_p1) {
this.sendMessage('needdifferentplayers');
return false;
}
if(this.red_score === this.blue_score) {
this.sendMessage('noequals');
return false;
}
break;
}
return true;
},
addMatch() {
if (this.checkSubmission()) {
let self = this;
axios.post('/add_score.php', {
red_score: self.red_score,
blue_score: self.blue_score,
red_p1: self.red_p1,
red_p2: self.red_p2,
blue_p1: self.blue_p1,
blue_p2: self.blue_p2,
}).then(function (response) {
console.log(response);
self.ranking = response.data;
self.commentMatch.call(self);
self.red_p1 = 0;
self.red_p2 = 'NULL';
self.blue_p1 = 0;
self.blue_p2 = 'NULL';
self.red_score = 0;
self.blue_score = 0;
}).catch(function (error) {
console.error(error);
this.say('Une erreur est survenue.');
alert('Une erreur est survenue.');
});
}
},
commentMatch() {
let self = this,
vars,
message,
messages = this.messages[this.match_type][Math.floor(Math.random()*2) ?
'forthewinner' : 'forthelooser'];
if(messages.length) {
message = messages[Math.floor(Math.random() * messages.length)];
vars = message.match(/:[0-9A-Za-z_]*/g);
if(vars) {
for(let match of vars) {
try {
message = message.replace(new RegExp(match, 'g'), self[match.substr(1)]);
} catch(e) {
console.error('String replace failed ', e);
}
}
}
console.info(message);
this.say(message);
}
},
sendMessage(messageKey) {
this.error = this.messages[messageKey].error;
this.say(this.messages[messageKey].speech);
},
say(text) {
window.speechSynthesis.speak(new SpeechSynthesisUtterance(text));
},
getPlayer(id) {
for(let player of this.players) {
if(player.id === id) {
return player;
}
}
return null;
},
}
})
</script>
</body>
</html>