const Rs = {
settings: {
wordLength: 5,
validLetters: [
"a",
"b",
"c",
"d",
"e",
"f",
"g",
"h",
"i",
"j",
"k",
"l",
"m",
"n",
"o",
"p",
"q",
"r",
"s",
"t",
"u",
"v",
"w",
"x",
"y",
"z"
]
},
lang: $("html")
.getAttribute("lang")
.match(/^[a-z]*/)[0],
word: ["S", "K", "I", "R", "T"],
turn: 0,
guess: [],
shareable: ``,
resetted: false,
addToGuess: function (letter, device) {
if (
Dict[Rs.lang].validLetters.includes(Rs.guess.at(-1) + letter) &&
device == "physical"
) {
Rs.guess[Rs.guess.length - 1] = Rs.guess.at(-1) + letter;
const tile =
$$("#game-board .tile")[
Rs.turn * Rs.settings.wordLength + Rs.guess.length - 1
];
tile.innerHTML = Rs.guess.at(-1);
} else if (Dict[Rs.lang]?.validAliases?.[Rs.guess.at(-1) + letter]) {
Rs.guess[Rs.guess.length - 1] =
Dict[Rs.lang].validAliases[Rs.guess.at(-1) + letter];
const tile =
$$("#game-board .tile")[
Rs.turn * Rs.settings.wordLength + Rs.guess.length - 1
];
tile.innerHTML = Rs.guess.at(-1);
} else if (
Rs.guess.length < 5 &&
Dict[Rs.lang].validLetters.includes(letter)
) {
Rs.guess.push(letter);
const tile =
$$("#game-board .tile")[
Rs.turn * Rs.settings.wordLength + Rs.guess.length - 1
];
tile.innerHTML = Rs.guess.at(-1);
tile.classList.replace("empty", "tba");
}
},
backspace: function () {
if (Rs.guess.length > 0) {
Rs.guess.pop();
const tile =
$$("#game-board .tile")[
Rs.turn * Rs.settings.wordLength + Rs.guess.length
];
tile.innerHTML = "";
tile.classList.replace("tba", "empty");
}
},
enter: function () {
if (Rs.guess.length == 5) {
if (Dict[Rs.lang].validWords.includes(Rs.guess.join(""))) {
let answer = [...Rs.word];
let squares = [
"⬜\ufe0f",
"⬜\ufe0f",
"⬜\ufe0f",
"⬜\ufe0f",
"⬜\ufe0f"
];
for (let i = 0; i < 5; i++) {
if (Rs.guess[i] == answer[i]) {
$$("#game-board .tile")[
Rs.turn * Rs.settings.wordLength + i
].classList.replace("tba", "correct");
$(`#key-${Rs.guess[i]}`).classList.replace(
"empty",
"correct"
);
$(`#key-${Rs.guess[i]}`).classList.replace(
"misplaced",
"correct"
);
squares[i] = "✅";
answer[i] = "";
}
}
console.log(answer);
if (
JSON.stringify(answer) ==
JSON.stringify(["", "", "", "", ""])
) {
Rs.shareable +=
"\n" +
squares.join("") +
"\n" +
Rs.strings[Rs.lang].gameUrl;
$(
"#toasts"
).innerHTML += `<div class="toast long" id="game-end"><strong>${Rs.strings[
Rs.lang
].toasts.scoreReveal()}</strong><p>${
Rs.strings[Rs.lang].toasts.whyNotShare
}</p><pre>${
Rs.shareable
}</pre><button onclick='navigator.clipboard.writeText(Rs.shareable)'>${
Rs.strings[Rs.lang].toasts.copyToClipboard
}</button><br><button onclick='Rs.reset()'>${
Rs.strings[Rs.lang].toasts.keepPlaying
}</button></div>`;
Rs.guess = [];
document.removeEventListener("keydown", Rs.logKey);
return;
}
for (let i = 0; i < 5; i++) {
console.log(Rs.guess);
console.log(answer);
if (
answer.includes(Rs.guess[i]) &&
!$$("#game-board .tile")[
Rs.turn * Rs.settings.wordLength + i
].classList.contains("correct")
) {
$$("#game-board .tile")[
Rs.turn * Rs.settings.wordLength + i
].classList.replace("tba", "misplaced");
$(`#key-${Rs.guess[i]}`).classList.replace(
"empty",
"misplaced"
);
squares[i] = "🟨";
answer[answer.indexOf(Rs.guess[i])] = "";
} else {
$$("#game-board .tile")[
Rs.turn * Rs.settings.wordLength + i
].classList.replace("tba", "wrong");
$(`#key-${Rs.guess[i]}`).classList.replace(
"empty",
"wrong"
);
}
}
if (Rs.turn == 4) {
Rs.shareable += "\n" + squares.join("");
$(
"#toasts"
).innerHTML += `<div class="toast long" id="game-end"><strong>${
Rs.strings[Rs.lang].toasts.betterLuckNextTime
}</strong><p>${Rs.strings[
Rs.lang
].toasts.wordReveal()}</p><pre>${
Rs.shareable
}</pre><button onclick='navigator.clipboard.writeText(Rs.shareable)'>${
Rs.strings[Rs.lang].toasts.copyToClipboard
}</button><br><button onclick='Rs.reset()'>${
Rs.strings[Rs.lang].toasts.keepPlaying
}</button></div>`;
Rs.guess = [];
document.removeEventListener("keydown", Rs.logKey);
return;
}
Rs.guess = [];
Rs.shareable += "\n" + squares.join("");
Rs.turn++;
} else {
Rs.backspace();
Rs.backspace();
Rs.backspace();
Rs.backspace();
Rs.backspace();
$("#toasts").innerHTML += Rs.strings[Rs.lang].toasts.notInDict;
setTimeout(function () {
$(".toast.short").remove();
}, 3490);
}
}
},
logKey: function (e) {
switch (e.key) {
case "Backspace":
e.preventDefault();
Rs.backspace();
break;
case "Enter":
Rs.enter();
break;
default:
Rs.addToGuess(e.key, "physical");
}
},
splitWord: function (word) {
let array = [];
if (Array.isArray(word)) {
return word;
}
for (x of word) {
if (Dict[Rs.lang].validLetters.includes(`${array.at(-1)}${x}`)) {
array[array.length - 1] += x;
} else {
array.push(x);
}
}
return array;
},
open: function (sel) {
$(sel).style.display = "block";
},
close: function (sel) {
$(sel).style.display = "none";
},
reset: function () {
Rs.guess = [];
Rs.turn = 0;
Rs.resetted = true;
Rs.shareable = `${Rs.strings[Rs.lang].gameName} ∞`;
$("#game-end").remove();
for (const x of $$("#game-board .tile")) {
x.outerHTML = `<div class="tile empty"></div>`;
}
for (const x of $$("#keyboard button:not(.special)")) {
x.setAttribute("class", "empty");
}
Rs.word = Rs.splitWord(
Dict[Rs.lang].answers[
Math.floor(Dict[Rs.lang].answers.length * Math.random())
]
);
document.addEventListener("keydown", Rs.logKey);
},
toggle: function (data) {
if ($(`html`).dataset[data] == "true") {
$(`html`).dataset[data] = "false";
$(`#${data}`).setAttribute("checked", null);
localStorage.setItem(`rumpelstiltskin-${data}`, "false");
} else {
$(`html`).dataset[data] = "true";
$(`#${data}`).setAttribute("checked", "true");
localStorage.setItem(`rumpelstiltskin-${data}`, "true");
}
},
changeKeyboard: function (layout) {
keyboardOutput = "";
for (row of Rs.keyboards[Rs.lang][layout].keys) {
keyboardOutput += `<div class="row">`;
for (key of row) {
switch (key) {
case "HALFSPACE":
keyboardOutput += `<div class="halfwidth"></div>`;
break;
case "FULLSPACE":
keyboardOutput += `<div class="fullwidth"></div>`;
break;
case "BACK":
keyboardOutput += `<button class="empty special" onclick="Rs.backspace()">⌫</button>`;
break;
case "ENTER":
keyboardOutput += `<button class="empty special" onclick="Rs.enter()">${
Rs.strings[Rs.lang].keyboard.enter
}</button>`;
break;
default:
keyboardOutput += `<button class="${
$(`#key-${key}`)
? $(`#key-${key}`).getAttribute("class")
: "empty"
}" onclick="Rs.addToGuess('${key}','onscreen')" id="key-${key}">${key}</button>`;
}
}
keyboardOutput += `</div>`;
}
$("#keyboard").innerHTML = keyboardOutput;
$(`html`).dataset.keyboardLayout = layout;
localStorage.setItem(`rumpelstiltskin-keyboard-layout`, layout);
},
changeTheme: function () {
$(`html`).dataset.theme = $(`#theme`).value;
if ($(`#theme [selected]`)) {
$(`#theme [selected]`).removeAttribute("selected");
}
$(`#theme [value="${$(`#theme`).value}"]`).setAttribute(
"selected",
"true"
);
localStorage.setItem("rumpelstiltskin-theme", $(`#theme`).value);
},
keyboards: {
en: {
qwerty: {
name: "Qwerty",
keys: [
["q", "w", "e", "r", "t", "y", "u", "i", "o", "p"],
[
"HALFSPACE",
"a",
"s",
"d",
"f",
"g",
"h",
"j",
"k",
"l",
"HALFSPACE"
],
["ENTER", "z", "x", "c", "v", "b", "n", "m", "BACK"]
]
},
azerty: {
name: "Azerty",
keys: [
["a", "z", "e", "r", "t", "y", "u", "i", "o", "p"],
["q", "s", "d", "f", "g", "h", "j", "k", "l", "m"],
["ENTER", "w", "x", "c", "v", "b", "n", "BACK"]
]
},
qwertz: {
name: "Qwertz",
keys: [
["q", "w", "e", "r", "t", "z", "u", "i", "o", "p"],
[
"HALFSPACE",
"a",
"s",
"d",
"f",
"g",
"h",
"j",
"k",
"l",
"HALFSPACE"
],
["ENTER", "y", "x", "c", "v", "b", "n", "m", "BACK"]
]
},
dvorak: {
name: "Dvorak",
keys: [
["ENTER", "BACK", "p", "y", "f", "g", "c", "r", "l"],
["a", "o", "e", "u", "i", "d", "h", "t", "n", "s"],
["FULLSPACE", "q", "j", "k", "x", "b", "m", "w", "v", "z"]
]
},
colemak: {
name: "Colemak",
keys: [
["q", "w", "f", "p", "g", "j", "l", "u", "y"],
["a", "r", "s", "t", "d", "h", "n", "e", "i", "o"],
["ENTER", "z", "x", "c", "v", "b", "k", "m", "BACK"]
]
},
alphabetical: {
name: "Alphabetical",
keys: [
["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"],
["k", "l", "m", "n", "o", "p", "q", "r", "s", "t"],
["ENTER", "u", "v", "w", "x", "y", "z", "BACK"]
]
}
},
nl: {
qwerty: {
name: "Qwerty",
keys: [
["q", "w", "e", "r", "t", "y", "u", "i", "o", "p"],
["a", "s", "d", "f", "g", "h", "j", "k", "l", "ij"],
["ENTER", "z", "x", "c", "v", "b", "n", "m", "BACK"]
]
},
azerty: {
name: "Azerty",
keys: [
["a", "z", "e", "r", "t", "y", "u", "i", "o", "p"],
["q", "s", "d", "f", "g", "h", "j", "k", "l", "m"],
["ENTER", "w", "x", "c", "v", "b", "n", "ij", "BACK"]
]
},
qwertz: {
name: "Qwertz",
keys: [
["q", "w", "e", "r", "t", "z", "u", "i", "o", "p"],
["a", "s", "d", "f", "g", "h", "j", "k", "l", "ij"],
["ENTER", "y", "x", "c", "v", "b", "n", "m", "BACK"]
]
},
dvorak: {
name: "Dvorak",
keys: [
["ENTER", "BACK", "p", "y", "f", "g", "c", "r", "l"],
["a", "o", "e", "u", "i", "d", "h", "t", "n", "s"],
["ij", "q", "j", "k", "x", "b", "m", "w", "v", "z"]
]
},
colemak: {
name: "Colemak",
keys: [
["q", "w", "f", "p", "g", "j", "l", "u", "y", "ij"],
["a", "r", "s", "t", "d", "h", "n", "e", "i", "o"],
["ENTER", "z", "x", "c", "v", "b", "k", "m", "BACK"]
]
},
alphabetical: {
name: "Alfabetisch",
keys: [
["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"],
["k", "l", "m", "n", "o", "p", "q", "r", "s", "t"],
["ENTER", "u", "v", "w", "x", "ij", "y", "z", "BACK"]
]
}
},
eo: {
qwerty: {
name: "ŜĜERTŬ",
keys: [
["ŝ", "ĝ", "e", "r", "t", "ŭ", "u", "i", "o", "p"],
["a", "s", "d", "f", "g", "h", "j", "k", "l", "ĵ"],
["ENTER", "z", "ĉ", "c", "v", "b", "n", "m", "ĥ", "BACK"]
]
},
azerty: {
name: "AZERTŬ",
keys: [
["a", "z", "e", "r", "t", "ŭ", "u", "i", "o", "p"],
["ŝ", "s", "d", "f", "g", "h", "j", "k", "l", "m"],
["ENTER", "ĝ", "ĵ", "ĉ", "c", "v", "b", "n", "ĥ", "BACK"]
]
},
qwertz: {
name: "ŜĜERTZ",
keys: [
["ŝ", "ĝ", "e", "r", "t", "z", "u", "i", "o", "p"],
["a", "s", "d", "f", "g", "h", "j", "k", "l", "ĵ"],
["ENTER", "ŭ", "ĉ", "c", "v", "b", "n", "m", "ĥ", "BACK"]
]
},
dvorak: {
name: "Dvorak",
keys: [
["ENTER", "BACK", "p", "ĝ", "f", "g", "c", "r", "l", "ĵ"],
["a", "o", "e", "u", "i", "d", "h", "t", "n", "s"],
["ĥ", "ĉ", "j", "k", "ŝ", "b", "m", "ŭ", "v", "z"]
]
},
colemak: {
name: "Kolmak",
keys: [
["ŝ", "ĝ", "f", "p", "g", "j", "l", "u", "ŭ", "ĵ"],
["a", "r", "s", "t", "d", "h", "n", "e", "i", "o"],
["ENTER", "z", "ĉ", "c", "v", "b", "k", "m", "ĥ", "BACK"]
]
},
alphabetical: {
name: "Alfabeta",
keys: [
["a", "b", "c", "ĉ", "d", "e", "f", "g", "ĝ", "h"],
["ĥ", "i", "j", "ĵ", "k", "l", "m", "n", "o", "p"],
["ENTER", "r", "s", "ŝ", "t", "u", "ŭ", "v", "z", "BACK"]
]
}
}
},
strings: {
en: {
gameName: `Rumpelstiltskin`,
currentDate: `${new Date().getFullYear()} ${
[
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec"
][new Date().getMonth()]
} ${new Date().getDate()}`,
gameUrl: `https://satyrs.eu/rs-en`,
toasts: {
notInDict: `<div class="toast short">That word isn’t in our dictionary, i’m afraid!</div>`,
keepPlaying: `Keep playing indefinitely`,
copyToClipboard: `Copy to clipboard`,
whyNotShare: `Why not share your result with your friends?`,
wordReveal: () =>
`The correct word was <b>${Rs.word
.join("")
.toUpperCase()}</b>. Why not commiserate with your friends?`,
betterLuckNextTime: `Ah, gubbins. Better luck next time.`,
scoreReveal: () =>
`You got ${
[
"a hole in one",
"an albatross",
"a birdie",
"a par",
"a bogey",
"a double bogey"
][Rs.turn]
}!`
},
keyboard: {
enter: `Enter`
}
},
nl: {
gameName: `Repelsteeltje`,
currentDate: `${new Date().getDate()} ${
[
"januari",
"februari",
"maart",
"april",
"mei",
"juni",
"juli",
"augustus",
"september",
"oktober",
"november",
"december"
][new Date().getMonth()]
} ${new Date().getFullYear()}`,
gameUrl: `https://satyrs.eu/rs-nl`,
toasts: {
notInDict: `<div class="toast short">Dat woord staat niet in ons woordenboek.</div>`,
keepPlaying: `Blijven spelen`,
copyToClipboard: `Naar klembord kopiëren`,
whyNotShare: `Wil je je resultaat met je vrienden delen?`,
wordReveal: () =>
`Het juiste woord was <b>${Rs.word
.join("")
.toUpperCase()}</b>. Wil je je mislukking met je vrienden delen?`,
betterLuckNextTime: `Ah, chips. Volgende keer beter!`,
scoreReveal: () =>
`Je hebt een ${
[
"hole-in-one",
"albatros",
"birdie",
"par",
"bogey",
"double bogey"
][Rs.turn]
} gemaakt!`
},
keyboard: {
enter: `Enter`
}
},
eo: {
gameName: `Tremotino`,
currentDate: `${new Date().getDate()}-an de ${
[
"januaro",
"februaro",
"marto",
"aprilo",
"majo",
"junio",
"julio",
"auĝusto",
"septembro",
"oktobro",
"novembro",
"decembro"
][new Date().getMonth()]
} ${new Date().getFullYear()}`,
gameUrl: `https://satyrs.eu/rs-eo`,
toasts: {
notInDict: `<div class="toast short">Nia vortaro ne enhavas tiun vorton.</div>`,
keepPlaying: `Plue ludi`,
copyToClipboard: `Kopii al kliptabulo`,
whyNotShare: `Ĉu vi montrus vian rezulton al viaj amikoj?`,
wordReveal: () =>
`La ĝusta vorto estis <b>${Rs.word
.join("")
.toUpperCase()}</b>. Ĉu vi montrus vian eraron al viaj amikoj?`,
betterLuckNextTime: `Ho, ve. Pli bonŝancon venontfoje!`,
scoreReveal: () =>
`Vi divenis la vorton je ${
[
"unu provo",
"du provoj",
"tri provoj",
"kvar provoj",
"kvin provoj",
"ses provoj"
][Rs.turn]
}!`
},
keyboard: {
enter: `Enigi`
}
}
}
};
for (const x of ["highContrast", "legibleText"]) {
const storedValue = localStorage.getItem(`rumpelstiltskin-${x}`);
if (storedValue) {
$(`html`).dataset[x] = storedValue;
if (storedValue == "true") {
$(`#${x}`).checked = true;
}
}
}
if (localStorage.getItem(`rumpelstiltskin-keyboard-layout`)) {
Rs.changeKeyboard(localStorage.getItem(`rumpelstiltskin-keyboard-layout`));
} else {
Rs.changeKeyboard("qwerty");
}
if (localStorage.getItem(`rumpelstiltskin-theme`)) {
$(
`#theme [value="${localStorage.getItem(`rumpelstiltskin-theme`)}"]`
).setAttribute("selected", "true");
Rs.changeTheme();
}
Rs.word = Rs.splitWord(
Dict[Rs.lang].answers[
Math.floor(
(new Date() - new Date("2022-01-01 00:00")) / (1000 * 60 * 60 * 24)
) % Dict[Rs.lang].answers.length
]
);
Rs.shareable = `${Rs.strings[Rs.lang].gameName} ${
Rs.strings[Rs.lang].currentDate
}`;
document.addEventListener("keydown", Rs.logKey);