From dfb4afc10d56715b80f753b1273738bd11a309dd Mon Sep 17 00:00:00 2001 From: Benjamin Auder <benjamin.auder@somewhere> Date: Fri, 16 Nov 2018 17:33:27 +0100 Subject: [PATCH] Store moves, show PGN at end of game --- public/javascripts/base_rules.js | 35 ++++++++-- public/javascripts/components/game.js | 94 ++++++++++++++++++--------- 2 files changed, 93 insertions(+), 36 deletions(-) diff --git a/public/javascripts/base_rules.js b/public/javascripts/base_rules.js index 576bdd9b..0a5c0e72 100644 --- a/public/javascripts/base_rules.js +++ b/public/javascripts/base_rules.js @@ -47,9 +47,9 @@ class ChessRules // INITIALIZATION // fen = "position flags epSquare movesCount" - constructor(fen) + constructor(fen, moves) { - this.moves = []; + this.moves = moves; // Use fen string to initialize variables, flags and board this.initVariables(fen); this.flags = VariantRules.GetFlags(fen); @@ -665,12 +665,15 @@ class ChessRules move.flags = JSON.stringify(this.flags); //TODO: less costly this.updateVariables(move); + if (!!ingame) + { + move.notation = this.getNotation(move); + this.moves.push(move); + } + this.epSquares.push( this.getEpSquare(move) ); VariantRules.PlayOnBoard(this.board, move); this.movesCount++; - - if (!!ingame) - this.moves.push(move); } undo(move) @@ -1007,4 +1010,26 @@ class ChessRules return piece.toUpperCase() + (move.vanish.length > 1 ? "x" : "") + finalSquare; } } + + // The score is already computed when calling this function + getPGN(mycolor, score) + { + let pgn = ""; + pgn += '[Site "vchess.club"]<br>'; + const d = new Date(); + pgn += '[Date "' + d.getFullYear() + '-' + d.getMonth() + '-' + d.getDate() + '"]<br>'; + pgn += '[White "' + (mycolor=='w'?'Myself':'Anonymous') + '"]<br>'; + pgn += '[Black "' + (mycolor=='b'?'Myself':'Anonymous') + '"]<br>'; + pgn += '[Result "' + score + '"]<br>'; + + for (let i=0; i<this.moves.length; i++) + { + if (i % 2 == 0) + pgn += ((i/2)+1) + "."; + pgn += this.moves[i].notation + " "; + } + + pgn += score; + return pgn; + } } diff --git a/public/javascripts/components/game.js b/public/javascripts/components/game.js index f5db3378..592a7001 100644 --- a/public/javascripts/components/game.js +++ b/public/javascripts/components/game.js @@ -1,4 +1,4 @@ -// TODO: use indexedDB instead of localStorage: more flexible. +// TODO: use indexedDB instead of localStorage? (more flexible...) Vue.component('my-game', { data: function() { @@ -10,7 +10,7 @@ Vue.component('my-game', { start: {}, //pixels coordinates + id of starting square (click or drag) selectedPiece: null, //moving piece (or clicked piece) conn: null, //socket messages - endofgame: "", //end of game message + score: "*", //'*' means 'unfinished' mode: "idle", //human, computer or idle (when not playing) oppid: "", //opponent ID in case of HH game oppConnected: false, @@ -208,6 +208,51 @@ Vue.component('my-game', { // ); // elementArray.push(reserve); // } + let eogMessage = "Unfinished"; + switch (this.score) + { + case "1-0": + eogMessage = "White win"; + break; + case "0-1": + eogMessage = "Black win"; + break; + case "1/2": + eogMessage = "Draw"; + break; + } + let elemsOfEog = + [ + h('label', + { + attrs: { "for": "modal-control" }, + "class": { "modal-close": true }, + } + ), + h('h3', + { + "class": { "section": true }, + domProps: { innerHTML: "End of game" }, + } + ), + h('p', + { + "class": { "section": true }, + domProps: { innerHTML: eogMessage }, + } + ) + ]; + if (this.score != "*") + { + elemsOfEog.push( + h('p', //'textarea', //TODO: selectable! + { + domProps: { innerHTML: this.vr.getPGN(this.mycolor, this.score) }, + //attrs: { "readonly": true }, + } + ) + ); + } const modalEog = [ h('input', { @@ -223,26 +268,7 @@ Vue.component('my-game', { { "class": { "card": true, "smallpad": true }, }, - [ - h('label', - { - attrs: { "for": "modal-control" }, - "class": { "modal-close": true }, - } - ), - h('h3', - { - "class": { "section": true }, - domProps: { innerHTML: "End of game" }, - } - ), - h('p', - { - "class": { "section": true }, - domProps: { innerHTML: this.endofgame }, - } - ) - ] + elemsOfEog ) ] ) @@ -332,8 +358,11 @@ Vue.component('my-game', { if (continuation) { // TODO: check FEN integrity with opponent - this.newGame("human", localStorage.getItem("fen"), - localStorage.getItem("mycolor"), localStorage.getItem("oppid"), true); + const fen = localStorage.getItem("fen"); + const mycolor = localStorage.getItem("mycolor"); + const oppid = localStorage.getItem("oppid"); + const moves = JSON.parse(localStorage.getItem("moves")); + this.newGame("human", fen, mycolor, oppid, moves, true); // Send ping to server, which answers pong if opponent is connected this.conn.send(JSON.stringify({code:"ping", oppid:this.oppId})); } @@ -358,7 +387,7 @@ Vue.component('my-game', { this.oppConnected = true; break; case "resign": //..you won! - this.endGame("Victory!"); + this.endGame(this.mycolor=="w"?"1-0":"0-1"); break; // TODO: also use (dis)connect info to count online players case "connect": @@ -380,11 +409,11 @@ Vue.component('my-game', { this.conn.onclose = socketCloseListener; }, methods: { - endGame: function(message) { - this.endofgame = message; + endGame: function(score) { + this.score = score; let modalBox = document.getElementById("modal-control"); modalBox.checked = true; - setTimeout(() => { modalBox.checked = false; }, 2000); + //setTimeout(() => { modalBox.checked = false; }, 2000); //disabled, to show PGN if (this.mode == "human") this.clearStorage(); this.mode = "idle"; @@ -399,7 +428,7 @@ Vue.component('my-game', { return; //resign failed for some reason... } } - this.endGame("Try again!"); + this.endGame(this.mycolor=="w"?"0-1":"1-0"); }, updateStorage: function() { if (!localStorage.getItem("myid")) @@ -410,6 +439,7 @@ Vue.component('my-game', { localStorage.setItem("oppid", this.oppid); } localStorage.setItem("fen", this.vr.getFen()); + localStorage.setItem("moves", JSON.stringify(this.vr.moves)); }, clearStorage: function() { delete localStorage["variant"]; @@ -417,10 +447,12 @@ Vue.component('my-game', { delete localStorage["mycolor"]; delete localStorage["oppid"]; delete localStorage["fen"]; + delete localStorage["moves"]; }, - newGame: function(mode, fenInit, color, oppId, continuation) { + newGame: function(mode, fenInit, color, oppId, moves, continuation) { const fen = fenInit || VariantRules.GenRandInitFen(); console.log(fen); //DEBUG + this.score = "*"; if (mode=="human" && !oppId) { // Send game request and wait.. @@ -435,7 +467,7 @@ Vue.component('my-game', { setTimeout(() => { modalBox.checked = false; }, 2000); return; } - this.vr = new VariantRules(fen); + this.vr = new VariantRules(fen, moves || []); this.mode = mode; if (mode=="human") { -- 2.44.0