File : data/Route.js

1
/*
2
Copyright - 2017 2023 - wwwouaiebe - Contact: https://www.ouaie.be/
3
4
This  program is free software;
5
you can redistribute it and/or modify it under the terms of the
6
GNU General Public License as published by the Free Software Foundation;
7
either version 3 of the License, or any later version.
8
This program is distributed in the hope that it will be useful,
9
but WITHOUT ANY WARRANTY; without even the implied warranty of
10
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
GNU General Public License for more details.
12
You should have received a copy of the GNU General Public License
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
15
*/
16
/*
17
Changes:
18
    - v4.0.0:
19
        - created from v3.6.0
20
Doc reviewed 202208
21
 */
22
23
import theConfig from '../data/Config.js';
24
import ObjId from '../data/ObjId.js';
25
import ObjType from '../data/ObjType.js';
26
import Collection from '../data/Collection.js';
27
import WayPoint from '../data/WayPoint.js';
28
import Itinerary from '../data/Itinerary.js';
29
import Note from '../data/Note.js';
30
import theHTMLSanitizer from '../core/htmlSanitizer/HTMLSanitizer.js';
31
import TravelObject from '../data/TravelObject.js';
32
import { ROUTE_EDITION_STATUS, DISTANCE, ZERO, ONE, INVALID_OBJ_ID, LAT_LNG } from '../main/Constants.js';
33
34
/* ------------------------------------------------------------------------------------------------------------------------- */
35
/**
36
This class represent a route
37
*/
38
/* ------------------------------------------------------------------------------------------------------------------------- */
39
40
class Route extends TravelObject {
41
42
    /**
43
    The object type for routes
44
    @type {ObjType}
45
    */
46
47
    static #objType = new ObjType (
48
        'Route',
49
        [
50
            'name',
51
            'wayPoints',
52
            'notes',
53
            'itinerary',
54
            'width',
55
            'color',
56
            'dashIndex',
57
            'chain',
58
            'chainedDistance',
59
            'distance',
60
            'duration',
61
            'editionStatus',
62
            'hidden',
63
            'objId'
64
        ]
65
    );
66
67
    /**
68
    the name of the Route
69
    @type {String}
70
    */
71
72
    #name = '';
73
74
    /**
75
    a Collection of WayPoints
76
    @type {Collection.<WayPoint>}
77
    */
78
79
    #wayPoints = new Collection ( WayPoint );
80
81
    /**
82
    a Collection of Notes
83
    @type {Collection.<Note>}
84
    */
85
86
    #notes = new Collection ( Note );
87
88
    /**
89
    the Route Itinerary
90
    @type {Itinerary}
91
    */
92
93
    #itinerary = new Itinerary ( );
94
95
    /**
96
    the width of the Leaflet polyline used to represent the Route on the map
97
    @type {Number}
98
    */
99
100
    #width = theConfig.route.width;
101
102
    /**
103
    the color of the Leaflet polyline used to represent the Route on the map
104
    using the css format '#rrggbb'
105
    @type {String}
106
    */
107
108
    #color = theConfig.route.color;
109
110
    /**
111
    the dash of the Leaflet polyline used to represent the Route on the map.
112
    It's the index of the dash in the array Config.route.dashChoices
113
    @type {Number}
114
    */
115
116
    #dashIndex = theConfig.route.dashIndex;
117
118
    /**
119
    boolean indicates if the route is chained
120
    @type {Boolean}
121
    */
122
123
    #chain = true;
124
125
    /**
126
    the distance between the starting point of the travel and the starting point
127
    of the route if the route is chained, otherwise DISTANCE.defaultValue
128
    @type {Number}
129
    */
130
131
    #chainedDistance = DISTANCE.defaultValue;
132
133
    /**
134
    the length of the route or DISTANCE.defaultValue if the Itinerary is not anymore computed
135
    @type {Number}
136
    */
137
138
    #distance = DISTANCE.defaultValue;
139
140
    /**
141
    the duration of the route or DISTANCE.defaultValue if the Itinerary is not anymore computed
142
    @type {Number}
143
    */
144
145
    #duration = DISTANCE.defaultValue;
146
147
    /**
148
    A number indicating the status of the route.
149
    See ROUTE_EDITION_STATUS for possible values
150
    @type {Number}
151
    */
152
153
    #editionStatus = ROUTE_EDITION_STATUS.notEdited;
154
155
    /**
156
    a boolean set to true when the route is hidden on the map
157
    @type {Boolean}
158
    */
159
160
    #hidden = false;
161
162
    /**
163
    the objId of the route
164
    @type {Number}
165
    */
166
167
    #objId = INVALID_OBJ_ID;
168
169
    /**
170
    The constructor
171
    */
172
173
    constructor ( ) {
174
        super ( );
175
        this.#wayPoints.add ( new WayPoint ( ) );
176
        this.#wayPoints.add ( new WayPoint ( ) );
177
        this.#objId = ObjId.nextObjId;
178
    }
179
180
    /**
181
    the name of the Route
182
    @type {String}
183
    */
184
185
    get name ( ) { return this.#name; }
186
187
    set name ( Name ) {
188
        this.#name =
189
            'string' === typeof ( Name )
190
                ?
191
                theHTMLSanitizer.sanitizeToJsString ( Name )
192
                :
193
                '';
194
    }
195
196
    /**
197
    a Collection of WayPoints
198
    @type {Collection.<WayPoint>}
199
    */
200
201
    get wayPoints ( ) { return this.#wayPoints; }
202
203
    /**
204
    a Collection of Notes
205
    @type {Collection.<Note>}
206
    */
207
208
    get notes ( ) { return this.#notes; }
209
210
    /**
211
    the Route Itinerary
212
    @type {Itinerary}
213
    */
214
215
    get itinerary ( ) { return this.#itinerary; }
216
217
    /**
218
    the width of the Leaflet polyline used to represent the Route on the map
219
    @type {Number}
220
    */
221
222
    get width ( ) { return this.#width; }
223
224
    set width ( width ) {
225
        this.#width = 'number' === typeof ( width ) ? width : theConfig.route.width;
226
    }
227
228
    /**
229
    the color of the Leaflet polyline used to represent the Route on the map
230
    using the css format '#rrggbb'
231
    @type {String}
232
    */
233
234
    get color ( ) { return this.#color; }
235
236
    set color ( color ) {
237
        this.#color =
238
            'string' === typeof ( color )
239
                ?
240
                theHTMLSanitizer.sanitizeToColor ( color ) || theConfig.route.color
241
                :
242
                theConfig.route.color;
243
    }
244
245
    /**
246
    The index of the dash in the array Config.route.dashChoices
247
    @type {Number}
248
    */
249
250
    get dashIndex ( ) { return this.#dashIndex; }
251
252
    set dashIndex ( dashIndex ) {
253
        this.#dashIndex =
254
            'number' === typeof ( dashIndex ) && theConfig.route.dashChoices [ dashIndex ]
255
                ?
256
                dashIndex
257
                :
258
                ZERO;
259
    }
260
261
    /**
262
    The string used by Leaflet for the dash to display the route
263
    @type {String}
264
    */
265
266
    get dashString ( ) {
267
        let dashString = '';
268
        theConfig.route.dashChoices [ this.#dashIndex ].iDashArray.forEach (
269
            iDash => dashString += String ( iDash * this.#width ) + ','
270
        );
271
272
        return dashString.substring ( ZERO, dashString.length - ONE );
273
    }
274
275
    /**
276
    A boolean indicating if the route is chained
277
    @type {Boolean}
278
    */
279
280
    get chain ( ) { return this.#chain; }
281
282
    set chain ( chain ) { this.#chain = 'boolean' === typeof ( chain ) ? chain : false; }
283
284
    /**
285
    the distance betwween the starting point of the travel and the starting point
286
    of the route if the route is chained, otherwise DISTANCE.defaultValue
287
    @type {Number}
288
    */
289
290
    get chainedDistance ( ) { return this.#chainedDistance; }
291
292
    set chainedDistance ( chainedDistance ) {
293
        this.#chainedDistance = 'number' === typeof ( chainedDistance ) ? chainedDistance : DISTANCE.defaultValue;
294
    }
295
296
    /**
297
    the length of the route or DISTANCE.defaultValue if the Itinerary is not anymore computed
298
    @type {Number}
299
    */
300
301
    get distance ( ) { return this.#distance; }
302
303
    set distance ( distance ) {
304
        this.#distance = 'number' === typeof ( distance ) ? distance : DISTANCE.defaultValue;
305
    }
306
307
    /**
308
    the duration of the route or DISTANCE.defaultValue if the Itinerary is not anymore computed
309
    @type {Number}
310
    */
311
312
    get duration ( ) { return this.#duration; }
313
314
    set duration ( duration ) {
315
        this.#duration = 'number' === typeof ( duration ) ? duration : DISTANCE.defaultValue;
316
317
    }
318
319
    /**
320
    A number indicating the status of the route.
321
    See ROUTE_EDITION_STATUS for possible values
322
    @type {Number}
323
    */
324
325
    get editionStatus ( ) { return this.#editionStatus; }
326
327
    set editionStatus ( editionStatus ) {
328
        this.#editionStatus =
329
            'number' === typeof ( editionStatus )
330
                ?
331
                editionStatus
332
                :
333
                ROUTE_EDITION_STATUS.notEdited;
334
    }
335
336
    /**
337
    a boolean set to true when the route is hidden on the map
338
    @type {Boolean}
339
    */
340
341
    get hidden ( ) { return this.#hidden; }
342
343
    set hidden ( hidden ) {
344
        this.#hidden = 'boolean' === typeof ( hidden ) ? hidden : false;
345
    }
346
347
    /**
348
    A name computed from the starting WayPoint and ending WayPoint names and addresses
349
    @type {String}
350
    */
351
352
    get computedName ( ) {
353
        let computedName = this.name;
354
        if ( '' === computedName ) {
355
            computedName =
356
                ( '' === this.wayPoints.first.fullName ? '???' : this.wayPoints.first.fullName ) +
357
                ' ⮞ ' +
358
                ( '' === this.wayPoints.last.fullName ? '???' : this.wayPoints.last.fullName );
359
        }
360
361
        return computedName;
362
    }
363
364
    /**
365
    the objId of the Route. objId are unique identifier given by the code
366
    @type {Number}
367
    */
368
369
    get objId ( ) { return this.#objId; }
370
371
    /**
372
    the ObjType of the Route.
373
    @type {ObjType}
374
    */
375
376
    get objType ( ) { return Route.#objType; }
377
378
    /**
379
    This method verify that all waypoints have valid coordinates ( reminder: a route have always a startpoint
380
    and an endpoint!)
381
    @return {Boolean} true when all waypoints have valid coordinates
382
    */
383
384
    haveValidWayPoints ( ) {
385
        let haveValidWayPoints = true;
386
        this.wayPoints.forEach (
387
            wayPoint => {
388
                haveValidWayPoints =
389
                    haveValidWayPoints
390
                    &&
391
                    LAT_LNG.defaultValue !== wayPoint.lat
392
                    &&
393
                    LAT_LNG.defaultValue !== wayPoint.lng;
394
            }
395
        );
396
        return haveValidWayPoints;
397
    }
398
399
    /**
400
    An object literal with the WayPoint properties and without any methods.
401
    This object can be used with the JSON object
402
    @type {JsonObject}
403
    */
404
405
    get jsonObject ( ) {
406
        return {
407
            name : this.name,
408
            wayPoints : this.wayPoints.jsonObject,
409
            notes : this.notes.jsonObject,
410
            itinerary : this.itinerary.jsonObject,
411
            width : this.width,
412
            color : this.color,
413
            dashIndex : this.dashIndex,
414
            chain : this.chain,
415
            distance : parseFloat ( this.distance.toFixed ( DISTANCE.fixed ) ),
416
            duration : this.duration,
417
            editionStatus : this.editionStatus,
418
            hidden : this.hidden,
419
            chainedDistance : parseFloat ( this.chainedDistance.toFixed ( DISTANCE.fixed ) ),
420
            objId : this.#objId,
421
            objType : this.objType.jsonObject
422
        };
423
    }
424
425
    set jsonObject ( something ) {
426
        const otherthing = this.validateObject ( something );
427
        this.name = otherthing.name;
428
        this.wayPoints.jsonObject = otherthing.wayPoints;
429
        this.notes.jsonObject = otherthing.notes;
430
        this.itinerary.jsonObject = otherthing.itinerary;
431
        this.width = otherthing.width;
432
        this.color = otherthing.color;
433
        this.dashIndex = otherthing.dashIndex;
434
        this.chain = otherthing.chain;
435
        this.distance = otherthing.distance;
436
        this.duration = otherthing.duration;
437
        this.editionStatus = otherthing.editionStatus;
438
        this.hidden = otherthing.hidden;
439
        this.chainedDistance = otherthing.chainedDistance;
440
        this.#objId = ObjId.nextObjId;
441
    }
442
}
443
444
export default Route;
445
446
/* --- End of file --------------------------------------------------------------------------------------------------------- */
447