dashboard einzelansicht trend auslastung.
parent
4b7067fb63
commit
47a5035787
|
@ -2,4 +2,5 @@
|
|||
|
||||
## Projektstruktur
|
||||
- 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");
|
||||
}
|
||||
|
||||
public static function propertyCapacities(int $id)
|
||||
{
|
||||
return self::get("/property/{$id}/capacities");
|
||||
}
|
||||
|
||||
public static function propertyBase(int $id): mixed
|
||||
{
|
||||
return self::get("/property/{$id}/base");
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
@endforeach
|
||||
</dl>
|
||||
</article>
|
||||
<article class="header">
|
||||
<article class="header" style="grid-row-start: 1; grid-row-end: 3;">
|
||||
<header>
|
||||
<h2 id="belegung-title">
|
||||
Belegung am {{ json_decode($extractiondates)[0] }}
|
||||
|
@ -29,7 +29,52 @@
|
|||
</header>
|
||||
<div id="chart-calendar"></div>
|
||||
</article>
|
||||
<article class="header">
|
||||
<header>
|
||||
<h2>
|
||||
Entwicklung der Verfügbarkeit
|
||||
</h2>
|
||||
</header>
|
||||
<div id="chart-capacity"></div>
|
||||
</article>
|
||||
<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 cCalendar = echarts.init(chartCalendar);
|
||||
const h2Belegung = document.getElementById('belegung-title');
|
||||
|
@ -70,18 +115,26 @@ const cCalendarOptions = {
|
|||
orient: 'horizontal',
|
||||
range: '2024',
|
||||
top: 50,
|
||||
right: 0,
|
||||
right: 10,
|
||||
left: 50,
|
||||
bottom: "55%"
|
||||
bottom: "66%"
|
||||
},
|
||||
{
|
||||
orient: 'horizontal',
|
||||
range: '2025',
|
||||
right: 100,
|
||||
right: 10,
|
||||
left: 50,
|
||||
bottom: 60,
|
||||
top: '55%'
|
||||
top: '43%',
|
||||
bottom: '43%'
|
||||
},
|
||||
{
|
||||
orient: 'horizontal',
|
||||
range: '2026',
|
||||
right: 10,
|
||||
left: 50,
|
||||
top: '66%',
|
||||
bottom: '10%'
|
||||
}
|
||||
],
|
||||
options: [
|
||||
@foreach ($calendar as $c)
|
||||
|
@ -97,6 +150,12 @@ const cCalendarOptions = {
|
|||
coordinateSystem: 'calendar',
|
||||
calendarIndex: 1,
|
||||
data: {!! json_encode($c) !!}
|
||||
},
|
||||
{
|
||||
type: 'heatmap',
|
||||
coordinateSystem: 'calendar',
|
||||
calendarIndex: 2,
|
||||
data: {!! json_encode($c) !!}
|
||||
}]
|
||||
},
|
||||
@endforeach
|
||||
|
@ -105,9 +164,35 @@ const cCalendarOptions = {
|
|||
|
||||
cCalendar.setOption(cCalendarOptions);
|
||||
cCalendar.on('timelinechanged', (e) => {
|
||||
|
||||
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>
|
||||
@endsection
|
||||
|
|
|
@ -17,7 +17,6 @@ Route::get('/', function () {
|
|||
}
|
||||
|
||||
$propertiesGeo = Api::propertiesGeo();
|
||||
//dump($propertiesGeo);
|
||||
|
||||
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);
|
||||
$extractions = Api::propertyExtractions($id);
|
||||
$propertyCapacities = Api::propertyCapacities($id);
|
||||
$data = [];
|
||||
$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
|
||||
version: 0.1.0
|
||||
path: .
|
||||
sha256: 878bb6af1502cc9ac71feab6f184f593077f134626d6f8c552e9bcafb178f6b4
|
||||
sha256: c09f63486f0dd4151008de68ef73d00f72663dc3cc47894ff750d517f898a23b
|
||||
requires_python: '>=3.11'
|
||||
editable: true
|
||||
- kind: conda
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import data
|
||||
import polars as pl
|
||||
from data import etl_property_capacities as etl_pc
|
||||
from fastapi import FastAPI, Response
|
||||
|
||||
d = data.load()
|
||||
|
@ -34,6 +35,11 @@ def properties_geo():
|
|||
def property_extractions(id: int):
|
||||
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")
|
||||
def property_base_data(id: int):
|
||||
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