File : core/lib/FileCompactor.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
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
GNU General Public License for more details.
13
14
You should have received a copy of the GNU General Public License
15
along with this program; if not, write to the Free Software
16
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17
*/
18
/*
19
Changes:
20
    - v4.0.0:
21
        - created from v3.6.0
22
Doc reviewed 202208
23
 */
24
25
import PolylineEncoder from './PolylineEncoder.js';
26
import ItineraryPoint from '../../data/ItineraryPoint.js';
27
import { ELEV, ZERO, ONE, TWO, INVALID_OBJ_ID, LAT_LNG, DISTANCE } from '../../main/Constants.js';
28
29
/* ------------------------------------------------------------------------------------------------------------------------- */
30
/**
31
This class compress the travel to reduce the size of the file when saved to a file or decompress the
32
travel when reading from a file. Each route of a compressed file have the ItineraryPoints in only one object
33
and the lat and lng of    the ItineraryPoints are encoded with the polyline.encode algorithm
34
*/
35
/* ------------------------------------------------------------------------------------------------------------------------- */
36
37
class FileCompactor {
38
39
    /**
40
    Compress a route
41
    @param {JsonObject} routeJsonObject the route to compress. routeJsonObject is not a Route instance!
42
    It's an Object created with Route.jsonObject ( ).
43
    */
44
45
    #compressRoute ( routeJsonObject ) {
46
        const compressedItineraryPoints = {
47
            values : '',
48
            objType : new ItineraryPoint ( ).objType.jsonObject
49
        };
50
        const itineraryPoints = [];
51
        routeJsonObject.itinerary.itineraryPoints.forEach (
52
            itineraryPoint => {
53
                itineraryPoints.push (
54
                    [
55
                        itineraryPoint.lat,
56
                        itineraryPoint.lng,
57
                        itineraryPoint.distance,
58
                        itineraryPoint.elev,
59
                        itineraryPoint.objId
60
                    ]
61
                );
62
            }
63
        );
64
        compressedItineraryPoints.values = new PolylineEncoder ( ).encode (
65
            itineraryPoints,
66
            [ LAT_LNG.fixed, LAT_LNG.fixed, TWO, TWO, ZERO ]
67
        );
68
69
        routeJsonObject.itinerary.itineraryPoints = compressedItineraryPoints;
70
    }
71
72
    /**
73
    Decompress a route
74
    @param {JsonObject} routeJsonObject the compressed route. routeJsonObject is not a Route instance!
75
    It's an Object created with JSON.parse ( ).
76
    */
77
78
    #decompressRoute ( routeJsonObject ) {
79
        const decompressedItineraryPoints = [];
80
81
        /*
82
        routeJsonObject.itinerary.itineraryPoints have values since version 2.1.0 ,
83
        routeJsonObject.itinerary.itineraryPoints have latLngs before version 2.1.0
84
        not possible to adapt with TravelUpdater because TravelUpdater is executed after this
85
        */
86
87
        if ( routeJsonObject.itinerary.itineraryPoints.values ) {
88
            new PolylineEncoder ( ).decode (
89
                routeJsonObject.itinerary.itineraryPoints.values,
90
                [ LAT_LNG.fixed, LAT_LNG.fixed, TWO, TWO, ZERO ]
91
            )
92
                .forEach (
93
                    value => {
94
                        const itineraryPoint = {
95
                            lat : LAT_LNG.defaultValue,
96
                            lng : LAT_LNG.defaultValue,
97
                            distance : DISTANCE.defaultValue,
98
                            elev : ELEV.defaultValue,
99
                            objId : INVALID_OBJ_ID
100
                        };
101
                        [
102
                            itineraryPoint.lat,
103
                            itineraryPoint.lng,
104
                            itineraryPoint.distance,
105
                            itineraryPoint.elev,
106
                            itineraryPoint.objId
107
                        ] = value;
108
                        itineraryPoint.objType = routeJsonObject.itinerary.itineraryPoints.objType;
109
                        decompressedItineraryPoints.push ( itineraryPoint );
110
                    }
111
                );
112
        }
113
        else {
114
            routeJsonObject.itinerary.itineraryPoints.latLngs = new PolylineEncoder ( ).decode (
115
                routeJsonObject.itinerary.itineraryPoints.latLngs, [ LAT_LNG.fixed, LAT_LNG.fixed ]
116
            );
117
            let latLngsCounter = ZERO;
118
            routeJsonObject.itinerary.itineraryPoints.latLngs.forEach (
119
                latLng => {
120
                    const itineraryPoint = {};
121
                    itineraryPoint.lat = latLng [ ZERO ];
122
                    itineraryPoint.lng = latLng [ ONE ];
123
                    itineraryPoint.distance = routeJsonObject.itinerary.itineraryPoints.distances [ latLngsCounter ];
124
                    if ( routeJsonObject.itinerary.itineraryPoints.elevs ) {
125
                        itineraryPoint.elev = routeJsonObject.itinerary.itineraryPoints.elevs [ latLngsCounter ];
126
                    }
127
                    else {
128
                        itineraryPoint.elev = ELEV.defaultValue;
129
                    }
130
                    itineraryPoint.objId = routeJsonObject.itinerary.itineraryPoints.objIds [ latLngsCounter ];
131
                    itineraryPoint.objType = routeJsonObject.itinerary.itineraryPoints.objType;
132
                    decompressedItineraryPoints.push ( itineraryPoint );
133
                    latLngsCounter ++;
134
                }
135
            );
136
        }
137
        routeJsonObject.itinerary.itineraryPoints = decompressedItineraryPoints;
138
    }
139
140
    /**
141
    The constructor
142
    */
143
144
    constructor ( ) {
145
        Object.freeze ( this );
146
    }
147
148
    /**
149
    Decompress a travel
150
    @param {JsonObject} travelJsonObject the compressed travel. travelJsonObject is not a Travel instance!
151
    It's an Object created with JSON.parse ( ).
152
    */
153
154
    decompress ( travelJsonObject ) {
155
        travelJsonObject.routes.forEach ( this.#decompressRoute );
156
        if ( travelJsonObject.editedRoute ) {
157
158
            // don't remove the if statment... files created with version < 1.5.0 don't have editedRoute...
159
            this.#decompressRoute ( travelJsonObject.editedRoute );
160
        }
161
    }
162
163
    /**
164
    Compress the currently edited travel
165
    @return {JsonObject} a copy of the currently edited travel compressed and ready to be written in a file
166
    @param {Travel} travel The object to compress
167
    */
168
169
    compress ( travel ) {
170
        const compressedTravelJsonObject = travel.jsonObject;
171
        compressedTravelJsonObject.routes.forEach (
172
            routeJsonObject => this.#compressRoute ( routeJsonObject )
173
        );
174
        this.#compressRoute ( compressedTravelJsonObject.editedRoute );
175
176
        return compressedTravelJsonObject;
177
    }
178
}
179
180
export default FileCompactor;
181
182
/* --- End of file --------------------------------------------------------------------------------------------------------- */
183