WIP WIP prepared for Geiger

This commit is contained in:
rxf
2023-07-02 20:22:58 +02:00
parent 9eb09e16ff
commit 5dc66dbaa2
22 changed files with 1764 additions and 295 deletions
+4 -3
View File
@@ -11,10 +11,10 @@ let optSidsArray = []; // Arrray der letzten 5 Einträge
let nbrofdaysforavg = 8; // Stundenmittel Anzahl Tagte (default = 5)
let nbrofdaysfordaynight = 30; // use 30 days or day/night graphic
let stucols = 1; // Anzeige nur Balken (StundenMittel)
let activeTab = 'maptab'; // active TAB ID
export const noise_ymin = 30; // lowest value on y-axis for noise
export const noise_ymax = 120; // highest value on y-axis for noise
let activeTab = 'maptab'; // active TAB ID
export let peaklim = 70; // threshold for peak count
export const url = '/api'
@@ -164,7 +164,7 @@ export async function addSensorID2chart(chart, sensor, width) {
let indoor = sensor.indoor || false
let addr = await addAddress(sensor.sid)
let sens = chart.renderer.label(
`Sensor: <span class="bigger">${sensor.sid}</span> ${indoor ? ' (indoor)' : ''}&nbsp;&nbsp;&nbsp;&nbsp;${addr}`,
`Sensor: <span class="bigger">${sensor.sid}</span> ${indoor ? ' (indoor)' : ''}&nbsp;&nbsp;&nbsp;&nbsp;${addr.street}, ${addr.plz} ${addr.city}`,
width / 2 - 100, 65,
'text', 0, 0, true)
.css({
@@ -177,7 +177,8 @@ export async function addSensorID2chart(chart, sensor, width) {
}
export const showError = (err) => {
document.querySelector('#dialogError .modal-dialog .modal-content .modal-body').setHTML(err)
let e = document.querySelector('#dialogError .modal-dialog .modal-content .modal-body')
e.innerHTML = err
let myModal = new bootstrap.Modal(document.getElementById('dialogError'))
myModal.show()
}
+2
View File
File diff suppressed because one or more lines are too long
+34 -250
View File
@@ -3,267 +3,51 @@
import * as dt from './datetime.js'
import * as utils from "./chart_utilities.js"
import { showChart, loadAll } from './showcharts.js'
import {fetchfromserver, addAddress} from "./chart_utilities.js";
import * as mapn from './map_noise.js'
import * as mapg from './map_geiger.js'
import * as mapu from './map_utilities.js'
let map = null
let bounds
let popuptext = ''
let clickedSensor = 0
let clickedcoords = {}
const colorscale = ['#d53e4f', '#fc8d59', '#fee08b', '#e6f598', '#99d594', '#3288bd', '#808080'];
const dba = [100, 80, 60, 40, 20, 0, -999];
const APIURL = '/api/getmapdata?'
const mapparams = {
map: null,
bounds: null,
popuptext: '',
clickedSensor: 0,
APIURL: '/api/getmapdata?',
MAXZOOM: 19
}
export async function showMap(params) {
utils.removeTabs()
if(map && map.remove) {
map.off();
map.remove();
if(sysparams.category === 'laerm') {
utils.removeTabs()
if(mapparams.map && mapparams.map.remove) {
mapparams.map.off();
mapparams.map.remove();
}
}
map = L.map('map', {scrollWheelZoom: false}).setView(params.center, parseInt(params.zoom))
mapparams.map = L.map('map', {scrollWheelZoom: false}).setView(params.center, parseInt(params.zoom))
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
maxZoom: mapparams.MAXZOOM,
attribution: '&copy; <a href="http://www.js.openstreetmap.org/copyright">OpenStreetMap</a>'
}).addTo(map)
bounds = map.getBounds();
}).addTo(mapparams.map)
mapparams.bounds = mapparams.map.getBounds();
map.on('moveend', async function () {
bounds = map.getBounds()
await buildMarkers(params)
mapparams.map.on('moveend', async function () {
mapparams.bounds = mapparams.map.getBounds()
await buildMarkers(params, mapparams)
});
let legend = L.control({position: 'bottomright'})
legend.onAdd = function (map) {
let div = L.DomUtil.create('div', 'info legend')
let div_color = L.DomUtil.create('div', 'info legend inner', div)
div_color.innerHTML += 'dbA<br />';
// loop through our density intervals and generate a label with a colored square for each interval
for (let i = 0; i < dba.length - 1; i++) {
div_color.innerHTML +=
'<i style="background:' + colorscale[i] + '"></i>' +
'&nbsp;&nbsp;' + dba[i] + (i == 0 ? '+' : '') + '<br />'
}
div_color.innerHTML += '&nbsp;<i style="background:' + getColor(dba[dba.length - 1]) + '"></i> offline'
return div
};
legend.addTo(map)
if(sysparams.category === 'laerm') {
mapn.buildLegend(mapparams)
}
let lastdate = await buildMarkers(params)
showLastDate(lastdate);
let lastdate = await buildMarkers(params, mapparams)
mapu.showLastDate(lastdate, mapparams);
}
function getColor(d) {
let val = parseInt(d);
for (let i = 0; i < dba.length; i++) {
if (val >= dba[i]) {
return (colorscale[i]);
}
const buildMarkers = async (params, mapparams) => {
if(sysparams.category === 'laerm') {
return mapn.buildMarkers(params, mapparams)
} else if(sysparams.category === 'multigeiger') {
return mapg.buildMarkers(params, mapparams)
}
}
function calcPolygon(bounds) {
return L.polygon([[bounds.getNorth(), bounds.getWest()], [bounds.getNorth(), bounds.getEast()], [bounds.getSouth(), bounds.getEast()], [bounds.getSouth(), bounds.getWest()]], {
color: 'black',
fillOpacity: 0.5
});
;
}
// With all Markers in cluster (markers) calculate the median
// of the values. With this median fetch the color and return it.
// If there are 'offline' sensors (value == -1) strip then before
// calculating the median. If there are only offline sensor, return
// color of value==-1 (dark gray).
function getMedian(markers) {
markers.sort(function (a, b) { // first sort, the lowest first
let y1 = a.options.value;
let y2 = b.options.value;
if (y1 < y2) {
return -1;
}
if (y2 < y1) {
return 1;
}
return 0;
});
// console.log(markers);
let i = 0; // now find the 'offlines' (value == -1)
for (i = 0; i < markers.length; i++) {
if (markers[i].options.value > 0) {
break;
}
}
markers.splice(0, i); // remove these from array
let lang = markers.length;
if (lang > 1) { //
if ((lang % 2) == 1) { // uneven ->
return getColor(markers[(Math.floor(lang / 2))].options.value); // median is in the middle
} else { // evaen ->
lang = lang / 2; // median is mean of both middle values
// console.log(lang);
let wert = (markers[lang - 1].options.value +
markers[lang].options.value) / 2;
return getColor(wert);
}
} else if (lang == 1) { // only one marker -> return its color
return getColor(markers[0].options.value);
}
return getColor(-1); // only offlines
}
function buildIcon(color, n, indoor) {
let x = 100;
if (n < 10) {
x = 200;
} else if (n < 100) {
x = 150;
}
let txtColor = "black";
if (color == colorscale[5]) {
txtColor = "white"
}
let circIcon = '<svg xmlns="http://www.w3.org/2000/svg" width="600" height="600">' +
'<circle cx="300" cy="300" r="250" fill="' + color + '" stroke="black" stroke-width="20" />';
if (n !== 0) {
circIcon +=
'<text id="marker_text" x="' + x + '" ' +
'y="400" font-size="1500%" font-family="Verdana,Lucida Sans Unicode,sans-serif" ' +
'fill="' + txtColor + '">' + n + '</text>';
}
if(indoor) {
circIcon += '<line x1="125" y1="475" x2="475" y2="125" stroke="black" stroke-width="20" />'
}
circIcon += '</svg>';
let circIconUrl = encodeURI("data:image/svg+xml," + circIcon).replace(new RegExp('#', 'g'), '%23');
return circIconUrl;
}
export async function buildMarkers(params) {
// debug_log('buildMarkers(bounds)');
const box = {
west: bounds.getWest(), south: bounds.getSouth(),
east: bounds.getEast(), north: bounds.getNorth()
}
const url = APIURL + `type=noise&box=${bounds.toBBoxString()}`
let sensors = await fetchfromserver(url)
if (!sensors.err) {
let markers = L.markerClusterGroup({
spiderfyOnMaxZoom: true,
showCoverageOnHover: false,
zoomToBoundsOnClick: true,
// disableClusteringAtZoom: 14,
iconCreateFunction: function (cluster) {
let mymarkers = cluster.getAllChildMarkers();
let color = getMedian(mymarkers);
return new L.Icon({
iconUrl: buildIcon(color, cluster.getChildCount(), 0),
iconSize: [35, 35]
});
},
});
for (let x of sensors.values) {
if ((params.weeks > 0) && (x.weeks > params.weeks))
continue
// if (x.value <= -4) {
// continue
// }
let marker = L.marker([x.location[1], x.location[0]], {
icon: new L.Icon({
iconUrl: buildIcon(getColor(parseInt(x.value)), 0, x.indoor),
iconSize: [35, 35],
}),
name: x.id,
value: x.value,
url: '/graph?sid=' + x.id,
lastseen: dt.formatISODate(x.lastseen),
indoor: x.indoor
})
.on('click', e => onMarkerClick(e, true, sensors.popuptxt, params)) // define click- and
markers.addLayer(marker);
}
map.addLayer(markers);
return sensors.lastdate
} else {
utils.showError(sensors.err)
}
}
async function bauPopupText(item, txts) {
let addr = await addAddress(item.name)
let offlinetext = `
<tr><td colspan="2"><span style="color:red;">${txts.offline}</span></td></tr>
<tr><td>${txts.lastseen}:</td><td>${item.lastseen}</td></tr>`
let normaltext = `
<tr></tr><tr><td>LA_max:</td><td>${item.value}</td></tr>`
let popuptext = `
<div id="infoTitle">
<h4>${txts.sensor}: ${item.name}</h4>
<div class="addr">${addr}</div>
<div id="infoTable">
<table>
<tr><td colspan="2"><span style="color:limegreen;">${item.indoor==1 ? "indoor" : ""}</span></td></tr>
${item.value < 0 ? offlinetext : normaltext}
</table>
<div id="infoBtn">
<a href="#" class="speciallink">${txts.showchart}</a>
</div>
</div>
</div>`
return popuptext
}
async function onMarkerClick(e, click, txts, params) {
let item = e.target.options;
let popuptext = await bauPopupText(item, txts)
e.target.bindPopup(popuptext).openPopup(); // show the popup
let link = document.querySelector('.speciallink')
link.addEventListener('click', async function (ev) {
console.log(`Event clicked: ${clickedSensor}`)
params.sid = item.name
let ok = await showChart(params, 'live', 'dlive')
if (ok) {
let triggerEl = document.querySelector(`#livetab`)
bootstrap.Tab.getInstance(triggerEl).show() // Select tab by name
utils.setCurrentTab('livetab')
params.center = [e.latlng.lat, e.latlng.lng]
map.setView([e.latlng.lat, e.latlng.lng]);
ev.preventDefault()
await loadAll(params)
}
})
}
// add address to PopUp
/*
async function getCoords(city) {
let url = NOMINATIM_URL + city;
const response = await axios.get(encodeURI(url));
const data = response.data;
return data[0];
}
// Map auf Stadt setzen
async function setCenter(adr) {
let data = await getCoords(adr);
map.setView([parseFloat(data.lat), parseFloat(data.lon)]);
console.log(data);
}
*/
// Show the last date below tha map grafics
async function showLastDate(ld) {
const url = APIURL + 'type=noise'
let sensors = await fetchfromserver(url)
document.querySelector('#mapdate').innerText = `${sensors.valfromtxt} ${dt.formatISODate(ld).slice(0,-3)}`
document.querySelector('#actsensors').innerText = `${sensors.actsensors} ${sensors.registered}`
// $('#actsensors').html(`${erg.count} aktive Sensoren (angemeldet ${allsens})`)
}
+235
View File
@@ -0,0 +1,235 @@
import * as dt from './datetime.js'
import * as utils from "./chart_utilities.js"
import { showChart, loadAll } from './showcharts.js'
import * as mapu from './map_utilities.js'
const colorscale = ['#d73027','#fc8d59','#fee08b','#ffffbf','#d9ef8b','#91cf60','#1a9850', '#808080'];
const grades = [ 10, 5, 2, 1, 0.5, 0.2, 0.1, -999];
const cpms = [1482, 741, 296, 148, 74, 30, 15, -999];
const sv_factor = {'SBM-20': 1 / 2.47, 'SBM-19': 1 / 9.81888, 'Si22G': 0.081438};
let showOnlySi22G = false;
export function getColor(d) {
let erg = d3.scaleLinear()
.domain([0.05, 0.1, 0.2, 0.5, 5])
.range(["#267A45", "#66FA5F", "#F8Fc00","#FF0000","#9000FF"])
.clamp(true);
return d < -1 ? '#9ECDEA' : d==-1 ? '#7F7F7F' : d==0 ? '#333333' : erg(d);
}
/******************************************************
* buildMarkers
*
* fetch data for MArkers from 'mapdata' and create
* all the markers, that are visibile within bounds
* and plot them on the map.
* Use the ClusterGroup-Library to cluster the markers
*
* params:
* bounds find markers within this bounds
* return:
* all markers plotted on map
*******************************************************/
export async function buildMarkers(params, mpp) {
const url = mpp.APIURL + `type=radioactivity&box=${mpp.bounds.toBBoxString()}`
let sensors = await utils.fetchfromserver(url)
if (!sensors.err) {
// if (markersAll) {
// mpp.map.removeLayer(markersAll);
// }
let markers = L.markerClusterGroup({
spiderfyOnMaxZoom: true,
showCoverageOnHover: false,
zoomToBoundsOnClick: true,
// disableClusteringAtZoom: 14,
iconCreateFunction: function (cluster) {
let mymarkers = cluster.getAllChildMarkers();
let color = getMedian(mymarkers); // calc median of markers in cluster and use that color
// return L.divIcon({ html: '<b>' + cluster.getChildCount() + '</b>' });
return new L.Icon({
iconUrl: buildIcon(color, cluster.getChildCount()),
iconSize: [35, 35]
});
}
});
for (let x of sensors.values) {
if (x.location == undefined) { // if there is no location defined ...
continue; // ... skip this sensor
} // otherwise create marker
if ((x.name != "Radiation Si22G") && showOnlySi22G) {
continue;
}
if ((params.weeks > 0) && (x.weeks > params.weeks)) {
continue
}
let uSvph = x.value < 0 ? -1 : x.value / 60 * sv_factor[x.name.slice(10)];
let curcolor = getColor(uSvph > 0 ? x.indoor ? -2 : uSvph : uSvph);
let marker = L.marker([x.location[1], x.location[0]], {
name: x.id,
icon: new L.Icon({
iconUrl: buildIcon(curcolor),
iconSize: [35, 35]
}),
value: x.value,
mSvph: uSvph,
url: '/' + x.id,
rohr: x.name.slice(10),
indoor: x.indoor,
lastseen: dt.formatISODate(x.lastseen)
})
.on('click', e => onMarkerClick(e, true, sensors.popuptxt, params, mpp)) // define click- and
markers.addLayer(marker);
}
mpp.map.addLayer(markers);
return sensors.lastdate
} else {
utils.showError(sensors.err)
}
}
/*
let pos = map.latLngToLayerPoint(marker.getLatLng()).round();
marker.setZIndexOffset(100 - pos.y);
// if clicked on the marker fill popup with address and click function
marker.on('click', async function () {
let addr = await holAddress(marker);
marker.setPopupContent((getPopUp(marker,addr)));
$('#btnshwgrafic').click(() => {
map.closePopup();
// if(window.matchMedia("(orientation:portrait").matches) {
// showError(5,"goto Landscape")
// } else {
showGrafik(clickedSensor);
// }
});
});
marker.bindPopup(`Loading adresse data`); // and bind the popup text
if (marker.options.value != -2) {
markersAll.addLayer(marker);
} else {
console.log(`Too old Sensor: ${marker.options.name}`);
}
}
mpp.map.addLayer(markersAll);
}
*/
function buildIcon(color, n, indoor) {
let x = 100;
if (n < 10) {
x = 200;
} else if (n < 100) {
x = 150;
}
let txtColor = "black";
if (color == colorscale[5]) {
txtColor = "white"
}
let icon = '<svg xmlns="http://www.w3.org/2000/svg" width="600" height="600">' +
'<circle cx="300" cy="300" r="300" fill="' + color + '"/>' +
'<circle cx="300" cy="300" r="50"/>' +
'<path stroke="#000" stroke-width="175" fill="none" stroke-dasharray="171.74" d="M382,158a164,164 0 1,1-164,0"/>';
if (n !== undefined) {
icon +=
'<text id="marker_text" x="' + x + '" y="400" font-size="1500%" font-family="Verdana,Lucida Sans Unicode,sans-serif" fill="white">' + n + '</text>';
}
icon += '</svg>';
return encodeURI("data:image/svg+xml," + icon).replace(new RegExp('#', 'g'), '%23');
}
// With all Markers in cluster (markers) calculate the median
// of the values. With this median fetch the color and return it.
// If there are 'offline' sensors (value == -1) strip then before
// calculating the median. If there are only offline sensor, return
// color of value==-1 (dark gray).
function getMedian(markers) {
markers.sort(function (a, b) { // first sort, the lowest first
let y1 = a.options.mSvph;
let y2 = b.options.mSvph;
if (y1 < y2) {
return -1;
}
if (y2 < y1) {
return 1;
}
return 0;
});
// console.log(markers);
let i = 0; // now find the 'offlines' (mSvph == -1)
for (i = 0; i < markers.length; i++) {
if (markers[i].options.mSvph > 0) {
break;
}
}
markers.splice(0, i); // remove these from array
let lang = markers.length;
if (lang > 1) { //
if ((lang % 2) == 1) { // uneven ->
return getColor(markers[(Math.floor(lang / 2))].options.mSvph); // median is in the middle
} else { // evaen ->
lang = lang / 2; // median is mean of both middle mSvphs
// console.log(lang);
let wert = (markers[lang - 1].options.mSvph +
markers[lang].options.mSvph) / 2;
return getColor(wert);
}
} else if (lang == 1) { // only one marker -> return its color
return getColor(markers[0].options.mSvph);
}
return getColor(-1); // only offlines
}
async function bauPopupText(item, txts) {
let addr = ''
let offlinetext = `
<tr><td colspan="2"><span style="color:red;">${txts.offline}</span></td></tr>
<tr><td>${txts.lastseen}:</td><td>${item.lastseen}</td></tr>`
let normaltext = `
<tr></tr><tr><td>cpm:</td><td>${item.value}</td></tr>
<tr></tr><tr><td>µSvph:</td><td>${item.mSvph}</td></tr>`
let popuptext = `
<div id="infoTitle">
<h4>${txts.sensor}: ${item.name}</h4>
<div class="addr">${addr}</div>
<div id="infoTable">
<table>
<tr><td colspan="2"><span style="color:limegreen;">${item.indoor==1 ? "indoor" : ""}</span></td></tr>
${item.value < 0 ? offlinetext : normaltext}
</table>
<div id="infoBtn">
<a href="#" class="speciallink">${txts.showchart}</a>
</div>
</div>
</div>`
return popuptext
}
async function onMarkerClick(e, click, txts, params, mpp) {
let item = e.target.options;
let popuptext = await bauPopupText(item, txts)
e.target.bindPopup(popuptext).openPopup(); // show the popup
let addr = await utils.addAddress(item.name)
document.querySelector('#infoTitle .addr').innerHTML = `${addr.street}<br />${addr.plz} ${addr.city}`
let link = document.querySelector('.speciallink')
link.addEventListener('click', async function (ev) {
console.log(`Event clicked: ${mpp.clickedSensor}`)
params.sid = item.name
let ok = await showChart(params, 'live', 'dlive')
if (ok) {
let triggerEl = document.querySelector(`#livetab`)
bootstrap.Tab.getInstance(triggerEl).show() // Select tab by name
utils.setCurrentTab('livetab')
params.center = [e.latlng.lat, e.latlng.lng]
mpp.map.setView([e.latlng.lat, e.latlng.lng]);
ev.preventDefault()
await loadAll(params)
}
})
}
+202
View File
@@ -0,0 +1,202 @@
import * as dt from './datetime.js'
import * as utils from "./chart_utilities.js"
import { showChart, loadAll } from './showcharts.js'
import * as mapu from './map_utilities.js'
export const colorscale = ['#d53e4f', '#fc8d59', '#fee08b', '#e6f598', '#99d594', '#3288bd', '#808080'];
const dba = [100, 80, 60, 40, 20, 0, -999];
export function getColor(d) {
let val = parseInt(d);
for (let i = 0; i < dba.length; i++) {
if (val >= dba[i]) {
return (colorscale[i]);
}
}
}
export const buildLegend = (mpp) => {
let legend = L.control({position: 'bottomright'})
legend.onAdd = function () {
let div = L.DomUtil.create('div', 'info legend')
let div_color = L.DomUtil.create('div', 'info legend inner', div)
div_color.innerHTML += 'dbA<br />';
// loop through our density intervals and generate a label with a colored square for each interval
for (let i = 0; i < dba.length - 1; i++) {
div_color.innerHTML +=
'<i style="background:' + colorscale[i] + '"></i>' +
'&nbsp;&nbsp;' + dba[i] + (i == 0 ? '+' : '') + '<br />'
}
div_color.innerHTML += '&nbsp;<i style="background:' + getColor(dba[dba.length - 1]) + '"></i> offline'
return div
};
legend.addTo(mpp.map)
}
export async function buildMarkers(params, mpp) {
const url = mpp.APIURL + `type=noise&box=${mpp.bounds.toBBoxString()}`
let sensors = await utils.fetchfromserver(url)
if (!sensors.err) {
let markers = L.markerClusterGroup({
spiderfyOnMaxZoom: true,
showCoverageOnHover: false,
zoomToBoundsOnClick: true,
// disableClusteringAtZoom: 14,
iconCreateFunction: function (cluster) {
let mymarkers = cluster.getAllChildMarkers();
let color = getMedian(mymarkers);
return new L.Icon({
iconUrl: buildIcon(color, cluster.getChildCount(), 0),
iconSize: [35, 35]
});
},
});
for (let x of sensors.values) {
if ((params.weeks > 0) && (x.weeks > params.weeks)) {
continue
}
// if (x.value <= -4) {
// continue
// }
let marker = L.marker([x.location[1], x.location[0]], {
icon: new L.Icon({
iconUrl: buildIcon(getColor(parseInt(x.value)), 0, x.indoor),
iconSize: [35, 35],
}),
name: x.id,
value: x.value,
url: '/graph?sid=' + x.id,
lastseen: dt.formatISODate(x.lastseen),
indoor: x.indoor
})
.on('click', e => onMarkerClick(e, true, sensors.popuptxt, params, mpp)) // define click- and
markers.addLayer(marker);
}
mpp.map.addLayer(markers);
return sensors.lastdate
} else {
utils.showError(sensors.err)
}
}
function buildIcon(color, n, indoor) {
let x = 100;
if (n < 10) {
x = 200;
} else if (n < 100) {
x = 150;
}
let txtColor = "black";
if (color == colorscale[5]) {
txtColor = "white"
}
let icon = '<svg xmlns="http://www.w3.org/2000/svg" width="600" height="600">' +
'<circle cx="300" cy="300" r="250" fill="' + color + '" stroke="black" stroke-width="20" />';
if (n !== 0) {
icon +=
'<text id="marker_text" x="' + x + '" ' +
'y="400" font-size="1500%" font-family="Verdana,Lucida Sans Unicode,sans-serif" ' +
'fill="' + txtColor + '">' + n + '</text>';
}
if(indoor) {
icon += '<line x1="125" y1="475" x2="475" y2="125" stroke="black" stroke-width="20" />'
}
icon += '</svg>';
return encodeURI("data:image/svg+xml," + icon).replace(new RegExp('#', 'g'), '%23');
}
async function bauPopupText(item, txts) {
let addr = ''
let offlinetext = `
<tr><td colspan="2"><span style="color:red;">${txts.offline}</span></td></tr>
<tr><td>${txts.lastseen}:</td><td>${item.lastseen}</td></tr>`
let normaltext = `
<tr></tr><tr><td>LA_max:</td><td>${item.value}</td></tr>`
let popuptext = `
<div id="infoTitle">
<h4>${txts.sensor}: ${item.name}</h4>
<div class="addr">${addr}</div>
<div id="infoTable">
<table>
<tr><td colspan="2"><span style="color:limegreen;">${item.indoor==1 ? "indoor" : ""}</span></td></tr>
${item.value < 0 ? offlinetext : normaltext}
</table>
<div id="infoBtn">
<a href="#" class="speciallink">${txts.showchart}</a>
</div>
</div>
</div>`
return popuptext
}
async function onMarkerClick(e, click, txts, params, mpp) {
let item = e.target.options;
let popuptext = await bauPopupText(item, txts)
e.target.bindPopup(popuptext).openPopup(); // show the popup
let addr = await utils.addAddress(item.name)
document.querySelector('#infoTitle .addr').innerHTML = `${addr.street}<br />${addr.plz} ${addr.city}`
let link = document.querySelector('.speciallink')
link.addEventListener('click', async function (ev) {
console.log(`Event clicked: ${mpp.clickedSensor}`)
params.sid = item.name
let ok = await showChart(params, 'live', 'dlive')
if (ok) {
let triggerEl = document.querySelector(`#livetab`)
bootstrap.Tab.getInstance(triggerEl).show() // Select tab by name
utils.setCurrentTab('livetab')
params.center = [e.latlng.lat, e.latlng.lng]
mpp.map.setView([e.latlng.lat, e.latlng.lng]);
ev.preventDefault()
await loadAll(params)
}
})
}
// With all Markers in cluster (markers) calculate the median
// of the values. With this median fetch the color and return it.
// If there are 'offline' sensors (value == -1) strip then before
// calculating the median. If there are only offline sensor, return
// color of value==-1 (dark gray).
function getMedian(markers, value) {
markers.sort(function (a, b) { // first sort, the lowest first
let y1 = a.options.value;
let y2 = b.options.value;
if (y1 < y2) {
return -1;
}
if (y2 < y1) {
return 1;
}
return 0;
});
// console.log(markers);
let i = 0; // now find the 'offlines' (value == -1)
for (i = 0; i < markers.length; i++) {
if (markers[i].options.value > 0) {
break;
}
}
markers.splice(0, i); // remove these from array
let lang = markers.length;
if (lang > 1) { //
if ((lang % 2) == 1) { // uneven ->
return getColor(markers[(Math.floor(lang / 2))].options.value); // median is in the middle
} else { // evaen ->
lang = lang / 2; // median is mean of both middle values
// console.log(lang);
let wert = (markers[lang - 1].options.value +
markers[lang].options.value) / 2;
return getColor(wert);
}
} else if (lang == 1) { // only one marker -> return its color
return getColor(markers[0].options.value);
}
return getColor(-1); // only offlines
}
+28
View File
@@ -0,0 +1,28 @@
import * as mapn from './map_noise.js';
import * as mapg from './map_geiger.js';
import * as utils from "./chart_utilities.js"
import * as dt from './datetime.js'
function getColor(d, mapparams) {
if(sysparams.category === 'laerm') {
return mapn.getColor(d, mapparams)
} else if(sysparams.category === 'multigeiger') {
return mapg.getColor(d, mapparams)
}
}
// Show the last date below tha map grafics
export async function showLastDate(ld, mpp) {
let url
if(sysparams) {
url = mpp.APIURL + 'type=noise'
} else {
url = mpp.APIURL + 'type=radiactivity'
}
let sensors = await utils.fetchfromserver(url)
document.querySelector('#mapdate').innerText = `${sensors.valfromtxt} ${dt.formatISODate(ld).slice(0,-3)}`
document.querySelector('#actsensors').innerText = `${sensors.actsensors} ${sensors.registered}`
// $('#actsensors').html(`${erg.count} aktive Sensoren (angemeldet ${allsens})`)
}
+3 -1
View File
@@ -63,7 +63,9 @@ export async function showChart(params, typ, container) {
}
let erg = await fetchfromserver(url)
if (!erg.err) {
utils.showTabs()
if(sysparams.category === 'laerm') {
utils.showTabs()
}
document.querySelector('#odth').style.display = 'none'
document.querySelector('#nbday').style.display = 'inline'
erg.options.xAxis.labels.formatter = xformat