@idm-plugin/vessel 3.7.6 → 3.7.7
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/index.js +364 -362
- package/dist/index.umd.cjs +1 -1
- package/dist/speed/src/index.d.ts +2 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@ var mt = (x, e, t) => e in x ? ht(x, e, { enumerable: !0, configurable: !0, writ
|
|
|
3
3
|
var K = (x, e, t) => (mt(x, typeof e != "symbol" ? e + "" : e, t), t);
|
|
4
4
|
import z from "got";
|
|
5
5
|
import ut from "@log4js-node/log4js-api";
|
|
6
|
-
import
|
|
6
|
+
import p from "moment";
|
|
7
7
|
import { LaneHelper as R, LngLatHelper as J } from "@idm-plugin/geo2";
|
|
8
8
|
import { MeteoHelper2 as ft } from "@idm-plugin/meteo2";
|
|
9
9
|
import { Meteo2Assist as dt } from "@idm-plugin/meteo";
|
|
@@ -19,90 +19,90 @@ class nt {
|
|
|
19
19
|
* @param status
|
|
20
20
|
*/
|
|
21
21
|
parseStatus(e) {
|
|
22
|
-
let t,
|
|
22
|
+
let t, n;
|
|
23
23
|
switch (e) {
|
|
24
24
|
case 0:
|
|
25
|
-
t = "在航(主机推动)",
|
|
25
|
+
t = "在航(主机推动)", n = "Underway Using Engine";
|
|
26
26
|
break;
|
|
27
27
|
case 1:
|
|
28
|
-
t = "锚泊",
|
|
28
|
+
t = "锚泊", n = "Anchored";
|
|
29
29
|
break;
|
|
30
30
|
case 2:
|
|
31
|
-
t = "失控",
|
|
31
|
+
t = "失控", n = "Not under command";
|
|
32
32
|
break;
|
|
33
33
|
case 3:
|
|
34
|
-
t = "操纵受限",
|
|
34
|
+
t = "操纵受限", n = "Limited airworthiness";
|
|
35
35
|
break;
|
|
36
36
|
case 4:
|
|
37
|
-
t = "吃水受限",
|
|
37
|
+
t = "吃水受限", n = "Limited by ship's draft";
|
|
38
38
|
break;
|
|
39
39
|
case 5:
|
|
40
|
-
t = "靠泊",
|
|
40
|
+
t = "靠泊", n = "Mooring";
|
|
41
41
|
break;
|
|
42
42
|
case 6:
|
|
43
|
-
t = "搁浅",
|
|
43
|
+
t = "搁浅", n = "Stranded";
|
|
44
44
|
break;
|
|
45
45
|
case 7:
|
|
46
|
-
t = "捕捞作业",
|
|
46
|
+
t = "捕捞作业", n = "Engaged in fishing";
|
|
47
47
|
break;
|
|
48
48
|
case 8:
|
|
49
|
-
t = "靠帆船提供动力",
|
|
49
|
+
t = "靠帆船提供动力", n = "Sailing";
|
|
50
50
|
break;
|
|
51
51
|
default:
|
|
52
|
-
t = "未定义",
|
|
52
|
+
t = "未定义", n = "Undefined";
|
|
53
53
|
}
|
|
54
|
-
return { labelCn: t, labelEn:
|
|
54
|
+
return { labelCn: t, labelEn: n };
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
class Tt extends nt {
|
|
58
|
-
constructor(t,
|
|
58
|
+
constructor(t, n) {
|
|
59
59
|
super();
|
|
60
60
|
K(this, "clientId");
|
|
61
61
|
K(this, "clientSecret");
|
|
62
62
|
K(this, "token");
|
|
63
|
-
this.clientId = t, this.clientSecret =
|
|
63
|
+
this.clientId = t, this.clientSecret = n;
|
|
64
64
|
}
|
|
65
65
|
async authToken(t = {}) {
|
|
66
|
-
const
|
|
66
|
+
const n = "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
|
-
}, i = await z.post(
|
|
73
|
-
g == null || g.info("[%s] fetch access token from: %s - %j", t.requestId,
|
|
72
|
+
}, i = await z.post(n, o).json();
|
|
73
|
+
g == null || g.info("[%s] fetch access token from: %s - %j", t.requestId, n, i), i.error || (this.token = {
|
|
74
74
|
accessToken: i.access_token,
|
|
75
75
|
tokenType: i.token_type,
|
|
76
76
|
expiresIn: i.expires_in,
|
|
77
77
|
scope: i.scope,
|
|
78
78
|
jti: i.jti,
|
|
79
|
-
issuedAt:
|
|
79
|
+
issuedAt: p().utc().format()
|
|
80
80
|
});
|
|
81
81
|
}
|
|
82
82
|
async checkToken(t = {}) {
|
|
83
|
-
var
|
|
84
|
-
return (!this.token ||
|
|
83
|
+
var n;
|
|
84
|
+
return (!this.token || p().diff(p(this.token.issuedAt), "seconds") > (((n = this.token) == null ? void 0 : n.expiresIn) || 0) - 300) && await this.authToken(t), this.token;
|
|
85
85
|
}
|
|
86
86
|
/**
|
|
87
87
|
* 模糊查询
|
|
88
88
|
* @param kw
|
|
89
89
|
* @param options
|
|
90
90
|
*/
|
|
91
|
-
async suggest(t,
|
|
91
|
+
async suggest(t, n = {}) {
|
|
92
92
|
var s, r;
|
|
93
|
-
await this.checkToken(
|
|
93
|
+
await this.checkToken(n);
|
|
94
94
|
const o = "https://market.myvessel.cn/sdc/v1/mkt/vessels/fuzzy", i = {
|
|
95
95
|
headers: {
|
|
96
96
|
Authorization: `${(s = this.token) == null ? void 0 : s.tokenType} ${(r = this.token) == null ? void 0 : r.accessToken}`
|
|
97
97
|
},
|
|
98
98
|
json: {
|
|
99
99
|
kw: t,
|
|
100
|
-
recordNum:
|
|
100
|
+
recordNum: n.ps || 10
|
|
101
101
|
}
|
|
102
102
|
};
|
|
103
|
-
g == null || g.info("[%s] fetch suggest vessels from: %s - %j",
|
|
104
|
-
const
|
|
105
|
-
return
|
|
103
|
+
g == null || g.info("[%s] fetch suggest vessels from: %s - %j", n.requestId, o, i);
|
|
104
|
+
const a = await z.post(o, i).json();
|
|
105
|
+
return a.status !== 200 ? (g == null || g.warn("[%s] fetch suggest vessels failed: %j", n.requestId, { message: a.message, status: a.status, code: a.code }), []) : (a.data || []).map((l) => ({
|
|
106
106
|
mmsi: l.mmsi,
|
|
107
107
|
name: l.nameEn,
|
|
108
108
|
nameCn: l.nameCn,
|
|
@@ -119,19 +119,19 @@ class Tt extends nt {
|
|
|
119
119
|
* @param imo
|
|
120
120
|
* @param options
|
|
121
121
|
*/
|
|
122
|
-
async search(t,
|
|
122
|
+
async search(t, n = {}) {
|
|
123
123
|
var u, l;
|
|
124
|
-
await this.checkToken(
|
|
125
|
-
const o = /^\d{7}$/.test(t.toString()), i = o ? "https://market.myvessel.cn/sdc/v1/mkt/vessels/detail/imo" : "https://market.myvessel.cn/sdc/v1/mkt/vessels/detail/mmsi",
|
|
124
|
+
await this.checkToken(n);
|
|
125
|
+
const o = /^\d{7}$/.test(t.toString()), i = o ? "https://market.myvessel.cn/sdc/v1/mkt/vessels/detail/imo" : "https://market.myvessel.cn/sdc/v1/mkt/vessels/detail/mmsi", a = o ? { imo: t } : { mmsi: t }, s = {
|
|
126
126
|
headers: {
|
|
127
127
|
Authorization: `${(u = this.token) == null ? void 0 : u.tokenType} ${(l = this.token) == null ? void 0 : l.accessToken}`
|
|
128
128
|
},
|
|
129
|
-
searchParams:
|
|
129
|
+
searchParams: a
|
|
130
130
|
};
|
|
131
|
-
g == null || g.info("[%s] fetch vessel from: %s - %j",
|
|
131
|
+
g == null || g.info("[%s] fetch vessel from: %s - %j", n.requestId, i, s);
|
|
132
132
|
const r = await z.get(i, s).json();
|
|
133
133
|
if (r.status !== 200)
|
|
134
|
-
return g == null || g.warn("[%s] fetch suggest vessels failed: %j",
|
|
134
|
+
return g == null || g.warn("[%s] fetch suggest vessels failed: %j", n.requestId, { message: r.message, status: r.status, code: r.code }), {};
|
|
135
135
|
{
|
|
136
136
|
const h = r.data;
|
|
137
137
|
if (h)
|
|
@@ -161,9 +161,9 @@ class Tt extends nt {
|
|
|
161
161
|
}
|
|
162
162
|
return {};
|
|
163
163
|
}
|
|
164
|
-
async archives(t,
|
|
164
|
+
async archives(t, n = {}) {
|
|
165
165
|
var s, r;
|
|
166
|
-
await this.checkToken(
|
|
166
|
+
await this.checkToken(n);
|
|
167
167
|
const o = "https://svc.data.myvessel.cn/sdc/v1/ship/info/batch", i = {
|
|
168
168
|
headers: {
|
|
169
169
|
Authorization: `${(s = this.token) == null ? void 0 : s.tokenType} ${(r = this.token) == null ? void 0 : r.accessToken}`
|
|
@@ -172,28 +172,28 @@ class Tt extends nt {
|
|
|
172
172
|
mmsiList: typeof t == "number" ? [t] : t
|
|
173
173
|
}
|
|
174
174
|
};
|
|
175
|
-
g == null || g.info("[%s] fetch vessel archive from: %s - %j",
|
|
176
|
-
const
|
|
177
|
-
return
|
|
175
|
+
g == null || g.info("[%s] fetch vessel archive from: %s - %j", n.requestId, o, i);
|
|
176
|
+
const a = await z.post(o, i).json();
|
|
177
|
+
return a.status !== 200 ? (g == null || g.warn("[%s] fetch vessel archive failed: %j", n.requestId, { message: a.message, status: a.status, code: a.code }), {}) : a.data;
|
|
178
178
|
}
|
|
179
|
-
async realTimePosition(t,
|
|
179
|
+
async realTimePosition(t, n = {}) {
|
|
180
180
|
var r, u;
|
|
181
|
-
await this.checkToken(
|
|
181
|
+
await this.checkToken(n);
|
|
182
182
|
const o = "https://svc.data.myvessel.cn/sdc/v1/vessels/status/location/unit", i = {
|
|
183
183
|
headers: {
|
|
184
184
|
Authorization: `${(r = this.token) == null ? void 0 : r.tokenType} ${(u = this.token) == null ? void 0 : u.accessToken}`
|
|
185
185
|
},
|
|
186
186
|
searchParams: { mmsi: t }
|
|
187
187
|
};
|
|
188
|
-
g == null || g.info("[%s] fetch realtime position from: %s - %j",
|
|
189
|
-
const
|
|
190
|
-
if (
|
|
191
|
-
return g == null || g.warn("[%s] fetch realtime position failed: %j",
|
|
192
|
-
const s =
|
|
188
|
+
g == null || g.info("[%s] fetch realtime position from: %s - %j", n.requestId, o, i);
|
|
189
|
+
const a = await z.get(o, i).json();
|
|
190
|
+
if (a.code)
|
|
191
|
+
return g == null || g.warn("[%s] fetch realtime position failed: %j", n.requestId, { message: a.message, status: a.status, code: a.code }), a;
|
|
192
|
+
const s = a.data;
|
|
193
193
|
for (const l in s)
|
|
194
194
|
!isNaN(s[l]) && Number(s[l]) !== 1 / 0 && (s[l] = Number(s[l]));
|
|
195
195
|
if (s) {
|
|
196
|
-
const l =
|
|
196
|
+
const l = p(`${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,7 +208,7 @@ class Tt extends nt {
|
|
|
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) ? p.utc(s.eta).format() : void 0,
|
|
212
212
|
destination: s.dest,
|
|
213
213
|
positionTime: l.unix(),
|
|
214
214
|
status: s.status,
|
|
@@ -236,9 +236,9 @@ class Tt extends nt {
|
|
|
236
236
|
* @param excludeSeas 排除水域, [sea.code]
|
|
237
237
|
* @param options { requiretId: '请求ID', useAIModel: '启用AI算法', withECA: '是否计算低硫区航行距离', withSpecial: '是否计算穿越的特战区列表和海盗区列表', draught: '最大吃水' }
|
|
238
238
|
*/
|
|
239
|
-
async calculateRoute(t,
|
|
239
|
+
async calculateRoute(t, n, o, i, a, s = {}) {
|
|
240
240
|
var I, b, E;
|
|
241
|
-
const r =
|
|
241
|
+
const r = p();
|
|
242
242
|
await this.checkToken(s);
|
|
243
243
|
const u = "https://market.myvessel.cn/sdc/v1/mkt/routes/plan", l = {
|
|
244
244
|
maxDraught: s.draught || 10,
|
|
@@ -249,10 +249,10 @@ class Tt extends nt {
|
|
|
249
249
|
t.code && (l.startPortCode = t.code), t.lng !== void 0 && t.lat !== void 0 && (l.startPoint = {
|
|
250
250
|
lon: t.lng,
|
|
251
251
|
lat: t.lat
|
|
252
|
-
}),
|
|
253
|
-
lon:
|
|
254
|
-
lat:
|
|
255
|
-
}), o != null && o.length && (l.crossMonthList = o), i != null && i.length && (l.excludeNodes = i),
|
|
252
|
+
}), n.code && (l.endPortCode = n.code), n.lng !== void 0 && n.lat !== void 0 && (l.endPoint = {
|
|
253
|
+
lon: n.lng,
|
|
254
|
+
lat: n.lat
|
|
255
|
+
}), o != null && o.length && (l.crossMonthList = o), i != null && i.length && (l.excludeNodes = i), a != null && a.length && (l.excludeSeaAreas = a);
|
|
256
256
|
const h = {
|
|
257
257
|
headers: {
|
|
258
258
|
Authorization: `${(I = this.token) == null ? void 0 : I.tokenType} ${(b = this.token) == null ? void 0 : b.accessToken}`
|
|
@@ -273,8 +273,8 @@ class Tt extends nt {
|
|
|
273
273
|
route: [],
|
|
274
274
|
distance: 0,
|
|
275
275
|
memo: ""
|
|
276
|
-
}, { nodes:
|
|
277
|
-
k.nodes =
|
|
276
|
+
}, { nodes: w, seas: v, tracks: m, specialRegions: c, ecaLength: f } = d.data;
|
|
277
|
+
k.nodes = w == null ? void 0 : w.map((M) => ({
|
|
278
278
|
code: M.nodeCode,
|
|
279
279
|
nameEn: M.nameEn,
|
|
280
280
|
nameCn: M.nameCn,
|
|
@@ -330,26 +330,26 @@ class Tt extends nt {
|
|
|
330
330
|
lat: Math.round(M.lat * 1e5) / 1e5,
|
|
331
331
|
lng: Math.round(M.lon * 1e5) / 1e5
|
|
332
332
|
})), (E = k.waypoints) != null && E.length && (k.waypoints = R.simplifyCoordinates(k.waypoints), k.route = R.divideAccordingToLng(k.waypoints), k.distance = R.calculateRouteDistance(k.route), k.distanceInECA = f);
|
|
333
|
-
const
|
|
334
|
-
return k.memo = `time cost: ${
|
|
333
|
+
const S = p().diff(r, "second");
|
|
334
|
+
return k.memo = `time cost: ${S}s`, g.info("[%s] calculate route cost: %d seconds", s.requestId, S), k;
|
|
335
335
|
}
|
|
336
336
|
}
|
|
337
|
-
async trajectory(t,
|
|
337
|
+
async trajectory(t, n, o, i, a = !0, s = {}) {
|
|
338
338
|
await this.checkToken(s);
|
|
339
|
-
const r = await this.realTimePosition(t, s), u =
|
|
339
|
+
const r = await this.realTimePosition(t, s), u = p(n), l = p(o), h = [];
|
|
340
340
|
for (; l.diff(u, "day", !0) > 30; )
|
|
341
341
|
await this.trajectoryIn30Day(t, u, u.clone().add(30, "day"), r, i, h, s), u.add(30, "day");
|
|
342
342
|
return await this.trajectoryIn30Day(t, u, l, r, i, h, s), h;
|
|
343
343
|
}
|
|
344
|
-
async trajectoryIn30Day(t,
|
|
345
|
-
var b, E, k,
|
|
344
|
+
async trajectoryIn30Day(t, n, o, i, a, s, r = {}) {
|
|
345
|
+
var b, E, k, w, v;
|
|
346
346
|
const u = "https://svc.data.myvessel.cn/sdc/v1/vessels/status/track", l = {
|
|
347
347
|
headers: {
|
|
348
348
|
Authorization: `${(b = this.token) == null ? void 0 : b.tokenType} ${(E = this.token) == null ? void 0 : E.accessToken}`
|
|
349
349
|
},
|
|
350
350
|
json: {
|
|
351
351
|
mmsi: t,
|
|
352
|
-
startTime:
|
|
352
|
+
startTime: n.utcOffset(8).format("YYYY-MM-DD HH:mm:ss"),
|
|
353
353
|
endTime: o.utcOffset(8).format("YYYY-MM-DD HH:mm:ss")
|
|
354
354
|
}
|
|
355
355
|
};
|
|
@@ -358,11 +358,11 @@ class Tt extends nt {
|
|
|
358
358
|
if (h.code)
|
|
359
359
|
return g == null || g.warn("[%s] fetch trajectory failed: %j", r.requestId, u, { message: h.message, status: h.status, code: h.code }), h;
|
|
360
360
|
let d = -1;
|
|
361
|
-
const I =
|
|
361
|
+
const I = p(`${(w = (k = h.data) == null ? void 0 : k[0]) == null ? void 0 : w.postime} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
362
362
|
return (v = h.data) == null || v.forEach((m) => {
|
|
363
363
|
for (const N in m)
|
|
364
364
|
!isNaN(m[N]) && Number(m[N]) !== 1 / 0 && (m[N] = Number(m[N]));
|
|
365
|
-
const c =
|
|
365
|
+
const c = p(`${m.postime} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00"), f = m.status, { labelCn: y, labelEn: S } = this.parseStatus(f), M = {
|
|
366
366
|
mmsi: m.mmsi,
|
|
367
367
|
imo: i == null ? void 0 : i.imo,
|
|
368
368
|
lat: m.lat,
|
|
@@ -372,15 +372,15 @@ class Tt extends nt {
|
|
|
372
372
|
hdg: m.hdg,
|
|
373
373
|
draught: m.draught,
|
|
374
374
|
status: f,
|
|
375
|
-
eta: /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(m.eta) ?
|
|
375
|
+
eta: /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(m.eta) ? p(`${m.eta} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00").utc().format() : void 0,
|
|
376
376
|
destination: m.dest,
|
|
377
377
|
positionTime: c.unix(),
|
|
378
378
|
labelCn: y,
|
|
379
|
-
labelEn:
|
|
379
|
+
labelEn: S,
|
|
380
380
|
method: "trajectory",
|
|
381
381
|
vendor: "myVessel",
|
|
382
382
|
utc: c.utc().format()
|
|
383
|
-
}, j = Math.floor(c.diff(I, "minute", !0) / (
|
|
383
|
+
}, j = Math.floor(c.diff(I, "minute", !0) / (a || 1));
|
|
384
384
|
j !== d && (d = j, s.push(M));
|
|
385
385
|
}), s;
|
|
386
386
|
}
|
|
@@ -391,21 +391,21 @@ class jt extends nt {
|
|
|
391
391
|
K(this, "token");
|
|
392
392
|
this.token = t;
|
|
393
393
|
}
|
|
394
|
-
async realTimePosition(t,
|
|
394
|
+
async realTimePosition(t, n = {}) {
|
|
395
395
|
const o = "https://api.hifleet.com/position/position/get/token", i = {
|
|
396
396
|
searchParams: {
|
|
397
397
|
mmsi: t,
|
|
398
398
|
usertoken: this.token
|
|
399
399
|
}
|
|
400
|
-
},
|
|
401
|
-
g == null || g.info("[%s] fetch realtime position from: %s - %j",
|
|
402
|
-
const s =
|
|
400
|
+
}, a = await z.post(o, i).json();
|
|
401
|
+
g == null || g.info("[%s] fetch realtime position from: %s - %j", n.requestId, o, i);
|
|
402
|
+
const s = a == null ? void 0 : a.list;
|
|
403
403
|
if (!s)
|
|
404
|
-
return g == null || g.warn("[%s] fetch realtime position failed: %j",
|
|
404
|
+
return g == null || g.warn("[%s] fetch realtime position failed: %j", n.requestId, o, a), a;
|
|
405
405
|
for (const I in s)
|
|
406
406
|
!isNaN(s[I]) && Number(s[I]) !== 1 / 0 && (s[I] = Number(s[I]));
|
|
407
407
|
s.status = s.sp > 3 ? 0 : 1;
|
|
408
|
-
const r = s.status, { labelCn: u, labelEn: l } = this.parseStatus(r), h =
|
|
408
|
+
const r = s.status, { labelCn: u, labelEn: l } = this.parseStatus(r), h = p(`${s.ti} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
409
409
|
return {
|
|
410
410
|
mmsi: s.m,
|
|
411
411
|
name: s.n,
|
|
@@ -420,7 +420,7 @@ class jt extends nt {
|
|
|
420
420
|
cog: s.co,
|
|
421
421
|
hdg: s.h,
|
|
422
422
|
rot: isNaN(s.rot) ? 0 : s.rot,
|
|
423
|
-
eta: /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(s.eta) ?
|
|
423
|
+
eta: /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(s.eta) ? p.utc(s.eta).format() : void 0,
|
|
424
424
|
destination: s.destination,
|
|
425
425
|
vesselType: s.type,
|
|
426
426
|
dwt: s.dwt,
|
|
@@ -435,7 +435,7 @@ class jt extends nt {
|
|
|
435
435
|
vendor: "hifleet"
|
|
436
436
|
};
|
|
437
437
|
}
|
|
438
|
-
async search(t,
|
|
438
|
+
async search(t, n = {}) {
|
|
439
439
|
let o = "https://www.hifleet.com/hifleetapi/searchVesselOL.do";
|
|
440
440
|
const i = {
|
|
441
441
|
searchParams: {
|
|
@@ -447,23 +447,23 @@ class jt extends nt {
|
|
|
447
447
|
Host: "www.hifleet.com"
|
|
448
448
|
}
|
|
449
449
|
};
|
|
450
|
-
let
|
|
451
|
-
g == null || g.info("[%s] fetch vessel props from: %s - %j",
|
|
452
|
-
for (const r in
|
|
453
|
-
!isNaN(
|
|
450
|
+
let a = await z.post(o, i).json();
|
|
451
|
+
g == null || g.info("[%s] fetch vessel props from: %s - %j", n.requestId, o, i), a instanceof Array && (a = a[0]);
|
|
452
|
+
for (const r in a)
|
|
453
|
+
!isNaN(a[r]) && Number(a[r]) !== 1 / 0 && (a[r] = Number(a[r]));
|
|
454
454
|
const s = {
|
|
455
|
-
mmsi:
|
|
456
|
-
name:
|
|
457
|
-
imo:
|
|
458
|
-
callSign:
|
|
459
|
-
length:
|
|
460
|
-
breadth:
|
|
461
|
-
draught:
|
|
462
|
-
type:
|
|
455
|
+
mmsi: a.m,
|
|
456
|
+
name: a.n,
|
|
457
|
+
imo: a.i,
|
|
458
|
+
callSign: a.c,
|
|
459
|
+
length: a.l,
|
|
460
|
+
breadth: a.b,
|
|
461
|
+
draught: a.dr,
|
|
462
|
+
type: a.t
|
|
463
463
|
};
|
|
464
|
-
return o = "https://www.hifleet.com/hifleetapi/sameShipSearch.do",
|
|
464
|
+
return o = "https://www.hifleet.com/hifleetapi/sameShipSearch.do", a = await z.post(o, i).json(), g == null || g.info("[%s] search vessel dead weight from: %s - %j", n.requestId, o, i), a instanceof Array && (a = a[0]), a && (s.deadweight = Number(a.dwt)), s;
|
|
465
465
|
}
|
|
466
|
-
async suggest(t,
|
|
466
|
+
async suggest(t, n = {}) {
|
|
467
467
|
const o = "https://www.hifleet.com/hifleetapi/getShipSuggest.do", i = {
|
|
468
468
|
searchParams: {
|
|
469
469
|
q: t
|
|
@@ -473,10 +473,10 @@ class jt extends nt {
|
|
|
473
473
|
Origin: "https://www.hifleet.com",
|
|
474
474
|
Host: "www.hifleet.com"
|
|
475
475
|
}
|
|
476
|
-
},
|
|
477
|
-
g == null || g.info("[%s] suggest vessel props from: %s - %j",
|
|
476
|
+
}, a = await z.post(o, i).json();
|
|
477
|
+
g == null || g.info("[%s] suggest vessel props from: %s - %j", n.requestId, o, i);
|
|
478
478
|
const s = [];
|
|
479
|
-
for (const r of
|
|
479
|
+
for (const r of a)
|
|
480
480
|
s.push({
|
|
481
481
|
mmsi: !r.mmsi || isNaN(r.mmsi) ? null : Number(r.mmsi),
|
|
482
482
|
name: r.name,
|
|
@@ -486,12 +486,12 @@ class jt extends nt {
|
|
|
486
486
|
});
|
|
487
487
|
return s.sort((r, u) => u.score - r.score), s;
|
|
488
488
|
}
|
|
489
|
-
async trajectory(t,
|
|
489
|
+
async trajectory(t, n, o, i, a = !0, s = {}) {
|
|
490
490
|
var m, c, f;
|
|
491
491
|
const r = await this.realTimePosition(t, s);
|
|
492
|
-
let u =
|
|
493
|
-
const l =
|
|
494
|
-
if (
|
|
492
|
+
let u = p(n);
|
|
493
|
+
const l = p(o), h = p();
|
|
494
|
+
if (a) {
|
|
495
495
|
let y = l.diff(u, "d", !0);
|
|
496
496
|
y < 0 ? u = l.clone().subtract(40, "d") : y < 30 ? u.subtract(10, "d") : y < 60 ? u.subtract(5, "d") : u = l.clone().subtract(80, "d"), y = h.diff(l, "d", !0), l.add(y > 10 ? 240 : y * 24, "h");
|
|
497
497
|
}
|
|
@@ -507,12 +507,12 @@ class jt extends nt {
|
|
|
507
507
|
let E;
|
|
508
508
|
b && (E = ((c = (m = b.ships) == null ? void 0 : m.offors) == null ? void 0 : c.ship) || [], E.length || g == null || g.warn("[%s] fetch trajectory failed: %j", s.requestId, b));
|
|
509
509
|
const k = [];
|
|
510
|
-
let
|
|
511
|
-
const v =
|
|
510
|
+
let w = -1;
|
|
511
|
+
const v = p(`${(f = E == null ? void 0 : E[0]) == null ? void 0 : f.ti} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
512
512
|
for (const y of E) {
|
|
513
513
|
for (const L in y)
|
|
514
514
|
!isNaN(y[L]) && Number(y[L]) !== 1 / 0 && (y[L] = Number(y[L]));
|
|
515
|
-
const
|
|
515
|
+
const S = p(`${y.ti} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
516
516
|
y.status = y.sp > 4 ? 0 : 1;
|
|
517
517
|
const { labelEn: M, labelCn: j } = this.parseStatus(y.status), N = {
|
|
518
518
|
mmsi: y.m,
|
|
@@ -524,15 +524,15 @@ class jt extends nt {
|
|
|
524
524
|
sog: y.sp,
|
|
525
525
|
cog: y.co,
|
|
526
526
|
hdg: y.hdg,
|
|
527
|
-
positionTime:
|
|
528
|
-
utc:
|
|
527
|
+
positionTime: S.unix(),
|
|
528
|
+
utc: S.utc().format(),
|
|
529
529
|
status: y.status,
|
|
530
530
|
labelCn: j,
|
|
531
531
|
labelEn: M,
|
|
532
532
|
method: "trajectory",
|
|
533
533
|
vendor: "hifleet"
|
|
534
|
-
}, D = Math.floor(
|
|
535
|
-
D !==
|
|
534
|
+
}, D = Math.floor(S.diff(v, "minute", !0) / (i || 1));
|
|
535
|
+
D !== w && (w = D, k.push(N));
|
|
536
536
|
}
|
|
537
537
|
return k;
|
|
538
538
|
}
|
|
@@ -543,20 +543,20 @@ class xt extends nt {
|
|
|
543
543
|
K(this, "token");
|
|
544
544
|
this.token = t;
|
|
545
545
|
}
|
|
546
|
-
async realTimePosition(t,
|
|
546
|
+
async realTimePosition(t, n = {}) {
|
|
547
547
|
const o = {
|
|
548
548
|
searchParams: {
|
|
549
549
|
id: t,
|
|
550
550
|
k: this.token,
|
|
551
551
|
enc: 1
|
|
552
552
|
}
|
|
553
|
-
}, i = "https://api.shipxy.com/apicall/GetSingleShip",
|
|
554
|
-
if (g == null || g.info("[%s] fetch realtime position from: %s - %j",
|
|
555
|
-
return
|
|
556
|
-
const s =
|
|
553
|
+
}, i = "https://api.shipxy.com/apicall/GetSingleShip", a = await z.get(i, o).json();
|
|
554
|
+
if (g == null || g.info("[%s] fetch realtime position from: %s - %j", n.requestId, i, o), (a == null ? void 0 : a.status) !== 0)
|
|
555
|
+
return a;
|
|
556
|
+
const s = a.data[0];
|
|
557
557
|
for (const d in s)
|
|
558
558
|
!isNaN(s[d]) && Number(s[d]) !== 1 / 0 && (s[d] = Number(s[d]));
|
|
559
|
-
const { labelCn: r, labelEn: u } = await this.parseStatus(s.navistat), l =
|
|
559
|
+
const { labelCn: r, labelEn: u } = await this.parseStatus(s.navistat), l = p.unix(s.lasttime);
|
|
560
560
|
return {
|
|
561
561
|
mmsi: s.ShipID,
|
|
562
562
|
name: s.name,
|
|
@@ -580,9 +580,9 @@ class xt extends nt {
|
|
|
580
580
|
vendor: "shipxy"
|
|
581
581
|
};
|
|
582
582
|
}
|
|
583
|
-
async trajectory(t,
|
|
583
|
+
async trajectory(t, n, o, i, a = !0, s = {}) {
|
|
584
584
|
var v;
|
|
585
|
-
const r = await this.realTimePosition(t, s), u =
|
|
585
|
+
const r = await this.realTimePosition(t, s), u = p(n), l = p(o), h = "https://api.shipxy.com/apicall/GetShipTrack", d = {
|
|
586
586
|
searchParams: {
|
|
587
587
|
id: t,
|
|
588
588
|
k: this.token,
|
|
@@ -594,10 +594,10 @@ class xt extends nt {
|
|
|
594
594
|
}, I = await z.get(h, d).json();
|
|
595
595
|
if (g == null || g.info("[%s] fetch trajectory from: %s - %j", s.requestId, h, d), (I == null ? void 0 : I.status) !== 0)
|
|
596
596
|
return I;
|
|
597
|
-
const b = I == null ? void 0 : I.points, E = [], k =
|
|
598
|
-
let
|
|
597
|
+
const b = I == null ? void 0 : I.points, E = [], k = p.unix((v = b[0]) == null ? void 0 : v.utc);
|
|
598
|
+
let w = -1;
|
|
599
599
|
for (const m of b) {
|
|
600
|
-
const c =
|
|
600
|
+
const c = p.unix(m.utc), f = {
|
|
601
601
|
imo: r == null ? void 0 : r.imo,
|
|
602
602
|
mmsi: t,
|
|
603
603
|
sog: Math.round(m.sog * 3600 / 1e3 / 1852 * 100) / 100,
|
|
@@ -609,7 +609,7 @@ class xt extends nt {
|
|
|
609
609
|
method: "trajectory",
|
|
610
610
|
vendor: "shipxy"
|
|
611
611
|
}, y = Math.floor(c.diff(k, "minute", !0) / (i || 1));
|
|
612
|
-
y !==
|
|
612
|
+
y !== w && (w = y, E.push(f));
|
|
613
613
|
}
|
|
614
614
|
return E;
|
|
615
615
|
}
|
|
@@ -620,7 +620,7 @@ class Nt extends nt {
|
|
|
620
620
|
K(this, "token");
|
|
621
621
|
this.token = t;
|
|
622
622
|
}
|
|
623
|
-
async getShipId(t,
|
|
623
|
+
async getShipId(t, n = {}) {
|
|
624
624
|
const o = {
|
|
625
625
|
headers: {
|
|
626
626
|
appKey: this.token
|
|
@@ -628,10 +628,10 @@ class Nt extends nt {
|
|
|
628
628
|
json: {
|
|
629
629
|
mmsiList: t
|
|
630
630
|
}
|
|
631
|
-
}, i = "https://api3.myships.com/sp/ships/getShipIdByMMSI",
|
|
632
|
-
return g == null || g.info("[%s] fetch ship id from: %s - %j",
|
|
631
|
+
}, i = "https://api3.myships.com/sp/ships/getShipIdByMMSI", a = await z.post(i, o).json();
|
|
632
|
+
return g == null || g.info("[%s] fetch ship id from: %s - %j", n.requestId, i, o), a.code !== "0" ? a : a.data[0].shipId;
|
|
633
633
|
}
|
|
634
|
-
async getShipInfo(t,
|
|
634
|
+
async getShipInfo(t, n = {}) {
|
|
635
635
|
const o = {
|
|
636
636
|
headers: {
|
|
637
637
|
appKey: this.token
|
|
@@ -639,12 +639,12 @@ class Nt extends nt {
|
|
|
639
639
|
json: {
|
|
640
640
|
shipId: t
|
|
641
641
|
}
|
|
642
|
-
}, i = "https://api3.myships.com/sp/ships/aissta",
|
|
643
|
-
if (g == null || g.info("[%s] fetch ship info from: %s - %j",
|
|
644
|
-
return
|
|
645
|
-
const s =
|
|
642
|
+
}, i = "https://api3.myships.com/sp/ships/aissta", a = await z.post(i, o).json();
|
|
643
|
+
if (g == null || g.info("[%s] fetch ship info from: %s - %j", n.requestId, i, o), a.code !== "0")
|
|
644
|
+
return a;
|
|
645
|
+
const s = a.data;
|
|
646
646
|
let r = s.imo;
|
|
647
|
-
return t === "407170" && (r = "9198379", g == null || g.warn("[%s] ship(%s) imo error: %s, should be %s",
|
|
647
|
+
return t === "407170" && (r = "9198379", g == null || g.warn("[%s] ship(%s) imo error: %s, should be %s", n.requestId, t, s.imo, r)), {
|
|
648
648
|
mmsi: s.mmsi,
|
|
649
649
|
name: s.shipnameEn,
|
|
650
650
|
imo: r,
|
|
@@ -654,20 +654,20 @@ class Nt extends nt {
|
|
|
654
654
|
draught: (s.draught || 100) / 10
|
|
655
655
|
};
|
|
656
656
|
}
|
|
657
|
-
async realTimePosition(t,
|
|
658
|
-
const o = await this.getShipId(t,
|
|
657
|
+
async realTimePosition(t, n = {}) {
|
|
658
|
+
const o = await this.getShipId(t, n), i = await this.getShipInfo(o, n), a = {
|
|
659
659
|
headers: {
|
|
660
660
|
appKey: this.token
|
|
661
661
|
},
|
|
662
662
|
json: {
|
|
663
663
|
shipId: o
|
|
664
664
|
}
|
|
665
|
-
}, s = "https://api3.myships.com/sp/ships/position/latest", r = await z.post(s,
|
|
666
|
-
g == null || g.info("[%s] fetch realtime position from: %s - %j",
|
|
665
|
+
}, s = "https://api3.myships.com/sp/ships/position/latest", r = await z.post(s, a).json();
|
|
666
|
+
g == null || g.info("[%s] fetch realtime position from: %s - %j", n.requestId, s, a);
|
|
667
667
|
const u = r.data[0];
|
|
668
668
|
for (const b in u)
|
|
669
669
|
!isNaN(u[b]) && Number(u[b]) !== 1 / 0 && (u[b] = Number(u[b]));
|
|
670
|
-
const { labelCn: l, labelEn: h } = await this.parseStatus(u.aisNavStatus), d =
|
|
670
|
+
const { labelCn: l, labelEn: h } = await this.parseStatus(u.aisNavStatus), d = p.unix(u.posTime);
|
|
671
671
|
return {
|
|
672
672
|
...i,
|
|
673
673
|
mmsi: t,
|
|
@@ -686,13 +686,13 @@ class Nt extends nt {
|
|
|
686
686
|
vendor: "myship"
|
|
687
687
|
};
|
|
688
688
|
}
|
|
689
|
-
async trajectory(t,
|
|
690
|
-
const r =
|
|
689
|
+
async trajectory(t, n, o, i, a = !0, s = {}) {
|
|
690
|
+
const r = p(n), u = p(o), l = await this.getShipId(t), h = await this.getShipInfo(l), d = [];
|
|
691
691
|
for (; u.diff(r, "day", !0) > 30; )
|
|
692
692
|
await this.trajectoryIn30Day(l, r.unix(), r.add(30, "day").unix(), h, t, i, d);
|
|
693
693
|
return await this.trajectoryIn30Day(l, r.unix(), u.unix(), h, t, i, d), d;
|
|
694
694
|
}
|
|
695
|
-
async trajectoryIn30Day(t,
|
|
695
|
+
async trajectoryIn30Day(t, n, o, i, a, s, r, u = {}) {
|
|
696
696
|
var k;
|
|
697
697
|
const l = {
|
|
698
698
|
headers: {
|
|
@@ -700,27 +700,27 @@ class Nt extends nt {
|
|
|
700
700
|
},
|
|
701
701
|
json: {
|
|
702
702
|
shipId: t,
|
|
703
|
-
startTime:
|
|
703
|
+
startTime: n,
|
|
704
704
|
endTime: o
|
|
705
705
|
}
|
|
706
706
|
}, h = "https://api3.myships.com/sp/ships/position/history", d = await z.post(h, l).json();
|
|
707
707
|
if (g == null || g.info("[%s] fetch trajectory from: %s - %j", u.requestId, h, l), d.code !== "0")
|
|
708
708
|
return g == null || g.warn("[%s] invoke myship trajectory failed: %j", u.requestId, d), d;
|
|
709
709
|
const I = d.data;
|
|
710
|
-
for (const
|
|
711
|
-
!isNaN(I[
|
|
712
|
-
const b =
|
|
710
|
+
for (const w in I)
|
|
711
|
+
!isNaN(I[w]) && Number(I[w]) !== 1 / 0 && (I[w] = Number(I[w]));
|
|
712
|
+
const b = p.unix((k = I[0]) == null ? void 0 : k.posTime);
|
|
713
713
|
let E = -1;
|
|
714
|
-
for (const
|
|
715
|
-
const v =
|
|
714
|
+
for (const w of I) {
|
|
715
|
+
const v = p.unix(w.posTime), m = {
|
|
716
716
|
imo: i == null ? void 0 : i.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(
|
|
717
|
+
mmsi: a,
|
|
718
|
+
lat: Math.round(w.lat / 1e4 / 60 * 1e5) / 1e5,
|
|
719
|
+
lng: Math.round(w.lon / 1e4 / 60 * 1e5) / 1e5,
|
|
720
|
+
sog: Math.round(w.sog / 10 * 100) / 100,
|
|
721
|
+
cog: Math.round(w.cog / 10 * 100) / 100,
|
|
722
|
+
hdg: Math.round(w.heading * 100) / 100,
|
|
723
|
+
rot: Math.round(w.rot * 100) / 100,
|
|
724
724
|
positionTime: v.unix(),
|
|
725
725
|
utc: v.utc().format(),
|
|
726
726
|
method: "trajectory",
|
|
@@ -750,21 +750,21 @@ class Mt {
|
|
|
750
750
|
parsePrinciple(e, t = {}) {
|
|
751
751
|
var s, r, u;
|
|
752
752
|
_ == null || _.debug("[%s] parse rule: %s", t.requestId, e);
|
|
753
|
-
const
|
|
753
|
+
const n = new RegExp("(?<=\\[)(.+)(?=])", "g"), o = e.match(n) ? (s = e.match(n)) == null ? void 0 : s[0] : void 0, i = o == null ? void 0 : o.split(";");
|
|
754
754
|
if (!i)
|
|
755
755
|
return;
|
|
756
|
-
const
|
|
756
|
+
const a = {};
|
|
757
757
|
for (let l = 0; l < (i == null ? void 0 : i.length); l++) {
|
|
758
|
-
const h = (u = (r = i[l].match(
|
|
758
|
+
const h = (u = (r = i[l].match(n)) == null ? void 0 : r[0]) == null ? void 0 : u.split("],");
|
|
759
759
|
if (l === 0 && !h)
|
|
760
|
-
|
|
760
|
+
a.scope = i[0];
|
|
761
761
|
else if (h)
|
|
762
762
|
for (let d = 0, I = h.length; d < I; d++) {
|
|
763
763
|
const b = this.parseRule(h[d]);
|
|
764
|
-
b && (
|
|
764
|
+
b && (a[b.level] ? b.key ? a[b.level][b == null ? void 0 : b.key] = b : a[b.level] = b : b.key ? a[b.level] = { [b == null ? void 0 : b.key]: b } : a[b.level] = b);
|
|
765
765
|
}
|
|
766
766
|
}
|
|
767
|
-
return
|
|
767
|
+
return a;
|
|
768
768
|
}
|
|
769
769
|
/**
|
|
770
770
|
* 解析单一告警规则
|
|
@@ -773,9 +773,9 @@ class Mt {
|
|
|
773
773
|
* @param options
|
|
774
774
|
*/
|
|
775
775
|
parseRule(e, t = {}) {
|
|
776
|
-
var
|
|
776
|
+
var a;
|
|
777
777
|
_ == null || _.debug("[%s] parse rule: %s", t.requestId, e), e = e.startsWith("[") ? e : `[${e}`, e = e.endsWith("]") ? e : `${e}]`;
|
|
778
|
-
const
|
|
778
|
+
const n = new RegExp("(?<=\\[)(.+?)(?=])", "g"), o = (a = e == null ? void 0 : e.match(n)) == null ? void 0 : a[0], i = o == null ? void 0 : o.split(",");
|
|
779
779
|
if (i) {
|
|
780
780
|
let s = i[3] === "Number.MAX_VALUE" ? 100 : Number(i[3]);
|
|
781
781
|
return s = isNaN(s) ? 1 : s, {
|
|
@@ -793,26 +793,26 @@ class Mt {
|
|
|
793
793
|
* @param principle 告警规则
|
|
794
794
|
* @param options
|
|
795
795
|
*/
|
|
796
|
-
checkWeather(e, t,
|
|
797
|
-
var b, E, k,
|
|
798
|
-
let o = 0, i = 0,
|
|
799
|
-
const r = Math.round(((E = (b = t == null ? void 0 : t.SEVERE) == null ? void 0 : b.sigWave) == null ? void 0 : E.number) * 1.6 * 100) / 100, u = (
|
|
796
|
+
checkWeather(e, t, n = {}) {
|
|
797
|
+
var b, E, k, w, v, m, c, f, y, S, M, j, N, D, L;
|
|
798
|
+
let o = 0, i = 0, a = 0, s = 0;
|
|
799
|
+
const r = Math.round(((E = (b = t == null ? void 0 : t.SEVERE) == null ? void 0 : b.sigWave) == null ? void 0 : E.number) * 1.6 * 100) / 100, u = (w = (k = t == null ? void 0 : t.SEVERE) == null ? void 0 : k.sigWave) == null ? void 0 : w.number, l = (m = (v = t == null ? void 0 : t.HEAVY) == null ? void 0 : v.sigWave) == null ? void 0 : m.number, h = Math.round((((f = (c = t == null ? void 0 : t.SEVERE) == null ? void 0 : c.wind) == null ? void 0 : f.number) + 2) * 100) / 100, d = (S = (y = t == null ? void 0 : t.SEVERE) == null ? void 0 : y.wind) == null ? void 0 : S.number, I = (j = (M = t == null ? void 0 : t.HEAVY) == null ? void 0 : M.wind) == null ? void 0 : j.number;
|
|
800
800
|
for (let W = 0; W < (e == null ? void 0 : e.length); W++) {
|
|
801
|
-
const
|
|
802
|
-
s = V > s ? V : s, _ == null || _.debug("[%s] check sig.wave: %j",
|
|
801
|
+
const F = e[W], Y = (D = (N = F == null ? void 0 : F.meteo) == null ? void 0 : N.wave) == null ? void 0 : D.sig, A = (L = F == null ? void 0 : F.meteo) == null ? void 0 : L.wind, V = W ? p(F.eta).diff(p(e[W - 1].eta), "hour", !0) : 0;
|
|
802
|
+
s = V > s ? V : s, _ == null || _.debug("[%s] check sig.wave: %j", n.requestId, { ...Y, dgThd4Wv: r, svThd4Wv: u, hvThd4Wv: l }), (Y == null ? void 0 : Y.height) >= r ? F.isDangerous = !0 : (Y == null ? void 0 : Y.height) >= u ? F.isSevere = !0 : (Y == null ? void 0 : Y.height) >= l && (F.isHeavy = !0), _ == null || _.debug("[%s] check wind: %j", n.requestId, { ...A, dgThd4Wd: h, svThd4Wd: d, hvThd4Wd: I }), (A == null ? void 0 : A.scale) >= h ? (F.isDangerous = !0, delete F.isSevere, delete F.isHeavy) : (A == null ? void 0 : A.scale) > d ? (F.isDangerous || (F.isSevere = !0), delete F.isHeavy) : (A == null ? void 0 : A.scale) === I && !F.isDangerous && !F.isSevere && (F.isHeavy = !0), o += F.isDangerous ? V : 0, i += F.isSevere ? V : 0, a += F.isHeavy ? V : 0;
|
|
803
803
|
}
|
|
804
|
-
return o = Math.round(o * 100) / 100, i = Math.round(i * 100) / 100,
|
|
804
|
+
return o = Math.round(o * 100) / 100, i = Math.round(i * 100) / 100, a = Math.round(a * 100) / 100, s = Math.round(s), { sample: e, dangerous: o, severe: i, heavy: a, step: s < 3 ? 3 : s, wind: { dgThd4Wd: h, svThd4Wd: d, hvThd4Wd: I }, sig: { dgThd4Wv: r, svThd4Wv: u, hvThd4Wv: l } };
|
|
805
805
|
}
|
|
806
806
|
}
|
|
807
807
|
const Dt = new Mt();
|
|
808
|
-
let
|
|
808
|
+
let C;
|
|
809
809
|
try {
|
|
810
|
-
|
|
810
|
+
C = ut.getLogger("vessel");
|
|
811
811
|
} catch {
|
|
812
812
|
} finally {
|
|
813
813
|
}
|
|
814
814
|
const gt = new ft("", !0);
|
|
815
|
-
var bt = /* @__PURE__ */ ((x) => (x.common = "common", x.container = "container", x.tugs = "tugs", x))(bt || {}), vt = /* @__PURE__ */ ((x) => (x.Ballast = "Ballast", x.Laden = "Laden", x))(vt || {}),
|
|
815
|
+
var bt = /* @__PURE__ */ ((x) => (x.common = "common", x.container = "container", x.tugs = "tugs", x))(bt || {}), vt = /* @__PURE__ */ ((x) => (x.Ballast = "Ballast", x.Laden = "Laden", x))(vt || {}), wt = /* @__PURE__ */ ((x) => (x.Cp = "CP", x.Perf = "Basis", x.Instruct = "Other", x))(wt || {});
|
|
816
816
|
class H {
|
|
817
817
|
/**
|
|
818
818
|
* @see https://baike.baidu.com/item/%E6%96%B9%E5%BD%A2%E7%B3%BB%E6%95%B0/4965568?fr=aladdin
|
|
@@ -826,11 +826,11 @@ class H {
|
|
|
826
826
|
* @param draught 吃水 m
|
|
827
827
|
* @return [0.55, 0.85]
|
|
828
828
|
*/
|
|
829
|
-
static blockCoefficient(e, t,
|
|
830
|
-
let i = Math.round(e / (t *
|
|
829
|
+
static blockCoefficient(e, t, n, o) {
|
|
830
|
+
let i = Math.round(e / (t * n * o) * 100) / 100;
|
|
831
831
|
i = i < 0.55 ? 0.55 : i > 0.85 ? 0.85 : i;
|
|
832
|
-
const
|
|
833
|
-
return
|
|
832
|
+
const a = [0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85], s = a.map((r) => Math.abs(r - i));
|
|
833
|
+
return a[s.indexOf(Math.min(...s))];
|
|
834
834
|
}
|
|
835
835
|
/**
|
|
836
836
|
* @see https://baike.baidu.com/item/%E5%BC%97%E5%8A%B3%E5%BE%B7%E6%95%B0/228891?fromModule=search-result_lemma-recommend
|
|
@@ -843,8 +843,8 @@ class H {
|
|
|
843
843
|
* @param g 重力加速度 9.80 m/s^2
|
|
844
844
|
* @return [0.05, 0.30]
|
|
845
845
|
*/
|
|
846
|
-
static froudeNumber(e, t,
|
|
847
|
-
let o = Math.round(Math.sqrt(e * e / (
|
|
846
|
+
static froudeNumber(e, t, n = 9.8) {
|
|
847
|
+
let o = Math.round(Math.sqrt(e * e / (n * t)) * 100) / 100;
|
|
848
848
|
return o = o < 0.05 ? 0.05 : o > 0.3 ? 0.3 : o, o;
|
|
849
849
|
}
|
|
850
850
|
/**
|
|
@@ -854,7 +854,7 @@ class H {
|
|
|
854
854
|
* @param loadCondition
|
|
855
855
|
* @private
|
|
856
856
|
*/
|
|
857
|
-
static amendFactor(e, t,
|
|
857
|
+
static amendFactor(e, t, n) {
|
|
858
858
|
const o = {
|
|
859
859
|
0.55: [1.7, -1.4, -7.4],
|
|
860
860
|
0.6: [2.2, -2.5, -9.7],
|
|
@@ -864,7 +864,7 @@ class H {
|
|
|
864
864
|
0.8: [2.6, -13.1, -15.1],
|
|
865
865
|
0.85: [3.1, -18.7, 28]
|
|
866
866
|
};
|
|
867
|
-
let
|
|
867
|
+
let a = {
|
|
868
868
|
0.55: [1.7, -1.4, -7.4],
|
|
869
869
|
0.6: [2.2, -2.5, -9.7],
|
|
870
870
|
0.65: [2.6, -3.7, -11.6],
|
|
@@ -873,7 +873,7 @@ class H {
|
|
|
873
873
|
0.8: [3, -16.3, -21.6],
|
|
874
874
|
0.85: [3.4, -20.9, 31.8]
|
|
875
875
|
}[e];
|
|
876
|
-
return
|
|
876
|
+
return n === "Laden" && (a = o[e]), a[0] + a[1] * t + a[2] * Math.pow(t, 2);
|
|
877
877
|
}
|
|
878
878
|
/**
|
|
879
879
|
* 失速方向因子
|
|
@@ -887,8 +887,8 @@ class H {
|
|
|
887
887
|
* @private
|
|
888
888
|
*/
|
|
889
889
|
static directionFactor(e, t = 0) {
|
|
890
|
-
let
|
|
891
|
-
return e > 30 && e <= 60 ?
|
|
890
|
+
let n;
|
|
891
|
+
return e > 30 && e <= 60 ? n = (1.7 - 0.03 * Math.pow(t - 4, 2)) / 2 : e > 60 && e <= 150 ? n = (0.9 - 0.06 * Math.pow(t - 6, 2)) / 2 : e > 150 && e <= 180 ? n = (0.4 - 0.03 * Math.pow(t - 8, 2)) / 2 : n = 1, Math.round(n * 1e5) / 1e5;
|
|
892
892
|
}
|
|
893
893
|
/**
|
|
894
894
|
* 失速船型因子
|
|
@@ -902,21 +902,23 @@ class H {
|
|
|
902
902
|
* @param kts
|
|
903
903
|
* @private
|
|
904
904
|
*/
|
|
905
|
-
static vesselTagFactor(e, t,
|
|
905
|
+
static vesselTagFactor(e, t, n, o) {
|
|
906
906
|
let i;
|
|
907
|
-
return
|
|
907
|
+
return n === "container" ? i = 0.7 * o / 2 + Math.pow(o, 3) / (22 * Math.pow(e, 2 / 3)) : t === "Ballast" ? i = 0.7 * o / 2 + Math.pow(o, 3) / (2.7 * Math.pow(e, 2 / 3)) : i = 0.5 * o / 2 + Math.pow(o, 3) / (2.7 * Math.pow(e, 2 / 3)), i;
|
|
908
908
|
}
|
|
909
909
|
/**
|
|
910
910
|
* 浪高影响因子
|
|
911
911
|
* @param ht 浪高,单位m
|
|
912
912
|
* @param beta 夹角
|
|
913
|
-
* @param
|
|
913
|
+
* @param draught 吃水
|
|
914
|
+
* @param options
|
|
914
915
|
* @private
|
|
915
916
|
*/
|
|
916
|
-
static waveHeightFactor(e, t,
|
|
917
|
+
static waveHeightFactor(e, t, n = 10, o = {}) {
|
|
917
918
|
e = e < 3 ? e * 0.7 : e, e = e < 0 ? 0.2 : e, e = e > 6 ? e - 0.9 * (e - 6) : e, e = e > 9 ? 9 : e;
|
|
918
|
-
|
|
919
|
-
|
|
919
|
+
const i = Math.max(n > 10 ? n - 10 : 2.8);
|
|
920
|
+
let a;
|
|
921
|
+
return t > 30 && t <= 60 ? a = -0.6 : t > 60 && t <= 90 ? a = -0.5 : t > 90 && t <= 120 ? a = e < i ? 0.2 : -0.4 : t > 120 && t <= 150 ? a = e < i ? 0.25 : -0.5 : t > 150 && t <= 180 ? a = e < i ? 0.3 : -0.6 : a = -0.7, C == null || C.info("[%s] calculate wave height factor with ht(%d), beta(%d), draught(%d) and factor(%d)", o.requestId, e, t, n, a), Math.round(a * (0.144 * Math.pow(e, 2) + 0.378 * e) * 1e4) / 1e4;
|
|
920
922
|
}
|
|
921
923
|
/**
|
|
922
924
|
* 组装船舶运行参数
|
|
@@ -926,20 +928,20 @@ class H {
|
|
|
926
928
|
* @param bearing 方位角
|
|
927
929
|
* @private
|
|
928
930
|
*/
|
|
929
|
-
static assembleProperties(e, t,
|
|
931
|
+
static assembleProperties(e, t, n, o) {
|
|
930
932
|
var d;
|
|
931
|
-
const i = e.lbp ?? e.length ?? e.lengthOverall ?? 198.9642,
|
|
933
|
+
const i = e.lbp ?? e.length ?? e.lengthOverall ?? 198.9642, a = e.draught ?? 8, s = e.breadthMoulded ?? e.breadth ?? e.breadthExtreme ?? 32.4572, r = e.deadweight ?? 67035.7773, u = ((d = e == null ? void 0 : e.type) == null ? void 0 : d.toLowerCase()) || "common";
|
|
932
934
|
return {
|
|
933
935
|
tag: u.indexOf("container") > -1 ? "container" : u.indexOf("tugs") > -1 ? "tugs" : "common",
|
|
934
936
|
lbp: i,
|
|
935
937
|
loadCondition: t,
|
|
936
|
-
draught:
|
|
938
|
+
draught: a,
|
|
937
939
|
breadthMoulded: s,
|
|
938
940
|
// 排水量(吨)= 载重量(吨)/ 1.025 + 吃水(米)× 船舶型宽(米)× 船舶型长(米)× 0.7
|
|
939
941
|
// 其中,1.025是指海水的密度,吨是指公吨,吃水是指船舶的最大吃水深度。船舶型宽是指船舶的最大型宽,船舶型长是指船舶的设计型长。上述公式是针对常规船舶适用的,不同类型的船舶可能会有一些差异。
|
|
940
|
-
displacement: Math.round((r / 1.025 +
|
|
942
|
+
displacement: Math.round((r / 1.025 + a * s * i * 0.7) * 1e4) / 1e4,
|
|
941
943
|
// 换算为m/s
|
|
942
|
-
speed: Math.round((
|
|
944
|
+
speed: Math.round((n ?? 14.1382) * 1852 / 3600 * 1e4) / 1e4,
|
|
943
945
|
bearing: o || 90
|
|
944
946
|
};
|
|
945
947
|
}
|
|
@@ -954,26 +956,26 @@ class H {
|
|
|
954
956
|
* @param useRouteParam true 启用设置速度
|
|
955
957
|
* @param options
|
|
956
958
|
*/
|
|
957
|
-
static async speedLoseAt(e, t,
|
|
959
|
+
static async speedLoseAt(e, t, n, o = "", i = 2, a = !0, s = !1, r = {}) {
|
|
958
960
|
let u;
|
|
959
|
-
if (t.velocity && s && (e.speed = J.roundPrecision(t.velocity * 1852 / 3600, 6)),
|
|
961
|
+
if (t.velocity && s && (e.speed = J.roundPrecision(t.velocity * 1852 / 3600, 6)), a) {
|
|
960
962
|
let l;
|
|
961
963
|
try {
|
|
962
964
|
o = (o == null ? void 0 : o.toUpperCase()) === "CMEMS" ? "ECMWF" : o, o = (o == null ? void 0 : o.toUpperCase()) === "METEO2" ? "best_match" : o;
|
|
963
|
-
const { weatherModels: k, marineModels:
|
|
965
|
+
const { weatherModels: k, marineModels: w } = await dt.autoPickMeteoModel(o), v = n.utc().format(), m = await gt.spotForecast(t.lat, t.lng, v, !1, !1, !0, {
|
|
964
966
|
...r,
|
|
965
967
|
pastDays: 1,
|
|
966
968
|
forecastDays: 2,
|
|
967
969
|
weatherModels: k,
|
|
968
|
-
marineModels:
|
|
969
|
-
}), [c] = dt.pickHourly(m,
|
|
970
|
+
marineModels: w
|
|
971
|
+
}), [c] = dt.pickHourly(m, n);
|
|
970
972
|
l = dt.toLegacy(c);
|
|
971
973
|
} catch (k) {
|
|
972
|
-
|
|
974
|
+
C.warn("[%s] meteo2 spot(%j) forecast failed: %s", r.requestId, { ...t, eta: n.utc().format(), source: o }, k);
|
|
973
975
|
}
|
|
974
976
|
let h = H.currentFactor(e.bearing, l == null ? void 0 : l.current, i, r), d = H.weatherFactor(e, l, h, r);
|
|
975
977
|
const I = e.speed * 1.943844;
|
|
976
|
-
I + h + d <= 0 && (
|
|
978
|
+
I + h + d <= 0 && (C.warn(
|
|
977
979
|
"[%s] v0(%d) is less then factor(%d) = wxFactor(%d) + cFactor(%d), scale factor with 0.6",
|
|
978
980
|
r.requestId,
|
|
979
981
|
I,
|
|
@@ -982,7 +984,7 @@ class H {
|
|
|
982
984
|
h
|
|
983
985
|
), h = Math.round(h * 0.6 * 1e3) / 1e3, d = Math.round(d * 0.6 * 1e3) / 1e3);
|
|
984
986
|
const b = d <= (r.minV0Factor || -1) ? Math.max(r.maxV0Factor || -3, -1 * d * (d / 1.2)) : 0;
|
|
985
|
-
|
|
987
|
+
C == null || C.info("[%s] calculate speed lose with v0Factor(%d), cFactor(%d) and wxFactor(%d)", r.requestId, b, h, d), d += b;
|
|
986
988
|
let E = Math.round((I + h + d) * 100) / 100;
|
|
987
989
|
E = E <= 0 ? 1 : E, u = {
|
|
988
990
|
meteo: { ...l },
|
|
@@ -990,8 +992,8 @@ class H {
|
|
|
990
992
|
v0Factor: b,
|
|
991
993
|
cFactor: h,
|
|
992
994
|
speed: t.velocity && s ? t.velocity : E,
|
|
993
|
-
eta:
|
|
994
|
-
etd:
|
|
995
|
+
eta: n.utc().format(),
|
|
996
|
+
etd: n.utc().format()
|
|
995
997
|
};
|
|
996
998
|
} else
|
|
997
999
|
u = {
|
|
@@ -999,8 +1001,8 @@ class H {
|
|
|
999
1001
|
v0Factor: 0,
|
|
1000
1002
|
cFactor: 0,
|
|
1001
1003
|
speed: t.velocity && s ? t.velocity : Math.round(e.speed * 1.943844 * 100) / 100,
|
|
1002
|
-
eta:
|
|
1003
|
-
etd:
|
|
1004
|
+
eta: n.utc().format(),
|
|
1005
|
+
etd: n.utc().format()
|
|
1004
1006
|
};
|
|
1005
1007
|
return delete t.meteo, delete t.wxFactor, delete t.cFactor, delete t.speed, delete t.etd, { ...u, ...t };
|
|
1006
1008
|
}
|
|
@@ -1018,14 +1020,14 @@ class H {
|
|
|
1018
1020
|
* @param options
|
|
1019
1021
|
* @private
|
|
1020
1022
|
*/
|
|
1021
|
-
static async speedLoseInHoursStep(e, t,
|
|
1023
|
+
static async speedLoseInHoursStep(e, t, n, o, i, a, s = "", r = !0, u = !1, l = {}) {
|
|
1022
1024
|
t.utc();
|
|
1023
1025
|
const h = t.clone().add(14, "days"), d = [], I = [], b = [];
|
|
1024
|
-
let E = 0, k = 0,
|
|
1025
|
-
for (let m = 0; m <
|
|
1026
|
-
let c =
|
|
1026
|
+
let E = 0, k = 0, w, v;
|
|
1027
|
+
for (let m = 0; m < a.length - 1; m++) {
|
|
1028
|
+
let c = a[m];
|
|
1027
1029
|
c.distanceFromStart = Math.round((i + k) * 1e3) / 1e3;
|
|
1028
|
-
const f =
|
|
1030
|
+
const f = a[m + 1];
|
|
1029
1031
|
if (e.bearing = R.calculateBearing(c, f, !f.gcToPrevious), c.bearing = e.bearing, c.suspend && u) {
|
|
1030
1032
|
c.eta = c.eta || t.utc().format(), c.elapsed = c.elapsed ?? 0;
|
|
1031
1033
|
const M = c.suspend - c.elapsed;
|
|
@@ -1035,36 +1037,36 @@ class H {
|
|
|
1035
1037
|
const j = o - E;
|
|
1036
1038
|
c.elapsed += j, t.add(j, "hour"), o = 0;
|
|
1037
1039
|
}
|
|
1038
|
-
if (
|
|
1039
|
-
return c.distanceFromPrevious = k, { etd: t, from: v || c, to: c, next:
|
|
1040
|
+
if (C == null || C.info(`[%s] suspend ${c.elapsed} hours at %j, and remain ${o} hours need to go...`, l.requestId, c), o === 0)
|
|
1041
|
+
return c.distanceFromPrevious = k, { etd: t, from: v || c, to: c, next: a.filter((j) => j), wps: d, days: I, all: b };
|
|
1040
1042
|
} else
|
|
1041
1043
|
c.suspend = 0;
|
|
1042
|
-
r = t.isAfter(h) ? !1 : r, c = await H.speedLoseAt(e, c, t, s, 0, r, u, l), b.push(c), v = v || c, c.important && d.push(c), t.isSameOrAfter(
|
|
1044
|
+
r = t.isAfter(h) ? !1 : r, c = await H.speedLoseAt(e, c, t, s, 0, r, u, l), b.push(c), v = v || c, c.important && d.push(c), t.isSameOrAfter(n) && (I.push(c), n.add(24, "hour"));
|
|
1043
1045
|
const y = R.calculateDistance(c, f, !f.gcToPrevious);
|
|
1044
|
-
let
|
|
1045
|
-
if (E +
|
|
1046
|
-
if (E +=
|
|
1047
|
-
`[%s] go to %j from %j with ${y}nm, and cost ${
|
|
1046
|
+
let S = Math.round(y / v.speed * 1e5) / 1e5;
|
|
1047
|
+
if (E + S < o) {
|
|
1048
|
+
if (E += S, t.add(S, "hour"), delete a[m], C == null || C.debug(
|
|
1049
|
+
`[%s] go to %j from %j with ${y}nm, and cost ${S} hours`,
|
|
1048
1050
|
l.requestId,
|
|
1049
1051
|
{ lat: f.lat, lng: f.lng },
|
|
1050
1052
|
{ lat: v.lat, lng: v.lng, etd: v.etd }
|
|
1051
|
-
), k += y,
|
|
1052
|
-
|
|
1053
|
+
), k += y, a.filter((M) => M).length <= 1) {
|
|
1054
|
+
w = f, w.eta = t.utc().format(), w.distanceFromPrevious = y, w.distanceFromStart = Math.round((i + k) * 1e4) / 1e4, d.push(w), b.push(w), delete a[m + 1];
|
|
1053
1055
|
break;
|
|
1054
1056
|
}
|
|
1055
1057
|
} else {
|
|
1056
|
-
|
|
1057
|
-
const M = J.roundPrecision(v.speed *
|
|
1058
|
-
|
|
1059
|
-
`[%s] go to %j from %j with ${M}nm, and cost ${
|
|
1058
|
+
S = o - E, t.add(S, "hour");
|
|
1059
|
+
const M = J.roundPrecision(v.speed * S, 5);
|
|
1060
|
+
w = R.calculateCoordinate(c, e.bearing, M, "nauticalmiles", !f.gcToPrevious), w.eta = t.utc().format(), a[m] = w, C == null || C.debug(
|
|
1061
|
+
`[%s] go to %j from %j with ${M}nm, and cost ${S} hours`,
|
|
1060
1062
|
l.requestId,
|
|
1061
|
-
{ lat:
|
|
1063
|
+
{ lat: w.lat, lng: w.lng },
|
|
1062
1064
|
{ lat: c.lat, lng: c.lng, etd: c.etd }
|
|
1063
|
-
), k += M,
|
|
1065
|
+
), k += M, w.distanceFromPrevious = Math.round(k * 1e4) / 1e4, w.distanceFromStart = Math.round((i + k) * 1e4) / 1e4;
|
|
1064
1066
|
break;
|
|
1065
1067
|
}
|
|
1066
1068
|
}
|
|
1067
|
-
return { etd: t, from: v, to:
|
|
1069
|
+
return { etd: t, from: v, to: w, next: a.filter((m) => m), wps: d, days: I, all: b };
|
|
1068
1070
|
}
|
|
1069
1071
|
/**
|
|
1070
1072
|
* 洋流影响因子
|
|
@@ -1073,10 +1075,10 @@ class H {
|
|
|
1073
1075
|
* @param role 1: 船东, 2: 租家, 0: 未知
|
|
1074
1076
|
* @param options
|
|
1075
1077
|
*/
|
|
1076
|
-
static currentFactor(e, t,
|
|
1078
|
+
static currentFactor(e, t, n = 0, o = {}) {
|
|
1077
1079
|
const i = R.includedAngle(e, (t == null ? void 0 : t.degree) || 0) / 180 * Math.PI;
|
|
1078
|
-
let
|
|
1079
|
-
return Math.abs(i) === Math.PI / 2 && (
|
|
1080
|
+
let a;
|
|
1081
|
+
return Math.abs(i) === Math.PI / 2 && (a = 0), a = ((t == null ? void 0 : t.kts) || 0) * Math.cos(i), n & 2 ? a = Math.ceil(a * 100) / 100 : n & 1 ? a = Math.floor(a * 100) / 100 : a = Math.round(a * 100) / 100, C == null || C.info("[%s] calculate current factor with %j", o.requestId, { beta: i, current: t, factor: a, role: n }), Math.abs(a) > 5 ? 0 : a;
|
|
1080
1082
|
}
|
|
1081
1083
|
/**
|
|
1082
1084
|
* 风浪影响因子
|
|
@@ -1085,16 +1087,16 @@ class H {
|
|
|
1085
1087
|
* @param cFactor 洋流因子
|
|
1086
1088
|
* @param options
|
|
1087
1089
|
*/
|
|
1088
|
-
static weatherFactor(e, t,
|
|
1089
|
-
var b, E, k,
|
|
1090
|
-
|
|
1091
|
-
const i = H.blockCoefficient(e.displacement, e.lbp, e.breadthMoulded, e.draught),
|
|
1090
|
+
static weatherFactor(e, t, n = 0, o = {}) {
|
|
1091
|
+
var b, E, k, w, v, m, c;
|
|
1092
|
+
C == null || C.info("[%s] calculate weather factor via: %j", o.requestId, { ...e, ...t });
|
|
1093
|
+
const i = H.blockCoefficient(e.displacement, e.lbp, e.breadthMoulded, e.draught), a = J.roundPrecision(n * 1852 / 3600, 6), s = H.froudeNumber(e.speed - a, e.lbp), r = H.amendFactor(i, s, e.loadCondition);
|
|
1092
1094
|
let u = R.includedAngle(e.bearing, (b = t == null ? void 0 : t.wind) == null ? void 0 : b.degree);
|
|
1093
1095
|
const l = H.directionFactor(u, (E = t == null ? void 0 : t.wind) == null ? void 0 : E.scale), h = H.vesselTagFactor(e.displacement, e.loadCondition, e.tag, (k = t == null ? void 0 : t.wind) == null ? void 0 : k.kts);
|
|
1094
|
-
let d = l * r * h / 100 * (e.speed -
|
|
1095
|
-
d = Math.round(d * 1.943844 * 1e4) / 1e4 * -1, e.tag === "tugs" && Math.abs(d) > 1 && (d = d / (Math.abs(Math.round(d)) + 1)),
|
|
1096
|
-
const I = H.waveHeightFactor(((c = (m = t == null ? void 0 : t.wave) == null ? void 0 : m.sig) == null ? void 0 : c.height) ?? 1, u, e.draught);
|
|
1097
|
-
return
|
|
1096
|
+
let d = l * r * h / 100 * (e.speed - a);
|
|
1097
|
+
d = Math.round(d * 1.943844 * 1e4) / 1e4 * -1, e.tag === "tugs" && Math.abs(d) > 1 && (d = d / (Math.abs(Math.round(d)) + 1)), C == null || C.info("[%s] calculate wind wx factor: %d", o.requestId, d), u = R.includedAngle(e.bearing, (v = (w = t == null ? void 0 : t.wave) == null ? void 0 : w.sig) == null ? void 0 : v.degree);
|
|
1098
|
+
const I = H.waveHeightFactor(((c = (m = t == null ? void 0 : t.wave) == null ? void 0 : m.sig) == null ? void 0 : c.height) ?? 1, u, e.draught, o);
|
|
1099
|
+
return C == null || C.info("[%s] calculate wave wx factor: %d", o.requestId, I), d = Math.abs(d) > Math.abs(I) ? d : 0.7 * d + 0.9 * I, C == null || C.info("[%s] calculate finial weather factor: %d (0.7 * wf) + (0.9 * hf)", o.requestId, d), Math.round((d || 0) * 100) / 100;
|
|
1098
1100
|
}
|
|
1099
1101
|
/**
|
|
1100
1102
|
* 以12小时级别去掉重复的days
|
|
@@ -1102,7 +1104,7 @@ class H {
|
|
|
1102
1104
|
* @param interval 12 hours
|
|
1103
1105
|
*/
|
|
1104
1106
|
static async reduceDays(e, t = 12 * 60 * 60) {
|
|
1105
|
-
return e = e == null ? void 0 : e.reduce((
|
|
1107
|
+
return e = e == null ? void 0 : e.reduce((n, o) => (o.positionTime || (o.positionTime = p.utc(o.etd || o.eta).unix()), n.some((i) => Math.floor(i.positionTime / t) === Math.floor(o.positionTime / t)) || n.push(o), n), []), e;
|
|
1106
1108
|
}
|
|
1107
1109
|
/**
|
|
1108
1110
|
* 以分钟级别去掉重复的wps
|
|
@@ -1110,7 +1112,7 @@ class H {
|
|
|
1110
1112
|
* @param interval 1 minute
|
|
1111
1113
|
*/
|
|
1112
1114
|
static async reduceWPS(e, t = 60) {
|
|
1113
|
-
return e = e == null ? void 0 : e.reduce((
|
|
1115
|
+
return e = e == null ? void 0 : e.reduce((n, o) => (n.some((i) => Math.floor(p(i.etd).unix() / t) === Math.floor(p(o.etd).unix() / t)) || n.push(o), n), []), e;
|
|
1114
1116
|
}
|
|
1115
1117
|
/**
|
|
1116
1118
|
* 全程失速分析(走完航程)
|
|
@@ -1125,9 +1127,9 @@ class H {
|
|
|
1125
1127
|
* @param useRouteParam
|
|
1126
1128
|
* @param options
|
|
1127
1129
|
*/
|
|
1128
|
-
static async analyseInstant(e, t,
|
|
1130
|
+
static async analyseInstant(e, t, n, o, i, a = "", s = 0, r = !0, u = !1, l = {}) {
|
|
1129
1131
|
var U, G, X, Q, Z, $;
|
|
1130
|
-
const h =
|
|
1132
|
+
const h = p().valueOf();
|
|
1131
1133
|
e.lng = J.convertToStdLng(e.lng);
|
|
1132
1134
|
const { route: d, waypoints: I } = i.points, b = R.calculateSubRoute(e, d);
|
|
1133
1135
|
if (((U = b[0]) == null ? void 0 : U.length) <= 1)
|
|
@@ -1140,8 +1142,8 @@ class H {
|
|
|
1140
1142
|
v0: o.speed,
|
|
1141
1143
|
label: "CP"
|
|
1142
1144
|
/* Cp */
|
|
1143
|
-
},
|
|
1144
|
-
v.forEach((
|
|
1145
|
+
}, w = H.assembleProperties(n, o.loadCondition, E, 0), v = I.length ? R.calculateSubWaypoints(e, I) : [];
|
|
1146
|
+
v.forEach((q) => q.important = !0);
|
|
1145
1147
|
const m = {
|
|
1146
1148
|
from: { ...e },
|
|
1147
1149
|
route: b,
|
|
@@ -1155,46 +1157,46 @@ class H {
|
|
|
1155
1157
|
all: []
|
|
1156
1158
|
};
|
|
1157
1159
|
s || (R.calculateRouteDistance(b) / o.speed <= 72 ? s = 3 : s = 6);
|
|
1158
|
-
let f = R.simplifyRouteToCoordinates(b, v, 0), y = 0,
|
|
1159
|
-
t =
|
|
1160
|
+
let f = R.simplifyRouteToCoordinates(b, v, 0), y = 0, S = 0, M = 0, j = 0;
|
|
1161
|
+
t = p(t).utc();
|
|
1160
1162
|
const N = t.clone();
|
|
1161
1163
|
for (; f.length > 0; ) {
|
|
1162
|
-
const
|
|
1163
|
-
|
|
1164
|
+
const q = s - t.hour() % s, B = Math.ceil(t.clone().add(q, "h").set({ minute: 0, second: 0, millisecond: 0 }).diff(t, "h", !0) * 1e4) / 1e4, T = await H.speedLoseInHoursStep(
|
|
1165
|
+
w,
|
|
1164
1166
|
t,
|
|
1165
1167
|
N,
|
|
1166
1168
|
B,
|
|
1167
1169
|
y,
|
|
1168
1170
|
f,
|
|
1169
|
-
|
|
1171
|
+
a,
|
|
1170
1172
|
r,
|
|
1171
1173
|
u,
|
|
1172
1174
|
l
|
|
1173
1175
|
);
|
|
1174
1176
|
if (c.all.push(...T.all), (G = T.from) != null && G.speed && (c.hours.push(T.from), c.wps.push(...T.wps), c.days.push(...T.days)), f = T == null ? void 0 : T.next, !f.length) {
|
|
1175
|
-
const O = await H.speedLoseAt(
|
|
1176
|
-
O.bearing =
|
|
1177
|
+
const O = await H.speedLoseAt(w, T.to, p(T.to.eta), a, 0, r, u, l);
|
|
1178
|
+
O.bearing = w.bearing, c.hours.push(O), c.all.push(O);
|
|
1177
1179
|
}
|
|
1178
1180
|
y += Math.round((((X = T == null ? void 0 : T.to) == null ? void 0 : X.distanceFromPrevious) ?? 0) * 1e4) / 1e4;
|
|
1179
1181
|
}
|
|
1180
1182
|
const D = c.hours;
|
|
1181
|
-
for (let
|
|
1182
|
-
const B =
|
|
1183
|
-
|
|
1183
|
+
for (let q = 0; q < D.length - 1; q++) {
|
|
1184
|
+
const B = p(D[q + 1].eta).diff(D[q].etd, "hour", !0) || 1;
|
|
1185
|
+
S += (D[q].wxFactor || 0) * B, M += (D[q].cFactor || 0) * B, j += B;
|
|
1184
1186
|
}
|
|
1185
|
-
const L = D.reduce((
|
|
1186
|
-
(Q = c.wps) == null || Q.forEach((
|
|
1187
|
-
|
|
1187
|
+
const L = D.reduce((q, B) => q + (B.suspend || 0), 0);
|
|
1188
|
+
(Q = c.wps) == null || Q.forEach((q, B) => {
|
|
1189
|
+
q.positionTime = p.utc(q.etd || q.eta).unix();
|
|
1188
1190
|
const T = c.wps[B - 1];
|
|
1189
1191
|
if (T) {
|
|
1190
|
-
const O =
|
|
1191
|
-
|
|
1192
|
-
const at = R.calculateBearing(T,
|
|
1193
|
-
|
|
1192
|
+
const O = q.distanceFromStart - T.distanceFromStart, P = p(q.eta || q.etd).diff(p(T.etd || T.eta), "h", !0);
|
|
1193
|
+
q.avgSpd = Math.round(O / P * 100) / 100;
|
|
1194
|
+
const at = R.calculateBearing(T, q);
|
|
1195
|
+
q.avgBearing = at, T.bearing = at;
|
|
1194
1196
|
}
|
|
1195
|
-
}), c.wps = await H.reduceWPS(c.wps), c.days = await H.reduceDays(c.days), c.all = (Z = c.all) == null ? void 0 : Z.reduce((
|
|
1196
|
-
const W = c.hours.at(0),
|
|
1197
|
-
m.distance = Math.round(
|
|
1197
|
+
}), c.wps = await H.reduceWPS(c.wps), c.days = await H.reduceDays(c.days), c.all = (Z = c.all) == null ? void 0 : Z.reduce((q, B) => (B.positionTime = p.utc(B.etd || B.eta).unix(), q.some((T) => Math.round(T.positionTime / 60) === Math.round(B.positionTime / 60)) || q.push(B), q), []), m.sample = c;
|
|
1198
|
+
const W = c.hours.at(0), F = c.hours.at(-1);
|
|
1199
|
+
m.distance = Math.round(F.distanceFromStart * 1e3) / 1e3, m.etd = p(W.eta).utc().format(), m.eta = p(F.eta).utc().format(), m.wxFactor = Math.round(S / j * 1e3) / 1e3, m.cFactor = Math.round(M / j * 1e3) / 1e3, m.avgSpeed = Math.round(F.distanceFromStart / j * 1e3) / 1e3, m.totalHrs = Math.round(j * 1e3) / 1e3, m.suspend = Math.round(L * 1e3) / 1e3;
|
|
1198
1200
|
const Y = J.roundPrecision(o.dgo / 24 * L, 3), { distanceInECA: A, hoursInECA: V, totalDgoConsInECA: ot, eca: tt } = await this.calculateECA(m, o, l), et = J.roundPrecision(o.fo / 24 * (j - V), 3), it = J.roundPrecision(o.dgo / 24 * j + Y, 3);
|
|
1199
1201
|
m.extend = {
|
|
1200
1202
|
eca: tt,
|
|
@@ -1203,8 +1205,8 @@ class H {
|
|
|
1203
1205
|
totalDgoConsInECA: ot,
|
|
1204
1206
|
totalDgoConsInSuspend: Y
|
|
1205
1207
|
}, m.totalFoCons = et < 0 ? 0 : et, m.totalDgoCons = it;
|
|
1206
|
-
const st =
|
|
1207
|
-
return
|
|
1208
|
+
const st = p().valueOf() - h, ct = (($ = c == null ? void 0 : c.hours) == null ? void 0 : $.length) || 1;
|
|
1209
|
+
return C == null || C.info("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms", l == null ? void 0 : l.requestId, st, ct, Math.round(st / ct * 1e3) / 1e3), m;
|
|
1208
1210
|
}
|
|
1209
1211
|
/**
|
|
1210
1212
|
* 分段失速分析(最多走hours 小时)
|
|
@@ -1221,9 +1223,9 @@ class H {
|
|
|
1221
1223
|
* @param useRouteParam
|
|
1222
1224
|
* @param options
|
|
1223
1225
|
*/
|
|
1224
|
-
static async analyseInstantWithThreshed(e, t,
|
|
1225
|
-
var X, Q, Z, $,
|
|
1226
|
-
const I =
|
|
1226
|
+
static async analyseInstantWithThreshed(e, t, n, o, i, a, s, r = "", u = 3, l = !0, h = !1, d = {}) {
|
|
1227
|
+
var X, Q, Z, $, q, B;
|
|
1228
|
+
const I = p().valueOf();
|
|
1227
1229
|
e.lng = J.convertToStdLng(e.lng);
|
|
1228
1230
|
const { v0: b, label: E } = e.sog ? {
|
|
1229
1231
|
v0: e.sog,
|
|
@@ -1233,58 +1235,58 @@ class H {
|
|
|
1233
1235
|
v0: i.speed,
|
|
1234
1236
|
label: "CP"
|
|
1235
1237
|
/* Cp */
|
|
1236
|
-
}, k = H.assembleProperties(o, i.loadCondition, b, 0),
|
|
1237
|
-
if (((X =
|
|
1238
|
+
}, k = H.assembleProperties(o, i.loadCondition, b, 0), w = R.calculateSubRoute(e, a);
|
|
1239
|
+
if (((X = w[0]) == null ? void 0 : X.length) <= 1)
|
|
1238
1240
|
return;
|
|
1239
1241
|
const v = s.length ? R.calculateSubWaypoints(e, s) : [];
|
|
1240
1242
|
v.forEach((T) => T.important = !0);
|
|
1241
|
-
let m = R.simplifyRouteToCoordinates(
|
|
1243
|
+
let m = R.simplifyRouteToCoordinates(w, v, 0), c = 0, f = 0, y = 0, S = 0;
|
|
1242
1244
|
const M = {
|
|
1243
1245
|
hours: [],
|
|
1244
1246
|
wps: [],
|
|
1245
1247
|
days: [],
|
|
1246
1248
|
all: []
|
|
1247
1249
|
};
|
|
1248
|
-
t =
|
|
1250
|
+
t = p(t).utc();
|
|
1249
1251
|
const j = t.clone();
|
|
1250
1252
|
for (; m.length > 0; ) {
|
|
1251
1253
|
const T = u - t.hour() % u;
|
|
1252
1254
|
let O = Math.ceil(t.clone().add(T, "h").set({ minute: 0, second: 0, millisecond: 0 }).diff(t, "h", !0) * 1e4) / 1e4;
|
|
1253
|
-
O = t.clone().add(O, "h").isSameOrAfter(
|
|
1254
|
-
const
|
|
1255
|
-
if (M.all.push(...
|
|
1255
|
+
O = t.clone().add(O, "h").isSameOrAfter(n) ? n.diff(t, "h", !0) * 1e4 / 1e4 : O;
|
|
1256
|
+
const P = await H.speedLoseInHoursStep(k, t, j, O, c, m, r, l, h, d);
|
|
1257
|
+
if (M.all.push(...P.all), (Q = P.from) != null && Q.speed && (M.hours.push(P.from), P != null && P.wps && M.wps.push(...P.wps), M.days.push(...P.days)), m = P == null ? void 0 : P.next, m.length || M.hours.push(P == null ? void 0 : P.to), c += Math.round((((Z = P == null ? void 0 : P.to) == null ? void 0 : Z.distanceFromPrevious) ?? 0) * 1e4) / 1e4, !O)
|
|
1256
1258
|
break;
|
|
1257
1259
|
}
|
|
1258
|
-
M.wps = await H.reduceWPS(M.wps), M.days = await H.reduceDays(M.days), M.all = ($ = M.all) == null ? void 0 : $.reduce((T, O) => (O.positionTime =
|
|
1259
|
-
const
|
|
1260
|
-
if (
|
|
1261
|
-
const at = T.distanceFromStart -
|
|
1262
|
-
|
|
1260
|
+
M.wps = await H.reduceWPS(M.wps), M.days = await H.reduceDays(M.days), M.all = ($ = M.all) == null ? void 0 : $.reduce((T, O) => (O.positionTime = p.utc(O.etd || O.eta).unix(), T.some((P) => Math.round(p(P.etd).unix() / 60) === Math.round(p(O.etd).unix() / 60)) || T.push(O), T), []), (q = M.wps) == null || q.forEach((T, O) => {
|
|
1261
|
+
const P = M.wps[O - 1];
|
|
1262
|
+
if (P) {
|
|
1263
|
+
const at = T.distanceFromStart - P.distanceFromStart, lt = p(T.eta || T.etd).diff(p(P.etd || P.eta), "h", !0);
|
|
1264
|
+
P.bearing = R.calculateBearing(P, T), T.avgSpd = Math.round(at / lt * 100) / 100;
|
|
1263
1265
|
}
|
|
1264
1266
|
});
|
|
1265
1267
|
const N = M.hours;
|
|
1266
1268
|
for (let T = 0; T < N.length - 1; T++) {
|
|
1267
|
-
const O =
|
|
1268
|
-
f += N[T].wxFactor * O, y += N[T].cFactor * O,
|
|
1269
|
+
const O = p(N[T + 1].eta).diff(N[T].etd, "hour", !0);
|
|
1270
|
+
f += N[T].wxFactor * O, y += N[T].cFactor * O, S += O;
|
|
1269
1271
|
}
|
|
1270
|
-
const D = N.reduce((T, O) => T + (O.suspend || 0), 0), L = M.hours.at(0), W = M.hours.at(-1),
|
|
1272
|
+
const D = N.reduce((T, O) => T + (O.suspend || 0), 0), L = M.hours.at(0), W = M.hours.at(-1), F = await R.calculateRangeRoute(L, W, w), Y = await R.calculateRangeWaypoints(L, W, w, v), A = {
|
|
1271
1273
|
sample: M,
|
|
1272
1274
|
distance: Math.round(((W == null ? void 0 : W.distanceFromStart) || 0) * 1e4) / 1e4,
|
|
1273
1275
|
// 注意,可能会在first节点Drift,所有采用eta做为初始出发时间
|
|
1274
|
-
etd:
|
|
1275
|
-
eta:
|
|
1276
|
-
wxFactor: Math.round(f /
|
|
1277
|
-
cFactor: Math.round(y /
|
|
1278
|
-
avgSpeed: Math.round(((W == null ? void 0 : W.distanceFromStart) || 0) /
|
|
1279
|
-
totalHrs: Math.round(
|
|
1276
|
+
etd: p(L.eta).utc().format(),
|
|
1277
|
+
eta: p(W == null ? void 0 : W.eta).utc().format(),
|
|
1278
|
+
wxFactor: Math.round(f / S * 1e3) / 1e3,
|
|
1279
|
+
cFactor: Math.round(y / S * 1e3) / 1e3,
|
|
1280
|
+
avgSpeed: Math.round(((W == null ? void 0 : W.distanceFromStart) || 0) / S * 1e3) / 1e3,
|
|
1281
|
+
totalHrs: Math.round(S * 1e3) / 1e3,
|
|
1280
1282
|
suspend: Math.round(D * 1e3) / 1e3,
|
|
1281
1283
|
from: L,
|
|
1282
1284
|
to: W,
|
|
1283
|
-
route:
|
|
1285
|
+
route: F,
|
|
1284
1286
|
waypoints: Y,
|
|
1285
1287
|
v0: b,
|
|
1286
1288
|
label: E
|
|
1287
|
-
}, V = J.roundPrecision(i.dgo / 24 * D, 3), { distanceInECA: ot, hoursInECA: tt, totalDgoConsInECA: et, eca: it } = await this.calculateECA(A, i, d), rt = J.roundPrecision(i.fo / 24 * (
|
|
1289
|
+
}, V = J.roundPrecision(i.dgo / 24 * D, 3), { distanceInECA: ot, hoursInECA: tt, totalDgoConsInECA: et, eca: it } = await this.calculateECA(A, i, d), rt = J.roundPrecision(i.fo / 24 * (S - tt), 3), st = J.roundPrecision(i.dgo / 24 * S + V, 3);
|
|
1288
1290
|
A.extend = {
|
|
1289
1291
|
eca: it,
|
|
1290
1292
|
distanceInECA: ot,
|
|
@@ -1292,8 +1294,8 @@ class H {
|
|
|
1292
1294
|
totalDgoConsInECA: et,
|
|
1293
1295
|
totalDgoConsInSuspend: V
|
|
1294
1296
|
}, A.totalDgoCons = st, A.totalFoCons = rt < 0 ? 0 : rt;
|
|
1295
|
-
const U =
|
|
1296
|
-
return
|
|
1297
|
+
const U = p().valueOf() - I, G = ((B = M == null ? void 0 : M.hours) == null ? void 0 : B.length) || 1;
|
|
1298
|
+
return C == null || C.debug("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms", d == null ? void 0 : d.requestId, U, G, Math.round(U / G * 1e3) / 1e3), A;
|
|
1297
1299
|
}
|
|
1298
1300
|
/**
|
|
1299
1301
|
* 在指定航线条件下,基于多CP,动态计算最优成本(租金+油费)方案
|
|
@@ -1310,19 +1312,19 @@ class H {
|
|
|
1310
1312
|
* @param lane 基础航线(重要转向点)
|
|
1311
1313
|
* @param options
|
|
1312
1314
|
*/
|
|
1313
|
-
static async analyseCost(e, t,
|
|
1314
|
-
var
|
|
1315
|
-
const
|
|
1315
|
+
static async analyseCost(e, t, n, o, i = {}) {
|
|
1316
|
+
var w, v;
|
|
1317
|
+
const a = p().valueOf(), s = [];
|
|
1316
1318
|
e.speedStep = e.speedStep || 3, e.alterStep = e.alterStep ?? 1;
|
|
1317
1319
|
const r = R.calculateRouteDistance(o.route);
|
|
1318
1320
|
let u = 0;
|
|
1319
|
-
|
|
1321
|
+
n.forEach((m) => {
|
|
1320
1322
|
const c = Math.ceil(r / m.speed / 24);
|
|
1321
1323
|
u = u < c ? c : u;
|
|
1322
1324
|
}), u = u * 1.3;
|
|
1323
|
-
const l =
|
|
1325
|
+
const l = p.utc(e.etd).add(u ?? 14, "day");
|
|
1324
1326
|
let h = 1;
|
|
1325
|
-
for (const m of
|
|
1327
|
+
for (const m of n) {
|
|
1326
1328
|
const c = JSON.parse(JSON.stringify(o.route)), f = JSON.parse(JSON.stringify(o.waypoints)), y = await H.analyseInstantWithThreshed(
|
|
1327
1329
|
{ lat: e.lat, lng: e.lng },
|
|
1328
1330
|
e.etd,
|
|
@@ -1337,7 +1339,7 @@ class H {
|
|
|
1337
1339
|
e.useRouteParam,
|
|
1338
1340
|
i
|
|
1339
1341
|
);
|
|
1340
|
-
y && (await H.calculateCost(y, m, e, i), s.push(y),
|
|
1342
|
+
y && (await H.calculateCost(y, m, e, i), s.push(y), C == null || C.info("[%s][L%d-%d] analyse from %s to %s cost: %j", i.requestId, 1, h, e.etd, l.format(), {
|
|
1341
1343
|
cost: y.cost.total,
|
|
1342
1344
|
hire: y.cost.hire,
|
|
1343
1345
|
bunker: y.cost.bunker,
|
|
@@ -1348,9 +1350,9 @@ class H {
|
|
|
1348
1350
|
}
|
|
1349
1351
|
s.sort((m, c) => m.cost.total - c.cost.total);
|
|
1350
1352
|
const d = s.at(0), I = s.at(1), b = [];
|
|
1351
|
-
if (b.push({ combined: !1, speeds: [d], cost: (
|
|
1352
|
-
const m = d.cost.cp, c = I.cost.cp, f =
|
|
1353
|
-
let M = Math.ceil(
|
|
1353
|
+
if (b.push({ combined: !1, speeds: [d], cost: (w = d.cost) == null ? void 0 : w.total }), I) {
|
|
1354
|
+
const m = d.cost.cp, c = I.cost.cp, f = p(d.eta), y = p(d.etd), S = f.diff(y, "days", !0);
|
|
1355
|
+
let M = Math.ceil(S / 2);
|
|
1354
1356
|
M = M > 7 ? 7 : M < e.alterStep ? e.alterStep : M;
|
|
1355
1357
|
let j = 2, N = { combined: !1, speeds: [I], cost: (v = I.cost) == null ? void 0 : v.total }, D;
|
|
1356
1358
|
for (; M >= e.alterStep; ) {
|
|
@@ -1361,8 +1363,8 @@ class H {
|
|
|
1361
1363
|
}
|
|
1362
1364
|
b.push(N), D && b.push(D);
|
|
1363
1365
|
}
|
|
1364
|
-
const k =
|
|
1365
|
-
return
|
|
1366
|
+
const k = p().valueOf() - a;
|
|
1367
|
+
return C == null || C.info("[%s] analyse elapsed: %d ms", i == null ? void 0 : i.requestId, k), b.sort((m, c) => m.cost - c.cost);
|
|
1366
1368
|
}
|
|
1367
1369
|
/**
|
|
1368
1370
|
* 按步长多次减半,分别用7,4,2,1天步长及cpa,cpb交替计算各种组合下的成本
|
|
@@ -1374,24 +1376,24 @@ class H {
|
|
|
1374
1376
|
* @param step 步长,7,4,2,1
|
|
1375
1377
|
* @param options
|
|
1376
1378
|
*/
|
|
1377
|
-
static async combinedAnalyse(e, t,
|
|
1378
|
-
s.counter = 1,
|
|
1379
|
-
const r = await H.alternateAnalyse(e, t,
|
|
1380
|
-
|
|
1379
|
+
static async combinedAnalyse(e, t, n, o, i, a, s = {}) {
|
|
1380
|
+
s.counter = 1, C == null || C.info("[%s][L%d] analyse with alternate cp in every %d days", s.requestId, s.level, a);
|
|
1381
|
+
const r = await H.alternateAnalyse(e, t, n, o, 0, i, a, s), u = r.reduce((c, f) => c + f.cost.total, 0), l = r.reduce((c, f) => c + f.cost.hire, 0), h = r.reduce((c, f) => c + f.cost.bunker, 0), d = r.reduce((c, f) => c + f.distance, 0), I = r.reduce((c, f) => c + f.totalHrs, 0);
|
|
1382
|
+
C == null || C.info("[%s][L%d] cost with cpa/cpb turn: %j", s.requestId, s.level, {
|
|
1381
1383
|
cost: u,
|
|
1382
1384
|
hire: l,
|
|
1383
1385
|
bunker: h,
|
|
1384
1386
|
distance: d,
|
|
1385
1387
|
hours: I
|
|
1386
1388
|
});
|
|
1387
|
-
const b = await H.alternateAnalyse(e, t,
|
|
1388
|
-
return
|
|
1389
|
+
const b = await H.alternateAnalyse(e, t, n, o, 1, i, a, s), E = b.reduce((c, f) => c + f.cost.total, 0), k = b.reduce((c, f) => c + f.cost.hire, 0), w = 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);
|
|
1390
|
+
return C == null || C.info("[%s][L%d] cost with cpb/cpa turn: %j", s.requestId, s.level, {
|
|
1389
1391
|
cost: E,
|
|
1390
1392
|
hire: k,
|
|
1391
|
-
bunker:
|
|
1393
|
+
bunker: w,
|
|
1392
1394
|
distance: v,
|
|
1393
1395
|
hours: m
|
|
1394
|
-
}), u < E ? { combined: !0, cost: Math.round(u * 1e3) / 1e3, speeds: r, step:
|
|
1396
|
+
}), u < E ? { combined: !0, cost: Math.round(u * 1e3) / 1e3, speeds: r, step: a } : { combined: !0, cost: Math.round(E * 1e3) / 1e3, speeds: b, step: a };
|
|
1395
1397
|
}
|
|
1396
1398
|
/**
|
|
1397
1399
|
* 基于cp索引,交替计算指定步长下的成本
|
|
@@ -1404,17 +1406,17 @@ class H {
|
|
|
1404
1406
|
* @param step 步长,7,4,2,1
|
|
1405
1407
|
* @param options
|
|
1406
1408
|
*/
|
|
1407
|
-
static async alternateAnalyse(e, t,
|
|
1409
|
+
static async alternateAnalyse(e, t, n, o, i, a, s, r = {}) {
|
|
1408
1410
|
var d, I;
|
|
1409
|
-
let u =
|
|
1411
|
+
let u = p.utc(e.etd);
|
|
1410
1412
|
const l = { lat: e.lat, lng: e.lng }, h = [];
|
|
1411
|
-
for (; u.isBefore(
|
|
1412
|
-
const b = u.clone().utc().add(s, "day"), E = JSON.parse(JSON.stringify(
|
|
1413
|
+
for (; u.isBefore(n); ) {
|
|
1414
|
+
const b = u.clone().utc().add(s, "day"), E = JSON.parse(JSON.stringify(a.route)), k = JSON.parse(JSON.stringify(a.waypoints)), w = o[i], v = await H.analyseInstantWithThreshed(
|
|
1413
1415
|
l,
|
|
1414
1416
|
u.utc().format(),
|
|
1415
1417
|
b,
|
|
1416
1418
|
t,
|
|
1417
|
-
|
|
1419
|
+
w,
|
|
1418
1420
|
E,
|
|
1419
1421
|
k,
|
|
1420
1422
|
e.meteoVendor,
|
|
@@ -1423,7 +1425,7 @@ class H {
|
|
|
1423
1425
|
e.useRouteParam,
|
|
1424
1426
|
r
|
|
1425
1427
|
);
|
|
1426
|
-
v && (await H.calculateCost(v,
|
|
1428
|
+
v && (await H.calculateCost(v, w, e, r), C == null || C.info(
|
|
1427
1429
|
"[%s][L%d-%d] analyse from %s to %s cost: %j",
|
|
1428
1430
|
r.requestId,
|
|
1429
1431
|
r.level,
|
|
@@ -1436,12 +1438,12 @@ class H {
|
|
|
1436
1438
|
bunker: v.cost.bunker,
|
|
1437
1439
|
distance: v.distance,
|
|
1438
1440
|
hours: v.totalHrs,
|
|
1439
|
-
cp: `${
|
|
1441
|
+
cp: `${w.speed}/${w.fo}/${w.dgo}`
|
|
1440
1442
|
}
|
|
1441
1443
|
)), r.counter = r.counter + 1;
|
|
1442
1444
|
const m = (I = (d = v == null ? void 0 : v.sample) == null ? void 0 : d.hours) == null ? void 0 : I.at(-1);
|
|
1443
1445
|
if (m)
|
|
1444
|
-
l.lat = m.lat, l.lng = m.lng, u =
|
|
1446
|
+
l.lat = m.lat, l.lng = m.lng, u = p(m.eta), h.push(v), i = i ? 0 : 1;
|
|
1445
1447
|
else
|
|
1446
1448
|
break;
|
|
1447
1449
|
}
|
|
@@ -1454,10 +1456,10 @@ class H {
|
|
|
1454
1456
|
* @param props
|
|
1455
1457
|
* @param options
|
|
1456
1458
|
*/
|
|
1457
|
-
static async calculateCost(e, t,
|
|
1459
|
+
static async calculateCost(e, t, n, o = {}) {
|
|
1458
1460
|
var i;
|
|
1459
1461
|
if (e) {
|
|
1460
|
-
const
|
|
1462
|
+
const a = (n.addComm || 0) >= 1 ? (n.addComm || 0) / 100 : n.addComm || 0, s = Math.round((n.dailyHire || 0) * (e.suspend || 0) / 24 * 1e3) / 1e3, r = Math.round(e.totalHrs / 24 * (n.dailyHire || 0) * (1 - a) * 1e3) / 1e3 + s, u = Math.round(e.totalFoCons * (n.priceFO || 0) * 1e3) / 1e3, l = Math.round((e.totalDgoCons + (((i = e.extend) == null ? void 0 : i.totalDgoConsInECA) || 0)) * (n.priceDGO || 0) * 1e3) / 1e3;
|
|
1461
1463
|
e.cost = {
|
|
1462
1464
|
total: Math.round((r + u + l) * 1e3) / 1e3,
|
|
1463
1465
|
hire: Math.round(r * 1e3) / 1e3,
|
|
@@ -1472,21 +1474,21 @@ class H {
|
|
|
1472
1474
|
* 计算单cp模式下的ECA属性
|
|
1473
1475
|
*
|
|
1474
1476
|
*/
|
|
1475
|
-
static async calculateECA(e, t,
|
|
1477
|
+
static async calculateECA(e, t, n = {}) {
|
|
1476
1478
|
var r, u, l, h;
|
|
1477
1479
|
const o = await R.intersectInECA((e == null ? void 0 : e.route) || []);
|
|
1478
|
-
let i = 0,
|
|
1480
|
+
let i = 0, a = 0, s = 0;
|
|
1479
1481
|
(u = (r = e == null ? void 0 : e.sample) == null ? void 0 : r.wps) == null || u.forEach((d) => {
|
|
1480
|
-
d.positionTime =
|
|
1482
|
+
d.positionTime = p.utc(d.etd || d.eta).unix();
|
|
1481
1483
|
});
|
|
1482
1484
|
for (const d of o) {
|
|
1483
1485
|
i += d.distance;
|
|
1484
1486
|
const I = await R.deadReckoningTime((l = d.waypoints) == null ? void 0 : l.at(0), e.sample.all || e.sample.wps), b = await R.deadReckoningTime((h = d.waypoints) == null ? void 0 : h.at(-1), e.sample.all || e.sample.wps);
|
|
1485
|
-
d.in = I, d.out = b, d.totalHrs = J.roundPrecision((b.positionTime - I.positionTime) / 3600, 3), d.totalDgoCons = J.roundPrecision(t.fo / 24 * d.totalHrs, 3),
|
|
1487
|
+
d.in = I, d.out = b, d.totalHrs = J.roundPrecision((b.positionTime - I.positionTime) / 3600, 3), d.totalDgoCons = J.roundPrecision(t.fo / 24 * d.totalHrs, 3), a += d.totalHrs, s += d.totalDgoCons;
|
|
1486
1488
|
}
|
|
1487
|
-
return i = J.roundPrecision(i, 3),
|
|
1489
|
+
return i = J.roundPrecision(i, 3), a = J.roundPrecision(a, 3), s = J.roundPrecision(s, 3), {
|
|
1488
1490
|
distanceInECA: i,
|
|
1489
|
-
hoursInECA:
|
|
1491
|
+
hoursInECA: a,
|
|
1490
1492
|
totalDgoConsInECA: s,
|
|
1491
1493
|
eca: o
|
|
1492
1494
|
};
|
|
@@ -1498,61 +1500,61 @@ class H {
|
|
|
1498
1500
|
*/
|
|
1499
1501
|
static async mergeSpeeds(e, t = {}) {
|
|
1500
1502
|
var m, c;
|
|
1501
|
-
const
|
|
1503
|
+
const n = {
|
|
1502
1504
|
hours: [],
|
|
1503
1505
|
wps: [],
|
|
1504
1506
|
days: [],
|
|
1505
1507
|
all: []
|
|
1506
1508
|
}, o = e.reduce((f, y) => f + y.distance, 0), i = e.reduce((f, y) => {
|
|
1507
|
-
var
|
|
1508
|
-
return f + (((
|
|
1509
|
-
}, 0),
|
|
1510
|
-
var
|
|
1511
|
-
return f + (((
|
|
1509
|
+
var S;
|
|
1510
|
+
return f + (((S = y.extend) == null ? void 0 : S.distanceInECA) || 0);
|
|
1511
|
+
}, 0), a = e.reduce((f, y) => f + y.totalHrs, 0), s = e.reduce((f, y) => {
|
|
1512
|
+
var S;
|
|
1513
|
+
return f + (((S = y.extend) == null ? void 0 : S.hoursInECA) || 0);
|
|
1512
1514
|
}, 0), r = e.reduce((f, y) => {
|
|
1513
|
-
var
|
|
1514
|
-
return f + (((
|
|
1515
|
-
}, 0), u = e.reduce((f, y) => f + y.wxFactor * y.totalHrs /
|
|
1515
|
+
var S;
|
|
1516
|
+
return f + (((S = y.extend) == null ? void 0 : S.totalDgoConsInECA) || 0);
|
|
1517
|
+
}, 0), u = e.reduce((f, y) => f + y.wxFactor * y.totalHrs / a, 0), l = e.reduce((f, y) => f + y.cFactor * y.totalHrs / a, 0), h = e.reduce((f, y) => f + y.totalFoCons, 0), d = e.reduce((f, y) => f + y.totalDgoCons, 0), I = e.reduce((f, y) => f + y.cost.total, 0), b = e.reduce((f, y) => f + y.cost.hire, 0), E = e.reduce((f, y) => f + y.cost.bunker, 0), k = [], w = [];
|
|
1516
1518
|
let v;
|
|
1517
1519
|
for (const f of e) {
|
|
1518
|
-
|
|
1519
|
-
const y = f.sample.hours,
|
|
1520
|
-
v && (N.distanceFromPrevious = v.distanceFromPrevious, N.distanceFromStart = v.distanceFromStart, y.forEach((
|
|
1521
|
-
Y && (
|
|
1522
|
-
}),
|
|
1523
|
-
Y && (
|
|
1524
|
-
}), M.at(0).distanceFromPrevious = v.distanceFromPrevious, M.at(0).distanceFromStart = v.distanceFromStart, M.forEach((
|
|
1525
|
-
Y && (
|
|
1526
|
-
}), j.at(0).distanceFromPrevious = v.distanceFromPrevious, j.at(0).distanceFromStart = v.distanceFromStart, j.forEach((
|
|
1527
|
-
Y && (
|
|
1520
|
+
w.push(...((m = f.extend) == null ? void 0 : m.eca) || []);
|
|
1521
|
+
const y = f.sample.hours, S = f.sample.all, M = f.sample.wps, j = f.sample.days, N = y.at(0);
|
|
1522
|
+
v && (N.distanceFromPrevious = v.distanceFromPrevious, N.distanceFromStart = v.distanceFromStart, y.forEach((F, Y) => {
|
|
1523
|
+
Y && (F.distanceFromStart = F.distanceFromStart + v.distanceFromStart);
|
|
1524
|
+
}), S.at(0).distanceFromPrevious = v.distanceFromPrevious, S.at(0).distanceFromStart = v.distanceFromStart, S.forEach((F, Y) => {
|
|
1525
|
+
Y && (F.distanceFromStart = F.distanceFromStart + v.distanceFromStart);
|
|
1526
|
+
}), M.at(0).distanceFromPrevious = v.distanceFromPrevious, M.at(0).distanceFromStart = v.distanceFromStart, M.forEach((F, Y) => {
|
|
1527
|
+
Y && (F.distanceFromStart = F.distanceFromStart + v.distanceFromStart);
|
|
1528
|
+
}), j.at(0).distanceFromPrevious = v.distanceFromPrevious, j.at(0).distanceFromStart = v.distanceFromStart, j.forEach((F, Y) => {
|
|
1529
|
+
Y && (F.distanceFromStart = F.distanceFromStart + v.distanceFromStart);
|
|
1528
1530
|
})), N.cp = f.cost.cp;
|
|
1529
|
-
const D = [f.etd, f.eta], L = k.findIndex((
|
|
1530
|
-
L === -1 ? (N.cp.segment = [D], k.push(N.cp)) : k[L].segment.push(D), y.forEach((
|
|
1531
|
+
const D = [f.etd, f.eta], L = k.findIndex((F) => F.id === N.cp.id);
|
|
1532
|
+
L === -1 ? (N.cp.segment = [D], k.push(N.cp)) : k[L].segment.push(D), y.forEach((F) => {
|
|
1531
1533
|
var A;
|
|
1532
|
-
((A =
|
|
1533
|
-
}),
|
|
1534
|
+
((A = n.hours) == null ? void 0 : A.findIndex((V) => V.eta === F.eta)) === -1 && n.hours.push(F);
|
|
1535
|
+
}), S.forEach((F) => {
|
|
1534
1536
|
var A;
|
|
1535
|
-
((A =
|
|
1536
|
-
}), M.forEach((
|
|
1537
|
+
((A = n.all) == null ? void 0 : A.findIndex((V) => V.eta === F.eta)) === -1 && n.all.push(F);
|
|
1538
|
+
}), M.forEach((F) => {
|
|
1537
1539
|
var A;
|
|
1538
|
-
((A =
|
|
1539
|
-
}), j.forEach((
|
|
1540
|
+
((A = n.wps) == null ? void 0 : A.findIndex((V) => V.eta === F.eta)) === -1 && n.wps.push(F);
|
|
1541
|
+
}), j.forEach((F) => {
|
|
1540
1542
|
var A;
|
|
1541
|
-
((A =
|
|
1543
|
+
((A = n == null ? void 0 : n.days) == null ? void 0 : A.findIndex((V) => V.eta === F.eta)) === -1 && n.days.push(F);
|
|
1542
1544
|
});
|
|
1543
|
-
const W = (c =
|
|
1544
|
-
W === -1 ?
|
|
1545
|
+
const W = (c = n.wps) == null ? void 0 : c.findIndex((F) => F.eta === N.eta);
|
|
1546
|
+
W === -1 ? n.wps.push(N) : n.wps[W] = N, v = y.at(-1);
|
|
1545
1547
|
}
|
|
1546
|
-
return
|
|
1547
|
-
const
|
|
1548
|
-
if (
|
|
1549
|
-
const M = f.distanceFromStart - (
|
|
1548
|
+
return n.wps.sort((f, y) => p(f.etd).unix() - p(y.etd).unix()), n.wps.forEach((f, y) => {
|
|
1549
|
+
const S = n.wps[y - 1];
|
|
1550
|
+
if (S) {
|
|
1551
|
+
const M = f.distanceFromStart - (S.distanceFromStart || 0), j = p(f.eta || f.etd).diff(p(S.etd || S.eta), "hour", !0), N = Math.round(M / j * 100) / 100;
|
|
1550
1552
|
f.avgSpd = N;
|
|
1551
|
-
const D = R.calculateBearing(
|
|
1552
|
-
|
|
1553
|
+
const D = R.calculateBearing(S, f);
|
|
1554
|
+
S.bearing = D;
|
|
1553
1555
|
}
|
|
1554
1556
|
}), {
|
|
1555
|
-
sample:
|
|
1557
|
+
sample: n,
|
|
1556
1558
|
etd: e.at(0).etd,
|
|
1557
1559
|
eta: e.at(-1).eta,
|
|
1558
1560
|
from: e.at(0).from,
|
|
@@ -1560,8 +1562,8 @@ class H {
|
|
|
1560
1562
|
v0: e.at(0).v0,
|
|
1561
1563
|
label: "Combined",
|
|
1562
1564
|
distance: Math.round(o * 1e3) / 1e3,
|
|
1563
|
-
totalHrs: Math.round(
|
|
1564
|
-
avgSpeed: Math.round(o /
|
|
1565
|
+
totalHrs: Math.round(a * 1e3) / 1e3,
|
|
1566
|
+
avgSpeed: Math.round(o / a * 1e3) / 1e3,
|
|
1565
1567
|
wxFactor: Math.round(u * 1e3) / 1e3,
|
|
1566
1568
|
cFactor: Math.round(l * 1e3) / 1e3,
|
|
1567
1569
|
totalFoCons: Math.round(h * 1e3) / 1e3,
|
|
@@ -1573,7 +1575,7 @@ class H {
|
|
|
1573
1575
|
},
|
|
1574
1576
|
extend: {
|
|
1575
1577
|
cps: k,
|
|
1576
|
-
eca:
|
|
1578
|
+
eca: w,
|
|
1577
1579
|
distanceInECA: Math.round(i * 1e3) / 1e3,
|
|
1578
1580
|
hoursInECA: Math.round(s * 1e3) / 1e3,
|
|
1579
1581
|
totalDgoConsInECA: Math.round(r * 1e3) / 1e3,
|
|
@@ -1592,7 +1594,7 @@ export {
|
|
|
1592
1594
|
Tt as MyVesselImpl,
|
|
1593
1595
|
xt as ShipxyImpl,
|
|
1594
1596
|
H as SpeedHelper,
|
|
1595
|
-
|
|
1597
|
+
wt as SpeedLabel,
|
|
1596
1598
|
bt as VesselTag,
|
|
1597
1599
|
Dt as alertHelper
|
|
1598
1600
|
};
|