Reformat and modernise code

This commit is contained in:
Florine W. Dekker 2019-06-08 03:57:10 +02:00
parent e013d67d1d
commit e7fe9a9254
Signed by: FWDekker
GPG Key ID: B1B567AF58D6EE0F
1 changed files with 227 additions and 232 deletions

View File

@ -3,297 +3,292 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="author" content="Felix W. Dekker" />
<meta name="application-name" content="Dice probabilities" />
<meta name="description" content="Calculates the probability of throwing a value given a combination of dice." />
<meta name="theme-color" content="#0033cc" />
<meta name="author" content="Felix W. Dekker"/>
<meta name="application-name" content="Dice probabilities"/>
<meta name="description" content="Calculates the probability of throwing a value given a combination of dice."/>
<meta name="theme-color" content="#0033cc"/>
<title>Dice probabilities | FWDekker</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.min.css" integrity="sha256-l85OmPOjvil/SOvVt3HnSSjzF1TUMyT9eV0c2BzEGzU=" crossorigin="anonymous" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/milligram/1.3.0/milligram.min.css" integrity="sha256-Ro/wP8uUi8LR71kwIdilf78atpu8bTEwrK5ZotZo+Zc=" crossorigin="anonymous" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.min.css"
integrity="sha256-l85OmPOjvil/SOvVt3HnSSjzF1TUMyT9eV0c2BzEGzU=" crossorigin="anonymous"/>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/milligram/1.3.0/milligram.min.css"
integrity="sha256-Ro/wP8uUi8LR71kwIdilf78atpu8bTEwrK5ZotZo+Zc=" crossorigin="anonymous"/>
<style>
body {
margin-top: 50px;
margin-bottom: 50px;
}
</style>
<style>
body {
margin-top: 50px;
margin-bottom: 50px;
}
</style>
</head>
<body>
<div class="container">
<h1>Dice probabilities</h1>
<blockquote>
<p><em>Calculates the probability of throwing a value given a combination of dice.</em></p>
</blockquote>
<div class="container">
<h1>Dice probabilities</h1>
<blockquote>
<p><em>Calculates the probability of throwing a value given a combination of dice.</em></p>
</blockquote>
<!-- Input -->
<div class="row">
<div class="column">
<form>
<fieldset>
<table id="dieSettings">
<thead>
<tr>
<th>Sides per die</th>
<th>Number of throws</th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td><button id="addDieRowButton" class="button-outline" type="button">Add dice</button></td>
</tr>
</tbody>
</table>
<!-- Input -->
<div class="row">
<div class="column">
<form>
<fieldset>
<table id="dieSettings">
<thead>
<tr>
<th>Sides per die</th>
<th>Number of throws</th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td>
<button id="addDieRowButton" class="button-outline" type="button">Add dice</button>
</td>
</tr>
</tbody>
</table>
<button id="submit" type="button">Submit</button>
</fieldset>
</form>
</div>
</div>
<button id="submit" type="button">Submit</button>
</fieldset>
</form>
</div>
</div>
<!-- Output -->
<h2>Probabilities</h2>
<div class="row" height="400px">
<div class="column">
<canvas id="probChart"></canvas>
</div>
</div>
</div>
<!-- Output -->
<h2>Probabilities</h2>
<div class="row">
<div class="column">
<canvas id="probChart"></canvas>
</div>
</div>
</div>
<!-- Scripts -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.3/Chart.min.js"
integrity="sha256-oSgtFCCmHWRPQ/JmR4OoZ3Xke1Pw4v50uh6pLcu+fIc=" crossorigin="anonymous"></script>
<script>
//////
///
/// Helper functions
///
//////
<!-- Scripts -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.3/Chart.min.js" integrity="sha256-oSgtFCCmHWRPQ/JmR4OoZ3Xke1Pw4v50uh6pLcu+fIc=" crossorigin="anonymous"></script>
<script>
//////
///
/// Helper functions
///
//////
const doAfterLoad = fun => {
const oldOnLoad = window.onload || (() => {
});
window.onload = (() => {
oldOnLoad();
fun();
});
};
function addOnLoad(fun) {
var oldOnLoad = window.onload || (() => {});
window.onload = (() => {
oldOnLoad();
fun();
});
}
const repeat = (value, length) => {
const zeroArray = [];
for (let i = 0; i < length; i++)
zeroArray.push(value);
return zeroArray;
};
function repeat(value, length) {
var zeroArray = [];
for (var i = 0; i < length; i++) {
zeroArray.push(value);
}
return zeroArray;
}
const rangeExclusive = (from, to) => {
const rangeArray = [];
for (let i = from; i < to; i++)
rangeArray.push(i);
return rangeArray;
};
function rangeExclusive(from, to) {
var rangeArray = [];
for (var i = from; i < to; i++) {
rangeArray.push(i);
}
return rangeArray;
}
const rangeInclusive = (from, to) => {
const rangeArray = rangeExclusive(from, to);
rangeArray.push(to);
return rangeArray;
};
function rangeInclusive(from, to) {
var rangeArray = rangeExclusive(from, to);
rangeArray.push(to);
return rangeArray;
}
function iterateNodeList(nodeList, fun) {
for (var i = 0; i < nodeList.length; i++) {
var node = nodeList.item(i);
fun(node);
}
}
const iterateNodeList = (nodeList, fun) => {
for (let i = 0; i < nodeList.length; i++) {
const node = nodeList.item(i);
fun(node);
}
};
//////
///
/// Input
///
//////
//////
///
/// Input
///
//////
var inputTable = {};
const inputTable = {};
// Functions
inputTable.getTable = function() {
return document.querySelector("#dieSettings tbody");
};
// Functions
inputTable.getTable = () => document.querySelector("#dieSettings tbody");
inputTable.highestDieRowIndex = function() {
var table = inputTable.getTable();
inputTable.highestDieRowIndex = () => {
const table = inputTable.getTable();
var highestDieRowIndex = -1;
iterateNodeList(table.getElementsByTagName("tr"), (node) => {
if (!isNaN(node.dataset.index)) {
highestDieRowIndex = Math.max(highestDieRowIndex, node.dataset.index);
}
});
let highestDieRowIndex = -1;
iterateNodeList(table.getElementsByTagName("tr"), (node) => {
if (!isNaN(node.dataset.index))
highestDieRowIndex = Math.max(highestDieRowIndex, node.dataset.index);
});
return highestDieRowIndex;
};
return highestDieRowIndex;
};
inputTable.addDieRow = function() {
function createNumberInput(index, className, value) {
var input = document.createElement("input");
input.id = className + index;
input.className = className;
input.type = "number";
input.min = 1;
input.step = 1;
input.value = value;
input.addEventListener("keypress", (e) => {
if (e.key == "Enter") {
updateProbGraph();
}
});
input.focus();
return input;
}
inputTable.addDieRow = () => {
const createNumberInput = (index, className, value) => {
const input = document.createElement("input");
input.id = className + index;
input.className = className;
input.type = "number";
input.min = 1;
input.step = 1;
input.value = value;
input.addEventListener("keypress", (e) => {
if (e.key === "Enter")
outputChart.updateProbGraph();
});
input.focus();
return input;
};
function createRemoveLink(index, className) {
var link = document.createElement("button");
link.id = className + index;
link.className = className + " button-clear";
link.type = "button";
link.innerHTML = "Remove";
link.onclick = (() => inputTable.removeDieRow(index));
return link;
}
const createRemoveLink = (index, className) => {
const link = document.createElement("button");
link.id = className + index;
link.className = className + " button-clear";
link.type = "button";
link.innerHTML = "Remove";
link.onclick = (() => inputTable.removeDieRow(index));
return link;
};
var table = inputTable.getTable();
var newIndex = inputTable.highestDieRowIndex() + 1;
const table = inputTable.getTable();
const newIndex = inputTable.highestDieRowIndex() + 1;
var row = table.insertRow(newIndex);
row.dataset.index = newIndex;
const row = table.insertRow(newIndex);
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, "dieEyes", 6));
row.insertCell().appendChild(createNumberInput(newIndex, "dieCount", 2));
row.insertCell().appendChild(createRemoveLink(newIndex, "dieRemove"));
};
inputTable.removeDieRow = function(index) {
if (inputTable.highestDieRowIndex() > 0) {
var table = inputTable.getTable();
var row = table.querySelector("tr[data-index=\"" + index + "\"]");
row.parentElement.removeChild(row);
}
};
inputTable.removeDieRow = index => {
if (inputTable.highestDieRowIndex() > 0) {
const table = inputTable.getTable();
const row = table.querySelector("tr[data-index=\"" + index + "\"]");
row.parentElement.removeChild(row);
}
};
inputTable.getDice = function() {
var dice = [];
inputTable.getDice = () => {
const dice = [];
var eyesInputs = document.getElementsByClassName("dieEyes");
var countInputs = document.getElementsByClassName("dieCount");
for (var i = 0; i < eyesInputs.length; i++) {
var count = parseInt(countInputs.item(i).value);
const eyesInputs = document.getElementsByClassName("dieEyes");
const countInputs = document.getElementsByClassName("dieCount");
for (let i = 0; i < eyesInputs.length; i++) {
const count = parseInt(countInputs.item(i).value);
for (var j = 0; j < count; j++) {
dice.push(parseInt(eyesInputs.item(i).value));
}
}
for (let j = 0; j < count; j++)
dice.push(parseInt(eyesInputs.item(i).value));
}
return dice;
};
return dice;
};
// Handlers
document.getElementById("addDieRowButton").onclick = inputTable.addDieRow;
// Handlers
document.getElementById("addDieRowButton").onclick = inputTable.addDieRow;
// Init
addOnLoad(() => document.getElementById("addDieRowButton").click());
// Init
doAfterLoad(() => document.getElementById("addDieRowButton").click());
//////
///
/// Output
///
//////
//////
///
/// Output
///
//////
var outputChart = {};
const outputChart = {};
// Functions
outputChart.calculateDiceFrequencies = function(dice) {
if (dice.length == 0) {
return [];
}
// Functions
outputChart.calculateDiceFrequencies = dice => {
if (dice.length === 0)
return [];
// Roll dice
var rollFreqs = [0].concat(repeat(1, dice[0]));
dice.slice(1).forEach(die => {
var dieRollFreqs = rollFreqs.concat(repeat(0, die));
rollFreqs = repeat(0, dieRollFreqs.length);
// Roll dice
let rollFreqs = [0].concat(repeat(1, dice[0]));
dice.slice(1).forEach(die => {
const dieRollFreqs = rollFreqs.concat(repeat(0, die));
rollFreqs = repeat(0, dieRollFreqs.length);
rangeInclusive(1, die).forEach(throwValue => {
rangeExclusive(1, dieRollFreqs.length - die).forEach(i => {
rollFreqs[throwValue + i] += dieRollFreqs[i];
});
});
});
rollFreqs.shift();
rangeInclusive(1, die).forEach(throwValue => {
rangeExclusive(1, dieRollFreqs.length - die).forEach(i => {
rollFreqs[throwValue + i] += dieRollFreqs[i];
});
});
});
rollFreqs.shift();
// Calculate frequencies
var totalRolls = rollFreqs.reduce((a, b) => a + b, 0);
rangeExclusive(0, rollFreqs.length).forEach(roll => {
rollFreqs[roll] = rollFreqs[roll] / totalRolls;
});
// Calculate frequencies
const totalRolls = rollFreqs.reduce((a, b) => a + b, 0);
rangeExclusive(0, rollFreqs.length).forEach(roll => {
rollFreqs[roll] = rollFreqs[roll] / totalRolls;
});
return rollFreqs;
};
return rollFreqs;
};
outputChart.updateProbGraph = function() {
var dice = inputTable.getDice();
var rollFreqs = outputChart.calculateDiceFrequencies(dice);
outputChart.updateProbGraph = () => {
const dice = inputTable.getDice();
const rollFreqs = outputChart.calculateDiceFrequencies(dice);
probChart.data.labels = rangeInclusive(1, rollFreqs.length);
probChart.data.datasets = [{
data: rollFreqs,
backgroundColor: "rgb(155, 77, 202, 0.4)"
}];
probChart.update();
};
probChart.data.labels = rangeInclusive(1, rollFreqs.length);
probChart.data.datasets = [{
data: rollFreqs,
backgroundColor: "rgb(155, 77, 202, 0.4)"
}];
probChart.update();
};
// Handlers
document.getElementById("submit").onclick = outputChart.updateProbGraph;
// Handlers
document.getElementById("submit").onclick = outputChart.updateProbGraph;
// Init
var ctx = document.getElementById("probChart").getContext("2d");
var probChart = new Chart(ctx, {
type: "line",
data: {},
options: {
legend: {
display: false
},
scales: {
yAxes: [{
display: true,
ticks: {
suggestedMin: 0
}
}]
}
}
});
// Init
const ctx = document.getElementById("probChart").getContext("2d");
const probChart = new Chart(ctx, {
type: "line",
data: {},
options: {
legend: {
display: false
},
scales: {
yAxes: [{
display: true,
ticks: {
suggestedMin: 0
}
}]
}
}
});
addOnLoad(() => document.getElementById("submit").click());
</script>
doAfterLoad(() => document.getElementById("submit").click());
</script>
</body>
</html>