UNPKG

mobility-toolbox-js

Version:

Toolbox for JavaScript applications in the domains of mobility and logistics.

176 lines (175 loc) 7.8 kB
import { getCenter } from 'ol/extent'; import GeoJSON from 'ol/format/GeoJSON'; import { toLonLat } from 'ol/proj'; export const MOCO_REASONS_CATEGORY = { DAS_PERSONAL_BETREFEND: 'Das Personal betreffend', SICHERHEITSRELEVANT: 'Sicherheitsrelevant', SPEZIELLE_ANLAESSE: 'Spezielle Anl\u00E4sse', TECHNISCHE_PROBLEME: 'Technische Probleme', UMWELTEINFLUESSE: 'Umwelteinflüsse', UNDEFINIERT: 'Undefiniert', UNFALL: 'Unfall', VERKEHRLICHE_GRUENDE: 'Verkehrliche Gr\u00FCnde', VERSCHIEDENES: 'Verschiedenes', }; export const MOCO_IMAGE_BY_CATEGORY = { [MOCO_REASONS_CATEGORY.DAS_PERSONAL_BETREFEND]: 'das_personal_betrefend', [MOCO_REASONS_CATEGORY.SICHERHEITSRELEVANT]: 'sicherheitsrelevant', [MOCO_REASONS_CATEGORY.SPEZIELLE_ANLAESSE]: 'spezielle_anlaesse', [MOCO_REASONS_CATEGORY.TECHNISCHE_PROBLEME]: 'technische_probleme', [MOCO_REASONS_CATEGORY.UMWELTEINFLUESSE]: 'umwelteinfluesse', [MOCO_REASONS_CATEGORY.UNDEFINIERT]: 'undefiniert', [MOCO_REASONS_CATEGORY.UNFALL]: 'unfall', [MOCO_REASONS_CATEGORY.VERKEHRLICHE_GRUENDE]: 'verkehrliche_gruende', [MOCO_REASONS_CATEGORY.VERSCHIEDENES]: 'verschiedenes', }; export const getTime = (str) => { return parseInt(str === null || str === void 0 ? void 0 : str.substr(0, 8).replace(/:/g, ''), 10); }; export const isMocoNotificationNotOutOfDate = (notification, now = new Date()) => { // TODO: The backend should be responsible to returns only good notifications. let notOutOfDate = notification.properties.affected_time_intervals.some((ati) => { return now < new Date(ati.end); }); if (!notOutOfDate) { notOutOfDate = (notification.properties.publications || []).some((publication) => { return (now >= new Date(publication.visible_from) && now <= new Date(publication.visible_until)); }); } return notOutOfDate; }; export const isMocoNotificationPublished = (notificationProperties, now) => { var _a; if (!((_a = notificationProperties === null || notificationProperties === void 0 ? void 0 : notificationProperties.publications) === null || _a === void 0 ? void 0 : _a.length)) { // If there is no piblications date, use the time intervals return isMocoNotificationActive(notificationProperties, now); } return notificationProperties.publications.some((publication) => { return (now >= new Date(publication.visible_from) && now <= new Date(publication.visible_until)); }); }; export const isMocoNotificationActive = (notificationProperties, now) => { return notificationProperties.affected_time_intervals.some((affectedTimeInterval) => { const { end, start, time_of_day_end: dayTimeEnd, time_of_day_start: dayTimeStart, } = affectedTimeInterval; const nowTime = getTime(now.toTimeString()); const startTime = getTime(dayTimeStart || ''); const endTime = getTime(dayTimeEnd || ''); const inRange = new Date(start) <= now && now <= new Date(end); return startTime && endTime ? inRange && startTime <= nowTime && nowTime <= endTime : inRange; }); }; export const getMocoStartsString = (notificationProperties, now) => { const next = notificationProperties.affected_time_intervals.reduce((a, b) => { const aEnd = new Date(a.end); const aStart = new Date(a.start); const bStart = new Date(b.start); return now < aEnd && aStart < bStart ? a : b; }, {}); const nextStartDate = new Date(next.start); let starts; if (now.toDateString() === nextStartDate.toDateString() || now.getTime() - nextStartDate.getTime() > 0) { if (next.time_of_day_start) { starts = `ab ${next.time_of_day_start.substr(0, 5)}`; } else { starts = `ab ${nextStartDate.toLocaleTimeString(['de'], { hour: '2-digit', hour12: false, minute: '2-digit', })}`; } } else { starts = `ab ${nextStartDate.toLocaleDateString(['de-DE'], { day: 'numeric', month: 'short', })}`; } return starts; }; export const getMocoIconRefFeatures = (notification) => { const format = new GeoJSON(); const features = notification.features || []; const lineFeatures = features.filter((f) => { var _a; return ((_a = f.geometry) === null || _a === void 0 ? void 0 : _a.type) !== 'Point'; }); const lineFeaturesUsedForIcons = lineFeatures.filter((f) => { return f.properties.is_icon_ref; }); const iconsForLines = lineFeaturesUsedForIcons .map((affectedLine) => { const affectedLineFeature = format.readFeature(affectedLine, { dataProjection: 'EPSG:4326', featureProjection: 'EPSG:3857', }); const geometry = affectedLineFeature.getGeometry(); if (!geometry) { return null; } const center = getCenter(geometry.getExtent()); const iconRefPoint = geometry.getClosestPoint(center); const iconRefFeatureProperties = Object.assign(Object.assign({}, notification.properties), affectedLine.properties); // if (!iconRefFeatureProperties.disruption_type) { // iconRefFeatureProperties.disruption_type = 'OTHER'; // } // // Set Banner image // if (iconRefFeatureProperties.disruption_type) { // iconRefFeatureProperties.disruption_type_banner = // iconRefFeatureProperties.disruption_type + '_BANNER'; // } if (iconRefPoint) { const iconForLine = { geometry: { coordinates: toLonLat(iconRefPoint), type: 'Point', }, id: `${Math.random()}`, properties: iconRefFeatureProperties, type: 'Feature', }; return iconForLine; } }) .filter((f) => { return !!f; }); // @ts-expect-error bad geometry type from backend return iconsForLines; }; export const getMocoNotificationsAsFeatureCollection = (notifications) => { // Merge all features into a single GeoJSON feature collection // and add the notification properties to each feature. const features = notifications.flatMap((notification) => { return (notification.features || []).map((feature) => { var _a, _b; const feat = Object.assign(Object.assign({}, feature), { properties: Object.assign(Object.assign({}, notification.properties), feature.properties) }); const reasonCategoryName = (_b = (_a = notification.properties.reasons) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.category_name; // reasons_category is used to choose the proper icon in the style // @ts-expect-error the value is a string in the style feat.properties.reasons_category = MOCO_IMAGE_BY_CATEGORY[reasonCategoryName || MOCO_REASONS_CATEGORY.UNDEFINIERT] || MOCO_IMAGE_BY_CATEGORY[MOCO_REASONS_CATEGORY.UNDEFINIERT]; return feat; }); }); return { // @ts-expect-error conflict between geometry types features, type: 'FeatureCollection', }; }; export const getCurrentGraph = (mapping, zoom) => { const breakPoints = Object.keys(mapping).map((k) => { return parseFloat(k); }); const closest = breakPoints.reverse().find((bp) => { return bp <= Math.floor(zoom) - 1; }); // - 1 due to ol zoom !== mapbox zoom // @ts-expect-error the value is a number in der style return mapping[closest || Math.min(...breakPoints)]; };