socketCloseListener: null,
initialize() {
ajax("/variants", "GET", res => { this.state.variants = res.variantArray; });
- let mysid = localStorage["mysid"];
+ let mysid = localStorage.getItem("mysid");
if (!mysid)
{
mysid = getRandString();
- localStorage["mysid"] = mysid; //done only once (unless user clear browser data)
+ localStorage.setItem("mysid", mysid); //done only once (unless user clear browser data)
}
// Quick user setup using local storage:
this.state.user = {
- id: localStorage["myid"] || 0,
- name: localStorage["myname"] || "", //"" for "anonymous"
+ id: localStorage.getItem("myid") || 0,
+ name: localStorage.getItem("myname") || "", //"" for "anonymous"
email: "", //unknown yet
notify: false, //email notifications
sid: mysid,
// NOTE: still superficial identity usurpation possible, but difficult.
ajax("/whoami", "GET", res => {
this.state.user.id = res.id;
+ const storedId = localStorage.getItem("myid");
+ if (res.id > 0 && !storedId) //user cleared localStorage
+ localStorage.setItem("myid", res.id);
+ else if (res.id == 0 && !!storedId) //user cleared cookie
+ localStorage.removeItem("myid");
this.state.user.name = res.name;
+ const storedName = localStorage.getItem("myname");
+ if (!!res.name && !storedName) //user cleared localStorage
+ localStorage.setItem("myname", res.name);
+ else if (!res.name && !!storedName) //user cleared cookie
+ localStorage.removeItem("myname");
this.state.user.email = res.email;
this.state.user.notify = res.notify;
});
this.gameRef.rid = to.query["rid"];
this.loadGame();
},
- "game.clocks": function(newState) {
- if (this.game.moves.length < 2 || this.game.score != "*")
- {
- // 1st move not completed yet, or game over: freeze time
- this.virtualClocks = newState.map(s => ppt(s));
- return;
- }
- const currentTurn = this.vr.turn;
- const colorIdx = ["w","b"].indexOf(currentTurn);
- let countdown = newState[colorIdx] -
- (Date.now() - this.game.initime[colorIdx])/1000;
- this.virtualClocks = [0,1].map(i => {
- const removeTime = i == colorIdx
- ? (Date.now() - this.game.initime[colorIdx])/1000
- : 0;
- return ppt(newState[i] - removeTime);
- });
- let clockUpdate = setInterval(() => {
- if (countdown < 0 || this.vr.turn != currentTurn || this.game.score != "*")
- {
- clearInterval(clockUpdate);
- if (countdown < 0)
- this.gameOver(this.vr.turn=="w" ? "0-1" : "1-0", this.st.tr["Time"]);
- }
- else
- this.$set(this.virtualClocks, colorIdx, ppt(Math.max(0, --countdown)));
- }, 1000);
- },
},
// NOTE: some redundant code with Hall.vue (mostly related to people array)
created: function() {
this.vr = new V(game.fen);
const gtype = (game.cadence.indexOf('d') >= 0 ? "corr" : "live");
const tc = extractTime(game.cadence);
+ const myIdx = game.players.findIndex(p => {
+ return p.sid == this.st.user.sid || p.uid == this.st.user.id;
+ });
+ const mycolor = [undefined,"w","b"][myIdx+1]; //undefined for observers
if (!game.chats)
game.chats = []; //live games don't have chat history
if (gtype == "corr")
if (L >= 1)
game.initime[L%2] = game.moves[L-1].played;
}
- // Now that we used idx and played, re-format moves as for live games
- game.moves = game.moves.map( (m) => {
+ const reformattedMoves = game.moves.map( (m) => {
const s = m.squares;
return {
appear: s.appear,
end: s.end,
};
});
- // Also sort chat messages (if any)
+ // Sort chat messages from newest to oldest
game.chats.sort( (c1,c2) => { return c2.added - c1.added; });
+ if (myIdx >= 0 && game.chats.length > 0)
+ {
+ // TODO: group multi-moves into an array, to deduce color from index
+ // and not need this (also repeated in BaseGame::re_setVariables())
+ let vr_tmp = new V(game.fenStart); //vr is already at end of game
+ for (let i=0; i<reformattedMoves.length; i++)
+ {
+ game.moves[i].color = vr_tmp.turn;
+ vr_tmp.play(reformattedMoves[i]);
+ }
+ // Blue background on chat button if last chat message arrived after my last move.
+ let dtLastMove = 0;
+ for (let midx = game.moves.length-1; midx >= 0; midx--)
+ {
+ if (game.moves[midx].color == mycolor)
+ {
+ dtLastMove = game.moves[midx].played;
+ break;
+ }
+ }
+ if (dtLastMove < game.chats[0].added)
+ document.getElementById("chatBtn").classList.add("somethingnew");
+ }
+ // Now that we used idx and played, re-format moves as for live games
+ game.moves = reformattedMoves;
}
- const myIdx = game.players.findIndex(p => {
- return p.sid == this.st.user.sid || p.uid == this.st.user.id;
- });
if (gtype == "live" && game.clocks[0] < 0) //game unstarted
{
game.clocks = [tc.mainTime, tc.mainTime];
{
type: gtype,
increment: tc.increment,
- mycolor: [undefined,"w","b"][myIdx+1],
+ mycolor: mycolor,
// opponent sid not strictly required (or available), but easier
// at least oppsid or oppid is available anyway:
oppsid: (myIdx < 0 ? undefined : game.players[1-myIdx].sid),
oppid: (myIdx < 0 ? undefined : game.players[1-myIdx].uid),
}
);
+ this.re_setClocks();
this.$nextTick(() => {
this.game.rendered = true;
// Did lastate arrive before game was rendered?
GameStorage.get(this.gameRef.id, afterRetrieval);
}
},
+ re_setClocks: function() {
+ if (this.game.moves.length < 2 || this.game.score != "*")
+ {
+ // 1st move not completed yet, or game over: freeze time
+ this.virtualClocks = this.game.clocks.map(s => ppt(s));
+ return;
+ }
+ const currentTurn = this.vr.turn;
+ const colorIdx = ["w","b"].indexOf(currentTurn);
+ let countdown = this.game.clocks[colorIdx] -
+ (Date.now() - this.game.initime[colorIdx])/1000;
+ this.virtualClocks = [0,1].map(i => {
+ const removeTime = i == colorIdx
+ ? (Date.now() - this.game.initime[colorIdx])/1000
+ : 0;
+ return ppt(this.game.clocks[i] - removeTime);
+ });
+ let clockUpdate = setInterval(() => {
+ if (countdown < 0 || this.vr.turn != currentTurn || this.game.score != "*")
+ {
+ clearInterval(clockUpdate);
+ if (countdown < 0)
+ this.gameOver(this.vr.turn=="w" ? "0-1" : "1-0", this.st.tr["Time"]);
+ }
+ else
+ this.$set(this.virtualClocks, colorIdx, ppt(Math.max(0, --countdown)));
+ }, 1000);
+ },
// Post-process a move (which was just played in BaseGame)
processMove: function(move) {
if (this.game.type == "corr" && move.color == this.game.mycolor)
{
-
-//TODO: if takeback, then time over occurs.
-
if (!confirm(this.st.tr["Move played:"] + " " + move.notation + "\n" + this.st.tr["Are you sure?"]))
+ {
return this.$set(this.game, "moveToUndo", move);
+ }
}
- // Update storage (corr or live) if I play in the game
const colorIdx = ["w","b"].indexOf(move.color);
const nextIdx = ["w","b"].indexOf(this.vr.turn);
// https://stackoverflow.com/a/38750895
// Update current game object:
this.game.moves.push(move);
this.game.fen = move.fen;
- this.$set(this.game.clocks, colorIdx, this.game.clocks[colorIdx] + addTime);
+ this.game.clocks[colorIdx] += addTime;
// move.initime is set only when I receive a "lastate" move from opponent
this.game.initime[nextIdx] = move.initime || Date.now();
+ this.re_setClocks();
// If repetition detected, consider that a draw offer was received:
const fenObj = V.ParseFen(move.fen);
let repIdx = fenObj.position + "_" + fenObj.turn;