@idm-plugin/vessel 3.4.8 → 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 +626 -623
- 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");
|
|
@@ -63,25 +63,25 @@ class Tt extends at {
|
|
|
63
63
|
this.clientId = t, this.clientSecret = a;
|
|
64
64
|
}
|
|
65
65
|
async authToken(t = {}) {
|
|
66
|
-
const a = "https://svc.data.myvessel.cn/ada/oauth/token",
|
|
66
|
+
const a = "https://svc.data.myvessel.cn/ada/oauth/token", o = {
|
|
67
67
|
searchParams: {
|
|
68
68
|
client_id: this.clientId,
|
|
69
69
|
client_secret: this.clientSecret,
|
|
70
70
|
grant_type: "client_credentials"
|
|
71
71
|
}
|
|
72
|
-
}, n = await B.post(a,
|
|
72
|
+
}, n = await B.post(a, o).json();
|
|
73
73
|
M == null || M.info("[%s] fetch access token from: %s - %j", t.requestId, a, n), n.error || (this.token = {
|
|
74
74
|
accessToken: n.access_token,
|
|
75
75
|
tokenType: n.token_type,
|
|
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
|
* 模糊查询
|
|
@@ -91,7 +91,7 @@ class Tt extends at {
|
|
|
91
91
|
async suggest(t, a = {}) {
|
|
92
92
|
var s, r;
|
|
93
93
|
await this.checkToken(a);
|
|
94
|
-
const
|
|
94
|
+
const o = "https://market.myvessel.cn/sdc/v1/mkt/vessels/fuzzy", n = {
|
|
95
95
|
headers: {
|
|
96
96
|
Authorization: `${(s = this.token) == null ? void 0 : s.tokenType} ${(r = this.token) == null ? void 0 : r.accessToken}`
|
|
97
97
|
},
|
|
@@ -100,18 +100,18 @@ class Tt extends at {
|
|
|
100
100
|
recordNum: a.ps || 10
|
|
101
101
|
}
|
|
102
102
|
};
|
|
103
|
-
M == null || M.info("[%s] fetch suggest vessels from: %s - %j", a.requestId,
|
|
104
|
-
const
|
|
105
|
-
return
|
|
106
|
-
mmsi:
|
|
107
|
-
name:
|
|
108
|
-
nameCn:
|
|
109
|
-
imo: Number.isNaN(
|
|
110
|
-
callSign:
|
|
111
|
-
type:
|
|
112
|
-
flagName:
|
|
103
|
+
M == null || M.info("[%s] fetch suggest vessels from: %s - %j", a.requestId, o, n);
|
|
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((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,13 +120,13 @@ class Tt 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
|
-
const
|
|
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
|
-
searchParams:
|
|
129
|
+
searchParams: i
|
|
130
130
|
};
|
|
131
131
|
M == null || M.info("[%s] fetch vessel from: %s - %j", a.requestId, n, s);
|
|
132
132
|
const r = await B.get(n, s).json();
|
|
@@ -164,7 +164,7 @@ class Tt extends at {
|
|
|
164
164
|
async archives(t, a = {}) {
|
|
165
165
|
var s, r;
|
|
166
166
|
await this.checkToken(a);
|
|
167
|
-
const
|
|
167
|
+
const o = "https://svc.data.myvessel.cn/sdc/v1/ship/info/batch", n = {
|
|
168
168
|
headers: {
|
|
169
169
|
Authorization: `${(s = this.token) == null ? void 0 : s.tokenType} ${(r = this.token) == null ? void 0 : r.accessToken}`
|
|
170
170
|
},
|
|
@@ -172,28 +172,28 @@ class Tt extends at {
|
|
|
172
172
|
mmsiList: typeof t == "number" ? [t] : t
|
|
173
173
|
}
|
|
174
174
|
};
|
|
175
|
-
M == null || M.info("[%s] fetch vessel archive from: %s - %j", a.requestId,
|
|
176
|
-
const
|
|
177
|
-
return
|
|
175
|
+
M == null || M.info("[%s] fetch vessel archive from: %s - %j", a.requestId, o, n);
|
|
176
|
+
const i = await B.post(o, n).json();
|
|
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
|
-
const
|
|
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
|
};
|
|
188
|
-
M == null || M.info("[%s] fetch realtime position from: %s - %j", a.requestId,
|
|
189
|
-
const
|
|
190
|
-
if (
|
|
191
|
-
return M == null || M.warn("[%s] fetch realtime position failed: %j", a.requestId, { message:
|
|
192
|
-
const s =
|
|
193
|
-
for (const
|
|
194
|
-
!isNaN(s[
|
|
188
|
+
M == null || M.info("[%s] fetch realtime position from: %s - %j", a.requestId, o, n);
|
|
189
|
+
const i = await B.get(o, n).json();
|
|
190
|
+
if (i.code)
|
|
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
|
+
const s = i.data;
|
|
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 Tt 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 Tt 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 {};
|
|
@@ -236,35 +236,39 @@ class Tt extends at {
|
|
|
236
236
|
* @param excludeSeas 排除水域, [sea.code]
|
|
237
237
|
* @param options { requiretId: '请求ID', useAIModel: '启用AI算法', withECA: '是否计算低硫区航行距离', withSpecial: '是否计算穿越的特战区列表和海盗区列表', draught: '最大吃水' }
|
|
238
238
|
*/
|
|
239
|
-
async calculateRoute(t, a,
|
|
240
|
-
var
|
|
241
|
-
const r =
|
|
239
|
+
async calculateRoute(t, a, o, n, i, s = {}) {
|
|
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 Tt 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,62 +330,62 @@ class Tt 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
|
-
async trajectory(t, a,
|
|
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
|
-
async trajectoryIn30Day(t, a,
|
|
345
|
-
var
|
|
346
|
-
const
|
|
348
|
+
async trajectoryIn30Day(t, a, o, n, i, s, r = {}) {
|
|
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,
|
|
352
356
|
startTime: a.utcOffset(8).format("YYYY-MM-DD HH:mm:ss"),
|
|
353
|
-
endTime:
|
|
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
|
}
|
|
@@ -392,20 +396,20 @@ class Ft extends at {
|
|
|
392
396
|
this.token = t;
|
|
393
397
|
}
|
|
394
398
|
async realTimePosition(t, a = {}) {
|
|
395
|
-
const
|
|
399
|
+
const o = "https://api.hifleet.com/position/position/get/token", n = {
|
|
396
400
|
searchParams: {
|
|
397
401
|
mmsi: t,
|
|
398
402
|
usertoken: this.token
|
|
399
403
|
}
|
|
400
|
-
},
|
|
401
|
-
M == null || M.info("[%s] fetch realtime position from: %s - %j", a.requestId,
|
|
402
|
-
const s =
|
|
404
|
+
}, i = await B.post(o, n).json();
|
|
405
|
+
M == null || M.info("[%s] fetch realtime position from: %s - %j", a.requestId, o, n);
|
|
406
|
+
const s = i == null ? void 0 : i.list;
|
|
403
407
|
if (!s)
|
|
404
|
-
return M == null || M.warn("[%s] fetch realtime position failed: %j", a.requestId,
|
|
405
|
-
for (const
|
|
406
|
-
!isNaN(s[
|
|
408
|
+
return M == null || M.warn("[%s] fetch realtime position failed: %j", a.requestId, o, i), i;
|
|
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,14 +433,14 @@ 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
|
};
|
|
437
441
|
}
|
|
438
442
|
async search(t, a = {}) {
|
|
439
|
-
let
|
|
443
|
+
let o = "https://www.hifleet.com/hifleetapi/searchVesselOL.do";
|
|
440
444
|
const n = {
|
|
441
445
|
searchParams: {
|
|
442
446
|
keyword: t
|
|
@@ -447,24 +451,24 @@ class Ft extends at {
|
|
|
447
451
|
Host: "www.hifleet.com"
|
|
448
452
|
}
|
|
449
453
|
};
|
|
450
|
-
let
|
|
451
|
-
M == null || M.info("[%s] fetch vessel props from: %s - %j", a.requestId,
|
|
452
|
-
for (const r in
|
|
453
|
-
!isNaN(
|
|
454
|
+
let i = await B.post(o, n).json();
|
|
455
|
+
M == null || M.info("[%s] fetch vessel props from: %s - %j", a.requestId, o, n), i instanceof Array && (i = i[0]);
|
|
456
|
+
for (const r in i)
|
|
457
|
+
!isNaN(i[r]) && Number(i[r]) !== 1 / 0 && (i[r] = Number(i[r]));
|
|
454
458
|
const s = {
|
|
455
|
-
mmsi:
|
|
456
|
-
name:
|
|
457
|
-
imo:
|
|
458
|
-
callSign:
|
|
459
|
-
length:
|
|
460
|
-
breadth:
|
|
461
|
-
draught:
|
|
462
|
-
type:
|
|
459
|
+
mmsi: i.m,
|
|
460
|
+
name: i.n,
|
|
461
|
+
imo: i.i,
|
|
462
|
+
callSign: i.c,
|
|
463
|
+
length: i.l,
|
|
464
|
+
breadth: i.b,
|
|
465
|
+
draught: i.dr,
|
|
466
|
+
type: i.t
|
|
463
467
|
};
|
|
464
|
-
return
|
|
468
|
+
return o = "https://www.hifleet.com/hifleetapi/sameShipSearch.do", i = await B.post(o, n).json(), M == null || M.info("[%s] search vessel dead weight from: %s - %j", a.requestId, o, n), i instanceof Array && (i = i[0]), i && (s.deadweight = Number(i.dwt)), s;
|
|
465
469
|
}
|
|
466
470
|
async suggest(t, a = {}) {
|
|
467
|
-
const
|
|
471
|
+
const o = "https://www.hifleet.com/hifleetapi/getShipSuggest.do", n = {
|
|
468
472
|
searchParams: {
|
|
469
473
|
q: t
|
|
470
474
|
},
|
|
@@ -473,10 +477,10 @@ class Ft extends at {
|
|
|
473
477
|
Origin: "https://www.hifleet.com",
|
|
474
478
|
Host: "www.hifleet.com"
|
|
475
479
|
}
|
|
476
|
-
},
|
|
477
|
-
M == null || M.info("[%s] suggest vessel props from: %s - %j", a.requestId,
|
|
480
|
+
}, i = await B.post(o, n).json();
|
|
481
|
+
M == null || M.info("[%s] suggest vessel props from: %s - %j", a.requestId, o, n);
|
|
478
482
|
const s = [];
|
|
479
|
-
for (const r of
|
|
483
|
+
for (const r of i)
|
|
480
484
|
s.push({
|
|
481
485
|
mmsi: !r.mmsi || isNaN(r.mmsi) ? null : Number(r.mmsi),
|
|
482
486
|
name: r.name,
|
|
@@ -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
|
-
async trajectory(t, a,
|
|
490
|
-
var
|
|
493
|
+
async trajectory(t, a, o, n, i = !0, s = {}) {
|
|
494
|
+
var m, c, f;
|
|
491
495
|
const r = await this.realTimePosition(t, s);
|
|
492
|
-
let
|
|
493
|
-
const
|
|
494
|
-
if (
|
|
495
|
-
let
|
|
496
|
-
|
|
496
|
+
let l = w(a);
|
|
497
|
+
const u = w(o), d = w();
|
|
498
|
+
if (i) {
|
|
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 {
|
|
@@ -544,19 +548,19 @@ class Nt extends at {
|
|
|
544
548
|
this.token = t;
|
|
545
549
|
}
|
|
546
550
|
async realTimePosition(t, a = {}) {
|
|
547
|
-
const
|
|
551
|
+
const o = {
|
|
548
552
|
searchParams: {
|
|
549
553
|
id: t,
|
|
550
554
|
k: this.token,
|
|
551
555
|
enc: 1
|
|
552
556
|
}
|
|
553
|
-
}, n = "https://api.shipxy.com/apicall/GetSingleShip",
|
|
554
|
-
if (M == null || M.info("[%s] fetch realtime position from: %s - %j", a.requestId, n,
|
|
555
|
-
return
|
|
556
|
-
const s =
|
|
557
|
+
}, n = "https://api.shipxy.com/apicall/GetSingleShip", i = await B.get(n, o).json();
|
|
558
|
+
if (M == null || M.info("[%s] fetch realtime position from: %s - %j", a.requestId, n, o), (i == null ? void 0 : i.status) !== 0)
|
|
559
|
+
return i;
|
|
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
|
-
async trajectory(t, a,
|
|
584
|
-
var
|
|
585
|
-
const r = await this.realTimePosition(t, s),
|
|
587
|
+
async trajectory(t, a, o, n, i = !0, 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 {
|
|
@@ -621,28 +625,28 @@ class xt extends at {
|
|
|
621
625
|
this.token = t;
|
|
622
626
|
}
|
|
623
627
|
async getShipId(t, a = {}) {
|
|
624
|
-
const
|
|
628
|
+
const o = {
|
|
625
629
|
headers: {
|
|
626
630
|
appKey: this.token
|
|
627
631
|
},
|
|
628
632
|
json: {
|
|
629
633
|
mmsiList: t
|
|
630
634
|
}
|
|
631
|
-
}, n = "https://api3.myships.com/sp/ships/getShipIdByMMSI",
|
|
632
|
-
return M == null || M.info("[%s] fetch ship id from: %s - %j", a.requestId, n,
|
|
635
|
+
}, n = "https://api3.myships.com/sp/ships/getShipIdByMMSI", i = await B.post(n, o).json();
|
|
636
|
+
return M == null || M.info("[%s] fetch ship id from: %s - %j", a.requestId, n, o), i.code !== "0" ? i : i.data[0].shipId;
|
|
633
637
|
}
|
|
634
638
|
async getShipInfo(t, a = {}) {
|
|
635
|
-
const
|
|
639
|
+
const o = {
|
|
636
640
|
headers: {
|
|
637
641
|
appKey: this.token
|
|
638
642
|
},
|
|
639
643
|
json: {
|
|
640
644
|
shipId: t
|
|
641
645
|
}
|
|
642
|
-
}, n = "https://api3.myships.com/sp/ships/aissta",
|
|
643
|
-
if (M == null || M.info("[%s] fetch ship info from: %s - %j", a.requestId, n,
|
|
644
|
-
return
|
|
645
|
-
const s =
|
|
646
|
+
}, n = "https://api3.myships.com/sp/ships/aissta", i = await B.post(n, o).json();
|
|
647
|
+
if (M == null || M.info("[%s] fetch ship info from: %s - %j", a.requestId, n, o), i.code !== "0")
|
|
648
|
+
return i;
|
|
649
|
+
const s = i.data;
|
|
646
650
|
let r = s.imo;
|
|
647
651
|
return t === "407170" && (r = "9198379", M == null || M.warn("[%s] ship(%s) imo error: %s, should be %s", a.requestId, t, s.imo, r)), {
|
|
648
652
|
mmsi: s.mmsi,
|
|
@@ -655,78 +659,78 @@ class xt extends at {
|
|
|
655
659
|
};
|
|
656
660
|
}
|
|
657
661
|
async realTimePosition(t, a = {}) {
|
|
658
|
-
const
|
|
662
|
+
const o = await this.getShipId(t, a), n = await this.getShipInfo(o, a), i = {
|
|
659
663
|
headers: {
|
|
660
664
|
appKey: this.token
|
|
661
665
|
},
|
|
662
666
|
json: {
|
|
663
|
-
shipId:
|
|
667
|
+
shipId: o
|
|
664
668
|
}
|
|
665
|
-
}, s = "https://api3.myships.com/sp/ships/position/latest", r = await B.post(s,
|
|
666
|
-
M == null || M.info("[%s] fetch realtime position from: %s - %j", a.requestId, s,
|
|
667
|
-
const
|
|
668
|
-
for (const
|
|
669
|
-
!isNaN(
|
|
670
|
-
const { labelCn:
|
|
669
|
+
}, s = "https://api3.myships.com/sp/ships/position/latest", r = await B.post(s, i).json();
|
|
670
|
+
M == null || M.info("[%s] fetch realtime position from: %s - %j", a.requestId, s, i);
|
|
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
|
-
async trajectory(t, a,
|
|
690
|
-
const r =
|
|
691
|
-
for (;
|
|
692
|
-
await this.trajectoryIn30Day(
|
|
693
|
-
return await this.trajectoryIn30Day(
|
|
693
|
+
async trajectory(t, a, o, n, i = !0, s = {}) {
|
|
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,
|
|
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
|
},
|
|
701
705
|
json: {
|
|
702
706
|
shipId: t,
|
|
703
707
|
startTime: a,
|
|
704
|
-
endTime:
|
|
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
|
-
mmsi:
|
|
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:
|
|
721
|
+
mmsi: i,
|
|
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,23 +752,23 @@ 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
|
-
const a = new RegExp("(?<=\\[)(.+)(?=])", "g"),
|
|
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
|
-
const
|
|
757
|
-
for (let
|
|
758
|
-
const d = (
|
|
759
|
-
if (
|
|
760
|
-
|
|
760
|
+
const i = {};
|
|
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)
|
|
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
|
-
return
|
|
771
|
+
return i;
|
|
768
772
|
}
|
|
769
773
|
/**
|
|
770
774
|
* 解析单一告警规则
|
|
@@ -773,9 +777,9 @@ class Mt {
|
|
|
773
777
|
* @param options
|
|
774
778
|
*/
|
|
775
779
|
parseRule(e, t = {}) {
|
|
776
|
-
var
|
|
780
|
+
var i;
|
|
777
781
|
J == null || J.debug("[%s] parse rule: %s", t.requestId, e), e = e.startsWith("[") ? e : `[${e}`, e = e.endsWith("]") ? e : `${e}]`;
|
|
778
|
-
const a = new RegExp("(?<=\\[)(.+?)(?=])", "g"),
|
|
782
|
+
const a = new RegExp("(?<=\\[)(.+?)(?=])", "g"), o = (i = e == null ? void 0 : e.match(a)) == null ? void 0 : i[0], n = o == null ? void 0 : o.split(",");
|
|
779
783
|
if (n) {
|
|
780
784
|
let s = n[3] === "Number.MAX_VALUE" ? 100 : Number(n[3]);
|
|
781
785
|
return s = isNaN(s) ? 1 : s, {
|
|
@@ -794,20 +798,20 @@ class Mt {
|
|
|
794
798
|
* @param options
|
|
795
799
|
*/
|
|
796
800
|
checkWeather(e, t, a = {}) {
|
|
797
|
-
var
|
|
798
|
-
let
|
|
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, { ...
|
|
801
|
+
var b, S, C, p, v, m, c, f, h, g, I, F, P, D, H;
|
|
802
|
+
let o = 0, n = 0, i = 0, s = 0;
|
|
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
|
|
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
|
}
|
|
@@ -826,11 +830,11 @@ class Y {
|
|
|
826
830
|
* @param draught 吃水 m
|
|
827
831
|
* @return [0.55, 0.85]
|
|
828
832
|
*/
|
|
829
|
-
static blockCoefficient(e, t, a,
|
|
830
|
-
let n = Math.round(e / (t * a *
|
|
833
|
+
static blockCoefficient(e, t, a, o) {
|
|
834
|
+
let n = Math.round(e / (t * a * o) * 100) / 100;
|
|
831
835
|
n = n < 0.55 ? 0.55 : n > 0.85 ? 0.85 : n;
|
|
832
|
-
const
|
|
833
|
-
return
|
|
836
|
+
const i = [0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85], s = i.map((r) => Math.abs(r - n));
|
|
837
|
+
return i[s.indexOf(Math.min(...s))];
|
|
834
838
|
}
|
|
835
839
|
/**
|
|
836
840
|
* @see https://baike.baidu.com/item/%E5%BC%97%E5%8A%B3%E5%BE%B7%E6%95%B0/228891?fromModule=search-result_lemma-recommend
|
|
@@ -844,8 +848,8 @@ class Y {
|
|
|
844
848
|
* @return [0.05, 0.30]
|
|
845
849
|
*/
|
|
846
850
|
static froudeNumber(e, t, a = 9.8) {
|
|
847
|
-
let
|
|
848
|
-
return
|
|
851
|
+
let o = Math.round(Math.sqrt(e * e / (a * t)) * 100) / 100;
|
|
852
|
+
return o = o < 0.05 ? 0.05 : o > 0.3 ? 0.3 : o, o;
|
|
849
853
|
}
|
|
850
854
|
/**
|
|
851
855
|
* 失速修正系數
|
|
@@ -855,7 +859,7 @@ class Y {
|
|
|
855
859
|
* @private
|
|
856
860
|
*/
|
|
857
861
|
static amendFactor(e, t, a) {
|
|
858
|
-
const
|
|
862
|
+
const o = {
|
|
859
863
|
0.55: [1.7, -1.4, -7.4],
|
|
860
864
|
0.6: [2.2, -2.5, -9.7],
|
|
861
865
|
0.65: [2.6, -3.7, -11.6],
|
|
@@ -864,7 +868,7 @@ class Y {
|
|
|
864
868
|
0.8: [2.6, -13.1, -15.1],
|
|
865
869
|
0.85: [3.1, -18.7, 28]
|
|
866
870
|
};
|
|
867
|
-
let
|
|
871
|
+
let i = {
|
|
868
872
|
0.55: [1.7, -1.4, -7.4],
|
|
869
873
|
0.6: [2.2, -2.5, -9.7],
|
|
870
874
|
0.65: [2.6, -3.7, -11.6],
|
|
@@ -873,7 +877,7 @@ class Y {
|
|
|
873
877
|
0.8: [3, -16.3, -21.6],
|
|
874
878
|
0.85: [3.4, -20.9, 31.8]
|
|
875
879
|
}[e];
|
|
876
|
-
return a === "Laden" && (
|
|
880
|
+
return a === "Laden" && (i = o[e]), i[0] + i[1] * t + i[2] * Math.pow(t, 2);
|
|
877
881
|
}
|
|
878
882
|
/**
|
|
879
883
|
* 失速方向因子
|
|
@@ -902,9 +906,9 @@ class Y {
|
|
|
902
906
|
* @param kts
|
|
903
907
|
* @private
|
|
904
908
|
*/
|
|
905
|
-
static vesselTagFactor(e, t, a,
|
|
909
|
+
static vesselTagFactor(e, t, a, o) {
|
|
906
910
|
let n;
|
|
907
|
-
return a === "container" ? n = 0.7 *
|
|
911
|
+
return a === "container" ? n = 0.7 * o / 2 + Math.pow(o, 3) / (22 * Math.pow(e, 2 / 3)) : t === "Ballast" ? n = 0.7 * o / 2 + Math.pow(o, 3) / (2.7 * Math.pow(e, 2 / 3)) : n = 0.5 * o / 2 + Math.pow(o, 3) / (2.7 * Math.pow(e, 2 / 3)), n;
|
|
908
912
|
}
|
|
909
913
|
/**
|
|
910
914
|
* 浪高影响因子
|
|
@@ -925,21 +929,21 @@ class Y {
|
|
|
925
929
|
* @param bearing 方位角
|
|
926
930
|
* @private
|
|
927
931
|
*/
|
|
928
|
-
static assembleProperties(e, t, a,
|
|
932
|
+
static assembleProperties(e, t, a, o) {
|
|
929
933
|
var y;
|
|
930
|
-
const n = e.lbp ?? e.length ?? e.lengthOverall ?? 198.9642,
|
|
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
|
-
draught:
|
|
939
|
+
draught: i,
|
|
936
940
|
breadthMoulded: s,
|
|
937
941
|
// 排水量(吨)= 载重量(吨)/ 1.025 + 吃水(米)× 船舶型宽(米)× 船舶型长(米)× 0.7
|
|
938
942
|
// 其中,1.025是指海水的密度,吨是指公吨,吃水是指船舶的最大吃水深度。船舶型宽是指船舶的最大型宽,船舶型长是指船舶的设计型长。上述公式是针对常规船舶适用的,不同类型的船舶可能会有一些差异。
|
|
939
|
-
displacement: Math.round((r / 1.025 +
|
|
943
|
+
displacement: Math.round((r / 1.025 + i * s * n * 0.7) * 1e4) / 1e4,
|
|
940
944
|
// 换算为m/s
|
|
941
945
|
speed: Math.round((a ?? 14.1382) * 1852 / 3600 * 1e4) / 1e4,
|
|
942
|
-
bearing:
|
|
946
|
+
bearing: o || 90
|
|
943
947
|
};
|
|
944
948
|
}
|
|
945
949
|
/**
|
|
@@ -953,41 +957,41 @@ class Y {
|
|
|
953
957
|
* @param useRouteParam true 启用设置速度
|
|
954
958
|
* @param options
|
|
955
959
|
*/
|
|
956
|
-
static async speedLoseAt(e, t, a,
|
|
957
|
-
let
|
|
958
|
-
if (t.velocity && s && (e.speed = z.roundPrecision(t.velocity * 1852 / 3600, 6)),
|
|
959
|
-
let
|
|
960
|
+
static async speedLoseAt(e, t, a, o = "", n = 2, i = !0, s = !1, r = {}) {
|
|
961
|
+
let l;
|
|
962
|
+
if (t.velocity && s && (e.speed = z.roundPrecision(t.velocity * 1852 / 3600, 6)), i) {
|
|
963
|
+
let u;
|
|
960
964
|
try {
|
|
961
|
-
|
|
962
|
-
const { weatherModels:
|
|
965
|
+
o = (o == null ? void 0 : o.toUpperCase()) === "CMEMS" ? "ECMWF" : o, o = (o == null ? void 0 : o.toUpperCase()) === "METEO2" ? "best_match" : o;
|
|
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,
|
|
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 (
|
|
1018
|
-
|
|
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 =
|
|
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,10 +1062,10 @@ class Y {
|
|
|
1058
1062
|
* @param role 1: 船东, 2: 租家, 0: 未知
|
|
1059
1063
|
*/
|
|
1060
1064
|
static currentFactor(e, t, a = 0) {
|
|
1061
|
-
const
|
|
1062
|
-
if (Math.abs(
|
|
1065
|
+
const o = O.includedAngle(e, (t == null ? void 0 : t.degree) || 0) / 180 * Math.PI;
|
|
1066
|
+
if (Math.abs(o) === Math.PI / 2)
|
|
1063
1067
|
return 0;
|
|
1064
|
-
let n = ((t == null ? void 0 : t.kts) || 0) * Math.cos(
|
|
1068
|
+
let n = ((t == null ? void 0 : t.kts) || 0) * Math.cos(o);
|
|
1065
1069
|
return a & 2 ? n = Math.ceil(n * 100) / 100 : a & 1 ? n = Math.floor(n * 100) / 100 : n = Math.round(n * 100) / 100, Math.abs(n) > 5 ? 0 : n;
|
|
1066
1070
|
}
|
|
1067
1071
|
/**
|
|
@@ -1071,16 +1075,15 @@ class Y {
|
|
|
1071
1075
|
* @param cFactor 洋流因子
|
|
1072
1076
|
*/
|
|
1073
1077
|
static weatherFactor(e, t, a = 0) {
|
|
1074
|
-
var
|
|
1075
|
-
|
|
1076
|
-
const
|
|
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;
|
|
1078
|
+
var k, b, S, C, p, v, m;
|
|
1079
|
+
T == null || T.debug("calculate weather factor via: %j", { ...e, ...t });
|
|
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);
|
|
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,
|
|
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,
|
|
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,84 +1114,84 @@ class Y {
|
|
|
1111
1114
|
* @param useRouteParam
|
|
1112
1115
|
* @param options
|
|
1113
1116
|
*/
|
|
1114
|
-
static async analyseInstant(e, t, a,
|
|
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 */
|
|
1125
1128
|
} : {
|
|
1126
|
-
v0:
|
|
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 (;
|
|
1150
|
+
for (; f.length > 0; ) {
|
|
1148
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(
|
|
1149
|
-
|
|
1152
|
+
p,
|
|
1150
1153
|
t,
|
|
1151
1154
|
P,
|
|
1152
1155
|
V,
|
|
1153
|
-
c,
|
|
1154
|
-
m,
|
|
1155
|
-
o,
|
|
1156
|
-
r,
|
|
1157
1156
|
h,
|
|
1158
|
-
|
|
1157
|
+
f,
|
|
1158
|
+
i,
|
|
1159
|
+
r,
|
|
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 E =
|
|
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];
|
|
1175
1178
|
if (E) {
|
|
1176
|
-
const L = A.distanceFromStart - E.distanceFromStart, q =
|
|
1177
|
-
A.avgSpd = Math.round(L / q * 100) / 100, E.bearing =
|
|
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,
|
|
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 E =
|
|
1237
|
+
for (; m.length > 0; ) {
|
|
1238
|
+
const E = l - t.hour() % l;
|
|
1236
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 = E.distanceFromStart - q.distanceFromStart,
|
|
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 =
|
|
1252
|
+
const P = I.hours;
|
|
1250
1253
|
for (let E = 0; E < P.length - 1; E++) {
|
|
1251
|
-
const L =
|
|
1252
|
-
|
|
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((E, L) => E + (L.suspend || 0), 0), H =
|
|
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,动态计算最优成本(租金+油费)方案
|
|
@@ -1294,59 +1297,59 @@ class Y {
|
|
|
1294
1297
|
* @param lane 基础航线(重要转向点)
|
|
1295
1298
|
* @param options
|
|
1296
1299
|
*/
|
|
1297
|
-
static async analyseCost(e, t, a,
|
|
1298
|
-
var
|
|
1299
|
-
const
|
|
1300
|
+
static async analyseCost(e, t, a, o, n = {}) {
|
|
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交替计算各种组合下的成本
|
|
@@ -1358,24 +1361,24 @@ class Y {
|
|
|
1358
1361
|
* @param step 步长,7,4,2,1
|
|
1359
1362
|
* @param options
|
|
1360
1363
|
*/
|
|
1361
|
-
static async combinedAnalyse(e, t, a,
|
|
1362
|
-
s.counter = 1,
|
|
1363
|
-
const r = await Y.alternateAnalyse(e, t, a,
|
|
1364
|
-
|
|
1365
|
-
cost:
|
|
1366
|
-
hire:
|
|
1364
|
+
static async combinedAnalyse(e, t, a, o, n, i, s = {}) {
|
|
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索引,交替计算指定步长下的成本
|
|
@@ -1388,44 +1391,44 @@ class Y {
|
|
|
1388
1391
|
* @param step 步长,7,4,2,1
|
|
1389
1392
|
* @param options
|
|
1390
1393
|
*/
|
|
1391
|
-
static async alternateAnalyse(e, t, a,
|
|
1392
|
-
var y,
|
|
1393
|
-
let
|
|
1394
|
-
const
|
|
1395
|
-
for (;
|
|
1396
|
-
const
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
g,
|
|
1400
|
-
t,
|
|
1394
|
+
static async alternateAnalyse(e, t, a, o, n, i, s, r = {}) {
|
|
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
|
}
|
|
@@ -1438,15 +1441,15 @@ class Y {
|
|
|
1438
1441
|
* @param props
|
|
1439
1442
|
* @param options
|
|
1440
1443
|
*/
|
|
1441
|
-
static async calculateCost(e, t, a,
|
|
1444
|
+
static async calculateCost(e, t, a, o = {}) {
|
|
1442
1445
|
var n;
|
|
1443
1446
|
if (e) {
|
|
1444
|
-
const
|
|
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,22 +1460,22 @@ class Y {
|
|
|
1457
1460
|
*
|
|
1458
1461
|
*/
|
|
1459
1462
|
static async calculateECA(e, t, a = {}) {
|
|
1460
|
-
var r,
|
|
1461
|
-
const
|
|
1462
|
-
let n = 0,
|
|
1463
|
-
(
|
|
1464
|
-
y.positionTime =
|
|
1463
|
+
var r, l, u, d;
|
|
1464
|
+
const o = await O.intersectInECA((e == null ? void 0 : e.route) || []);
|
|
1465
|
+
let n = 0, i = 0, s = 0;
|
|
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
|
-
for (const y of
|
|
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
|
-
return n = z.roundPrecision(n, 3),
|
|
1474
|
+
return n = z.roundPrecision(n, 3), i = z.roundPrecision(i, 3), s = z.roundPrecision(s, 3), {
|
|
1472
1475
|
distanceInECA: n,
|
|
1473
|
-
hoursInECA:
|
|
1476
|
+
hoursInECA: i,
|
|
1474
1477
|
totalDgoConsInECA: s,
|
|
1475
|
-
eca:
|
|
1478
|
+
eca: o
|
|
1476
1479
|
};
|
|
1477
1480
|
}
|
|
1478
1481
|
/**
|
|
@@ -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
|
-
},
|
|
1490
|
-
var
|
|
1491
|
-
return
|
|
1492
|
-
}, 0),
|
|
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,
|
|
@@ -1537,21 +1540,21 @@ class Y {
|
|
|
1537
1540
|
to: e.at(-1).to,
|
|
1538
1541
|
v0: e.at(0).v0,
|
|
1539
1542
|
label: "Combined",
|
|
1540
|
-
distance: Math.round(
|
|
1541
|
-
totalHrs: Math.round(
|
|
1542
|
-
avgSpeed: Math.round(
|
|
1543
|
-
wxFactor: Math.round(
|
|
1544
|
-
cFactor: Math.round(
|
|
1543
|
+
distance: Math.round(o * 1e3) / 1e3,
|
|
1544
|
+
totalHrs: Math.round(i * 1e3) / 1e3,
|
|
1545
|
+
avgSpeed: Math.round(o / i * 1e3) / 1e3,
|
|
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,
|