~sircmpwn/hnstats

dcd09eca8a4362635a2642fdde0667fe8ae5bd1e — Drew DeVault 6 years ago 2b3c0dd
Fix graphs on Firefox
1 files changed, 84 insertions(+), 79 deletions(-)

M templates/article.html
M templates/article.html => templates/article.html +84 -79
@@ 84,13 84,8 @@
<noscript>
  <p>We would render some graphs here, but you have JavaScript disabled.</p>
</noscript>
<p>
  Posts in the top 30 posts are sampled every 5 minutes, and other posts are
  sampled every 15 minutes. A <span class="grey">grey</span> background
  indicates a sampling interval of 15 minutes.
</p>
<div class="row charts">
  <div class="col-md-4">
  <div class="col-md-6">
    <h4>Rank over time</h4>
    <svg height="250" id="rank-over-time"></svg>
    <p style="width: 80%; text-align: center; margin: 0 auto;">


@@ 99,17 94,7 @@
      </small>
    </p>
  </div>
  <div class="col-md-4">
    <h4>Score over time</h4>
    <svg height="250" id="score-over-time"></svg>
  </div>
  <div class="col-md-4">
    <h4>Comments over time</h4>
    <svg height="250" id="comments-over-time"></svg>
  </div>
</div>
<div class="row charts">
  <div class="col-md-4">
  <div class="col-md-6">
    <h4>Base rank over time</h4>
    <svg height="250" id="base-rank-over-time"></svg>
    <p style="width: 80%; text-align: center; margin: 0 auto;">


@@ 122,6 107,21 @@
    </p>
  </div>
</div>
<div class="row charts">
  <div class="col-md-6">
    <h4>Score over time</h4>
    <svg height="250" id="score-over-time"></svg>
  </div>
  <div class="col-md-6">
    <h4>Comments over time</h4>
    <svg height="250" id="comments-over-time"></svg>
  </div>
</div>
<p>
  Posts in the top 30 posts are sampled every 5 minutes, and other posts are
  sampled every 15 minutes. A <span class="grey">grey</span> background
  indicates a sampling interval of 15 minutes.
</p>
{% endblock %}
{% block scripts %}
<style>


@@ 162,75 162,80 @@ for (var i = 0; i < data.title_changes.length; i++) {
  data.title_changes[i].date = new Date(data.title_changes[i].date + "+00:00");
}

function createTimeChart(selector, yfunc, filter, invert) {
  var samples = filter ? data.samples.filter(filter) : data.samples;
  var elem = document.querySelector(selector);
  var svg = d3.select(selector);
  var margin = {top: 20, right: 20, bottom: 40, left: 50};
  var width = elem.clientWidth - margin.left - margin.right;
  var height = elem.clientHeight - margin.top - margin.bottom;
  var g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
  var x = d3.scaleUtc()
      .rangeRound([0, width]);
  var y = d3.scaleLinear()
      .range(invert ? [0, height] : [height, 0]);
  var line = d3.line()
      .x(function(s) { return x(s.created); })
      .y(function(s) { return y(yfunc(s)); });
  x.domain(d3.extent(samples, function(s) { return s.created; }));
  y.domain(d3.extent(samples, yfunc));
function render() {
  function createTimeChart(selector, yfunc, filter, invert) {
    var samples = filter ? data.samples.filter(filter) : data.samples;
    var elem = document.querySelector(selector);
    var svg = d3.select(selector);
    var margin = {top: 20, right: 20, bottom: 40, left: 50};
    var bb = elem.getBoundingClientRect();
    var width = bb.width - margin.left - margin.right;
    var height = bb.height - margin.top - margin.bottom;
    var g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
    var x = d3.scaleUtc()
        .rangeRound([0, width]);
    var y = d3.scaleLinear()
        .range(invert ? [0, height] : [height, 0]);
    var line = d3.line()
        .x(function(s) { return x(s.created); })
        .y(function(s) { return y(yfunc(s)); });
    x.domain(d3.extent(samples, function(s) { return s.created; }));
    y.domain(d3.extent(samples, yfunc));

  var greyStart = null, sample = null;
  function addGrey(greyEnd) {
    console.log(sample.rank, greyStart, greyEnd);
    g.append("rect")
      .attr("class", "grey")
      .attr("x", greyStart)
      .attr("y", 0)
      .attr("width", greyEnd - greyStart)
      .attr("height", height);
    greyStart = null;
  }
  for (var i = 0; i < samples.length; i++) {
    sample = samples[i];
    if ((sample.rank === -1 || sample.rank > 30) && greyStart === null) {
      greyStart = x(samples[i == 0 ? 0 : i - 1].created);
    } else if (sample.rank <= 30 || i == samples.length - 1) {
      if (greyStart !== null) {
        addGrey(x(sample.created));
    var greyStart = null, sample = null;
    function addGrey(greyEnd) {
      console.log(sample.rank, greyStart, greyEnd);
      g.append("rect")
        .attr("class", "grey")
        .attr("x", greyStart)
        .attr("y", 0)
        .attr("width", greyEnd - greyStart)
        .attr("height", height);
      greyStart = null;
    }
    for (var i = 0; i < samples.length; i++) {
      sample = samples[i];
      if ((sample.rank === -1 || sample.rank > 30) && greyStart === null) {
        greyStart = x(samples[i == 0 ? 0 : i - 1].created);
      } else if (sample.rank <= 30 || i == samples.length - 1) {
        if (greyStart !== null) {
          addGrey(x(sample.created));
        }
      }
    }
  }

  g.append("g")
      .attr("class", "axis axis--x")
      .attr("transform", "translate(0," + height + ")")
      .call(d3.axisBottom(x))
      .selectAll("text")
        .attr("y", 0)
        .attr("x", 20)
        .attr("dy", ".5em")
        .attr("transform", "rotate(45)");
    g.append("g")
        .attr("class", "axis axis--x")
        .attr("transform", "translate(0," + height + ")")
        .call(d3.axisBottom(x))
        .selectAll("text")
          .attr("y", 0)
          .attr("x", 20)
          .attr("dy", ".5em")
          .attr("transform", "rotate(45)");

  g.append("g")
      .attr("class", "axis axis--y")
      .call(d3.axisLeft(y));
    g.append("g")
        .attr("class", "axis axis--y")
        .call(d3.axisLeft(y));

    g.append("path")
        .datum(samples)
        .attr("class", "line")
        .attr("d", line);
  }

  g.append("path")
      .datum(samples)
      .attr("class", "line")
      .attr("d", line);
  createTimeChart("#rank-over-time",
      function(s) { return s.rank + 1 },
      function(s) { return s.rank !== -1 },
      true);
  createTimeChart("#base-rank-over-time",
      function(s) { return s.base_rank + 1 },
      function(s) { return s.base_rank !== null && s.rank !== -1 },
      true);
  createTimeChart("#score-over-time", function(s) { return s.score });
  createTimeChart("#comments-over-time", function(s) { return s.comments });
}

createTimeChart("#rank-over-time",
    function(s) { return s.rank + 1 },
    function(s) { return s.rank !== -1 },
    true);
createTimeChart("#base-rank-over-time",
    function(s) { return s.base_rank + 1 },
    function(s) { return s.base_rank !== null && s.rank !== -1 },
    true);
createTimeChart("#score-over-time", function(s) { return s.score });
createTimeChart("#comments-over-time", function(s) { return s.comments });
render();
</script>
{% endblock %}