"use strict" let fields = [ "Datenelch", "6 Stunden Schlaf", "Tschunk getrunken", "Spaß gehabt", "Sticker getauscht", "DECT genutzt", "Hardware gehackt", "Kabel vergessen", "Halle gesucht", "$dinge gelötet", "an SoS teil-genommen", "Neue Leute kennen-gelernt", "Wasser getrunken", "Waffel gegessen", "Corona Test gemacht", "2 Mahlzeiten gegessen", "Fairydust bewundert", "Talk angeschaut", "CCC Merch getragen", "Engel-schicht gemacht", "In der Lounge getanzt", "Etwas Neues aus-probiert", "Maske getragen", "geduscht" ]; let seed; const urlParams = new URLSearchParams(window.location.search); const seed_elem = document.querySelector('#seeed-value'); const allFields = document.querySelectorAll('#bingo td'); const bingoFields = document.querySelectorAll('#bingo td.bingo-field'); const centerFieldImage = document.querySelector('#center-field-image'); const refreshBingoButton = document.querySelector('#refresh-bingo'); const copyPermalinkButton = document.querySelector('#copy-permalink'); centerFieldImage.src = "img/logo.svg" centerFieldImage.alt = "37C3 Logo"; centerFieldImage.parentElement.addEventListener('contextmenu', ev => { ev.preventDefault(); centerFieldImage.parentElement.classList.remove('bingo'); }); /** * Reads the seed from URL Parameter or generates new seed */ if (urlParams.has('seeed')) { seed = urlParams.get('seeed'); } else { seed = Date.now().toString(); } const copyPermalinkToClipboard = function () { const permalink = window.location.href; navigator.clipboard.writeText(permalink); } copyPermalinkButton.addEventListener('click', copyPermalinkToClipboard); const shuffleBoard = () => { let prng_hash_seed = cyrb128(seed); let rand = sfc32(prng_hash_seed[0], prng_hash_seed[1], prng_hash_seed[2], prng_hash_seed[3]); return fields .map(value => ({value, sort: rand()})) .sort((a, b) => a.sort - b.sort) .map(({value}) => value) .slice(0, 24) } const checkForBingo = (field) => { let bingo = false; let clickedRow = parseInt(field.dataset.row); let clickedCol = parseInt(field.dataset.col); //check horizontal and vertical axis if (document.querySelectorAll(`#bingo td.drawn[data-row='${clickedRow}']`).length === 5) { document.querySelectorAll(`#bingo td.drawn[data-row='${clickedRow}']`).forEach(elem => elem.classList.add('bingo')); bingo = true; } else { } if (document.querySelectorAll(`#bingo td.drawn[data-col='${clickedCol}']`).length === 5) { document.querySelectorAll(`#bingo td.drawn[data-col='${clickedCol}']`).forEach(elem => elem.classList.add('bingo')); bingo = true; } else { } //check diagonal axis if (clickedRow === clickedCol) { if ( document.querySelector(`#bingo td.drawn[data-row="0"][data-col="0"]`) && document.querySelector(`#bingo td.drawn[data-row="1"][data-col="1"]`) && document.querySelector(`#bingo td.drawn[data-row="3"][data-col="3"]`) && document.querySelector(`#bingo td.drawn[data-row="4"][data-col="4"]`) ) { document.querySelector(`#bingo td.drawn[data-row="0"][data-col="0"]`).classList.add('bingo'); document.querySelector(`#bingo td.drawn[data-row="1"][data-col="1"]`).classList.add('bingo'); document.querySelector(`#bingo td.drawn[data-row="2"][data-col="2"]`).classList.add('bingo'); document.querySelector(`#bingo td.drawn[data-row="3"][data-col="3"]`).classList.add('bingo'); document.querySelector(`#bingo td.drawn[data-row="4"][data-col="4"]`).classList.add('bingo'); bingo = true; } } else if (clickedRow + clickedCol === 4) { if ( document.querySelector(`#bingo td.drawn[data-row="0"][data-col="4"]`) && document.querySelector(`#bingo td.drawn[data-row="1"][data-col="3"]`) && document.querySelector(`#bingo td.drawn[data-row="3"][data-col="1"]`) && document.querySelector(`#bingo td.drawn[data-row="4"][data-col="0"]`) ) { document.querySelector(`#bingo td.drawn[data-row="0"][data-col="4"]`).classList.add('bingo'); document.querySelector(`#bingo td.drawn[data-row="1"][data-col="3"]`).classList.add('bingo'); document.querySelector(`#bingo td.drawn[data-row="2"][data-col="2"]`).classList.add('bingo'); document.querySelector(`#bingo td.drawn[data-row="3"][data-col="1"]`).classList.add('bingo'); document.querySelector(`#bingo td.drawn[data-row="4"][data-col="0"]`).classList.add('bingo'); bingo = true; } } if (bingo) { window.fireworks.start(); } }; const drawBingoFieldEventHandler = (ev) => { let field = ev.target; if (field && !field.classList.contains('drawn')) { field.classList.add('drawn'); checkForBingo(field); } else { console.error('Sum ting wong (*  ̄︿ ̄)'); } }; const undrawBingoFieldEventHandler = (ev) => { ev.preventDefault(); let field = ev.target; if (field) { field.classList.remove('drawn'); field.classList.remove('bingo'); } else { console.error('Sum ting wong (*  ̄︿ ̄)'); } }; const drawTable = () => { shuffleBoard().forEach((field, index) => { bingoFields[index].textContent = field; bingoFields[index].addEventListener('click', drawBingoFieldEventHandler); bingoFields[index].addEventListener('contextmenu', undrawBingoFieldEventHandler); }); seed_elem.innerText = seed; window.history.pushState(null, null, '?seeed=' + seed); } // hash function, thx stackoverflow :3 function cyrb128(str) { let h1 = 1779033703, h2 = 3144134277, h3 = 1013904242, h4 = 2773480762; for (let i = 0, k; i < str.length; i++) { k = str.charCodeAt(i); h1 = h2 ^ Math.imul(h1 ^ k, 597399067); h2 = h3 ^ Math.imul(h2 ^ k, 2869860233); h3 = h4 ^ Math.imul(h3 ^ k, 951274213); h4 = h1 ^ Math.imul(h4 ^ k, 2716044179); } h1 = Math.imul(h3 ^ (h1 >>> 18), 597399067); h2 = Math.imul(h4 ^ (h2 >>> 22), 2869860233); h3 = Math.imul(h1 ^ (h3 >>> 17), 951274213); h4 = Math.imul(h2 ^ (h4 >>> 19), 2716044179); return [(h1 ^ h2 ^ h3 ^ h4) >>> 0, (h2 ^ h1) >>> 0, (h3 ^ h1) >>> 0, (h4 ^ h1) >>> 0]; } function sfc32(a, b, c, d) { return function () { a >>>= 0; b >>>= 0; c >>>= 0; d >>>= 0; var t = (a + b) | 0; a = b ^ b >>> 9; b = c + (c << 3) | 0; c = (c << 21 | c >>> 11); d = d + 1 | 0; t = t + d | 0; c = c + t | 0; return (t >>> 0) / 4294967296; } } 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; } } drawTable(); const redrawTable = function () { allFields.forEach(elem => { elem.classList.remove('bingo'); }); bingoFields.forEach(elem => { elem.classList.remove('drawn'); }); seed = Date.now().toString(); drawTable(); } refreshBingoButton.addEventListener('click', redrawTable)