First Visualization of Race Data

This commit is contained in:
sirsandmann 2017-12-11 01:26:27 +01:00
parent 3ccffc0134
commit 56a74866a7
5 changed files with 88 additions and 75 deletions

View File

@ -31,3 +31,9 @@ body {
top: 0; /* not 10px, but 0 instead */ top: 0; /* not 10px, but 0 instead */
left: 0; left: 0;
} }
.line {
fill: none;
stroke: steelblue;
stroke-width: 2px;
}

View File

@ -44,15 +44,19 @@
<main role="main" class="container"> <main role="main" class="container">
<div class="content-box"> <div class="content-box">
<h1>Hallo!</h1> <h1>Rennen, Brumm, Brumm!</h1>
<p class="lead"> <p class="lead">
Mit Bootstrap sieht alles per Default ein wenig hübscher aus.<br>
Eingerückt wird mit 2 Leerzeichen pro Einrückungsebene.<br> Eingerückt wird mit 2 Leerzeichen pro Einrückungsebene.<br>
Charset ist UTF-8.<br> Charset ist UTF-8.<br>
TODO TODO
</p> </p>
</div> </div>
<div class="content-box chart-box">
<p>Hier erscheint gleich ein Diagramm.</p>
<div id="lineGraphBox"></div>
</div>
<div class="content-box chart-box"> <div class="content-box chart-box">
<p>Hier erscheint gleich ein Test-Diagramm.</p> <p>Hier erscheint gleich ein Test-Diagramm.</p>
<div id="testchartbox"></div> <div id="testchartbox"></div>

View File

@ -1,80 +1,58 @@
"use strict"; "use strict";
/* // https://bl.ocks.org/mbostock/3884955
* This may be restructured in the future - code to create diagrams will live here. function createLineGraph(containerId, raceData){
*/
function createTestPieChart(containerId, dataset) {
var width = 1000;
var height = 1000; var height = 1000;
// Build the basic container for the chart var width = 1000;
var svg = d3.select(containerId)
.append("div") // set the dimensions and margins of the graph
.classed("svg-container", true) var margin = {top: 20, right: 20, bottom: 30, left: 50},
.append("svg") width = width - margin.left - margin.right,
.attr("preserveAspectRatio", "xMinYMin meet") height = height - margin.top - margin.bottom;
.attr("viewBox", "0 0 " + width + " " + height + "")
.classed("svg-content-responsive", true) // set the ranges
var x = d3.scaleLinear().range([0, width]);
var y = d3.scaleLinear().range([height, 0]);
var allLineData = raceDataToLineData(raceData);
// defines how the passed in Data, at "svg.append" shall be interpreted
var lineDataDefinition = d3.line()
.x(function(d) { return x(d.lap); })
.y(function(d) { return y(d.position); });
// append the svg obgect to the body of the page
// appends a 'group' element to 'svg'
// moves the 'group' element to the top left margin
var svg = d3.select(containerId).append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g") .append("g")
.classed("main-group", true) .attr("transform",
.attr("transform", "translate(" + (width / 2) + "," + (height / 2) + ")"); "translate(" + margin.left + "," + margin.top + ")");
var arcs = svg.append("g").classed("pie-chart-arcs", true); // Scale the range of the data
var labels = svg.append("g").classed("pie-chart-labels", true); x.domain([0, raceData.lapTimes.size]);
var lines = svg.append("g").classed("pie-chart-lines", true); y.domain([raceData.drivers.length, 1]);
// Preparations are done, now let's build the pie chart // Adds all lines
var maxRadius = Math.min(width, height) / 2; allLineData.forEach((singleLineData) => {
var radius = maxRadius * 0.4; svg.append("path")
var color = d3.scaleOrdinal(d3.schemeCategory10); .data([singleLineData])
.attr("class", "line")
.attr("d", lineDataDefinition);
});
var arc = d3.arc() // Add the X Axis
.innerRadius(radius*0.4) svg.append("g")
.outerRadius(radius); .attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
var pie = d3.pie()
.sort(function(a, b) { return b.count - a.count })
.value(function(d) { return d.count; });
arcs.selectAll("path")
.data(pie(dataset))
.enter()
.append("path")
.attr("d", arc)
.attr("fill", function(d, i) {
return color(d.data.label);
});
labels.selectAll("text")
.data(pie(dataset))
.enter()
.append("text")
.attr("dy", ".35em")
.text(function(d) {
console.log(d);
return d.data.label;
});
function midAngle(d) {
return d.startAngle + (d.endAngle - d.startAngle) / 2;
}
lines.selectAll("polyline")
.data(pie(dataset))
.enter()
.append("polyline")
.transition()
.duration(1000)
.attrTween("points", function(d) {
this._current = this._current || d;
var interpolate = d3.interpolate(this._current, d);
this._current = interpolate(0);
return function(t) {
var d2 = interpolate(t);
var pos = outerArc.centroid(d2);
pos[0] = radius * 0.95 * (midAngle(d2) < Math.PI ? 1 : -1);
return [arc.centroid(d2), outerArc.centroid(d2), pos];
};
})
// Add the Y Axis on both sides
svg.append("g")
.call(d3.axisLeft(y));
svg.append("g")
.call(d3.axisRight(y))
.attr("transform", "translate( " + (width) + ", 0 )");
} }

View File

@ -6,6 +6,6 @@
preprocessor.load(function(data) { preprocessor.load(function(data) {
createTestPieChart("#testchartbox", queries.getDriversByNationality()); createLineGraph("#lineGraphBox", processor.getRace(1));
}); });

View File

@ -1,6 +1,6 @@
"use strict"; "use strict";
/* /*
* This file contains utility functions, data structures and * This file contains utility functions, data structures and
* stuff not related to what this project actually does. * stuff not related to what this project actually does.
*/ */
@ -34,6 +34,31 @@ var loadingDialog = {
var percentage = (this.progressItemsDone / this.progressItems) * 100; var percentage = (this.progressItemsDone / this.progressItems) * 100;
if(percentage < 0 || isNaN(percentage)) percentage = 0; if(percentage < 0 || isNaN(percentage)) percentage = 0;
if(percentage > 100) percentage = 100; if(percentage > 100) percentage = 100;
$(this.id + " .progress-bar").attr("style", "width: " + percentage + "%;"); $(this.id + " .progress-bar").attr("style", "width: " + percentage + "%;");
}, },
}; };
//Gets the position of Driver with driverid in specific lap
function getPositionOfDriver(driver, lap, defaultReturn){
var lapEntryWithDrivId =lap.filter( drivLap => drivLap.driverId == driver.driverId );
if(lapEntryWithDrivId.length > 0){
return lapEntryWithDrivId[0].position;
}else{
return defaultReturn;
}
}
// transforms the raceData to a format, with which lineDataDefinition can work
function raceDataToLineData(raceData){
// define the lines
var lineData = [];
raceData.drivers.forEach((driver, drivIn)=>{
lineData.push();
var lapsOfDriverInLineDataFormat = [];
raceData.lapTimes.forEach((lap, lapIn) => {
lapsOfDriverInLineDataFormat.push({ 'lap': lapIn, 'position': getPositionOfDriver(driver, lap, raceData.drivers.length)});
});
lineData.splice(drivIn, 0, lapsOfDriverInLineDataFormat);
});
return lineData;
}