JSFiddle - React, Tailwind, and code Playground
HTML
<div id="ctr">
<div id="left">
<canvas height="729" width="729" style="height: 729px; width: 729px;" id="c"></canvas>
</div>
<div id="right">
<table>
<thead>
<tr>
<th>X</th>
<th>Y</th>
<th>Color</th>
<th>Delete</th>
</tr>
</thead>
<tbody id="candidates-ctr">
</tbody>
</table>
<div>
<button id="add-candidate">Add Candidate</button>
</div>
<div>
<button id="run-sim">Run Sim</button>
</div>
<div>
<button id="stop-sim">Stop Sim</button>
</div>
<div>
<label for="depth-ipt">Depth</label>
<input type="number" min="1" max="6" id="depth-ipt" value="5" />
</div>
<div>
<label for="nvoters-ipt">Num Voters</label>
<input type="number" min="1" max="1000000" id="nvoters-ipt" value="10000" />
</div>
<div>
<label for="sigma-ipt">Standard Deviation of Voter Position</label>
<input type="number" min="0" max="10" step="0.001" id="sigma-ipt" value="0.5" />
</div>
</div>
</div>
CSS
#ctr {
position: relative;
}
#left {
position: absolute;
left: 0%;
width: 50%;
}
#right {
position: absolute;
left: 50%;
width: 50%;
}
table {
width: 100%;
border-collapse: collapse;
}
td,
th {
border: 1px solid black;
}
JavaScript
var canvas, context, candidates, queue, job, depth, nVoters, sigma;
function addCandidateRow(candidates, i) {
var candidate = candidates[i];
var ctr = document.getElementById('candidates-ctr');
var row = document.createElement('tr');
var xCtr = document.createElement('td');
var xIpt = document.createElement('input');
xIpt.setAttribute('type', 'number');
xIpt.setAttribute('step', '0.01');
xIpt.setAttribute('min', '-0.25');
xIpt.setAttribute('max', '0.25');
xIpt.setAttribute('value', candidate[0]);
xIpt.addEventListener('change', e => candidate[0] = parseFloat(e.target.value));
var yCtr = document.createElement('td');
var yIpt = document.createElement('input');
yIpt.setAttribute('type', 'number');
yIpt.setAttribute('step', '0.01');
yIpt.setAttribute('min', '-0.25');
yIpt.setAttribute('max', '0.25');
yIpt.setAttribute('value', candidate[1]);
yIpt.addEventListener('change', e => candidate[1] = parseFloat(e.target.value));
var colorCtr = document.createElement('td');
var colorIpt = document.createElement('input');
colorIpt.setAttribute('type', 'color');
colorIpt.setAttribute('value', candidate[2]);
colorIpt.addEventListener('change', e => candidate[2] = e.target.value);
var delCtr = document.createElement('td');
var delBtn = document.createElement('button');
delBtn.textContent = 'Delete';
delBtn.addEventListener('click', e => {
candidates.splice(i, 1);
ctr.removeChild(row);
});
xCtr.appendChild(xIpt);
yCtr.appendChild(yIpt);
colorCtr.appendChild(colorIpt);
delCtr.appendChild(delBtn);
row.appendChild(xCtr);
row.appendChild(yCtr);
row.appendChild(colorCtr);
row.appendChild(delCtr);
ctr.appendChild(row);
}
function fillCell(resolution, x, y, color) {
context.fillStyle = color;
var size = 729 / (3 ** resolution);
var tileX = Math.floor(x * 3 ** resolution) * size;
var tileY =...