dashboard einzelansicht trend auslastung.
parent
4b7067fb63
commit
47a5035787
|
@ -3,3 +3,4 @@
|
||||||
## Projektstruktur
|
## Projektstruktur
|
||||||
- etl: Enthält den Programmcode, welcher die Daten aufbereitet und via REST-API zur Verfügung stellt.
|
- etl: Enthält den Programmcode, welcher die Daten aufbereitet und via REST-API zur Verfügung stellt.
|
||||||
- dashboard: Webapplikation zur Exploration und Visualisierung der Daten.
|
- dashboard: Webapplikation zur Exploration und Visualisierung der Daten.
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,11 @@ class Api
|
||||||
return self::get("/property/{$id}/extractions");
|
return self::get("/property/{$id}/extractions");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function propertyCapacities(int $id)
|
||||||
|
{
|
||||||
|
return self::get("/property/{$id}/capacities");
|
||||||
|
}
|
||||||
|
|
||||||
public static function propertyBase(int $id): mixed
|
public static function propertyBase(int $id): mixed
|
||||||
{
|
{
|
||||||
return self::get("/property/{$id}/base");
|
return self::get("/property/{$id}/base");
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
@endforeach
|
@endforeach
|
||||||
</dl>
|
</dl>
|
||||||
</article>
|
</article>
|
||||||
<article class="header">
|
<article class="header" style="grid-row-start: 1; grid-row-end: 3;">
|
||||||
<header>
|
<header>
|
||||||
<h2 id="belegung-title">
|
<h2 id="belegung-title">
|
||||||
Belegung am {{ json_decode($extractiondates)[0] }}
|
Belegung am {{ json_decode($extractiondates)[0] }}
|
||||||
|
@ -29,7 +29,52 @@
|
||||||
</header>
|
</header>
|
||||||
<div id="chart-calendar"></div>
|
<div id="chart-calendar"></div>
|
||||||
</article>
|
</article>
|
||||||
|
<article class="header">
|
||||||
|
<header>
|
||||||
|
<h2>
|
||||||
|
Entwicklung der Verfügbarkeit
|
||||||
|
</h2>
|
||||||
|
</header>
|
||||||
|
<div id="chart-capacity"></div>
|
||||||
|
</article>
|
||||||
<script type="module">
|
<script type="module">
|
||||||
|
const chartCapacity = document.getElementById('chart-capacity');
|
||||||
|
const cCapacity = echarts.init(chartCapacity);
|
||||||
|
|
||||||
|
const cCapacityOptions = {
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis'
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
left: '0',
|
||||||
|
right: 10,
|
||||||
|
bottom: '0',
|
||||||
|
containLabel: true
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: 'category',
|
||||||
|
boundaryGap: false,
|
||||||
|
data: {!! json_encode($capacities['dates']) !!}
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'value',
|
||||||
|
min: 0,
|
||||||
|
max: 100
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: 'Alle',
|
||||||
|
type: 'line',
|
||||||
|
stack: 'Total',
|
||||||
|
symbolSize: 7,
|
||||||
|
data: {!! json_encode($capacities['capacities']) !!}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
cCapacity.setOption(cCapacityOptions);
|
||||||
|
|
||||||
|
|
||||||
const chartCalendar = document.getElementById('chart-calendar');
|
const chartCalendar = document.getElementById('chart-calendar');
|
||||||
const cCalendar = echarts.init(chartCalendar);
|
const cCalendar = echarts.init(chartCalendar);
|
||||||
const h2Belegung = document.getElementById('belegung-title');
|
const h2Belegung = document.getElementById('belegung-title');
|
||||||
|
@ -70,18 +115,26 @@ const cCalendarOptions = {
|
||||||
orient: 'horizontal',
|
orient: 'horizontal',
|
||||||
range: '2024',
|
range: '2024',
|
||||||
top: 50,
|
top: 50,
|
||||||
right: 0,
|
right: 10,
|
||||||
left: 50,
|
left: 50,
|
||||||
bottom: "55%"
|
bottom: "66%"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
orient: 'horizontal',
|
orient: 'horizontal',
|
||||||
range: '2025',
|
range: '2025',
|
||||||
right: 100,
|
right: 10,
|
||||||
left: 50,
|
left: 50,
|
||||||
bottom: 60,
|
top: '43%',
|
||||||
top: '55%'
|
bottom: '43%'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
orient: 'horizontal',
|
||||||
|
range: '2026',
|
||||||
|
right: 10,
|
||||||
|
left: 50,
|
||||||
|
top: '66%',
|
||||||
|
bottom: '10%'
|
||||||
|
}
|
||||||
],
|
],
|
||||||
options: [
|
options: [
|
||||||
@foreach ($calendar as $c)
|
@foreach ($calendar as $c)
|
||||||
|
@ -97,6 +150,12 @@ const cCalendarOptions = {
|
||||||
coordinateSystem: 'calendar',
|
coordinateSystem: 'calendar',
|
||||||
calendarIndex: 1,
|
calendarIndex: 1,
|
||||||
data: {!! json_encode($c) !!}
|
data: {!! json_encode($c) !!}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'heatmap',
|
||||||
|
coordinateSystem: 'calendar',
|
||||||
|
calendarIndex: 2,
|
||||||
|
data: {!! json_encode($c) !!}
|
||||||
}]
|
}]
|
||||||
},
|
},
|
||||||
@endforeach
|
@endforeach
|
||||||
|
@ -105,9 +164,35 @@ const cCalendarOptions = {
|
||||||
|
|
||||||
cCalendar.setOption(cCalendarOptions);
|
cCalendar.setOption(cCalendarOptions);
|
||||||
cCalendar.on('timelinechanged', (e) => {
|
cCalendar.on('timelinechanged', (e) => {
|
||||||
|
|
||||||
h2Belegung.innerText = "Belegung am "+cCalendarOptions.timeline.data[e.currentIndex];
|
h2Belegung.innerText = "Belegung am "+cCalendarOptions.timeline.data[e.currentIndex];
|
||||||
|
/*
|
||||||
|
series = cCalendarOptions.series[0].data
|
||||||
|
series[e.currentIndex]
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: 'Alle',
|
||||||
|
type: 'line',
|
||||||
|
stack: 'Total',
|
||||||
|
symbolSize: 7,
|
||||||
|
data: {!! json_encode($capacities['capacities']) !!}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
cCapacity.setOption({
|
||||||
|
|
||||||
|
|
||||||
})
|
})
|
||||||
|
*/
|
||||||
|
})
|
||||||
|
|
||||||
|
cCapacity.on('click', 'series', (e) => {
|
||||||
|
|
||||||
|
cCalendar.dispatchAction({
|
||||||
|
type: 'timelineChange',
|
||||||
|
currentIndex: e.dataIndex
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
|
@ -17,7 +17,6 @@ Route::get('/', function () {
|
||||||
}
|
}
|
||||||
|
|
||||||
$propertiesGeo = Api::propertiesGeo();
|
$propertiesGeo = Api::propertiesGeo();
|
||||||
//dump($propertiesGeo);
|
|
||||||
|
|
||||||
return view('overview', ["geo" => $propertiesGeo, "growth" => $propertiesGrowth, "propsPerRegion" => [json_encode($propsPerRegionName), json_encode($propsPerRegionCounts)]]);
|
return view('overview', ["geo" => $propertiesGeo, "growth" => $propertiesGrowth, "propsPerRegion" => [json_encode($propsPerRegionName), json_encode($propsPerRegionCounts)]]);
|
||||||
});
|
});
|
||||||
|
@ -26,6 +25,7 @@ Route::get('/prop/{id}', function (int $id) {
|
||||||
|
|
||||||
$propertyBase = Api::propertyBase($id);
|
$propertyBase = Api::propertyBase($id);
|
||||||
$extractions = Api::propertyExtractions($id);
|
$extractions = Api::propertyExtractions($id);
|
||||||
|
$propertyCapacities = Api::propertyCapacities($id);
|
||||||
$data = [];
|
$data = [];
|
||||||
$dates = [];
|
$dates = [];
|
||||||
|
|
||||||
|
@ -46,5 +46,5 @@ Route::get('/prop/{id}', function (int $id) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return view('property', ['base' => $propertyBase[0], "extractiondates" => json_encode($dates), "calendar" => $data]);
|
return view('property', ['base' => $propertyBase[0], "extractiondates" => json_encode($dates), "calendar" => $data, 'capacities' => $propertyCapacities]);
|
||||||
});
|
});
|
||||||
|
|
|
@ -2200,7 +2200,7 @@ packages:
|
||||||
name: consultancy-2
|
name: consultancy-2
|
||||||
version: 0.1.0
|
version: 0.1.0
|
||||||
path: .
|
path: .
|
||||||
sha256: 878bb6af1502cc9ac71feab6f184f593077f134626d6f8c552e9bcafb178f6b4
|
sha256: c09f63486f0dd4151008de68ef73d00f72663dc3cc47894ff750d517f898a23b
|
||||||
requires_python: '>=3.11'
|
requires_python: '>=3.11'
|
||||||
editable: true
|
editable: true
|
||||||
- kind: conda
|
- kind: conda
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import data
|
import data
|
||||||
import polars as pl
|
import polars as pl
|
||||||
|
from data import etl_property_capacities as etl_pc
|
||||||
from fastapi import FastAPI, Response
|
from fastapi import FastAPI, Response
|
||||||
|
|
||||||
d = data.load()
|
d = data.load()
|
||||||
|
@ -34,6 +35,11 @@ def properties_geo():
|
||||||
def property_extractions(id: int):
|
def property_extractions(id: int):
|
||||||
return d.extractions_for(property_id = id).pl().to_dicts()
|
return d.extractions_for(property_id = id).pl().to_dicts()
|
||||||
|
|
||||||
|
@app.get("/property/{id}/capacities")
|
||||||
|
def property_capacities_data(id: int):
|
||||||
|
capacities = etl_pc.property_capacities(id)
|
||||||
|
return capacities
|
||||||
|
|
||||||
@app.get("/property/{id}/base")
|
@app.get("/property/{id}/base")
|
||||||
def property_base_data(id: int):
|
def property_base_data(id: int):
|
||||||
return d.property_base_data(id).pl().to_dicts()
|
return d.property_base_data(id).pl().to_dicts()
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
from io import StringIO
|
||||||
|
|
||||||
|
import polars as pl
|
||||||
|
|
||||||
|
import data
|
||||||
|
|
||||||
|
d = data.load()
|
||||||
|
|
||||||
|
def property_capacities(id: int):
|
||||||
|
|
||||||
|
extractions = d.extractions_for(id).pl()
|
||||||
|
df_dates = pl.DataFrame()
|
||||||
|
|
||||||
|
for row in extractions.rows(named=True):
|
||||||
|
df_calendar = pl.read_json(StringIO(row['calendar']))
|
||||||
|
#df_calendar.insert_column(0, pl.Series("created_at", [row['created_at']]))
|
||||||
|
df_dates = pl.concat([df_calendar, df_dates], how="diagonal")
|
||||||
|
|
||||||
|
# order = sorted(df_dates.columns)
|
||||||
|
# df_dates = df_dates.select(order)
|
||||||
|
sum_hor = df_dates.sum_horizontal()
|
||||||
|
#print(sum_hor)
|
||||||
|
# Get the available dates per extraction
|
||||||
|
count_days = []
|
||||||
|
for dates in df_dates.rows():
|
||||||
|
# Remove all None values
|
||||||
|
liste = [x for x in dates if x is not None]
|
||||||
|
count_days.append(len(liste))
|
||||||
|
|
||||||
|
print(sum_hor)
|
||||||
|
counts = pl.DataFrame({"count_days" : count_days, "sum" : sum_hor})
|
||||||
|
result = {"capacities": [], "dates": extractions['created_at'].cast(pl.Datetime).to_list() }
|
||||||
|
|
||||||
|
for row in counts.rows(named=True):
|
||||||
|
max_capacity = row['count_days'] * 2
|
||||||
|
max_capacity_perc = 100 / max_capacity
|
||||||
|
result['capacities'].append(round(max_capacity_perc * row['sum'], 2))
|
||||||
|
result['capacities'].reverse()
|
||||||
|
return result
|
||||||
|
|
Loading…
Reference in New Issue