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;
      }...