Merge branch 'automatic_scoring' into 'develop'
Automatic scoring See merge request raphj/trivabble!13
This commit is contained in:
commit
0bd24691d3
|
@ -196,6 +196,12 @@ msgstr "La vérification orthographique nécessite que Trivabble télécharge un
|
|||
msgid "Spell checking is based on:"
|
||||
msgstr "La vérification orthographique est basée sur :"
|
||||
|
||||
msgid "{0} points will be added to:"
|
||||
msgstr "{0} points vont être ajoutés à:"
|
||||
|
||||
msgid "There are no points to add."
|
||||
msgstr "Il n’y a pas de point à ajouter."
|
||||
|
||||
msgid "Settings"
|
||||
msgstr "Paramètres"
|
||||
|
||||
|
@ -231,3 +237,6 @@ msgstr "Désactiver la vérification orthographique"
|
|||
|
||||
msgid "Spell checking is not available for this language."
|
||||
msgstr "La vérification orthographique n'est pas disponible dans cette langue."
|
||||
|
||||
msgid "Score new words"
|
||||
msgstr "Compter les points"
|
||||
|
|
|
@ -196,6 +196,12 @@ msgstr ""
|
|||
msgid "Spell checking is based on:"
|
||||
msgstr ""
|
||||
|
||||
msgid "{0} points will be added to:"
|
||||
msgstr ""
|
||||
|
||||
msgid "There are no points to add."
|
||||
msgstr: ""
|
||||
|
||||
msgid "Settings"
|
||||
msgstr ""
|
||||
|
||||
|
@ -236,3 +242,6 @@ msgstr ""
|
|||
|
||||
msgid "Spell checking is not available for this language."
|
||||
msgstr ""
|
||||
|
||||
msgid "Score new words"
|
||||
msgstr ""
|
||||
|
|
|
@ -40,8 +40,8 @@
|
|||
margin-top:1em;
|
||||
}
|
||||
|
||||
.alert-content {
|
||||
padding:1ex
|
||||
.alert-content-and-input {
|
||||
padding:1ex;
|
||||
}
|
||||
|
||||
.alert input[type=text], .alert input[type=number], .alert input[type=password] {
|
||||
|
@ -81,3 +81,18 @@
|
|||
border-radius:3px
|
||||
}
|
||||
|
||||
.alert-prompt-buttons {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.alert.choice .alert-prompt-buttons, .alert.prompt .alert-prompt-buttons {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.alert.choice.choice-inline .alert-content, .choice.choice-inline .alert-prompt {
|
||||
display:inline-block;
|
||||
}
|
||||
|
||||
.alert.choice.choice-inline .alert-prompt {
|
||||
padding-left: 1ex;
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
let divAlertCallbackYes;
|
||||
let divAlertCallbackNo;
|
||||
let alertInput;
|
||||
let alertSelect;
|
||||
let divAlertContent;
|
||||
|
||||
const _ = (window.libD && libD.l10n) ? libD.l10n() : function (s) {
|
||||
|
@ -85,14 +86,26 @@
|
|||
|
||||
divAlertInput.appendChild(alertInput);
|
||||
|
||||
divAlertInput.appendChild(document.createElement("div"));
|
||||
divAlertInput.lastChild.className = "alert-prompt-buttons";
|
||||
divAlertInput.lastChild.appendChild(document.createElement("button"));
|
||||
divAlertInput.lastChild.lastChild.textContent = _("OK");
|
||||
divAlertInput.lastChild.lastChild.onclick = promptOK;
|
||||
divAlertInput.lastChild.appendChild(document.createElement("button"));
|
||||
divAlertInput.lastChild.lastChild.textContent = _("Annuler");
|
||||
divAlertInput.lastChild.lastChild.onclick = promptCancel;
|
||||
alertSelect = document.createElement("select");
|
||||
alertSelect.onchange = function () {
|
||||
alertInput.value = alertSelect.value;
|
||||
};
|
||||
|
||||
divAlertInput.appendChild(alertSelect);
|
||||
|
||||
const divAlertContentAndInput = document.createElement("div");
|
||||
divAlertContentAndInput.className = "alert-content-and-input";
|
||||
divAlertContentAndInput.appendChild(divAlertContent);
|
||||
divAlertContentAndInput.appendChild(divAlertInput);
|
||||
|
||||
const divAlerPromptButton = document.createElement("div");
|
||||
divAlerPromptButton.className = "alert-prompt-buttons";
|
||||
divAlerPromptButton.appendChild(document.createElement("button"));
|
||||
divAlerPromptButton.lastChild.textContent = _("OK");
|
||||
divAlerPromptButton.lastChild.onclick = promptOK;
|
||||
divAlerPromptButton.appendChild(document.createElement("button"));
|
||||
divAlerPromptButton.lastChild.textContent = _("Cancel");
|
||||
divAlerPromptButton.lastChild.onclick = promptCancel;
|
||||
|
||||
divAlertConfirm = document.createElement("div");
|
||||
divAlertConfirm.className = _("alert-confirm");
|
||||
|
@ -111,8 +124,8 @@
|
|||
|
||||
const divAlertOuter = document.createElement("div");
|
||||
divAlertOuter.className = "alert-outer";
|
||||
divAlertOuter.appendChild(divAlertContent);
|
||||
divAlertOuter.appendChild(divAlertInput);
|
||||
divAlertOuter.appendChild(divAlertContentAndInput);
|
||||
divAlertOuter.appendChild(divAlerPromptButton);
|
||||
divAlertOuter.appendChild(divAlertConfirm);
|
||||
divAlertOuter.appendChild(divAlertButton);
|
||||
divAlert.appendChild(divAlertOuter);
|
||||
|
@ -131,6 +144,8 @@
|
|||
}
|
||||
|
||||
divAlert.classList.remove("prompt");
|
||||
divAlert.classList.remove("choice");
|
||||
divAlert.classList.remove("choice-inline");
|
||||
|
||||
divAlertContent.textContent = msg;
|
||||
divAlertInput.style.display = "none";
|
||||
|
@ -149,11 +164,15 @@
|
|||
}
|
||||
|
||||
divAlert.classList.add("prompt");
|
||||
divAlert.classList.remove("choice");
|
||||
divAlert.classList.remove("choice-inline");
|
||||
|
||||
divAlertContent.textContent = msg;
|
||||
divAlertInput.style.display = "";
|
||||
alertInput.style.display = "";
|
||||
alertInput.value = defaultText || "";
|
||||
alertInput.type = (options && options.type) || "text";
|
||||
alertSelect.style.display = "none";
|
||||
divAlertConfirm.style.display = "none";
|
||||
divAlertButton.style.display = "none";
|
||||
divAlertCallback = callback;
|
||||
|
@ -170,6 +189,8 @@
|
|||
}
|
||||
|
||||
divAlert.classList.remove("prompt");
|
||||
divAlert.classList.remove("choice");
|
||||
divAlert.classList.remove("choice-inline");
|
||||
|
||||
divAlertContent.textContent = msg;
|
||||
divAlertInput.style.display = "none";
|
||||
|
@ -180,4 +201,35 @@
|
|||
divAlert.style.display = "";
|
||||
divAlertConfirm.getElementsByTagName("button")[0].focus();
|
||||
};
|
||||
|
||||
global.myChoice = function (msg, options, callback, defaultValue) {
|
||||
if (!divAlert) {
|
||||
prepare();
|
||||
}
|
||||
|
||||
divAlert.classList.remove("prompt");
|
||||
divAlert.classList.add("choice");
|
||||
|
||||
if (options.dispositionInline) {
|
||||
divAlert.classList.add("choice-inline");
|
||||
} else {
|
||||
divAlert.classList.remove("choice-inline");
|
||||
}
|
||||
|
||||
alertSelect.options.length = 0;
|
||||
for (const key of options.choices) {
|
||||
[].push.call(alertSelect.options, new Option(key, key));
|
||||
}
|
||||
alertSelect.value = alertInput.value = defaultValue;
|
||||
|
||||
divAlertContent.textContent = msg;
|
||||
divAlertInput.style.display = "";
|
||||
alertInput.style.display = "none";
|
||||
alertSelect.style.display = "";
|
||||
divAlertConfirm.style.display = "none";
|
||||
divAlertButton.style.display = "none";
|
||||
divAlertCallback = callback;
|
||||
divAlert.style.display = "";
|
||||
divAlertConfirm.getElementsByTagName("button")[0].focus();
|
||||
};
|
||||
}(this));
|
||||
|
|
|
@ -35,6 +35,11 @@ window.TrivabbleConf = {
|
|||
// The defaut double tap duration. If not set, the value at the middle of the previous array is used.
|
||||
DOUBLE_TAP_DURATION: 1800,
|
||||
|
||||
// The default premium for playing seven tiles on a turn
|
||||
PREMIUM_SEVEN_TILES: 50,
|
||||
|
||||
// Score is automically affected to last player. If false, score is automatically affected to the player who pressed the Score button
|
||||
SCORE_LAST_PLAYER: true,
|
||||
|
||||
// I don't like trailing commas, here is a nice message for you reading this file :-)
|
||||
HAVE_FUN: true
|
||||
|
|
|
@ -124,6 +124,7 @@
|
|||
<button id="clear-rack" class="minibutton" data-l10n="text-content">Put back all the tiles of your rack in the bag</button>
|
||||
<button id="show-rack" class="minibutton" data-l10n="text-content">Show my rack to other players</button>
|
||||
<button id="check-spelling" class="minibutton" data-l10n="text-content" hidden="true">Check spelling for new words</button>
|
||||
<button id="score-words" class="minibutton" data-l10n="text-content">Score new words</button>
|
||||
</div>
|
||||
<div id="help-box">
|
||||
<p id="help-box-title" data-l10n="text-content">Tip!</p>
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* @source: https://gitlab.com/raphj/trivabble/
|
||||
*/
|
||||
|
||||
/*global libD, myConfirm, myAlert, myPrompt*/
|
||||
/*global libD, myConfirm, myAlert, myPrompt, myChoice*/
|
||||
|
||||
(function () {
|
||||
"use strict";
|
||||
|
@ -60,6 +60,8 @@
|
|||
setConf("FLASH_LIGHT_DURATION", middle("FLASH_LIGHT_DURATIONS"));
|
||||
setConf("FLASH_LIGHT_COLOR", "#ee6633");
|
||||
setConf("API_ENTRY_POINT", Conf.APP_PATH + "/:trivabble");
|
||||
setConf("PREMIUM_SEVEN_TILES", 50);
|
||||
setConf("SCORE_LAST_PLAYER", true);
|
||||
|
||||
function getSetting(key) {
|
||||
let type;
|
||||
|
@ -193,6 +195,8 @@
|
|||
let currentMessageId = 1;
|
||||
const waitingMsgs = [];
|
||||
|
||||
let lastPlayer = null;
|
||||
|
||||
let serverVersion = 0;
|
||||
|
||||
function mouseDown(ele, fun, stop) {
|
||||
|
@ -720,6 +724,14 @@
|
|||
}
|
||||
|
||||
function setCell(index, letter, highlight) {
|
||||
if (lastPlayer) {
|
||||
if (letter) {
|
||||
currentTilePlayed[index] = letter;
|
||||
} else {
|
||||
delete currentTilePlayed[index];
|
||||
}
|
||||
}
|
||||
|
||||
setTileParent(boardCells[index].getElementsByClassName("tile-placeholder")[0], letter, highlight);
|
||||
}
|
||||
|
||||
|
@ -911,11 +923,14 @@
|
|||
tablePlayers[currentPlayer].classList.remove("current-player");
|
||||
}
|
||||
|
||||
currentTilePlayed = {};
|
||||
currentPlayer = player;
|
||||
refreshCurrentPlayer();
|
||||
}
|
||||
|
||||
function getScoreCell(playerName) {
|
||||
return tablePlayers[playerName].childNodes[2].childNodes[0];
|
||||
}
|
||||
|
||||
function setPlayers(players) {
|
||||
if (participantPlaceholder) {
|
||||
participantPlaceholder.parentNode.removeChild(participantPlaceholder);
|
||||
|
@ -1027,7 +1042,10 @@
|
|||
}
|
||||
|
||||
if (Object.prototype.hasOwnProperty.call(player, "score")) {
|
||||
const scoreCell = tablePlayers[playerName].childNodes[2].childNodes[0];
|
||||
const scoreCell = getScoreCell(playerName);
|
||||
if (parseInt(scoreCell.textContent) !== player.score) {
|
||||
currentTilePlayed = {};
|
||||
}
|
||||
scoreCell.textContent = player.score;
|
||||
blink(scoreCell);
|
||||
}
|
||||
|
@ -1042,6 +1060,15 @@
|
|||
refreshCurrentPlayer();
|
||||
}
|
||||
|
||||
function handleLastPlayer(data) {
|
||||
if (data.player) {
|
||||
if (lastPlayer !== data.player) {
|
||||
currentTilePlayed = {};
|
||||
}
|
||||
lastPlayer = data.player;
|
||||
}
|
||||
}
|
||||
|
||||
function applyAction(data) {
|
||||
switch (data.action) {
|
||||
case "pushBag": //TODO
|
||||
|
@ -1056,9 +1083,14 @@
|
|||
participants.removeChild(participants.rows[1]);
|
||||
}
|
||||
sendCmds([{cmd: "hello"}]);
|
||||
|
||||
lastPlayer = null;
|
||||
currentTilePlayed = {};
|
||||
break;
|
||||
|
||||
case "moveLetter":
|
||||
handleLastPlayer(data);
|
||||
|
||||
if (data.from === "board") {
|
||||
setCell(data.indexFrom, "");
|
||||
} else if (data.from === "rack") {
|
||||
|
@ -1066,17 +1098,32 @@
|
|||
}
|
||||
|
||||
if (data.to === "board") {
|
||||
setCell(data.indexTo, data.letter, Object.prototype.hasOwnProperty.call(data, "player") && data.player !== getSetting("PlayerName"));
|
||||
setCell(
|
||||
data.indexTo,
|
||||
data.letter,
|
||||
data.player && data.player !== getSetting("PlayerName")
|
||||
);
|
||||
} else if (data.to === "rack") {
|
||||
setRackCell(data.indexTo, data.letter);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case "setCell":
|
||||
setCell(data.indexTo, data.letter, Object.prototype.hasOwnProperty.call(data, "player") && data.player !== getSetting("PlayerName"));
|
||||
handleLastPlayer(data);
|
||||
|
||||
setCell(
|
||||
data.indexTo,
|
||||
data.letter,
|
||||
data.player && data.player !== getSetting("PlayerName")
|
||||
);
|
||||
|
||||
if ((data.letter !== "") && (currentTilePlayed[data.indexTo] === "-")) {
|
||||
currentTilePlayed[data.indexTo] = data.letter;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case "setRackCell":
|
||||
setRackCell(data.indexTo, data.letter);
|
||||
}
|
||||
|
@ -1824,6 +1871,84 @@
|
|||
return [].indexOf.call(tr.parentNode.rows, tr);
|
||||
}
|
||||
|
||||
function scoreWords() {
|
||||
let totalScore = 0;
|
||||
|
||||
const newWords = searchNewWords();
|
||||
for (const k of Object.keys(newWords)) {
|
||||
let wordFactor = 1;
|
||||
let wordScore = 0;
|
||||
|
||||
const word = newWords[k];
|
||||
for (let l = 0; l < word.letters.length; l++) {
|
||||
const index = ((word.row + (l * word.incRow)) * 15) + word.col + (l * word.incCol);
|
||||
|
||||
/* Letter score */
|
||||
const tilePlaceholder = boardCells[index].getElementsByClassName("tile-placeholder")[0];
|
||||
const tile = tilePlaceholder.getElementsByClassName("tile")[0];
|
||||
const letterScore = tile.lastChild.textContent;
|
||||
let letterFactor = 1;
|
||||
|
||||
/* Is a freshly played letter? */
|
||||
if (currentTilePlayed[index] === word.letters[l]) {
|
||||
|
||||
/* Letter factor */
|
||||
if (boardCells[index].classList.contains("special-cell-doubleLetter")) {
|
||||
letterFactor = 2;
|
||||
} else if (boardCells[index].classList.contains("special-cell-tripleLetter")) {
|
||||
letterFactor = 3;
|
||||
}
|
||||
|
||||
/* Word factor */
|
||||
if (boardCells[index].classList.contains("special-cell-doubleWord")) {
|
||||
wordFactor *= 2;
|
||||
} else if (boardCells[index].classList.contains("special-cell-tripleWord")) {
|
||||
wordFactor *= 3;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
wordScore += letterScore * letterFactor;
|
||||
}
|
||||
|
||||
totalScore += wordScore * wordFactor;
|
||||
}
|
||||
|
||||
if (!totalScore) {
|
||||
myAlert(_("There are no points to add."));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check for trivabble (the premium score) */
|
||||
if (Object.keys(currentTilePlayed).length === 7) {
|
||||
totalScore += getSetting("PREMIUM_SEVEN_TILES");
|
||||
}
|
||||
|
||||
/* Ѕcore last player or the one who pressed the button */
|
||||
const playerName = getSetting("SCORE_LAST_PLAYER") ? lastPlayer : getSetting("PlayerName");
|
||||
|
||||
myChoice(
|
||||
format(_("{0} points will be added to:"), totalScore), {
|
||||
choices: Object.keys(tablePlayers),
|
||||
dispositionInline: true
|
||||
},
|
||||
function (name) {
|
||||
if (!name) {
|
||||
return;
|
||||
}
|
||||
|
||||
currentTilePlayed = {};
|
||||
|
||||
sendCmds([{
|
||||
cmd: "score",
|
||||
player: name,
|
||||
score: parseInt(getScoreCell(name).textContent) + totalScore
|
||||
}]);
|
||||
},
|
||||
playerName || lastPlayer || currentPlayer || getSetting("PlayerName")
|
||||
);
|
||||
}
|
||||
|
||||
function triggerFlashLight(cell) {
|
||||
if (!cell) {
|
||||
return;
|
||||
|
@ -2192,6 +2317,7 @@
|
|||
document.getElementById("btn-settings-close").onclick = hideSettings;
|
||||
document.getElementById("next-help-msg").onclick = nextHelpMessage;
|
||||
document.getElementById("disable-spell-checker").onclick = toggleSpellChecker;
|
||||
document.getElementById("score-words").onclick = scoreWords;
|
||||
window.addEventListener("keydown", function (e) {
|
||||
if (e.key === "Escape") {
|
||||
document.querySelector(".modal").classList.remove("show-modal");
|
||||
|
|
Loading…
Reference in New Issue