Files
shtclck/shtclck.js

355 lines
11 KiB
JavaScript

let interval = 0;
let resetTime = 30;
let timer = resetTime * 2;
let race = 7;
let alternateBreak = false;
let player1 = 'Player 1';
let player2 = 'Player 2';
let activePlayer = 1;
let breakedPlayer = 1;
let element;
let audioCtx;
document.body.oncontextmenu = function () {
return false;
}; // i know this is useless. it was just distracting me ;)
/* get data from cookie if possible */
if (document.cookie.length) {
var cookies = document.cookie.split('; ').reduce((prev, current) => {
const [name, ...value] = current.split('=');
prev[name] = value.join('=');
return prev;
}, {});
resetTime = cookies.resetTime ?? resetTime;
timer = resetTime * 2;
updateDisplay();
race = cookies.race ?? race;
document.querySelector('.display-race').innerText = race;
player1 = cookies.player1 ?? player1;
document.querySelector('#player1 .player-name').innerText = player1;
player2 = cookies.player2 ?? player2;
document.querySelector('#player2 .player-name').innerText = player2;
alternateBreak = cookies.alternateBreak ? (cookies.alternateBreak == 'true') : alternateBreak;
}
document.getElementById('welcome-play').addEventListener('click', toggleWelcome);
// Player
function setPlayer1Name(name) {
document.querySelector('#player1 .player-name').innerText = name;
document.cookie = "player1=" + name;
}
document.querySelector('#player1 .player-name').addEventListener('click', function () {
showPrompt('text', 'Enter name of Player 1:', this.innerText, 'setPlayer1Name');
});
function setPlayer2Name(name) {
document.querySelector('#player2 .player-name').innerText = name;
document.cookie = "player2=" + name;
}
document.querySelector('#player2 .player-name').addEventListener('click', function () {
showPrompt('text', 'Enter name of Player 2:', this.innerText, 'setPlayer2Name');
});
function toggleActivePlayer() {
document.querySelector('#player' + activePlayer + ' .player-name').classList.remove('active');
activePlayer = activePlayer == 1 ? 2 : 1;
document.querySelector('#player' + activePlayer + ' .player-name').classList.add('active');
}
document.querySelectorAll('.player-name').forEach(function (element) {
onLongPress(element, toggleActivePlayer);
});
function increasePlayerScore() {
if (interval) {
toggleTimer();
}
timer = resetTime * 2;
updateDisplay();
this.innerText = Number.parseInt(this.innerText) + 1;
if (alternateBreak) {
breakedPlayer = breakedPlayer == 1 ? 2 : 1;
} else {
breakedPlayer = this.dataset.player;
}
if (activePlayer != breakedPlayer) {
toggleActivePlayer();
}
document.querySelector('.display-break.active').classList.remove('active');
document.getElementById("display-break-player" + breakedPlayer).classList.add('active');
}
document.querySelectorAll('td.player-score').forEach(element => element.addEventListener('click', increasePlayerScore));
function setPlayer1Score(score) {
document.querySelector('#player1 .player-score').innerText = score ? score : 0;
}
element = document.querySelector('#player1 .player-score');
onLongPress(element, () => {
showPrompt('number', 'Enter score for player 1:', document.querySelector('#player1 .player-score').innerText, 'setPlayer1Score');
});
function setPlayer2Score(score) {
document.querySelector('#player2 .player-score').innerText = score ? score : 0;
}
element = document.querySelector('#player2 .player-score');
onLongPress(element, () => {
showPrompt('number', 'Enter score for player 2:', document.querySelector('#player2 .player-score').innerText, 'setPlayer2Score');
});
function playerExtension() {
timer += resetTime;
updateDisplay();
this.classList.remove('active');
}
document.querySelectorAll('.player-extension').forEach(element => element.addEventListener('click', playerExtension));
document.querySelectorAll('.player-extension').forEach(function (element) {
onLongPress(element, () => element.classList.toggle('active'));
});
// Display
function toggleBreakedPlayer() {
document.querySelectorAll('.display-break').forEach(element => element.classList.toggle('active'));
breakedPlayer = breakedPlayer == 1 ? 2 : 1;
}
document.querySelectorAll('.display-break').forEach(function (element) {
onLongPress(element, () => toggleBreakedPlayer());
});
function resetTimer() {
timer = resetTime;
updateDisplay();
}
document.querySelector('.display-timer').addEventListener('click', resetTimer);
function setTimer(newTimer) {
if (interval) {
toggleTimer();
}
timer = newTimer ? Number.parseInt(newTimer) : timer;
updateDisplay();
}
element = document.querySelector('.display-timer');
onLongPress(element, () => showPrompt('number', 'Enter time:', timer, 'setTimer'));
// Controls
function toggleTimer() {
if (timer == 0) {
return;
}
if (!interval) {
interval = setInterval(runTimer, 1000);
runTimer();
} else {
clearInterval(interval);
interval = null;
}
document.querySelector('#controls-play i').classList.toggle('fa-play');
document.querySelector('#controls-play i').classList.toggle('fa-pause');
}
document.getElementById('controls-play').addEventListener('click', toggleTimer);
function switchPlayer() {
resetTimer();
toggleActivePlayer();
if (!interval) {
toggleTimer();
}
}
document.getElementById('controls-switch').addEventListener('click', switchPlayer);
element = document.getElementById('controls-switch');
onLongPress(element, () => {
switchPlayer();
timer = resetTime * 2;
updateDisplay();
});
function toggleSettings() {
document.getElementById('main').classList.toggle('invisible');
document.getElementById('settings').classList.toggle('invisible');
document.getElementById('settings-time').value = resetTime;
document.getElementById('settings-race').value = race;
document.getElementById('settings-alternate').checked = alternateBreak;
}
document.getElementById('controls-settings').addEventListener('click', toggleSettings);
// Modals
// Welcome screen
function toggleWelcome() {
document.getElementById('main').classList.toggle('invisible');
document.getElementById('welcome').classList.toggle('invisible');
document.body.requestFullscreen();
screen.orientation.lock('landscape');
}
// settings
function resetGame() {
document.querySelectorAll('.player-score').forEach(element => element.innerText = 0);
if (activePlayer == 2) {
toggleActivePlayer();
}
if (breakedPlayer == 2) {
toggleBreakedPlayer();
}
if (interval) {
toggleTimer();
}
timer = resetTime * 2;
updateDisplay();
document.querySelectorAll('.player-extension').forEach(element => element.classList.add('active'));
document.body.requestFullscreen();
screen.orientation.lock('landscape');
toggleSettings();
}
document.getElementById('settings-reset').addEventListener('click', resetGame);
function setFullscreen() {
document.body.requestFullscreen();
screen.orientation.lock('landscape');
}
document.getElementById('settings-fullscreen').addEventListener('click', setFullscreen);
function toggleAbout() {
document.getElementById('about').classList.toggle('invisible');
document.getElementById('settings').classList.toggle('invisible');
}
document.getElementById('settings-about').addEventListener('click', toggleAbout);
document.getElementById('about-cancel').addEventListener('click', toggleAbout);
document.getElementById('settings-cancel').addEventListener('click', toggleSettings);
function saveSettings() {
var inputtime = document.getElementById('settings-time').value;
if (isNaN(inputtime) || inputtime <= 0) {
alert("Must input numbers > 0");
return false;
}
resetTime = Math.floor(inputtime)
document.cookie = "resetTime=" + resetTime;
resetTimer();
var newRace = document.getElementById('settings-race').value;
race = newRace ? newRace : race;
document.cookie = "race=" + race;
document.querySelector('.display-race').innerText = race;
alternateBreak = document.getElementById('settings-alternate').checked;
document.cookie = "alternateBreak=" + alternateBreak;
toggleSettings();
}
document.getElementById('settings-save').addEventListener('click', saveSettings);
// update timer + bar concurrently
function updateDisplay() {
document.querySelector('.display-timer').innerText = timer;
document.querySelector('.display-bar').style.background = "linear-gradient(90deg, rgba(0,0,0,1) -200%, rgba(255,0,0,1) " + (Math.ceil(100 - (timer / resetTime) * 300)) + "%, rgba(0,241,32,1) 100%)";
}
function runTimer() {
if (timer < 0) {
toggleTimer();
return;
}
updateDisplay();
timer--;
if (timer < 0) {
beep(1000, 1212);
toggleTimer();
return;
}
if (timer < 5) {
beep(100, 606);
}
}
function showPrompt(type, label, value, callback) {
document.getElementById('prompt').classList.remove('invisible');
document.getElementById('prompt').classList.remove('active');
document.querySelectorAll('.prompt-input').forEach(element => element.classList.add('invisible'));
document.querySelectorAll('.prompt-input.prompt-' + type).forEach(function(element) {
element.classList.remove('invisible');
element.classList.add('active');
});
document.querySelector('.prompt-input.prompt-' + type + ' label').innerText = label;
document.querySelector('.prompt-input.prompt-' + type + ' input').value = value;
document.querySelector('#prompt-save').dataset.callback = callback;
}
document.getElementById('prompt-cancel').addEventListener('click', () => document.getElementById('prompt').classList.add('invisible'));
function savePrompt() {
window[this.dataset.callback](document.querySelector('.prompt-input.active input').value);
document.getElementById('prompt').classList.add('invisible');
}
document.getElementById('prompt-save').addEventListener('click', savePrompt);
// Helpers
function onLongPress(element, callback) {
let timer;
element.addEventListener('touchstart', () => {
timer = setTimeout(() => {
timer = null;
callback();
}, 500);
});
function cancel() {
clearTimeout(timer);
}
element.addEventListener('touchend', cancel);
element.addEventListener('touchmove', cancel);
}
//duration of the tone in milliseconds. Default is 500
//frequency of the tone in hertz. default is 440
//volume of the tone. Default is 1, off is 0.
//type of tone. Possible values are sine, square, sawtooth, triangle, and custom. Default is sine.
//callback to use on end of tone
function beep(duration, frequency, volume, type, callback) {
if (!audioCtx) {
audioCtx = new (window.AudioContext || window.webkitAudioContext || window.audioContext);
}
var oscillator = audioCtx.createOscillator();
var gainNode = audioCtx.createGain();
oscillator.connect(gainNode);
gainNode.connect(audioCtx.destination);
if (volume) {
gainNode.gain.value = volume;
}
if (frequency) {
oscillator.frequency.value = frequency;
}
if (type) {
oscillator.type = type;
}
if (callback) {
oscillator.onended = callback;
}
oscillator.start(audioCtx.currentTime);
oscillator.stop(audioCtx.currentTime + ((duration || 500) / 1000));
};