|
|
|
"use strict"
|
|
|
|
// 'MARTINAA/JAAAAA??!!',
|
|
|
|
// '"Du bist doch auch so einer, der ..."',
|
|
|
|
// 'Brain-AFK',
|
|
|
|
// 'Rant über Kollegen',
|
|
|
|
// 'Redet in StammTV rein',
|
|
|
|
// 'Häää?',
|
|
|
|
// 'Bin mal kurz mitem Hund',
|
|
|
|
// '*schnupft*',
|
|
|
|
// 'Habt ihr des neue ... schon gesehen?',
|
|
|
|
// 'Random Nonsense-Problem',
|
|
|
|
// 'Auf Ausbildung freuen',
|
|
|
|
// 'Erzählt von Hinz und Kunz',
|
|
|
|
// 'Was heißt eigentlich ...?',
|
|
|
|
// 'Wiederholung',
|
|
|
|
// 'Story geht länger als nötig',
|
|
|
|
// 'Labert direkt los',
|
|
|
|
// 'Haljo',
|
|
|
|
// 'Klicken im Mikro',
|
|
|
|
// 'Schlafen',
|
|
|
|
// 'Akustik',
|
|
|
|
// 'Spielt LoL',
|
|
|
|
// 'Tamme Story',
|
|
|
|
// 'Ich kam heut morgen auf Arbeit...',
|
|
|
|
// 'Crypto / Fiat / Inflation ...'
|
|
|
|
|
|
|
|
let topics = {
|
|
|
|
'7vsWild': {
|
|
|
|
'title': '7 vs. Wild',
|
|
|
|
'image': 'img/7-vs-wild-logo.svg',
|
|
|
|
'bingo_color': 'green',
|
|
|
|
'bingo_hover_color': 'darkgreen',
|
|
|
|
'field_color': 'cornflower',
|
|
|
|
'field_hover_color': 'cadetblue',
|
|
|
|
'fields': [
|
|
|
|
'Krokodil',
|
|
|
|
'Blut zu sehen',
|
|
|
|
'"Ich kämpfe"',
|
|
|
|
'"Ich kann nicht mehr"',
|
|
|
|
'Jemand trinkt unsauberes Wasser',
|
|
|
|
'Jemand schneidet von einem lebenden Baum was ab',
|
|
|
|
'Knossi raucht',
|
|
|
|
'Nackt',
|
|
|
|
'Jemand isst eine Kokosnuss',
|
|
|
|
'Stufenlos verstellbare Knoten',
|
|
|
|
'"Ich frag mich, wie es den anderen so geht"',
|
|
|
|
'Kleidung ist feucht/nass',
|
|
|
|
'Joris verwirft seinen Tagesplan',
|
|
|
|
'Sascha flext für die Kamera',
|
|
|
|
'"Bist du deppert?"',
|
|
|
|
'Sonnenbrand',
|
|
|
|
'7 in the wild',
|
|
|
|
'Aus Plastik Müll wird was gebaut',
|
|
|
|
'Es wird geschrien',
|
|
|
|
'Es wird gesungen',
|
|
|
|
'"Mir ist kalt"',
|
|
|
|
'Dinge bekommen Namen',
|
|
|
|
'"Das ist auf einem anderen Level"',
|
|
|
|
'Kleine Krebse',
|
|
|
|
'Jemand entschuldigt sich',
|
|
|
|
'Challenge wird falsch verstanden',
|
|
|
|
'Es ist alles ganz anders als ich es mir vorgestellt habe',
|
|
|
|
'Jemand kündigt an aufzuhören, tut es aber nicht',
|
|
|
|
'Urin',
|
|
|
|
'Jemand spricht durch die Kamera mit Freunden/Familie',
|
|
|
|
'Shelter bricht zusammen',
|
|
|
|
'Jemand weint',
|
|
|
|
'Sonne kommt raus',
|
|
|
|
'Medi Kit wird geöffnet',
|
|
|
|
'Kriegt kein Feuer an',
|
|
|
|
'Joris starrt in die Kamera',
|
|
|
|
'Schimmel',
|
|
|
|
'Jemand geht früher'
|
|
|
|
]
|
|
|
|
},
|
|
|
|
'tinder': {
|
|
|
|
'title': '🔥 Tinder',
|
|
|
|
'image': 'img/Tinder.svg',
|
|
|
|
'field_color': 'firebrick',
|
|
|
|
'field_hover_color': 'crimson',
|
|
|
|
'bingo_color': 'purple',
|
|
|
|
'bingo_hover_color': 'darkviolet',
|
|
|
|
'fields': [
|
|
|
|
'Triple Sternzeichen',
|
|
|
|
'Unaufgeräumtes Zimmer',
|
|
|
|
'Pferdemädchen',
|
|
|
|
'Duckface',
|
|
|
|
'Waschmaschine im Hintergrund',
|
|
|
|
'Nur schwarze Bilder',
|
|
|
|
'Französin',
|
|
|
|
'Selfcare',
|
|
|
|
'Persönlichkeitstyp',
|
|
|
|
'Nur Fotos mit mehreren',
|
|
|
|
'Tier das ihr nicht gehört',
|
|
|
|
'Nur Emojis',
|
|
|
|
'Nur Bilder',
|
|
|
|
'Instagram Handle',
|
|
|
|
'Spricht kein Deutsch',
|
|
|
|
'Nicht aus der Region (nur zu Besuch)',
|
|
|
|
'Selfie ohne Kopf',
|
|
|
|
'Random Foto',
|
|
|
|
'Spotify Song',
|
|
|
|
'Name nicht lesbar',
|
|
|
|
'Hat bereits Kinder',
|
|
|
|
'Bild im Gym',
|
|
|
|
'Polyamorie',
|
|
|
|
'EMF',
|
|
|
|
'Augenbrauen des Todes',
|
|
|
|
'Schweizerdeutsche Beschreibung',
|
|
|
|
'Man kennt sich',
|
|
|
|
'Bild in Barcelona',
|
|
|
|
'Bikinibilder',
|
|
|
|
'Thermalbad',
|
|
|
|
'TikTok Filter',
|
|
|
|
'Disney/Harry Potter',
|
|
|
|
'Polyglot'
|
|
|
|
]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let seed;
|
|
|
|
let topic;
|
|
|
|
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');
|
|
|
|
const winnerMessage = document.querySelector('#winner-message');
|
|
|
|
const topicTitle = document.querySelector('#topic');
|
|
|
|
const topicSelect = document.querySelector('#topic-select');
|
|
|
|
|
|
|
|
const topicChanged = function () {
|
|
|
|
console.log('topic changed');
|
|
|
|
topic = topicSelect.selectedOptions[0].id;
|
|
|
|
redrawTable();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Reads the seed from URL Parameter or generates new seed
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (urlParams.has('seeed')) {
|
|
|
|
seed = urlParams.get('seeed');
|
|
|
|
} else {
|
|
|
|
seed = Date.now().toString();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (urlParams.has('topic')) {
|
|
|
|
topic = urlParams.get('topic');
|
|
|
|
} else {
|
|
|
|
topic = 'tinder';
|
|
|
|
}
|
|
|
|
|
|
|
|
let index = 0;
|
|
|
|
for (let x in topics) {
|
|
|
|
let option = document.createElement('option');
|
|
|
|
option.id = x;
|
|
|
|
option.text = topics[x].title;
|
|
|
|
topicSelect.add(option);
|
|
|
|
if (x === topic) {
|
|
|
|
topicSelect.selectedIndex = index;
|
|
|
|
};
|
|
|
|
index++;
|
|
|
|
}
|
|
|
|
|
|
|
|
topicSelect.addEventListener("change", topicChanged);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set fields, headline and center image based on topic
|
|
|
|
*/
|
|
|
|
|
|
|
|
let fields; // = topics[topic].fields;
|
|
|
|
|
|
|
|
//topicTitle.innerText = topics[topic].title;
|
|
|
|
//centerFieldImage.src = topics[topic].image;
|
|
|
|
//centerFieldImage.alt = topics[topic].title + ' Logo';
|
|
|
|
centerFieldImage.parentElement.addEventListener('contextmenu', ev => {
|
|
|
|
ev.preventDefault();
|
|
|
|
centerFieldImage.parentElement.classList.remove('bingo');
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
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) {
|
|
|
|
winnerMessage.classList.remove('won');
|
|
|
|
window.fireworks.start();
|
|
|
|
winnerMessage.classList.add('won');
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
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 = () => {
|
|
|
|
topicTitle.innerText = topics[topic].title;
|
|
|
|
centerFieldImage.src = topics[topic].image;
|
|
|
|
centerFieldImage.alt = topics[topic].title + ' Logo';
|
|
|
|
fields = topics[topic].fields;
|
|
|
|
|
|
|
|
let sheet = new CSSStyleSheet();
|
|
|
|
|
|
|
|
sheet.replaceSync(`
|
|
|
|
td.drawn {
|
|
|
|
background-color: ` + topics[topic].field_color + `;
|
|
|
|
text-decoration: line-through;
|
|
|
|
}
|
|
|
|
td.drawn:hover {
|
|
|
|
background-color: ` + topics[topic].field_hover_color + `;
|
|
|
|
}
|
|
|
|
td.drawn.bingo {
|
|
|
|
background-color: ` + topics[topic].bingo_color + `;
|
|
|
|
}
|
|
|
|
td.drawn.bingo:hover {
|
|
|
|
background-color: `+ topics[topic].bingo_hover_color +`;
|
|
|
|
}`
|
|
|
|
);
|
|
|
|
|
|
|
|
document.adoptedStyleSheets = [sheet]
|
|
|
|
|
|
|
|
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 + '&topic=' + topic);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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 () {
|
|
|
|
winnerMessage.classList.remove('won');
|
|
|
|
allFields.forEach(elem => {
|
|
|
|
elem.classList.remove('bingo');
|
|
|
|
});
|
|
|
|
bingoFields.forEach(elem => {
|
|
|
|
elem.classList.remove('drawn');
|
|
|
|
});
|
|
|
|
seed = Date.now().toString();
|
|
|
|
|
|
|
|
|
|
|
|
drawTable();
|
|
|
|
}
|
|
|
|
refreshBingoButton.addEventListener('click', redrawTable)
|