rpg-dices/script.js
2024-05-03 19:48:16 +02:00

318 lines
10 KiB
JavaScript
Executable File

class Dice {
constructor(sides, addition = 0, count = 1, color = "#000") {
this.sides = sides;
this.addition = addition;
this.count = count;
this.color = color;
this.selected = false;
}
}
class DiceHistoryEntry {
constructor(dice = undefined, formula = undefined, result = undefined) {
this.dice = dice;
this.formula = formula;
this.result = result;
}
}
const default_sides = [4, 6, 8, 10, 12, 20, 100];
const default_colors = ["#de324c", "#f4895f", "#f8e16f", "#95cf92", "#369acc", "#9656a2", "#000000"];
let darkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
let dices = [];
let history = [];
let dicesContainer = document.getElementById("dices");
let historyContainer = document.getElementById("history");
function getDiceLabel(dice) {
return (dice.count > 1 ? dice.count : "") + "D" + dice.sides + (dice.addition ? (dice.addition < 0 ? "-" : "+") + Math.abs(dice.addition) : "");
}
function renderDice(dice, index) {
const diceElement = document.createElement("div");
diceElement.classList.add("dice");
const diceImage = document.createElement("div");
diceImage.classList.add("dice-image");
if (default_sides.indexOf(dice.sides) != -1) {
diceImage.classList.add("dice-image-" + dice.sides);
} else {
diceImage.classList.add("dice-image-custom");
}
if (dice.color) {
diceImage.style.backgroundColor = dice.color;
// revert b/w on dark-mode
if (darkMode) {
if (["#000", "#000000", "black", "rgb(0,0,0)", "rgb(0, 0, 0)"].indexOf(dice.color) != -1) {
diceImage.style.backgroundColor = "#fff";
} else if (["#fff", "#ffffff", "white", "rgb(255,255,255)", "rgb(255, 255, 255)"].indexOf(dice.color) != -1) {
diceImage.style.backgroundColor = "#000";
}
}
}
const diceImageContainer = document.createElement("div");
diceImageContainer.classList.add("dice-image-container");
diceImageContainer.onclick = function () {
if (dices[index].selected) {
dices[index].selected = false;
diceElement.classList.remove("selected");
} else {
dices[index].selected = true;
diceElement.classList.add("selected");
}
if (dices.filter((dice) => dice.selected).length) {
document.getElementById('roll-button').classList.remove("disabled");
} else {
document.getElementById('roll-button').classList.add("disabled");
}
localStorage.setItem('dices', JSON.stringify(dices));
};
diceImageContainer.appendChild(diceImage);
diceElement.appendChild(diceImageContainer);
const diceLabelContainer = document.createElement("div");
diceLabelContainer.classList.add("label-container");
const diceLabel = document.createElement("label");
diceLabel.innerText = getDiceLabel(dice);
diceLabelContainer.appendChild(diceLabel);
diceElement.appendChild(diceLabelContainer);
const diceRemove = document.createElement("div");
diceRemove.classList.add("remove");
diceRemove.onclick = function () {
removeDice(index);
};
diceElement.appendChild(diceRemove);
if (dice.selected) {
diceElement.classList.add("selected");
} else {
diceElement.classList.remove("selected");
}
dicesContainer.appendChild(diceElement);
}
function renderDices() {
dicesContainer.innerHTML = "";
dices.forEach((dice, index) => {
renderDice(dice, index);
})
if (dices.filter((dice) => dice.selected).length) {
document.getElementById('roll-button').classList.remove("disabled");
} else {
document.getElementById('roll-button').classList.add("disabled");
}
}
function addDice(sides, addition = 0, count = 1, color = "#000") {
dices.push(new Dice(sides, addition, count, color));
localStorage.setItem('dices', JSON.stringify(dices));
renderDices();
}
function removeDice(index) {
dices.splice(index, 1);
localStorage.setItem('dices', JSON.stringify(dices));
renderDices();
}
function resetDices() {
dices = [];
default_sides.forEach((side, i) => {
dices.push(new Dice(side, 0, 1, default_colors[i]));
});
localStorage.setItem('dices', JSON.stringify(dices));
renderDices();
}
function addDiceForm() {
let inputSides = document.getElementById("inputSides");
if (!inputSides.value) {
inputSides = document.getElementById("inputCustom")
}
const inputAddition = document.getElementById("inputAddition");
const inputCount = document.getElementById("inputCount");
const inputColor = document.getElementById("inputColor");
addDice(+inputSides.value, +inputAddition.value, +inputCount.value, inputColor.value);
}
function setDicesContainer(container) {
dicesContainer = container;
}
function renderHistory() {
historyContainer.innerHTML = "";
if (history.length) {
document.getElementById('history-button').classList.remove("disabled");
} else {
document.getElementById('history-button').classList.add("disabled");
}
history.forEach((entry) => {
if (entry.dice && entry.result) {
const entryElement = document.createElement("div");
entryElement.classList.add("entry");
const diceLabel = document.createElement("label");
diceLabel.innerHTML = getDiceLabel(entry.dice) + ":&nbsp;";
diceLabel.style.color = entry.dice.color;
// revert b/w on dark-mode
if (darkMode) {
if (["#000", "#000000", "black", "rgb(0,0,0)", "rgb(0, 0, 0)"].indexOf(entry.dice.color) != -1) {
diceLabel.style.color = "#fff";
} else if (["#fff", "#ffffff", "white", "rgb(255,255,255)", "rgb(255, 255, 255)"].indexOf(entry.dice.color) != -1) {
diceLabel.style.color = "#000";
}
}
entryElement.appendChild(diceLabel);
const diceResult = document.createElement("span");
diceResult.innerText = entry.result;
entryElement.appendChild(diceResult);
const diceFormula = document.createElement("span");
const diceEqual = document.createElement("span");
entryElement.appendChild(diceEqual);
entryElement.appendChild(diceFormula);
if (entry.formula) {
diceFormula.innerText = entry.formula;
diceEqual.innerText = " = "
}
historyContainer.appendChild(entryElement);
} else {
historyContainer.appendChild(document.createElement("hr"));
}
})
}
function roll(dice) {
let formula = "";
for (let index = 0; index < dice.count; index++) {
formula += Math.floor(Math.random() * dice.sides + 1);
if (index < dice.count - 1) {
formula += " + ";
}
}
if (dice.addition) {
formula += " + " + dice.addition;
}
const result = eval(formula);
if (formula.indexOf("+") == -1) {
formula = "";
}
history.unshift(new DiceHistoryEntry(dice, formula, result));
localStorage.setItem('history', JSON.stringify(history));
renderHistory();
}
function rollSelected() {
if (dices.filter((dice) => dice.selected).length) {
if (history.length) {
history.unshift(new DiceHistoryEntry());
}
dices.forEach((dice) => {
if (dice.selected) {
roll(dice);
}
})
}
}
function clearHistory() {
history = [];
localStorage.removeItem('history');
renderHistory();
}
function exportData() {
const downloadButton = document.createElement('a');
downloadButton.setAttribute('href', 'data:application/json;charset=utf-8,' + encodeURIComponent(JSON.stringify({ dices: dices, history: history })));
downloadButton.setAttribute('download', 'rgp-dices-' + new Date().toISOString() + '.json');
document.body.appendChild(downloadButton);
downloadButton.click();
document.body.removeChild(downloadButton);
}
function importData(event) {
event.target.parentElement.classList.remove("error");
try {
const reader = new FileReader();
reader.addEventListener('load', async (event) => {
const data = JSON.parse(event.target.result);
if (data.dices) {
dices = data.dices;
renderDices();
}
if (data.history) {
history = data.history;
renderHistory();
}
});
reader.readAsText(event.target.files[0]);
} catch (e) {
console.warn(e);
event.target.parentElement.classList.add("error");
}
}
function updateCustom() {
if (!document.getElementById("inputSides").value) {
document.getElementById("inputCustom").classList.remove("hidden");
} else {
document.getElementById("inputCustom").classList.add("hidden");
}
}
function toggleDarkMode() {
if (darkMode) {
darkMode = false;
document.body.classList.remove("dark");
document.getElementById("dark-mode-icon").src = "./assets/dark.svg";
document.getElementById("dark-mode-text").innerText = "Dark Mode";
} else {
darkMode = true;
document.body.classList.add("dark");
document.getElementById("dark-mode-icon").src = "./assets/light.svg";
document.getElementById("dark-mode-text").innerText = "Light Mode";
}
renderDices();
renderHistory();
}
if (localStorage.getItem('dices')) {
dices = JSON.parse(localStorage.getItem('dices'));
} else {
default_sides.forEach((side, i) => {
dices.push(new Dice(side, 0, 1, default_colors[i]));
})
}
if (localStorage.getItem('history')) {
history = JSON.parse(localStorage.getItem('history'));
}
document.getElementById("importFile").addEventListener("change", importData);
renderDices();
renderHistory();
updateCustom();
if (darkMode) {
document.body.classList.add("dark");
document.getElementById("dark-mode-icon").src = "./assets/light.svg";
document.getElementById("dark-mode-text").innerText = "Light Mode";
}