estimation.html 10.6 KB
{% extends "base.html" %}


{% block title %}Estimation {{ estimation.public_id }} of your ✈ travel footprint{% endblock %}


{% block hero %}
<div class="jumbotron">
{% if estimation.has_failed() %}
    <h1>{{ content.estimation.failure.hero.title | safe }}</h1>
    <p>{{ content.estimation.failure.hero.description | markdown | safe }}</p>
{% else %}
    <h1>{{ content.estimation.hero.title | safe }}</h1>
    <p>{{ content.estimation.hero.description | markdown | safe }}</p>
{% endif %}
</div>
{% endblock %}



{% macro render_cities(cities) %}
<ul class="numbered-list">
{% for city in cities %}
    <li>
        <span class="city-name" title="{{ city.address }}">
    {% if loop.first %}
        <strong>
        {{ city.city }}
        </strong>
    {% else %}
        {{ city.city }}
    {% endif %}
        </span>
        –
        {{ "%.d" | format(city.footprint | round(0) | int) }} CO<sub>2</sub><small>EQ</small>
    </li>
{% endfor %}
</ul>
{% endmacro %}


{% block body %}
<h2>
    {{ estimation.public_id }} ({{ estimation.status.name }})
</h2>

{% if estimation.errors %}
<div class="row">
    <div class="col-md-12 alert-danger card">
        <div class="card-body">
            <h3 class="card-title">Errors</h3>
            <pre>
{{ estimation.errors }}
            </pre>
        </div>
    </div>
</div>
{% endif %}

<div class="row">
    <h4>Total CO<sub>2</sub> footprint (in grams-equivalent) of each city</h4>
    <div id="cities_footprints_d3viz" class="plot-container"></div>
    <hr>
    <div id="cities_footprints_d3viz_lollipop" class="plot-container"></div>
{#    <br>#}
{#    <p>A Legend here</p>#}
</div>

<hr>

<div class="row">

{% if not estimation.has_failed() %}
{#{% set estimation_output = estimation.get_output_dict() %}#}
{% if estimation.has_many_to_many() %}
    <div class="col-md-6">
    <p>
        For each destination city, the sum of the travels from all the origins.
    </p>
    {{ render_cities(estimation_output.cities) }}
    </div>
{% else %}
    <div class="col-md-6">
    <p>
        Carbon footprint for each city.
    </p>
    {{ render_cities(estimation_output.cities) }}
    </div>
{% endif %}

    <div class="col-md-6">
        <ul class="nav">
            <li class="nav-item m-4">
                <a href="/estimation/{{ estimation.public_id }}.csv" class="btn btn-lg btn-primary">
                    Download CSV
                </a>
            </li>
            <li class="nav-item m-4">
                <a href="/estimation/{{ estimation.public_id }}.yml" class="btn btn-lg btn-warning">
                    Download Raw YAML
                </a>
            </li>
{#            <li class="nav-item m-4">#}
{#                <a href="/estimation/{{ estimation.public_id }}.xls" class="btn btn-lg btn-secondary disabled">#}
{#                    Download XLS#}
{#                </a>#}
{#            </li>#}
{#            <li class="nav-item m-4">#}
{#                <a href="/estimation/{{ estimation.public_id }}.ods" class="btn btn-lg btn-secondary disabled">#}
{#                    Download ODS#}
{#                </a>#}
{#            </li>#}
        </ul>
    </div>

</div>

<hr>

{% if estimation.warnings %}
<div class="row">
    <div class="col-md-12 alert-warning card">
        <div class="card-body">
            <h3 class="card-title">Warnings</h3>
            <pre>
{{ estimation.warnings }}
            </pre>
        </div>
    </div>
</div>
{% endif %}

{#<div class="row">#}
{#    <div class="col-md-6">#}
{#        <h3>Raw Output <small>(YAML)</small></h3>#}
{#        <pre>#}
{#{{ estimation.output_yaml }}#}
{#        </pre>#}
{#    </div>#}
{#</div>#}
{% endif %}
{% endblock %}
{% block js %}
<script src="/static/js/vendor/d3.v4.js"></script>
<script src="/static/js/vendor/d3-legend.js"></script>
{#<script src="https://d3js.org/d3.v4.js"></script>#}
{#<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-legend/2.25.6/d3-legend.js"></script>#}

<script type="text/javascript">

/** POLYFILLS **/
Math.log10 = Math.log10 || function(x) {
  return Math.log(x) * Math.LOG10E;
};

/**
 * Useful for axes' domains on plots.
 * @param value
 * @returns {number}
 */
var ceil_value_to_magnitude = function(value) {
    var sign = 1;
    if (value < 0) {
        value = Math.abs(value);
        sign = -1;
    }
    if (value < 1) {
        return sign;
    }

    var low = Math.pow(10, Math.floor(Math.log10(value)));

    var cursor = low;
    var noloop = 0;
    while ((cursor < value) && (noloop <= 100)) {
        cursor += 0.1 * low;
        noloop += 1;
    }

    return sign * cursor;
};

/** CONFIG **/

var plots_config = {
    'cities_count': {{ estimation_output.cities | length }}
};

/** PLOTS **/

jQuery(document).ready(function($){

    var vizid = "#cities_footprints_d3viz";
    var csvUrl = "/estimation/{{ estimation.public_id }}.csv";
    var x_key = 'city';
    var y_key = 'co2 (g)';

    // Set the dimensions and margins of the graph
    var margin = {top: 10, right: 30, bottom: 150, left: 150},
        height = 666 - margin.top - margin.bottom;
    var width = Math.max(880, $(vizid).parent().width());
    width = width - margin.left - margin.right;

    // Append the svg object to the body of the page
    var svg = d3.select(vizid)
      .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 + ")");

    // Parse the Data
    d3.csv(csvUrl, function(data) {

        // Extrema
        var data_y_max = d3.max(data, function(d) { return parseFloat(d['co2 (g)']); });
        var axis_y_max = ceil_value_to_magnitude(data_y_max);

        // X axis
        var x = d3.scaleBand()
          .range([ 0, width ])
          .domain(data.map(function(d) { return d[x_key]; }))
          .padding(0.2);
        svg.append("g")
          .attr("transform", "translate(0," + height + ")")
          .call(d3.axisBottom(x))
          .selectAll("text")
            .attr("transform", "translate(-10,0)rotate(-45)")
            .style("text-anchor", "end");

        // Add Y axis
        var y = d3.scaleLinear()
          .range([ height, 0 ])
          .domain([ 0, axis_y_max ]);
        svg.append("g")
          .call(d3.axisLeft(y));

        // Bars
        svg.selectAll("mybar")
          .data(data)
          .enter()
          .append("rect")
            .attr("x", function(d) { return x(d[x_key]); })
            .attr("width", x.bandwidth())
            .attr("fill", "#d0808b")
            // Hide bars at the beginning
            .attr("height", function(d) { return height - y(0); }) // always equal to 0
            .attr("y", function(d) { return y(0); });

        // Animation
        svg.selectAll("rect")
          .transition()
          .duration(800)
          .attr("y", function(d) { return y(d[y_key]); })
          .attr("height", function(d) { return height - y(d[y_key]); })
          .delay(function(d, i) { return(i*100); });

        // …
    });

});


jQuery(document).ready(function($){
    var vizid = "#cities_footprints_d3viz_lollipop";
    var csvUrl = "/estimation/{{ estimation.public_id }}.csv";
    var y_key = 'city';
    var x_key = 'co2 (g)';

    var margin = {top: 10, right: 30, bottom: 150, left: 150},
        height = Math.max(300, 100+16*plots_config['cities_count']) - margin.top - margin.bottom;
    var width = Math.max(880, $(vizid).parent().width());
    width = width - margin.left - margin.right;

    var svg = d3.select(vizid)
      .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(csvUrl, function (data) {

        // Extrema
        var data_x_max = d3.max(data, function(d) { return parseFloat(d[x_key]); });
        var axis_x_max = ceil_value_to_magnitude(data_x_max);

        // Add X axis
        var x = d3.scaleLinear()
            .domain([0, axis_x_max])
            .range([0, width]);
        svg.append("g")
            .attr("transform", "translate(0," + height + ")")
            .call(d3.axisBottom(x))
            .selectAll("text")
            .attr("transform", "translate(-10,0)rotate(-45)")
            .style("text-anchor", "end");

        // Y axis
        var y = d3.scaleBand()
            .range([0, height])
            .domain(data.map(function (d) {
                return d[y_key];
            }))
            .padding(1);
        svg.append("g")
            .call(d3.axisLeft(y));

        {#svg.append("g")#}
        {#    .attr("class", "legendQuant")#}
        {#    .attr("transform", "translate(20,20)");#}
        {##}
        {#var legend = d3.legendColor()#}
        {#    .labelFormat(d3.format(".2f"))#}
        {#    .useClass(true)#}
        {#    .title("Legend")#}
        {#    .titleWidth(100)#}
        {#    .scale(y);#}
        {##}
        {#svg.select(".legendQuant")#}
        {#    .call(legend);#}

        svg.append("g")
            .append('text')
            .attr("transform", "translate("+(-180+width/2.0)+","+(height+111)+")")
            {#.text("CO2 emissions as a function of travelling distance");#}
            .text("CO\u2082 emissions equivalent per target city.");

        // Lines
        svg.selectAll("myline")
            .data(data)
            .enter()
            .append("line")
//            .attr("x1", function (d) {
//                return x(d[x_key]);
//            })
            .attr("x1", x(0))
            .attr("x2", x(0))
            .attr("y1", function (d) {
                return y(d[y_key]);
            })
            .attr("y2", function (d) {
                return y(d[y_key]);
            })
            .attr("stroke", "grey");

        // Circles
        svg.selectAll("mycircle")
            .data(data)
            .enter()
            .append("circle")
            .attr("cx", function (d) {
                return x(d[x_key]);
            })
            .attr("cy", function (d) {
                return y(d[y_key]);
            })
            .attr("r", "0")
            .style("fill", "#69b3a2")
            .attr("stroke", "black");

        var animation_duration = 300;
        var animation_delay = 100;

        svg.selectAll("circle")
            .transition()
            .duration(animation_duration)
            .attr("r", "4")
            .delay(function(d, i) { return(i*animation_delay); });

        svg.selectAll("line")
            .transition()
            .duration(animation_duration*0.618)
            .attr("x1", function (d) { return x(d[x_key]); })
            .delay(function(d, i) { return(i*animation_delay); });
    });

});

</script>
{% endblock %}