Skip to content

Instantly share code, notes, and snippets.

@avimoondra
Last active August 29, 2015 14:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save avimoondra/ab99e72ffa2e44a64f11 to your computer and use it in GitHub Desktop.
Save avimoondra/ab99e72ffa2e44a64f11 to your computer and use it in GitHub Desktop.
Simulation Study
<!DOCTYPE html>
<html lang="en">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
<script src="http://d3js.org/d3.v3.min.js"></script>
<link rel="stylesheet" href="https://code.jquery.com/ui/1.11.2/themes/smoothness/jquery-ui.css">
<script src="https://code.jquery.com/ui/1.11.2/jquery-ui.min.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta charset="utf-8">
</head>
<body>
<style type="text/css">
*:focus {
outline: 0;
}
#svgWrapper {
display: inline-block;
}
#panelWrapper {
width: 475px;
border: solid #808080 1px;
padding: 10px;
display: inline-block;
position: fixed;
margin-top: 10px;
}
.separator {
margin-bottom: 10px;
height: 1px;
background-color: #808080;
}
#sliderWrapper {
width: 420px;
display: inline-block;
}
#slider {
margin-left: 12px;
margin-right: 10px;
}
#simulation-step5-playButton{
width: 22px;
}
.table-line {
stroke: black;
width: 1px;
}
.table-title {
font-weight: bold;
font-size: 20px;
}
.math-line {
stroke: black;
width: 1px;
}
.sim-label {
font: 13px Monaco;
}
#currentSimIndex {
opacity: 0.3;
font-size: 20px;
}
svg {
font: 15px sans-serif;
}
svg .card--inactive {
opacity: 0.5;
}
svg .dot--hidden {
opacity: 0;
}
svg .infobox--hidden {
opacity: 0;
}
svg .card.promoted {
stroke: #F05133;
}
svg .card.notPromoted {
stroke: #569BBD;
}
svg .axis path,
svg .axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
#maleSimPromoted {
opacity: 1;
}
#pValueCalculationBorder{
fill: white;
stroke: black;
stroke-width: 1;
opacity: 0.95;
}
</style>
<div>
<div id="svgWrapper">
<svg width="700" height="700">
<g id="experimentTable" transform="translate(30,30)">
<text class="table-title" x="60" y="30"> Observed </text>
<text x="180" y="30">
<tspan x="180">promoted</tspan>
<tspan x="260">not promoted</tspan>
<tspan x="360">Total</tspan>
</text>
<text x="80" y="50">
<tspan x="120">male </tspan>
<tspan x="180" >21</tspan>
<tspan x="260">3</tspan>
<tspan x="360">24</tspan>
</text>
<text x="80" y="70">
<tspan x="107">female</tspan>
<tspan x="180" >14</tspan>
<tspan x="260">10</tspan>
<tspan x="360">24</tspan>
</text>
<text x="80" y="90">
<tspan x="117">Total</tspan>
<tspan x="180" >35</tspan>
<tspan x="260">13</tspan>
<tspan x="360">48</tspan>
</text>
<line class="table-line" x1="60" y1="75" x2="410" y2="75"></line>
<line class="table-line" x1="355" y1="0" x2="355" y2="100"></line>
</g>
<g id="experimentMath" transform="translate(500,100)">
<text x="0" y="0">
<tspan x="0" y="0"> 21 </tspan>
<tspan x="0" y="1.5em"> 24</tspan>
</text>
<text x="3em" y="0">
<tspan x="3em" y="0"> 14 </tspan>
<tspan x="3em" y="1.5em"> 24</tspan>
</text>
<text x="5em" y="9">
= 0.292
</text>
<text x="-10" y="-30"> Observed Difference </text>
<line class="math-line" x1="0" y1="6" x2="17" y2="6"></line>
<line class="math-line" x1="26" y1="6" x2="35" y2="6"></line>
<line class="math-line" x1="45" y1="6" x2="62" y2="6"></line>
</g>
<g id="simulationTable" transform="translate(30,230)">
<text x="17" y="30" id="currentSimIndex"></text>
<text class="table-title" x="55" y="30"> Simulated </text>
<text x="180" y="30">
<tspan x="360">Total</tspan>
<tspan x="180">promoted</tspan>
<tspan x="260">not promoted</tspan>
</text>
<text x="80" y="50">
<tspan class="sim-label" x="87">male_sim</tspan>
<tspan class="simulation-text-component" id="maleSimPromoted" x="180" ></tspan>
<tspan class="simulation-text-component" id="maleSimNotPromoted" x="260"></tspan>
<tspan id="totalMale" x="360">24</tspan>
</text>
<text x="80" y="70">
<tspan class="sim-label" x="72">female_sim</tspan>
<tspan class="simulation-text-component" id="femaleSimPromoted" x="180" ></tspan>
<tspan class="simulation-text-component" id="femaleSimNotPromoted" x="260"></tspan>
<tspan id="totalFemale" x="360">24</tspan>
</text>
<text x="80" y="90">
<tspan x="117">Total</tspan>
<tspan id="totalPromoted" x="180" >35</tspan>
<tspan id="totalNotPromoted" x="260">13</tspan>
<tspan id="totalFemale" x="360">48</tspan>
</text>
<line class="table-line" x1="60" y1="75" x2="410" y2="75"></line>
<line class="table-line" x1="355" y1="0" x2="355" y2="100"></line>
</g>
<g id="simulationMath" transform="translate(500,300)">
<text x="0" y="0">
<tspan class="simulation-text-component" id="male-numerator" x="0" y="0"> </tspan>
<tspan x="0" y="1.5em"> 24</tspan>
</text>
<line x1="0" y1="6" x2="20" y2="6"></line>
<text x="3em" y="0">
<tspan class="simulation-text-component" id="female-numerator" x="3em" y="0"> </tspan>
<tspan x="3em" y="1.5em"> 24</tspan>
</text>
<text class="simulation-text-component" id="simulatedDifference" x="5em" y="9"></text>
<text x="-10" y="-30"> Simulated Difference </text>
<line class="math-line" x1="0" y1="6" x2="17" y2="6"></line>
<line class="math-line" x1="26" y1="6" x2="35" y2="6"></line>
<line class="math-line" x1="45" y1="6" x2="62" y2="6"></line>
</g>
<g id="pValueCalculationWrapper" class="infobox--hidden" transform="translate(300,355)">
<rect id="pValueCalculationBorder" x="0" y="10" width="350" height="75"></rect>
<g transform="translate(0,50)">
<text x="10" y="0"> p-value ≈ </text>
<g transform="translate(80,-10)">
<text x="0" y="0"> #(difference ≥ 0.292) </text>
<line class="math-line" x1="0" y1="6" x2="145" y2="6"></line>
<text x="20" y="20"> # simulations</text>
</g>
<g transform="translate(250,-10)">
<text id="pValueNumeratorCounter" x="7" y="0"> </text>
<line class="math-line" x1="0" y1="6" x2="25" y2="6"></line>
<text x="0" y="20"> 100 </text>
</g>
<g transform="translate(234,0)">
<text x="0" y="0"> = </text>
</g>
<g transform="translate(285,0)">
<text > = </text>
<text x="15" id="pValueCalculation"> </text>
</g>
</g>
</g>
</svg>
</div>
<div id="panelWrapper">
<p> <b> Simulation </b></p>
<p>
Simulate the experiment 100 times under the assumption that the null hypothesis is true, i.e. assuming there is no gender bias. Use a deck of 48 cards, each representing one resume in the study. 35 of these cards are red, representing <font color="#F05133">promoted</font> candidates, and 13 are blue, representing <font color="#569BBD"> NOT promoted </font> candidates. <button id="simulation-step0" type="button" class="btn btn-primary btn-xs"> Generate Deck </button>
<p><b> Step 1. </b> Shuffle the deck. <button id="simulation-step1" type="button" class="btn btn-primary btn-xs disabled"> Shuffle </button></p>
<p><b> Step 2. </b> Split into 2 piles of 24 as to represent the completely random, non-biased promotion decisions for the 24 males and 24 females. <button id="simulation-step2" type="button" class="btn btn-primary btn-xs disabled"> Split </button></p>
<p><b> Step 3. </b> Compute the difference in promotion rates between males and females. To do this: count the number of red cards in each pile of 24, calculate the proportion of such files in each pile, and compute the difference. <button id="simulation-step3-1" type="button" class="btn btn-primary btn-xs disabled"> Fill Table </button> <button id="simulation-step3-2" type="button" class="btn btn-primary btn-xs disabled"> Count </button> <button id="simulation-step3-3" type="button" class="btn btn-primary btn-xs disabled"> Compute </button> </p>
<p><b> Step 4. </b> Record this value on the dot plot. <button id="simulation-step4" type="button" class="btn btn-primary btn-xs disabled"> Record </button> </p>
<p><b> Step 5. </b> Repeat Steps (1)-(4) 100 times.
<div id="step4buttonWrapper">
<button id="simulation-step5-playButton" type="button" class="btn btn-primary btn-xs disabled"> ► </button>
<div id="sliderWrapper"><div id="slider"></div></div>
</div>
</p>
<div class="separator"></div>
<p> <b> Results </b> </p>
<p>The dot plot shows the distribution of simulated differences. We want to compare the data from the original experiment to this distribution of simulated differences in order to gauge the likelihood of obtaining such a result if in fact the null hypothesis is true. <button id="simulation-plotOriginal" type="button" class="btn btn-primary btn-xs disabled"> Mark original data on plot </button> Does the original observation appear to be a likely outcome? How likely is it to obtain differences at least as extreme as the original difference if in fact the null hypothesis is true?
<button id="simulation-pValue" type="button" class="btn btn-primary btn-xs disabled"> Calculate p-value </button>
</p>
</div>
</div>
<script>
exp = {};
exp.total = 48;
exp.totalPromoted = 35;
exp.totalNotPromoted = exp.total - exp.totalPromoted;
exp.totalMale = exp.total/2;
exp.totalFemale = exp.total/2;
exp.differenceInPromotionRates = 21/exp.totalMale - 14/exp.totalFemale;
sim = {};
sim.total = 100;
simulations = Array(sim.total);
currentSimIndex = 0;
svg = d3.select("svg");
function shuffle(array) {
var n = array.length, t, i;
while (n) {
i = Math.random() * n-- | 0; // 0 ≤ i < n
t = array[n];
array[n] = array[i];
array[i] = t;
}
return array;
}
var generateData = function(){
data = d3.range(exp.total);
for(var i = 0; i < sim.total; i++){
data = shuffle(data);
males = data.slice(0,exp.totalMale);
females = data.slice(exp.totalMale,exp.total);
simData = [];
for(var j = 0; j < data.length; j++){
simDataPoint = {
"unshuffledIndex": data[j],
"shuffledIndex": j,
"status": (function(index){
if(data[index] < 35){
return "promoted";
}
return "notPromoted";
})(j),
"gender": (function(index){
if(index < exp.totalMale){
return "male";
}
return "female";
})(j)
}
simData.push(simDataPoint);
}
maleSimPromoted = males.filter(function(element) {return element < 35}).length;
maleSimNotPromoted = exp.totalMale - maleSimPromoted;
femaleSimPromoted = exp.totalPromoted - maleSimPromoted;
femaleSimNotPromoted = exp.totalFemale - femaleSimPromoted;
simulationObject = {
"simData": simData,
"simMales": males,
"simFemales": females,
"maleSimPromoted": maleSimPromoted,
"maleSimNotPromoted": maleSimNotPromoted,
"femaleSimPromoted": femaleSimPromoted,
"femaleSimNotPromoted": femaleSimNotPromoted
}
simulations[i] = simulationObject;
}
}
generateData();
// TODO: scale dataPointRadius to match height of tallest tower to total graph height
plot = {}
plot.width = 500;
plot.height = 600;
plot.marginLeftOffset = 100;
plot.xAxisLabelOffset = 45;
plot.dataPointRadius = 3;
plot.dataPointSpacing = 2.5;
plot.towers = {};
plot.towerOffset = 10;
plot.towerStart = plot.height - plot.towerOffset;
var initDotPlot = function(){
differences = [];
simulations.forEach(function(simulation, index){
difference = simulation.maleSimPromoted/exp.totalMale - simulation.femaleSimPromoted/exp.totalFemale;
differences.push(difference);
})
var x = d3.scale.linear()
.domain([d3.min(differences),Math.max(d3.max(differences), exp.differenceInPromotionRates)]).nice()
.range([0, plot.width]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(100," + plot.height+ ")")
.call(xAxis)
.append("text")
.attr("class", "label graph-component")
.attr("x", plot.width/2)
.attr("y", plot.xAxisLabelOffset)
.style("text-anchor", "middle")
.text("Difference in Promotion Rates");
datapoints = svg.append("g")
.attr("class","datapoint-wrapper");
simIndex = 0;
datapoints.selectAll(".datapoint")
.data(differences)
.enter()
.append("circle")
.attr("class", function(d){
base = "datapoint graph-component dot--hidden"
if(d >= exp.differenceInPromotionRates){
return base + " pValue"
}
return base;
})
.attr("id", function(){
return "datapoint-" + (simIndex++);
})
.attr("r", plot.dataPointRadius)
.attr("cx", function(d) { return x(d) + plot.marginLeftOffset; })
svg.selectAll(".datapoint").each(function(d, i){
if(plot.towers.hasOwnProperty(d)){
d3.select(this).attr("cy", plot.towerStart - plot.dataPointSpacing * plot.dataPointRadius * plot.towers[d])
plot.towers[d] = plot.towers[d] + 1;
} else {
d3.select(this).attr("cy", plot.towerStart)
plot.towers[d] = 1;
}
});
datapoints.append("circle")
.attr("class", "datapoint graph-component experiment dot--hidden")
.attr("r", plot.dataPointRadius)
.attr("cx", x(exp.differenceInPromotionRates) + plot.marginLeftOffset)
.attr("cy", plot.height)
.style("fill","#F05133");
datapoints.append("circle")
.attr("class","datapoint graph-component experiment outlined dot--hidden")
.attr("r", plot.dataPointRadius+2)
.attr("cx", x(exp.differenceInPromotionRates) + plot.marginLeftOffset)
.attr("cy", plot.height)
.style("stroke","#F05133")
.style("fill","none")
}
initDotPlot();
var slideFunction = function(event, ui){
currentSimIndex = ui.value;
for(i = 0; i < 100; i++){
selection = d3.selectAll("#datapoint-" + i);
if(i < currentSimIndex){
selection.classed("dot--hidden", false);
} else {
selection.classed("dot--hidden", true);
}
}
pause();
stepForward(function(){})
}
var initSlider = function(){
$( "#slider" ).slider({
disabled: true,
max: 99,
min: 0,
step: 1,
slide: slideFunction
});
}
initSlider();
cardDeck = {};
cardDeck.height = 20;
cardDeck.width = 150;
cardDeck.scale = d3.scale.ordinal()
.domain(d3.range(exp.total))
.rangePoints([0, cardDeck.width]);
function shuffleTransform(d, i) {
return "translate(" + cardDeck.scale(d.shuffledIndex) + "," + cardDeck.height + ")";
}
function unshuffledTransform(d, i){
return "translate(" + cardDeck.scale(d.unshuffledIndex) + "," + cardDeck.height + ")";
}
var updateSimIndexCounter = function() {
svg.select("#currentSimIndex")
.text(function(){
displayNum = currentSimIndex + 1;
if(displayNum < 10){
return "00" + displayNum
} else if(displayNum < 100) {
return "0" + displayNum
}
return displayNum;
}())
}
var step0 = function(){
var cards = svg.append("g")
.attr("class","unshuffled-deck simulation-component")
.attr("transform","translate(200,170)") //TODO magic numbers
.selectAll("line")
.data(simulations[currentSimIndex].simData)
.enter().append("line")
.attr("class", function(d,i) {
return "card " + d.status + " " + d.gender;
})
.attr("transform", unshuffledTransform)
.attr("y2", -cardDeck.height);
updateSimIndexCounter();
}
var step1 = function(duration, callback){
var deck = d3.selectAll(".card");
d3.transition()
.each(function(){
deck.transition()
.duration(duration)
.attr("transform", shuffleTransform)
})
.transition()
.each("end", callback);
}
function clone(selector) {
var node = d3.select(selector).node();
return d3.select(node.parentNode.insertBefore(node.cloneNode(true), node.nextSibling));
}
function cloneAll(selector) {
var nodes = d3.selectAll(selector);
nodes.each(function(d, i) {
nodes[0][i] = this.parentNode.insertBefore(this.cloneNode(true), this.nextSibling);
});
return nodes;
}
function getTransformCoords(transformText){
x = parseFloat(transformText.substring(transformText.indexOf("(") + 1,transformText.indexOf(",")));
y = parseFloat(transformText.substring(transformText.indexOf(",") + 1,transformText.indexOf(")")));
return {"x": x, "y": y}
}
//TODO magic numbers
var step2 = function(duration, callback){
var deck = cloneAll(".unshuffled-deck")
.classed("unshuffled-deck", false)
.classed("shuffled-deck", true);
svg.selectAll(".unshuffled-deck>line")
.classed("card--inactive", true)
var males = deck.selectAll(".male")
var females = deck.selectAll(".female");
duration = duration/2;
d3.transition()
.duration(duration)
.each(function(){
males.transition()
.attr("transform", function(){
transformText = d3.select(this).attr("transform");
coords = getTransformCoords(transformText);
return "translate(" + (coords.x - 10) + "," + (coords.y + 30) + ")";
});
})
.transition()
.each(function(){
females.transition()
.attr("transform", function(){
transformText = d3.select(this).attr("transform");
coords = getTransformCoords(transformText);
return "translate(" + (coords.x + 10) + "," + (coords.y + 30) + ")";
});
})
.transition()
.each("end", callback);
}
var fillTable = function(duration, callback){
var deck= cloneAll(".shuffled-deck")
.classed("shuffled-deck", false)
.classed("split-shuffled-deck", true);
svg.selectAll(".shuffled-deck>line")
.classed("card--inactive", true);
var promotedMales = deck.selectAll(".male.promoted");
var notPromotedMales = deck.selectAll(".male.notPromoted");
var promotedFemales = deck.selectAll(".female.promoted");
var notPromotedFemales = deck.selectAll(".female.notPromoted");
var fillTableCell = function(selection, startX, startY){
return function(){
selection.transition()
.attr("transform", function(d, i){
transformText = d3.select(this).attr("transform");
coords = getTransformCoords(transformText);
return "translate(" + (startX + i*2) + "," + (coords.y + startY) + ")";
});
}
}
// TODO magic numbers
duration = duration/4;
d3.transition()
.duration(duration)
.each(fillTableCell(promotedMales, 30, 60))
.transition()
.each(fillTableCell(notPromotedMales, 120, 60))
.transition()
.each(fillTableCell(promotedFemales, 30, 85))
.transition()
.each(fillTableCell(notPromotedFemales, 120, 85))
.transition()
.each("end", callback);
}
var countCards = function(duration, callback){
d3.transition()
.duration(duration)
.each(function(){
simulation = simulations[currentSimIndex];
d3.select("#maleSimPromoted").transition()
.text(simulation.maleSimPromoted)
d3.select("#femaleSimPromoted").transition()
.text(simulation.femaleSimPromoted);
d3.select("#maleSimNotPromoted").transition()
.text(simulation.maleSimNotPromoted);
d3.select("#femaleSimNotPromoted").transition()
.text(simulation.femaleSimNotPromoted);
})
.transition()
.each("end", callback);
}
var computeDifference = function(duration, callback){
d3.transition()
.duration(duration)
.each(function(){
simulation = simulations[currentSimIndex];
d3.select("#male-numerator")
.text(simulation.maleSimPromoted);
d3.select("#female-numerator")
.text(simulation.femaleSimPromoted);
differenceText = simulation.maleSimPromoted/exp.totalMale - simulation.femaleSimPromoted/exp.totalFemale + "";
differenceText = differenceText.substring(0, Math.min(differenceText.indexOf(".") + 4, differenceText.length));
d3.select("#simulatedDifference")
.text("= " + differenceText);
})
.transition()
.each("end", callback)
}
var step3 = function(duration, callback){
fillTable(duration, function(){
countCards(duration, function(){
computeDifference(duration, function(){
callback();
});
});
});
}
var step4 = function(callback){
$("#slider").slider("value", currentSimIndex);
d3.select("#datapoint-" + currentSimIndex)
.classed("dot--hidden", false)
callback();
}
var step5 = function(){
d3.selectAll(".simulation-component").remove();
d3.selectAll(".simulation-text-component").text("");
step0(currentSimIndex);
}
var resetSimulation = step5;
var plotOriginalExperiment = function(){
d3.selectAll(".datapoint.experiment")
.classed("dot--hidden",false);
}
var stepForward = function(callback, duration){
resetSimulation();
step1(100, function(){
step2(100, function(){
step3(300, function(){
step4(callback);
})
})
});
}
paused = false;
var pause = function(){
button = $("#simulation-step5-playButton");
button.removeClass("playing");
button.text("►")
paused = true;
}
var resume = function(){
button = $("#simulation-step5-playButton");
button.addClass("playing");
button.text("II")
paused = false;
play();
}
var play = function(){
if(currentSimIndex == 100 || paused) return;
stepForward(function(){
currentSimIndex++;
play();
});
}
var pValueAnimation = function(){
if($("#slider").slider("value") != (sim.total - 1)){
$("#slider").slider("value", (sim.total - 1))
slideFunction({}, {"value": (sim.total - 1)})
}
var infobox = svg.select("#pValueCalculationWrapper").remove()
console.log(infobox)
svg.append(function(){
return infobox[0][0]
}).classed("infobox--hidden", false);
start = svg.select(".experiment.outlined")
startX = start.attr("cx") - start.attr("r");
startY = plot.height;
maxTowerHeight = function(){
currMax = 0;
for (var property in plot.towers){
if (plot.towers.hasOwnProperty(property)){
if(parseFloat(property) >= exp.differenceInPromotionRates){
if(parseFloat(plot.towers[property]) > currMax){
currMax = parseFloat(plot.towers[property]);
}
}
}
}
return (currMax != 0 ? currMax : 0) * plot.dataPointSpacing * plot.dataPointRadius
+ plot.towerOffset;
}
var path = d3.select(".datapoint-wrapper").append("path")
.attr("d","M" + startX + " " + startY + " h -5 v -" + maxTowerHeight() +" h 5")
.attr("fill", "none")
.attr("stroke", "#F05133")
.attr("stroke-width","1.5");
var totalLength = path.node().getTotalLength();
path
.attr("stroke-dasharray", totalLength + " " + totalLength)
.attr("stroke-dashoffset", totalLength)
.transition()
.duration(1000)
.ease("linear")
.attr("stroke-dashoffset", 0)
.transition()
.each("end", function(){
var pValuePoints = cloneAll(".pValue")
.classed("pValue",false)
.classed("pValueAnimate", true);
svg.selectAll(".pValue")
.style("opacity", 0.5);
counter = 0;
counterEl = svg.select("#pValueNumeratorCounter").text(counter);
pValuePoints.transition()
.duration(1000)
.delay(function(d, i){
return i * 100;
})
.attr("cx", 565)
.attr("cy", 390)
.each("end", function(){
counter++;
return counterEl.text(counter);
})
.transition()
.each("end",function(){
num = parseFloat(svg.select("#pValueNumeratorCounter").text());
denom = parseFloat(sim.total);
svg.select("#pValueCalculation").transition().text(num/denom)
});
});
}
d3.select("#simulation-step0").on("click", function(){
step0();
d3.select("#simulation-step0").classed("disabled", true)
d3.select("#simulation-step1").classed("disabled", false);
});
d3.select("#simulation-step1").on("click", function(){
step1(400);
d3.select("#simulation-step1").classed("disabled", true)
d3.select("#simulation-step2").classed("disabled", false);
});
d3.select("#simulation-step2").on("click", function(){
step2(400);
d3.select("#simulation-step2").classed("disabled", true)
d3.select("#simulation-step3-1").classed("disabled", false);
});
d3.select("#simulation-step3-1").on("click", function(){
fillTable(1200, function(){
d3.select("#simulation-step3-2").classed("disabled", false);
});
d3.select("#simulation-step3-1").classed("disabled", true)
});
d3.select("#simulation-step3-2").on("click", function(){
countCards();
d3.select("#simulation-step3-2").classed("disabled", true)
d3.select("#simulation-step3-3").classed("disabled", false)
});
d3.select("#simulation-step3-3").on("click", function(){
computeDifference();
d3.select("#simulation-step3-3").classed("disabled", true);
d3.select("#simulation-step4").classed("disabled", false);
});
d3.select("#simulation-step4").on("click", function(){
step4(function(){});
d3.select("#simulation-step4").classed("disabled", true);
d3.select("#simulation-step5-playButton").classed("disabled",false);
$("#slider").slider("option","disabled",false);
currentSimIndex++;
d3.select("#simulation-plotOriginal").classed("disabled", false);
});
d3.select("#simulation-step5-playButton").on("click", function(){
if($(this).hasClass("playing")){
pause();
} else {
resume();
}
});
d3.select("#simulation-plotOriginal").on("click", function(){
plotOriginalExperiment();
d3.select("#simulation-plotOriginal").classed("disabled", true);
d3.select("#simulation-pValue").classed("disabled",false);
});
d3.select("#simulation-pValue").on("click", function(){
pValueAnimation();
d3.select("#simulation-pValue").classed("disabled", true);
});
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment