console.log("DEV_ENABLE_SERVING_FILES: Serving files in the current directory. Please never do this on a production server, this is for development purposes only.");
}
-var debuglog = DEBUG_LOG ? console.log.bind(console) : () => null;
+const debuglog = DEBUG_LOG ? console.log.bind(console) : () => null;
-var http = require("http");
-var fs = require("fs");
+const http = require("http");
+const fs = require("fs");
-var frBag = [
+const frBag = [
" ", " ", // Jokers
"E", "E", "E", "E", "E", "E", "E", "E", "E", "E", "E", "E", "E", "E", "E",
"A", "A", "A", "A", "A", "A", "A", "A", "A",
"Z"
];
-var frValues = {
+const frValues = {
" ": 0,
"E": 1,
"A": 1,
};
-var games = {};
-var dateNow = 0;
+const games = {};
+let dateNow = 0;
-var saveTimeout = null;
-var running = true;
+let saveTimeout = null;
+let running = true;
function saveGames(exit) {
fs.writeFile("games.backup.json", JSON.stringify(games), function (err) {
}
function newBoard() {
- var res = new Array(15 * 15);
+ const res = new Array(15 * 15);
- for (var i = 0; i < 15 * 15; i++) {
+ for (let i = 0; i < 15 * 15; i++) {
res[i] = "";
}
};
Game.fromJSON = function (obj) {
- var game = new Game();
+ const game = new Game();
game.board = obj.board || newBoard();
game.bag = obj.bag || frBag.slice();
game.remainingLetters = obj.remainingLetters || game.bag.length;
};
Game.prototype.getPlayerRack = function (player) {
- var playerID = "#" + player;
+ const playerID = "#" + player;
return (this.racks[playerID] || (this.racks[playerID] = []));
};
Game.prototype.getPlayerScore = function (player) {
- var playerID = "#" + player;
+ const playerID = "#" + player;
return (this.scores[playerID] || (this.scores[playerID] = 0));
};
Game.prototype.setPlayerScore = function (player, score) {
- var playerID = "#" + player;
+ const playerID = "#" + player;
if (!Object.prototype.hasOwnProperty.call(this.racks, playerID) || typeof score !== "number") {
return;
this.getPlayerRack(playerName); // Create the player's rack
}
- var players = [];
+ const players = [];
- for (var player in this.racks) {
+ for (let player in this.racks) {
if (Object.prototype.hasOwnProperty.call(this.racks, player)) {
player = player.slice(1); // '#'
players.push({
};
Game.prototype.addListeningPlayer = function (playerName, responseAndIsES) {
- var that = this;
+ const that = this;
that.listeningPlayers.push(responseAndIsES);
keepAlive(responseAndIsES);
- var closed = false;
+ let closed = false;
function close () {
if (closed) {
closed = true;
stopKeepAlive(responseAndIsES);
- var index = that.listeningPlayers.indexOf(responseAndIsES);
+ const index = that.listeningPlayers.indexOf(responseAndIsES);
if (index !== -1) {
that.listeningPlayers[index] = that.listeningPlayers[that.listeningPlayers.length - 1];
that.listeningPlayers.pop();
};
Game.prototype.commit = function () {
- var pendingEvents = this.pendingEvents;
+ const pendingEvents = this.pendingEvents;
this.pendingEvents = [];
- var msg = JSON.stringify(pendingEvents);
+ const msg = JSON.stringify(pendingEvents);
- for (var i = 0; i < this.listeningPlayers.length; i++) {
+ for (let i = 0; i < this.listeningPlayers.length; i++) {
while (i < this.listeningPlayers.length && !this.listeningPlayers[i]) {
this.listeningPlayers[i] = this.listeningPlayers[this.listeningPlayers.length - 1];
this.listeningPlayers.pop();
Game.prototype.bagPopLetter = function (player) {
if (this.remainingLetters) {
- var letter = "";
- var index;
+ let letter = "";
+ let index;
while (letter === "") {
index = Math.floor(Math.random() * this.bag.length);
Game.prototype.bagPushLetter = function (letter, player) {
if (letter) {
- var index = 0;
+ let index = 0;
while (this.bag[index] !== "") {
index++;
};
function newGameId() {
- var number;
+ let number;
- var k = 10000;
- var retries = 0;
+ let k = 10000;
+ let retries = 0;
do {
number = Math.floor(Math.random() * k).toString();
}
function countTiles(rack) {
- var count = 0;
+ let count = 0;
- for (var i = 0; i < rack.length; i++) {
+ for (let i = 0; i < rack.length; i++) {
if (rack[i]) {
count++;
}
}
function handleCommand(cmd, gameNumber, playerName, response) {
- var game;
+ let game;
({gameNumber, game} = joinGame(gameNumber, playerName));
game.lastUpdated = new Date();
- var rack = null;
+ let rack = null;
switch (cmd.cmd) {
- case "joinGame":
+ case "joinGame": {
response.write(
JSON.stringify({
"error": 0,
})
);
break;
+ }
- case "hello":
+ case "hello": {
game.playerJoined(playerName);
break;
+ }
- case "sync":
+ case "sync": {
response.write(
JSON.stringify({
"error":0,
})
);
break;
+ }
- case "score":
+ case "score": {
game.setPlayerScore(cmd.player, cmd.score);
response.write("{\"error\":0}");
break;
+ }
- case "moveLetter":
- var letter = "";
+ case "moveLetter": {
+ let letter = "";
switch (cmd.from) {
case "rack":
});
}
break;
+ }
- case "setRack":
+ case "setRack": {
cmd.rack.length = 8;
rack = game.getPlayerRack(playerName);
- var initialRackCount = countTiles(rack);
- var rackCount = countTiles(cmd.rack);
+ const initialRackCount = countTiles(rack);
+ const rackCount = countTiles(cmd.rack);
debuglog(rack, cmd.rack);
break;
}
- var oldRack = rack.slice();
-
+ const oldRack = rack.slice();
for (let i = 0; i < 8; i++) {
cmd.rack[i] = (cmd.rack[i] || "")[0] || "";
if (cmd.rack[i]) {
- var indexLetter = oldRack.indexOf(cmd.rack[i]);
+ const indexLetter = oldRack.indexOf(cmd.rack[i]);
if (indexLetter === -1) {
response.write(
);
break;
- case "resetGame":
+ }
+
+ case "resetGame": {
game.reset();
response.write("{\"error\":0}");
break;
+ }
- case "msg":
+ case "msg": {
game.pendingEvents.push({
msg: {
sender: playerName,
});
response.write("{\"error\":0}");
break;
+ }
- default:
+ default: {
response.write("{\"error\":1,\"reason\":\"Unknown command\"}");
break;
+ }
}
}
function handleCommands(cmds, responseAndIsES) {
if (!cmds.cmds || !cmds.cmds.length) {
- var {gameNumber, game} = joinGame(cmds.gameNumber, cmds.playerName);
+ const {gameNumber, game} = joinGame(cmds.gameNumber, cmds.playerName);
writeResponse(responseAndIsES,
JSON.stringify({
return;
}
- var response = responseAndIsES[0];
+ const response = responseAndIsES[0];
response.write("[");
- for (var i = 0; i < cmds.cmds.length; i++) {
+ for (let i = 0; i < cmds.cmds.length; i++) {
if (i) {
response.write(",");
}
}
function handleRequest(request, response) {
- var post = "";
- var responseAndIsES = [response, false];
+ let post = "";
+ const responseAndIsES = [response, false];
response.on("error", function connectionError(e) {
console.error("An error occurred while trying to write on a socket", e);
response.end(err);
}
- var mime = "application/xhtml+xml; charset=utf-8";
- var mimes = {
+ let mime = "application/xhtml+xml; charset=utf-8";
+ const mimes = {
".mp3": "audio/mpeg",
".ogg": "audio/ogg",
".js": "application/javascript; charset=utf-8",
".svg": "image/svg+xml"
};
- for (var i in mimes) {
+ for (const i in mimes) {
if (request.url.endsWith(i)) {
mime = mimes[i];
break;
return;
}
- var eventSourceMatch = request.url.match(/\/:[^/]+\/sse\/(?<data>[\s\S]+)$/u);
+ const eventSourceMatch = request.url.match(/\/:[^/]+\/sse\/(?<data>[\s\S]+)$/u);
if (eventSourceMatch) {
response.setHeader("Content-Type", "text/event-stream");
if (err) {
console.error("WARNING: Could not restore previous backup of the games");
} else {
- var backup = JSON.parse(data);
+ const backup = JSON.parse(data);
- for (var gameNumber in backup) {
+ for (const gameNumber in backup) {
if (Object.prototype.hasOwnProperty.call(backup, gameNumber)) {
games[gameNumber] = Game.fromJSON(backup[gameNumber]);
}
(function () {
"use strict";
- var VERSION = 202004041733;
- var POLLING_DELAY = 2000;
+ const VERSION = 202004041733;
+ const POLLING_DELAY = 2000;
- var _ = (window.libD && libD.l10n) ? libD.l10n() : function (s) {return s;};
+ const _ = (window.libD && libD.l10n) ? libD.l10n() : function (s) {return s;};
- var trivabble = window.trivabble = {l10n: _};
+ const trivabble = window.trivabble = {l10n: _};
function format(s, v) {
return s.replace("{0}", v);
}
- var board, rack, boardCells = [], scoreOf, bag;
+ let board;
+ let rack;
+ const boardCells = [];
+ let scoreOf;
+ let bag;
- var playerLetters = [];
+ const playerLetters = [];
- var audioNotification, audioChat;
- var chatMessages, helpBag, helpClear;
+ let audioNotification;
+ let audioChat;
+ let chatMessages;
+ let helpBag;
+ let helpClear;
- var tablePlayers = {};
- var participantPlaceholder, participants, name;
+ let tablePlayers = {};
+ let participantPlaceholder;
+ let participants;
+ let name;
- var lastDate = 0;
+ let lastDate = 0;
- var blockMove = 0;
- var needsRestart = false;
- var gameInProgress = false;
+ let blockMove = 0;
+ let needsRestart = false;
+ const gameInProgress = false;
- var eventSource = null;
- var blockEventSourceAutoRetry = false;
- var connectionLostMessage = null;
- var boundEventShowConnectionLost = false;
+ let eventSource = null;
+ let blockEventSourceAutoRetry = false;
+ let connectionLostMessage = null;
+ let boundEventShowConnectionLost = false;
function mouseDown(ele, fun, stop) {
- var meth = stop ? "removeEventListener" : "addEventListener";
+ const meth = stop ? "removeEventListener" : "addEventListener";
ele[meth]("mousedown", fun, false);
}
function mouseUp(ele, fun, stop) {
- var meth = stop ? "removeEventListener" : "addEventListener";
+ const meth = stop ? "removeEventListener" : "addEventListener";
ele[meth]("mouseup", fun, false);
}
function mouseMove(ele, fun, stop) {
- var meth = stop ? "removeEventListener" : "addEventListener";
+ const meth = stop ? "removeEventListener" : "addEventListener";
ele[meth]("mousemove", fun, false);
}
function setRack(rack) {
- for (var i = 0; i < 7; i++) {
+ for (let i = 0; i < 7; i++) {
setTileParent(playerLetters[i], rack[i] || "");
}
}
function getFreeRackSpaceIndex() {
- for (var i = 0; i < 7; i++) {
+ for (let i = 0; i < 7; i++) {
if (!playerLetters[i].getElementsByClassName("tile")[0]) {
return i;
}
unbindEventsShowConnectionLost();
if (!connectionLostMessage) {
- connectionLostMessage = chatMessage("", _("Whoops, there is a problem. We are trying to fix it as soon as possible. Please wait a few seconds. If it persists, please contact the person who is able to fix the problem."))
+ connectionLostMessage = chatMessage("", _("Whoops, there is a problem. We are trying to fix it as soon as possible. Please wait a few seconds. If it persists, please contact the person who is able to fix the problem."));
connectionLostMessage.classList.add("error");
}
}
}
}
- var tileInitCoords = null;
- var tileInitMouseCoords = null;
- var tileDest = null;
- var tileInitDest = null;
- var movingTile = null;
- var rackBCR = null;
- var boardBCR = null;
- var bagBCR = null;
- var moveCMD = null;
+ let tileInitCoords = null;
+ let tileInitMouseCoords = null;
+ let tileDest = null;
+ let tileInitDest = null;
+ let movingTile = null;
+ let rackBCR = null;
+ let boardBCR = null;
+ let bagBCR = null;
+ let moveCMD = null;
function getLetter(l) {
- var tile = l.getElementsByClassName("tile")[0];
+ const tile = l.getElementsByClassName("tile")[0];
if (!tile) {
return "";
}
tileDest.appendChild(movingTile);
if (isParentOf(board, tileDest)) {
- var tiles = [].slice.call(board.getElementsByClassName("tile-highlight"));
- var len = tiles.length;
-
- for (var i = 0; i < len; i++) {
- tiles[i].classList.remove("tile-highlight");
+ for (const tile of board.getElementsByClassName("tile-highlight")) {
+ tile.classList.remove("tile-highlight");
}
}
} else if (tileInitDest.getElementsByClassName("tile")[0]) {
- for (var i = 0; i < 7; i++) {
+ for (let i = 0; i < 7; i++) {
if (!playerLetters[i].getElementsByClassName("tile")[0]) {
playerLetters[i].appendChild(movingTile);
break;
if (tileDest) {
tileDest.classList.remove("tile-target");
- var moveRack = {
+ const moveRack = {
cmd: "setRack",
rack: [
getLetter(playerLetters[0]),
}
function dragTileMove(e) {
- var newLeft = (tileInitCoords.left + (e.clientX - tileInitMouseCoords.clientX));
- var newTop = (tileInitCoords.top + (e.clientY - tileInitMouseCoords.clientY));
+ let newLeft = (tileInitCoords.left + (e.clientX - tileInitMouseCoords.clientX));
+ let newTop = (tileInitCoords.top + (e.clientY - tileInitMouseCoords.clientY));
movingTile.style.left = (newLeft + window.scrollX) + "px";
movingTile.style.top = (newTop + window.scrollY) + "px";
- var newDest = null;
+ let newDest = null;
newTop += tileInitCoords.height / 2;
newLeft += tileInitCoords.width / 2;
(newTop > boardBCR.top && newTop < (boardBCR.top + boardBCR.height)) &&
(newLeft > boardBCR.left && newLeft < (boardBCR.left + boardBCR.width))
) {
- var rowIndex = Math.floor(
+ const rowIndex = Math.floor(
(
(newTop - boardBCR.top) / boardBCR.height
) * board.rows.length
);
if (rowIndex > 0 && rowIndex < board.rows.length - 1) {
- var row = board.rows[rowIndex];
+ const row = board.rows[rowIndex];
- var colIndex = Math.floor(
+ const colIndex = Math.floor(
(
(newLeft - boardBCR.left) / boardBCR.width
) * row.cells.length
(newTop > rackBCR.top && newTop < (rackBCR.top + rackBCR.height)) &&
(newLeft > rackBCR.left && newLeft < (rackBCR.left + rackBCR.width))
) {
- var index = Math.floor(
+ const index = Math.floor(
(
(newLeft - rackBCR.left) / rackBCR.width
) * playerLetters.length
newDest = playerLetters[index];
if (newDest && newDest.getElementsByClassName("tile")[0]) {
- var i = index + 1, tile;
+ let i = index + 1;
+let tile;
while (playerLetters[i]) {
tile = playerLetters[i].getElementsByClassName("tile")[0];
if (!tile) {
- var j = i;
+ let j = i;
while (j > index) {
playerLetters[j].appendChild(
playerLetters[j - 1].getElementsByClassName("tile")[0]
while (playerLetters[i]) {
tile = playerLetters[i].getElementsByClassName("tile")[0];
if (!tile) {
- var j = i;
+ let j = i;
while (j < index) {
playerLetters[j].appendChild(
playerLetters[j + 1].getElementsByClassName("tile")[0]
rackBCR = rack.getBoundingClientRect();
bagBCR = bag.getBoundingClientRect();
- var from, index;
+ let from;
+ let index;
- var p = movingTile.parentNode;
- var oldP = movingTile;
- var oldOldP = null;
+ let p = movingTile.parentNode;
+ let oldP = movingTile;
+ let oldOldP = null;
while (p) {
if (p === board) {
}
function makeLetter(letter, highlight) {
- var tile = document.createElement("span");
+ const tile = document.createElement("span");
tile.className = "tile";
tile.appendChild(document.createElement("span"));
tile.lastChild.className = "tile-letter";
}
function setTileParent(p, letter, highlight) {
- var tile = p.getElementsByClassName("tile")[0];
+ let tile = p.getElementsByClassName("tile")[0];
if (tile) {
if (letter) {
setLetter(tile, letter, highlight);
}
function setBoard(board) {
- for (var i = 0; i < 15 * 15; i++) {
+ for (let i = 0; i < 15 * 15; i++) {
setCell(i, board[i]);
}
}
);
}
- var pollingServer = false;
- var pollingReady = false;
- var retriedImmediately = false;
+ let pollingServer = false;
+ let pollingReady = false;
+ let retriedImmediately = false;
function forceReload(msg) {
needsRestart = true;
document.getElementById("panel").lastChild.textContent = _("To continue playing, click here");
}
);
- throw e;
}
function fatalError(e) {
}
function chatMessage(sender, content) {
- var msgDom = document.createElement("div");
+ const msgDom = document.createElement("div");
msgDom.className = "msg";
function handleReceivedData(data) {
if (data instanceof Array) {
- for (var i = 0; i < data.length; i++) {
- handleReceivedData(data[i]);
- }
+ data.forEach(handleReceivedData);
return;
}
participantPlaceholder = null;
}
- for (var i = 0; i < data.players.length; i++) {
- var player = data.players[i];
- var playerName = data.players[i].player;
+ for (let i = 0; i < data.players.length; i++) {
+ const player = data.players[i];
+ const playerName = data.players[i].player;
if (!tablePlayers[playerName]) {
- var before = null;
+ let before = null;
- for (var j = 1; j < participants.rows.length; j++) {
+ for (let j = 1; j < participants.rows.length; j++) {
if (playerName < participants.rows[j].cells[0].textContent) {
before = participants.rows[j];
break;
}
}
- var row = document.createElement("tr");
+ const row = document.createElement("tr");
participants.insertBefore(row, before);
row.appendChild(document.createElement("td"));
row.lastChild.textContent = playerName;
}
if (Object.prototype.hasOwnProperty.call(player, "score")) {
- var scoreCell = tablePlayers[playerName].childNodes[2];
+ const scoreCell = tablePlayers[playerName].childNodes[2];
scoreCell.textContent = player.score;
blink(scoreCell);
}
if (Object.prototype.hasOwnProperty.call(player, "rackCount")) {
- var countCell = tablePlayers[playerName].childNodes[1];
+ const countCell = tablePlayers[playerName].childNodes[1];
countCell.textContent = player.rackCount;
blink(countCell);
}
return;
}
- var thisRequestIsPolling = false;
- var currentIndex = 0;
- var expectedLength = 0;
+ let thisRequestIsPolling = false;
+ let currentIndex = 0;
+ let expectedLength = 0;
if (!data.cmds || !data.cmds.length) {
if (pollingServer) {
data.version = VERSION;
if (window.EventSource) {
- eventSource = new EventSource('/:trivabble/sse/' + JSON.stringify(data));
+ eventSource = new EventSource("/:trivabble/sse/" + JSON.stringify(data));
eventSource.onopen = connectionReady;
blockMove++;
}
- var xhr = new XMLHttpRequest();
+ const xhr = new XMLHttpRequest();
xhr.open("POST", "/:trivabble", true);
xhr.setRequestHeader("Content-Type", "text/plain");
connectionReady();
while (true) {
if (!expectedLength) {
- var i = currentIndex;
+ let i = currentIndex;
while (i < xhr.responseText.length) {
if ("0123456789".indexOf(xhr.responseText.charAt(i)) === -1) {
expectedLength = parseInt(xhr.responseText.substring(currentIndex, i));
}
if (expectedLength && (xhr.responseText.length >= currentIndex + expectedLength)) {
- var end = currentIndex + expectedLength;
+ const end = currentIndex + expectedLength;
+ let msgs;
+
try {
- var msgs = JSON.parse(
+ msgs = JSON.parse(
xhr.responseText.substring(
currentIndex,
end
);
}
- var specialTypesText = {
+ const specialTypesText = {
"doubleLetter" : _("Double\nLetter"),
"doubleWord" : _("Double\nWord"),
"tripleLetter" : _("Triple\nLetter"),
sendCmds();
}
- var audioTileLoaded = false, audioMsgLoaded = false, tilesSound, msgSound;
+ let audioTileLoaded = false;
+ let audioMsgLoaded = false;
+ let tilesSound;
+ let msgSound;
function loadAudio() {
if (!audioTileLoaded && tilesSound.checked) {
return;
}
- var index = getFreeRackSpaceIndex();
+ const index = getFreeRackSpaceIndex();
if (index === -1) {
myAlert(_("You cannot take another tile: your rack is full."));
} else {
function initChat() {
chatMessages.style.width = chatMessages.offsetWidth + "px";
- var btn = document.getElementById("chat-btn");
- var ta = document.getElementById("chat-ta");
+ const btn = document.getElementById("chat-btn");
+ const ta = document.getElementById("chat-ta");
ta.onmouseup = function () {
chatMessages.style.width = ta.offsetWidth + "px";
audioNotification.preload = "auto";
audioNotification.volume = 1;
- var audioSourceOGG = document.createElement("source");
+ let audioSourceOGG = document.createElement("source");
audioSourceOGG.src = "notification.ogg";
- var audioSourceMP3 = document.createElement("source");
+ let audioSourceMP3 = document.createElement("source");
audioSourceMP3.src = "notification.mp3";
audioNotification.appendChild(audioSourceOGG);
audioNotification.appendChild(audioSourceMP3);
}
trivabble.applyL10n = function () {
- var n = document.querySelectorAll("[data-l10n]");
-
- for (var i = 0, len = n.length; i < len; i++) {
- if (n[i].dataset.l10n === "text-content") {
- n[i].textContent = _(n[i].textContent.trim());
+ for (const node of document.querySelectorAll("[data-l10n]")) {
+ if (node.dataset.l10n === "text-content") {
+ node.textContent = _(node.textContent.trim());
} else {
- n[i].setAttribute(n[i].dataset.l10n, _(n[i].getAttribute(n[i].dataset.l10n)));
+ node.setAttribute(node.dataset.l10n, _(node.getAttribute(node.dataset.l10n)));
}
}
name.textContent = localStorage.trivabblePlayerName;
- var letters = "ABCDEFGHIJKLMNO";
+ const letters = "ABCDEFGHIJKLMNO";
- var doubleLetter = {
+ const doubleLetter = {
"0,3" : true,
"0,11": true,
"2,6" : true,
"6,12": true
};
- var cell;
+ let cell;
- for (var i = 0; i < 7; i++) {
- var span = document.createElement("span");
+ for (let i = 0; i < 7; i++) {
+ const span = document.createElement("span");
span.className = "tile-placeholder";
rack.appendChild(span);
playerLetters.push(span);
}
- for (var i = 0; i < 15; i++) {
+ for (let i = 0; i < 15; i++) {
board.rows[0].appendChild(document.createElement("th"));
board.rows[0].lastChild.textContent = i + 1;
board.appendChild(document.createElement("tr"));
board.lastChild.appendChild(document.createElement("th"));
board.lastChild.lastChild.textContent = letters[i];
- for (var j = 0; j < 15; j++) {
+ for (let j = 0; j < 15; j++) {
cell = document.createElement("td");
boardCells.push(cell);
board.lastChild.appendChild(cell);
board.appendChild(document.createElement("tr"));
board.lastChild.appendChild(board.rows[0].cells[0].cloneNode(false));
- for (var i = 0; i < 15; i++) {
+ for (let i = 0; i < 15; i++) {
board.lastChild.appendChild(document.createElement("th"));
board.lastChild.lastChild.textContent = i + 1;
}
}
function initLang() {
- var lang = localStorage.trivabbleLang || libD.lang;
- libD.lang = lang;
+ const lang = libD.lang = localStorage.trivabbleLang || libD.lang;
- var langSel = document.getElementById("select-lang");
+ const langSel = document.getElementById("select-lang");
langSel.value = lang;
langSel.onchange = langSelectionChange;
- var script = document.createElement("script");
+ const script = document.createElement("script");
script.src = "l10n/js/" + lang + ".js";
script.onerror = trivabble.l10nError;
document.getElementsByTagName("head")[0].appendChild(script);