381 lines
14 KiB
Twig
381 lines
14 KiB
Twig
{% extends 'base.html.twig' %}
|
|
|
|
{% block stylesheets %}
|
|
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css" integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ==" crossorigin=""/>
|
|
<style>
|
|
.sched_col {
|
|
width: 3.5%;
|
|
}
|
|
.marked {
|
|
background-color: #ff0000;
|
|
}
|
|
.shift-table {
|
|
margin-top: 20px;
|
|
margin-left: 20px;
|
|
margin-right: 20px;
|
|
}
|
|
.shift-table th {
|
|
text-align: center;
|
|
}
|
|
.shift-table td {
|
|
padding: 5px 10px 5px 10px;
|
|
border: 1px solid black;
|
|
}
|
|
</style>
|
|
{% endblock %}
|
|
|
|
{% block body %}
|
|
<!-- BEGIN: Subheader -->
|
|
<div class="m-subheader">
|
|
<div class="d-flex align-items-center">
|
|
<div class="mr-auto">
|
|
<h3 class="m-subheader__title">Analytics Forecasting - {{ date | date('M - l') }}</h3>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- END: Subheader -->
|
|
<div class="m-content">
|
|
<!--Begin::Section-->
|
|
<div id="map_coverage" style="height:600px; margin-bottom: 15px;">
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-xl-12">
|
|
<div class="m-portlet m-portlet--mobile">
|
|
<table class="shift-table">
|
|
<thead>
|
|
<tr>
|
|
<th style="width: 250px;">Day</th>
|
|
<th style="width: 100px;"># JO</th>
|
|
<th style="width: 100px;"># Rider</th>
|
|
<th style="width: 100px;">JO per Rider</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for i in 0..6 %}
|
|
<tr>
|
|
<td>{{ agg_data[i].label }}</td>
|
|
<td>{{ agg_data[i].total_jos }}</td>
|
|
<td>{{ agg_data[i].total_riders }}</td>
|
|
{% if agg_data[i].total_riders == 0 %}
|
|
<td>0</td>
|
|
{% else %}
|
|
<td>{{ (agg_data[i].total_jos / agg_data[i].total_riders) | round(1, 'common') }}</td>
|
|
{% endif %}
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{% for hub in hub_list %}
|
|
<div class="row">
|
|
<div class="col-xl-12">
|
|
<div class="m-portlet m-portlet--mobile">
|
|
<div class="m-portlet__head">
|
|
<div class="m-portlet__head-caption">
|
|
<div class="m-portlet__head-title col-xl-12">
|
|
<h3 class="m-portlet__head-text col-xl-4">
|
|
{{ hub.label }}
|
|
</h3>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="year-day-chart-{{ hub.id }}" style="height: 400px;">
|
|
</div>
|
|
|
|
<div id="month-weekday-chart-{{ hub.id }}" style="height: 400px;">
|
|
</div>
|
|
|
|
<div id="month-weekday-chart-rv-{{ hub.id }}" style="height: 400px;">
|
|
</div>
|
|
|
|
<div id="month-all-weekday-chart-{{ hub.id }}" style="height: 400px;">
|
|
</div>
|
|
|
|
<table class="shift-table">
|
|
<thead>
|
|
<tr>
|
|
<th style="width: 250px;">Day</th>
|
|
<th style="width: 100px;"># JO</th>
|
|
<th style="width: 100px;"># Rider</th>
|
|
<th style="width: 100px;">JO per Rider</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for i in 0..6 %}
|
|
<tr>
|
|
<td>{{ hub.data_shift[i].weekday }}</td>
|
|
<td>{{ hub.data_shift[i].total_jos }}</td>
|
|
<td>{{ hub.data_shift[i].total_riders }}</td>
|
|
{% if hub.data_shift[i].total_riders == 0 %}
|
|
<td>0</td>
|
|
{% else %}
|
|
<td>{{ (hub.data_shift[i].total_jos / hub.data_shift[i].total_riders) | round(1, 'common') }}</td>
|
|
{% endif %}
|
|
</tr>
|
|
{% endfor %}
|
|
<tr>
|
|
<td>Overall</td>
|
|
<td>{{ hub.total_jos }}</td>
|
|
<td>{{ hub.total_riders }}</td>
|
|
{% if hub.total_riders == 0 %}
|
|
<td>0</td>
|
|
{% else %}
|
|
<td>{{ (hub.total_jos / hub.total_riders) | round(1, 'common') }}</td>
|
|
{% endif %}
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
|
|
{% for day_data in hub.data_shift %}
|
|
<div id="shift-table-{{ hub.id }}">
|
|
<table class="shift-table">
|
|
<thead>
|
|
<tr>
|
|
<th>{{ day_data.weekday }}</th>
|
|
<th>00</th>
|
|
<th>01</th>
|
|
<th>02</th>
|
|
<th>03</th>
|
|
<th>04</th>
|
|
<th>05</th>
|
|
<th>06</th>
|
|
<th>07</th>
|
|
<th>08</th>
|
|
<th>09</th>
|
|
<th>10</th>
|
|
<th>11</th>
|
|
<th>12</th>
|
|
<th>13</th>
|
|
<th>14</th>
|
|
<th>15</th>
|
|
<th>16</th>
|
|
<th>17</th>
|
|
<th>18</th>
|
|
<th>19</th>
|
|
<th>20</th>
|
|
<th>21</th>
|
|
<th>22</th>
|
|
<th>23</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for shift_data in day_data.shifts %}
|
|
{% for i in 1..shift_data.count %}
|
|
<tr>
|
|
<td style="width: 250px;">{{ shift_data.label }}</td>
|
|
{% for hour_coverage in shift_data.hours %}
|
|
{% if hour_coverage %}
|
|
<td class="sched_col marked"></td>
|
|
{% else %}
|
|
<td class="sched_col"></td>
|
|
{% endif %}
|
|
{% endfor %}
|
|
</tr>
|
|
{% endfor %}
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block scripts %}
|
|
<script src="//www.amcharts.com/lib/4/core.js"></script>
|
|
<script src="//www.amcharts.com/lib/4/charts.js"></script>
|
|
<script src="//www.amcharts.com/lib/4/maps.js"></script>
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.3.1/leaflet.js"></script>
|
|
<script>
|
|
|
|
|
|
// map
|
|
|
|
var map = L.map('map_coverage').setView([{% trans %}default_lat{% endtrans %}, {% trans %}default_long{% endtrans %}], 13);
|
|
L.tileLayer('https://api.maptiler.com/maps/streets/{z}/{x}/{y}.png?key={{ maptiler_api_key }}',{
|
|
tileSize: 512,
|
|
zoomOffset: -1,
|
|
minZoom: 1,
|
|
crossOrigin: true
|
|
}).addTo(map);
|
|
|
|
{% for cover in hub_coverage %}
|
|
L.circle([{{ cover.latitude }}, {{ cover.longitude }}], { radius: {{ cover.distance }} }).addTo(map);
|
|
{% endfor %}
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
// display not covered
|
|
{% for jo_na in not_covered %}
|
|
L.marker([{{ jo_na.latitude }}, {{ jo_na.longitude }}]).addTo(map);
|
|
{% endfor %}
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
{% for hub in hub_list %}
|
|
// create chart instance
|
|
var chart = am4core.create("year-day-chart-{{ hub.id }}", am4charts.XYChart);
|
|
|
|
// add data
|
|
chart.data = {{ hub.data_year|json_encode|raw }};
|
|
|
|
// create axes
|
|
var categoryAxis = chart.xAxes.push(new am4charts.CategoryAxis());
|
|
categoryAxis.dataFields.category = "date";
|
|
categoryAxis.title.text = "Date";
|
|
|
|
var valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
|
|
valueAxis.title.text = "Orders";
|
|
valueAxis.maxPrecision = 0;
|
|
|
|
// year day
|
|
var s2018 = chart.series.push(new am4charts.LineSeries());
|
|
s2018.name = "2018";
|
|
s2018.stroke = am4core.color("#0000FF");
|
|
s2018.strokeWidth = 2;
|
|
s2018.dataFields.valueY = "y2018";
|
|
s2018.dataFields.categoryX = "date";
|
|
|
|
var s2019 = chart.series.push(new am4charts.LineSeries());
|
|
s2019.name = "2019";
|
|
s2019.stroke = am4core.color("#FF0000");
|
|
s2019.strokeWidth = 2;
|
|
s2019.dataFields.valueY = "y2019";
|
|
s2019.dataFields.categoryX = "date";
|
|
|
|
var s2020 = chart.series.push(new am4charts.LineSeries());
|
|
s2020.name = "2020";
|
|
s2020.stroke = am4core.color("#00FF00");
|
|
s2020.strokeWidth = 2;
|
|
s2020.dataFields.valueY = "y2020";
|
|
s2020.dataFields.categoryX = "date";
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
var chart2 = am4core.create("month-weekday-chart-{{ hub.id }}", am4charts.XYChart);
|
|
chart2.data = {{ hub.data_weekday|json_encode|raw }};
|
|
chart2.legend = new am4charts.Legend();
|
|
|
|
var xAxis = chart2.xAxes.push(new am4charts.CategoryAxis());
|
|
xAxis.dataFields.category = "hour";
|
|
xAxis.title.text = "Hour";
|
|
var yAxis = chart2.yAxes.push(new am4charts.ValueAxis());
|
|
yAxis.title.text = "Orders";
|
|
yAxis.maxPrecision = 0;
|
|
|
|
var l2018 = chart2.series.push(new am4charts.LineSeries());
|
|
l2018.name = "2018";
|
|
l2018.stroke = am4core.color("#0000FF");
|
|
l2018.strokeWidth = 2;
|
|
l2018.dataFields.valueY = "y2018_average";
|
|
l2018.dataFields.categoryX = "hour";
|
|
|
|
var l2019 = chart2.series.push(new am4charts.LineSeries());
|
|
l2019.name = "2019";
|
|
l2019.stroke = am4core.color("#FF0000");
|
|
l2019.strokeWidth = 3;
|
|
l2019.dataFields.valueY = "y2019_average";
|
|
l2019.dataFields.categoryX = "hour";
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
var chart2 = am4core.create("month-weekday-chart-rv-{{ hub.id }}", am4charts.XYChart);
|
|
chart2.data = {{ hub.data_weekday|json_encode|raw }};
|
|
chart2.legend = new am4charts.Legend();
|
|
|
|
var xAxis = chart2.xAxes.push(new am4charts.CategoryAxis());
|
|
xAxis.dataFields.category = "hour";
|
|
xAxis.title.text = "Hour";
|
|
var yAxis = chart2.yAxes.push(new am4charts.ValueAxis());
|
|
yAxis.title.text = "Orders";
|
|
yAxis.maxPrecision = 0;
|
|
|
|
var l2018 = chart2.series.push(new am4charts.LineSeries());
|
|
l2018.name = "2018";
|
|
l2018.stroke = am4core.color("#0000FF");
|
|
l2018.strokeWidth = 2;
|
|
l2018.dataFields.valueY = "y2018_rv_average";
|
|
l2018.dataFields.categoryX = "hour";
|
|
|
|
var l2019 = chart2.series.push(new am4charts.LineSeries());
|
|
l2019.name = "2019";
|
|
l2019.stroke = am4core.color("#FF0000");
|
|
l2019.strokeWidth = 3;
|
|
l2019.dataFields.valueY = "y2019_rv_average";
|
|
l2019.dataFields.categoryX = "hour";
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
var chart2 = am4core.create("month-all-weekday-chart-{{ hub.id }}", am4charts.XYChart);
|
|
chart2.data = {{ hub.data_all_weekdays|json_encode|raw }};
|
|
chart2.legend = new am4charts.Legend();
|
|
|
|
var xAxis = chart2.xAxes.push(new am4charts.CategoryAxis());
|
|
xAxis.dataFields.category = "hour";
|
|
xAxis.title.text = "Hour";
|
|
var yAxis = chart2.yAxes.push(new am4charts.ValueAxis());
|
|
yAxis.title.text = "Orders";
|
|
yAxis.maxPrecision = 0;
|
|
|
|
var lmon = chart2.series.push(new am4charts.LineSeries());
|
|
lmon.name = "Monday";
|
|
lmon.stroke = am4core.color("#003f5c");
|
|
lmon.strokeWidth = 2;
|
|
lmon.dataFields.valueY = "y2018_Monday_rv_average";
|
|
lmon.dataFields.categoryX = "hour";
|
|
|
|
var l = chart2.series.push(new am4charts.LineSeries());
|
|
l.name = "Tuesday";
|
|
l.stroke = am4core.color("#374c80");
|
|
l.strokeWidth = 2;
|
|
l.dataFields.valueY = "y2018_Tuesday_rv_average";
|
|
l.dataFields.categoryX = "hour";
|
|
|
|
var l = chart2.series.push(new am4charts.LineSeries());
|
|
l.name = "Wednesday";
|
|
l.stroke = am4core.color("#7a5195");
|
|
l.strokeWidth = 2;
|
|
l.dataFields.valueY = "y2018_Wednesday_rv_average";
|
|
l.dataFields.categoryX = "hour";
|
|
|
|
var l = chart2.series.push(new am4charts.LineSeries());
|
|
l.name = "Thursday";
|
|
l.stroke = am4core.color("#bc5090");
|
|
l.strokeWidth = 2;
|
|
l.dataFields.valueY = "y2018_Thursday_rv_average";
|
|
l.dataFields.categoryX = "hour";
|
|
|
|
var l = chart2.series.push(new am4charts.LineSeries());
|
|
l.name = "Friday";
|
|
l.stroke = am4core.color("#ef5675");
|
|
l.strokeWidth = 2;
|
|
l.dataFields.valueY = "y2018_Friday_rv_average";
|
|
l.dataFields.categoryX = "hour";
|
|
|
|
var l = chart2.series.push(new am4charts.LineSeries());
|
|
l.name = "Saturday";
|
|
l.stroke = am4core.color("#ff764a");
|
|
l.strokeWidth = 2;
|
|
l.dataFields.valueY = "y2018_Saturday_rv_average";
|
|
l.dataFields.categoryX = "hour";
|
|
|
|
var l = chart2.series.push(new am4charts.LineSeries());
|
|
l.name = "Sunday";
|
|
l.stroke = am4core.color("#ffa600");
|
|
l.strokeWidth = 2;
|
|
l.dataFields.valueY = "y2018_Sunday_rv_average";
|
|
l.dataFields.categoryX = "hour";
|
|
|
|
{% endfor %}
|
|
|
|
</script>
|
|
{% endblock %}
|