JSFiddle - React, Tailwind, and code Playground
by blackjet3
HTML
<fieldset>
<label>Regular Token Draw <input type="checkbox" id="regular" value="1" checked></label>
<label>1x Grotesque Statue <input type="checkbox" id="grotesque" value="1"></label>
<label>2x Grotesque Statue <input type="checkbox" id="grotesquex2" value="1"></label>
<label>Olive McBride <input type="checkbox" id="olive" value="1" checked></label>
<label>Olive McBride into Grotesque Statue <input type="checkbox" id="olivegrotesque" value="1"></label>
<label>Grotesque Statue into Olive McBride <input type="checkbox" id="grotesqueolive" value="1"></label>
<hr>
<label>Olive McBride (2)<input type="checkbox" id="olive2" value="1" checked></label>
<label>Commit 1 Icon <input type="checkbox" id="plus1" value="1"></label>
<label>Commit 2 Icons <input type="checkbox" id="plus2" value="1"></label>
<label>Jacqueline Fine <input type="checkbox" id="jacqueline" value="1"></label>
<label>Jacqueline Fine and Olive McBride <input type="checkbox" id="olivejacqueline" value="1"></label>
<label>Jacqueline Fine and Olive McBride (2) <input type="checkbox" id="olive2jacqueline" value="1"></label>
</fieldset>
<label>Token Bag: <textarea id="tokens"># numbered tokens
+1
0 x3
-1
-2 x2
-3
-5
# icon tokens
-2 Skull x2
-3 Squid
# auto fail and pass tokens
-999 Cthulhu
-1 Elder Sign # Replace with 999 for Father Mateo's auto-success</textarea></label>
<label>Number of Test Runs: <input id="testCnt" value="10000"></label>
<button id="doMath">Draw tokens and plot graph!</button>
<div id="explanation">
<p>
<strong>How to read this chart:</strong> On the x-axis you have a list of modifiers. The question you should ask is: "I can beat a modifier of X, how likely is it that I will succeed?"
</p>
<p>
<strong>Example:</strong> If you are doing a skill test with a difficulty of 4 and you have a skill value of 6 (including all modifiers), the question is: "I can beat a modifier of -2, how likely is it that I will succeed?" - looking at the chart you will...
CSS
fieldset {
float: right;
width: 49%;
box-sizing: border-box;
}
fieldset label {
width: 100%;
}
label {
width: 49%;
text-align: right;
display: inline-block;
}
label > *:not([type="checkbox"]) {
width: calc(100% - 150px);
box-sizing: border-box;
}
textarea {
height: 200px;
vertical-align: top;
}
#results {
white-space: pre;
}
JavaScript
google.charts.load('current', {'packages':['corechart']});
const ta = document.getElementById('tokens');
const res = document.getElementById('results');
const testCnt = document.getElementById('testCnt');
const tokenModifiersForm = {
regular: document.getElementById('regular'),
grotesque: document.getElementById('grotesque'),
grotesquex2: document.getElementById('grotesquex2'),
olive: document.getElementById('olive'),
olive2: document.getElementById('olive2'),
olivegrotesque: document.getElementById('olivegrotesque'),
grotesqueolive: document.getElementById('grotesqueolive'),
plus1: document.getElementById('plus1'),
plus2: document.getElementById('plus2'),
jacqueline: document.getElementById('jacqueline'),
olivejacqueline: document.getElementById('olivejacqueline'),
olive2jacqueline: document.getElementById('olive2jacqueline'),
}
document.getElementById('doMath').addEventListener('click', () => {
let tokens = ta.value.replace(/ *(#.*)?$/gm, '') // remove comments
.replace(/^\n/gm, '') // remove empty lines
.split('\n'); // convert to array
// any token that has 'x2' (or any other number) appended should be multiplied by that amount
// split token value and token name (if any)
for (let i = 0, regex = /^([+-]?\d+) *(.*?) *(?:x(\d+))?$/; i < tokens.length; i++) {
let match = regex.exec(tokens[i]);
if (match[3]) {
for (let j = 1; j < match[3]; j++) {
tokens.push(match[1]);
}
}
tokens[i] = {
value: match[1] * 1,
label: match[2] || match[1]
};
}
let data = [];
let labels = [];
// accumulate test data for regular drawing
if (tokenModifiersForm.regular.checked) {
data.unshift({});
labels.unshift(tokenModifiersForm.regular.parentNode.innerText);
for (let i = 0; i < testCnt.value; i++) {
let value = tokens[Math.floor(Math.random() * tokens.length)].value;
if (isNaN(data[0][value])) {
data[0][value] = 1;
}...