First Commit

This commit is contained in:
2025-11-02 22:52:08 +01:00
commit 73fbbf1be2
5821 changed files with 977526 additions and 0 deletions

View File

@@ -0,0 +1,824 @@
/**
*
*/
// Nach dem Laden des Dokumentes:
$(document).ready(function() {
// Globals:
const url = "php/statistic.php";
const months = ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember' ];
const colors = { besucher: ['#FFB60A','#FF6702','#E54818'], aktivitaet: ['#D1D8D1','#ABC1C5','#81ACBC'], gesamt: ['#CBD26A','#88AD63','#5A8A40'] };
const barsPerPage = 23;
let privilege = checkQuery(location.search)
var useYear = (new Date()).getFullYear(); // <======= TODO moment verwenden!
Highcharts.setOptions({
lang:{
numericSymbols: null
}
});
// die Übergabe parsen und analysieren
function checkQuery(s) {
if (s != '') {
let p = s.split('=');
if((p[0] == '?besucher') && (p[1]=='olersituv6p9')) {
return true;
}
}
return false;
}
$('#versn').html("Version: " + VERSION + ' vom ' + VDATE);
// Selectbox füllen und Default ewinstellen
// Event für den Jahr-Button
function fillSelectBox(year) {
$('#jsel').empty();
$.getJSON(url, {cmd: 'GET_YEARS'}, function (daten, err) {
if(err != 'success') {
alert("Fehler <br />" + err); // if error, show it
} else {
let flag=false;
for(let i=0; i<daten.length; i++) {
if (daten[i] == year) {
flag=true;
$('#jsel').append("<option value="+daten[i]+" selected>"+daten[i]+"</option>");
} else {
$('#jsel').append("<option value="+daten[i]+">"+daten[i]+"</option>");
}
}
if(!flag) {
$('#jsel').prepend("<option value="+year+" selected>"+year+"</option>");
}
}
});
}
function showGesamtStatistik() {
$('#allbutt').text('Jahr');
$('#djbutton').hide();
$('#Eingabe').hide();
$('#plot1').empty();
$('#plot2').empty();
$('#plot1').css('border','none');
$('#plot2').css('border','none');
getData('gesamt',false,false);
}
function showJahresStatistik(y,animate,store) {
$('#allbutt').text('Gesamt');
if(privilege) {
$('#Eingabe').show();
}
$('#plot3').empty();
$('#plot3').css('border','none');
$('#djbutton').show();
if(animate == true) {
optBesucher.plotOptions.series.animation = true;
optAktivi.plotOptions.series.animation = true;
} else {
optBesucher.plotOptions.series.animation = false;
optAktivi.plotOptions.series.animation = false;
}
getData('year',false,y,store);
}
// Event für den Gesamt-Button:
$('#allbutt').click( function() {
if($('#allbutt').text() == 'Gesamt') {
showGesamtStatistik();
} else {
showJahresStatistik(useYear,true,false);
}
});
// Event für den Eingabe-Button
$('#Eingabe').click(function() {
$('#entryDialog').dialog('open');
});
// Event für die SelectBox
$('#jsel').change(function() {
useYear = $(this).val();
showJahresStatistik(useYear,true,false);
});
var optBesucher = {
chart: {
type: 'column',
height: 380,
borderColor: '#FF0000',
borderWidth: 1
},
title: {
style: {
fontWeight: 'bold',
}
},
xAxis: {
categories: months,
},
yAxis: {
min: 0,
title: {
text: 'Besucher'
},
stackLabels: {
enabled: true,
align: 'center',
style: {
fontWeight: 'bold',
color: (Highcharts.theme && Highcharts.theme.textColor) || 'gray',
},
}
},
legend: {
align: 'right',
layout: 'vertical',
verticalAlign: 'middle',
backgroundColor: (Highcharts.theme && Highcharts.theme.background2) || 'white',
borderColor: '#CCC',
borderWidth: 1,
shadow: false,
useHTML: true
},
tooltip: {
formatter: function() {
let s= '<b>' + this.x + '</b><br/>';
s += this.series.name +': ' + this.y +'<br/>Total: ' + this.point.stackTotal;
return s
}
},
plotOptions: {
column: {
stacking: 'normal',
},
series: {
animation: true,
}
},
};
var optAktivi = {
chart: {
type: 'column',
height: 380,
borderColor: '#FF0000',
borderWidth: 1
},
title: {
style: {
fontWeight: 'bold',
}
},
xAxis: {
categories: months,
},
yAxis: {
min: 0,
title: {
text: 'Anzahl'
},
stackLabels: {
enabled: true,
style: {
fontWeight: 'bold',
color: (Highcharts.theme && Highcharts.theme.textColor) || 'gray',
}
}
},
tooltip: {
formatter: function() {
let s= '<b>' + this.x + '</b><br/>';
s += this.series.name +': ' + this.y +'<br/>Total: ' + this.point.stackTotal;
return s
}
},
plotOptions: {
column: {
stacking: 'normal',
dataLabels: {
enabled: true,
color: 'black',
style: {
textOutline: 'none'
}
},
},
series: {
animation: true,
}
},
};
var optGesamt = {
chart: {
events: {
load: function() {
this.xAxis[0].setExtremes(2008,2022);
}
},
type: 'column',
height: 380,
borderColor: '#FF0000',
borderWidth: 1,
panning: true
},
title: {
style: {
fontWeight: 'bold',
}
},
legend: {
align: 'right',
layout: 'vertical',
verticalAlign: 'middle',
backgroundColor: (Highcharts.theme && Highcharts.theme.background2) || 'white',
borderColor: 'black',
borderWidth: 1,
shadow: false,
},
tooltip: {
formatter: function() {
let s = '<b>'+ this.x + '</b><br/>';
s += this.series.name +': ' + this.y;
return s;
}
},
plotOptions: {
column: {
// pointPadding: 0.2,
borderWidth: 0,
dataLabels: {
enabled: true,
color: 'gray',
formatter: function () {
return this.y;
},
style: {
textOutline: 'none'
}
},
},
series: {
pointWidth: 10,
groupPadding: 0.1,
},
},
yAxis: {
min: 0,
max: 4000,
title:{
text: "",
}
},
xAxis: {
tickInterval: 1
}
};
// die Summen in die Summen-Tabewlle eintragen (überschreiben)
function saveSummen(year, sb, sa) {
// HACK: die Dten für bemG aus dem HTML.feld lesen (das ist noch gültig!)
let bmg = $('#ie_bemerkungGes').val();
let cmd = { cmd: "CRUP_G", toInsert: {jahr: year, sumb: sb, suma: sa, bemG: bmg} };
doAjaxCall_arr(url, cmd, null);
}
function getData(what,entry,year,storeSum) {
let cmd = { cmd: "GET_ALL_G"};
if (what == 'year') {
cmd = { cmd: "GET_ALL_A", jahr: year };
}
$.getJSON(url, cmd, function(daten,err) { // AJAX Call
if(err != 'success') {
alert("Fehler <br />" + err); // if error, show it
} else {
if (entry == true) {
buildEntryScreen(data)
} else {
if (what == 'year') {
var data = daten.data;
var dt = [];
for(let i = 0; i< data.length; i++) {
dt.push(parseData(data[i]));
}
let dx = { data: dt, sumA: parseInt(daten.sumA),sumB: parseInt(daten.sumB), sumBT: parseInt(daten.sumBT), sumBZ: parseFloat(daten.sumBZ), bemG: daten.bemG}
if(storeSum == true) {
saveSummen(year, dx.sumB, dx.sumA);
}
// console.log(dx);
plotBars(dx,what);
} else {
let d = daten.data;
let dx = [];
for(let i = 0; i< d.length; i++) {
var entry = {};
for (key in d[i]) {
if (key != 'bemerkung') {
entry[key] = parseInt(d[i][key]);
} else {
entry[key] = d[i][key];
}
}
dx.push(entry);
}
let dt = { data: dx, lastMonth: findLastMonth(daten.lastDate.fullYear), lastYear: daten.lastDate.lastYear, sumA: parseInt(daten.sumA),sumB: parseInt(daten.sumB) }
// console.log(dt);
plotBars(dt,what);
}
}
}
});
}
// Den letzen belegten Monat aus den Daten des Jahres finden und als Nummer (1..12) übergeben
function findLastMonth(data) {
if (data.length < 12) {
return data.length;
}
data.sort(function(a,b) {return (a.datum > b.datum) ? 1 : ((b.datum > a.datum) ? -1 : 0);});
let lm = 12;
for (let month = 11; month>0; month--) {
let flag = true;
for (let x in data[month]) {
if (x == 'datum') {
continue;
}
if (data[month][x] != 0) {
flag = false;
break;
}
}
if (flag) {
lm = month;
}
}
console.log("Monat: ", lm);
return lm;
}
function plotBars(daten, what) {
let monat=0;
let seriesbt = [];
let seriesbs = [];
let seriesbn = [];
let seriesBem = [];
let seriestd = [];
let seriesbeo = [];
let seriesfue = [];
let seriesbeot = [];
let seriesbeoz = [];
let data = daten.data;
let seltTotals = false;
if(what == 'year') {
// Einlesen der Daten in die Serien
$.each(data, function(i){
monat += 1;
seriesbt.push(this.besucherToT == 0 ? null : this.besucherToT);
seriesbs.push(this.besucherSonder == 0 ? null : this.besucherSonder);
seriesbn.push(this.besucherNormal == 0 ? null : this.besucherNormal);
seriestd.push(this.techdienst == 0 ? null : this.techdienst);
seriesbeo.push(this.beobachtungen == 0 ? null : this.beobachtungen);
seriesfue.push(this.fuehrungen == 0 ? null : this.fuehrungen);
seriesbeoz.push(this.beoZeit == 0 ? null : this.beoZeit);
seriesbeot.push(this.beoTage == 0 ? null : this.beoTage);
seriesBem.push(this.bemerkung);
});
// nicht belegte Monate des Jahres mit 'null' auffüllen
monat += 1;
for (; monat <13; monat++) {
seriesbn.push(null);
seriesfue.push(null);
}
// Plot für die Besucherzahlen
optBesucher.title.text = "Besucherzahlen "+ useYear;
optBesucher.series = [];
if(useYear >= 2015) { // Neu Auswertung ab 2015
selfTotals = true;
optBesucher.series[0] = { data : seriesbt, name: 'Tag der offenen Tür', color: colors.besucher[0] };
optBesucher.series[1] = { data : seriesbs, name: 'Sonderführungen', color: colors.besucher[1] };
optBesucher.series[2] = { data : seriesbn, name: 'Reguläre Führungen', color: colors.besucher[2] } ;
optBesucher.yAxis.stackLabels = { enabled: false};
optBesucher.plotOptions.column.dataLabels= {
enabled: true,
color: 'black',
style: {
textOutline: 'none'
},
formatter: function() {
if(this.y > 5) {
return(this.y);
}
}
};
optBesucher.legend.labelFormatter = function() {
if (this.name.startsWith('Regul')) {
return this.name + "<br /><br /> Gesamt: " + daten.sumB;
} else {
return this.name;
}
}
} else { // Alte Auswertung vor 2015
selfTotals = false;
optBesucher.series[0] = {data: seriesbn, name:'Besucher', color: colors.besucher[2]};
optBesucher.plotOptions.column.dataLabels= {};
optBesucher.yAxis.stackLabels = { enabled: true, align: 'center',
style: { fontWeight: 'bold', color: (Highcharts.theme && Highcharts.theme.textColor) || 'gray', },
}
optBesucher.legend.labelFormatter = function() {
return this.name + "<br /><br /> Gesamt: " + daten.sumB;
};
}
doThePlot('plot1','Besucher',seriesBem,selfTotals);
// Plot für die Aktivitäten (bzw. bei den Alten Daten für die Beo-Zeit und Beo-Tage)
optAktivi.title.text= "Aktivitäten " + useYear;
optAktivi.series = [];
optAktivi.legend = {
align: 'right',
layout: 'vertical',
verticalAlign: 'middle',
backgroundColor: (Highcharts.theme && Highcharts.theme.background2) || 'white',
borderColor: '#CCC',
borderWidth: 1,
shadow: false,
useHTML: true
};
if(useYear >= 2015) {
optAktivi.series[0] = { name: 'Technischer Dienst', color: colors.aktivitaet[0], data: seriestd };
optAktivi.series[1] = { name: 'Beobachtungen', color: colors.aktivitaet[1], data: seriesbeo };
optAktivi.series[2] = { name: 'Führungen', color: colors.aktivitaet[2], data: seriesfue };
optAktivi.plotOptions.column.stacking = 'normal';
optAktivi.legend.labelFormatter = function() {
if (this.name.startsWith('F')) {
return this.name + "<br /><br /> Gesamt: " + daten.sumA;
} else {
return this.name;
}
}
} else {
optAktivi.plotOptions.column.stacking = null;
optAktivi.series[0] = { name: 'Beobachtungs-Zeit', color: colors.aktivitaet[1], data: seriesbeoz };
optAktivi.series[1] = { name: 'Beobachtungs-Tage', color: colors.aktivitaet[2], data: seriesbeot };
optAktivi.yAxis.title.text = '<span style="color:'+colors.aktivitaet[1]+';">Tage</span> / <span style="color:'+colors.aktivitaet[2]+';">Stunden</span>';
optAktivi.legend.labelFormatter = function() {
if(this.name == 'Beobachtungs-Zeit') {
return this.name + "<br /> Gesamt: " + daten.sumBZ + " h";
} else {
return this.name + "<br /> Gesamt: " + daten.sumBT + "<br />";
}
}
};
doThePlot('plot2','Aktivitaet',null, false);
} else { // what == 'gesamt'
// Daten für die Geamt-Übersicht einlesen
$.each(data, function(i){
seriesfue.push([this.jahr, this.aktivitaeten == 0 ? null : this.aktivitaeten]);
seriesbn.push([this.jahr, this.besucher == 0 ? null : this.besucher]);
seriesBem.push([this.jahr,this.bemerkung]);
});
optGesamt.series = [];
optGesamt.series[0] = { name: 'Beo-Tage', color: colors.gesamt[0], data: seriesfue, total: daten.sumA };
optGesamt.series[1] = { name: 'Besucher', color: colors.gesamt[2], data: seriesbn, total: daten.sumB };
// Da die gesamten Daten auf einem Plot nicht gut aussehen, wird hier auf
// 2 bis 4 Plots aufgespalten (jeder Plot hat max. 15 Einträge --> 60 Jahre !!
var steps = Math.floor(seriesfue.length / barsPerPage);
var st = [1992];
var slic = [0];
for (let i=0; i<= steps; i++) {
st.push(st[st.length-1]+barsPerPage);
slic.push(slic[slic.length-1]+barsPerPage);
}
for(let j=1,i=st.length-2; i>=0; i--,j++) {
if ((st[i] < daten.lastYear) && ((st[i+1]-1) >= daten.lastYear)) {
if(daten.lastMonth != 12) {
optGesamt.title.text = "Betriebsstatistik " + st[i] + " - " + months[daten.lastMonth-1] +" "+daten.lastYear;
} else {
optGesamt.title.text = "Betriebsstatistik " + st[i] + "-" + daten.lastYear;
}
} else {
optGesamt.title.text = "Betriebsstatistik " + st[i] + "-" + (st[i+1]-1);
}
optGesamt.chart. events = {
load: function() {
this.xAxis[0].setExtremes(st[i],st[i+1]-1);
}
};
if(st[i] < 2015) {
optGesamt.yAxis.title.text = '<span style="color:'+colors.gesamt[0]+';">Beo-Tage</span> / <span style="color:'+colors.gesamt[2]+';">Besucher</span>';
optGesamt.legend.labelFormatter = function() {
return this.name;
}
} else {
optGesamt.yAxis.title.text = '<span style="color:'+colors.gesamt[0]+';">Aktivitäten</span> / <span style="color:'+colors.gesamt[2]+';">Besucher</span>';
optGesamt.legend.labelFormatter = function() {
if(this.name == 'Besucher') {
return this.name + '<br /><span style="color:gray;">Summe (1992 bis jetzt):<br />'+this.options.total+'</span><br />';
} else {
return "Aktivitäten" + '<br /><span style="color:gray;">Summe (1992 bis jetzt):<br />'+this.options.total+'</span><br />';
}
};
}
doThePlot('plot'+j,what, seriesBem.slice(slic[i],slic[i+1]),false);
}
}
}
function doThePlot(p,w,s,t) {
let opt = optAktivi;
if (w == 'Besucher') {
opt = optBesucher;
} else if (w=='gesamt') {
opt = optGesamt;
}
Highcharts.chart(p, opt , function(chart) {
if ((s == undefined ) || (s.length == 0)) {
return;
};
var tx = "<div>"
for (let i=0; i< s.length; i++) {
if(w == 'Besucher') {
if(!((s[i] == "") || (s[i] == null))) {
tx += months[i] +": " + s[i] + "<br />";
}
} else {
if(!((s[i][1] == "") || (s[i][1] == null))) {
tx += s[i][0] +": " + s[i][1] + "<br />";
}
}
}
tx += "</div>";
var text = chart.renderer.label(
tx,
850,
40,'rect',0,0,true)
.css({
fontSize:'10pt',
color: 'gray'})
.add();
if(t == true) {
var tt = bauTotals(chart);
$.each(tt,function(i, t){
chart.renderer.label(
t.t,
t.x,
t.y,
'rect',0,0,true)
.css({ fontSize:'8pt', color: 'gray', fontWeight: 'bold'})
.add();
});
}
});
}
function bauTotals(chart) {
var totals = [];
var plotLeft = chart.plotLeft;
var plotTop = chart.plotTop-20;
for(var i=0; i<chart.series[0].points.length; i++) {
var p = chart.series[0].points[i];
if(p.stackTotal === undefined) {
p = chart.series[1].points[i];
if(p.stackTotal === undefined) {
p = chart.series[2].points[i];
}
}
var offset = -14;
if (p.stackTotal < 100) { offset = -10;}
totals.push({x: p.plotX+plotLeft+offset, y: p.plotY+plotTop, t: p.stackTotal});
}
return totals;
}
// Daten mit gegebenen Datum holen und anzeigen
function getNewData(d,mark) {
$.getJSON(url,{cmd:'GET_ONE_A', datum:d}, function(daten,err) {
if(err != 'success') {
alert("Fehler <br />" + err); // if error, show it
} else {
if (!((daten == null) || (daten.length == 0))) {
fillEntry(parseData(daten),mark);
} else {
clearEntry();
}
}
});
}
function parseData(daten) {
var entry = {};
for (key in daten) {
if ((key == 'datum') || (key == 'bemerkung') || (key == 'bemG')) {
entry[key] = daten[key];
} else {
if(isNaN(daten[key])) {
entry[key] = 0;
}
if (key == 'beoZeit') {
entry[key] = parseFloat(daten[key]);
} else {
entry[key] = parseInt(daten[key]);
}
}
}
return entry;
}
function fillEntry(daten,mark) {
for (let x in daten) {
if (daten[x] == 0) {
daten[x] = "";
}
}
$('#ie_besucherN').val(daten.besucherNormal);
$('#ie_besucherS').val(daten.besucherSonder);
$('#ie_besucherT').val(daten.besucherToT);
$('#ie_fuehrungen').val(daten.fuehrungen);
$('#ie_beobachtungen').val(daten.beobachtungen);
$('#ie_techDienst').val(daten.techdienst);
$('#ie_bemerkung').val(daten.bemerkung);
$('#ie_bemerkungGes').val(daten.bemG);
$('#ie_beoTage').val(daten.beoTage);
$('#ie_beoZeit').val(daten.beoZeit);
let year = $('#ie_jahr').val();
if (year >= 2015) {
$('#kl2015').hide();
$('#gr2015').show();
} else {
$('#gr2015').hide();
$('#kl2015').show();
}
if (mark==true) {
$('.ie_buttons').css('color','limegreen');
} else {
$('.ie_buttons').css('color','black');
}
}
$('.ie_buttons').click(function() {
$(this).css('color','black');
});
function clearEntry(daten) {
$('#ie_besucherN').val('');
$('#ie_besucherS').val('');
$('#ie_besucherT').val('');
$('#ie_fuehrungen').val('');
$('#ie_beobachtungen').val('');
$('#ie_techDienst').val('');
$('#ie_bemerkung').val('');
$('#ie_bemerkungGes').val('');
$('#ie_beoTage').val('');
$('#ie_beoZeit').val('');
let year = $('#ie_jahr').val();
if (year >= 2015) {
$('#kl2015').hide();
$('#gr2015').show();
} else {
$('#gr2015').hide();
$('#kl2015').show();
}
$('.ie_buttons').css('color','black');
}
function buildEntryScreen() {
let now = moment();
let datum='';
now.subtract(1,'M');
let y=now.year();
let m=now.month();
if((now.year() == useYear) || ((now.year() == useYear-1) && (now.month() == 11))) {
$('#ie_jahr').val(now.year());
$('#ie_monat').val(months[now.month()]);
datum = now.format('YYYY-MM-01');
} else {
$('#ie_jahr').val(useYear);
$('#ie_monat').val(months[11]);
datum = useYear +'-12-01';
}
console.log(datum);
getNewData(datum,false);
}
// Daten in die Datenbank schreiben
function saveSettings() {
let toInsert = {};
toInsert.besN = $('#ie_besucherN').val();
toInsert.besS = $('#ie_besucherS').val();
toInsert.besT = $('#ie_besucherT').val();
toInsert.fueh = $('#ie_fuehrungen').val();
toInsert.beob = $('#ie_beobachtungen').val();
toInsert.tech = $('#ie_techDienst').val();
toInsert.beme = $('#ie_bemerkung').val();
toInsert.beoT = $('#ie_beoTage').val();
toInsert.beoZ = $('#ie_beoZeit').val();
toInsert.datum = buildDate();
for (var w in toInsert) {
if(!toInsert.hasOwnProperty(w)) {
continue;
}
if((toInsert[w] == "") && (w != 'beme')) {
toInsert[w] = "0";
}
}
var arr = {cmd:'CRUP_A',toInsert:toInsert};
doAjaxCall_arr(url,arr,fromInsert) // Neue Daten eintragten
}
function fromInsert(erg) { // CallBack für Insert/Update
let y = JSON.parse(erg);
console.log("From Insert/Update: ",y); // Rückgabe ausgeben
var d = moment(y.datum);
useYear = d.year();
getNewData(d.format('YYYY-MM-01'),true); // Daten wieder aus der DB lesen und anzeigen
showJahresStatistik(d.year(),false,true);
fillSelectBox(d.year());
}
function buildDate() {
let idx = $('#ie_monat').prop('selectedIndex')+1;
if (idx < 10) {
idx = "0"+idx;
} else {
idx = ""+idx;
}
let x = $('#ie_jahr').val() + "-" + idx + "-01";
return moment(x).format("YYYY-MM-01");
}
// Dialog zun Anzeigen und Editieren eines Eintrages
$('#entryDialog').dialog({
autoOpen: false,
width: 400,
position: { my: 'top', at: 'top' , of: '#plot1'},
title: 'Eingabe',
open:
function(evt,ui) {
$(this).load('eingabe.html', function() {
buildEntryScreen();
// Events: Ändern des Jahres oder des Monats: Daten neu einlesen
$('#ie_monat').change(function() {
getNewData(buildDate(),false);
});
$('#ie_jahr').change(function() {
getNewData(buildDate(),false);
});
});
},
buttons: [
{
text: "Sichern",
click: function () {
saveSettings();
},
width: 130,
tabIndex: -1
},
// {
// text: "Löschen",
// click: function() {
// $('#entryloesch').dialog("open");
// },
// width: 130,
// tabIndex: -1
// },
{
text: "Beenden",
click : function() {
$(this).dialog("close");
},
width: 130,
tabIndex: -1
}],
modal: true,
close: function() {
// $(this).remove();
},
}); // end of dialog
if (!privilege) {
$('#Eingabe').css('display','none');
}
fillSelectBox(useYear);
getData('year',false,useYear,false);
});