mobility-toolbox-js 1.7.8-beta.7 → 1.7.8-beta.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,8 +1,10 @@
1
+ import qs from 'query-string';
1
2
  import {
2
3
  translateTrajCollResponse,
3
4
  translateTrajStationsResp,
4
5
  } from './TrajservAPIUtils';
5
6
  import API from '../../common/api/api';
7
+ import FetchTrajectoriesWorker from './fetchTrajectories.worker';
6
8
 
7
9
  /**
8
10
  * Access to the [Realtime service](https://developer.geops.io/apis/5dcbd5c9a256d90001cf1360/).
@@ -26,6 +28,7 @@ class TrajservAPI extends API {
26
28
  */
27
29
  constructor(options = {}) {
28
30
  super({ url: 'https://api.geops.io/tracker/v1', ...options });
31
+ this.fetchTrajectoriesWorker = new FetchTrajectoriesWorker();
29
32
  }
30
33
 
31
34
  /**
@@ -41,6 +44,27 @@ class TrajservAPI extends API {
41
44
  });
42
45
  }
43
46
 
47
+ /**
48
+ * Fetch trajectories using the worker.
49
+ *
50
+ * @param {GetTrajectoriesParams} params Request parameters. See [Realtime service documentation](https://developer.geops.io/apis/5dcbd5c9a256d90001cf1360/#/default/get_trajectory_collection).
51
+ * @param {AbortController} abortController Abort controller used to cancel the request.
52
+ // * @returns {Promise<Trajectory[]>} A list of trajectories.
53
+ */
54
+ // eslint-disable-next-line class-methods-use-this
55
+ fetchTrajectoriesWorkerr(params) {
56
+ // Clean requets parameters, removing undefined and null values.
57
+ const urlParams = { ...params, key: this.apiKey };
58
+ const clone = { ...urlParams };
59
+ Object.keys(urlParams).forEach(
60
+ (key) =>
61
+ (clone[key] === undefined || clone[key] === null) && delete clone[key],
62
+ );
63
+ this.fetchTrajectoriesWorker.postMessage(
64
+ `${this.url}/trajectory_collection?${qs.stringify(clone)}`,
65
+ );
66
+ }
67
+
44
68
  /**
45
69
  * Fetch trajectories.
46
70
  *
@@ -1,5 +1,3 @@
1
- import { LineString } from 'ol/geom';
2
-
3
1
  /**
4
2
  * Translate the response date object into a readable object.
5
3
  * @return {Date[]}
@@ -132,7 +130,7 @@ export const translateTrajCollResponse = (features = []) => {
132
130
  const trajectories = [];
133
131
  for (let i = 0; i < features.length; i += 1) {
134
132
  const traj = features[i];
135
- const geometry = new LineString(traj.geometry.coordinates);
133
+ const { geometry } = traj;
136
134
  const {
137
135
  ID: id,
138
136
  ProductIdentifier: type,
@@ -0,0 +1,23 @@
1
+ import { translateTrajCollResponse } from './TrajservAPIUtils';
2
+
3
+ let abortController = new AbortController();
4
+
5
+ // eslint-disable-next-line no-restricted-globals, func-names
6
+ self.onmessage = function (evt) {
7
+ // console.log('Worker: Message received from main script', evt.data);
8
+ abortController.abort();
9
+ abortController = new AbortController();
10
+ fetch(evt.data, {
11
+ signal: abortController.signal,
12
+ })
13
+ .then((res) => res.json())
14
+ .then((data) => {
15
+ const a = translateTrajCollResponse(data.features);
16
+ // eslint-disable-next-line no-restricted-globals
17
+ self.postMessage(a);
18
+ })
19
+ .catch(() => {
20
+ // eslint-disable-next-line no-restricted-globals
21
+ // self.postMessage(null);
22
+ });
23
+ };
@@ -65,6 +65,8 @@ class TralisAPI {
65
65
  /** @ignore */
66
66
  this.prefix = options.prefix || '';
67
67
 
68
+ this.isUpdateBboxOnMoveEnd = options.isUpdateBboxOnMoveEnd || false;
69
+
68
70
  /** @ignore */
69
71
  this.onOpen = this.onOpen.bind(this);
70
72
  }
@@ -312,7 +312,9 @@ class WebSocketConnector {
312
312
  !this.subscriptions.find((s) => s.params.channel === source) &&
313
313
  toRemove.find((subscr) => !subscr.quiet)
314
314
  ) {
315
- this.send(`DEL ${source}`);
315
+ if (this.isDELAllow) {
316
+ this.send(`DEL ${source}`);
317
+ }
316
318
  this.subscribed[source] = false;
317
319
  }
318
320
  }
@@ -0,0 +1,67 @@
1
+ import GeomType from 'ol/geom/GeometryType';
2
+
3
+ /**
4
+ * Interpolate a position along a geometry at a specific date.
5
+ *
6
+ * @param {number} now Current date to interpolate a position with. In ms.
7
+ * @param {ol/geom/LineString~LineString} geometry The geoemtry used to interpolate a position.
8
+ * @param {Array<Array<number,number,number>>} timeIntervals The time intervals used to interpolate a position, ex: [[dateInMs, fraction, rotation]...].
9
+ * @returns
10
+ */
11
+ const interpolate = (now, geometry, timeIntervals) => {
12
+ let coord;
13
+ let start;
14
+ let end;
15
+ let startFrac;
16
+ let endFrac;
17
+ let timeFrac;
18
+ let rotation;
19
+
20
+ // Search th time interval.
21
+ for (let j = 0; j < timeIntervals.length - 1; j += 1) {
22
+ // Rotation only available in tralis layer.
23
+ [start, startFrac, rotation] = timeIntervals[j];
24
+ [end, endFrac] = timeIntervals[j + 1];
25
+
26
+ if (start <= now && now <= end) {
27
+ break;
28
+ } else {
29
+ start = null;
30
+ end = null;
31
+ }
32
+ }
33
+ // The geometry can also be a Point
34
+ if (geometry.getType() === GeomType.POINT) {
35
+ coord = geometry.getCoordinates();
36
+ } else if (geometry.getType() === GeomType.LINE_STRING) {
37
+ if (start && end) {
38
+ // interpolate position inside the time interval.
39
+ timeFrac = interpolate ? Math.min((now - start) / (end - start), 1) : 0;
40
+
41
+ const geomFrac = interpolate
42
+ ? timeFrac * (endFrac - startFrac) + startFrac
43
+ : 0;
44
+
45
+ coord = geometry.getCoordinateAt(geomFrac);
46
+
47
+ // It happens that the now date was some ms before the first timeIntervals we have.
48
+ } else if (now < timeIntervals[0][0]) {
49
+ [[, , rotation]] = timeIntervals;
50
+ timeFrac = 0;
51
+ coord = geometry.getFirstCoordinate();
52
+ } else if (now > timeIntervals[timeIntervals.length - 1][0]) {
53
+ [, , rotation] = timeIntervals[timeIntervals.length - 1];
54
+ timeFrac = 1;
55
+ coord = geometry.getLastCoordinate();
56
+ }
57
+ } else {
58
+ // eslint-disable-next-line no-console
59
+ console.error(
60
+ 'This geometry type is not supported. Only Point or LineString are. Current geometry: ',
61
+ geometry,
62
+ );
63
+ }
64
+ return { coord, rotation, timeFrac };
65
+ };
66
+
67
+ export default interpolate;
@@ -507,6 +507,9 @@ const TrackerLayerMixin = (Base) =>
507
507
  }
508
508
  }
509
509
 
510
+ /**
511
+ *
512
+
510
513
  /**
511
514
  * Launch renderTrajectories. it avoids duplicating code in renderTrajectories method.
512
515
  *
@@ -111,6 +111,19 @@ export class TrajservLayerInterface {
111
111
  */
112
112
  const TrajservLayerMixin = (TrackerLayer) =>
113
113
  class extends TrackerLayer {
114
+ constructor(options) {
115
+ super(options);
116
+
117
+ if (this.api.fetchTrajectoriesWorkerr) {
118
+ const that = this;
119
+ this.api.fetchTrajectoriesWorker.onmessage = (evt) => {
120
+ if (evt.data) {
121
+ that.onReceiveTrajectories(evt.data);
122
+ }
123
+ };
124
+ }
125
+ }
126
+
114
127
  /**
115
128
  * Define layer's properties.
116
129
  *
@@ -347,6 +360,11 @@ const TrajservLayerMixin = (TrackerLayer) =>
347
360
  this.abortFetchTrajectories();
348
361
  this.abortController = new AbortController();
349
362
 
363
+ if (this.api.fetchTrajectoriesWorkerr) {
364
+ this.api.fetchTrajectoriesWorkerr(this.getParams({ attr_det: 1 }));
365
+ return;
366
+ }
367
+
350
368
  this.api
351
369
  .fetchTrajectories(
352
370
  this.getParams({
@@ -364,12 +382,32 @@ const TrajservLayerMixin = (TrackerLayer) =>
364
382
  .then((trajectories) => {
365
383
  // Don't set trajectories when the user has aborted the request.
366
384
  if (trajectories) {
367
- this.trajectories = trajectories;
368
- this.renderTrajectories();
385
+ if (this.worker) {
386
+ this.onReceiveTrajectories(trajectories);
387
+ } else {
388
+ this.trajectories = trajectories;
389
+ this.renderTrajectories();
390
+ }
369
391
  }
370
392
  });
371
393
  }
372
394
 
395
+ onReceiveTrajectories(trajectories) {
396
+ // Don't set trajectories when the user has aborted the request.
397
+ if (trajectories) {
398
+ this.tracker.setTrajectories(trajectories);
399
+
400
+ if (this.worker) {
401
+ this.worker.postMessage({
402
+ action: 'sendData',
403
+ trajectories,
404
+ });
405
+ }
406
+
407
+ this.renderTrajectories();
408
+ }
409
+ }
410
+
373
411
  /**
374
412
  * Draw the trajectory as a line with points for each stop.
375
413
  *
@@ -243,12 +243,26 @@ const TralisLayerMixin = (TrackerLayer) =>
243
243
  if (this.filter && !this.filter(trajectory)) {
244
244
  return;
245
245
  }
246
+
246
247
  this.trajectories[trajectory.properties.train_id] = trajectory;
247
248
  this.renderTrajectories();
249
+
250
+ if (this.worker) {
251
+ this.worker.postMessage({
252
+ action: 'addTrajectory',
253
+ trajectory,
254
+ });
255
+ }
248
256
  }
249
257
 
250
258
  removeTrajectory(id) {
251
259
  delete this.trajectories[id];
260
+ if (this.worker) {
261
+ this.worker.postMessage({
262
+ action: 'removeTrajectory',
263
+ trajectoryId: id,
264
+ });
265
+ }
252
266
  }
253
267
 
254
268
  // getRefreshTimeInMs() {
@@ -298,7 +312,8 @@ const TralisLayerMixin = (TrackerLayer) =>
298
312
  this.map.getView().getProjection(),
299
313
  ),
300
314
  };
301
- } else {
315
+ } else if (!this.worker) {
316
+ // We can't pass the olGeometry to the worker because it's not serializable.
302
317
  trajectory.properties.olGeometry = this.format.readGeometry(geometry);
303
318
  }
304
319
 
@@ -0,0 +1,93 @@
1
+ import stringify from 'json-stringify-safe';
2
+ import GeoJSON from 'ol/format/GeoJSON';
3
+ import { delayTrackerStyle } from './utils';
4
+ import Tracker from './Tracker';
5
+
6
+ const debug = false;
7
+
8
+ const trajectories = {};
9
+ let renderTimeout;
10
+ let count = 0;
11
+ const format = new GeoJSON();
12
+ const tracker = new Tracker({
13
+ canvas: new OffscreenCanvas(1, 1),
14
+ width: 1,
15
+ height: 1,
16
+ style: delayTrackerStyle,
17
+ });
18
+
19
+ const render = (evt) => {
20
+ // eslint-disable-next-line no-console
21
+ if (debug) console.time('render');
22
+ // eslint-disable-next-line no-console
23
+ if (debug) console.log('render', evt.data.frameState);
24
+ count = 0;
25
+ const { frameState, viewState, options } = evt.data;
26
+
27
+ const { nbTrajectoriesRendered } = tracker.renderTrajectories(
28
+ Object.values(trajectories),
29
+ viewState,
30
+ options,
31
+ );
32
+
33
+ if (debug) console.timeEnd('render');
34
+ if (debug) console.log('NUMBER OF STYLES CREATED', count);
35
+
36
+ const imageData = tracker.canvas.transferToImageBitmap();
37
+ const state = { ...frameState };
38
+ delete state.layerStatesArray;
39
+ delete state.viewState.projection;
40
+
41
+ // eslint-disable-next-line no-restricted-globals
42
+ self.postMessage(
43
+ {
44
+ action: 'rendered',
45
+ imageData,
46
+ // transform: rendererTransform,
47
+ nbRenderedTrajectories: nbTrajectoriesRendered,
48
+ frameState: JSON.parse(stringify(state)),
49
+ },
50
+ [imageData],
51
+ );
52
+ renderTimeout = null;
53
+ };
54
+
55
+ // eslint-disable-next-line no-restricted-globals
56
+ self.onmessage = (evt) => {
57
+ // debugger;
58
+ if (evt.data.action === 'addTrajectory') {
59
+ const { trajectory } = evt.data;
60
+ const id = trajectory.properties.train_id;
61
+ trajectories[id] = trajectory;
62
+ trajectories[id].properties.olGeometry = format.readGeometry(
63
+ trajectory.geometry,
64
+ );
65
+ return;
66
+ }
67
+
68
+ if (evt.data.action === 'removeTrajectory') {
69
+ delete trajectories[evt.data.trajectoryId];
70
+ return;
71
+ }
72
+
73
+ // if (evt.data.action === 'sendData') {
74
+ // // eslint-disable-next-line no-console
75
+ // if (debug) console.log('sendData', evt.data);
76
+ // if (debug) console.time('sendData');
77
+ // trajectories = evt.data.trajectories;
78
+ // if (debug) console.timeEnd('sendData');
79
+ // return;
80
+ // }
81
+
82
+ if (evt.data.action !== 'render') {
83
+ return;
84
+ }
85
+
86
+ if (renderTimeout) {
87
+ clearTimeout(renderTimeout);
88
+ }
89
+
90
+ renderTimeout = setTimeout(() => {
91
+ render(evt);
92
+ }, 0);
93
+ };
@@ -0,0 +1,134 @@
1
+ const cacheDelayBg = {};
2
+
3
+ // Draw circle delay background
4
+ export const getDelayBgCanvas = (origin, radius, color) => {
5
+ const key = `${origin}, ${radius}, ${color}`;
6
+ if (!cacheDelayBg[key]) {
7
+ // console.log('cacheDelayBg');
8
+ const canvas = new OffscreenCanvas(origin * 2, origin * 2);
9
+ const ctx = canvas.getContext('2d');
10
+ ctx.beginPath();
11
+ ctx.arc(origin, origin, radius, 0, 2 * Math.PI, false);
12
+ ctx.fillStyle = color;
13
+ ctx.filter = 'blur(1px)';
14
+ ctx.fill();
15
+ cacheDelayBg[key] = canvas;
16
+ }
17
+ return cacheDelayBg[key];
18
+ };
19
+
20
+ // Draw delay text
21
+ const cacheDelayText = {};
22
+ export const getDelayTextCanvas = (
23
+ width,
24
+ text,
25
+ fontSize,
26
+ font,
27
+ delayColor,
28
+ delayOutlineColor,
29
+ pixelRatio,
30
+ ) => {
31
+ const key = `${width}, ${text}, ${font}, ${delayColor}, ${delayOutlineColor}, ${pixelRatio}`;
32
+ if (!cacheDelayText[key]) {
33
+ const canvas = new OffscreenCanvas(width, fontSize + 8);
34
+ const ctx = canvas.getContext('2d');
35
+ ctx.textAlign = 'left';
36
+ ctx.textBaseline = 'middle';
37
+ ctx.font = font;
38
+ ctx.fillStyle = delayColor;
39
+ ctx.strokeStyle = delayOutlineColor;
40
+ ctx.lineWidth = 1.5 * pixelRatio;
41
+ const delayText = text;
42
+ ctx.strokeText(delayText, 0, fontSize);
43
+ ctx.fillText(delayText, 0, fontSize);
44
+ cacheDelayText[key] = canvas;
45
+ }
46
+ return cacheDelayText[key];
47
+ };
48
+
49
+ // Draw colored circle with black border
50
+ const cacheCircle = {};
51
+ export const getCircleCanvas = (
52
+ origin,
53
+ radius,
54
+ color,
55
+ hasStroke,
56
+ hasDash,
57
+ pixelRatio,
58
+ ) => {
59
+ const key = `${origin}, ${radius}, ${color}, ${hasStroke}, ${hasDash}, ${pixelRatio}`;
60
+ if (!cacheCircle[key]) {
61
+ // console.log('cacheDelayBg');
62
+ const canvas = new OffscreenCanvas(origin * 2, origin * 2);
63
+ const ctx = canvas.getContext('2d');
64
+ ctx.fillStyle = color;
65
+
66
+ if (hasStroke) {
67
+ ctx.lineWidth = 1 * pixelRatio;
68
+ ctx.strokeStyle = '#000000';
69
+ }
70
+
71
+ ctx.beginPath();
72
+ ctx.arc(origin, origin, radius, 0, 2 * Math.PI, false);
73
+ ctx.fill();
74
+
75
+ if (hasDash) {
76
+ ctx.setLineDash([5, 3]);
77
+ }
78
+
79
+ if (hasStroke) {
80
+ ctx.stroke();
81
+ }
82
+
83
+ cacheCircle[key] = canvas;
84
+ }
85
+ return cacheCircle[key];
86
+ };
87
+
88
+ // Draw text in the circle
89
+ const cacheText = {};
90
+ export const getTextCanvas = (
91
+ text,
92
+ origin,
93
+ textSize,
94
+ fillColor,
95
+ strokeColor,
96
+ hasStroke,
97
+ pixelRatio,
98
+ ) => {
99
+ const key = `${text}, ${origin}, ${textSize}, ${fillColor},${strokeColor}, ${hasStroke}, ${pixelRatio}`;
100
+ if (!cacheText[key]) {
101
+ const canvas = new OffscreenCanvas(origin * 2, origin * 2);
102
+ const ctx = canvas.getContext('2d');
103
+
104
+ // Draw a stroke to the text only if a provider provides realtime but we don't use it.
105
+ if (hasStroke) {
106
+ ctx.save();
107
+ ctx.textBaseline = 'middle';
108
+ ctx.textAlign = 'center';
109
+ ctx.font = `bold ${textSize + 2}px Arial`;
110
+ ctx.strokeStyle = strokeColor;
111
+ ctx.strokeText(text, origin, origin);
112
+ ctx.restore();
113
+ }
114
+
115
+ // Draw a text
116
+ ctx.textBaseline = 'middle';
117
+ ctx.textAlign = 'center';
118
+ ctx.fillStyle = fillColor;
119
+ ctx.font = `bold ${textSize}px Arial`;
120
+ ctx.strokeStyle = strokeColor;
121
+ ctx.strokeText(text, origin, origin);
122
+ ctx.fillText(text, origin, origin);
123
+
124
+ cacheText[key] = canvas;
125
+ }
126
+ return cacheText[key];
127
+ };
128
+
129
+ export default {
130
+ getDelayBgCanvas,
131
+ getDelayTextCanvas,
132
+ getCircleCanvas,
133
+ getTextCanvas,
134
+ };
@@ -8,10 +8,11 @@ import {
8
8
  } from '../trackerConfig';
9
9
 
10
10
  const createCanvas = (width, height) => {
11
- const canvas = document.createElement('canvas');
12
- canvas.width = width;
13
- canvas.height = height;
14
- return canvas;
11
+ return new OffscreenCanvas(width, height);
12
+ // const canvas = document.createElement('canvas');
13
+ // canvas.width = width;
14
+ // canvas.height = height;
15
+ // return canvas;
15
16
  };
16
17
 
17
18
  // Draw circle delay background
@@ -204,6 +205,7 @@ const style = (trajectory, viewState, options) => {
204
205
  ? radius + 5 * pixelRatio
205
206
  : 14 * pixelRatio;
206
207
  }
208
+
207
209
  const mustDrawText = radius > 10 * pixelRatio;
208
210
 
209
211
  // Optimize the cache key, very important in high zoom level
@@ -5,3 +5,4 @@ export { default as delayTrackerStyle } from './delayTrackerStyle';
5
5
  export * from './delayTrackerStyle';
6
6
  export { default as simpleTrackerStyle } from './simpleTrackerStyle';
7
7
  export * from './timeUtils';
8
+ export { default as getVehiclePosition } from './getVehiclePosition';
@@ -2,9 +2,10 @@
2
2
  * A very simple tracker style.
3
3
  * Display blue point for each train.
4
4
  */
5
- const canvas = document.createElement('canvas');
6
- canvas.width = 15;
7
- canvas.height = 15;
5
+ // const canvas = document.createElement('canvas');
6
+ // canvas.width = 15;
7
+ // canvas.height = 15;
8
+ const canvas = new OffscreenCanvas(15, 15);
8
9
  const ctx = canvas.getContext('2d');
9
10
  ctx.arc(8, 8, 5, 0, 2 * Math.PI, false);
10
11
  ctx.fillStyle = '#8ED6FF';
@@ -0,0 +1,2 @@
1
+ !function(e){var r={};function t(n){if(r[n])return r[n].exports;var o=r[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,t),o.l=!0,o.exports}t.m=e,t.c=r,t.d=function(e,r,n){t.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:n})},t.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},t.t=function(e,r){if(1&r&&(e=t(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(t.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var o in e)t.d(n,o,function(r){return e[r]}.bind(null,o));return n},t.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(r,"a",r),r},t.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},t.p="",t(t.s=0)}([function(e,r,t){"use strict";t.r(r);var n=function(){for(var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],r=[],t=0;t<e.length;t+=1){var n=e[t],o=n.geometry,i=n.properties,l=i.ID,a=i.ProductIdentifier,u=i.PublishedLineName,c=i.RouteIdentifier,f=i.DirectionText,s=i.Operator,d=i.OperatorURL,p=i.Publisher,b=i.PublisherURL,y=i.License,v=i.LicenseUrl,m=i.LicenseNote,g=i.Color,O=i.JourneyIdentifier,h=i.RealtimeAvailable,P=i.OperatorProvidesRealtime,j=i.DayOfOperation,x=i.Delay,I=i.TimeIntervals,C=i.TextColor,L=i.Cancelled;r.push({id:l,type:a,name:u,routeIdentifier:c,directionText:f,operator:s,operatorUrl:d,publisher:p,publisherUrl:b,license:y,licenseUrl:v,licenseNote:m,journeyIdentifier:O,realtimeAvailable:h,operatorProvidesRealtime:P,dayOfOperation:j,delay:x,timeIntervals:I,color:g&&"#".concat(g),textColor:C&&"#".concat(C),geometry:o,cancelled:L})}return r},o=new AbortController;self.onmessage=function(e){o.abort(),o=new AbortController,fetch(e.data,{signal:o.signal}).then((function(e){return e.json()})).then((function(e){var r=n(e.features);self.postMessage(r)})).catch((function(){}))}}]);
2
+ //# sourceMappingURL=fetchTrajectories.worker.worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["webpack://mobility-toolbox-js/webpack/bootstrap","webpack://mobility-toolbox-js/./src/api/trajserv/TrajservAPIUtils.js","webpack://mobility-toolbox-js/./src/api/trajserv/fetchTrajectories.worker.js"],"names":["installedModules","__webpack_require__","moduleId","exports","module","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","translateTrajCollResponse","features","trajectories","length","traj","geometry","properties","id","ID","type","ProductIdentifier","PublishedLineName","routeIdentifier","RouteIdentifier","directionText","DirectionText","operator","Operator","operatorUrl","OperatorURL","publisher","Publisher","publisherUrl","PublisherURL","license","License","licenseUrl","LicenseUrl","licenseNote","LicenseNote","color","Color","journeyIdentifier","JourneyIdentifier","realtimeAvailable","RealtimeAvailable","operatorProvidesRealtime","OperatorProvidesRealtime","dayOfOperation","DayOfOperation","delay","Delay","timeIntervals","TimeIntervals","textColor","TextColor","cancelled","Cancelled","push","abortController","AbortController","self","onmessage","evt","abort","fetch","data","signal","then","res","json","a","postMessage","catch"],"mappings":"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","file":"fetchTrajectories.worker.worker.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 0);\n","/**\n * Translate the response date object into a readable object.\n * @return {Date[]}\n * @ignore\n */\nconst translateDates = (dates = []) => {\n const newDates = [];\n\n for (let i = 0; i < dates.length; i += 1) {\n const { d: day, m: month, y: year } = dates[i];\n newDates.push({\n day,\n month,\n year,\n });\n }\n return newDates;\n};\n\n/**\n * Translate the trajstations response into a readable object.\n * @return {Object} returns a readable object\n * @private\n */\nexport const translateTrajStationsResp = (data) => {\n const newData = { ...data };\n\n // MAke sure all property exists.\n ['a', 'f', 'tt'].forEach((prop) => {\n if (!newData[prop]) {\n newData[prop] = {};\n }\n });\n\n const {\n id,\n hs: destination,\n t: vehicleType,\n ln: longName,\n sn: shortName,\n wa: wheelchairAccessible,\n ba: bicyclesAllowed,\n rt: realTime,\n fid: feedsId,\n rid: routeIdentifier,\n c: bgColor,\n tc: datacolor,\n a: { n: operator, u: operatorUrl, tz: operatorTimeZone },\n f: { n: publisher, u: publisherUrl, tz: publisherTimeZone },\n tt: {\n n: dateNotOperatingDays,\n p: dateAdditionalOperatingDays,\n t: operatingPeriod,\n },\n sts: dataStations,\n } = newData;\n\n const notOperatingDays = translateDates(dateNotOperatingDays);\n const additionalOperatingDays = translateDates(dateAdditionalOperatingDays);\n const backgroundColor = bgColor && `#${bgColor}`;\n const color = datacolor && `#${datacolor}`;\n\n const stations = [];\n for (let i = 0; i < (dataStations || []).length; i += 1) {\n const {\n sid: stationId,\n n: stationName,\n p: coordinates,\n at: arrivalTime,\n dt: departureTime,\n ap: arrivalDate,\n dp: departureDate,\n ad: arrivalDelay,\n dd: departureDelay,\n dot: noDropOff,\n put: noPickUp,\n c: cancelled,\n wa: stWheelchairAccessible,\n } = dataStations[i];\n\n stations.push({\n stationId,\n stationName,\n coordinates,\n arrivalTime: arrivalTime !== -1 ? arrivalDate * 1000 : null,\n departureTime: departureTime !== -1 ? departureDate * 1000 : null,\n arrivalDelay,\n departureDelay,\n noDropOff: !!noDropOff,\n noPickUp: !!noPickUp,\n cancelled: !!cancelled,\n wheelchairAccessible: !!stWheelchairAccessible,\n });\n }\n\n return {\n id,\n destination,\n backgroundColor,\n color,\n vehicleType,\n routeIdentifier,\n longName,\n shortName,\n stations,\n wheelchairAccessible: !!wheelchairAccessible,\n bicyclesAllowed: !!bicyclesAllowed,\n realTime,\n feedsId,\n operatingInformations: {\n operatingPeriod,\n notOperatingDays,\n additionalOperatingDays,\n },\n operator,\n operatorUrl,\n operatorTimeZone,\n publisher,\n publisherUrl,\n publisherTimeZone,\n };\n};\n\n/**\n * Translate the trajectory_collection response into a js usable object.\n * @return {Array} returns an array of trajectories.\n * @ignore\n */\nexport const translateTrajCollResponse = (features = []) => {\n const trajectories = [];\n for (let i = 0; i < features.length; i += 1) {\n const traj = features[i];\n const { geometry } = traj;\n const {\n ID: id,\n ProductIdentifier: type,\n PublishedLineName: name,\n RouteIdentifier: routeIdentifier,\n DirectionText: directionText,\n Operator: operator,\n OperatorURL: operatorUrl,\n Publisher: publisher,\n PublisherURL: publisherUrl,\n License: license,\n LicenseUrl: licenseUrl,\n LicenseNote: licenseNote,\n Color: color,\n JourneyIdentifier: journeyIdentifier,\n RealtimeAvailable: realtimeAvailable,\n OperatorProvidesRealtime: operatorProvidesRealtime,\n DayOfOperation: dayOfOperation,\n Delay: delay,\n TimeIntervals: timeIntervals,\n TextColor: textColor,\n Cancelled: cancelled,\n } = traj.properties;\n\n trajectories.push({\n id,\n type,\n name,\n routeIdentifier,\n directionText,\n operator,\n operatorUrl,\n publisher,\n publisherUrl,\n license,\n licenseUrl,\n licenseNote,\n journeyIdentifier,\n realtimeAvailable,\n operatorProvidesRealtime,\n dayOfOperation,\n delay,\n timeIntervals,\n color: color && `#${color}`,\n textColor: textColor && `#${textColor}`,\n geometry,\n cancelled,\n });\n }\n return trajectories;\n};\n\nexport default {\n translateTrajCollResponse,\n translateTrajStationsResp,\n};\n","import { translateTrajCollResponse } from './TrajservAPIUtils';\n\nlet abortController = new AbortController();\n\n// eslint-disable-next-line no-restricted-globals, func-names\nself.onmessage = function (evt) {\n // console.log('Worker: Message received from main script', evt.data);\n abortController.abort();\n abortController = new AbortController();\n fetch(evt.data, {\n signal: abortController.signal,\n })\n .then((res) => res.json())\n .then((data) => {\n const a = translateTrajCollResponse(data.features);\n // eslint-disable-next-line no-restricted-globals\n self.postMessage(a);\n })\n .catch(() => {\n // eslint-disable-next-line no-restricted-globals\n // self.postMessage(null);\n });\n};\n"],"sourceRoot":""}