+ data: { gid: this.gameRef },
+ success: (res) => {
+ res.game.moves.forEach(m => {
+ m.squares = JSON.parse(m.squares);
+ });
+ callback(res.game);
+ }
+ }
+ );
+ } else
+ // Local game (or live remote)
+ GameStorage.get(this.gameRef, callback);
+ },
+ 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).split(':'));
+ return;
+ }
+ const currentTurn = this.vr.turn;
+ const currentMovesCount = this.game.moves.length;
+ 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).split(':');
+ });
+ this.clockUpdate = setInterval(
+ () => {
+ if (
+ countdown < 0 ||
+ this.game.moves.length > currentMovesCount ||
+ this.game.score != "*"
+ ) {
+ clearInterval(this.clockUpdate);
+ if (countdown < 0)
+ this.gameOver(
+ currentTurn == "w" ? "0-1" : "1-0",
+ "Time"
+ );
+ } else
+ this.$set(
+ this.virtualClocks,
+ colorIdx,
+ ppt(Math.max(0, --countdown)).split(':')
+ );
+ },
+ 1000
+ );
+ },
+ // Update variables and storage after a move:
+ processMove: function(move, data) {
+ if (!data) data = {};
+ const moveCol = this.vr.turn;
+ const colorIdx = ["w", "b"].indexOf(moveCol);
+ const nextIdx = 1 - colorIdx;
+ const doProcessMove = () => {
+ const origMovescount = this.game.moves.length;
+ let addTime = 0; //for live games
+ if (moveCol == this.game.mycolor && !data.receiveMyMove) {
+ if (this.drawOffer == "received")
+ // I refuse draw
+ this.drawOffer = "";
+ if (this.game.type == "live" && origMovescount >= 2) {
+ const elapsed = Date.now() - this.game.initime[colorIdx];
+ // elapsed time is measured in milliseconds
+ addTime = this.game.increment - elapsed / 1000;
+ }
+ }
+ // Update current game object:
+ playMove(move, this.vr);
+ // The move is played: stop clock
+ clearInterval(this.clockUpdate);
+ if (!data.score)
+ // Received move, score is computed in BaseGame, but maybe not yet.
+ // ==> Compute it here, although this is redundant (TODO)
+ data.score = this.vr.getCurrentScore();
+ if (data.score != "*") this.gameOver(data.score);
+ this.game.moves.push(move);
+ this.game.fen = this.vr.getFen();
+ if (this.game.type == "live") {
+ if (!!data.clock) this.game.clocks[colorIdx] = data.clock;
+ else this.game.clocks[colorIdx] += addTime;
+ } else {
+ // In corr games, just reset clock to mainTime:
+ this.game.clocks[colorIdx] = extractTime(this.game.cadence).mainTime;
+ }
+ // NOTE: opponent's initime is reset after "gotmove" is received
+ if (
+ !this.game.mycolor ||
+ moveCol != this.game.mycolor ||
+ !!data.receiveMyMove
+ ) {
+ this.game.initime[nextIdx] = Date.now();
+ }
+ // If repetition detected, consider that a draw offer was received:
+ const fenObj = this.vr.getFenForRepeat();
+ this.repeat[fenObj] =
+ !!this.repeat[fenObj]
+ ? this.repeat[fenObj] + 1
+ : 1;
+ if (this.repeat[fenObj] >= 3) this.drawOffer = "threerep";
+ else if (this.drawOffer == "threerep") this.drawOffer = "";
+ if (!!this.game.mycolor && !data.receiveMyMove) {
+ // NOTE: 'var' to see that variable outside this block
+ var filtered_move = getFilteredMove(move);
+ }
+ if (moveCol == this.game.mycolor && !data.receiveMyMove) {
+ // Notify turn on MyGames page:
+ this.notifyMyGames(
+ "turn",