@idm-plugin/vessel 3.4.9 → 3.5.0
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/dist/ais/src/index.d.ts +6 -4
- package/dist/index.js +521 -518
- package/dist/index.umd.cjs +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
var
|
|
2
|
-
var mt = (x, e, t) => e in x ?
|
|
1
|
+
var ht = Object.defineProperty;
|
|
2
|
+
var mt = (x, e, t) => e in x ? ht(x, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : x[e] = t;
|
|
3
3
|
var U = (x, e, t) => (mt(x, typeof e != "symbol" ? e + "" : e, t), t);
|
|
4
4
|
import B from "got";
|
|
5
5
|
import dt from "@log4js-node/log4js-api";
|
|
6
|
-
import
|
|
7
|
-
import { LaneHelper as
|
|
6
|
+
import w from "moment";
|
|
7
|
+
import { LaneHelper as O, LngLatHelper as z } from "@idm-plugin/geo2";
|
|
8
8
|
import { MeteoHelper2 as ft } from "@idm-plugin/meteo2";
|
|
9
9
|
import { Meteo2Assist as ct } from "@idm-plugin/meteo";
|
|
10
10
|
let M;
|
|
@@ -54,7 +54,7 @@ class at {
|
|
|
54
54
|
return { labelCn: t, labelEn: a };
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
|
-
class
|
|
57
|
+
class jt extends at {
|
|
58
58
|
constructor(t, a) {
|
|
59
59
|
super();
|
|
60
60
|
U(this, "clientId");
|
|
@@ -76,12 +76,12 @@ class Et extends at {
|
|
|
76
76
|
expiresIn: n.expires_in,
|
|
77
77
|
scope: n.scope,
|
|
78
78
|
jti: n.jti,
|
|
79
|
-
issuedAt:
|
|
79
|
+
issuedAt: w().utc().format()
|
|
80
80
|
});
|
|
81
81
|
}
|
|
82
82
|
async checkToken(t = {}) {
|
|
83
83
|
var a;
|
|
84
|
-
return (!this.token ||
|
|
84
|
+
return (!this.token || w().diff(w(this.token.issuedAt), "seconds") > (((a = this.token) == null ? void 0 : a.expiresIn) || 0) - 300) && await this.authToken(t), this.token;
|
|
85
85
|
}
|
|
86
86
|
/**
|
|
87
87
|
* 模糊查询
|
|
@@ -102,16 +102,16 @@ class Et extends at {
|
|
|
102
102
|
};
|
|
103
103
|
M == null || M.info("[%s] fetch suggest vessels from: %s - %j", a.requestId, o, n);
|
|
104
104
|
const i = await B.post(o, n).json();
|
|
105
|
-
return i.status !== 200 ? (M == null || M.warn("[%s] fetch suggest vessels failed: %j", a.requestId, { message: i.message, status: i.status, code: i.code }), []) : (i.data || []).map((
|
|
106
|
-
mmsi:
|
|
107
|
-
name:
|
|
108
|
-
nameCn:
|
|
109
|
-
imo: Number.isNaN(
|
|
110
|
-
callSign:
|
|
111
|
-
type:
|
|
112
|
-
flagName:
|
|
105
|
+
return i.status !== 200 ? (M == null || M.warn("[%s] fetch suggest vessels failed: %j", a.requestId, { message: i.message, status: i.status, code: i.code }), []) : (i.data || []).map((u) => ({
|
|
106
|
+
mmsi: u.mmsi,
|
|
107
|
+
name: u.nameEn,
|
|
108
|
+
nameCn: u.nameCn,
|
|
109
|
+
imo: Number.isNaN(u.imo) ? null : Number(u.imo),
|
|
110
|
+
callSign: u.callsign,
|
|
111
|
+
type: u.vesselTypeNameEn,
|
|
112
|
+
flagName: u.flagCtry,
|
|
113
113
|
vendor: "myvessel",
|
|
114
|
-
raw:
|
|
114
|
+
raw: u
|
|
115
115
|
}));
|
|
116
116
|
}
|
|
117
117
|
/**
|
|
@@ -120,11 +120,11 @@ class Et extends at {
|
|
|
120
120
|
* @param options
|
|
121
121
|
*/
|
|
122
122
|
async search(t, a = {}) {
|
|
123
|
-
var
|
|
123
|
+
var l, u;
|
|
124
124
|
await this.checkToken(a);
|
|
125
125
|
const o = /^\d{7}$/.test(t.toString()), n = o ? "https://market.myvessel.cn/sdc/v1/mkt/vessels/detail/imo" : "https://market.myvessel.cn/sdc/v1/mkt/vessels/detail/mmsi", i = o ? { imo: t } : { mmsi: t }, s = {
|
|
126
126
|
headers: {
|
|
127
|
-
Authorization: `${(
|
|
127
|
+
Authorization: `${(l = this.token) == null ? void 0 : l.tokenType} ${(u = this.token) == null ? void 0 : u.accessToken}`
|
|
128
128
|
},
|
|
129
129
|
searchParams: i
|
|
130
130
|
};
|
|
@@ -177,11 +177,11 @@ class Et extends at {
|
|
|
177
177
|
return i.status !== 200 ? (M == null || M.warn("[%s] fetch vessel archive failed: %j", a.requestId, { message: i.message, status: i.status, code: i.code }), {}) : i.data;
|
|
178
178
|
}
|
|
179
179
|
async realTimePosition(t, a = {}) {
|
|
180
|
-
var r,
|
|
180
|
+
var r, l;
|
|
181
181
|
await this.checkToken(a);
|
|
182
182
|
const o = "https://svc.data.myvessel.cn/sdc/v1/vessels/status/location/unit", n = {
|
|
183
183
|
headers: {
|
|
184
|
-
Authorization: `${(r = this.token) == null ? void 0 : r.tokenType} ${(
|
|
184
|
+
Authorization: `${(r = this.token) == null ? void 0 : r.tokenType} ${(l = this.token) == null ? void 0 : l.accessToken}`
|
|
185
185
|
},
|
|
186
186
|
searchParams: { mmsi: t }
|
|
187
187
|
};
|
|
@@ -190,10 +190,10 @@ class Et extends at {
|
|
|
190
190
|
if (i.code)
|
|
191
191
|
return M == null || M.warn("[%s] fetch realtime position failed: %j", a.requestId, { message: i.message, status: i.status, code: i.code }), i;
|
|
192
192
|
const s = i.data;
|
|
193
|
-
for (const
|
|
194
|
-
!isNaN(s[
|
|
193
|
+
for (const u in s)
|
|
194
|
+
!isNaN(s[u]) && Number(s[u]) !== 1 / 0 && (s[u] = Number(s[u]));
|
|
195
195
|
if (s) {
|
|
196
|
-
const
|
|
196
|
+
const u = w(`${s.postime} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
197
197
|
return {
|
|
198
198
|
mmsi: s.mmsi,
|
|
199
199
|
name: s.vesselName || s.aisVesselName,
|
|
@@ -208,9 +208,9 @@ class Et extends at {
|
|
|
208
208
|
cog: s.cog,
|
|
209
209
|
hdg: s.hdg,
|
|
210
210
|
rot: s.rot,
|
|
211
|
-
eta: /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(s.eta) ?
|
|
211
|
+
eta: /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(s.eta) ? w.utc(s.eta).format() : void 0,
|
|
212
212
|
destination: s.dest,
|
|
213
|
-
positionTime:
|
|
213
|
+
positionTime: u.unix(),
|
|
214
214
|
status: s.status,
|
|
215
215
|
labelCn: s.statusNameCn,
|
|
216
216
|
labelEn: s.statusNameEn,
|
|
@@ -223,7 +223,7 @@ class Et extends at {
|
|
|
223
223
|
net: s.net,
|
|
224
224
|
method: "position",
|
|
225
225
|
vendor: "myVessel",
|
|
226
|
-
utc:
|
|
226
|
+
utc: u.utc().format()
|
|
227
227
|
};
|
|
228
228
|
} else
|
|
229
229
|
return {};
|
|
@@ -237,34 +237,38 @@ class Et extends at {
|
|
|
237
237
|
* @param options { requiretId: '请求ID', useAIModel: '启用AI算法', withECA: '是否计算低硫区航行距离', withSpecial: '是否计算穿越的特战区列表和海盗区列表', draught: '最大吃水' }
|
|
238
238
|
*/
|
|
239
239
|
async calculateRoute(t, a, o, n, i, s = {}) {
|
|
240
|
-
var
|
|
241
|
-
const r =
|
|
240
|
+
var k, b, S;
|
|
241
|
+
const r = w();
|
|
242
242
|
await this.checkToken(s);
|
|
243
|
-
const
|
|
243
|
+
const l = "https://svc.data.myvessel.cn/sdc/v1/routes/routing/nodes", u = {
|
|
244
|
+
endPoint: {
|
|
245
|
+
lon: a.lng,
|
|
246
|
+
lat: a.lat
|
|
247
|
+
},
|
|
248
|
+
maxDraught: s.draught || 10,
|
|
249
|
+
useAIModel: s.useAIModel || !1,
|
|
250
|
+
withECA: s.withECA || !1,
|
|
251
|
+
withSpecialRegion: s.withSpecial || !1
|
|
252
|
+
};
|
|
253
|
+
t.code && (u.startPortCode = t.code), t.lng !== void 0 && t.lat !== void 0 && (u.startPoint = {
|
|
254
|
+
lon: t.lng,
|
|
255
|
+
lat: t.lat
|
|
256
|
+
}), a.code && (u.endPortCode = a.code), a.lng !== void 0 && a.lat !== void 0 && (u.endPoint = {
|
|
257
|
+
lon: a.lng,
|
|
258
|
+
lat: a.lat
|
|
259
|
+
}), o != null && o.length && (u.crossMonthList = o), n != null && n.length && (u.excludeNodes = n), i != null && i.length && (u.excludeSeaAreas = i);
|
|
260
|
+
const d = {
|
|
244
261
|
headers: {
|
|
245
|
-
Authorization: `${(
|
|
262
|
+
Authorization: `${(k = this.token) == null ? void 0 : k.tokenType} ${(b = this.token) == null ? void 0 : b.accessToken}`
|
|
246
263
|
},
|
|
247
|
-
json:
|
|
248
|
-
startPoint: {
|
|
249
|
-
lon: t.lng,
|
|
250
|
-
lat: t.lat
|
|
251
|
-
},
|
|
252
|
-
endPoint: {
|
|
253
|
-
lon: a.lng,
|
|
254
|
-
lat: a.lat
|
|
255
|
-
},
|
|
256
|
-
maxDraught: s.draught || 10,
|
|
257
|
-
useAIModel: s.useAIModel || !1,
|
|
258
|
-
withECA: s.withECA || !1,
|
|
259
|
-
withSpecialRegion: s.withSpecial || !1
|
|
260
|
-
}
|
|
264
|
+
json: u
|
|
261
265
|
};
|
|
262
|
-
|
|
263
|
-
const
|
|
264
|
-
if (
|
|
265
|
-
return M == null || M.warn("[%s] fetch route failed: %j", s.requestId, { message:
|
|
266
|
+
M == null || M.info("[%s] fetch route from: %s - %j", s.requestId, l, d);
|
|
267
|
+
const y = await B.post(l, d).json();
|
|
268
|
+
if (y.status !== 200)
|
|
269
|
+
return M == null || M.warn("[%s] fetch route failed: %j", s.requestId, { message: y.message, status: y.status, code: y.code }), {};
|
|
266
270
|
{
|
|
267
|
-
const
|
|
271
|
+
const C = {
|
|
268
272
|
status: "Success",
|
|
269
273
|
nodes: [],
|
|
270
274
|
seas: [],
|
|
@@ -273,52 +277,52 @@ class Et extends at {
|
|
|
273
277
|
route: [],
|
|
274
278
|
distance: 0,
|
|
275
279
|
memo: ""
|
|
276
|
-
}, { nodes:
|
|
277
|
-
|
|
278
|
-
code:
|
|
279
|
-
nameEn:
|
|
280
|
-
nameCn:
|
|
280
|
+
}, { nodes: p, seas: v, tracks: m, specialRegions: c } = y.data;
|
|
281
|
+
C.nodes = p == null ? void 0 : p.map((g) => ({
|
|
282
|
+
code: g.nodeCode,
|
|
283
|
+
nameEn: g.nameEn,
|
|
284
|
+
nameCn: g.nameCn,
|
|
281
285
|
// 中心
|
|
282
286
|
center: {
|
|
283
|
-
lat: Math.round(
|
|
284
|
-
lng: Math.round(
|
|
287
|
+
lat: Math.round(g.lat * 1e6) / 1e6,
|
|
288
|
+
lng: Math.round(g.lon * 1e6) / 1e6
|
|
285
289
|
},
|
|
286
290
|
// 起点
|
|
287
291
|
start: {
|
|
288
|
-
lat: Math.round(
|
|
289
|
-
lng: Math.round(
|
|
292
|
+
lat: Math.round(g.startLat * 1e6) / 1e6,
|
|
293
|
+
lng: Math.round(g.startLon * 1e6) / 1e6
|
|
290
294
|
},
|
|
291
295
|
// 终点
|
|
292
296
|
end: {
|
|
293
|
-
lat: Math.round(
|
|
294
|
-
lng: Math.round(
|
|
297
|
+
lat: Math.round(g.endLat * 1e6) / 1e6,
|
|
298
|
+
lng: Math.round(g.endLat * 1e6) / 1e6
|
|
295
299
|
},
|
|
296
300
|
// 是否为不可避开关键节点
|
|
297
|
-
isKey:
|
|
301
|
+
isKey: g.isKeyNode,
|
|
298
302
|
// 重要枢纽节点
|
|
299
|
-
isHub:
|
|
300
|
-
})),
|
|
301
|
-
code:
|
|
302
|
-
nameEn:
|
|
303
|
-
nameCn:
|
|
303
|
+
isHub: g.isHubNode
|
|
304
|
+
})), C.seas = v == null ? void 0 : v.map((g) => ({
|
|
305
|
+
code: g.mrgidSea,
|
|
306
|
+
nameEn: g.nameEn,
|
|
307
|
+
nameCn: g.nameCn,
|
|
304
308
|
center: {
|
|
305
|
-
lat: Math.round(
|
|
306
|
-
lng: Math.round(
|
|
309
|
+
lat: Math.round(g.centerLat * 1e6) / 1e6,
|
|
310
|
+
lng: Math.round(g.centerLon * 1e6) / 1e6
|
|
307
311
|
},
|
|
308
312
|
min: {
|
|
309
|
-
lat: Math.round(
|
|
310
|
-
lng: Math.round(
|
|
313
|
+
lat: Math.round(g.minLat * 1e6) / 1e6,
|
|
314
|
+
lng: Math.round(g.minLon * 1e6) / 1e6
|
|
311
315
|
},
|
|
312
316
|
max: {
|
|
313
|
-
lat: Math.round(
|
|
314
|
-
lng: Math.round(
|
|
317
|
+
lat: Math.round(g.maxLat * 1e6) / 1e6,
|
|
318
|
+
lng: Math.round(g.maxLon * 1e6) / 1e6
|
|
315
319
|
},
|
|
316
|
-
level:
|
|
317
|
-
})),
|
|
318
|
-
|
|
319
|
-
type:
|
|
320
|
-
distance:
|
|
321
|
-
rows:
|
|
320
|
+
level: g.mapLevel
|
|
321
|
+
})), c == null || c.map((g) => {
|
|
322
|
+
g.regionLength && C.regions.push({
|
|
323
|
+
type: g.regionType,
|
|
324
|
+
distance: g.regionLength,
|
|
325
|
+
rows: g.regions.map((I) => ({
|
|
322
326
|
code: I.regionCode,
|
|
323
327
|
nameCn: I.nameCn,
|
|
324
328
|
nameEn: I.nameEn,
|
|
@@ -326,26 +330,26 @@ class Et extends at {
|
|
|
326
330
|
distance: I.length
|
|
327
331
|
}))
|
|
328
332
|
});
|
|
329
|
-
}),
|
|
330
|
-
lat: Math.round(
|
|
331
|
-
lng: Math.round(
|
|
332
|
-
})), (
|
|
333
|
-
const
|
|
334
|
-
return
|
|
333
|
+
}), C.waypoints = m == null ? void 0 : m.map((g) => ({
|
|
334
|
+
lat: Math.round(g.lat * 1e5) / 1e5,
|
|
335
|
+
lng: Math.round(g.lon * 1e5) / 1e5
|
|
336
|
+
})), (S = C.waypoints) != null && S.length && (C.waypoints = O.simplifyCoordinates(C.waypoints), C.route = O.divideAccordingToLng(C.waypoints), C.distance = O.calculateRouteDistance(C.route));
|
|
337
|
+
const h = w().diff(r, "second");
|
|
338
|
+
return C.memo = `time cost: ${h}s`, M.info("[%s] calculate route cost: %d seconds", s.requestId, h), C;
|
|
335
339
|
}
|
|
336
340
|
}
|
|
337
341
|
async trajectory(t, a, o, n, i = !0, s = {}) {
|
|
338
342
|
await this.checkToken(s);
|
|
339
|
-
const r = await this.realTimePosition(t, s),
|
|
340
|
-
for (;
|
|
341
|
-
await this.trajectoryIn30Day(t,
|
|
342
|
-
return await this.trajectoryIn30Day(t,
|
|
343
|
+
const r = await this.realTimePosition(t, s), l = w(a), u = w(o), d = [];
|
|
344
|
+
for (; u.diff(l, "day", !0) > 30; )
|
|
345
|
+
await this.trajectoryIn30Day(t, l, l.clone().add(30, "day"), r, n, d, s), l.add(30, "day");
|
|
346
|
+
return await this.trajectoryIn30Day(t, l, u, r, n, d, s), d;
|
|
343
347
|
}
|
|
344
348
|
async trajectoryIn30Day(t, a, o, n, i, s, r = {}) {
|
|
345
|
-
var
|
|
346
|
-
const
|
|
349
|
+
var b, S, C, p, v;
|
|
350
|
+
const l = "https://svc.data.myvessel.cn/sdc/v1/vessels/status/track", u = {
|
|
347
351
|
headers: {
|
|
348
|
-
Authorization: `${(
|
|
352
|
+
Authorization: `${(b = this.token) == null ? void 0 : b.tokenType} ${(S = this.token) == null ? void 0 : S.accessToken}`
|
|
349
353
|
},
|
|
350
354
|
json: {
|
|
351
355
|
mmsi: t,
|
|
@@ -353,35 +357,35 @@ class Et extends at {
|
|
|
353
357
|
endTime: o.utcOffset(8).format("YYYY-MM-DD HH:mm:ss")
|
|
354
358
|
}
|
|
355
359
|
};
|
|
356
|
-
M == null || M.info("[%s] fetch trajectory from: %s - %j", r.requestId,
|
|
357
|
-
const d = await B.post(
|
|
360
|
+
M == null || M.info("[%s] fetch trajectory from: %s - %j", r.requestId, l, u);
|
|
361
|
+
const d = await B.post(l, u).json();
|
|
358
362
|
if (d.code)
|
|
359
|
-
return M == null || M.warn("[%s] fetch trajectory failed: %j", r.requestId,
|
|
363
|
+
return M == null || M.warn("[%s] fetch trajectory failed: %j", r.requestId, l, { message: d.message, status: d.status, code: d.code }), d;
|
|
360
364
|
let y = -1;
|
|
361
|
-
const
|
|
362
|
-
return (
|
|
363
|
-
for (const P in
|
|
364
|
-
!isNaN(
|
|
365
|
-
const
|
|
366
|
-
mmsi:
|
|
365
|
+
const k = w(`${(p = (C = d.data) == null ? void 0 : C[0]) == null ? void 0 : p.postime} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
366
|
+
return (v = d.data) == null || v.forEach((m) => {
|
|
367
|
+
for (const P in m)
|
|
368
|
+
!isNaN(m[P]) && Number(m[P]) !== 1 / 0 && (m[P] = Number(m[P]));
|
|
369
|
+
const c = w(`${m.postime} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00"), f = m.status, { labelCn: h, labelEn: g } = this.parseStatus(f), I = {
|
|
370
|
+
mmsi: m.mmsi,
|
|
367
371
|
imo: n == null ? void 0 : n.imo,
|
|
368
|
-
lat:
|
|
369
|
-
lng:
|
|
370
|
-
sog:
|
|
371
|
-
cog:
|
|
372
|
-
hdg:
|
|
373
|
-
draught:
|
|
374
|
-
status:
|
|
375
|
-
eta: /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(
|
|
376
|
-
destination:
|
|
377
|
-
positionTime:
|
|
378
|
-
labelCn:
|
|
379
|
-
labelEn:
|
|
372
|
+
lat: m.lat,
|
|
373
|
+
lng: m.lon,
|
|
374
|
+
sog: m.sog,
|
|
375
|
+
cog: m.cog,
|
|
376
|
+
hdg: m.hdg,
|
|
377
|
+
draught: m.draught,
|
|
378
|
+
status: f,
|
|
379
|
+
eta: /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(m.eta) ? w(`${m.eta} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00").utc().format() : void 0,
|
|
380
|
+
destination: m.dest,
|
|
381
|
+
positionTime: c.unix(),
|
|
382
|
+
labelCn: h,
|
|
383
|
+
labelEn: g,
|
|
380
384
|
method: "trajectory",
|
|
381
385
|
vendor: "myVessel",
|
|
382
|
-
utc:
|
|
383
|
-
}, F = Math.floor(
|
|
384
|
-
F !== y && (y = F, s.push(
|
|
386
|
+
utc: c.utc().format()
|
|
387
|
+
}, F = Math.floor(c.diff(k, "minute", !0) / (i || 1));
|
|
388
|
+
F !== y && (y = F, s.push(I));
|
|
385
389
|
}), s;
|
|
386
390
|
}
|
|
387
391
|
}
|
|
@@ -402,10 +406,10 @@ class Ft extends at {
|
|
|
402
406
|
const s = i == null ? void 0 : i.list;
|
|
403
407
|
if (!s)
|
|
404
408
|
return M == null || M.warn("[%s] fetch realtime position failed: %j", a.requestId, o, i), i;
|
|
405
|
-
for (const
|
|
406
|
-
!isNaN(s[
|
|
409
|
+
for (const k in s)
|
|
410
|
+
!isNaN(s[k]) && Number(s[k]) !== 1 / 0 && (s[k] = Number(s[k]));
|
|
407
411
|
s.status = s.sp > 3 ? 0 : 1;
|
|
408
|
-
const r = s.status, { labelCn:
|
|
412
|
+
const r = s.status, { labelCn: l, labelEn: u } = this.parseStatus(r), d = w(`${s.ti} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
409
413
|
return {
|
|
410
414
|
mmsi: s.m,
|
|
411
415
|
name: s.n,
|
|
@@ -420,7 +424,7 @@ class Ft extends at {
|
|
|
420
424
|
cog: s.co,
|
|
421
425
|
hdg: s.h,
|
|
422
426
|
rot: isNaN(s.rot) ? 0 : s.rot,
|
|
423
|
-
eta: /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(s.eta) ?
|
|
427
|
+
eta: /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(s.eta) ? w.utc(s.eta).format() : void 0,
|
|
424
428
|
destination: s.destination,
|
|
425
429
|
vesselType: s.type,
|
|
426
430
|
dwt: s.dwt,
|
|
@@ -429,8 +433,8 @@ class Ft extends at {
|
|
|
429
433
|
positionTime: d.unix(),
|
|
430
434
|
utc: d.utc().format(),
|
|
431
435
|
status: r,
|
|
432
|
-
labelCn:
|
|
433
|
-
labelEn:
|
|
436
|
+
labelCn: l,
|
|
437
|
+
labelEn: u,
|
|
434
438
|
method: "position",
|
|
435
439
|
vendor: "hifleet"
|
|
436
440
|
};
|
|
@@ -484,57 +488,57 @@ class Ft extends at {
|
|
|
484
488
|
imo: !r.imo || isNaN(r.imo) ? null : Number(r.imo),
|
|
485
489
|
score: r._score
|
|
486
490
|
});
|
|
487
|
-
return s.sort((r,
|
|
491
|
+
return s.sort((r, l) => l.score - r.score), s;
|
|
488
492
|
}
|
|
489
493
|
async trajectory(t, a, o, n, i = !0, s = {}) {
|
|
490
|
-
var
|
|
494
|
+
var m, c, f;
|
|
491
495
|
const r = await this.realTimePosition(t, s);
|
|
492
|
-
let
|
|
493
|
-
const
|
|
496
|
+
let l = w(a);
|
|
497
|
+
const u = w(o), d = w();
|
|
494
498
|
if (i) {
|
|
495
|
-
let
|
|
496
|
-
|
|
499
|
+
let h = u.diff(l, "d", !0);
|
|
500
|
+
h < 0 ? l = u.clone().subtract(40, "d") : h < 30 ? l.subtract(10, "d") : h < 60 ? l.subtract(5, "d") : l = u.clone().subtract(80, "d"), h = d.diff(u, "d", !0), u.add(h > 10 ? 240 : h * 24, "h");
|
|
497
501
|
}
|
|
498
502
|
const y = {
|
|
499
503
|
searchParams: {
|
|
500
|
-
endtime:
|
|
501
|
-
starttime:
|
|
504
|
+
endtime: u.utcOffset("+8:00").format("YYYY-MM-DD HH:mm:ss"),
|
|
505
|
+
starttime: l.utcOffset("+8:00").format("YYYY-MM-DD HH:mm:ss"),
|
|
502
506
|
mmsi: t,
|
|
503
507
|
usertoken: this.token
|
|
504
508
|
}
|
|
505
|
-
},
|
|
506
|
-
M == null || M.info("[%s] fetch trajectory from: %s - %j", s.requestId,
|
|
507
|
-
let
|
|
508
|
-
|
|
509
|
-
const
|
|
510
|
-
let
|
|
511
|
-
const
|
|
512
|
-
for (const
|
|
513
|
-
for (const H in
|
|
514
|
-
!isNaN(
|
|
515
|
-
const
|
|
516
|
-
|
|
517
|
-
const { labelEn:
|
|
518
|
-
mmsi:
|
|
519
|
-
name:
|
|
509
|
+
}, k = "https://api.hifleet.com/position/trajectory/nocompressed/withstatic/token", b = await B.get(k, y).json();
|
|
510
|
+
M == null || M.info("[%s] fetch trajectory from: %s - %j", s.requestId, k, y);
|
|
511
|
+
let S;
|
|
512
|
+
b && (S = ((c = (m = b.ships) == null ? void 0 : m.offors) == null ? void 0 : c.ship) || [], S.length || M == null || M.warn("[%s] fetch trajectory failed: %j", s.requestId, b));
|
|
513
|
+
const C = [];
|
|
514
|
+
let p = -1;
|
|
515
|
+
const v = w(`${(f = S == null ? void 0 : S[0]) == null ? void 0 : f.ti} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
516
|
+
for (const h of S) {
|
|
517
|
+
for (const H in h)
|
|
518
|
+
!isNaN(h[H]) && Number(h[H]) !== 1 / 0 && (h[H] = Number(h[H]));
|
|
519
|
+
const g = w(`${h.ti} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
520
|
+
h.status = h.sp > 4 ? 0 : 1;
|
|
521
|
+
const { labelEn: I, labelCn: F } = this.parseStatus(h.status), P = {
|
|
522
|
+
mmsi: h.m,
|
|
523
|
+
name: h.n,
|
|
520
524
|
imo: r == null ? void 0 : r.imo,
|
|
521
|
-
lat:
|
|
522
|
-
lng:
|
|
523
|
-
draught:
|
|
524
|
-
sog:
|
|
525
|
-
cog:
|
|
526
|
-
hdg:
|
|
527
|
-
positionTime:
|
|
528
|
-
utc:
|
|
529
|
-
status:
|
|
525
|
+
lat: h.la,
|
|
526
|
+
lng: h.lo,
|
|
527
|
+
draught: h.draught,
|
|
528
|
+
sog: h.sp,
|
|
529
|
+
cog: h.co,
|
|
530
|
+
hdg: h.hdg,
|
|
531
|
+
positionTime: g.unix(),
|
|
532
|
+
utc: g.utc().format(),
|
|
533
|
+
status: h.status,
|
|
530
534
|
labelCn: F,
|
|
531
|
-
labelEn:
|
|
535
|
+
labelEn: I,
|
|
532
536
|
method: "trajectory",
|
|
533
537
|
vendor: "hifleet"
|
|
534
|
-
}, D = Math.floor(
|
|
535
|
-
D !==
|
|
538
|
+
}, D = Math.floor(g.diff(v, "minute", !0) / (n || 1));
|
|
539
|
+
D !== p && (p = D, C.push(P));
|
|
536
540
|
}
|
|
537
|
-
return
|
|
541
|
+
return C;
|
|
538
542
|
}
|
|
539
543
|
}
|
|
540
544
|
class Nt extends at {
|
|
@@ -556,7 +560,7 @@ class Nt extends at {
|
|
|
556
560
|
const s = i.data[0];
|
|
557
561
|
for (const y in s)
|
|
558
562
|
!isNaN(s[y]) && Number(s[y]) !== 1 / 0 && (s[y] = Number(s[y]));
|
|
559
|
-
const { labelCn: r, labelEn:
|
|
563
|
+
const { labelCn: r, labelEn: l } = await this.parseStatus(s.navistat), u = w.unix(s.lasttime);
|
|
560
564
|
return {
|
|
561
565
|
mmsi: s.ShipID,
|
|
562
566
|
name: s.name,
|
|
@@ -572,46 +576,46 @@ class Nt extends at {
|
|
|
572
576
|
hdg: Math.round(s.hdg / 100 * 100) / 100,
|
|
573
577
|
rot: Math.round(s.rot / 100 * 100) / 100,
|
|
574
578
|
positionTime: s.lasttime,
|
|
575
|
-
utc:
|
|
579
|
+
utc: u.utc().format(),
|
|
576
580
|
status: s.navistat,
|
|
577
|
-
labelEn:
|
|
581
|
+
labelEn: l,
|
|
578
582
|
labelCn: r,
|
|
579
583
|
method: "position",
|
|
580
584
|
vendor: "shipxy"
|
|
581
585
|
};
|
|
582
586
|
}
|
|
583
587
|
async trajectory(t, a, o, n, i = !0, s = {}) {
|
|
584
|
-
var
|
|
585
|
-
const r = await this.realTimePosition(t, s),
|
|
588
|
+
var v;
|
|
589
|
+
const r = await this.realTimePosition(t, s), l = w(a), u = w(o), d = "https://api.shipxy.com/apicall/GetShipTrack", y = {
|
|
586
590
|
searchParams: {
|
|
587
591
|
id: t,
|
|
588
592
|
k: this.token,
|
|
589
593
|
enc: 1,
|
|
590
594
|
cut: 0,
|
|
591
|
-
btm:
|
|
592
|
-
etm:
|
|
595
|
+
btm: l.unix(),
|
|
596
|
+
etm: u.unix()
|
|
593
597
|
}
|
|
594
|
-
},
|
|
595
|
-
if (M == null || M.info("[%s] fetch trajectory from: %s - %j", s.requestId, d, y), (
|
|
596
|
-
return
|
|
597
|
-
const
|
|
598
|
-
let
|
|
599
|
-
for (const
|
|
600
|
-
const
|
|
598
|
+
}, k = await B.get(d, y).json();
|
|
599
|
+
if (M == null || M.info("[%s] fetch trajectory from: %s - %j", s.requestId, d, y), (k == null ? void 0 : k.status) !== 0)
|
|
600
|
+
return k;
|
|
601
|
+
const b = k == null ? void 0 : k.points, S = [], C = w.unix((v = b[0]) == null ? void 0 : v.utc);
|
|
602
|
+
let p = -1;
|
|
603
|
+
for (const m of b) {
|
|
604
|
+
const c = w.unix(m.utc), f = {
|
|
601
605
|
imo: r == null ? void 0 : r.imo,
|
|
602
606
|
mmsi: t,
|
|
603
|
-
sog: Math.round(
|
|
604
|
-
cog: Math.round(
|
|
605
|
-
lat: Math.round(
|
|
606
|
-
lng: Math.round(
|
|
607
|
-
positionTime:
|
|
608
|
-
utc:
|
|
607
|
+
sog: Math.round(m.sog * 3600 / 1e3 / 1852 * 100) / 100,
|
|
608
|
+
cog: Math.round(m.cog / 100 * 100) / 100,
|
|
609
|
+
lat: Math.round(m.lat / 1e6 * 1e5) / 1e5,
|
|
610
|
+
lng: Math.round(m.lon / 1e6 * 1e5) / 1e5,
|
|
611
|
+
positionTime: c.unix(),
|
|
612
|
+
utc: c.utc().format(),
|
|
609
613
|
method: "trajectory",
|
|
610
614
|
vendor: "shipxy"
|
|
611
|
-
},
|
|
612
|
-
|
|
615
|
+
}, h = Math.floor(c.diff(C, "minute", !0) / (n || 1));
|
|
616
|
+
h !== p && (p = h, S.push(f));
|
|
613
617
|
}
|
|
614
|
-
return
|
|
618
|
+
return S;
|
|
615
619
|
}
|
|
616
620
|
}
|
|
617
621
|
class xt extends at {
|
|
@@ -664,37 +668,37 @@ class xt extends at {
|
|
|
664
668
|
}
|
|
665
669
|
}, s = "https://api3.myships.com/sp/ships/position/latest", r = await B.post(s, i).json();
|
|
666
670
|
M == null || M.info("[%s] fetch realtime position from: %s - %j", a.requestId, s, i);
|
|
667
|
-
const
|
|
668
|
-
for (const
|
|
669
|
-
!isNaN(
|
|
670
|
-
const { labelCn:
|
|
671
|
+
const l = r.data[0];
|
|
672
|
+
for (const b in l)
|
|
673
|
+
!isNaN(l[b]) && Number(l[b]) !== 1 / 0 && (l[b] = Number(l[b]));
|
|
674
|
+
const { labelCn: u, labelEn: d } = await this.parseStatus(l.aisNavStatus), y = w.unix(l.posTime);
|
|
671
675
|
return {
|
|
672
676
|
...n,
|
|
673
677
|
mmsi: t,
|
|
674
|
-
lat: Math.round(
|
|
675
|
-
lng: Math.round(
|
|
676
|
-
sog: Math.round(
|
|
677
|
-
cog: Math.round(
|
|
678
|
-
hdg: Math.round(
|
|
679
|
-
rot: Math.round(
|
|
680
|
-
positionTime:
|
|
678
|
+
lat: Math.round(l.lat / 1e4 / 60 * 1e5) / 1e5,
|
|
679
|
+
lng: Math.round(l.lon / 1e4 / 60 * 1e5) / 1e5,
|
|
680
|
+
sog: Math.round(l.sog / 10 * 100) / 100,
|
|
681
|
+
cog: Math.round(l.cog / 10 * 100) / 100,
|
|
682
|
+
hdg: Math.round(l.heading * 100) / 100,
|
|
683
|
+
rot: Math.round(l.rot * 100) / 100,
|
|
684
|
+
positionTime: l.posTime,
|
|
681
685
|
utc: y.utc().format(),
|
|
682
|
-
status:
|
|
686
|
+
status: l.aisNavStatus,
|
|
683
687
|
labelEn: d,
|
|
684
|
-
labelCn:
|
|
688
|
+
labelCn: u,
|
|
685
689
|
method: "position",
|
|
686
690
|
vendor: "myship"
|
|
687
691
|
};
|
|
688
692
|
}
|
|
689
693
|
async trajectory(t, a, o, n, i = !0, s = {}) {
|
|
690
|
-
const r =
|
|
691
|
-
for (;
|
|
692
|
-
await this.trajectoryIn30Day(
|
|
693
|
-
return await this.trajectoryIn30Day(
|
|
694
|
+
const r = w(a), l = w(o), u = await this.getShipId(t), d = await this.getShipInfo(u), y = [];
|
|
695
|
+
for (; l.diff(r, "day", !0) > 30; )
|
|
696
|
+
await this.trajectoryIn30Day(u, r.unix(), r.add(30, "day").unix(), d, t, n, y);
|
|
697
|
+
return await this.trajectoryIn30Day(u, r.unix(), l.unix(), d, t, n, y), y;
|
|
694
698
|
}
|
|
695
|
-
async trajectoryIn30Day(t, a, o, n, i, s, r,
|
|
696
|
-
var
|
|
697
|
-
const
|
|
699
|
+
async trajectoryIn30Day(t, a, o, n, i, s, r, l = {}) {
|
|
700
|
+
var C;
|
|
701
|
+
const u = {
|
|
698
702
|
headers: {
|
|
699
703
|
appKey: this.token
|
|
700
704
|
},
|
|
@@ -703,30 +707,30 @@ class xt extends at {
|
|
|
703
707
|
startTime: a,
|
|
704
708
|
endTime: o
|
|
705
709
|
}
|
|
706
|
-
}, d = "https://api3.myships.com/sp/ships/position/history", y = await B.post(d,
|
|
707
|
-
if (M == null || M.info("[%s] fetch trajectory from: %s - %j",
|
|
708
|
-
return M == null || M.warn("[%s] invoke myship trajectory failed: %j",
|
|
709
|
-
const
|
|
710
|
-
for (const
|
|
711
|
-
!isNaN(
|
|
712
|
-
const
|
|
713
|
-
let
|
|
714
|
-
for (const
|
|
715
|
-
const
|
|
710
|
+
}, d = "https://api3.myships.com/sp/ships/position/history", y = await B.post(d, u).json();
|
|
711
|
+
if (M == null || M.info("[%s] fetch trajectory from: %s - %j", l.requestId, d, u), y.code !== "0")
|
|
712
|
+
return M == null || M.warn("[%s] invoke myship trajectory failed: %j", l.requestId, y), y;
|
|
713
|
+
const k = y.data;
|
|
714
|
+
for (const p in k)
|
|
715
|
+
!isNaN(k[p]) && Number(k[p]) !== 1 / 0 && (k[p] = Number(k[p]));
|
|
716
|
+
const b = w.unix((C = k[0]) == null ? void 0 : C.posTime);
|
|
717
|
+
let S = -1;
|
|
718
|
+
for (const p of k) {
|
|
719
|
+
const v = w.unix(p.posTime), m = {
|
|
716
720
|
imo: n == null ? void 0 : n.imo,
|
|
717
721
|
mmsi: i,
|
|
718
|
-
lat: Math.round(
|
|
719
|
-
lng: Math.round(
|
|
720
|
-
sog: Math.round(
|
|
721
|
-
cog: Math.round(
|
|
722
|
-
hdg: Math.round(
|
|
723
|
-
rot: Math.round(
|
|
724
|
-
positionTime:
|
|
725
|
-
utc:
|
|
722
|
+
lat: Math.round(p.lat / 1e4 / 60 * 1e5) / 1e5,
|
|
723
|
+
lng: Math.round(p.lon / 1e4 / 60 * 1e5) / 1e5,
|
|
724
|
+
sog: Math.round(p.sog / 10 * 100) / 100,
|
|
725
|
+
cog: Math.round(p.cog / 10 * 100) / 100,
|
|
726
|
+
hdg: Math.round(p.heading * 100) / 100,
|
|
727
|
+
rot: Math.round(p.rot * 100) / 100,
|
|
728
|
+
positionTime: v.unix(),
|
|
729
|
+
utc: v.utc().format(),
|
|
726
730
|
method: "trajectory",
|
|
727
731
|
vendor: "myship"
|
|
728
|
-
},
|
|
729
|
-
|
|
732
|
+
}, c = Math.floor(v.diff(b, "minute", !0) / (s || 1));
|
|
733
|
+
c !== S && (S = c, r.push(m));
|
|
730
734
|
}
|
|
731
735
|
return r;
|
|
732
736
|
}
|
|
@@ -748,20 +752,20 @@ class Mt {
|
|
|
748
752
|
* @param options
|
|
749
753
|
*/
|
|
750
754
|
parsePrinciple(e, t = {}) {
|
|
751
|
-
var s, r,
|
|
755
|
+
var s, r, l;
|
|
752
756
|
J == null || J.debug("[%s] parse rule: %s", t.requestId, e);
|
|
753
757
|
const a = new RegExp("(?<=\\[)(.+)(?=])", "g"), o = e.match(a) ? (s = e.match(a)) == null ? void 0 : s[0] : void 0, n = o == null ? void 0 : o.split(";");
|
|
754
758
|
if (!n)
|
|
755
759
|
return;
|
|
756
760
|
const i = {};
|
|
757
|
-
for (let
|
|
758
|
-
const d = (
|
|
759
|
-
if (
|
|
761
|
+
for (let u = 0; u < (n == null ? void 0 : n.length); u++) {
|
|
762
|
+
const d = (l = (r = n[u].match(a)) == null ? void 0 : r[0]) == null ? void 0 : l.split("],");
|
|
763
|
+
if (u === 0 && !d)
|
|
760
764
|
i.scope = n[0];
|
|
761
765
|
else if (d)
|
|
762
|
-
for (let y = 0,
|
|
763
|
-
const
|
|
764
|
-
|
|
766
|
+
for (let y = 0, k = d.length; y < k; y++) {
|
|
767
|
+
const b = this.parseRule(d[y]);
|
|
768
|
+
b && (i[b.level] ? b.key ? i[b.level][b == null ? void 0 : b.key] = b : i[b.level] = b : b.key ? i[b.level] = { [b == null ? void 0 : b.key]: b } : i[b.level] = b);
|
|
765
769
|
}
|
|
766
770
|
}
|
|
767
771
|
return i;
|
|
@@ -794,20 +798,20 @@ class Mt {
|
|
|
794
798
|
* @param options
|
|
795
799
|
*/
|
|
796
800
|
checkWeather(e, t, a = {}) {
|
|
797
|
-
var
|
|
801
|
+
var b, S, C, p, v, m, c, f, h, g, I, F, P, D, H;
|
|
798
802
|
let o = 0, n = 0, i = 0, s = 0;
|
|
799
|
-
const r = Math.round(((
|
|
800
|
-
for (let
|
|
801
|
-
const N = e[
|
|
802
|
-
s = K > s ? K : s, J == null || J.debug("[%s] check sig.wave: %j", a.requestId, { ...
|
|
803
|
+
const r = Math.round(((S = (b = t == null ? void 0 : t.SEVERE) == null ? void 0 : b.sigWave) == null ? void 0 : S.number) * 1.6 * 100) / 100, l = (p = (C = t == null ? void 0 : t.SEVERE) == null ? void 0 : C.sigWave) == null ? void 0 : p.number, u = (m = (v = t == null ? void 0 : t.HEAVY) == null ? void 0 : v.sigWave) == null ? void 0 : m.number, d = Math.round((((f = (c = t == null ? void 0 : t.SEVERE) == null ? void 0 : c.wind) == null ? void 0 : f.number) + 2) * 100) / 100, y = (g = (h = t == null ? void 0 : t.SEVERE) == null ? void 0 : h.wind) == null ? void 0 : g.number, k = (F = (I = t == null ? void 0 : t.HEAVY) == null ? void 0 : I.wind) == null ? void 0 : F.number;
|
|
804
|
+
for (let j = 0; j < (e == null ? void 0 : e.length); j++) {
|
|
805
|
+
const N = e[j], R = (D = (P = N == null ? void 0 : N.meteo) == null ? void 0 : P.wave) == null ? void 0 : D.sig, W = (H = N == null ? void 0 : N.meteo) == null ? void 0 : H.wind, K = j ? w(N.eta).diff(w(e[j - 1].eta), "hour", !0) : 0;
|
|
806
|
+
s = K > s ? K : s, J == null || J.debug("[%s] check sig.wave: %j", a.requestId, { ...R, dgThd4Wv: r, svThd4Wv: l, hvThd4Wv: u }), (R == null ? void 0 : R.height) >= r ? N.isDangerous = !0 : (R == null ? void 0 : R.height) >= l ? N.isSevere = !0 : (R == null ? void 0 : R.height) >= u && (N.isHeavy = !0), J == null || J.debug("[%s] check wind: %j", a.requestId, { ...W, dgThd4Wd: d, svThd4Wd: y, hvThd4Wd: k }), (W == null ? void 0 : W.scale) >= d ? (N.isDangerous = !0, delete N.isSevere, delete N.isHeavy) : (W == null ? void 0 : W.scale) > y ? (N.isDangerous || (N.isSevere = !0), delete N.isHeavy) : (W == null ? void 0 : W.scale) === k && !N.isDangerous && !N.isSevere && (N.isHeavy = !0), o += N.isDangerous ? K : 0, n += N.isSevere ? K : 0, i += N.isHeavy ? K : 0;
|
|
803
807
|
}
|
|
804
|
-
return o = Math.round(o * 100) / 100, n = Math.round(n * 100) / 100, i = Math.round(i * 100) / 100, s = Math.round(s), { sample: e, dangerous: o, severe: n, heavy: i, step: s < 3 ? 3 : s, wind: { dgThd4Wd: d, svThd4Wd: y, hvThd4Wd:
|
|
808
|
+
return o = Math.round(o * 100) / 100, n = Math.round(n * 100) / 100, i = Math.round(i * 100) / 100, s = Math.round(s), { sample: e, dangerous: o, severe: n, heavy: i, step: s < 3 ? 3 : s, wind: { dgThd4Wd: d, svThd4Wd: y, hvThd4Wd: k }, sig: { dgThd4Wv: r, svThd4Wv: l, hvThd4Wv: u } };
|
|
805
809
|
}
|
|
806
810
|
}
|
|
807
811
|
const Dt = new Mt();
|
|
808
|
-
let
|
|
812
|
+
let T;
|
|
809
813
|
try {
|
|
810
|
-
|
|
814
|
+
T = dt.getLogger("vessel");
|
|
811
815
|
} catch {
|
|
812
816
|
} finally {
|
|
813
817
|
}
|
|
@@ -927,9 +931,9 @@ class Y {
|
|
|
927
931
|
*/
|
|
928
932
|
static assembleProperties(e, t, a, o) {
|
|
929
933
|
var y;
|
|
930
|
-
const n = e.lbp ?? e.length ?? e.lengthOverall ?? 198.9642, i = e.draught ?? 8, s = e.breadthMoulded ?? e.breadth ?? e.breadthExtreme ?? 32.4572, r = e.deadweight ?? 67035.7773,
|
|
934
|
+
const n = e.lbp ?? e.length ?? e.lengthOverall ?? 198.9642, i = e.draught ?? 8, s = e.breadthMoulded ?? e.breadth ?? e.breadthExtreme ?? 32.4572, r = e.deadweight ?? 67035.7773, l = ((y = e == null ? void 0 : e.type) == null ? void 0 : y.toLowerCase()) || "common";
|
|
931
935
|
return {
|
|
932
|
-
tag:
|
|
936
|
+
tag: l.indexOf("container") > -1 ? "container" : l.indexOf("tugs") > -1 ? "tugs" : "common",
|
|
933
937
|
lbp: n,
|
|
934
938
|
loadCondition: t,
|
|
935
939
|
draught: i,
|
|
@@ -954,40 +958,40 @@ class Y {
|
|
|
954
958
|
* @param options
|
|
955
959
|
*/
|
|
956
960
|
static async speedLoseAt(e, t, a, o = "", n = 2, i = !0, s = !1, r = {}) {
|
|
957
|
-
let
|
|
961
|
+
let l;
|
|
958
962
|
if (t.velocity && s && (e.speed = z.roundPrecision(t.velocity * 1852 / 3600, 6)), i) {
|
|
959
|
-
let
|
|
963
|
+
let u;
|
|
960
964
|
try {
|
|
961
965
|
o = (o == null ? void 0 : o.toUpperCase()) === "CMEMS" ? "ECMWF" : o, o = (o == null ? void 0 : o.toUpperCase()) === "METEO2" ? "best_match" : o;
|
|
962
|
-
const { weatherModels:
|
|
966
|
+
const { weatherModels: b, marineModels: S } = await ct.autoPickMeteoModel(o), C = await gt.spotForecast(t.lat, t.lng, a.utc().format(), !1, !1, !0, {
|
|
963
967
|
...r,
|
|
964
968
|
pastDays: 1,
|
|
965
969
|
forecastDays: 1,
|
|
966
|
-
weatherModels:
|
|
967
|
-
marineModels:
|
|
968
|
-
}), [
|
|
969
|
-
|
|
970
|
-
} catch (
|
|
971
|
-
|
|
970
|
+
weatherModels: b,
|
|
971
|
+
marineModels: S
|
|
972
|
+
}), [p] = ct.pickHourly(C, a);
|
|
973
|
+
u = ct.toLegacy(p);
|
|
974
|
+
} catch (b) {
|
|
975
|
+
T.warn("[%s] meteo2 spot(%j) forecast failed: %s", r.requestId, { ...t, eta: a.utc().format(), source: o }, b);
|
|
972
976
|
}
|
|
973
|
-
const d = Y.currentFactor(e.bearing,
|
|
974
|
-
|
|
975
|
-
meteo: { ...
|
|
977
|
+
const d = Y.currentFactor(e.bearing, u == null ? void 0 : u.current, n), y = Y.weatherFactor(e, u, d), k = Math.round((e.speed * 1.943844 + y + d) * 100) / 100;
|
|
978
|
+
l = {
|
|
979
|
+
meteo: { ...u },
|
|
976
980
|
wxFactor: y,
|
|
977
981
|
cFactor: d,
|
|
978
|
-
speed: t.velocity && s ? t.velocity :
|
|
982
|
+
speed: t.velocity && s ? t.velocity : k < 0 ? 1 : k,
|
|
979
983
|
eta: a.utc().format(),
|
|
980
984
|
etd: a.utc().format()
|
|
981
985
|
};
|
|
982
986
|
} else
|
|
983
|
-
|
|
987
|
+
l = {
|
|
984
988
|
wxFactor: 0,
|
|
985
989
|
cFactor: 0,
|
|
986
990
|
speed: t.velocity && s ? t.velocity : Math.round(e.speed * 1.943844 * 100) / 100,
|
|
987
991
|
eta: a.utc().format(),
|
|
988
992
|
etd: a.utc().format()
|
|
989
993
|
};
|
|
990
|
-
return delete t.meteo, delete t.wxFactor, delete t.cFactor, delete t.speed, delete t.etd, { ...
|
|
994
|
+
return delete t.meteo, delete t.wxFactor, delete t.cFactor, delete t.speed, delete t.etd, { ...l, ...t };
|
|
991
995
|
}
|
|
992
996
|
/**
|
|
993
997
|
* 基于步长计算失速样本
|
|
@@ -1003,53 +1007,53 @@ class Y {
|
|
|
1003
1007
|
* @param options
|
|
1004
1008
|
* @private
|
|
1005
1009
|
*/
|
|
1006
|
-
static async speedLoseInHoursStep(e, t, a, o, n, i, s = "", r = !0,
|
|
1010
|
+
static async speedLoseInHoursStep(e, t, a, o, n, i, s = "", r = !0, l = !1, u = {}) {
|
|
1007
1011
|
t.utc();
|
|
1008
|
-
const d = t.clone().add(14, "days"), y = [],
|
|
1009
|
-
let
|
|
1010
|
-
for (let
|
|
1011
|
-
let
|
|
1012
|
-
|
|
1013
|
-
const
|
|
1014
|
-
if (e.bearing =
|
|
1015
|
-
|
|
1016
|
-
const
|
|
1017
|
-
if (o -
|
|
1018
|
-
o = o -
|
|
1012
|
+
const d = t.clone().add(14, "days"), y = [], k = [], b = [];
|
|
1013
|
+
let S = 0, C = 0, p, v;
|
|
1014
|
+
for (let m = 0; m < i.length - 1; m++) {
|
|
1015
|
+
let c = i[m];
|
|
1016
|
+
c.distanceFromStart = Math.round((n + C) * 1e3) / 1e3;
|
|
1017
|
+
const f = i[m + 1];
|
|
1018
|
+
if (e.bearing = O.calculateBearing(c, f, !f.gcToPrevious), c.bearing = e.bearing, c.suspend && l) {
|
|
1019
|
+
c.eta = c.eta || t.utc().format(), c.elapsed = c.elapsed ?? 0;
|
|
1020
|
+
const I = c.suspend - c.elapsed;
|
|
1021
|
+
if (o - S > I)
|
|
1022
|
+
o = o - S - I, t.add(I, "hour"), c.elapsed = c.suspend;
|
|
1019
1023
|
else {
|
|
1020
|
-
const F = o -
|
|
1021
|
-
|
|
1024
|
+
const F = o - S;
|
|
1025
|
+
c.elapsed += F, t.add(F, "hour"), o = 0;
|
|
1022
1026
|
}
|
|
1023
|
-
if (
|
|
1024
|
-
return
|
|
1027
|
+
if (T == null || T.info(`[%s] suspend ${c.elapsed} hours at %j, and remain ${o} hours need to go...`, u.requestId, c), o === 0)
|
|
1028
|
+
return c.distanceFromPrevious = C, { etd: t, from: v || c, to: c, next: i.filter((F) => F), wps: y, days: k, all: b };
|
|
1025
1029
|
} else
|
|
1026
|
-
|
|
1027
|
-
r = t.isAfter(d) ? !1 : r,
|
|
1028
|
-
const
|
|
1029
|
-
let
|
|
1030
|
-
if (
|
|
1031
|
-
if (
|
|
1032
|
-
`[%s] go to %j from %j with ${
|
|
1033
|
-
|
|
1034
|
-
{ lat:
|
|
1035
|
-
{ lat:
|
|
1036
|
-
),
|
|
1037
|
-
|
|
1030
|
+
c.suspend = 0;
|
|
1031
|
+
r = t.isAfter(d) ? !1 : r, c = await Y.speedLoseAt(e, c, t, s, 0, r, l, u), b.push(c), v = v || c, c.important && y.push(c), t.isSameOrAfter(a) && (k.push(c), a.add(24, "hour"));
|
|
1032
|
+
const h = O.calculateDistance(c, f, !f.gcToPrevious);
|
|
1033
|
+
let g = Math.round(h / v.speed * 1e5) / 1e5;
|
|
1034
|
+
if (S + g < o) {
|
|
1035
|
+
if (S += g, t.add(g, "hour"), delete i[m], T == null || T.debug(
|
|
1036
|
+
`[%s] go to %j from %j with ${h}nm, and cost ${g} hours`,
|
|
1037
|
+
u.requestId,
|
|
1038
|
+
{ lat: f.lat, lng: f.lng },
|
|
1039
|
+
{ lat: v.lat, lng: v.lng, etd: v.etd }
|
|
1040
|
+
), C += h, i.filter((I) => I).length <= 1) {
|
|
1041
|
+
p = f, p.eta = t.utc().format(), p.distanceFromPrevious = h, p.distanceFromStart = Math.round((n + C) * 1e4) / 1e4, y.push(p), b.push(p), delete i[m + 1];
|
|
1038
1042
|
break;
|
|
1039
1043
|
}
|
|
1040
1044
|
} else {
|
|
1041
|
-
|
|
1042
|
-
const
|
|
1043
|
-
|
|
1044
|
-
`[%s] go to %j from %j with ${
|
|
1045
|
-
|
|
1046
|
-
{ lat:
|
|
1047
|
-
{ lat:
|
|
1048
|
-
),
|
|
1045
|
+
g = o - S, t.add(g, "hour");
|
|
1046
|
+
const I = z.roundPrecision(v.speed * g, 5);
|
|
1047
|
+
p = O.calculateCoordinate(c, e.bearing, I, "nauticalmiles", !f.gcToPrevious), p.eta = t.utc().format(), i[m] = p, T == null || T.debug(
|
|
1048
|
+
`[%s] go to %j from %j with ${I}nm, and cost ${g} hours`,
|
|
1049
|
+
u.requestId,
|
|
1050
|
+
{ lat: p.lat, lng: p.lng },
|
|
1051
|
+
{ lat: c.lat, lng: c.lng, etd: c.etd }
|
|
1052
|
+
), C += I, p.distanceFromPrevious = Math.round(C * 1e4) / 1e4, p.distanceFromStart = Math.round((n + C) * 1e4) / 1e4;
|
|
1049
1053
|
break;
|
|
1050
1054
|
}
|
|
1051
1055
|
}
|
|
1052
|
-
return { etd: t, from:
|
|
1056
|
+
return { etd: t, from: v, to: p, next: i.filter((m) => m), wps: y, days: k, all: b };
|
|
1053
1057
|
}
|
|
1054
1058
|
/**
|
|
1055
1059
|
* 洋流影响因子
|
|
@@ -1058,7 +1062,7 @@ class Y {
|
|
|
1058
1062
|
* @param role 1: 船东, 2: 租家, 0: 未知
|
|
1059
1063
|
*/
|
|
1060
1064
|
static currentFactor(e, t, a = 0) {
|
|
1061
|
-
const o = (e
|
|
1065
|
+
const o = O.includedAngle(e, (t == null ? void 0 : t.degree) || 0) / 180 * Math.PI;
|
|
1062
1066
|
if (Math.abs(o) === Math.PI / 2)
|
|
1063
1067
|
return 0;
|
|
1064
1068
|
let n = ((t == null ? void 0 : t.kts) || 0) * Math.cos(o);
|
|
@@ -1071,16 +1075,15 @@ class Y {
|
|
|
1071
1075
|
* @param cFactor 洋流因子
|
|
1072
1076
|
*/
|
|
1073
1077
|
static weatherFactor(e, t, a = 0) {
|
|
1074
|
-
var
|
|
1075
|
-
|
|
1078
|
+
var k, b, S, C, p, v, m;
|
|
1079
|
+
T == null || T.debug("calculate weather factor via: %j", { ...e, ...t });
|
|
1076
1080
|
const o = Y.blockCoefficient(e.displacement, e.lbp, e.breadthMoulded, e.draught), n = z.roundPrecision(a * 1852 / 3600, 6), i = Y.froudeNumber(e.speed - n, e.lbp), s = Y.amendFactor(o, i, e.loadCondition);
|
|
1077
|
-
let r =
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
return S == null || S.debug("wave wx factor = %d", y), d = Math.abs(d) > Math.abs(y) ? d : d * 0.3 + y * 0.7, S == null || S.debug("weather factor = %d", d), d = Math.abs(d) > 3 ? 3 * (Math.abs(d) / d) + Math.abs(d) / d * (Math.abs(d) - 2) * 0.1 : d, Math.round((d || 0) * 100) / 100;
|
|
1081
|
+
let r = O.includedAngle(e.bearing, (k = t == null ? void 0 : t.wind) == null ? void 0 : k.degree);
|
|
1082
|
+
const l = Y.directionFactor(r, (b = t == null ? void 0 : t.wind) == null ? void 0 : b.scale), u = Y.vesselTagFactor(e.displacement, e.loadCondition, e.tag, (S = t == null ? void 0 : t.wind) == null ? void 0 : S.kts);
|
|
1083
|
+
let d = l * s * u / 100 * (e.speed - n);
|
|
1084
|
+
d = Math.round(d * 1.943844 * 1e4) / 1e4 * -1, e.tag === "tugs" && Math.abs(d) > 1 && (d = d / (Math.abs(Math.round(d)) + 1)), T == null || T.debug("wind wx factor = %d", d), r = O.includedAngle(e.bearing, (p = (C = t == null ? void 0 : t.wave) == null ? void 0 : C.sig) == null ? void 0 : p.degree);
|
|
1085
|
+
const y = Y.waveHeightFactor(((m = (v = t == null ? void 0 : t.wave) == null ? void 0 : v.sig) == null ? void 0 : m.height) ?? 1, r);
|
|
1086
|
+
return T == null || T.debug("wave wx factor = %d", y), d = Math.abs(d) > Math.abs(y) ? d : d * 0.3 + y * 0.7, T == null || T.debug("weather factor = %d", d), d = Math.abs(d) > 3 ? 3 * (Math.abs(d) / d) + Math.abs(d) / d * (Math.abs(d) - 2) * 0.1 : d, Math.round((d || 0) * 100) / 100;
|
|
1084
1087
|
}
|
|
1085
1088
|
/**
|
|
1086
1089
|
* 以12小时级别去掉重复的days
|
|
@@ -1088,7 +1091,7 @@ class Y {
|
|
|
1088
1091
|
* @param interval 12 hours
|
|
1089
1092
|
*/
|
|
1090
1093
|
static async reduceDays(e, t = 12 * 60 * 60) {
|
|
1091
|
-
return e = e == null ? void 0 : e.reduce((a, o) => (o.positionTime || (o.positionTime =
|
|
1094
|
+
return e = e == null ? void 0 : e.reduce((a, o) => (o.positionTime || (o.positionTime = w.utc(o.etd || o.eta).unix()), a.some((n) => Math.floor(n.positionTime / t) === Math.floor(o.positionTime / t)) || a.push(o), a), []), e;
|
|
1092
1095
|
}
|
|
1093
1096
|
/**
|
|
1094
1097
|
* 以分钟级别去掉重复的wps
|
|
@@ -1096,7 +1099,7 @@ class Y {
|
|
|
1096
1099
|
* @param interval 1 minute
|
|
1097
1100
|
*/
|
|
1098
1101
|
static async reduceWPS(e, t = 60) {
|
|
1099
|
-
return e = e == null ? void 0 : e.reduce((a, o) => (a.some((n) => Math.floor(
|
|
1102
|
+
return e = e == null ? void 0 : e.reduce((a, o) => (a.some((n) => Math.floor(w(n.etd).unix() / t) === Math.floor(w(o.etd).unix() / t)) || a.push(o), a), []), e;
|
|
1100
1103
|
}
|
|
1101
1104
|
/**
|
|
1102
1105
|
* 全程失速分析(走完航程)
|
|
@@ -1111,14 +1114,14 @@ class Y {
|
|
|
1111
1114
|
* @param useRouteParam
|
|
1112
1115
|
* @param options
|
|
1113
1116
|
*/
|
|
1114
|
-
static async analyseInstant(e, t, a, o, n, i = "", s = 0, r = !0,
|
|
1117
|
+
static async analyseInstant(e, t, a, o, n, i = "", s = 0, r = !0, l = !1, u = {}) {
|
|
1115
1118
|
var _, G, X, Q, Z, $;
|
|
1116
|
-
const d =
|
|
1119
|
+
const d = w().valueOf();
|
|
1117
1120
|
e.lng = z.convertToStdLng(e.lng);
|
|
1118
|
-
const { route: y, waypoints:
|
|
1119
|
-
if (((_ =
|
|
1121
|
+
const { route: y, waypoints: k } = n.points, b = O.calculateSubRoute(e, y);
|
|
1122
|
+
if (((_ = b[0]) == null ? void 0 : _.length) <= 1)
|
|
1120
1123
|
return;
|
|
1121
|
-
const { v0:
|
|
1124
|
+
const { v0: S, label: C } = e.sog ? {
|
|
1122
1125
|
v0: e.sog,
|
|
1123
1126
|
label: e.label || "Other"
|
|
1124
1127
|
/* Instruct */
|
|
@@ -1126,69 +1129,69 @@ class Y {
|
|
|
1126
1129
|
v0: o.speed,
|
|
1127
1130
|
label: "CP"
|
|
1128
1131
|
/* Cp */
|
|
1129
|
-
},
|
|
1130
|
-
|
|
1131
|
-
const
|
|
1132
|
+
}, p = Y.assembleProperties(a, o.loadCondition, S, 0), v = k.length ? O.calculateSubWaypoints(e, k) : [];
|
|
1133
|
+
v.forEach((A) => A.important = !0);
|
|
1134
|
+
const m = {
|
|
1132
1135
|
from: { ...e },
|
|
1133
|
-
route:
|
|
1134
|
-
waypoints:
|
|
1135
|
-
v0:
|
|
1136
|
-
label:
|
|
1137
|
-
},
|
|
1136
|
+
route: b,
|
|
1137
|
+
waypoints: v,
|
|
1138
|
+
v0: S,
|
|
1139
|
+
label: C
|
|
1140
|
+
}, c = {
|
|
1138
1141
|
hours: [],
|
|
1139
1142
|
days: [],
|
|
1140
1143
|
wps: [],
|
|
1141
1144
|
all: []
|
|
1142
1145
|
};
|
|
1143
|
-
s || (
|
|
1144
|
-
let
|
|
1145
|
-
t =
|
|
1146
|
+
s || (O.calculateRouteDistance(b) / o.speed <= 72 ? s = 3 : s = 6);
|
|
1147
|
+
let f = O.simplifyRouteToCoordinates(b, v, 0), h = 0, g = 0, I = 0, F = 0;
|
|
1148
|
+
t = w(t).utc();
|
|
1146
1149
|
const P = t.clone();
|
|
1147
|
-
for (;
|
|
1148
|
-
const A = s - t.hour() % s, V = Math.ceil(t.clone().add(A, "h").set({ minute: 0, second: 0, millisecond: 0 }).diff(t, "h", !0) * 1e4) / 1e4,
|
|
1149
|
-
|
|
1150
|
+
for (; f.length > 0; ) {
|
|
1151
|
+
const A = s - t.hour() % s, V = Math.ceil(t.clone().add(A, "h").set({ minute: 0, second: 0, millisecond: 0 }).diff(t, "h", !0) * 1e4) / 1e4, E = await Y.speedLoseInHoursStep(
|
|
1152
|
+
p,
|
|
1150
1153
|
t,
|
|
1151
1154
|
P,
|
|
1152
1155
|
V,
|
|
1153
|
-
|
|
1154
|
-
|
|
1156
|
+
h,
|
|
1157
|
+
f,
|
|
1155
1158
|
i,
|
|
1156
1159
|
r,
|
|
1157
|
-
|
|
1158
|
-
|
|
1160
|
+
l,
|
|
1161
|
+
u
|
|
1159
1162
|
);
|
|
1160
|
-
if (
|
|
1161
|
-
const L = await Y.speedLoseAt(
|
|
1162
|
-
L.bearing =
|
|
1163
|
+
if (c.all.push(...E.all), (G = E.from) != null && G.speed && (c.hours.push(E.from), c.wps.push(...E.wps), c.days.push(...E.days)), f = E == null ? void 0 : E.next, !f.length) {
|
|
1164
|
+
const L = await Y.speedLoseAt(p, E.to, w(E.to.eta), i, 0, r, l, u);
|
|
1165
|
+
L.bearing = p.bearing, c.hours.push(L), c.all.push(L);
|
|
1163
1166
|
}
|
|
1164
|
-
|
|
1167
|
+
h += Math.round((((X = E == null ? void 0 : E.to) == null ? void 0 : X.distanceFromPrevious) ?? 0) * 1e4) / 1e4;
|
|
1165
1168
|
}
|
|
1166
|
-
const D =
|
|
1169
|
+
const D = c.hours;
|
|
1167
1170
|
for (let A = 0; A < D.length - 1; A++) {
|
|
1168
|
-
const V =
|
|
1169
|
-
|
|
1171
|
+
const V = w(D[A + 1].eta).diff(D[A].etd, "hour", !0) || 1;
|
|
1172
|
+
g += (D[A].wxFactor || 0) * V, I += (D[A].cFactor || 0) * V, F += V;
|
|
1170
1173
|
}
|
|
1171
1174
|
const H = D.reduce((A, V) => A + (V.suspend || 0), 0);
|
|
1172
|
-
(Q =
|
|
1173
|
-
A.positionTime =
|
|
1174
|
-
const
|
|
1175
|
-
if (
|
|
1176
|
-
const L = A.distanceFromStart -
|
|
1177
|
-
A.avgSpd = Math.round(L / q * 100) / 100,
|
|
1175
|
+
(Q = c.wps) == null || Q.forEach((A, V) => {
|
|
1176
|
+
A.positionTime = w.utc(A.etd || A.eta).unix();
|
|
1177
|
+
const E = c.wps[V - 1];
|
|
1178
|
+
if (E) {
|
|
1179
|
+
const L = A.distanceFromStart - E.distanceFromStart, q = w(A.eta || A.etd).diff(w(E.etd || E.eta), "h", !0);
|
|
1180
|
+
A.avgSpd = Math.round(L / q * 100) / 100, E.bearing = O.calculateBearing(E, A);
|
|
1178
1181
|
}
|
|
1179
|
-
}),
|
|
1180
|
-
const
|
|
1181
|
-
|
|
1182
|
-
const
|
|
1183
|
-
|
|
1182
|
+
}), c.wps = await Y.reduceWPS(c.wps), c.days = await Y.reduceDays(c.days), c.all = (Z = c.all) == null ? void 0 : Z.reduce((A, V) => (V.positionTime = w.utc(V.etd || V.eta).unix(), A.some((E) => Math.round(E.positionTime / 60) === Math.round(V.positionTime / 60)) || A.push(V), A), []), m.sample = c;
|
|
1183
|
+
const j = c.hours.at(0), N = c.hours.at(-1);
|
|
1184
|
+
m.distance = Math.round(N.distanceFromStart * 1e3) / 1e3, m.etd = w(j.eta).utc().format(), m.eta = w(N.eta).utc().format(), m.wxFactor = Math.round(g / F * 1e3) / 1e3, m.cFactor = Math.round(I / F * 1e3) / 1e3, m.avgSpeed = Math.round(N.distanceFromStart / F * 1e3) / 1e3, m.totalHrs = Math.round(F * 1e3) / 1e3, m.suspend = Math.round(H * 1e3) / 1e3;
|
|
1185
|
+
const R = z.roundPrecision(o.dgo / 24 * H, 3), { distanceInECA: W, hoursInECA: K, totalDgoConsInECA: nt, eca: tt } = await this.calculateECA(m, o, u), et = z.roundPrecision(o.fo / 24 * (F - K), 3), ot = z.roundPrecision(o.dgo / 24 * F + R, 3);
|
|
1186
|
+
m.extend = {
|
|
1184
1187
|
eca: tt,
|
|
1185
|
-
distanceInECA:
|
|
1188
|
+
distanceInECA: W,
|
|
1186
1189
|
hoursInECA: K,
|
|
1187
1190
|
totalDgoConsInECA: nt,
|
|
1188
|
-
totalDgoConsInSuspend:
|
|
1189
|
-
},
|
|
1190
|
-
const st =
|
|
1191
|
-
return
|
|
1191
|
+
totalDgoConsInSuspend: R
|
|
1192
|
+
}, m.totalFoCons = et < 0 ? 0 : et, m.totalDgoCons = ot;
|
|
1193
|
+
const st = w().valueOf() - d, rt = (($ = c == null ? void 0 : c.hours) == null ? void 0 : $.length) || 1;
|
|
1194
|
+
return T == null || T.info("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms", u == null ? void 0 : u.requestId, st, rt, Math.round(st / rt * 1e3) / 1e3), m;
|
|
1192
1195
|
}
|
|
1193
1196
|
/**
|
|
1194
1197
|
* 分段失速分析(最多走hours 小时)
|
|
@@ -1205,11 +1208,11 @@ class Y {
|
|
|
1205
1208
|
* @param useRouteParam
|
|
1206
1209
|
* @param options
|
|
1207
1210
|
*/
|
|
1208
|
-
static async analyseInstantWithThreshed(e, t, a, o, n, i, s, r = "",
|
|
1211
|
+
static async analyseInstantWithThreshed(e, t, a, o, n, i, s, r = "", l = 3, u = !0, d = !1, y = {}) {
|
|
1209
1212
|
var X, Q, Z, $, A, V;
|
|
1210
|
-
const
|
|
1213
|
+
const k = w().valueOf();
|
|
1211
1214
|
e.lng = z.convertToStdLng(e.lng);
|
|
1212
|
-
const { v0:
|
|
1215
|
+
const { v0: b, label: S } = e.sog ? {
|
|
1213
1216
|
v0: e.sog,
|
|
1214
1217
|
label: e.label || "Other"
|
|
1215
1218
|
/* Instruct */
|
|
@@ -1217,67 +1220,67 @@ class Y {
|
|
|
1217
1220
|
v0: n.speed,
|
|
1218
1221
|
label: "CP"
|
|
1219
1222
|
/* Cp */
|
|
1220
|
-
},
|
|
1221
|
-
if (((X =
|
|
1223
|
+
}, C = Y.assembleProperties(o, n.loadCondition, b, 0), p = O.calculateSubRoute(e, i);
|
|
1224
|
+
if (((X = p[0]) == null ? void 0 : X.length) <= 1)
|
|
1222
1225
|
return;
|
|
1223
|
-
const
|
|
1224
|
-
|
|
1225
|
-
let
|
|
1226
|
-
const
|
|
1226
|
+
const v = s.length ? O.calculateSubWaypoints(e, s) : [];
|
|
1227
|
+
v.forEach((E) => E.important = !0);
|
|
1228
|
+
let m = O.simplifyRouteToCoordinates(p, v, 0), c = 0, f = 0, h = 0, g = 0;
|
|
1229
|
+
const I = {
|
|
1227
1230
|
hours: [],
|
|
1228
1231
|
wps: [],
|
|
1229
1232
|
days: [],
|
|
1230
1233
|
all: []
|
|
1231
1234
|
};
|
|
1232
|
-
t =
|
|
1235
|
+
t = w(t).utc();
|
|
1233
1236
|
const F = t.clone();
|
|
1234
|
-
for (;
|
|
1235
|
-
const
|
|
1236
|
-
let L = Math.ceil(t.clone().add(
|
|
1237
|
+
for (; m.length > 0; ) {
|
|
1238
|
+
const E = l - t.hour() % l;
|
|
1239
|
+
let L = Math.ceil(t.clone().add(E, "h").set({ minute: 0, second: 0, millisecond: 0 }).diff(t, "h", !0) * 1e4) / 1e4;
|
|
1237
1240
|
L = t.clone().add(L, "h").isSameOrAfter(a) ? a.diff(t, "h", !0) * 1e4 / 1e4 : L;
|
|
1238
|
-
const q = await Y.speedLoseInHoursStep(
|
|
1239
|
-
if (
|
|
1241
|
+
const q = await Y.speedLoseInHoursStep(C, t, F, L, c, m, r, u, d, y);
|
|
1242
|
+
if (I.all.push(...q.all), (Q = q.from) != null && Q.speed && (I.hours.push(q.from), q != null && q.wps && I.wps.push(...q.wps), I.days.push(...q.days)), m = q == null ? void 0 : q.next, m.length || I.hours.push(q == null ? void 0 : q.to), c += Math.round((((Z = q == null ? void 0 : q.to) == null ? void 0 : Z.distanceFromPrevious) ?? 0) * 1e4) / 1e4, !L)
|
|
1240
1243
|
break;
|
|
1241
1244
|
}
|
|
1242
|
-
|
|
1243
|
-
const q =
|
|
1245
|
+
I.wps = await Y.reduceWPS(I.wps), I.days = await Y.reduceDays(I.days), I.all = ($ = I.all) == null ? void 0 : $.reduce((E, L) => (L.positionTime = w.utc(L.etd || L.eta).unix(), E.some((q) => Math.round(w(q.etd).unix() / 60) === Math.round(w(L.etd).unix() / 60)) || E.push(L), E), []), (A = I.wps) == null || A.forEach((E, L) => {
|
|
1246
|
+
const q = I.wps[L - 1];
|
|
1244
1247
|
if (q) {
|
|
1245
|
-
const ut =
|
|
1246
|
-
q.bearing =
|
|
1248
|
+
const ut = E.distanceFromStart - q.distanceFromStart, lt = w(E.eta || E.etd).diff(w(q.etd || q.eta), "h", !0);
|
|
1249
|
+
q.bearing = O.calculateBearing(q, E), E.avgSpd = Math.round(ut / lt * 100) / 100;
|
|
1247
1250
|
}
|
|
1248
1251
|
});
|
|
1249
|
-
const P =
|
|
1250
|
-
for (let
|
|
1251
|
-
const L =
|
|
1252
|
-
|
|
1252
|
+
const P = I.hours;
|
|
1253
|
+
for (let E = 0; E < P.length - 1; E++) {
|
|
1254
|
+
const L = w(P[E + 1].eta).diff(P[E].etd, "hour", !0);
|
|
1255
|
+
f += P[E].wxFactor * L, h += P[E].cFactor * L, g += L;
|
|
1253
1256
|
}
|
|
1254
|
-
const D = P.reduce((
|
|
1255
|
-
sample:
|
|
1256
|
-
distance: Math.round(((
|
|
1257
|
+
const D = P.reduce((E, L) => E + (L.suspend || 0), 0), H = I.hours.at(0), j = I.hours.at(-1), N = await O.calculateRangeRoute(H, j, p), R = await O.calculateRangeWaypoints(H, j, p, v), W = {
|
|
1258
|
+
sample: I,
|
|
1259
|
+
distance: Math.round(((j == null ? void 0 : j.distanceFromStart) || 0) * 1e4) / 1e4,
|
|
1257
1260
|
// 注意,可能会在first节点Drift,所有采用eta做为初始出发时间
|
|
1258
|
-
etd:
|
|
1259
|
-
eta:
|
|
1260
|
-
wxFactor: Math.round(
|
|
1261
|
-
cFactor: Math.round(
|
|
1262
|
-
avgSpeed: Math.round(((
|
|
1263
|
-
totalHrs: Math.round(
|
|
1261
|
+
etd: w(H.eta).utc().format(),
|
|
1262
|
+
eta: w(j == null ? void 0 : j.eta).utc().format(),
|
|
1263
|
+
wxFactor: Math.round(f / g * 1e3) / 1e3,
|
|
1264
|
+
cFactor: Math.round(h / g * 1e3) / 1e3,
|
|
1265
|
+
avgSpeed: Math.round(((j == null ? void 0 : j.distanceFromStart) || 0) / g * 1e3) / 1e3,
|
|
1266
|
+
totalHrs: Math.round(g * 1e3) / 1e3,
|
|
1264
1267
|
suspend: Math.round(D * 1e3) / 1e3,
|
|
1265
1268
|
from: H,
|
|
1266
|
-
to:
|
|
1269
|
+
to: j,
|
|
1267
1270
|
route: N,
|
|
1268
|
-
waypoints:
|
|
1269
|
-
v0:
|
|
1270
|
-
label:
|
|
1271
|
-
}, K = z.roundPrecision(n.dgo / 24 * D, 3), { distanceInECA: nt, hoursInECA: tt, totalDgoConsInECA: et, eca: ot } = await this.calculateECA(
|
|
1272
|
-
|
|
1271
|
+
waypoints: R,
|
|
1272
|
+
v0: b,
|
|
1273
|
+
label: S
|
|
1274
|
+
}, K = z.roundPrecision(n.dgo / 24 * D, 3), { distanceInECA: nt, hoursInECA: tt, totalDgoConsInECA: et, eca: ot } = await this.calculateECA(W, n, y), it = z.roundPrecision(n.fo / 24 * (g - tt), 3), st = z.roundPrecision(n.dgo / 24 * g + K, 3);
|
|
1275
|
+
W.extend = {
|
|
1273
1276
|
eca: ot,
|
|
1274
1277
|
distanceInECA: nt,
|
|
1275
1278
|
hoursInECA: tt,
|
|
1276
1279
|
totalDgoConsInECA: et,
|
|
1277
1280
|
totalDgoConsInSuspend: K
|
|
1278
|
-
},
|
|
1279
|
-
const _ =
|
|
1280
|
-
return
|
|
1281
|
+
}, W.totalDgoCons = st, W.totalFoCons = it < 0 ? 0 : it;
|
|
1282
|
+
const _ = w().valueOf() - k, G = ((V = I == null ? void 0 : I.hours) == null ? void 0 : V.length) || 1;
|
|
1283
|
+
return T == null || T.debug("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms", y == null ? void 0 : y.requestId, _, G, Math.round(_ / G * 1e3) / 1e3), W;
|
|
1281
1284
|
}
|
|
1282
1285
|
/**
|
|
1283
1286
|
* 在指定航线条件下,基于多CP,动态计算最优成本(租金+油费)方案
|
|
@@ -1295,58 +1298,58 @@ class Y {
|
|
|
1295
1298
|
* @param options
|
|
1296
1299
|
*/
|
|
1297
1300
|
static async analyseCost(e, t, a, o, n = {}) {
|
|
1298
|
-
var
|
|
1299
|
-
const i =
|
|
1301
|
+
var p, v;
|
|
1302
|
+
const i = w().valueOf(), s = [];
|
|
1300
1303
|
e.speedStep = e.speedStep || 3, e.alterStep = e.alterStep ?? 1;
|
|
1301
|
-
const r =
|
|
1302
|
-
let
|
|
1303
|
-
a.forEach((
|
|
1304
|
-
const
|
|
1305
|
-
|
|
1306
|
-
}),
|
|
1307
|
-
const
|
|
1304
|
+
const r = O.calculateRouteDistance(o.route);
|
|
1305
|
+
let l = 0;
|
|
1306
|
+
a.forEach((m) => {
|
|
1307
|
+
const c = Math.ceil(r / m.speed / 24);
|
|
1308
|
+
l = l < c ? c : l;
|
|
1309
|
+
}), l = l * 1.3;
|
|
1310
|
+
const u = w.utc(e.etd).add(l ?? 14, "day");
|
|
1308
1311
|
let d = 1;
|
|
1309
|
-
for (const
|
|
1310
|
-
const
|
|
1312
|
+
for (const m of a) {
|
|
1313
|
+
const c = JSON.parse(JSON.stringify(o.route)), f = JSON.parse(JSON.stringify(o.waypoints)), h = await Y.analyseInstantWithThreshed(
|
|
1311
1314
|
{ lat: e.lat, lng: e.lng },
|
|
1312
1315
|
e.etd,
|
|
1313
|
-
l,
|
|
1314
|
-
t,
|
|
1315
|
-
f,
|
|
1316
1316
|
u,
|
|
1317
|
+
t,
|
|
1317
1318
|
m,
|
|
1319
|
+
c,
|
|
1320
|
+
f,
|
|
1318
1321
|
e.meteoVendor,
|
|
1319
1322
|
e.speedStep,
|
|
1320
1323
|
e.useMeteo,
|
|
1321
1324
|
e.useRouteParam,
|
|
1322
1325
|
n
|
|
1323
1326
|
);
|
|
1324
|
-
|
|
1325
|
-
cost:
|
|
1326
|
-
hire:
|
|
1327
|
-
bunker:
|
|
1328
|
-
distance:
|
|
1329
|
-
hours:
|
|
1330
|
-
cp: `${
|
|
1327
|
+
h && (await Y.calculateCost(h, m, e, n), s.push(h), T == null || T.info("[%s][L%d-%d] analyse from %s to %s cost: %j", n.requestId, 1, d, e.etd, u.format(), {
|
|
1328
|
+
cost: h.cost.total,
|
|
1329
|
+
hire: h.cost.hire,
|
|
1330
|
+
bunker: h.cost.bunker,
|
|
1331
|
+
distance: h.distance,
|
|
1332
|
+
hours: h.totalHrs,
|
|
1333
|
+
cp: `${m.speed}/${m.fo}/${m.dgo}`
|
|
1331
1334
|
})), d++;
|
|
1332
1335
|
}
|
|
1333
|
-
s.sort((
|
|
1334
|
-
const y = s.at(0),
|
|
1335
|
-
if (
|
|
1336
|
-
const
|
|
1337
|
-
let
|
|
1338
|
-
|
|
1339
|
-
let F = 2, P = { combined: !1, speeds: [
|
|
1340
|
-
for (;
|
|
1341
|
-
const H = await Y.combinedAnalyse(e, t,
|
|
1342
|
-
if (P.cost > H.cost ? D ? (D == null ? void 0 : D.cost) > H.cost && (D = H) : (D = P, P = H) : (!D || (D == null ? void 0 : D.cost) > H.cost) && (D = H),
|
|
1336
|
+
s.sort((m, c) => m.cost.total - c.cost.total);
|
|
1337
|
+
const y = s.at(0), k = s.at(1), b = [];
|
|
1338
|
+
if (b.push({ combined: !1, speeds: [y], cost: (p = y.cost) == null ? void 0 : p.total }), k) {
|
|
1339
|
+
const m = y.cost.cp, c = k.cost.cp, f = w(y.eta), h = w(y.etd), g = f.diff(h, "days", !0);
|
|
1340
|
+
let I = Math.ceil(g / 2);
|
|
1341
|
+
I = I > 7 ? 7 : I < e.alterStep ? e.alterStep : I;
|
|
1342
|
+
let F = 2, P = { combined: !1, speeds: [k], cost: (v = k.cost) == null ? void 0 : v.total }, D;
|
|
1343
|
+
for (; I >= e.alterStep; ) {
|
|
1344
|
+
const H = await Y.combinedAnalyse(e, t, u, [m, c], o, I, { ...n, level: F });
|
|
1345
|
+
if (P.cost > H.cost ? D ? (D == null ? void 0 : D.cost) > H.cost && (D = H) : (D = P, P = H) : (!D || (D == null ? void 0 : D.cost) > H.cost) && (D = H), I <= e.alterStep)
|
|
1343
1346
|
break;
|
|
1344
|
-
|
|
1347
|
+
I = Math.ceil(I / 2), F += 1;
|
|
1345
1348
|
}
|
|
1346
|
-
|
|
1349
|
+
b.push(P), D && b.push(D);
|
|
1347
1350
|
}
|
|
1348
|
-
const
|
|
1349
|
-
return
|
|
1351
|
+
const C = w().valueOf() - i;
|
|
1352
|
+
return T == null || T.info("[%s] analyse elapsed: %d ms", n == null ? void 0 : n.requestId, C), b.sort((m, c) => m.cost - c.cost);
|
|
1350
1353
|
}
|
|
1351
1354
|
/**
|
|
1352
1355
|
* 按步长多次减半,分别用7,4,2,1天步长及cpa,cpb交替计算各种组合下的成本
|
|
@@ -1359,23 +1362,23 @@ class Y {
|
|
|
1359
1362
|
* @param options
|
|
1360
1363
|
*/
|
|
1361
1364
|
static async combinedAnalyse(e, t, a, o, n, i, s = {}) {
|
|
1362
|
-
s.counter = 1,
|
|
1363
|
-
const r = await Y.alternateAnalyse(e, t, a, o, 0, n, i, s),
|
|
1364
|
-
|
|
1365
|
-
cost:
|
|
1366
|
-
hire:
|
|
1365
|
+
s.counter = 1, T == null || T.info("[%s][L%d] analyse with alternate cp in every %d days", s.requestId, s.level, i);
|
|
1366
|
+
const r = await Y.alternateAnalyse(e, t, a, o, 0, n, i, s), l = r.reduce((c, f) => c + f.cost.total, 0), u = r.reduce((c, f) => c + f.cost.hire, 0), d = r.reduce((c, f) => c + f.cost.bunker, 0), y = r.reduce((c, f) => c + f.distance, 0), k = r.reduce((c, f) => c + f.totalHrs, 0);
|
|
1367
|
+
T == null || T.info("[%s][L%d] cost with cpa/cpb turn: %j", s.requestId, s.level, {
|
|
1368
|
+
cost: l,
|
|
1369
|
+
hire: u,
|
|
1367
1370
|
bunker: d,
|
|
1368
1371
|
distance: y,
|
|
1369
|
-
hours:
|
|
1372
|
+
hours: k
|
|
1370
1373
|
});
|
|
1371
|
-
const
|
|
1372
|
-
return
|
|
1373
|
-
cost:
|
|
1374
|
-
hire:
|
|
1375
|
-
bunker:
|
|
1376
|
-
distance:
|
|
1377
|
-
hours:
|
|
1378
|
-
}),
|
|
1374
|
+
const b = await Y.alternateAnalyse(e, t, a, o, 1, n, i, s), S = b.reduce((c, f) => c + f.cost.total, 0), C = b.reduce((c, f) => c + f.cost.hire, 0), p = b.reduce((c, f) => c + f.cost.bunker, 0), v = b.reduce((c, f) => c + f.distance, 0), m = b.reduce((c, f) => c + f.totalHrs, 0);
|
|
1375
|
+
return T == null || T.info("[%s][L%d] cost with cpb/cpa turn: %j", s.requestId, s.level, {
|
|
1376
|
+
cost: S,
|
|
1377
|
+
hire: C,
|
|
1378
|
+
bunker: p,
|
|
1379
|
+
distance: v,
|
|
1380
|
+
hours: m
|
|
1381
|
+
}), l < S ? { combined: !0, cost: Math.round(l * 1e3) / 1e3, speeds: r, step: i } : { combined: !0, cost: Math.round(S * 1e3) / 1e3, speeds: b, step: i };
|
|
1379
1382
|
}
|
|
1380
1383
|
/**
|
|
1381
1384
|
* 基于cp索引,交替计算指定步长下的成本
|
|
@@ -1389,43 +1392,43 @@ class Y {
|
|
|
1389
1392
|
* @param options
|
|
1390
1393
|
*/
|
|
1391
1394
|
static async alternateAnalyse(e, t, a, o, n, i, s, r = {}) {
|
|
1392
|
-
var y,
|
|
1393
|
-
let
|
|
1394
|
-
const
|
|
1395
|
-
for (;
|
|
1396
|
-
const
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
g,
|
|
1400
|
-
t,
|
|
1395
|
+
var y, k;
|
|
1396
|
+
let l = w.utc(e.etd);
|
|
1397
|
+
const u = { lat: e.lat, lng: e.lng }, d = [];
|
|
1398
|
+
for (; l.isBefore(a); ) {
|
|
1399
|
+
const b = l.clone().utc().add(s, "day"), S = JSON.parse(JSON.stringify(i.route)), C = JSON.parse(JSON.stringify(i.waypoints)), p = o[n], v = await Y.analyseInstantWithThreshed(
|
|
1400
|
+
u,
|
|
1401
|
+
l.utc().format(),
|
|
1401
1402
|
b,
|
|
1402
|
-
|
|
1403
|
-
|
|
1403
|
+
t,
|
|
1404
|
+
p,
|
|
1405
|
+
S,
|
|
1406
|
+
C,
|
|
1404
1407
|
e.meteoVendor,
|
|
1405
1408
|
e.speedStep,
|
|
1406
1409
|
e.useMeteo,
|
|
1407
1410
|
e.useRouteParam,
|
|
1408
1411
|
r
|
|
1409
1412
|
);
|
|
1410
|
-
|
|
1413
|
+
v && (await Y.calculateCost(v, p, e, r), T == null || T.info(
|
|
1411
1414
|
"[%s][L%d-%d] analyse from %s to %s cost: %j",
|
|
1412
1415
|
r.requestId,
|
|
1413
1416
|
r.level,
|
|
1414
1417
|
r.counter,
|
|
1415
|
-
|
|
1416
|
-
|
|
1418
|
+
l.utc().format(),
|
|
1419
|
+
b.utc().format(),
|
|
1417
1420
|
{
|
|
1418
|
-
cost:
|
|
1419
|
-
hire:
|
|
1420
|
-
bunker:
|
|
1421
|
-
distance:
|
|
1422
|
-
hours:
|
|
1423
|
-
cp: `${
|
|
1421
|
+
cost: v.cost.total,
|
|
1422
|
+
hire: v.cost.hire,
|
|
1423
|
+
bunker: v.cost.bunker,
|
|
1424
|
+
distance: v.distance,
|
|
1425
|
+
hours: v.totalHrs,
|
|
1426
|
+
cp: `${p.speed}/${p.fo}/${p.dgo}`
|
|
1424
1427
|
}
|
|
1425
1428
|
)), r.counter = r.counter + 1;
|
|
1426
|
-
const
|
|
1427
|
-
if (
|
|
1428
|
-
|
|
1429
|
+
const m = (k = (y = v == null ? void 0 : v.sample) == null ? void 0 : y.hours) == null ? void 0 : k.at(-1);
|
|
1430
|
+
if (m)
|
|
1431
|
+
u.lat = m.lat, u.lng = m.lng, l = w(m.eta), d.push(v), n = n ? 0 : 1;
|
|
1429
1432
|
else
|
|
1430
1433
|
break;
|
|
1431
1434
|
}
|
|
@@ -1441,12 +1444,12 @@ class Y {
|
|
|
1441
1444
|
static async calculateCost(e, t, a, o = {}) {
|
|
1442
1445
|
var n;
|
|
1443
1446
|
if (e) {
|
|
1444
|
-
const i = (a.addComm || 0) >= 1 ? (a.addComm || 0) / 100 : a.addComm || 0, s = Math.round((a.dailyHire || 0) * (e.suspend || 0) / 24 * 1e3) / 1e3, r = Math.round(e.totalHrs / 24 * (a.dailyHire || 0) * (1 - i) * 1e3) / 1e3 + s,
|
|
1447
|
+
const i = (a.addComm || 0) >= 1 ? (a.addComm || 0) / 100 : a.addComm || 0, s = Math.round((a.dailyHire || 0) * (e.suspend || 0) / 24 * 1e3) / 1e3, r = Math.round(e.totalHrs / 24 * (a.dailyHire || 0) * (1 - i) * 1e3) / 1e3 + s, l = Math.round(e.totalFoCons * (a.priceFO || 0) * 1e3) / 1e3, u = Math.round((e.totalDgoCons + (((n = e.extend) == null ? void 0 : n.totalDgoConsInECA) || 0)) * (a.priceDGO || 0) * 1e3) / 1e3;
|
|
1445
1448
|
e.cost = {
|
|
1446
|
-
total: Math.round((r +
|
|
1449
|
+
total: Math.round((r + l + u) * 1e3) / 1e3,
|
|
1447
1450
|
hire: Math.round(r * 1e3) / 1e3,
|
|
1448
1451
|
suspendHire: s,
|
|
1449
|
-
bunker: Math.round((
|
|
1452
|
+
bunker: Math.round((l + u) * 1e3) / 1e3,
|
|
1450
1453
|
cp: t
|
|
1451
1454
|
};
|
|
1452
1455
|
}
|
|
@@ -1457,16 +1460,16 @@ class Y {
|
|
|
1457
1460
|
*
|
|
1458
1461
|
*/
|
|
1459
1462
|
static async calculateECA(e, t, a = {}) {
|
|
1460
|
-
var r,
|
|
1461
|
-
const o = await
|
|
1463
|
+
var r, l, u, d;
|
|
1464
|
+
const o = await O.intersectInECA((e == null ? void 0 : e.route) || []);
|
|
1462
1465
|
let n = 0, i = 0, s = 0;
|
|
1463
|
-
(
|
|
1464
|
-
y.positionTime =
|
|
1466
|
+
(l = (r = e == null ? void 0 : e.sample) == null ? void 0 : r.wps) == null || l.forEach((y) => {
|
|
1467
|
+
y.positionTime = w.utc(y.etd || y.eta).unix();
|
|
1465
1468
|
});
|
|
1466
1469
|
for (const y of o) {
|
|
1467
1470
|
n += y.distance;
|
|
1468
|
-
const
|
|
1469
|
-
y.in =
|
|
1471
|
+
const k = await O.deadReckoningTime((u = y.waypoints) == null ? void 0 : u.at(0), e.sample.all || e.sample.wps), b = await O.deadReckoningTime((d = y.waypoints) == null ? void 0 : d.at(-1), e.sample.all || e.sample.wps);
|
|
1472
|
+
y.in = k, y.out = b, y.totalHrs = z.roundPrecision((b.positionTime - k.positionTime) / 3600, 3), y.totalDgoCons = z.roundPrecision(t.fo / 24 * y.totalHrs, 3), i += y.totalHrs, s += y.totalDgoCons;
|
|
1470
1473
|
}
|
|
1471
1474
|
return n = z.roundPrecision(n, 3), i = z.roundPrecision(i, 3), s = z.roundPrecision(s, 3), {
|
|
1472
1475
|
distanceInECA: n,
|
|
@@ -1481,53 +1484,53 @@ class Y {
|
|
|
1481
1484
|
* @param options
|
|
1482
1485
|
*/
|
|
1483
1486
|
static async mergeSpeeds(e, t = {}) {
|
|
1484
|
-
var
|
|
1487
|
+
var m, c;
|
|
1485
1488
|
const a = {
|
|
1486
1489
|
hours: [],
|
|
1487
1490
|
wps: [],
|
|
1488
1491
|
days: []
|
|
1489
|
-
}, o = e.reduce((
|
|
1490
|
-
var
|
|
1491
|
-
return
|
|
1492
|
-
}, 0), i = e.reduce((
|
|
1493
|
-
var
|
|
1494
|
-
return
|
|
1495
|
-
}, 0), r = e.reduce((
|
|
1496
|
-
var
|
|
1497
|
-
return
|
|
1498
|
-
}, 0),
|
|
1499
|
-
let
|
|
1500
|
-
for (const
|
|
1501
|
-
|
|
1502
|
-
const
|
|
1503
|
-
|
|
1504
|
-
N && (
|
|
1505
|
-
}),
|
|
1506
|
-
N && (
|
|
1507
|
-
}),
|
|
1508
|
-
N && (
|
|
1509
|
-
})), F.cp =
|
|
1510
|
-
const P = [
|
|
1511
|
-
D === -1 ? (F.cp.segment = [P],
|
|
1512
|
-
var
|
|
1513
|
-
((
|
|
1514
|
-
}),
|
|
1515
|
-
var
|
|
1516
|
-
((
|
|
1517
|
-
}),
|
|
1518
|
-
var
|
|
1519
|
-
((
|
|
1492
|
+
}, o = e.reduce((f, h) => f + h.distance, 0), n = e.reduce((f, h) => {
|
|
1493
|
+
var g;
|
|
1494
|
+
return f + (((g = h.extend) == null ? void 0 : g.distanceInECA) || 0);
|
|
1495
|
+
}, 0), i = e.reduce((f, h) => f + h.totalHrs, 0), s = e.reduce((f, h) => {
|
|
1496
|
+
var g;
|
|
1497
|
+
return f + (((g = h.extend) == null ? void 0 : g.hoursInECA) || 0);
|
|
1498
|
+
}, 0), r = e.reduce((f, h) => {
|
|
1499
|
+
var g;
|
|
1500
|
+
return f + (((g = h.extend) == null ? void 0 : g.totalDgoConsInECA) || 0);
|
|
1501
|
+
}, 0), l = e.reduce((f, h) => f + h.wxFactor * h.totalHrs / i, 0), u = e.reduce((f, h) => f + h.cFactor * h.totalHrs / i, 0), d = e.reduce((f, h) => f + h.totalFoCons, 0), y = e.reduce((f, h) => f + h.totalDgoCons, 0), k = e.reduce((f, h) => f + h.cost.total, 0), b = e.reduce((f, h) => f + h.cost.hire, 0), S = e.reduce((f, h) => f + h.cost.bunker, 0), C = [], p = [];
|
|
1502
|
+
let v;
|
|
1503
|
+
for (const f of e) {
|
|
1504
|
+
p.push(...((m = f.extend) == null ? void 0 : m.eca) || []);
|
|
1505
|
+
const h = f.sample.hours, g = f.sample.wps, I = f.sample.days, F = h.at(0);
|
|
1506
|
+
v && (F.distanceFromPrevious = v.distanceFromPrevious, F.distanceFromStart = v.distanceFromStart, h.forEach((j, N) => {
|
|
1507
|
+
N && (j.distanceFromStart = j.distanceFromStart + v.distanceFromStart);
|
|
1508
|
+
}), g.at(0).distanceFromPrevious = v.distanceFromPrevious, g.at(0).distanceFromStart = v.distanceFromStart, g.forEach((j, N) => {
|
|
1509
|
+
N && (j.distanceFromStart = j.distanceFromStart + v.distanceFromStart);
|
|
1510
|
+
}), I.at(0).distanceFromPrevious = v.distanceFromPrevious, I.at(0).distanceFromStart = v.distanceFromStart, I.forEach((j, N) => {
|
|
1511
|
+
N && (j.distanceFromStart = j.distanceFromStart + v.distanceFromStart);
|
|
1512
|
+
})), F.cp = f.cost.cp;
|
|
1513
|
+
const P = [f.etd, f.eta], D = C.findIndex((j) => j.id === F.cp.id);
|
|
1514
|
+
D === -1 ? (F.cp.segment = [P], C.push(F.cp)) : C[D].segment.push(P), h.forEach((j) => {
|
|
1515
|
+
var R;
|
|
1516
|
+
((R = a.hours) == null ? void 0 : R.findIndex((W) => W.eta === j.eta)) === -1 && a.hours.push(j);
|
|
1517
|
+
}), g.forEach((j) => {
|
|
1518
|
+
var R;
|
|
1519
|
+
((R = a.wps) == null ? void 0 : R.findIndex((W) => W.eta === j.eta)) === -1 && a.wps.push(j);
|
|
1520
|
+
}), I.forEach((j) => {
|
|
1521
|
+
var R;
|
|
1522
|
+
((R = a == null ? void 0 : a.days) == null ? void 0 : R.findIndex((W) => W.eta === j.eta)) === -1 && a.days.push(j);
|
|
1520
1523
|
});
|
|
1521
|
-
const H = (
|
|
1522
|
-
H === -1 ? a.wps.push(F) : a.wps[H] = F,
|
|
1524
|
+
const H = (c = a.wps) == null ? void 0 : c.findIndex((j) => j.eta === F.eta);
|
|
1525
|
+
H === -1 ? a.wps.push(F) : a.wps[H] = F, v = h.at(-1);
|
|
1523
1526
|
}
|
|
1524
|
-
return a.wps.sort((
|
|
1525
|
-
const
|
|
1526
|
-
if (
|
|
1527
|
-
const
|
|
1528
|
-
|
|
1529
|
-
const D =
|
|
1530
|
-
|
|
1527
|
+
return a.wps.sort((f, h) => w(f.etd).unix() - w(h.etd).unix()), a.wps.forEach((f, h) => {
|
|
1528
|
+
const g = a.wps[h - 1];
|
|
1529
|
+
if (g) {
|
|
1530
|
+
const I = f.distanceFromStart - (g.distanceFromStart || 0), F = w(f.eta || f.etd).diff(w(g.etd || g.eta), "hour", !0), P = Math.round(I / F * 100) / 100;
|
|
1531
|
+
f.avgSpd = P;
|
|
1532
|
+
const D = O.calculateBearing(g, f);
|
|
1533
|
+
g.bearing = D;
|
|
1531
1534
|
}
|
|
1532
1535
|
}), {
|
|
1533
1536
|
sample: a,
|
|
@@ -1540,18 +1543,18 @@ class Y {
|
|
|
1540
1543
|
distance: Math.round(o * 1e3) / 1e3,
|
|
1541
1544
|
totalHrs: Math.round(i * 1e3) / 1e3,
|
|
1542
1545
|
avgSpeed: Math.round(o / i * 1e3) / 1e3,
|
|
1543
|
-
wxFactor: Math.round(
|
|
1544
|
-
cFactor: Math.round(
|
|
1546
|
+
wxFactor: Math.round(l * 1e3) / 1e3,
|
|
1547
|
+
cFactor: Math.round(u * 1e3) / 1e3,
|
|
1545
1548
|
totalFoCons: Math.round(d * 1e3) / 1e3,
|
|
1546
1549
|
totalDgoCons: Math.round(y * 1e3) / 1e3,
|
|
1547
1550
|
cost: {
|
|
1548
|
-
total: Math.round(
|
|
1549
|
-
hire: Math.round(
|
|
1550
|
-
bunker: Math.round(
|
|
1551
|
+
total: Math.round(k * 1e3) / 1e3,
|
|
1552
|
+
hire: Math.round(b * 1e3) / 1e3,
|
|
1553
|
+
bunker: Math.round(S * 1e3) / 1e3
|
|
1551
1554
|
},
|
|
1552
1555
|
extend: {
|
|
1553
|
-
cps:
|
|
1554
|
-
eca:
|
|
1556
|
+
cps: C,
|
|
1557
|
+
eca: p,
|
|
1555
1558
|
distanceInECA: Math.round(n * 1e3) / 1e3,
|
|
1556
1559
|
hoursInECA: Math.round(s * 1e3) / 1e3,
|
|
1557
1560
|
totalDgoConsInECA: Math.round(r * 1e3) / 1e3,
|
|
@@ -1567,7 +1570,7 @@ export {
|
|
|
1567
1570
|
Ft as HifleetImpl,
|
|
1568
1571
|
pt as LoadCondition,
|
|
1569
1572
|
xt as MyShipImpl,
|
|
1570
|
-
|
|
1573
|
+
jt as MyVesselImpl,
|
|
1571
1574
|
Nt as ShipxyImpl,
|
|
1572
1575
|
Y as SpeedHelper,
|
|
1573
1576
|
vt as SpeedLabel,
|