From dfeb96ea90e880a2557cbb5953dbb7258c912283 Mon Sep 17 00:00:00 2001 From: Benjamin Auder <benjamin.auder@somewhere> Date: Wed, 5 Feb 2020 12:15:05 +0100 Subject: [PATCH] TODO: finish draw offer logic + fix inCheck bug (no highlight) --- client/src/components/Board.vue | 10 +++++----- client/src/components/Settings.vue | 7 +++++-- client/src/store.js | 14 ++++++++------ client/src/translations/en.js | 1 + client/src/utils/gameStorage.js | 3 ++- client/src/views/Game.vue | 22 +++++++++++++++++++--- server/db/create.sql | 2 +- server/models/Game.js | 8 +++++--- server/routes/games.js | 25 +++++++++++++++++-------- 9 files changed, 63 insertions(+), 29 deletions(-) diff --git a/client/src/components/Board.vue b/client/src/components/Board.vue index 1b7fd6bc..6a20d54b 100644 --- a/client/src/components/Board.vue +++ b/client/src/components/Board.vue @@ -1,6 +1,7 @@ <script> import { getSquareId, getSquareFromId } from "@/utils/squareId"; import { ArrayFun } from "@/utils/array"; +import { store } from "@/store"; export default { name: 'my-board', @@ -10,13 +11,12 @@ export default { props: ["vr","lastMove","analyze","orientation","userColor","vname"], data: function () { return { - hints: (!localStorage["hints"] ? true : localStorage["hints"] === "1"), - bcolor: localStorage["bcolor"] || "lichess", //lichess, chesscom or chesstempo possibleMoves: [], //filled after each valid click/dragstart choices: [], //promotion pieces, or checkered captures... (as moves) selectedPiece: null, //moving piece (or clicked piece) incheck: [], start: {}, //pixels coordinates + id of starting square (click or drag) + settings: store.state.settings, }; }, render(h) { @@ -83,7 +83,7 @@ export default { ); // Create board element (+ reserves if needed by variant or mode) const lm = this.lastMove; - const showLight = this.hints && this.vname != "Dark"; + const showLight = this.settings.highlight && this.vname != "Dark"; const gameDiv = h( 'div', { @@ -126,7 +126,7 @@ export default { ) ); } - if (this.hints && hintSquares[ci][cj]) + if (this.settings.hints && hintSquares[ci][cj]) { elems.push( h( @@ -150,7 +150,7 @@ export default { ['board'+sizeY]: true, 'light-square': (i+j)%2==0, 'dark-square': (i+j)%2==1, - [this.bcolor]: true, + [this.settings.bcolor]: true, 'in-shadow': this.vname=="Dark" && !this.analyze && (!this.userColor || !this.vr.enlightened[this.userColor][ci][cj]), diff --git a/client/src/components/Settings.vue b/client/src/components/Settings.vue index 003dc15f..b9a2b637 100644 --- a/client/src/components/Settings.vue +++ b/client/src/components/Settings.vue @@ -39,9 +39,12 @@ export default { updateSettings: function(event) { const propName = event.target.id.substr(3).replace(/^\w/, c => c.toLowerCase()) - localStorage[propName] = ["bcolor","sound"].includes(propName) + let value = (["bcolor","sound"].includes(propName) ? event.target.value - : event.target.checked; + : event.target.checked); + if (propName == "sound") + value = parseInt(value); + store.updateSetting(propName, value); }, }, }; diff --git a/client/src/store.js b/client/src/store.js index 0234807f..798251f9 100644 --- a/client/src/store.js +++ b/client/src/store.js @@ -42,12 +42,10 @@ export const store = "&page=" + encodeURIComponent(page)); // Settings initialized with values from localStorage this.state.settings = { - bcolor: localStorage["bcolor"] || "lichess", - sound: parseInt(localStorage["sound"]) || 2, - hints: parseInt(localStorage["hints"]) || 1, - coords: !!eval(localStorage["coords"]), - highlight: !!eval(localStorage["highlight"]), - sqSize: parseInt(localStorage["sqSize"]), + bcolor: localStorage.getItem("bcolor") || "lichess", + sound: parseInt(localStorage.getItem("sound")) || 1, + hints: localStorage.getItem("hints") == "true", + highlight: localStorage.getItem("highlight") == "true", }; this.socketCloseListener = () => { // Next line may fail at first, but should retry and eventually success (TODO?) @@ -62,6 +60,10 @@ export const store = : "en"); this.setTranslations(); }, + updateSetting: function(propName, value) { + this.state.settings[propName] = value; + localStorage.setItem(propName, value); + }, setTranslations: async function() { // Import translations from "./translations/$lang.js" const tModule = await import("@/translations/" + this.state.lang + ".js"); diff --git a/client/src/translations/en.js b/client/src/translations/en.js index 0a7f93db..9b4e1372 100644 --- a/client/src/translations/en.js +++ b/client/src/translations/en.js @@ -24,6 +24,7 @@ export const translations = "Database error:": "Database error:", "Download PGN": "Download PGN", "Draw": "Draw", + "Draw offer only in your turn": "Draw offer only in your turn", "Email": "Email", "Email sent!": "Email sent!", "Empty message": "Empty message", diff --git a/client/src/utils/gameStorage.js b/client/src/utils/gameStorage.js index 7fadbedd..bf5dfba4 100644 --- a/client/src/utils/gameStorage.js +++ b/client/src/utils/gameStorage.js @@ -81,8 +81,9 @@ export const GameStorage = gid: gameId, newObj: { + // Some fields may be undefined: chat: obj.chat, - move: obj.move, //may be undefined... + move: obj.move, fen: obj.fen, score: obj.score, scoreMsg: obj.scoreMsg, diff --git a/client/src/views/Game.vue b/client/src/views/Game.vue index 6ea6cdd9..ec1962ee 100644 --- a/client/src/views/Game.vue +++ b/client/src/views/Game.vue @@ -320,6 +320,8 @@ export default { } else if (this.drawOffer == "") //no effect if drawOffer == "sent" { + if (this.game.mycolor != this.vr.turn) + return alert(this.st.tr["Draw offer only in your turn"]); if (!confirm(this.st.tr["Offer draw?"])) return; this.drawOffer = "sent"; @@ -327,7 +329,7 @@ export default { if (sid != this.st.user.sid) this.st.conn.send(JSON.stringify({code:"drawoffer", target:sid})); }); - GameStorage.update(this.gameRef.id, {drawOffer: true}); + GameStorage.update(this.gameRef.id, {drawOffer: this.game.mycolor}); } }, abortGame: function() { @@ -396,8 +398,6 @@ export default { } if (L >= 1) game.initime[L%2] = game.moves[L-1].played; - if (game.drawOffer) - this.drawOffer = "received"; } // Now that we used idx and played, re-format moves as for live games game.moves = game.moves.map( (m) => { @@ -432,6 +432,22 @@ export default { } } } + + + + // TODO: (and also when receiving / sending a move ?) +// if (!!game.drawOffer) +// { +// if (game.drawOffer == "w") +// { +// if (myIdx == 0) +// { +// this.drawOffer = "sent"; + + + + + this.game = Object.assign({}, game, // NOTE: assign mycolor here, since BaseGame could also be VS computer diff --git a/server/db/create.sql b/server/db/create.sql index d18a3105..21c7728b 100644 --- a/server/db/create.sql +++ b/server/db/create.sql @@ -41,7 +41,7 @@ create table Games ( scoreMsg varchar, timeControl varchar, created datetime, --used only for DB cleaning - drawOffer boolean, + drawOffer character, foreign key (vid) references Variants(id) ); diff --git a/server/models/Game.js b/server/models/Game.js index da59b4a6..a3ddc3c4 100644 --- a/server/models/Game.js +++ b/server/models/Game.js @@ -11,7 +11,7 @@ const UserModel = require("./User"); * score: varchar (result) * scoreMsg: varchar ("Time", "Mutual agreement"...) * created: datetime - * drawOffer: boolean + * drawOffer: char ('w','b' or '' for none) * * Structure table Players: * gid: ref game id @@ -56,7 +56,7 @@ const GameModel = "INSERT INTO Games" + " (vid, fenStart, fen, score, timeControl, created, drawOffer)" + " VALUES (" + vid + ",'" + fen + "','" + fen + "','*','" - + timeControl + "'," + Date.now() + "," + false + ")"; + + timeControl + "'," + Date.now() + ",'')"; db.run(query, function(err) { if (!!err) return cb(err); @@ -200,7 +200,9 @@ const GameModel = let modifs = ""; if (!!obj.message) modifs += "message = message || ' ' || '" + obj.message + "',"; - if ([true,false].includes(obj.drawOffer)) + // NOTE: if drawOffer is true, we should check that it's player's turn + // A bit overcomplicated. Let's trust the client on that for now... + if (!!obj.drawOffer) modifs += "drawOffer = " + obj.drawOffer + ","; if (!!obj.fen) modifs += "fen = '" + obj.fen + "',"; diff --git a/server/routes/games.js b/server/routes/games.js index 24bfc82c..c6e25a6a 100644 --- a/server/routes/games.js +++ b/server/routes/games.js @@ -76,14 +76,23 @@ router.put("/games", access.logged, access.ajax, (req,res) => { GameModel.update(gid, obj, (err) => { if (!!err) return res.json(err); - // Notify opponent if he enabled notifications: - GameModel.getPlayers(gid, (err2,players) => { - if (!!err2) - return res.json(err); - const oppid = (players[0].id == req.userId ? players[1].id : players[0].id); - UserModel.tryNotify(oppid, - "New move in game: " + params.siteURL + "/game/" + gid); - }); + if (!!obj.move || !!obj.score) + { + // Notify opponent if he enabled notifications: + GameModel.getPlayers(gid, (err2,players) => { + if (!err2) + { + const oppid = (players[0].id == req.userId + ? players[1].id + : players[0].id); + const messagePrefix = (!!obj.move + ? "New move in game: " + : "Game ended: "); + UserModel.tryNotify(oppid, + messagePrefix + params.siteURL + "/game/" + gid); + } + }); + } res.json({}); }); }); -- 2.44.0