Create graph for overlaps #409
This commit is contained in:
parent
711082cf23
commit
0911a1787e
2 changed files with 128 additions and 7 deletions
|
|
@ -62,13 +62,14 @@ class AnalyticsController extends Controller
|
|||
|
||||
$hub_data = [];
|
||||
$hub_coverage = [];
|
||||
$overlaps = [];
|
||||
foreach ($hub_list as $key => $hub_id)
|
||||
{
|
||||
$dist = $distances[$key];
|
||||
$hub = $em->getRepository(Hub::class)->find($hub_id);
|
||||
$coords = $hub->getCoordinates();
|
||||
|
||||
$dist = $distances[$key];
|
||||
$hub_data[$hub_id] = $this->generateHubData($em, $hub, $dist, $today);
|
||||
$hub_data[$hub_id] = $this->generateHubData($em, $hub, $dist, $today, $overlaps);
|
||||
|
||||
$hub_coverage[] = [
|
||||
'longitude' => $coords->getLongitude(),
|
||||
|
|
@ -77,16 +78,32 @@ class AnalyticsController extends Controller
|
|||
];
|
||||
}
|
||||
|
||||
// reprocess weekday data to account for overlap
|
||||
foreach ($hub_data as $hub_id => $one_hub)
|
||||
{
|
||||
$c_weekday = $one_hub['c_weekday'];
|
||||
$chart_weekday = $this->generateWeekdayData($c_weekday, $today, $overlaps);
|
||||
$hub_data[$hub_id]['data_weekday'] = $chart_weekday;
|
||||
|
||||
unset($hub_data[$hub_id]['c_weekday']);
|
||||
}
|
||||
|
||||
// error_log(print_r($overlaps, true));
|
||||
|
||||
// get job orders not covered by hubs
|
||||
$not_covered = $this->generateNotCoveredData($em, $hub_coverage, $today);
|
||||
|
||||
$params = [
|
||||
'date' => $today,
|
||||
'hub_list' => $hub_data,
|
||||
'hub_coverage' => $hub_coverage,
|
||||
'not_covered' => $not_covered,
|
||||
];
|
||||
|
||||
return $this->render('analytics/forecast_submit.html.twig', $params);
|
||||
}
|
||||
|
||||
protected function generateHubData($em, $hub, $distance_limit, DateTime $today)
|
||||
protected function generateHubData($em, $hub, $distance_limit, DateTime $today, &$overlaps)
|
||||
{
|
||||
$date_start = DateTime::createFromFormat('Y-m-d H:i:s', '2018-01-01 00:00:00');
|
||||
$date_end = new DateTime();
|
||||
|
|
@ -95,7 +112,7 @@ class AnalyticsController extends Controller
|
|||
// $hub = $em->getRepository(Hub::class)->find($hub_id);
|
||||
$conn = $em->getConnection();
|
||||
|
||||
// get job order data
|
||||
// get job order data (job orders within coverage area)
|
||||
$jos = $this->generateJobOrderData($conn, $hub, $distance_limit);
|
||||
|
||||
// initialize counters
|
||||
|
|
@ -116,6 +133,9 @@ class AnalyticsController extends Controller
|
|||
$hour = $date->format('H');
|
||||
$week = $date->format('W');
|
||||
|
||||
$jo_id = $jo['id'];
|
||||
$hub_id = $hub->getID();
|
||||
|
||||
// year day
|
||||
if (!isset($c_day[$year][$month][$day]))
|
||||
$c_day[$year][$month][$day] = 0;
|
||||
|
|
@ -126,9 +146,11 @@ class AnalyticsController extends Controller
|
|||
{
|
||||
$c_weekday[$year][$month][$weekday][$hour]['total'] = 0;
|
||||
$c_weekday[$year][$month][$weekday][$hour]['count'] = 0;
|
||||
$c_weekday[$year][$month][$weekday][$hour]['jos'] = [];
|
||||
}
|
||||
|
||||
$c_weekday[$year][$month][$weekday][$hour]['total']++;
|
||||
$c_weekday[$year][$month][$weekday][$hour]['jos'][$jo_id] = $jo_id;
|
||||
|
||||
if (!isset($c_week_count[$year][$month][$week][$weekday][$hour]))
|
||||
{
|
||||
|
|
@ -136,12 +158,19 @@ class AnalyticsController extends Controller
|
|||
$c_week_count[$year][$month][$week][$weekday][$hour] = 1;
|
||||
$c_weekday[$year][$month][$weekday][$hour]['count']++;
|
||||
}
|
||||
|
||||
// track overlaps (jo that can be handled by more than one hub)
|
||||
if (!isset($overlaps[$jo_id]))
|
||||
{
|
||||
$overlaps[$jo_id] = [];
|
||||
}
|
||||
$overlaps[$jo_id][$hub_id] = $hub_id;
|
||||
}
|
||||
|
||||
// error_log(print_r($c_weekday, true));
|
||||
|
||||
$chart_year = $this->generateYearData($date_start, $date_end, $c_day);
|
||||
$chart_weekday = $this->generateWeekdayData($c_weekday, $today);
|
||||
// $chart_weekday = $this->generateWeekdayData($c_weekday, $today);
|
||||
|
||||
// error_log(print_r($chart_weekday, true));
|
||||
|
||||
|
|
@ -149,7 +178,9 @@ class AnalyticsController extends Controller
|
|||
'id' => $hub->getID(),
|
||||
'label' => $hub->getName(),
|
||||
'data_year' => $chart_year,
|
||||
'data_weekday' => $chart_weekday,
|
||||
// 'data_weekday' => $chart_weekday,
|
||||
'c_weekday' => $c_weekday, // sending raw weekday data because we need to process overlaps
|
||||
// TODO: refactor this pls
|
||||
];
|
||||
|
||||
return $params;
|
||||
|
|
@ -212,7 +243,7 @@ class AnalyticsController extends Controller
|
|||
return $chart_year;
|
||||
}
|
||||
|
||||
protected function generateWeekdayData($all_weekday_data, $today)
|
||||
protected function generateWeekdayData($all_weekday_data, $today, $overlaps)
|
||||
{
|
||||
$data = [];
|
||||
|
||||
|
|
@ -241,13 +272,65 @@ class AnalyticsController extends Controller
|
|||
{
|
||||
$year_id = 'y' . $year;
|
||||
|
||||
// calculate the rider value for each JO and use that score as basis
|
||||
$total_rv = $this->calculateTotalRiderValue($year_data[$month][$weekday][$hour]['jos'], $overlaps);
|
||||
|
||||
$data[$id][$year_id] = $year_data[$month][$weekday][$hour]['total'];
|
||||
$data[$id][$year_id . '_count'] = $year_data[$month][$weekday][$hour]['count'];
|
||||
$data[$id][$year_id . '_average'] = ceil($year_data[$month][$weekday][$hour]['total'] / $year_data[$month][$weekday][$hour]['count']);
|
||||
$data[$id][$year_id . '_rv_average'] = ceil($total_rv / $year_data[$month][$weekday][$hour]['count']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
protected function calculateTotalRiderValue($jos, $overlaps)
|
||||
{
|
||||
// rider value = 1 / number of hubs (overlaps) that can service JO
|
||||
|
||||
$sum = 0.0;
|
||||
$jo_count = count($jos);
|
||||
|
||||
foreach ($jos as $jo_id)
|
||||
{
|
||||
$hub_count = count($overlaps[$jo_id]);
|
||||
$rv = 1 / $hub_count;
|
||||
$sum += $rv;
|
||||
}
|
||||
|
||||
return $sum;
|
||||
}
|
||||
|
||||
protected function generateNotCoveredData($em, $hub_coverage, $today)
|
||||
{
|
||||
$conn = $em->getConnection();
|
||||
|
||||
$month = $today->format('m');
|
||||
$weekday = $today->format('N') - 1;
|
||||
|
||||
$wheres = [];
|
||||
foreach ($hub_coverage as $hub_data)
|
||||
{
|
||||
$long = $hub_data['longitude'];
|
||||
$lat = $hub_data['latitude'];
|
||||
$dist = $hub_data['distance'];
|
||||
|
||||
// get areas not covered
|
||||
$wheres[] = "st_distance(coordinates, Point($long, $lat)) * 111195 > $dist";
|
||||
}
|
||||
|
||||
$where_string = implode(' and ', $wheres);
|
||||
|
||||
$sql = "select st_x(coordinates) as longitude, st_y(coordinates) as latitude, id, date_schedule from job_order where $where_string and status <> 'cancelled' and month(date_schedule) = $month and weekday(date_schedule) = $weekday order by date_schedule asc";
|
||||
$stmt = $conn->prepare($sql);
|
||||
$stmt->execute();
|
||||
$jos = $stmt->fetchAll();
|
||||
|
||||
// error_log($sql);
|
||||
error_log(print_r($jos, true));
|
||||
|
||||
return $jos;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,6 +38,9 @@
|
|||
|
||||
<div id="month-weekday-chart-{{ hub.id }}" style="height: 400px;">
|
||||
</div>
|
||||
|
||||
<div id="month-weekday-chart-rv-{{ hub.id }}" style="height: 400px;">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -67,6 +70,15 @@ var map = L.map('map_coverage').setView([{% trans %}default_lat{% endtrans %}, {
|
|||
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);
|
||||
|
|
@ -132,6 +144,32 @@ 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 }};
|
||||
|
||||
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";
|
||||
|
||||
{% endfor %}
|
||||
|
||||
</script>
|
||||
|
|
|
|||
Loading…
Reference in a new issue