CINXE.COM
Article revision statistics
<!doctype html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <link href="/static/common.css" rel="stylesheet" type="text/css" /> <link href="/static/diff.css" rel="stylesheet" type="text/css" /> <title>Article revision statistics</title> <!--<script type="text/javascript" src="//static.toolforge.org/res/jquery/2.1.0/jquery.min.js"></script>--> <script src="https://code.jquery.com/jquery-2.2.4.min.js"></script> <script type="text/javascript"> var urlParams={};(function(){var a,b=/\+/g,c=/([^&=]+)=?([^&]*)/g,d=function(a){return decodeURIComponent(a.replace(b," "))},e=window.location.search.substring(1);while(a=c.exec(e))urlParams[d(a[1])]=d(a[2])})(); // http://stackoverflow.com/questions/901115/how-can-i-get-query-string-values function setTheParams() { var elem; for (var key in urlParams) { elem = $("#" + key); if (elem.prop("type") == 'checkbox') elem.prop("checked", 1); else elem.val(urlParams[key]); } } $(document).ready(setTheParams); </script> <script> $(document).ready(function() { $("#editchart").scroll(function () { $("#sizechart").scrollTop($("#editchart").scrollTop()); $("#sizechart").scrollLeft($("#editchart").scrollLeft()); }); $("#sizechart").scroll(function () { $("#editchart").scrollTop($("#sizechart").scrollTop()); $("#editchart").scrollLeft($("#sizechart").scrollLeft()); }); } ); Date.prototype.addDays = function(days) { var dat = new Date(this.valueOf()); dat.setDate(dat.getDate() + days); return dat; } </script> <link rel="stylesheet" type="text/css" href="/static/graphing.css" /> </head> <body> <h1 id=top>Article revision statistics</h1> <p>This tool displays various statistics about the history of an article.</p> <hr style="text-align:left;width:875px;margin-left:0"> <table> <tr> <td>Article:</td> <td> <a href="https://en.wikisource.org/wiki/The_New_Student's_Reference_Work/Coast-Survey">The_New_Student's_Reference_Work/Coast-Survey</a> </td> </tr> <tr> <td>Total revisions:</td> <td>2</td> </tr> <tr> <td>Number of minor edits:</td> <td>1 (50.0%)</td> </tr> <tr> <td>Number of IP edits:</td> <td>0 (0.0%)</td> </tr> <tr> <td>First edit:</td> <td>2017-09-06T20:35:35+00:00 (by Bob Burkhardt)</td> </tr> <tr> <td>Most recent edit:</td> <td>2022-01-16T14:50:40+00:00 (by MpaaBot)</td> </tr> <tr> <td>Average time between edits:</td> <td>796.0 days</td> </tr> <tr> <td>Average number of edits per month:</td> <td>0.038</td> </tr> <tr> <td>Average number of edits per year:</td> <td>0.459</td> </tr> <tr> <td>Number of edits in the last day:</td> <td>0</td> </tr> <tr> <td>Number of edits in the last week:</td> <td>0</td> </tr> <tr> <td>Number of edits in the last month:</td> <td>0</td> </tr> <tr> <td>Number of edits in the last year:</td> <td>0</td> </tr> <tr> <td>Number of users:</td> <td>2</td> </tr> <tr> <td>Average edits per user:</td> <td>1.0</td> </tr> </table> <h2 id=editsgraph>Edits over time</h2> <hr/> <div style="margin:0 auto"> <div class="legend"> <ul> <li> <form> <label><input type=radio name=mode onclick="cum_edit_chart(window.cumSums, 'Total number of edits')" /> ∫</label> <label><input type=radio name=mode onclick="edit_chart(window.payload, 'Number of edits')" checked /> <sup>Δy</sup>⁄<sub>Δx</sub></label> </form> </li> <li><span class=dashbox style="color:crimson; font-weight:bolder;">█</span> all edits</li> <li><span class=dashbox style="color:mediumseagreen; font-weight:bolder;">█</span> minor edits</li> <li><span class=dashbox style="color:darkorchid; font-weight:bolder;">█</span> anon edits</li> </ul> </div> <div id=editchart style="width:60%; height:430px; padding:10px; overflow:auto; border:2px solid gray; float:left"> </div> </div> <div style="clear:both"></div> <h2 id=sizegraph>Article size over time</h2> <hr/> <div style="margin:0 auto"> <div class="legend" style='text-align:center'> <div style='display:inline-block'> <ul> <li><a href="//en.wikipedia.org/wiki/Quartile"><small>(legend)</small></a></li> <li> <svg width=50 height=120> <text x=10 y=10>Q₃</text> <line x1=10 y1=20 x2=20 y2=20 class=whisker></line> <line x1=15 y1=20 x2=15 y2=80 class=whisker></line> <line x1=5 y1=55 x2=25 y2=45 class=line></line> <circle class=focuscircle r=6 cx=15 cy=50></circle> <text x=30 y=45>Q₂</text> <line x1=10 y1=80 x2=20 y2=80 class=whisker></line> <text x=10 y=100>Q₁</text> </svg> </li> </ul> </div> </div> <div id=sizechart style="width:60%; height:430px; padding:10px; overflow:auto; border:2px solid gray; float:left"> </div> </div> <div style="clear: both"></div> <!-- <h2>Circle graphs even though they suck</h2> <hr/> <div style="margin:0 auto"> <div id=circlelegend class="legend"> <3 </div> <div id="circlegraphs" style="width:60%; height:430px; padding:10px; overflow:auto; border:2px solid gray; float:left"> </div> </div> <div style="clear:both"></div> --> <h2 id=top50>Top 50 contributors</h2> <hr/> <table border=1> <tr> <th>Username</th> <th># of edits</th> <th>Minor</th> <th>First edit</th> <th>Latest edit</th> <th>Mean time between edits</th> <th>Mean page size (KiB)</th> <th>Added (B)</th> <th>Removed (B)</th> </tr> <tr> <td> <a href="https://en.wikisource.org/wiki/User:Bob Burkhardt">Bob Burkhardt</a> (<a href="https://en.wikisource.org/wiki/User_talk:Bob Burkhardt">talk</a>) </td> <td>1</td> <td>0 (0.0%)</td> <td>2017-09-06T20:35:35+00:00</td> <td>2017-09-06T20:35:35+00:00</td> <td>None</td> <td>0.146</td> <td>149</td> <td>0</td> </tr> <tr> <td> <a href="https://en.wikisource.org/wiki/User:MpaaBot">MpaaBot</a> (<a href="https://en.wikisource.org/wiki/User_talk:MpaaBot">talk</a>) </td> <td>1</td> <td>1 (100.0%)</td> <td>2022-01-16T14:50:40+00:00</td> <td>2022-01-16T14:50:40+00:00</td> <td>None</td> <td>0.246</td> <td>103</td> <td>0</td> </tr> </table> <span id='warnings'> </span> <br /> <small> Elapsed time: 0.035 seconds. <br /> 06:32:05, 28 Nov 2024 </small> <br /> <br /> <a href="/articleinfo.py"><small>←New search</small></a> <div id=footer> <a href="https://toolforge.org/"> <img src="/static/res/logos/powered-by-tool-labs-2.png" alt="Powered by Toolforge" style="float: left"/> </a> <small> © 2016 <a href="https://en.wikipedia.org/wiki/User:Σ">User:Σ</a> </small> </div> <!--<script src="/static/res/d3/3.4.8/d3.min.js"></script>--> <script src="https://unpkg.com/d3@3.4.8/d3.min.js"></script> <script> //(function() { var margin = {top: 20, right: 50, bottom: 90, left: 50}, width = 2112 - margin.left - margin.right, height = 400 - margin.top - margin.bottom; if (width < 0) width *= -1; if (height < 0) height *= -1; var parseDate = d3.time.format("%Y/%m").parse, bisectDate = d3.bisector(function (d) { return d.date; }).left; // (2024, 11, 28) window.payload = [ {date: new Date(2017, 8, 1), crap: [0.146, 0.146, 0.146]}, {date: new Date(2017, 9, 1), crap: [0.146, 0.146, 0.146]}, {date: new Date(2017, 10, 1), crap: [0.146, 0.146, 0.146]}, {date: new Date(2017, 11, 1), crap: [0.146, 0.146, 0.146]}, {date: new Date(2017, 12, 1), crap: [0.146, 0.146, 0.146]}, {date: new Date(2018, 1, 1), crap: [0.146, 0.146, 0.146]}, {date: new Date(2018, 2, 1), crap: [0.146, 0.146, 0.146]}, {date: new Date(2018, 3, 1), crap: [0.146, 0.146, 0.146]}, {date: new Date(2018, 4, 1), crap: [0.146, 0.146, 0.146]}, {date: new Date(2018, 5, 1), crap: [0.146, 0.146, 0.146]}, {date: new Date(2018, 6, 1), crap: [0.146, 0.146, 0.146]}, {date: new Date(2018, 7, 1), crap: [0.146, 0.146, 0.146]}, {date: new Date(2018, 8, 1), crap: [0.146, 0.146, 0.146]}, {date: new Date(2018, 9, 1), crap: [0.146, 0.146, 0.146]}, {date: new Date(2018, 10, 1), crap: [0.146, 0.146, 0.146]}, {date: new Date(2018, 11, 1), crap: [0.146, 0.146, 0.146]}, {date: new Date(2018, 12, 1), crap: [0.146, 0.146, 0.146]}, {date: new Date(2019, 1, 1), crap: [0.146, 0.146, 0.146]}, {date: new Date(2019, 2, 1), crap: [0.146, 0.146, 0.146]}, {date: new Date(2019, 3, 1), crap: [0.146, 0.146, 0.146]}, {date: new Date(2019, 4, 1), crap: [0.146, 0.146, 0.146]}, {date: new Date(2019, 5, 1), crap: [0.146, 0.146, 0.146]}, {date: new Date(2019, 6, 1), crap: [0.146, 0.146, 0.146]}, {date: new Date(2019, 7, 1), crap: [0.146, 0.146, 0.146]}, {date: new Date(2019, 8, 1), crap: [0.146, 0.146, 0.146]}, {date: new Date(2019, 9, 1), crap: [0.146, 0.146, 0.146]}, {date: new Date(2019, 10, 1), crap: [0.146, 0.146, 0.146]}, {date: new Date(2019, 11, 1), crap: [0.146, 0.146, 0.146]}, {date: new Date(2019, 12, 1), crap: [0.146, 0.146, 0.146]}, {date: new Date(2020, 1, 1), crap: [0.146, 0.146, 0.146]}, {date: new Date(2020, 2, 1), crap: [0.146, 0.146, 0.146]}, {date: new Date(2020, 3, 1), crap: [0.146, 0.146, 0.146]}, {date: new Date(2020, 4, 1), crap: [0.146, 0.146, 0.146]}, {date: new Date(2020, 5, 1), crap: [0.146, 0.146, 0.146]}, {date: new Date(2020, 6, 1), crap: [0.146, 0.146, 0.146]}, {date: new Date(2020, 7, 1), crap: [0.146, 0.146, 0.146]}, {date: new Date(2020, 8, 1), crap: [0.146, 0.146, 0.146]}, {date: new Date(2020, 9, 1), crap: [0.146, 0.146, 0.146]}, {date: new Date(2020, 10, 1), crap: [0.146, 0.146, 0.146]}, {date: new Date(2020, 11, 1), crap: [0.146, 0.146, 0.146]}, {date: new Date(2020, 12, 1), crap: [0.146, 0.146, 0.146]}, {date: new Date(2021, 1, 1), crap: [0.146, 0.146, 0.146]}, {date: new Date(2021, 2, 1), crap: [0.146, 0.146, 0.146]}, {date: new Date(2021, 3, 1), crap: [0.146, 0.146, 0.146]}, {date: new Date(2021, 4, 1), crap: [0.146, 0.146, 0.146]}, {date: new Date(2021, 5, 1), crap: [0.146, 0.146, 0.146]}, {date: new Date(2021, 6, 1), crap: [0.146, 0.146, 0.146]}, {date: new Date(2021, 7, 1), crap: [0.146, 0.146, 0.146]}, {date: new Date(2021, 8, 1), crap: [0.146, 0.146, 0.146]}, {date: new Date(2021, 9, 1), crap: [0.146, 0.146, 0.146]}, {date: new Date(2021, 10, 1), crap: [0.146, 0.146, 0.146]}, {date: new Date(2021, 11, 1), crap: [0.146, 0.146, 0.146]}, {date: new Date(2021, 12, 1), crap: [0.246, 0.246, 0.246]}, {date: new Date(2022, 1, 1), crap: [0.246, 0.246, 0.246]}, {date: new Date(2022, 2, 1), crap: [0.246, 0.246, 0.246]}, {date: new Date(2022, 3, 1), crap: [0.246, 0.246, 0.246]}, {date: new Date(2022, 4, 1), crap: [0.246, 0.246, 0.246]}, {date: new Date(2022, 5, 1), crap: [0.246, 0.246, 0.246]}, {date: new Date(2022, 6, 1), crap: [0.246, 0.246, 0.246]}, {date: new Date(2022, 7, 1), crap: [0.246, 0.246, 0.246]}, {date: new Date(2022, 8, 1), crap: [0.246, 0.246, 0.246]}, {date: new Date(2022, 9, 1), crap: [0.246, 0.246, 0.246]}, {date: new Date(2022, 10, 1), crap: [0.246, 0.246, 0.246]}, {date: new Date(2022, 11, 1), crap: [0.246, 0.246, 0.246]}, {date: new Date(2022, 12, 1), crap: [0.246, 0.246, 0.246]}, {date: new Date(2023, 1, 1), crap: [0.246, 0.246, 0.246]}, {date: new Date(2023, 2, 1), crap: [0.246, 0.246, 0.246]}, {date: new Date(2023, 3, 1), crap: [0.246, 0.246, 0.246]}, {date: new Date(2023, 4, 1), crap: [0.246, 0.246, 0.246]}, {date: new Date(2023, 5, 1), crap: [0.246, 0.246, 0.246]}, {date: new Date(2023, 6, 1), crap: [0.246, 0.246, 0.246]}, {date: new Date(2023, 7, 1), crap: [0.246, 0.246, 0.246]}, {date: new Date(2023, 8, 1), crap: [0.246, 0.246, 0.246]}, {date: new Date(2023, 9, 1), crap: [0.246, 0.246, 0.246]}, {date: new Date(2023, 10, 1), crap: [0.246, 0.246, 0.246]}, {date: new Date(2023, 11, 1), crap: [0.246, 0.246, 0.246]}, {date: new Date(2023, 12, 1), crap: [0.246, 0.246, 0.246]}, {date: new Date(2024, 1, 1), crap: [0.246, 0.246, 0.246]}, {date: new Date(2024, 2, 1), crap: [0.246, 0.246, 0.246]}, {date: new Date(2024, 3, 1), crap: [0.246, 0.246, 0.246]}, {date: new Date(2024, 4, 1), crap: [0.246, 0.246, 0.246]}, {date: new Date(2024, 5, 1), crap: [0.246, 0.246, 0.246]}, {date: new Date(2024, 6, 1), crap: [0.246, 0.246, 0.246]}, {date: new Date(2024, 7, 1), crap: [0.246, 0.246, 0.246]}, {date: new Date(2024, 8, 1), crap: [0.246, 0.246, 0.246]}, {date: new Date(2024, 9, 1), crap: [0.246, 0.246, 0.246]}, {date: new Date(2024, 10, 1), crap: [0.246, 0.246, 0.246]}, ]; (function (data) { if (data.length < 3) { return $("#sizechart").text("Not enough revisions for the size chart to be worth graphing :("); } data.sort(function (a, b) { return a.date - b.date; }); var svg = d3.select("#sizechart").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 + ")"); var x = d3.time.scale() .range([0, width]); var y = d3.scale.linear() .range([height, 0]); var xAxis = d3.svg.axis() .scale(x) .orient("bottom") .ticks(d3.time.months) .tickSize(16, 0) .tickFormat(d3.time.format("%Y/%m")); var yAxis = d3.svg.axis() .scale(y) .orient("left"); var line = d3.svg.line() .x(function (d) { return x(d.date); }) .y(function (d) { return y(d.crap[1]); }); var xdomain = d3.extent(data, function (d) { return d.date} );//[data[0].date, data[data.length - 1].date]; x.domain(xdomain); //var ydomain = d3.extent(data, function (d) { return d.crap[1]; }); var ydomain = [0.146, 1.246]; // so quartiles don't go off the screen y.domain(ydomain); svg.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xAxis) .selectAll("text") .attr("y", 0) .attr("x", 9) .attr("dy", ".35em") .style("text-anchor", "end") .attr("transform", "translate(0," + (margin.bottom-60) + ")" + "rotate(-45)"); 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") .text("Article size (KiB)"); svg.append("path") .datum(data) .attr("class", "line") .attr("d", line); for (var i = 0; i < data.length; i++) { var date, dateL, dateR; var q1, med, q3; var whisker; date = data[i].date; q1 = data[i].crap[0]; med = data[i].crap[1]; q3 = data[i].crap[2]; if (q1 == q3) // if there's no whisker, skip it continue; whisker = [q1, med, q3]; svg.append("path") .datum([{date: date, crap: [null, q1, null]}, {date: date, crap: [null, q3, null]}]) .attr("class", "whisker") .attr("d", line); // draw the ends so it looks like a "I" dateL = new Date(date.getTime()); dateR = new Date(date.getTime()); dateL.setDate(dateL.getDate() - 3); dateR.setDate(dateR.getDate() + 3); svg.append("path") .datum([{date: dateL, crap: [null, q1, null]}, {date: dateR, crap: [null, q1, null]}]) .attr("class", "whisker") .attr("d", line); svg.append("path") .datum([{date: dateL, crap: [null, q3, null]}, {date: dateR, crap: [null, q3, null]}]) .attr("class", "whisker") .attr("d", line); } var focus = svg.append("g") .attr("class", "overlay") .style("display", "none"); var circlefoc = focus.append("g"); circlefoc.append("circle") .attr("class", "focuscircle") .attr("r", 4.5); circlefoc.append("text") .attr("x", 9) .attr("y", 9) .attr("dy", ".35em"); focus.append("line") .attr("id", "lineX") .attr("class", "focusline"); focus.append("line") .attr("id", "lineY") .attr("class", "focusline"); svg.append("rect") .attr("class", "overlay") .attr("width", width) //.attr("fill-opacity", 0) // what the shit .attr("height", height) .on("mouseover", function () { focus.style("display", null); }) .on("mouseout", function () { focus.style("display", "none"); }) .on("mousemove", mousemove); function mousemove() { var x0 = x.invert(d3.mouse(this)[0]), i = bisectDate(data, x0, 1), d0 = data[i - 1], d1 = data[i], d = x0 - d0.date > d1.date - x0 ? d1 : d0; circlefoc.attr("transform", "translate(" + x(d.date) + "," + y(d.crap[1]) + ")"); circlefoc.select("text").attr("fill", "black").text(d.crap[1]); focus.select("#lineX") .attr("x1", x(d.date)).attr("y1", y(ydomain[0])) .attr("x2", x(d.date)).attr("y2", y(ydomain[1])); focus.select("#lineY") .attr("x1", x(xdomain[0])).attr("y1", y(d.crap[1])) .attr("x2", x(xdomain[1])).attr("y2", y(d.crap[1])); } })(window.payload); window.cumSums = [{date: new Date, crap: [0, 0, 0]}]; /* tee hee */ window.payload = [ {date: new Date(2017, 8, 1), crap: [1, 0, 0]}, {date: new Date(2017, 9, 1), crap: [0, 0, 0]}, {date: new Date(2017, 10, 1), crap: [0, 0, 0]}, {date: new Date(2017, 11, 1), crap: [0, 0, 0]}, {date: new Date(2017, 12, 1), crap: [0, 0, 0]}, {date: new Date(2018, 1, 1), crap: [0, 0, 0]}, {date: new Date(2018, 2, 1), crap: [0, 0, 0]}, {date: new Date(2018, 3, 1), crap: [0, 0, 0]}, {date: new Date(2018, 4, 1), crap: [0, 0, 0]}, {date: new Date(2018, 5, 1), crap: [0, 0, 0]}, {date: new Date(2018, 6, 1), crap: [0, 0, 0]}, {date: new Date(2018, 7, 1), crap: [0, 0, 0]}, {date: new Date(2018, 8, 1), crap: [0, 0, 0]}, {date: new Date(2018, 9, 1), crap: [0, 0, 0]}, {date: new Date(2018, 10, 1), crap: [0, 0, 0]}, {date: new Date(2018, 11, 1), crap: [0, 0, 0]}, {date: new Date(2018, 12, 1), crap: [0, 0, 0]}, {date: new Date(2019, 1, 1), crap: [0, 0, 0]}, {date: new Date(2019, 2, 1), crap: [0, 0, 0]}, {date: new Date(2019, 3, 1), crap: [0, 0, 0]}, {date: new Date(2019, 4, 1), crap: [0, 0, 0]}, {date: new Date(2019, 5, 1), crap: [0, 0, 0]}, {date: new Date(2019, 6, 1), crap: [0, 0, 0]}, {date: new Date(2019, 7, 1), crap: [0, 0, 0]}, {date: new Date(2019, 8, 1), crap: [0, 0, 0]}, {date: new Date(2019, 9, 1), crap: [0, 0, 0]}, {date: new Date(2019, 10, 1), crap: [0, 0, 0]}, {date: new Date(2019, 11, 1), crap: [0, 0, 0]}, {date: new Date(2019, 12, 1), crap: [0, 0, 0]}, {date: new Date(2020, 1, 1), crap: [0, 0, 0]}, {date: new Date(2020, 2, 1), crap: [0, 0, 0]}, {date: new Date(2020, 3, 1), crap: [0, 0, 0]}, {date: new Date(2020, 4, 1), crap: [0, 0, 0]}, {date: new Date(2020, 5, 1), crap: [0, 0, 0]}, {date: new Date(2020, 6, 1), crap: [0, 0, 0]}, {date: new Date(2020, 7, 1), crap: [0, 0, 0]}, {date: new Date(2020, 8, 1), crap: [0, 0, 0]}, {date: new Date(2020, 9, 1), crap: [0, 0, 0]}, {date: new Date(2020, 10, 1), crap: [0, 0, 0]}, {date: new Date(2020, 11, 1), crap: [0, 0, 0]}, {date: new Date(2020, 12, 1), crap: [0, 0, 0]}, {date: new Date(2021, 1, 1), crap: [0, 0, 0]}, {date: new Date(2021, 2, 1), crap: [0, 0, 0]}, {date: new Date(2021, 3, 1), crap: [0, 0, 0]}, {date: new Date(2021, 4, 1), crap: [0, 0, 0]}, {date: new Date(2021, 5, 1), crap: [0, 0, 0]}, {date: new Date(2021, 6, 1), crap: [0, 0, 0]}, {date: new Date(2021, 7, 1), crap: [0, 0, 0]}, {date: new Date(2021, 8, 1), crap: [0, 0, 0]}, {date: new Date(2021, 9, 1), crap: [0, 0, 0]}, {date: new Date(2021, 10, 1), crap: [0, 0, 0]}, {date: new Date(2021, 11, 1), crap: [0, 0, 0]}, {date: new Date(2021, 12, 1), crap: [1, 1, 0]}, {date: new Date(2022, 1, 1), crap: [0, 0, 0]}, {date: new Date(2022, 2, 1), crap: [0, 0, 0]}, {date: new Date(2022, 3, 1), crap: [0, 0, 0]}, {date: new Date(2022, 4, 1), crap: [0, 0, 0]}, {date: new Date(2022, 5, 1), crap: [0, 0, 0]}, {date: new Date(2022, 6, 1), crap: [0, 0, 0]}, {date: new Date(2022, 7, 1), crap: [0, 0, 0]}, {date: new Date(2022, 8, 1), crap: [0, 0, 0]}, {date: new Date(2022, 9, 1), crap: [0, 0, 0]}, {date: new Date(2022, 10, 1), crap: [0, 0, 0]}, {date: new Date(2022, 11, 1), crap: [0, 0, 0]}, {date: new Date(2022, 12, 1), crap: [0, 0, 0]}, {date: new Date(2023, 1, 1), crap: [0, 0, 0]}, {date: new Date(2023, 2, 1), crap: [0, 0, 0]}, {date: new Date(2023, 3, 1), crap: [0, 0, 0]}, {date: new Date(2023, 4, 1), crap: [0, 0, 0]}, {date: new Date(2023, 5, 1), crap: [0, 0, 0]}, {date: new Date(2023, 6, 1), crap: [0, 0, 0]}, {date: new Date(2023, 7, 1), crap: [0, 0, 0]}, {date: new Date(2023, 8, 1), crap: [0, 0, 0]}, {date: new Date(2023, 9, 1), crap: [0, 0, 0]}, {date: new Date(2023, 10, 1), crap: [0, 0, 0]}, {date: new Date(2023, 11, 1), crap: [0, 0, 0]}, {date: new Date(2023, 12, 1), crap: [0, 0, 0]}, {date: new Date(2024, 1, 1), crap: [0, 0, 0]}, {date: new Date(2024, 2, 1), crap: [0, 0, 0]}, {date: new Date(2024, 3, 1), crap: [0, 0, 0]}, {date: new Date(2024, 4, 1), crap: [0, 0, 0]}, {date: new Date(2024, 5, 1), crap: [0, 0, 0]}, {date: new Date(2024, 6, 1), crap: [0, 0, 0]}, {date: new Date(2024, 7, 1), crap: [0, 0, 0]}, {date: new Date(2024, 8, 1), crap: [0, 0, 0]}, {date: new Date(2024, 9, 1), crap: [0, 0, 0]}, {date: new Date(2024, 10, 1), crap: [0, 0, 0]}, ]; var i; for (i = 0; i < payload.length; i++) { var date, next; date = payload[i].date; next = payload[i].crap.slice(0); for (var j = 0; j < next.length; j++) next[j] += cumSums[i].crap[j]; cumSums.push({date: date, crap: next}); } cumSums.splice(0, 1); window.cum_edit_chart = function (data, ylabel) { $(".dashbox").html("—"); var chart; chart = $("#editchart"); chart.empty(); if (data.length < 3) { return chart.html("Not enough revisions for the edit chart to be worth graphing :("); } data.sort(function (a, b) { return a.date - b.date; }); var svg = d3.select("#editchart").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 + ")"); var x = d3.time.scale() .range([0, width]); var y = d3.scale.linear() .range([height, 0]); var xAxis = d3.svg.axis() .scale(x) .orient("bottom") .ticks(d3.time.month, 1) .tickSize(18, 0) .tickFormat(d3.time.format("%Y/%m")); var yAxis = d3.svg.axis() .scale(y) .orient("left"); var deltaX; for (var j = 0; j < 3; j++) { var xdomain = d3.extent(data, function (d) { return d.date; });//[data[0].date, data[data.length - 1].date]; x.domain(xdomain); var ydomain = d3.extent(data, function (d) { return d.crap[0]; } ); // .crap[0] because it's the biggest ydomain[0] = 0; // 0 because it's the smallest y.domain(ydomain); deltaX = x(data[1].date); var bar_offset = deltaX / 4; var line = d3.svg.line() .x(function (d) { return x(d.date); }) .y((function (n) { return function (d) { return y(d.crap[n]); } })(j)); if (0) for (var n = 0; n < data.length; n++) { svg.append("rect") .attr("x", x(data[n].date) + j * bar_offset) .attr("width", bar_offset) .attr("y", height - (height - y(data[n].crap[j]))) .attr("height", height - y(data[n].crap[j])) .attr("class", (j == 0) ? "redblock" : (j == 1) ? "greenblock" : (j == 2) ? "purpleblock" : ""); } svg.append("path") .datum(data) .attr("class", (j == 0) ? "redline" : (j == 1) ? "greenline" : (j == 2) ? "purpleline" : "line") .attr("d", line); //break; } svg.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xAxis) .selectAll("text") .attr("y", 0) .attr("x", 9) .attr("dy", ".35em") .style("text-anchor", "end") .attr("transform", "translate(0," + (margin.bottom-60) + ")" + "rotate(-45)"); 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") .text(ylabel); var focus = svg.append("g") .attr("class", "overlay") .style("display", "none"); var circlefoc = focus.append("g"); circlefoc.append("circle") .attr("class", "focuscircle") .attr("r", 4.5); circlefoc.append("text") .attr("x", 9) .attr("y", 9) .attr("dy", ".35em"); focus.append("line") .attr("id", "lineX") .attr("class", "focusline"); focus.append("line") .attr("id", "lineY") .attr("class", "focusline"); svg.append("rect") .attr("class", "overlay") .attr("width", width) //.attr("fill-opacity", 0) // what the shit .attr("height", height) .on("mouseover", function () { focus.style("display", null); }) .on("mouseout", function () { focus.style("display", "none"); }) .on("mousemove", mousemove); function mousemove() { var xCoord = d3.mouse(this)[0]; var x0 = x.invert(xCoord), i = bisectDate(data, x0, 1), d0 = data[i - 1], d1 = data[i], d = x0 - d0.date > d1.date - x0 ? d1 : d0; d = d0; var y0 = y.invert(d3.mouse(this)[1]); var n = 0; var highest = Infinity; var possible = d.crap.slice(0); for (var j = 0; j < possible.length; j++) { possible[j] = Math.abs(possible[j] - y0); if (possible[j] < highest) { highest = possible[j]; n = j; } } circlefoc.attr("transform", "translate(" + (x(d.date)) + "," + y(d.crap[n]) + ")"); circlefoc.select("text").attr("fill", "black").text(d.crap[n]); focus.select("#lineX") .attr("x1", x(d.date)).attr("y1", y(ydomain[0])) .attr("x2", x(d.date)).attr("y2", y(ydomain[1])); focus.select("#lineY") .attr("x1", x(xdomain[0])).attr("y1", y(d.crap[n])) .attr("x2", x(xdomain[1])).attr("y2", y(d.crap[n])); } }; (window.edit_chart = function (data, ylabel) { $(".dashbox").html("█"); var chart; chart = $("#editchart"); chart.empty(); if (data.length < 3) { return chart.html("Not enough revisions for the edit chart to be worth graphing :("); } data.sort(function (a, b) { return a.date - b.date; }); var svg = d3.select("#editchart").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 + ")"); var x = d3.time.scale() .range([0, width]); var y = d3.scale.linear() .range([height, 0]); var xAxis = d3.svg.axis() .scale(x) .orient("bottom") .ticks(d3.time.month, 1) .tickSize(18, 0) .tickFormat(d3.time.format("%Y/%m")); var yAxis = d3.svg.axis() .scale(y) .orient("left"); var deltaX; for (var j = 0; j < 3; j++) { var xdomain = d3.extent(data, function (d) { return d.date; });//[data[0].date, data[data.length - 1].date]; x.domain(xdomain); var ydomain = d3.extent(data, function (d) { return d.crap[0]; } ); // .crap[0] because it's the biggest ydomain[0] = 0; // 0 because it's the smallest y.domain(ydomain); deltaX = x(data[1].date); var bar_offset = deltaX / 4; var line = d3.svg.line() .x(function (d) { return x(d.date); }) .y((function (n) { return function (d) { return y(d.crap[n]); } })(j)); for (var n = 0; n < data.length; n++) { svg.append("rect") .attr("x", x(data[n].date) + j * bar_offset) .attr("width", bar_offset) .attr("y", height - (height - y(data[n].crap[j]))) .attr("height", height - y(data[n].crap[j])) .attr("class", (j == 0) ? "redblock" : (j == 1) ? "greenblock" : (j == 2) ? "purpleblock" : ""); } if (0) svg.append("path") .datum(data) .attr("class", (j == 0) ? "redline" : (j == 1) ? "greenline" : (j == 2) ? "purpleline" : "line") .attr("d", line); //break; } svg.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xAxis) .selectAll("text") .attr("y", 0) .attr("x", 9) .attr("dy", ".35em") .style("text-anchor", "end") .attr("transform", "translate(0," + (margin.bottom-60) + ")" + "rotate(-45)"); 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") .text(ylabel); var focus = svg.append("g") .attr("class", "overlay") .style("display", "none"); var circlefoc = focus.append("g"); circlefoc.append("rect") .attr("class", "focusbar") .attr("height", 2) .attr("width", deltaX * 3/4); circlefoc.append("text") .attr("x", 9) .attr("y", -9) .attr("dy", ".35em"); focus.append("line") .attr("id", "lineX") .attr("class", "focusline"); focus.append("line") .attr("id", "lineY") .attr("class", "focusline"); svg.append("rect") .attr("class", "overlay") .attr("width", width) //.attr("fill-opacity", 0) // what the shit .attr("height", height) .on("mouseover", function () { focus.style("display", null); }) .on("mouseout", function () { focus.style("display", "none"); }) .on("mousemove", mousemove); function mousemove() { var xCoord = d3.mouse(this)[0]; var x0 = x.invert(xCoord), i = bisectDate(data, x0, 1), d0 = data[i - 1], d1 = data[i], d = x0 - d0.date > d1.date - x0 ? d1 : d0; d = d0; var y0 = y.invert(d3.mouse(this)[1]); var n = 0; var highest = Infinity; var possible = d.crap.slice(0); for (var j = 0; j < possible.length; j++) { possible[j] = Math.abs(possible[j] - y0); if (possible[j] < highest) { highest = possible[j]; n = j; } } circlefoc.attr("transform", "translate(" + (x(d.date)) + "," + y(d.crap[n]) + ")"); circlefoc.select("text").attr("fill", "black").text(d.crap[n]); if (0) focus.select("#lineX") .attr("x1", x(d.date)).attr("y1", y(ydomain[0])) .attr("x2", x(d.date)).attr("y2", y(ydomain[1])); focus.select("#lineY") .attr("x1", x(xdomain[0])).attr("y1", y(d.crap[n])) .attr("x2", x(xdomain[1])).attr("y2", y(d.crap[n])); } })(payload, "Number of edits"); //})(); </script> </body> </html>