mobility-toolbox-js
Version:
Toolbox for JavaScript applications in the domains of mobility and logistics.
176 lines (175 loc) • 7.8 kB
JavaScript
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)];
};