github/VisualStudio activity on GitHub similar to https://github.com/blog/2195-the-shape-of-open-source
| <!DOCTYPE html> | |
| <head> | |
| <meta charset="utf-8"> | |
| <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"> | |
| <style> | |
| body { | |
| font: 12px sans-serif; | |
| color: #121401; | |
| padding-bottom: 30px; | |
| } | |
| .axis path, | |
| .axis line { | |
| fill: none; | |
| stroke: #121401; | |
| stroke-width: 2px; | |
| shape-rendering: crispEdges; | |
| } | |
| .point { | |
| stroke: grey; | |
| stroke-width: 3px; | |
| opacity: 0; | |
| } | |
| .x.label { | |
| font-size: 16px; | |
| font-weight: normal; | |
| } | |
| .y.label { | |
| font-size: 16px; | |
| font-weight: normal; | |
| } | |
| .x.label.year{ | |
| font-size: 12px; | |
| font-weight: normal; | |
| } | |
| .attribution{ | |
| font-size: 16px; | |
| font-weight: normal; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <h2 style="font-size:18px;text-align:center;margin-left:-260px">github/VisualStudio activity</h2> | |
| <script src="https://d3js.org/d3.v3.min.js" charset="utf-8"></script> | |
| <script src="https://code.jquery.com/jquery-2.2.4.min.js" integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44=" crossorigin="anonymous"></script> | |
| <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script> | |
| <script> | |
| function toTitleCase(str) | |
| { | |
| return str.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();}); | |
| } | |
| var margin = {top: 20, right: 55, bottom: 100, left: 90}, | |
| width = 1100 - margin.left - margin.right, | |
| height = 700 - margin.top - margin.bottom; | |
| var x = d3.scale.ordinal() | |
| .rangeRoundBands([0, width], .1); | |
| var y = d3.scale.linear() | |
| .rangeRound([height, 0]); | |
| var xAxis = d3.svg.axis() | |
| .scale(x) | |
| .orient("bottom"); | |
| var yAxis = d3.svg.axis() | |
| .scale(y) | |
| .orient("left"); | |
| var stack = d3.layout.stack() | |
| .offset("zero") | |
| .values(function (d) { return d.values; }) | |
| .x(function (d) { return x(d.label) + x.rangeBand() / 2; }) | |
| .y(function (d) { return d.value; }); | |
| var area = d3.svg.area() | |
| .interpolate("cardinal") | |
| .x(function (d) { return x(d.label) + x.rangeBand() / 2; }) | |
| .y0(function (d) { return y(d.y0); }) | |
| .y1(function (d) { return y(d.y0 + d.y); }); | |
| var color = d3.scale.ordinal() | |
| .range(["#f4a460","#6495ed","#0c457d","#8b8878","#f46066","#188cef"]); | |
| var svg = d3.select("body").append("svg") | |
| .attr("width", width + margin.left + margin.right) | |
| .attr("height", height + margin.top + margin.bottom) | |
| .append("g") | |
| .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); | |
| d3.csv("summary.csv", function (error, data) { | |
| var labelVar = 'year_week'; | |
| var varNames = d3.keys(data[0]) | |
| .filter(function (key) { return key !== labelVar;}); | |
| color.domain(varNames); | |
| var seriesArr = [], series = {}; | |
| varNames.forEach(function (name) { | |
| series[name] = {name: name, values:[]}; | |
| seriesArr.push(series[name]); | |
| }); | |
| data.forEach(function (d) { | |
| varNames.map(function (name) { | |
| series[name].values.push({name: name, label: d[labelVar], value: +d[name]}); | |
| }); | |
| }); | |
| x.domain(data.map(function (d) { return d.year_week; })); | |
| stack(seriesArr); | |
| y.domain([0, d3.max(seriesArr, function (c) { | |
| return d3.max(c.values, function (d) { return d.y0 + d.y; }); | |
| })]); | |
| svg.append("g") | |
| .attr("class", "x axis") | |
| .attr("transform", "translate(0," + height + ")") | |
| .call(xAxis) | |
| .selectAll("text") | |
| .style("text-anchor", "end") | |
| .attr("dx", "-.8em") | |
| .attr("dy", ".15em") | |
| .attr("transform", function(d) { | |
| return "rotate(-65)" | |
| }); | |
| svg.append("g") | |
| .attr("class", "y axis") | |
| .call(yAxis) | |
| .append("text") | |
| .attr("transform", "rotate(-90)") | |
| .attr("y", 6) | |
| .attr("dy", ".71em") | |
| .style("text-anchor", "end"); | |
| svg.append("text") | |
| .attr("class", "y label") | |
| .attr("text-anchor", "end") | |
| .attr("x", -240) | |
| .attr("transform", "rotate(-90)") | |
| .attr("y", height-640) | |
| .text("Count"); | |
| svg.append("text") | |
| .attr("class", "attribution") | |
| .attr("x", width - 138) | |
| .attr("y", height + 85) | |
| .text("Source: GitHub.com") | |
| svg.append("text") | |
| .attr("class", "x label") | |
| .attr("text-anchor", "end") | |
| .attr("x", width/2) | |
| .attr("y", height + 70) | |
| .text("Date"); | |
| var selection = svg.selectAll(".series") | |
| .data(seriesArr) | |
| .enter().append("g") | |
| .attr("class", "series"); | |
| selection.append("path") | |
| .attr("class", "streamPath") | |
| .attr("d", function (d) { return area(d.values); }) | |
| .style("fill", function (d) { return color(d.name); }) | |
| .style("stroke", "grey"); | |
| var points = svg.selectAll(".seriesPoints") | |
| .data(seriesArr) | |
| .enter().append("g") | |
| .attr("class", "seriesPoints"); | |
| points.selectAll(".point") | |
| .data(function (d) { return d.values; }) | |
| .enter().append("circle") | |
| .attr("class", "point") | |
| .attr("cx", function (d) { return x(d.label) + x.rangeBand() / 2; }) | |
| .attr("cy", function (d) { return y(d.y0 + d.y); }) | |
| .attr("r", "10px") | |
| .style("fill",function (d) { return color(d.name); }) | |
| var legend = svg.selectAll(".legend") | |
| .data(varNames.slice().reverse()) | |
| .enter().append("g") | |
| .attr("class", "legend") | |
| .attr("transform", function (d, i) { return "translate(-850," + i * 20 + ")"; }); | |
| legend.append("rect") | |
| .attr("x", width - 80) | |
| .attr("width", 20) | |
| .attr("height", 20) | |
| .style("fill", color) | |
| .style("stroke", "grey"); | |
| legend.append("text") | |
| .attr("x", width - 40) | |
| .attr("y", 10) | |
| .attr("dy", ".5em") | |
| .style("font-size", 12) | |
| .text(function (d) { return toTitleCase(d.replace(/_/g, ' ')); }); | |
| function removePopovers () { | |
| $('.popover').each(function() { | |
| $(this).remove(); | |
| }); | |
| } | |
| function showPopover (d) { | |
| $(this).popover({ | |
| title: d.name, | |
| placement: 'auto top', | |
| container: 'body', | |
| trigger: 'manual', | |
| html : true, | |
| content: function() { | |
| return "Quarter: " + d.label + | |
| "<br/>Rounds: " + d3.format(",")(d.value ? d.value: d.y1 - d.y0); } | |
| }); | |
| $(this).popover('show') | |
| } | |
| }); | |
| </script> | |
| </body> | |
| </html> |
| year_week | issues | issue_comments | pull_request_comments | pull_request_review_comments | commits | pull_requests | |
|---|---|---|---|---|---|---|---|
| 2015-01 | 0 | 0 | 0 | 0 | 13 | 0 | |
| 2015-02 | 0 | 0 | 0 | 0 | 68 | 0 | |
| 2015-03 | 0 | 0 | 0 | 0 | 153 | 0 | |
| 2015-04 | 0 | 0 | 0 | 0 | 236 | 0 | |
| 2015-05 | 0 | 0 | 0 | 0 | 26 | 0 | |
| 2015-06 | 0 | 0 | 0 | 0 | 21 | 0 | |
| 2015-07 | 18 | 48 | 10 | 7 | 67 | 8 | |
| 2015-08 | 20 | 100 | 38 | 30 | 102 | 19 | |
| 2015-09 | 21 | 76 | 42 | 49 | 76 | 20 | |
| 2015-10 | 11 | 72 | 57 | 102 | 125 | 20 | |
| 2015-11 | 9 | 44 | 25 | 27 | 53 | 6 | |
| 2015-12 | 10 | 37 | 19 | 24 | 48 | 10 | |
| 2016-01 | 12 | 78 | 47 | 25 | 96 | 24 | |
| 2016-02 | 5 | 65 | 54 | 27 | 55 | 12 | |
| 2016-03 | 15 | 66 | 15 | 15 | 97 | 8 | |
| 2016-04 | 10 | 30 | 55 | 27 | 135 | 11 | |
| 2016-05 | 37 | 64 | 83 | 36 | 140 | 27 | |
| 2016-06 | 15 | 49 | 68 | 69 | 101 | 28 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment