X-Git-Url: https://git.auder.net/?a=blobdiff_plain;f=public%2Fjavascripts%2Fcomponents%2Froom.js;h=fbf02ee189904273792d41bcc9dab3f11caf7237;hb=b955c65b942d09d24b5c3bed0d755d4f2f8f71f1;hp=16fcc903278d79a85af8a5bdec6dc32cf5799926;hpb=81da2786f2f497b4416e0488c34a48fb794c28df;p=vchess.git diff --git a/public/javascripts/components/room.js b/public/javascripts/components/room.js index 16fcc903..fbf02ee1 100644 --- a/public/javascripts/components/room.js +++ b/public/javascripts/components/room.js @@ -1,242 +1,158 @@ -// TODO: main playing hall, chat + online players + current challenges + button "new game" +// main playing hall: chat + online players + current challenges + button "new game" +// TODO: my-challenge-list, gérant clicks sur challenges, affichage, réception/émission des infos sur challenges ; de même, my-player-list +// TODO: si on est en train de jouer une partie, le notifier aux nouveaux connectés /* -input#modal-newgame.modal(type="checkbox") -div(role="dialog" aria-labelledby="newGameTxt") - .card.smallpad.small-modal - label#close-newgame.modal-close(for="modal-newgame") - h3#newGameTxt= translations["New game"] - p= translations["Waiting for opponent..."] -*/ - -/* -Players + challenges : == "room" home of variant (surligner si nouveau défi perso et pas affichage courant) -joueurs en ligne (dte), -Nouvelle partie + défis en temps réel + parties en cours (milieu, tabs), -chat général (gauche, activé ou non (bool global storage)). +TODO: surligner si nouveau défi perso et pas affichage courant (cadences base + incrément, corr == incr >= 1jour ou base >= 7j) ---> correspondance: stocker sur serveur lastMove + peerId + color + movesCount + gameId + variant + timeleft -quand je poste un lastMove corr, supprimer mon ancien lastMove le cas échéant (tlm l'a eu) -fin de partie corr: garder maxi nbPlayers lastMove sur serveur, pendant 7 jours (arbitraire) +--> correspondance: stocker sur serveur lastMove + uid + color + movesCount + gameId + variant + timeleft +fin de partie corr: supprimer partie du serveur au bout de 7 jours (arbitraire) +main time should be positive (no 0+2 & cie...) */ - case "newgame": //opponent found - // oppid: opponent socket ID - this.newGame("human", data.fen, data.color, data.oppid, data.gameid); - break; - - // TODO: elsewhere, probably (new game button) - clickGameSeek: function(e) { - this.getRidOfTooltip(e.currentTarget); - if (this.mode == "human" && this.score == "*") - return; //no newgame while playing - if (this.seek) - { - this.conn.send(JSON.stringify({code:"cancelnewgame"})); - this.seek = false; - } - else - this.newGame("human"); - }, - clickComputerGame: function(e) { - this.getRidOfTooltip(e.currentTarget); - if (this.mode == "computer" && this.score == "*" - && this.vr.turn != this.mycolor) +// TODO: au moins l'échange des coups en P2P ? +// TODO: objet game, objet challenge ? et player ? +Vue.component('my-room', { + props: ["conn","settings"], + data: function () { + return { + gdisplay: "live", + user: user, + liveGames: [], + corrGames: [], + players: [], //online players + challenges: [], //live challenges + people: [], //people who connect to this room (or disconnect) + }; + }, + // Modal new game, and then sub-components + template: ` +
+ +
+
+ +

+ {{ translate("Game state (FEN):") }} +

+ +

TODO: cadence, adversaire (pre-filled if click on name)

+

cadence 2m+12s ou 7d+1d (m,s ou d,d) --> main, increment

+

Note: leave FEN blank for random; FEN only for targeted challenge

+ +
+
+
+ + + +
+ +
+
+

Online players

+
+ {{ p.name }} +
+
+
+ + +
+ + + + +
+
+ `, + created: function() { + // TODO: ask server for current corr games (all but mines: names, ID, time control) + const socketMessageListener = msg => { + const data = JSON.parse(msg.data); + switch (data.code) { - // Wait for computer reply first (avoid potential "ghost move" bug) - return; + case "newgame": + // TODO: new game just started: data contain all informations + // (id, players, time control, fenStart ...) + break; + // TODO: also receive live games summaries (update) + // (just players names, time control, and ID + player ID) + case "acceptchallenge": + // oppid: opponent socket ID (or DB id if registered) + if (true) //TODO: if challenge is full + this.newGame(data.challenge, data.user); //user.id et user.name + break; + case "withdrawchallenge": + // TODO + break; + case "cancelchallenge": + // TODO + break; + // TODO: distinguish these (dis)connect events from their analogs in game.js + case "connect": + this.players.push({name:data.name, id:data.uid}); + break; + case "disconnect": + const pIdx = this.players.findIndex(p => p.id == data.uid); + this.players.splice(pIdx); + break; } - this.newGame("computer"); + }; + const socketCloseListener = () => { + this.conn.addEventListener('message', socketMessageListener); + this.conn.addEventListener('close', socketCloseListener); + }; + this.conn.onmessage = socketMessageListener; + this.conn.onclose = socketCloseListener; + }, + methods: { + translate: translate, + showGame: function(game) { + let hash = "#game?id=" + game.id; + if (!!game.uid) + hash += "&uid=" + game.uid; + location.hash = hash; }, - clickFriendGame: function(e) { - this.getRidOfTooltip(e.currentTarget); - document.getElementById("modal-fenedit").checked = true; + challenge: function(player) { + this.conn.send(JSON.stringify({code:"sendchallenge", oppid:p.id, + user:{name:user.name,id:user.id}})); }, - // In main hall : - newGame: function(mode, fenInit, color, oppId, gameId) { - const fen = fenInit || VariantRules.GenRandInitFen(); - console.log(fen); //DEBUG - if (mode=="human" && !oppId) - { - const storageVariant = localStorage.getItem("variant"); - if (!!storageVariant && storageVariant !== variant - && localStorage["score"] == "*") - { - return alert(translations["Finish your "] + - storageVariant + translations[" game first!"]); - } - // Send game request and wait.. - try { - this.conn.send(JSON.stringify({code:"newgame", fen:fen, gameid: getRandString() })); - } catch (INVALID_STATE_ERR) { - return; //nothing achieved - } - this.seek = true; - let modalBox = document.getElementById("modal-newgame"); - modalBox.checked = true; - setTimeout(() => { modalBox.checked = false; }, 2000); - return; - } - const prefix = this.getStoragePrefix(mode); - if (mode == "computer") + clickChallenge: function(challenge) { + const index = this.challenges.findIndex(c => c.id == challenge.id); + const toIdx = challenge.to.findIndex(p => p.id == user.id); + const me = {name:user.name,id:user.id}; + if (toIdx >= 0) { - const storageVariant = localStorage.getItem(prefix+"variant"); - if (!!storageVariant) - { - const score = localStorage.getItem(prefix+"score"); - if (storageVariant !== variant && score == "*") - { - if (!confirm(storageVariant + - translations[": unfinished computer game will be erased"])) - { - return; - } - } - } + // It's a multiplayer challenge I accepted: withdraw + this.conn.send(JSON.stringify({code:"withdrawchallenge", + cid:challenge.id, user:me})); + this.challenges.to.splice(toIdx, 1); } - else if (mode == "friend") + else if (challenge.from.id == user.id) //it's my challenge: cancel it { - const storageVariant = localStorage.getItem(prefix+"variant"); - if (!!storageVariant) - { - const score = localStorage.getItem(prefix+"score"); - if (storageVariant !== variant && score == "*") - { - if (!confirm(storageVariant + - translations[": current analysis will be erased"])) - { - return; - } - } - } + this.conn.send(JSON.stringify({code:"cancelchallenge", cid:challenge.id})); + this.challenges.splice(index, 1); } - this.vr = new VariantRules(fen, []); - this.score = "*"; - this.pgnTxt = ""; //redundant with this.score = "*", but cleaner - this.mode = mode; - this.incheck = []; - this.fenStart = V.ParseFen(fen).position; //this is enough - if (mode=="human") + else //accept a challenge { - // Opponent found! - this.gameId = gameId; - this.oppid = oppId; - this.oppConnected = true; - this.mycolor = color; - this.seek = false; - if (this.sound >= 1) - new Audio("/sounds/newgame.mp3").play().catch(err => {}); - document.getElementById("modal-newgame").checked = false; + this.conn.send(JSON.stringify({code:"acceptchallenge", + cid:challenge.id, user:me})); + this.challenges[index].to.push(me); } - else if (mode == "computer") - { - this.compWorker.postMessage(["init",this.vr.getFen()]); - this.mycolor = (Math.random() < 0.5 ? 'w' : 'b'); - if (this.mycolor != this.vr.turn) - this.playComputerMove(); - } - else if (mode == "friend") - this.mycolor = "w"; //convention... - //else: problem solving: nothing more to do - if (mode != "problem") - this.setStorage(); //store game state in case of interruptions }, - continueGame: function(mode) { - this.mode = mode; - this.oppid = (mode=="human" ? localStorage.getItem("oppid") : undefined); - const prefix = this.getStoragePrefix(mode); - this.mycolor = localStorage.getItem(prefix+"mycolor"); - const moves = JSON.parse(localStorage.getItem(prefix+"moves")); - const fen = localStorage.getItem(prefix+"fen"); - const score = localStorage.getItem(prefix+"score"); //set in "endGame()" - this.fenStart = localStorage.getItem(prefix+"fenStart"); - this.vr = new VariantRules(fen, moves); - this.incheck = this.vr.getCheckSquares(this.vr.turn); - if (mode == "human") - { - this.gameId = localStorage.getItem("gameId"); - // Send ping to server (answer pong if opponent is connected) - this.conn.send(JSON.stringify({ - code:"ping",oppid:this.oppid,gameId:this.gameId})); - } - else if (mode == "computer") - { - this.compWorker.postMessage(["init",fen]); - if (score == "*" && this.mycolor != this.vr.turn) - this.playComputerMove(); - } - //else: nothing special to do in friend mode - if (score != "*") - { - // Small delay required when continuation run faster than drawing page - setTimeout(() => this.endGame(score), 100); - } + // user: last person to accept the challenge + newGame: function(chall, user) { + const fen = chall.fen || V.GenRandInitFen(); + const game = {}; //TODO: fen, players, time ... + //setStorage(game); //TODO + game.players.forEach(p => { + this.conn.send( + JSON.stringify({code:"newgame", oppid:p.id, game:game})); + }); + if (this.settings.sound >= 1) + new Audio("/sounds/newgame.mp3").play().catch(err => {}); }, - - - // TODO: option du bouton "new game" - const modalFenEdit = [ - h('input', - { - attrs: { "id": "modal-fenedit", type: "checkbox" }, - "class": { "modal": true }, - }), - h('div', - { - attrs: { "role": "dialog", "aria-labelledby": "titleFenedit" }, - }, - [ - h('div', - { - "class": { "card": true, "smallpad": true }, - }, - [ - h('label', - { - attrs: { "id": "close-fenedit", "for": "modal-fenedit" }, - "class": { "modal-close": true }, - } - ), - h('h3', - { - attrs: { "id": "titleFenedit" }, - "class": { "section": true }, - domProps: { innerHTML: translations["Game state (FEN):"] }, - } - ), - h('input', - { - attrs: { - "id": "input-fen", - type: "text", - value: VariantRules.GenRandInitFen(), - }, - } - ), - h('button', - { - on: { click: - () => { - const fen = document.getElementById("input-fen").value; - document.getElementById("modal-fenedit").checked = false; - this.newGame("friend", fen); - } - }, - domProps: { innerHTML: translations["Ok"] }, - } - ), - h('button', - { - on: { click: - () => { - document.getElementById("input-fen").value = - VariantRules.GenRandInitFen(); - } - }, - domProps: { innerHTML: translations["Random"] }, - } - ), - ] - ) - ] - ) - ]; - elementArray = elementArray.concat(modalFenEdit); + }, +});