fleetmap-reports 1.0.413 → 1.0.414

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fleetmap-reports",
3
- "version": "1.0.413",
3
+ "version": "1.0.414",
4
4
  "description": "",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -6,6 +6,7 @@ const { getUserPartner } = require('fleetmap-partners')
6
6
  const { devicesToProcess } = require('./util/device')
7
7
  const automaticReports = require('./automaticReports')
8
8
  const traccarHelper = require('./util/traccar')
9
+ const { getIdleEvents } = require('./util/route')
9
10
 
10
11
  const fileName = 'IdleReport'
11
12
 
@@ -149,46 +150,6 @@ function processDevices (from, to, devices, routes, userData) {
149
150
  return devicesResult
150
151
  }
151
152
 
152
- function getIdleEvents (route) {
153
- const idleEvents = []
154
-
155
- const routeByDevice = route.reduce(function (a, x) {
156
- (a[x.deviceId] = a[x.deviceId] || []).push(x)
157
- return a
158
- }, {})
159
-
160
- Object.keys(routeByDevice).forEach(function (key) {
161
- let inIdle = false
162
- routeByDevice[key].forEach(p => {
163
- if (p.attributes.ignition && p.speed === 0) {
164
- if (!inIdle) {
165
- const idleEvent = {
166
- position: p,
167
- idleTime: 0
168
- }
169
- idleEvents.push(idleEvent)
170
- inIdle = true
171
- } else {
172
- if (!idleEvents[idleEvents.length - 1].position.attributes.driverUniqueId) {
173
- idleEvents[idleEvents.length - 1].position.attributes.driverUniqueId = p.attributes.driverUniqueId
174
- }
175
- if (p.attributes.idleTime) {
176
- idleEvents[idleEvents.length - 1].idleTime = p.attributes.idleTime
177
- }
178
- }
179
- } else if (inIdle) {
180
- const currentIdleEvent = idleEvents[idleEvents.length - 1]
181
- if (p.attributes.idleTime === undefined) {
182
- currentIdleEvent.idleTime = new Date(p.fixTime) - new Date(currentIdleEvent.position.fixTime)
183
- }
184
- inIdle = false
185
- }
186
- })
187
- })
188
-
189
- return idleEvents
190
- }
191
-
192
153
  async function exportIdleReportToPDF (userData, reportData) {
193
154
  console.log('Export to PDF')
194
155
 
@@ -7,8 +7,9 @@ const { headerFromUser, addTable } = require('./util/pdfDocument')
7
7
  const { getStyle } = require('./reportStyle')
8
8
  const traccarHelper = require('./util/traccar')
9
9
  const trips = require('./util/trips')
10
- const { isInsideTimetable, addNearestPOIs, isPartialInsideTimetable, calculateTrip } = require('./util/trips')
10
+ const { isInsideTimetable, addNearestPOIs, isPartialInsideTimetable, calculateTrip, getTripIdleTime } = require('./util/trips')
11
11
  const { devicesToProcess } = require('./util/device')
12
+ const { getIdleEvents } = require('./util/route')
12
13
 
13
14
  const fileName = 'TripReport'
14
15
 
@@ -192,6 +193,13 @@ function processDrivers (from, to, userData, data) {
192
193
 
193
194
  trips.sort((a, b) => new Date(a.startTime).getTime() - new Date(b.startTime).getTime())
194
195
 
196
+ const idleEvents = getIdleEvents(data.route.filter(p => p.attributes.driverUniqueId === d.uniqueId || !p.attributes.ignition))
197
+
198
+ trips.forEach(function (trip, i) {
199
+ trip.stopEngineHours = getTripIdleTime(trip, idleEvents)
200
+ trip.stopDuration = i !== trips.length - 1 ? (new Date(trips[i + 1].startTime) - new Date(trip.endTime)) : 0
201
+ })
202
+
195
203
  addNearestPOIs(trips, userData)
196
204
 
197
205
  if (trips.length > 0) {
@@ -229,7 +237,9 @@ async function exportTripReportToPDF (userData, reportData) {
229
237
  ]
230
238
 
231
239
  if (userData.byDriver) {
232
- headers.push(translations.report.distance,
240
+ headers.push(translations.report.idleTime,
241
+ translations.report.stopTime,
242
+ translations.report.distance,
233
243
  translations.report.avgSpeed,
234
244
  translations.report.maxSpeed,
235
245
  translations.report.name)
@@ -276,7 +286,7 @@ async function exportTripReportToPDF (userData, reportData) {
276
286
  doc.text(translations.report.headerStartAddress + ': ' + d.trips[0].startAddress, 20, space + 35)
277
287
  }
278
288
 
279
- d.trips.map(a => {
289
+ d.trips.forEach(a => {
280
290
  const temp = [
281
291
  getTripDate(userData.user, a),
282
292
  getTripStart(userData.user, a),
@@ -285,18 +295,16 @@ async function exportTripReportToPDF (userData, reportData) {
285
295
  convertMS(a.duration)
286
296
  ]
287
297
 
298
+ temp.push(convertMS(a.stopEngineHours),
299
+ convertMS(a.stopDuration),
300
+ Intl.NumberFormat(userData.user.attributes.lang, { maximumFractionDigits: 2 }).format(a.totalKms),
301
+ Math.round(a.averageSpeed * 1.85200),
302
+ Math.round(a.maxSpeed * 1.85200))
303
+
288
304
  if (userData.byDriver) {
289
- temp.push(Intl.NumberFormat(userData.user.attributes.lang, { maximumFractionDigits: 2 }).format(a.totalKms),
290
- Math.round(a.averageSpeed * 1.85200),
291
- Math.round(a.maxSpeed * 1.85200),
292
- a.deviceName)
305
+ temp.push(a.deviceName)
293
306
  } else {
294
- temp.push(convertMS(a.stopEngineHours),
295
- convertMS(a.stopDuration),
296
- Intl.NumberFormat(userData.user.attributes.lang, { maximumFractionDigits: 2 }).format(a.totalKms),
297
- Math.round(a.averageSpeed * 1.85200),
298
- Math.round(a.maxSpeed * 1.85200),
299
- getDriverName(userData.drivers, a.driverUniqueId))
307
+ temp.push(getDriverName(userData.drivers, a.driverUniqueId))
300
308
  }
301
309
 
302
310
  data.push(temp)
@@ -307,17 +315,11 @@ async function exportTripReportToPDF (userData, reportData) {
307
315
  convertMS(d.trips.reduce((a, b) => a + b.duration, 0))
308
316
  ]
309
317
 
310
- if (userData.byDriver) {
311
- footValues.push(getSumTotalKms(userData.user, d.trips),
312
- getSumAvgSpeed(d.trips),
313
- getMaxSpeed(d.trips))
314
- } else {
315
- footValues.push(convertMS(d.trips.reduce((a, b) => a + b.stopEngineHours, 0)),
316
- convertMS(d.trips.reduce((a, b) => a + b.stopDuration, 0)),
317
- getSumTotalKms(userData.user, d.trips),
318
- getSumAvgSpeed(d.trips),
319
- getMaxSpeed(d.trips))
320
- }
318
+ footValues.push(convertMS(d.trips.reduce((a, b) => a + b.stopEngineHours, 0)),
319
+ convertMS(d.trips.reduce((a, b) => a + b.stopDuration, 0)),
320
+ getSumTotalKms(userData.user, d.trips),
321
+ getSumAvgSpeed(d.trips),
322
+ getMaxSpeed(d.trips))
321
323
 
322
324
  const style = getStyle(getUserPartner(userData.user))
323
325
  addTable(doc, headers, data, footValues, style, space + (userData.allWeek ? 40 : 45))
@@ -345,6 +347,8 @@ function exportTripReportToExcel (userData, reportData) {
345
347
  { label: translations.report.end, value: 'end' },
346
348
  { label: translations.report.endAddress, value: 'endAddress' },
347
349
  { label: translations.report.tripTime, value: 'tripTime' },
350
+ { label: translations.report.idleTime, value: 'idleTime' },
351
+ { label: translations.report.stopTime, value: 'stopTime' },
348
352
  { label: translations.report.distance, value: 'distance' },
349
353
  { label: translations.report.avgSpeed, value: 'averageSpeed' },
350
354
  { label: translations.report.maxSpeed, value: 'maxSpeed' },
@@ -0,0 +1,41 @@
1
+ function getIdleEvents (route) {
2
+ const idleEvents = []
3
+
4
+ const routeByDevice = route.reduce(function (a, x) {
5
+ (a[x.deviceId] = a[x.deviceId] || []).push(x)
6
+ return a
7
+ }, {})
8
+
9
+ Object.keys(routeByDevice).forEach(function (key) {
10
+ let inIdle = false
11
+ routeByDevice[key].forEach(p => {
12
+ if (p.attributes.ignition && p.speed === 0) {
13
+ if (!inIdle) {
14
+ const idleEvent = {
15
+ position: p,
16
+ idleTime: 0
17
+ }
18
+ idleEvents.push(idleEvent)
19
+ inIdle = true
20
+ } else {
21
+ if (!idleEvents[idleEvents.length - 1].position.attributes.driverUniqueId) {
22
+ idleEvents[idleEvents.length - 1].position.attributes.driverUniqueId = p.attributes.driverUniqueId
23
+ }
24
+ if (p.attributes.idleTime) {
25
+ idleEvents[idleEvents.length - 1].idleTime = p.attributes.idleTime
26
+ }
27
+ }
28
+ } else if (inIdle) {
29
+ const currentIdleEvent = idleEvents[idleEvents.length - 1]
30
+ if (p.attributes.idleTime === undefined) {
31
+ currentIdleEvent.idleTime = new Date(p.fixTime) - new Date(currentIdleEvent.position.fixTime)
32
+ }
33
+ inIdle = false
34
+ }
35
+ })
36
+ })
37
+
38
+ return idleEvents
39
+ }
40
+
41
+ exports.getIdleEvents = getIdleEvents
package/src/util/trips.js CHANGED
@@ -1,175 +1,178 @@
1
- const {coordsDistance, convertFromUTC, weekDaySelected} = require("./utils");
1
+ const { coordsDistance, convertFromUTC, weekDaySelected } = require('./utils')
2
2
 
3
3
  const minDistance = 0
4
4
  const minAvgSpeed = 0
5
5
 
6
- function addNearestPOIs(trips, userData){
7
- trips.forEach(t => {
8
- t.totalKms = t.distance / 1000
9
-
10
- const distance = userData.geofences
11
- .filter(g => g && g.area.startsWith('CIRCLE'))
12
- .map(g => {
13
- const str = g.area.substring('CIRCLE ('.length, g.area.indexOf(','))
14
- const coord = str.trim().split(' ')
15
- return {
16
- p: g,
17
- distance: Math.round(coordsDistance(parseFloat(coord[1]), parseFloat(coord[0]), t.endLon, t.endLat))
18
- }
19
- })
20
- const nearestPOIs = distance.filter(a => a.distance < 100).sort((a, b) => (a.distance > b.distance) ? 1 : -1)
21
- if (nearestPOIs.length > 0) {
22
- t.endPOIName = nearestPOIs[0].p.name
6
+ function addNearestPOIs (trips, userData) {
7
+ trips.forEach(t => {
8
+ t.totalKms = t.distance / 1000
9
+
10
+ const distance = userData.geofences
11
+ .filter(g => g && g.area.startsWith('CIRCLE'))
12
+ .map(g => {
13
+ const str = g.area.substring('CIRCLE ('.length, g.area.indexOf(','))
14
+ const coord = str.trim().split(' ')
15
+ return {
16
+ p: g,
17
+ distance: Math.round(coordsDistance(parseFloat(coord[1]), parseFloat(coord[0]), t.endLon, t.endLat))
23
18
  }
24
- })
25
- }
26
-
27
- function checkTripsKms(traccarInstance, from, to, devices, data) {
28
- console.log('checkTripsKms')
29
- const trips = data.trips.filter(t => t.distance === minDistance && t.averageSpeed > minAvgSpeed)
30
- if(trips.length > 0) {
31
- //Vehicles with imported positions. calculate trip distance with route positions
32
- trips.forEach(t => {
33
- if(t.distance === minDistance && t.averageSpeed > minAvgSpeed) {
34
- const tripRoute = data.route.filter(p => p.deviceId === t.deviceId
35
- && new Date(p.fixTime).getTime() >= new Date(t.startTime).getTime()
36
- && new Date(p.fixTime).getTime() <= new Date(t.endTime).getTime())
37
-
38
- let current = null
39
- const distances = []
40
- for(const p of tripRoute) {
41
- if(current) {
42
- distances.push(coordsDistance(parseFloat(current.longitude),parseFloat(current.latitude),
43
- parseFloat(p.longitude),parseFloat(p.latitude)))
44
- }
45
- current = p
46
- }
47
-
48
- t.distance = distances.reduce((a, b) => a + b, 0)
49
- }
50
- })
19
+ })
20
+ const nearestPOIs = distance.filter(a => a.distance < 100).sort((a, b) => (a.distance > b.distance) ? 1 : -1)
21
+ if (nearestPOIs.length > 0) {
22
+ t.endPOIName = nearestPOIs[0].p.name
51
23
  }
24
+ })
52
25
  }
53
26
 
54
- function isPartialInsideTimetable(t, userData, route){
55
- const tripStart = new Date(t.startTime)
56
- const tripEnd = new Date(t.endTime)
57
-
58
- let isPartialInside = false
59
-
60
- if(weekDaySelected(tripStart, userData.weekDays)) {
61
-
62
- const startDate = new Date(convertFromUTC(t.startTime, userData.user.attributes.timezone).toISOString().split('T')[0] + ' '+userData.dayHours.startTime)
63
- const endDate = new Date(convertFromUTC(t.startTime, userData.user.attributes.timezone).toISOString().split('T')[0] + ' '+userData.dayHours.endTime)
64
-
65
- if(startDate.getTime() > endDate.getTime()){
66
- //Trip starts outside time period and ends inside time period
67
- if (tripStart.getTime() < endDate.getTime()
68
- && tripEnd.getTime() > endDate.getTime()) {
69
- //Trip starts inside time period and ends outside time period
70
- const routeInside = route.filter(p => new Date(p.fixTime).getTime() < new Date(endDate.toUTCString()).getTime() && new Date(p.fixTime).getTime() > new Date(t.startTime).getTime() && t.deviceId === p.deviceId)
71
- updateTrip(t, routeInside)
72
- t.endTime = endDate.toISOString()
73
- t.endTimeIsOut = true
74
- isPartialInside = true
75
- }
76
-
77
- if (tripStart.getTime() < startDate.getTime()
78
- && new Date(t.endTime).getTime() > startDate.getTime()) {
79
-
80
- //Trip starts outside time period and ends inside time period
81
- const routeInside = route.filter(p => new Date(p.fixTime).getTime() > startDate.getTime() && new Date(p.fixTime).getTime() < new Date(t.endTime).getTime() && t.deviceId === p.deviceId)
82
- updateTrip(t, routeInside)
83
- t.startTime = startDate.toISOString()
84
- t.startTimeIsOut = true
85
- isPartialInside = true
86
- }
87
-
88
- } else {
89
- if (tripStart.getTime() < startDate.getTime()
90
- && tripEnd.getTime() > startDate.getTime()) {
91
- //Trip starts outside time period and ends inside time period
92
- const routeInside = route.filter(p => new Date(p.fixTime).getTime() > new Date(startDate.toUTCString()).getTime() && new Date(p.fixTime).getTime() < new Date(t.endTime).getTime() && t.deviceId === p.deviceId)
93
- updateTrip(t, routeInside)
94
- t.startTime = startDate.toISOString()
95
- t.startTimeIsOut = true
96
- isPartialInside = true
97
- }
98
-
99
- if (tripStart.getTime() < endDate.getTime()
100
- && tripEnd.getTime() > endDate.getTime()) {
101
- //Trip starts inside time period and ends outside time period
102
- const routeInside = route.filter(p => new Date(p.fixTime).getTime() < endDate.getTime() && new Date(p.fixTime).getTime() > new Date(t.startTime).getTime() && t.deviceId === p.deviceId)
103
- updateTrip(t, routeInside)
104
- t.endTime = endDate.toISOString()
105
- t.endTimeIsOut = true
106
- isPartialInside = true
107
- }
27
+ function checkTripsKms (traccarInstance, from, to, devices, data) {
28
+ console.log('checkTripsKms')
29
+ const trips = data.trips.filter(t => t.distance === minDistance && t.averageSpeed > minAvgSpeed)
30
+ if (trips.length > 0) {
31
+ // Vehicles with imported positions. calculate trip distance with route positions
32
+ trips.forEach(t => {
33
+ if (t.distance === minDistance && t.averageSpeed > minAvgSpeed) {
34
+ const tripRoute = data.route.filter(p => p.deviceId === t.deviceId &&
35
+ new Date(p.fixTime).getTime() >= new Date(t.startTime).getTime() &&
36
+ new Date(p.fixTime).getTime() <= new Date(t.endTime).getTime())
37
+
38
+ let current = null
39
+ const distances = []
40
+ for (const p of tripRoute) {
41
+ if (current) {
42
+ distances.push(coordsDistance(parseFloat(current.longitude), parseFloat(current.latitude),
43
+ parseFloat(p.longitude), parseFloat(p.latitude)))
44
+ }
45
+ current = p
108
46
  }
109
- }
110
47
 
111
- return isPartialInside
48
+ t.distance = distances.reduce((a, b) => a + b, 0)
49
+ }
50
+ })
51
+ }
112
52
  }
113
53
 
54
+ function isPartialInsideTimetable (t, userData, route) {
55
+ const tripStart = new Date(t.startTime)
56
+ const tripEnd = new Date(t.endTime)
57
+
58
+ let isPartialInside = false
59
+
60
+ if (weekDaySelected(tripStart, userData.weekDays)) {
61
+ const startDate = new Date(convertFromUTC(t.startTime, userData.user.attributes.timezone).toISOString().split('T')[0] + ' ' + userData.dayHours.startTime)
62
+ const endDate = new Date(convertFromUTC(t.startTime, userData.user.attributes.timezone).toISOString().split('T')[0] + ' ' + userData.dayHours.endTime)
63
+
64
+ if (startDate.getTime() > endDate.getTime()) {
65
+ // Trip starts outside time period and ends inside time period
66
+ if (tripStart.getTime() < endDate.getTime() &&
67
+ tripEnd.getTime() > endDate.getTime()) {
68
+ // Trip starts inside time period and ends outside time period
69
+ const routeInside = route.filter(p => new Date(p.fixTime).getTime() < new Date(endDate.toUTCString()).getTime() && new Date(p.fixTime).getTime() > new Date(t.startTime).getTime() && t.deviceId === p.deviceId)
70
+ updateTrip(t, routeInside)
71
+ t.endTime = endDate.toISOString()
72
+ t.endTimeIsOut = true
73
+ isPartialInside = true
74
+ }
75
+
76
+ if (tripStart.getTime() < startDate.getTime() &&
77
+ new Date(t.endTime).getTime() > startDate.getTime()) {
78
+ // Trip starts outside time period and ends inside time period
79
+ const routeInside = route.filter(p => new Date(p.fixTime).getTime() > startDate.getTime() && new Date(p.fixTime).getTime() < new Date(t.endTime).getTime() && t.deviceId === p.deviceId)
80
+ updateTrip(t, routeInside)
81
+ t.startTime = startDate.toISOString()
82
+ t.startTimeIsOut = true
83
+ isPartialInside = true
84
+ }
85
+ } else {
86
+ if (tripStart.getTime() < startDate.getTime() &&
87
+ tripEnd.getTime() > startDate.getTime()) {
88
+ // Trip starts outside time period and ends inside time period
89
+ const routeInside = route.filter(p => new Date(p.fixTime).getTime() > new Date(startDate.toUTCString()).getTime() && new Date(p.fixTime).getTime() < new Date(t.endTime).getTime() && t.deviceId === p.deviceId)
90
+ updateTrip(t, routeInside)
91
+ t.startTime = startDate.toISOString()
92
+ t.startTimeIsOut = true
93
+ isPartialInside = true
94
+ }
95
+
96
+ if (tripStart.getTime() < endDate.getTime() &&
97
+ tripEnd.getTime() > endDate.getTime()) {
98
+ // Trip starts inside time period and ends outside time period
99
+ const routeInside = route.filter(p => new Date(p.fixTime).getTime() < endDate.getTime() && new Date(p.fixTime).getTime() > new Date(t.startTime).getTime() && t.deviceId === p.deviceId)
100
+ updateTrip(t, routeInside)
101
+ t.endTime = endDate.toISOString()
102
+ t.endTimeIsOut = true
103
+ isPartialInside = true
104
+ }
105
+ }
106
+ }
107
+
108
+ return isPartialInside
109
+ }
114
110
 
115
- function isInsideTimetable(t, userData){
116
- const tripStart = new Date(t.startTime)
117
- const tripEnd = new Date(t.endTime)
111
+ function isInsideTimetable (t, userData) {
112
+ const tripStart = new Date(t.startTime)
113
+ const tripEnd = new Date(t.endTime)
118
114
 
119
- if(weekDaySelected(tripStart, userData.weekDays)) {
120
- const startDate = new Date(convertFromUTC(t.startTime, userData.user.attributes.timezone).toISOString().split('T')[0] + ' '+userData.dayHours.startTime)
121
- const endDate = new Date(convertFromUTC(t.startTime, userData.user.attributes.timezone).toISOString().split('T')[0] + ' '+userData.dayHours.endTime)
115
+ if (weekDaySelected(tripStart, userData.weekDays)) {
116
+ const startDate = new Date(convertFromUTC(t.startTime, userData.user.attributes.timezone).toISOString().split('T')[0] + ' ' + userData.dayHours.startTime)
117
+ const endDate = new Date(convertFromUTC(t.startTime, userData.user.attributes.timezone).toISOString().split('T')[0] + ' ' + userData.dayHours.endTime)
122
118
 
123
- //Trips inside time period
124
- if(startDate.getTime() < endDate.getTime()) {
125
- console.log((tripStart.getTime() > startDate.getTime() && tripEnd.getTime() < endDate.getTime()))
126
- return tripStart.getTime() > startDate.getTime() && tripEnd.getTime() < endDate.getTime()
127
- } else {
128
- return (tripStart.getTime() < endDate.getTime() && tripEnd.getTime() < endDate.getTime()) ||
119
+ // Trips inside time period
120
+ if (startDate.getTime() < endDate.getTime()) {
121
+ console.log((tripStart.getTime() > startDate.getTime() && tripEnd.getTime() < endDate.getTime()))
122
+ return tripStart.getTime() > startDate.getTime() && tripEnd.getTime() < endDate.getTime()
123
+ } else {
124
+ return (tripStart.getTime() < endDate.getTime() && tripEnd.getTime() < endDate.getTime()) ||
129
125
  (tripStart.getTime() > startDate.getTime())
130
- }
131
126
  }
127
+ }
132
128
 
133
- return false
129
+ return false
134
130
  }
135
131
 
136
- function updateTrip(t, route){
137
- if (!route[route.length-1]) { return }
138
- const distance = route[route.length-1].attributes.totalDistance - route[0].attributes.totalDistance
139
- t.distance = distance
140
- t.duration = new Date(route[route.length-1].fixTime).getTime() - new Date(route[0].fixTime).getTime()
141
- t.maxSpeed = route.reduce((a, b) => Math.max(a, b.speed), 0)
142
- t.averageSpeed = distance > 0 ? ((route.reduce((a, b) => a + b.speed, 0)) / route.length) : 0
132
+ function updateTrip (t, route) {
133
+ if (!route[route.length - 1]) { return }
134
+ const distance = route[route.length - 1].attributes.totalDistance - route[0].attributes.totalDistance
135
+ t.distance = distance
136
+ t.duration = new Date(route[route.length - 1].fixTime).getTime() - new Date(route[0].fixTime).getTime()
137
+ t.maxSpeed = route.reduce((a, b) => Math.max(a, b.speed), 0)
138
+ t.averageSpeed = distance > 0 ? ((route.reduce((a, b) => a + b.speed, 0)) / route.length) : 0
143
139
  }
144
140
 
145
- function calculateTrip(device, route) {
146
- const startPos = route[0]
147
- const endPos = route[route.length-1]
148
-
149
- return {
150
- deviceId: device.id,
151
- deviceName: device.name,
152
- distance: route.reduce((a, b) => a + b.attributes.distance, 0),
153
- averageSpeed: Math.round((route.map(p => p.speed).reduce((a, b) => a + b, 0)) / route.length),
154
- maxSpeed: route.map(p => p.speed).reduce(function (a, b) { return Math.max(a, b) }),
155
- spentFuel: 0,
156
- startOdometer: startPos.attributes.odometer || startPos.attributes.totalDistance,
157
- endOdometer: endPos.attributes.odometer || endPos.attributes.totalDistance,
158
- startPositionId: startPos.id,
159
- endPositionId: endPos.id,
160
- startLat: startPos.latitude,
161
- startLon: startPos.longitude,
162
- startTime: startPos.fixTime,
163
- startAddress: startPos.address,
164
- endLat: endPos.latitude,
165
- endLon: endPos.longitude,
166
- endTime: endPos.fixTime,
167
- endAddress: endPos.address,
168
- endTimeIsOut: true,
169
- duration: new Date(endPos.fixTime).getTime() - new Date(startPos.fixTime).getTime(),
170
- driverUniqueId: null,
171
- driverName: null
172
- }
141
+ function calculateTrip (device, route) {
142
+ const startPos = route[0]
143
+ const endPos = route[route.length - 1]
144
+
145
+ return {
146
+ deviceId: device.id,
147
+ deviceName: device.name,
148
+ distance: route.reduce((a, b) => a + b.attributes.distance, 0),
149
+ averageSpeed: Math.round((route.map(p => p.speed).reduce((a, b) => a + b, 0)) / route.length),
150
+ maxSpeed: route.map(p => p.speed).reduce(function (a, b) { return Math.max(a, b) }),
151
+ spentFuel: 0,
152
+ startOdometer: startPos.attributes.odometer || startPos.attributes.totalDistance,
153
+ endOdometer: endPos.attributes.odometer || endPos.attributes.totalDistance,
154
+ startPositionId: startPos.id,
155
+ endPositionId: endPos.id,
156
+ startLat: startPos.latitude,
157
+ startLon: startPos.longitude,
158
+ startTime: startPos.fixTime,
159
+ startAddress: startPos.address,
160
+ endLat: endPos.latitude,
161
+ endLon: endPos.longitude,
162
+ endTime: endPos.fixTime,
163
+ endAddress: endPos.address,
164
+ endTimeIsOut: true,
165
+ duration: new Date(endPos.fixTime).getTime() - new Date(startPos.fixTime).getTime(),
166
+ driverUniqueId: null,
167
+ driverName: null
168
+ }
169
+ }
170
+
171
+ function getTripIdleTime (trip, idleEvents) {
172
+ const tripStartDate = new Date(trip.startTime)
173
+ const tripEndDate = new Date(trip.endTime)
174
+ const idleEventsInsideTrip = idleEvents.filter(i => tripStartDate < new Date(i.position.fixTime) && tripEndDate > new Date(i.position.fixTime))
175
+ return idleEventsInsideTrip.reduce((a, b) => a + b.idleTime, 0)
173
176
  }
174
177
 
175
178
  exports.checkTripsKms = checkTripsKms
@@ -177,3 +180,4 @@ exports.isInsideTimetable = isInsideTimetable
177
180
  exports.isPartialInsideTimetable = isPartialInsideTimetable
178
181
  exports.addNearestPOIs = addNearestPOIs
179
182
  exports.calculateTrip = calculateTrip
183
+ exports.getTripIdleTime = getTripIdleTime