Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
207 lines (182 sloc) 6.99 KB
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: lightgray;
shape-rendering: crispEdges;
}
.line {
fill: none;
stroke: steelblue;
stroke-width: 2.5;
}
</style>
<body>
<form>
MyLaps.com event ID: <input type="text" id="eventid" value="2695656" />
<input type="submit" id="geteventid" value="Lapchart"/>
</form>
<p>
Home: <a href='http://p1software.com/lapchart'>http://p1software.com/lapchart</a><br>
Code: <a href='http://github.com/kenklin/p1lapchart'>http://github.com/kenklin/p1lapchart</a>
<p>
<div id="lapchartdiv"></div>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script> // Inspired by: http://bl.ocks.org/mbostock/3884955
function p1lapchart(
eventid, // mylaps.com lapchart event id, e.g., 2695656, 2748380, 2759453
lapchartdiv) // element id for placing SVG chart
{
//var source = 'http://localhost:8080/api/eventlapchart/' + eventid;
//var source = 'http://ec2-54-227-108-228.compute-1.amazonaws.com/api/eventlapchart/' + eventid;
var source = 'http://p1software-eb1.elasticbeanstalk.com/p1lapchart/api/' + eventid;
var line_nosel = 2.5;
var line_sel = 8;
var x_tick_spacing = 10; // min x (laps) spacing in pixels
var y_tick_spacing = 12; // min y (cars/pos) spacing in pixels
var overall_width = 960;
var overall_height = 800;
var margin = {top: 40, right: 50, bottom: 30, left: 200},
width = overall_width - margin.left - margin.right,
height = overall_height - margin.top - margin.bottom;
d3.json(source, function(error, data) {
if (data.p1meta.status != 0) {
$('#' + lapchartdiv).html('<h2>Sorry, either the P1LapChart server is down or the entered MyLaps.com ID (' + eventid + ') is not for a lapchart.</h2>');
return;
}
var color = d3.scale.category20();
color.domain(data.lapchart.participants.map(function(p) { return p.startNumber; }));
var laps_array = d3.entries(data.p1laps);
var cars = laps_array.map(function(l) {
var c = l.key;
var p = data.lapchart.participants.filter(function(element, index, array) {return element.startNumber == c});
var n = p[0] == undefined ? undefined : p[0].name;
return {
car: c,
name: n,
laps: l.value.map(function(pos, lap) {
return {num: lap, pos: pos};
})
};
});
//cars.reverse(); // paint slowest first
// Determine x and y value domains
var domain = {
x_min: d3.min(cars, function(car) { return d3.min(car.laps, function(v) { return v.num; }); }),
x_max: d3.max(cars, function(car) { return d3.max(car.laps, function(v) { return v.num; }); }),
y_min: d3.min(cars, function(car) { return d3.min(car.laps, function(v) { return v.pos; }); }),
y_max: d3.max(cars, function(car) { return d3.max(car.laps, function(v) { return v.pos; }); })
};
// y axis (height is adaptive)
while (height / (domain.y_max - domain.y_min) < y_tick_spacing) {
overall_height += 50;
height += 50;
}
var y = d3.scale.linear()
.range([0, height]);
var yAxis = d3.svg.axis()
.scale(y)
.ticks(domain.y_max - domain.y_min)
// .tickFormat("")
.orient("left");
y.domain([domain.y_min, domain.y_max]);
// x axis (width is constant)
var lap_ticks = domain.x_max - domain.x_min;
while (width / lap_ticks < x_tick_spacing) {
lap_ticks /= 5;
}
var x = d3.scale.linear()
.range([0, width]);
var xAxis = d3.svg.axis()
.scale(x)
.ticks(lap_ticks)
.tickSize(-height) // https://github.com/mbostock/d3/wiki/SVG-Axes#wiki-tickSize
.orient("bottom");
x.domain([domain.x_min, domain.x_max]);
var svg = d3.select("#" + lapchartdiv).append("svg")
.attr("width", overall_width)
.attr("height", overall_height)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.append("text")
.attr("x", width - 6)
.attr("y", -6)
.attr("dx", ".71em")
.style("text-anchor", "end")
.text("Lap");
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
var car = svg.selectAll(".car")
.data(cars)
.enter().append("g")
.attr("class", "car");
var line = d3.svg.line()
// .interpolate("basis")
.x(function(d) { return x(d.num); })
.y(function(d) { return y(d.pos); });
car.append("path") // Line
.attr("class", "line")
.attr("d", function(d) { return line(d.laps); })
.on("click", function(d) {
var w = d3.select(this).style("stroke-width");
d3.select(this).style("stroke-width", w == line_nosel ? line_sel : line_nosel);
})
.style("stroke", function(d) { return color(d.car); });
car.append("text") // Car number and name at beginning of path
.datum(function(d) { return {car: d.car, name: d.name, value: d.laps[0]}; })
.attr("transform", function(d) { return "translate(" + x(d.value.num) + "," + y(d.value.pos) + ")"; })
.attr("x", -margin.left + 10)
.attr("dy", ".35em")
.style("font-size", "12px")
.text(function(d) { return d.car + " - " + d.name; });
car.append("text") // Car number at end of path
.datum(function(d) { return {car: d.car, value: d.laps[d.laps.length - 1]}; })
.attr("transform", function(d) { return "translate(" + x(d.value.num) + "," + y(d.value.pos) + ")"; })
.attr("x", 3)
.attr("dy", ".35em")
.style("font-size", "12px")
.text(function(d) { return d.car; });
svg.append("text") // Title (location)
.attr("x", (width / 2))
.attr("y", 0 - 2 * (margin.top / 3))
.attr("text-anchor", "middle")
.style("font-size", "16px")
.text(data.event.name);
svg.append("text") // Subtitle (date, source)
.attr("x", (width / 2))
.attr("y", 0 - (margin.top / 3))
.attr("text-anchor", "middle")
.text(data.event.location.name + " (Length: " + data.event.location.lengthLabel + ", Date: " + data.session.dateTime + "), Source: " + data.p1meta.source);
});
}
$('form').submit(function() { // http://api.jquery.com/submit
$('#lapchartdiv').html('Click on a line (currently working on Internet Explorer and Firefox)<br>');
p1lapchart($('#eventid').val(), 'lapchartdiv');
return false;
});
function getURLParameter(name) { // http://stackoverflow.com/questions/1403888/get-url-parameter-with-jquery
return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.search)||[,""])[1].replace(/\+/g, '%20'))||null;
}
$(function() {
var eventid = getURLParameter('id'); // 2695656, 2748380, 2759453
if (eventid == null) {
eventid = $('#eventid').val();
}
if (eventid != null && eventid != '') {
$('#eventid').val(eventid);
$('#geteventid').submit();
}
});
</script>
</body>