Graph of Imitator Dynamics simulation over several generations. The grid used for the dynamics is actually a sort of torus, where the edges continue on to the opposite side.
Generations can be iterated through using the Next
and Previous
buttons.
Built with blockbuilder.org
xxxxxxxxxx
<html>
<head>
<style>
.TfT { fill: #0A8BB2; background: #0A8BB2;}
.AC { fill: #1AC18B; background: #1AC18B;}
.AD { fill: #E40E0E; background: #E40E0E;}
.NTfT { fill: #0e46e1; background: #0e46e1;}
.circle {
width: 16px;
height: 16px;
-webkit-border-radius: 8px;
-moz-border-radius: 8px;
border-radius: 8px;
float: left;
}
span {
margin-left: 8px;
font-weight: bold;
}
</style>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="//d3js.org/d3.v4.0.0-alpha.28.min.js" charset="utf-8"></script>
<script src="d3-iconarray.min.js"></script>
</head>
<body>
<div class="row">
<div class="col-sm-7">
<svg id="svg"></svg>
</div>
<div class="col-sm-5">
<div><div class="circle AC"></div><span>Always Cooperate</span></div>
<div><div class="circle AD"></div><span>Always Defect</span></div>
<div><div class="circle TfT"></div><span>Tit-for-Tat</span></div>
<div><div class="circle NTfT"></div><span>Not Tit-for-Tat</span></div>
<div>
<button id="btn-prev" type="button" class="btn btn-default btn-sm" onclick="prev()">
<span class="glyphicon glyphicon-chevron-left"></span> Previous
</button>
<button id="btn-next" type="button" class="btn btn-default btn-sm" onclick="next()">
<span class="glyphicon glyphicon-chevron-right"></span> Next
</button>
</div>
<br>
<div>Generation: <span id="gen"></span></div>
</div>
</div>
<script>
var width = 500,
height = 500,
rows = 30,
columns = 30,
iconWidth = 12,
gapSize = 1,
gapInterval = 6;
var T = 0;
var DATA;
var layout = d3_iconarray.layout()
.widthFirst(false)
.height(rows);
var map_row = (d, i) => {
return {
"t": i,
data: Object.keys(d).map(key => {return {"class": d[key]}})
}
}
var svg = d3.select("#svg")
.attr("width", width)
.attr("height", height);
function appendCircles(selection) {
selection.append("circle")
.attr("cx", iconWidth/2)
.attr("cy", iconWidth/2)
.attr("r", 0)
.transition()
.delay((d) => { return 10 * d.position.y; })
.duration(333)
.attr("r", iconWidth/2);
}
d3.csv('data.csv', map_row, function(data) {
var grid = layout(data[T]["data"]);
DATA = data;
var arrayScale = d3_iconarray.scale()
.domain([0, rows])
.range([0, height])
.gapSize(gapSize)
.gapInterval(gapInterval);
svg.selectAll("g").data(grid)
.enter().append("g")
.attr("class", (d) => { return "icon " + d.data.class; })
.attr("transform", (d) => {
return "translate(" +
arrayScale(d.position.x) + "," +
arrayScale(d.position.y) + ")";
})
.call(appendCircles);
buttonsEnabled();
});
function next() {
T += 1;
redraw(T);
buttonsEnabled();
}
function prev() {
T -= 1;
redraw(T);
buttonsEnabled();
}
function updateGeneration() {
d3.select("#gen").text(T)
}
function buttonsEnabled() {
if (T === 0) {
d3.select("#btn-prev").attr("disabled", true);
}
else {
d3.select("#btn-prev").attr("disabled", null);
}
if (T === DATA.length-1) {
d3.select("#btn-next").attr("disabled", true);
}
else {
d3.select("#btn-next").attr("disabled", null);
}
updateGeneration()
}
var redraw = function(t) {
var grid = layout(DATA[t]["data"]);
svg.selectAll(".icon")
.data(grid)
.attr("class", (d) => { return "icon " + d.data.class; })
}
</script>
</body>
</html>
https://d3js.org/d3.v4.0.0-alpha.28.min.js