qwörtle/index.js

476 lines
200 KiB
JavaScript
Raw Normal View History

2022-02-23 11:32:40 +00:00
"use strict";
2022-02-28 18:30:49 +00:00
const words = "aalen abbau abend abgab abruf abtei abtes abzug achse achte acker äcker adels adern adler affen after agent ahnen ähren akten aktie aktiv akute alarm alben album algen alias alibi alien allee allem aller alles allzu altar altem alten alter älter altes ämter amtes anbau anbot angab angel angst anime ankam anker anruf ansah anzug apfel äpfel april arche areal arena ärger armee ärmel armen armer armut aroma arten ärzte asche asien ästen atlas atmen atome audio augen auges autor autos babys bäche bachs baden bäder bades bälle bande bände bands bänke bären basen basis baten bauch bauen bauer baues bäume baute beben begab beide beige beine bekam belag beleg berät berge bergs beruf beste beten beton beute bevor bezog bezug bibel biber biegt biene biete binde birgt bitte blase blass blatt blaue blech blick blieb blind blitz block blüht blume blüte boden böden bogen bögen bombe bonus boote börse bösen bosse boten boxen boxer boxte brach brand braun braut bravo breit brief bruch brust buche bucht buden bühne bulle bunde bünde bunte büros busch busse büste bytes chaos chöre circa clubs dabei dafür daher dahin damen damit dämme dämon dampf dankt daran darin darum datei daten datum dauer davon davor debüt decke decks deckt degen dehnt deich deine dekan dekor delle delta demos denen denke denkt depot deren derer desto dicht dicke diebe dient diese dinge dolch dorfs dosen dosis draht drama drang drauf dreht dritt droge droht druck duell dünen dünne durch dürfe dürre durst düsen ebene echte ecken edikt edlen ehren eiche eiern eifer eigen eilen eilig einem einen einer eines einig einst eisen eises eklat elend elfen elfte elite empor enden endes endet engel engem engen enger enges enkel enorm enten enzym erben erbes erbin erbte erden erdöl ergab erhob erich erlag erlös ernst ernte erste erwog essen etage ethik etwas ewige exakt extra faden fäden fähig fahne fähre fahrt fährt falke falle fälle falls fällt fängt farbe färbt fasst fauna faust fazit feder fehde fehle fehlt feier feind feine felde felle ferne feste feuer figur filme films final finde firma fisch fjord flach flora floss flöte fluch flüge fluss fokus folge folgt folie foren forst forum fotos frage fragt freie fremd freut frist fromm frost frühe fuchs fugen fügen fügte fühle fühlt führe führt fülle füllt funde funke fürst gabel gaben gänge gänse ganze gänze gasen gasse gäste gatte gebar geben gebet gebot gegen gehen gehör geier geige geist gelbe gelte genau genre genug gerät gerne geste getan geübt ghana gilde ginge glanz glatt gleis glich glied glück gnade gotik grabe grade gramm graue greif griff grill grimm grobe grube grund grüne gummi gunst gutem guten guter güter gutes haare haben hafen häfen hafer haken halbe halde halle halte hände handy hänge hängt harte härte hasen hasst hatte hätte haube hauch haupt hause hebel heben hecht heere hefte hegte heilt helme henne herab heran herde herrn herum heute hexen hielt hilfe hilft hinab hinzu hirte hitze hobby höfen hofes hofft hohem hohen höhen hoher höher hohes höhle holen hölle holte honig hoppe hören hörer hörte hosen hotel hufen hüfte hügel hülle human humor hunde hürde hütte ideal ideen ihnen ihrem ihren ihrer ihres ikone immer indem indes index indiz innen insel intro ionen islam jacke jagen jäger jahre jedem jeden jeder jedes jeher jenem jenen jener jenes jetzt joker jüdin junge jungs kabel kader käfer käfig kahle kalte kälte kamen kämen kamin kampf kanal kanon kante kanus kappe karma karte kasse katze kauft kegel kehle kehrt keine kelch kenne kennt kerne kerns kerze kette keule kinos kiosk kiste klage klagt klang klare klärt kleid klein klima klubs kluft kluge knabe knapp knauf knick knien kniet knopf kohle kokon kombi komet komik komma komme kommt könig könne konto köpfe kopie koran korps kraft krank kranz kraus krebs kreis kreuz krieg krimi krise krone küche kugel kühen kühle kühne küken kunde kunst kuppe kurse kurve kurze kürze küsst küste labor lacht laden läden lagen lager laien lampe lande lange l
2022-02-23 09:38:57 +00:00
.split(" ")
.map(x => x.toUpperCase());
2023-09-29 06:57:38 +00:00
const validGuesses = "nudel pilot weber aabbs aabye aacsb aadje aadre aagot aäkon aalen aalls aalst aalto aamir aamon aangs aarne aaros aarti aasee aasen aaser aasim aatal ababa ababu abaje abajo abala abale abana abani abaqa abart abary abasa abaso abata abate abazi abbad abban abbau abbay abbes abbie abbog abbot abbys abcwg abdal abdeh abdin abdon abduh abdus abeba abebe abedi abegg abeka abela abele abell abeln abels abend abens aberg abeti abetz abgab abgar abgas abhob abiad abich abiel abies abija abiku abile abily abita abiul abjar abkam abkan ablai ablaq abloy abner abney abobo abona aboot abort aboud above abram abras abrät abrax abret abreu abril abrin abris abruf absah absam absch absis abtei äbten abtes abtun abtut abudu abuit abuja abuli abuna aburi abuse abuti abvmz abweg abyme abyse abyss abzac abzog abzug acaau acari accor accra accum aceae acene acert aceto acfun acham achaz achen acher achse achte achti achum achun acide acids acier acies acini acioa acken acker äcker acoma acorn acque acqui acres acryl acsay acsev actar acten actes actio activ acton actor actum actus acube acura acute acuto adahm adahn adair adala adama adame adami adamo adamy adana adani adant adapt adare adass adawa adcom adcox addae addai addas added adden addie addio addis addon adeeb adeje adela adell adels adelt adema adena adens adept adern aders adeus adeva adhan adiak adieu adige adije adiko adile adina adine adios adiri aditi adium adjoa adlau adler adlig admed admer admin admon adnan adnat adnet adobe adopt adora adore adorf adorn adoum adour adpcm adpkd adrar adrie adris adrum adsel adulf adult aduno adwen aecma aecom aecrr aedes aedis aegid aegil aegir aegis aegon aegyd aeham aelac aelia aelin aelle aelst aemon aenar aenea aenne aentg aequo aerea aerei aeria aeris aerny aerob aeron aeros aerts aesch aesop aevum afarm afbet afdpg afeef affen affet affin affix äffte afing afire aflaq afpfl afrin afrob afron aftab aften after afton afula afyon afzal afzul agago ägäis agama agame agami agana agano agape agata agate agatz agave agbar agcam agees agein agena ageng agens agent agera agerl agfaö aggas agger aggie agglo aggro aghte ägide ägidi agido agiez agile agimi aging agiou agipi agips agius agkod agler agnat agnew agnos agnus agoco agogo agona agony agoos agoro agovv agrai agram agrar agree agrin agris agros aguai aguer aguia agung aguti ahabs ahadi ahaks ahali ahamm ahaus ahbez ahdan ahead ahern ahlat ahlem ahlke ahmen ahmte ahnen ahner ahnst ahnte ahold ahram ahrar ahras ahrdt ahrem ähren ahron ahsan ahsel ahsen ahuga ahura ahuva ahven ahvst aiacr aibeg aicha aichi aicpa aidac aidan aidcp aided aiden aidid aidit aidos aigis aigle aigos aiken aiket aikey aikin ailbe ailes aileu ailey ailin aille ailly ailoc ailsa aiman aimed aimee aimer ainda ainen aines ainet ainoa ainrc ainsi ainur aioli aiono airag airai airel airey airgo airys aisch aisey aisha aisle aisne aitor aitos aixam aixer aixro aizen ajahn ajaju ajaka ajays ajena ajeti ajimu ajing ajmal ajoin ajrak ajuin akaar akaba akagi akaki akali akama akamu akane akari akash akast akbal akbay akcja akebu akela akemi akens akera akere akers akgün akhan akhfg akiba akide akiko akima akino akiro akita akiva akiza akkad akkbb akkon akkos akkra akmol akmsu akner aknoz akoma akont akora akord akoya akram akrap akrem akron aksai aksak aksoy aksum aksuu aktan akten aktes aktie aktin aktiv aktor akuna akuri akute akyab akyem akyol alach alaka alami alamo alams alana aland alang alano alans alara alard alarm alaun alawi alayh albas albay albea albee alben alber albia albig albim albis albit albon albro albue album albus albuz alcan alceo alcis alcon alcoy alcun alcus alcye aldan alday aldea alden alder aldor aldra aleas aleck alecs aleea aleev alefu aleid aleit aleix aleja aleje alemu alene aleph alers alert alesi aleta alete alexe alexi alexx alexy alexz aleyn alfau alfea alfee alfen alfie alfin alfon alfoz alfre algae algen alger algis algol algot alhed alian alias alibi alica alida alien aliki alimi aliph alisa alise aliso alita aliti aliud aliye aljer aljos alkan alkas
2022-02-23 09:38:57 +00:00
.split(" ")
.map(x => x.toUpperCase());
2022-02-22 21:53:28 +00:00
const valid = "abcdefghijklmnopqrstuvwxyzäöü".toUpperCase();
function xmur3(str) {
for(var i = 0, h = 1779033703 ^ str.length; i < str.length; i++) {
h = Math.imul(h ^ str.charCodeAt(i), 3432918353);
h = h << 13 | h >>> 19;
} return function() {
h = Math.imul(h ^ (h >>> 16), 2246822507);
h = Math.imul(h ^ (h >>> 13), 3266489909);
return (h ^= h >>> 16) >>> 0;
}
}
function mulberry32(a) {
return function() {
var t = a += 0x6D2B79F5;
t = Math.imul(t ^ t >>> 15, t | 1);
t ^= t + Math.imul(t ^ t >>> 7, t | 61);
return ((t ^ t >>> 14) >>> 0) / 4294967296;
}
}
2022-02-23 10:26:58 +00:00
const LOCALSTORAGE_KEY = "qwörtle.data";
let saveData = JSON.parse(localStorage.getItem(LOCALSTORAGE_KEY) || "{}");
2022-02-23 11:00:26 +00:00
function saveLocalStorage() {
localStorage.setItem(LOCALSTORAGE_KEY, JSON.stringify(saveData));
}
2022-02-23 10:26:58 +00:00
const inputAmount = document.getElementById("puzzles");
const NUMBER_OF_WORDS = Number(inputAmount.value) || 4;
2022-02-23 11:32:40 +00:00
const daysSinceEpoch = Math.floor(new Date()/8.64e7);
const startDay = 19046;
2022-02-23 11:00:26 +00:00
const daysSinceStart = daysSinceEpoch - startDay + 1;
const rngSeed = NUMBER_OF_WORDS === 4 ? daysSinceEpoch : (daysSinceEpoch*daysSinceEpoch*NUMBER_OF_WORDS);
const rng = mulberry32(rngSeed);
2022-02-22 21:53:28 +00:00
const chosenWords = [];
for (let i = 0; i < NUMBER_OF_WORDS; i++) {
2022-02-22 21:53:28 +00:00
while (true) {
const idx = Math.floor((rng() * words.length) % words.length);
const chosen = words[idx];
if (chosenWords.indexOf(chosen) !== -1) {
continue;
}
chosenWords.push(chosen);
break;
}
}
const WORD_LENGTH = 5;
const MAX_GUESSES = 5 + NUMBER_OF_WORDS;
2022-02-24 08:11:25 +00:00
const URL = "https://studwww.informatik.kit.edu/~s_keller/qwörtle/";
2022-02-22 21:53:28 +00:00
const guessed = [];
let input = "";
const data = [];
2022-02-23 14:35:32 +00:00
const solutions = [];
const done = Array(NUMBER_OF_WORDS).fill(false);
2022-02-24 08:11:25 +00:00
let shareText = "";
2022-02-22 21:53:28 +00:00
2022-02-23 11:32:40 +00:00
function gameOver() {
2022-02-23 14:35:32 +00:00
for (const el of solutions) {
el.style.display = "block";
}
2022-02-23 11:32:40 +00:00
const NUMBERS = "0⃣1⃣2⃣3⃣4⃣5⃣6⃣7⃣8⃣9⃣";
2022-02-24 08:11:25 +00:00
const FAIL = "❌";
const SOLVED = "✅";
2022-02-23 11:32:40 +00:00
const ANY = "⬜";
const POSITION = "🟨";
const CORRECT = "🟩";
const DONE = "⬛⬛⬛⬛⬛";
let text = "";
text += "Tägliches Qwörtle #" + daysSinceStart + "\n";
2022-02-24 08:11:25 +00:00
let summary = "";
for (let i = 0; i < NUMBER_OF_WORDS; i++) {
2022-02-23 11:32:40 +00:00
if (done[i]) {
if (done[i] <= 9) {
summary += NUMBERS.slice(done[i] * 3, done[i] * 3 + 3);
} else {
summary += SOLVED;
}
2022-02-24 08:11:25 +00:00
} else {
summary += FAIL;
2022-02-23 11:32:40 +00:00
}
if (i % 2 === 1) {
2022-02-24 08:11:25 +00:00
summary += "\n";
2022-02-23 11:32:40 +00:00
}
}
2022-02-24 08:11:25 +00:00
document.getElementById("summary").innerText = summary;
document.getElementById("summary").style.display = "block";
text += summary + URL + "\n";
for (let i = 0; i < NUMBER_OF_WORDS / 2; i++) {
2022-02-23 11:32:40 +00:00
for (let j = 0; j < MAX_GUESSES; j++) {
const rowA = data[2*i * MAX_GUESSES + j];
const rowB = data[(2*i+1) * MAX_GUESSES + j];
let part1 = "";
let part2 = "";
for (let k = 0; k < WORD_LENGTH; k++) {
if (rowA[k].classList.contains("correct")) {
part1 += CORRECT;
} else if (rowA[k].classList.contains("wrong-position")) {
part1 += POSITION;
} else {
part1 += ANY;
}
if (rowB[k].classList.contains("correct")) {
part2 += CORRECT;
} else if (rowB[k].classList.contains("wrong-position")) {
part2 += POSITION;
} else {
part2 += ANY;
}
}
if (done[2*i] && done[2*i] <= j) {
part1 = DONE;
}
if (done[2*i+1] && done[2*i+1] <= j) {
part2 = DONE;
}
if (part1 === DONE && part2 === DONE) {
break;
}
text += part1 + " " + part2 + "\n";
}
if (i % 2 === 0) {
2022-02-23 11:32:40 +00:00
text += "\n";
}
}
2022-02-24 08:11:25 +00:00
shareText = text;
document.getElementById("share").style.display = "block";
}
function desktopShare() {
2022-02-23 11:32:40 +00:00
const textarea = document.getElementById("copyarea");
2022-02-24 08:11:25 +00:00
textarea.style.display = "block";
textarea.value = shareText;
2022-02-23 11:32:40 +00:00
textarea.select();
document.execCommand("copy");
setTimeout(() => {
2022-02-24 08:11:25 +00:00
textarea.value = shareText; // not sure why this is needed..
2022-02-23 11:32:40 +00:00
}, 0);
}
2022-02-24 08:11:25 +00:00
document.getElementById("share").addEventListener("click", () => {
if (navigator.clipboard) {
navigator.clipboard.writeText(shareText);
document.getElementById("copied-to-clipboard").style.display = "block";
} else {
desktopShare();
}
});
2022-02-23 14:12:20 +00:00
let keys = {};
let characters = [];
for (let i = 0; i < NUMBER_OF_WORDS; i++) {
characters.push({});
}
2022-02-23 14:12:20 +00:00
function makeGradient(a, b, c, d, allNope) {
2022-02-23 14:12:20 +00:00
const CORRECT = "rgb(0 204 136)";
const POSITION = "rgb(255 204 0)";
const OTHER = "rgb(156, 163, 175)";
const color = {
"correct": CORRECT,
"position": POSITION
};
if (allNope) {
2022-02-23 14:12:20 +00:00
return "rgb(21 94 117)";
}
const style = "conic-gradient(" +
2022-02-23 14:18:41 +00:00
(color[b] || OTHER) + " 0deg," +
2022-02-23 14:12:20 +00:00
(color[b] || OTHER) + " 90deg," +
2022-02-23 14:18:41 +00:00
(color[d] || OTHER) + " 90deg," +
(color[d] || OTHER) + " 180deg," +
2022-02-23 14:12:20 +00:00
(color[c] || OTHER) + " 180deg," +
(color[c] || OTHER) + " 270deg," +
2022-02-23 14:18:41 +00:00
(color[a] || OTHER) + " 270deg," +
(color[a] || OTHER) + " 360deg)";
2022-02-23 14:12:20 +00:00
return style;
}
2022-02-22 21:53:28 +00:00
function processKey(e) {
if (e.key === "Enter" && guessed.length < MAX_GUESSES) {
if (input.length < 5) {
console.error("input not long enough");
return;
}
2022-02-23 09:38:57 +00:00
if (validGuesses.indexOf(input) === -1) {
2022-02-22 21:53:28 +00:00
console.error("word not in list");
return;
}
for (let pos = 0; pos < NUMBER_OF_WORDS; pos++) {
2022-02-22 21:53:28 +00:00
if (done[pos]) {
2022-02-23 14:15:26 +00:00
for (let i = 0; i < WORD_LENGTH; i++) {
const el = data[pos * MAX_GUESSES + guessed.length][i];
el.className = "cell done";
}
2022-02-22 21:53:28 +00:00
continue;
}
let used = [];
let hints = [];
let word = chosenWords[pos];
for (let i = 0; i < WORD_LENGTH; i++) {
// check whether character i of input is correct
if (word[i] === input[i]) {
hints[i] = "correct";
used[i] = true;
2022-02-23 14:12:20 +00:00
characters[pos][input[i]] = "correct";
2022-02-22 21:53:28 +00:00
}
}
for (let i = 0; i < WORD_LENGTH; i++) {
// check whether character i of input is positioned incorrectly
if (hints[i]) {
continue;
}
for (let j = 0; j < WORD_LENGTH; j++) {
if (used[j]) {
continue;
}
if (input[i] === word[j]) {
hints[i] = "position";
used[j] = true;
2022-02-23 14:12:20 +00:00
if (characters[pos][input[i]] !== "correct") {
characters[pos][input[i]] = "position";
}
2022-02-22 21:53:28 +00:00
break;
}
}
}
2022-02-23 14:12:20 +00:00
for (let i = 0; i < WORD_LENGTH; i++) {
if (!characters[pos][input[i]]) {
characters[pos][input[i]] = "nope";
}
}
2022-02-22 21:53:28 +00:00
for (let i = 0; i < WORD_LENGTH; i++) {
const el = data[pos * MAX_GUESSES + guessed.length][i];
if (hints[i] === "correct") {
2022-02-23 14:15:26 +00:00
el.className = "correct cell done";
// add count for easy mode
const count = word.length - word.replaceAll(input[i], "").length;
if (count > 1) {
const counter = document.createElement("span");
counter.className = "counter";
counter.innerText = count;
data[pos * MAX_GUESSES + guessed.length][i].appendChild(counter);
}
2022-02-22 21:53:28 +00:00
} else if (hints[i] === "position") {
2022-02-23 14:15:26 +00:00
el.className = "wrong-position cell done";
// add count for easy mode
const count = word.length - word.replaceAll(input[i], "").length;
if (count > 1) {
const counter = document.createElement("span");
counter.className = "counter";
counter.innerText = count;
data[pos * MAX_GUESSES + guessed.length][i].appendChild(counter);
}
2022-02-23 14:15:26 +00:00
} else {
el.className = "cell done";
2022-02-22 21:53:28 +00:00
}
}
if (input === word) {
2022-02-23 11:32:40 +00:00
done[pos] = guessed.length + 1;
2022-02-23 14:25:47 +00:00
for (let char in keys) {
if (word.indexOf(char.toUpperCase()) === -1) {
characters[pos][char.toUpperCase()] = "nope";
}
}
2022-02-22 21:53:28 +00:00
}
}
guessed.push(input);
2022-02-23 11:00:26 +00:00
if (daysSinceEpoch in saveData) {
saveData[daysSinceEpoch].guesses.push(input);
} else {
saveData[daysSinceEpoch] = { guesses: [input] };
}
saveLocalStorage();
2022-02-22 21:53:28 +00:00
input = "";
2022-02-23 14:12:20 +00:00
for (let char in keys) {
2022-02-23 14:25:47 +00:00
if (char.length > 1) {
continue;
}
2022-02-23 14:12:20 +00:00
const c = char.toUpperCase();
let anyNotNope = false;
for (let i = 0; i < NUMBER_OF_WORDS; i++) {
anyNotNope |= (characters[i][c] && characters[i][c] !== "nope");
if (anyNotNope) {
break;
}
}
2022-02-23 14:25:47 +00:00
if (anyNotNope || (characters[0][c] === "nope" && characters[1][c] === "nope" && characters[2][c] === "nope" && characters[3][c] === "nope")) {
let allNope = true;
for (let i = 0; i < NUMBER_OF_WORDS; i++) {
if (characters[i][c] !== "nope") {
allNope = false;
break;
}
}
keys[char].style.background = makeGradient(characters[0][c], characters[1][c], characters[2][c], characters[3][c], allNope);
if (allNope) {
2022-02-23 14:25:47 +00:00
keys[char].style.color = "#fff";
2022-02-23 14:12:20 +00:00
keys[char].style.opacity = "0.5";
2022-02-23 14:25:47 +00:00
} else if (anyNotNope) {
2022-02-23 14:12:20 +00:00
keys[char].style.color = "#000";
}
}
}
2022-02-23 11:32:40 +00:00
if (guessed.length == MAX_GUESSES || done.indexOf(false) === -1) {
gameOver();
}
2022-02-22 21:53:28 +00:00
return;
} else if (e.key === "Backspace" && input.length > 0) {
for (let pos = 0; pos < NUMBER_OF_WORDS; pos++) {
2022-02-22 21:53:28 +00:00
data[pos * MAX_GUESSES + guessed.length][input.length - 1].innerText = "";
}
input = input.substring(0, input.length - 1);
} else {
if (e.key.length > 1) {
return;
}
const key = e.key.toUpperCase();
if (valid.indexOf(key) === -1) {
console.error("invalid key");
return;
}
if (input.length == 5) {
console.error("input full");
return;
}
for (let pos = 0; pos < NUMBER_OF_WORDS; pos++) {
2022-02-22 21:53:28 +00:00
if (done[pos]) {
continue;
}
data[pos * MAX_GUESSES + guessed.length][input.length].innerText = key;
}
input += key;
}
2022-02-23 09:38:57 +00:00
const validGuess = input.length < 5 || validGuesses.indexOf(input) !== -1;
for (let pos = 0; pos < NUMBER_OF_WORDS; pos++) {
2022-02-22 21:53:28 +00:00
if (done[pos]) {
continue;
}
if (!validGuess) {
data[pos * MAX_GUESSES + guessed.length][0].parentElement.className = "row invalid";
} else {
data[pos * MAX_GUESSES + guessed.length][0].parentElement.className = "row";
}
}
if (input === "GIGAQ") {
document.getElementById("secret-options").style.display = "block";
}
2022-02-22 21:53:28 +00:00
}
document.addEventListener("keydown", processKey);
2022-02-23 10:16:34 +00:00
// setup keyboard
const layout = [
"qwertzuiopü",
"asdfghjklöä",
["Backspace", "y", "x", "c", "v", "b", "n", "m", "Enter"]
];
const keyboard = document.getElementById("keyboard");
for (let i = 0; i < 3; i++) {
const row = keyboard.children[i];
for (const c of layout[i]) {
const button = document.createElement("button");
if (c === "Backspace") {
button.id = "backspace";
button.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" height="26.9px"><title>Backspace Key Icon</title><path d="M0 0h24v24H0V0z" fill="none"></path><path d="M22 3H7c-.69 0-1.23.35-1.59.88L0 12l5.41 8.11c.36.53.9.89 1.59.89h15c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H7.07L2.4 12l4.66-7H22v14zm-11.59-2L14 13.41 17.59 17 19 15.59 15.41 12 19 8.41 17.59 7 14 10.59 10.41 7 9 8.41 12.59 12 9 15.59z"></path></svg>';
} else if (c === "Enter") {
button.id = "enter";
button.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" height="26.9px"><title>Enter Key Icon</title><path d="M0 0h24v24H0V0z" fill="none"></path><path d="M19 7v4H5.83l3.58-3.59L8 6l-6 6 6 6 1.41-1.41L5.83 13H21V7h-2z"></path></svg>';
} else {
button.innerText = c.toUpperCase();
}
button.className = "key";
button.addEventListener("click", e => processKey({ key: c }));
row.appendChild(button);
2022-02-23 14:12:20 +00:00
keys[c] = button;
2022-02-23 10:16:34 +00:00
}
}
2022-02-22 21:53:28 +00:00
function createGameGrid(container) {
for (let pos = 0; pos < NUMBER_OF_WORDS; pos++) {
2022-02-23 14:35:32 +00:00
container.appendChild(createWordle(chosenWords[pos]));
2022-02-22 21:53:28 +00:00
}
}
2022-02-23 14:35:32 +00:00
function createWordle(word) {
2022-02-22 21:53:28 +00:00
const x = document.createElement("div");
x.className = "wordle";
for (let i = 0; i < MAX_GUESSES; i++) {
x.appendChild(createRow(data));
}
2022-02-23 14:35:32 +00:00
const solution = document.createElement("span");
solution.className = "solution";
solution.innerText = word;
x.appendChild(solution);
solutions.push(solution);
2022-02-22 21:53:28 +00:00
return x;
}
function createRow() {
const x = document.createElement("div");
x.className = "row";
const cells = [];
for (let i = 0; i < 5; i++) {
const cell = document.createElement("span");
x.appendChild(cell);
cell.className = "cell";
cells.push(cell);
}
data.push(cells);
return x;
}
const main = document.getElementById("main");
createGameGrid(main);
2022-02-23 10:26:58 +00:00
let wideOpt = document.getElementById("wide");
2023-09-29 06:57:38 +00:00
if (saveData["wide"] === undefined) {
// enable wide mode on wide screens
const vw = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0);
const vh = Math.max(document.documentElement.clientHeight || 0, window.innerHeight || 0);
if (vw > vh && vw >= 1400) {
saveData["wide"] = true;
}
}
2022-02-23 10:26:58 +00:00
if (saveData["wide"] !== undefined) {
wideOpt.checked = saveData["wide"];
}
function setWideMode() {
saveData.wide = wideOpt.checked;
if (saveData.wide) {
document.body.classList.add("wide");
2022-02-23 10:26:58 +00:00
} else {
document.body.classList.remove("wide");
2022-02-23 10:26:58 +00:00
}
2022-02-23 11:00:26 +00:00
saveLocalStorage();
2022-02-23 10:26:58 +00:00
}
wideOpt.addEventListener("change", setWideMode);
setWideMode();
2022-02-23 11:00:26 +00:00
let countOpt = document.getElementById("count");
if (saveData["count"] !== undefined) {
countOpt.checked = saveData["count"];
}
function setCountMode() {
saveData.count = countOpt.checked;
if (saveData.count) {
document.body.classList.add("count");
} else {
document.body.classList.remove("count");
}
saveLocalStorage();
}
countOpt.addEventListener("change", setCountMode);
setCountMode();
2022-02-23 11:00:26 +00:00
// load previous run
if (daysSinceEpoch in saveData) {
const guesses = saveData[daysSinceEpoch].guesses.slice();
saveData[daysSinceEpoch].guesses = [];
for (const guess of guesses) {
for (const c of guess) {
processKey({ key: c });
}
processKey({ key: "Enter" });
}
}