|
|
|
@ -1,6 +1,6 @@
|
|
|
|
|
// noinspection JSUnresolvedVariable
|
|
|
|
|
const {$, doAfterLoad, footer, header, nav} = window.fwdekker;
|
|
|
|
|
import {Chart, CategoryScale, Filler, LineController, LineElement, LinearScale, PointElement, Tooltip} from "chart.js"
|
|
|
|
|
const {$, $a, doAfterLoad} = window.fwdekker;
|
|
|
|
|
import {CategoryScale, Chart, Filler, LinearScale, LineController, LineElement, PointElement, Tooltip} from "chart.js"
|
|
|
|
|
|
|
|
|
|
Chart.register(CategoryScale, Filler, LineController, LineElement, LinearScale, PointElement, Tooltip);
|
|
|
|
|
|
|
|
|
@ -31,33 +31,6 @@ const rangeInclusive = (from, to) => {
|
|
|
|
|
return rangeArray;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const iterateNodeList = (nodeList, fun) => {
|
|
|
|
|
for (let i = 0; i < nodeList.length; i++) {
|
|
|
|
|
const node = nodeList.item(i);
|
|
|
|
|
fun(node);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//////
|
|
|
|
|
///
|
|
|
|
|
/// Template
|
|
|
|
|
///
|
|
|
|
|
//////
|
|
|
|
|
|
|
|
|
|
doAfterLoad(() => {
|
|
|
|
|
$("#nav").appendChild(nav("/Tools/Dice/"));
|
|
|
|
|
$("#header").appendChild(header({
|
|
|
|
|
title: "Dice",
|
|
|
|
|
description: "Calculate the probability of rolling a value given a combination of dice"
|
|
|
|
|
}));
|
|
|
|
|
$("#footer").appendChild(footer({
|
|
|
|
|
vcsURL: "https://git.fwdekker.com/tools/dice/",
|
|
|
|
|
version: "v%%VERSION_NUMBER%%"
|
|
|
|
|
}));
|
|
|
|
|
$("main").classList.remove("hidden");
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//////
|
|
|
|
|
///
|
|
|
|
@ -69,15 +42,15 @@ const inputTable = {};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Functions
|
|
|
|
|
inputTable.getTable = () => $("#dieSettings tbody");
|
|
|
|
|
inputTable.getTable = () => $("#die-settings tbody");
|
|
|
|
|
|
|
|
|
|
inputTable.dieRowCount = () => inputTable.getTable().querySelectorAll(".dieEyes").length;
|
|
|
|
|
inputTable.dieRowCount = () => $a(".die-eyes", inputTable.getTable()).length;
|
|
|
|
|
|
|
|
|
|
inputTable.highestDieRowIndex = () => {
|
|
|
|
|
const table = inputTable.getTable();
|
|
|
|
|
|
|
|
|
|
let highestDieRowIndex = -1;
|
|
|
|
|
iterateNodeList(table.getElementsByTagName("tr"), (node) => {
|
|
|
|
|
$a("tr", table).forEach((node) => {
|
|
|
|
|
if ("index" in node.dataset)
|
|
|
|
|
highestDieRowIndex = Math.max(highestDieRowIndex, +node.dataset.index);
|
|
|
|
|
});
|
|
|
|
@ -104,10 +77,9 @@ inputTable.addDieRow = () => {
|
|
|
|
|
const createRemoveLink = (index, className) => {
|
|
|
|
|
const link = document.createElement("button");
|
|
|
|
|
link.id = className + index;
|
|
|
|
|
link.className = className + " button-clear";
|
|
|
|
|
link.type = "button";
|
|
|
|
|
link.className = className + " outline";
|
|
|
|
|
link.innerHTML = "Remove";
|
|
|
|
|
link.onclick = (() => inputTable.removeDieRow(index));
|
|
|
|
|
link.addEventListener("click", () => inputTable.removeDieRow(index));
|
|
|
|
|
return link;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
@ -118,31 +90,36 @@ inputTable.addDieRow = () => {
|
|
|
|
|
const row = table.insertRow(inputTable.dieRowCount());
|
|
|
|
|
row.dataset.index = "" + newIndex;
|
|
|
|
|
|
|
|
|
|
row.insertCell().appendChild(createNumberInput(newIndex, "dieEyes", 6));
|
|
|
|
|
row.insertCell().appendChild(createNumberInput(newIndex, "dieCount", 2));
|
|
|
|
|
row.insertCell().appendChild(createRemoveLink(newIndex, "dieRemove"));
|
|
|
|
|
row.insertCell().appendChild(createNumberInput(newIndex, "die-eyes", 6));
|
|
|
|
|
row.insertCell().appendChild(createNumberInput(newIndex, "die-count", 2));
|
|
|
|
|
row.insertCell().appendChild(createRemoveLink(newIndex, "die-remove"));
|
|
|
|
|
|
|
|
|
|
$("#dieEyes" + newIndex).focus();
|
|
|
|
|
if (inputTable.dieRowCount() === 1)
|
|
|
|
|
$(".die-remove").disabled = true;
|
|
|
|
|
else
|
|
|
|
|
$a(".die-remove").forEach((button) => button.disabled = false);
|
|
|
|
|
$("#die-eyes" + newIndex).focus();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
inputTable.removeDieRow = index => {
|
|
|
|
|
if (inputTable.dieRowCount() > 1) {
|
|
|
|
|
const table = inputTable.getTable();
|
|
|
|
|
const row = table.querySelector("tr[data-index=\"" + index + "\"]");
|
|
|
|
|
row.parentElement.removeChild(row);
|
|
|
|
|
}
|
|
|
|
|
if (inputTable.dieRowCount() > 1)
|
|
|
|
|
$(`tr[data-index="${index}"]`, inputTable.getTable()).remove();
|
|
|
|
|
|
|
|
|
|
if (inputTable.dieRowCount() === 1)
|
|
|
|
|
$(".die-remove").disabled = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
inputTable.getDice = () => {
|
|
|
|
|
const dice = [];
|
|
|
|
|
|
|
|
|
|
const eyesInputs = document.getElementsByClassName("dieEyes");
|
|
|
|
|
const countInputs = document.getElementsByClassName("dieCount");
|
|
|
|
|
const countInputs = $a(".die-count");
|
|
|
|
|
const eyesInputs = $a(".die-eyes");
|
|
|
|
|
for (let i = 0; i < eyesInputs.length; i++) {
|
|
|
|
|
const count = parseInt(countInputs.item(i).value);
|
|
|
|
|
const eyes = parseInt(eyesInputs.item(i).value);
|
|
|
|
|
|
|
|
|
|
for (let j = 0; j < count; j++)
|
|
|
|
|
dice.push(parseInt(eyesInputs.item(i).value));
|
|
|
|
|
dice.push(eyes);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return dice;
|
|
|
|
@ -151,9 +128,9 @@ inputTable.getDice = () => {
|
|
|
|
|
|
|
|
|
|
// Init
|
|
|
|
|
doAfterLoad(() => {
|
|
|
|
|
const button = $("#addDieRowButton");
|
|
|
|
|
button.onclick = inputTable.addDieRow;
|
|
|
|
|
button.click();
|
|
|
|
|
const button = $("#add-die-row-button");
|
|
|
|
|
button.addEventListener("click", () => inputTable.addDieRow());
|
|
|
|
|
inputTable.addDieRow();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -190,9 +167,7 @@ outputChart.calculateDiceFrequencies = dice => {
|
|
|
|
|
|
|
|
|
|
// Calculate frequencies
|
|
|
|
|
const totalRolls = rollFreqs.reduce((a, b) => a + b, 0);
|
|
|
|
|
rangeExclusive(0, rollFreqs.length).forEach(roll => {
|
|
|
|
|
rollFreqs[roll] = rollFreqs[roll] / totalRolls;
|
|
|
|
|
});
|
|
|
|
|
rangeExclusive(0, rollFreqs.length).forEach(roll => rollFreqs[roll] = rollFreqs[roll] / totalRolls);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return rollFreqs;
|
|
|
|
@ -213,13 +188,18 @@ outputChart.updateProbGraph = () => {
|
|
|
|
|
|
|
|
|
|
// Init
|
|
|
|
|
doAfterLoad(() => {
|
|
|
|
|
probChart = new Chart($("#probChart").getContext("2d"), {
|
|
|
|
|
type: "line",
|
|
|
|
|
data: {},
|
|
|
|
|
options: {fill: true},
|
|
|
|
|
probChart = new Chart(
|
|
|
|
|
$("#prob-chart").getContext("2d"),
|
|
|
|
|
{
|
|
|
|
|
type: "line",
|
|
|
|
|
data: {},
|
|
|
|
|
options: {fill: true},
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$("#inputs").addEventListener("submit", (event) => {
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
outputChart.updateProbGraph();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const submit = $("#submit");
|
|
|
|
|
submit.onclick = outputChart.updateProbGraph;
|
|
|
|
|
submit.click()
|
|
|
|
|
outputChart.updateProbGraph();
|
|
|
|
|
});
|
|
|
|
|