Prediction Charts
parent
18a672a5de
commit
cd66207bc7
|
@ -74,11 +74,21 @@ class Api
|
||||||
return self::get("/region/{$id}/properties/capacities");
|
return self::get("/region/{$id}/properties/capacities");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function regionCapacitiesMonthly(int $id, string $date): mixed
|
||||||
|
{
|
||||||
|
return self::get("/region/{$id}/capacities/monthly/{$date}");
|
||||||
|
}
|
||||||
|
|
||||||
public static function propertyCapacitiesMonthly(int $id, string $date): mixed
|
public static function propertyCapacitiesMonthly(int $id, string $date): mixed
|
||||||
{
|
{
|
||||||
return self::get("/property/{$id}/capacities/monthly/{$date}");
|
return self::get("/property/{$id}/capacities/monthly/{$date}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function regionCapacitiesDaily(int $id, string $date): mixed
|
||||||
|
{
|
||||||
|
return self::get("/region/{$id}/capacities/weekdays/{$date}");
|
||||||
|
}
|
||||||
|
|
||||||
public static function propertyCapacitiesDaily(int $id, string $date): mixed
|
public static function propertyCapacitiesDaily(int $id, string $date): mixed
|
||||||
{
|
{
|
||||||
return self::get("/property/{$id}/capacities/weekdays/{$date}");
|
return self::get("/property/{$id}/capacities/weekdays/{$date}");
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App;
|
||||||
|
|
||||||
|
class Chart
|
||||||
|
{
|
||||||
|
public static function colors(int $count = 5){
|
||||||
|
$colors = ['#fff7fb','#ece7f2','#d0d1e6','#a6bddb','#74a9cf','#3690c0','#0570b0','#045a8d','#023858'];
|
||||||
|
return json_encode($colors);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -186,12 +186,13 @@ body.property main{
|
||||||
|
|
||||||
body.region main{
|
body.region main{
|
||||||
grid-template-columns: repeat(4, minmax(10%, 50%));
|
grid-template-columns: repeat(4, minmax(10%, 50%));
|
||||||
grid-template-rows: repeat(3, 1fr) 4em;
|
grid-template-rows: repeat(4, 1fr) 4em;
|
||||||
grid-template-areas:
|
grid-template-areas:
|
||||||
"chart1 chart1 chart2 chart2"
|
"chart1 chart1 chart2 chart2"
|
||||||
|
"chart1 chart1 chart6 chart6"
|
||||||
"chart1 chart1 chart3 chart4"
|
"chart1 chart1 chart3 chart4"
|
||||||
"chart6 chart6 chart3 chart4"
|
"chart1 chart1 chart3 chart4"
|
||||||
"chart6 chart6 timeline timeline";
|
"chart1 chart1 timeline timeline";
|
||||||
}
|
}
|
||||||
|
|
||||||
article{
|
article{
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
</article>
|
</article>
|
||||||
<article class="header" style="grid-area: chart6;">
|
<article class="header" style="grid-area: chart6;">
|
||||||
<header>
|
<header>
|
||||||
<h2 id="prediction-title">Auslastung Vorhersage</h2>
|
<h2 id="prediction-title">Gleitender Mittelwert für die Auslastung von {{ $region[0]['region_name'] }}</h2>
|
||||||
</header>
|
</header>
|
||||||
<div id="chart-prediction"></div>
|
<div id="chart-prediction"></div>
|
||||||
</article>
|
</article>
|
||||||
|
@ -105,7 +105,7 @@ const cCapacityOptions = {
|
||||||
xAxis: {
|
xAxis: {
|
||||||
type: 'category',
|
type: 'category',
|
||||||
boundaryGap: false,
|
boundaryGap: false,
|
||||||
data: {!! json_encode($regionCapacities[1]['dates']) !!},
|
data: {!! json_encode($regionCapacities['region']['dates']) !!},
|
||||||
name: 'Zeitpunkt Scraping',
|
name: 'Zeitpunkt Scraping',
|
||||||
nameLocation: 'center',
|
nameLocation: 'center',
|
||||||
nameGap: 24,
|
nameGap: 24,
|
||||||
|
@ -117,7 +117,7 @@ const cCapacityOptions = {
|
||||||
type: 'value',
|
type: 'value',
|
||||||
min: 0,
|
min: 0,
|
||||||
max: 100,
|
max: 100,
|
||||||
name: 'Auslastung in Prozent',
|
name: 'Auslastung in %',
|
||||||
nameLocation: 'center',
|
nameLocation: 'center',
|
||||||
nameGap: 38,
|
nameGap: 38,
|
||||||
nameTextStyle: {
|
nameTextStyle: {
|
||||||
|
@ -128,24 +128,108 @@ const cCapacityOptions = {
|
||||||
name: 'Auslastung alle Regionen',
|
name: 'Auslastung alle Regionen',
|
||||||
type: 'line',
|
type: 'line',
|
||||||
symbolSize: 7,
|
symbolSize: 7,
|
||||||
data: {!! json_encode($regionCapacities[0]['capacities']) !!}
|
data: {!! json_encode($regionCapacities['all']['capacities']) !!}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Auslastung Region',
|
name: 'Auslastung Region',
|
||||||
type: 'line',
|
type: 'line',
|
||||||
symbolSize: 7,
|
symbolSize: 7,
|
||||||
data: {!! json_encode($regionCapacities[1]['capacities']) !!}
|
data: {!! json_encode($regionCapacities['all']['capacities']) !!}
|
||||||
}]
|
}]
|
||||||
};
|
};
|
||||||
|
|
||||||
cCapacity.setOption(cCapacityOptions);
|
cCapacity.setOption(cCapacityOptions);
|
||||||
|
|
||||||
|
const chartCapacityMonthly = document.getElementById('chart-capacity-monthly');
|
||||||
|
const cCapacityMonthly = echarts.init(chartCapacityMonthly);
|
||||||
|
|
||||||
|
const cCapacityMonthlyOptions = {
|
||||||
|
timeline: {
|
||||||
|
show: false,
|
||||||
|
data: {!! json_encode($regionCapacities['region']['dates']) !!},
|
||||||
|
axisType: 'time',
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
top: 0,
|
||||||
|
bottom: 25,
|
||||||
|
left: 70,
|
||||||
|
right: 10
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: 'value',
|
||||||
|
max: 100
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'category',
|
||||||
|
},
|
||||||
|
options: [
|
||||||
|
@foreach ($regionCapacities['region_monthly'] as $m)
|
||||||
|
{
|
||||||
|
yAxis: {
|
||||||
|
data: {!! json_encode($m['months']) !!}
|
||||||
|
},
|
||||||
|
series: [{
|
||||||
|
type: 'bar',
|
||||||
|
data: {!! json_encode($m['capacities']) !!}
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
@endforeach
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
cCapacityMonthly.setOption(cCapacityMonthlyOptions);
|
||||||
|
|
||||||
|
const chartCapacityDaily = document.getElementById('chart-capacity-daily');
|
||||||
|
const cCapacityDaily = echarts.init(chartCapacityDaily);
|
||||||
|
|
||||||
|
const cCapacityDailyOptions = {
|
||||||
|
timeline: {
|
||||||
|
show: false,
|
||||||
|
data: {!! json_encode($regionCapacities['region']['dates']) !!},
|
||||||
|
axisType: 'time',
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
top: 0,
|
||||||
|
bottom: 25,
|
||||||
|
left: 70,
|
||||||
|
right: 10
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: 'value',
|
||||||
|
max: 100
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'category',
|
||||||
|
},
|
||||||
|
options: [
|
||||||
|
@foreach ($regionCapacities['region_daily'] as $d)
|
||||||
|
{
|
||||||
|
yAxis: {
|
||||||
|
data: {!! json_encode($d['weekdays']) !!}
|
||||||
|
},
|
||||||
|
series: [{
|
||||||
|
type: 'bar',
|
||||||
|
data: {!! json_encode($d['capacities']) !!}
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
@endforeach
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
cCapacityDaily.setOption(cCapacityDailyOptions);
|
||||||
|
|
||||||
const chartPrediction = document.getElementById('chart-prediction');
|
const chartPrediction = document.getElementById('chart-prediction');
|
||||||
const cPrediction = echarts.init(chartPrediction);
|
const cPrediction = echarts.init(chartPrediction);
|
||||||
|
|
||||||
const cPredictionOptions = {
|
const cPredictionOptions = {
|
||||||
|
timeline: {
|
||||||
|
show: false,
|
||||||
|
data: {!! json_encode($regionCapacities['region']['dates']) !!},
|
||||||
|
axisType: 'time',
|
||||||
|
replaceMerge: ['graphic', 'series']
|
||||||
|
},
|
||||||
legend: {
|
legend: {
|
||||||
data: ['Moving Average', 'Earlier', 'Later']
|
show: true
|
||||||
},
|
},
|
||||||
tooltip: {
|
tooltip: {
|
||||||
trigger: 'axis',
|
trigger: 'axis',
|
||||||
|
@ -161,48 +245,79 @@ const cPredictionOptions = {
|
||||||
xAxis: {
|
xAxis: {
|
||||||
type: 'category',
|
type: 'category',
|
||||||
boundaryGap: false,
|
boundaryGap: false,
|
||||||
data: {!! json_encode($prediction['dates']) !!},
|
|
||||||
name: 'Zeitpunkt Scraping',
|
name: 'Zeitpunkt Scraping',
|
||||||
nameLocation: 'center',
|
nameLocation: 'center',
|
||||||
nameGap: 24,
|
nameGap: 24,
|
||||||
nameTextStyle: {
|
nameTextStyle: {
|
||||||
fontWeight: 'bold',
|
fontWeight: 'bold',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
yAxis: {
|
yAxis: {
|
||||||
type: 'value',
|
type: 'value',
|
||||||
min: 0,
|
min: 0,
|
||||||
max: 1,
|
max: 100,
|
||||||
name: 'Auslastung in Prozent',
|
name: 'Auslastung in %',
|
||||||
nameLocation: 'center',
|
nameLocation: 'center',
|
||||||
nameGap: 38,
|
nameGap: 38,
|
||||||
nameTextStyle: {
|
nameTextStyle: {
|
||||||
fontWeight: 'bold',
|
fontWeight: 'bold',
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
series: [{
|
options: [
|
||||||
name: 'Moving Average',
|
@foreach ($predictions as $p)
|
||||||
type: 'line',
|
@if($p === null)
|
||||||
symbolSize: 7,
|
|
||||||
data: {!! json_encode($prediction['movAvg']) !!}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: 'Earlier',
|
graphic: {
|
||||||
type: 'line',
|
elements: [
|
||||||
symbolSize: 7,
|
{
|
||||||
data: {!! json_encode($prediction['cap_earlierTimeframe']) !!}
|
type: 'text',
|
||||||
|
left: 'center',
|
||||||
|
top: 'center',
|
||||||
|
style: {
|
||||||
|
text: 'Keine Daten für Zeitspanne',
|
||||||
|
fontSize: 44,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
@else
|
||||||
name: 'Later',
|
{
|
||||||
type: 'line',
|
graphic: {
|
||||||
symbolSize: 7,
|
elements: []
|
||||||
data: {!! json_encode($prediction['cap_laterTimeframe']) !!}
|
},
|
||||||
}]
|
xAxis: {
|
||||||
|
data: {!! json_encode($p['dates']) !!}
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: 'Gleitender Mittelwert',
|
||||||
|
type: 'line',
|
||||||
|
symbolSize: 7,
|
||||||
|
data: {!! json_encode($p['movAvg']) !!}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Daten vom ...',
|
||||||
|
type: 'line',
|
||||||
|
symbolSize: 7,
|
||||||
|
data: {!! json_encode($p['cap_earlierTimeframe']) !!}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Daten vom',
|
||||||
|
type: 'line',
|
||||||
|
symbolSize: 7,
|
||||||
|
data: {!! json_encode($p['cap_laterTimeframe']) !!}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
@endif
|
||||||
|
@endforeach
|
||||||
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
cPrediction.setOption(cPredictionOptions);
|
cPrediction.setOption(cPredictionOptions);
|
||||||
|
|
||||||
|
|
||||||
const chartHeatmap = document.getElementById('chart-heatmap');
|
const chartHeatmap = document.getElementById('chart-heatmap');
|
||||||
const cHeatmap = echarts.init(chartHeatmap);
|
const cHeatmap = echarts.init(chartHeatmap);
|
||||||
const cHeatmapOptions = {
|
const cHeatmapOptions = {
|
||||||
|
@ -284,5 +399,70 @@ const cHeatmapOptions = {
|
||||||
}
|
}
|
||||||
|
|
||||||
cHeatmap.setOption(cHeatmapOptions);
|
cHeatmap.setOption(cHeatmapOptions);
|
||||||
|
|
||||||
|
const chartTimeline = document.getElementById('timeline');
|
||||||
|
const cTimeline = echarts.init(chartTimeline);
|
||||||
|
|
||||||
|
const cTimelineOptions = {
|
||||||
|
grid: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
timeline: {
|
||||||
|
data: {!! json_encode($regionCapacities['region']['dates']) !!},
|
||||||
|
playInterval: 2000,
|
||||||
|
axisType: 'time',
|
||||||
|
left: 8,
|
||||||
|
right: 8,
|
||||||
|
bottom: 0,
|
||||||
|
label: {
|
||||||
|
show: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
cTimeline.setOption(cTimelineOptions);
|
||||||
|
|
||||||
|
cTimeline.on('timelinechanged', (e) => {
|
||||||
|
|
||||||
|
// Set markpoint on linechart
|
||||||
|
let x = cCapacityOptions.xAxis.data[e.currentIndex];
|
||||||
|
let y = cCapacityOptions.series[0].data[e.currentIndex];
|
||||||
|
|
||||||
|
cCapacityMonthly.dispatchAction({
|
||||||
|
type: 'timelineChange',
|
||||||
|
currentIndex: e.currentIndex
|
||||||
|
});
|
||||||
|
|
||||||
|
cCapacityDaily.dispatchAction({
|
||||||
|
type: 'timelineChange',
|
||||||
|
currentIndex: e.currentIndex
|
||||||
|
});
|
||||||
|
|
||||||
|
cPrediction.dispatchAction({
|
||||||
|
type: 'timelineChange',
|
||||||
|
currentIndex: e.currentIndex
|
||||||
|
});
|
||||||
|
|
||||||
|
cCapacity.setOption({
|
||||||
|
series: {
|
||||||
|
markPoint: {
|
||||||
|
data: [{
|
||||||
|
coord: [x, y]
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
cCapacity.on('click', 'series', (e) => {
|
||||||
|
|
||||||
|
// Switch to correct calendar in the timeline
|
||||||
|
cTimeline.dispatchAction({
|
||||||
|
type: 'timelineChange',
|
||||||
|
currentIndex: e.dataIndex
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
use App\Api;
|
use App\Api;
|
||||||
|
use App\Chart;
|
||||||
|
|
||||||
Route::get('/', function () {
|
Route::get('/', function () {
|
||||||
|
|
||||||
|
@ -20,9 +21,19 @@ Route::get('/', function () {
|
||||||
$propsPerRegionCounts[] = $el['count_properties'];
|
$propsPerRegionCounts[] = $el['count_properties'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$chartOptions = [
|
||||||
|
'colors' => Chart::colors()
|
||||||
|
];
|
||||||
|
|
||||||
$propertiesGeo = Api::propertiesGeo();
|
$propertiesGeo = Api::propertiesGeo();
|
||||||
|
|
||||||
return view('overview', ["regions" => $regionBase, "regionPropertiesCapacities" => $regionPropertyCapacities, "geo" => $propertiesGeo, "growth" => $propertiesGrowth, "propsPerRegion" => [json_encode($propsPerRegionId), json_encode($propsPerRegionName), json_encode($propsPerRegionCounts)]]);
|
return view('overview', [
|
||||||
|
"regions" => $regionBase,
|
||||||
|
"regionPropertiesCapacities" => $regionPropertyCapacities,
|
||||||
|
"geo" => $propertiesGeo,
|
||||||
|
"growth" => $propertiesGrowth,
|
||||||
|
"chartOptions" => $chartOptions,
|
||||||
|
"propsPerRegion" => [json_encode($propsPerRegionId), json_encode($propsPerRegionName), json_encode($propsPerRegionCounts)]]);
|
||||||
});
|
});
|
||||||
|
|
||||||
Route::get('/property/{id}', function (int $id) {
|
Route::get('/property/{id}', function (int $id) {
|
||||||
|
@ -92,14 +103,38 @@ Route::get('/region/{id}', function (int $id) {
|
||||||
$regionBaseAll = Api::regionBase(-1);
|
$regionBaseAll = Api::regionBase(-1);
|
||||||
$regionBaseAll[] = ['region_name' => 'Alle Regionen', 'region_id' => -1];
|
$regionBaseAll[] = ['region_name' => 'Alle Regionen', 'region_id' => -1];
|
||||||
$regionBaseRegion = $id >= 0 ? Api::regionBase($id) : [['region_name' => 'Alle Regionen']];
|
$regionBaseRegion = $id >= 0 ? Api::regionBase($id) : [['region_name' => 'Alle Regionen']];
|
||||||
$regionMovingAverage = Api::regionMovingAverage($id, '2024-04-25');
|
|
||||||
|
|
||||||
$regionPropertiesCapacities = Api::regionPropertiesCapacities($id);
|
$regionPropertiesCapacities = Api::regionPropertiesCapacities($id);
|
||||||
$regionCapacitiesRegion = Api::regionCapacities($id);
|
$regionCapacitiesRegion = Api::regionCapacities($id);
|
||||||
$regionCapacitiesAll = Api::regionCapacities(-1);
|
$regionCapacitiesAll = Api::regionCapacities(-1);
|
||||||
$regionCapacities = [$regionCapacitiesAll, $regionCapacitiesRegion];
|
|
||||||
|
|
||||||
return view('region', ['regions' => $regionBaseAll, 'region' => $regionBaseRegion, 'region_id' => $id, 'regionCapacities' => $regionCapacities, 'regionPropertiesCapacities' => $regionPropertiesCapacities, 'prediction' => $regionMovingAverage]);
|
$regionCapacitiesMonthly = [];
|
||||||
|
$regionCapacitiesDaily = [];
|
||||||
|
$regionPredictions = [];
|
||||||
|
|
||||||
|
foreach ($regionCapacitiesRegion['dates'] as $date) {
|
||||||
|
$regionCapacitiesMonthly[] = Api::regionCapacitiesMonthly($id, $date);
|
||||||
|
$regionCapacitiesDaily[] = Api::regionCapacitiesDaily($id, $date);
|
||||||
|
$regionPredictions[] = Api::regionMovingAverage($id, $date);
|
||||||
|
}
|
||||||
|
|
||||||
|
$regionCapacities = [
|
||||||
|
'all' => $regionCapacitiesAll,
|
||||||
|
'region' => $regionCapacitiesRegion,
|
||||||
|
'region_monthly' => $regionCapacitiesMonthly,
|
||||||
|
'region_daily' => $regionCapacitiesDaily
|
||||||
|
|
||||||
|
];
|
||||||
|
|
||||||
|
dump($regionPredictions);
|
||||||
|
|
||||||
|
return view('region', [
|
||||||
|
'regions' => $regionBaseAll,
|
||||||
|
'region' => $regionBaseRegion,
|
||||||
|
'region_id' => $id,
|
||||||
|
'regionCapacities' => $regionCapacities,
|
||||||
|
'regionPropertiesCapacities' => $regionPropertiesCapacities,
|
||||||
|
'predictions' => $regionPredictions]);
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue