@idm-plugin/vessel 1.9.5 → 1.9.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 +311 -309
- package/dist/index.umd.cjs +1 -1
- package/dist/speed/src/index.d.ts +0 -6
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
var ht = Object.defineProperty;
|
|
2
|
-
var lt = (
|
|
3
|
-
var
|
|
2
|
+
var lt = (E, e, t) => e in E ? ht(E, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : E[e] = t;
|
|
3
|
+
var K = (E, e, t) => (lt(E, typeof e != "symbol" ? e + "" : e, t), t);
|
|
4
4
|
import B from "got";
|
|
5
|
-
import
|
|
5
|
+
import rt from "@log4js-node/log4js-api";
|
|
6
6
|
import g from "moment";
|
|
7
7
|
import { LngLatHelper as J, LaneHelper as W } from "@idm-plugin/geo2";
|
|
8
|
-
import { MeteoHelper2 as ft
|
|
9
|
-
import { Meteo2Assist as
|
|
8
|
+
import { MeteoHelper2 as ft } from "@idm-plugin/meteo2";
|
|
9
|
+
import { Meteo2Assist as it } from "@idm-plugin/meteo";
|
|
10
10
|
let p;
|
|
11
11
|
try {
|
|
12
|
-
p =
|
|
12
|
+
p = rt.getLogger("vessel");
|
|
13
13
|
} catch {
|
|
14
14
|
} finally {
|
|
15
15
|
}
|
|
@@ -22,7 +22,7 @@ class et {
|
|
|
22
22
|
let t, n;
|
|
23
23
|
switch (e) {
|
|
24
24
|
case 0:
|
|
25
|
-
t = "在航(主机推动)", n = "
|
|
25
|
+
t = "在航(主机推动)", n = "Underway Using Engine";
|
|
26
26
|
break;
|
|
27
27
|
case 1:
|
|
28
28
|
t = "锚泊", n = "Anchored";
|
|
@@ -54,12 +54,12 @@ class et {
|
|
|
54
54
|
return { labelCn: t, labelEn: n };
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
|
-
class
|
|
57
|
+
class xt extends et {
|
|
58
58
|
constructor(t, n) {
|
|
59
59
|
super();
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
60
|
+
K(this, "clientId");
|
|
61
|
+
K(this, "clientSecret");
|
|
62
|
+
K(this, "token");
|
|
63
63
|
this.clientId = t, this.clientSecret = n;
|
|
64
64
|
}
|
|
65
65
|
async authToken(t = {}) {
|
|
@@ -69,30 +69,30 @@ class jt extends et {
|
|
|
69
69
|
client_secret: this.clientSecret,
|
|
70
70
|
grant_type: "client_credentials"
|
|
71
71
|
}
|
|
72
|
-
},
|
|
73
|
-
p == null || p.info("[%s] fetch access token from: %s - %j", t.requestId, n,
|
|
74
|
-
accessToken:
|
|
75
|
-
tokenType:
|
|
76
|
-
expiresIn:
|
|
77
|
-
scope:
|
|
78
|
-
jti:
|
|
72
|
+
}, o = await B.post(n, i).json();
|
|
73
|
+
p == null || p.info("[%s] fetch access token from: %s - %j", t.requestId, n, o), o.error || (this.token = {
|
|
74
|
+
accessToken: o.access_token,
|
|
75
|
+
tokenType: o.token_type,
|
|
76
|
+
expiresIn: o.expires_in,
|
|
77
|
+
scope: o.scope,
|
|
78
|
+
jti: o.jti,
|
|
79
79
|
issuedAt: g().utc().format()
|
|
80
80
|
});
|
|
81
81
|
}
|
|
82
82
|
async realTimePosition(t, n = {}) {
|
|
83
83
|
var d, r, h;
|
|
84
84
|
(!this.token || g().diff(g(this.token.issuedAt), "seconds") > ((d = this.token) == null ? void 0 : d.expiresIn) - 300) && await this.authToken(n);
|
|
85
|
-
const i = "https://svc.data.myvessel.cn/sdc/v1/vessels/status/location/unit",
|
|
85
|
+
const i = "https://svc.data.myvessel.cn/sdc/v1/vessels/status/location/unit", o = {
|
|
86
86
|
headers: {
|
|
87
87
|
Authorization: `${(r = this.token) == null ? void 0 : r.tokenType} ${(h = this.token) == null ? void 0 : h.accessToken}`
|
|
88
88
|
},
|
|
89
89
|
searchParams: { mmsi: t }
|
|
90
90
|
};
|
|
91
|
-
p == null || p.info("[%s] fetch realtime position from: %s - %j", n.requestId, i,
|
|
92
|
-
const
|
|
93
|
-
if (
|
|
94
|
-
return p == null || p.warn("[%s] fetch realtime position failed: %j", n.requestId, i, { message:
|
|
95
|
-
const s =
|
|
91
|
+
p == null || p.info("[%s] fetch realtime position from: %s - %j", n.requestId, i, o);
|
|
92
|
+
const a = await B.get(i, o).json();
|
|
93
|
+
if (a.code)
|
|
94
|
+
return p == null || p.warn("[%s] fetch realtime position failed: %j", n.requestId, i, { message: a.message, status: a.status, code: a.code }), a;
|
|
95
|
+
const s = a.data;
|
|
96
96
|
for (const M in s)
|
|
97
97
|
!isNaN(s[M]) && Number(s[M]) !== 1 / 0 && (s[M] = Number(s[M]));
|
|
98
98
|
if (s) {
|
|
@@ -131,18 +131,18 @@ class jt extends et {
|
|
|
131
131
|
} else
|
|
132
132
|
return {};
|
|
133
133
|
}
|
|
134
|
-
async trajectory(t, n, i,
|
|
134
|
+
async trajectory(t, n, i, o, a = !0, s = {}) {
|
|
135
135
|
(!this.token || g().diff(g(this.token.issuedAt), "seconds") > this.token.expiresIn - 300) && await this.authToken(s);
|
|
136
136
|
const d = await this.realTimePosition(t, s), r = g(n), h = g(i), M = [];
|
|
137
137
|
for (; h.diff(r, "day", !0) > 30; )
|
|
138
|
-
await this.trajectoryIn30Day(t, r, r.clone().add(30, "day"), d,
|
|
139
|
-
return await this.trajectoryIn30Day(t, r, h, d,
|
|
138
|
+
await this.trajectoryIn30Day(t, r, r.clone().add(30, "day"), d, o, M, s), r.add(30, "day");
|
|
139
|
+
return await this.trajectoryIn30Day(t, r, h, d, o, M, s), M;
|
|
140
140
|
}
|
|
141
|
-
async trajectoryIn30Day(t, n, i,
|
|
142
|
-
var m,
|
|
141
|
+
async trajectoryIn30Day(t, n, i, o, a, s, d = {}) {
|
|
142
|
+
var m, C, S, w, b;
|
|
143
143
|
const r = "https://svc.data.myvessel.cn/sdc/v1/vessels/status/track", h = {
|
|
144
144
|
headers: {
|
|
145
|
-
Authorization: `${(m = this.token) == null ? void 0 : m.tokenType} ${(
|
|
145
|
+
Authorization: `${(m = this.token) == null ? void 0 : m.tokenType} ${(C = this.token) == null ? void 0 : C.accessToken}`
|
|
146
146
|
},
|
|
147
147
|
json: {
|
|
148
148
|
mmsi: t,
|
|
@@ -155,13 +155,13 @@ class jt extends et {
|
|
|
155
155
|
if (M.code)
|
|
156
156
|
return p == null || p.warn("[%s] fetch trajectory failed: %j", d.requestId, r, { message: M.message, status: M.status, code: M.code }), M;
|
|
157
157
|
let y = -1;
|
|
158
|
-
const v = g(`${(w = (
|
|
158
|
+
const v = g(`${(w = (S = M.data) == null ? void 0 : S[0]) == null ? void 0 : w.postime} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
159
159
|
return (b = M.data) == null || b.forEach((c) => {
|
|
160
160
|
for (const Y in c)
|
|
161
161
|
!isNaN(c[Y]) && Number(c[Y]) !== 1 / 0 && (c[Y] = Number(c[Y]));
|
|
162
|
-
const f = g(`${c.postime} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00"), l = c.status, { labelCn: u, labelEn: I } = this.parseStatus(l),
|
|
162
|
+
const f = g(`${c.postime} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00"), l = c.status, { labelCn: u, labelEn: I } = this.parseStatus(l), k = {
|
|
163
163
|
mmsi: c.mmsi,
|
|
164
|
-
imo:
|
|
164
|
+
imo: o == null ? void 0 : o.imo,
|
|
165
165
|
lat: c.lat,
|
|
166
166
|
lng: c.lon,
|
|
167
167
|
sog: c.sog,
|
|
@@ -177,28 +177,28 @@ class jt extends et {
|
|
|
177
177
|
method: "trajectory",
|
|
178
178
|
vendor: "myVessel",
|
|
179
179
|
utc: f.utc().format()
|
|
180
|
-
}, D = Math.floor(f.diff(v, "minute", !0) / (
|
|
181
|
-
D !== y && (y = D, s.push(
|
|
180
|
+
}, D = Math.floor(f.diff(v, "minute", !0) / (a || 1));
|
|
181
|
+
D !== y && (y = D, s.push(k));
|
|
182
182
|
}), s;
|
|
183
183
|
}
|
|
184
184
|
}
|
|
185
185
|
class Et extends et {
|
|
186
186
|
constructor(t) {
|
|
187
187
|
super();
|
|
188
|
-
|
|
188
|
+
K(this, "token");
|
|
189
189
|
this.token = t;
|
|
190
190
|
}
|
|
191
191
|
async realTimePosition(t, n = {}) {
|
|
192
|
-
const i = "https://api.hifleet.com/position/position/get/token",
|
|
192
|
+
const i = "https://api.hifleet.com/position/position/get/token", o = {
|
|
193
193
|
searchParams: {
|
|
194
194
|
mmsi: t,
|
|
195
195
|
usertoken: this.token
|
|
196
196
|
}
|
|
197
|
-
},
|
|
198
|
-
p == null || p.info("[%s] fetch realtime position from: %s - %j", n.requestId, i,
|
|
199
|
-
const s =
|
|
197
|
+
}, a = await B.post(i, o).json();
|
|
198
|
+
p == null || p.info("[%s] fetch realtime position from: %s - %j", n.requestId, i, o);
|
|
199
|
+
const s = a == null ? void 0 : a.list;
|
|
200
200
|
if (!s)
|
|
201
|
-
return p == null || p.warn("[%s] fetch realtime position failed: %j", n.requestId, i,
|
|
201
|
+
return p == null || p.warn("[%s] fetch realtime position failed: %j", n.requestId, i, a), a;
|
|
202
202
|
for (const v in s)
|
|
203
203
|
!isNaN(s[v]) && Number(s[v]) !== 1 / 0 && (s[v] = Number(s[v]));
|
|
204
204
|
s.status = s.sp > 3 ? 0 : 1;
|
|
@@ -234,7 +234,7 @@ class Et extends et {
|
|
|
234
234
|
}
|
|
235
235
|
async search(t, n = {}) {
|
|
236
236
|
let i = "https://www.hifleet.com/hifleetapi/searchVesselOL.do";
|
|
237
|
-
const
|
|
237
|
+
const o = {
|
|
238
238
|
searchParams: {
|
|
239
239
|
keyword: t
|
|
240
240
|
},
|
|
@@ -244,24 +244,24 @@ class Et extends et {
|
|
|
244
244
|
Host: "www.hifleet.com"
|
|
245
245
|
}
|
|
246
246
|
};
|
|
247
|
-
let
|
|
248
|
-
p == null || p.info("[%s] fetch vessel props from: %s - %j", n.requestId, i,
|
|
249
|
-
for (const d in
|
|
250
|
-
!isNaN(
|
|
247
|
+
let a = await B.post(i, o).json();
|
|
248
|
+
p == null || p.info("[%s] fetch vessel props from: %s - %j", n.requestId, i, o), a instanceof Array && (a = a[0]);
|
|
249
|
+
for (const d in a)
|
|
250
|
+
!isNaN(a[d]) && Number(a[d]) !== 1 / 0 && (a[d] = Number(a[d]));
|
|
251
251
|
const s = {
|
|
252
|
-
mmsi:
|
|
253
|
-
name:
|
|
254
|
-
imo:
|
|
255
|
-
callSign:
|
|
256
|
-
length:
|
|
257
|
-
breadth:
|
|
258
|
-
draught:
|
|
259
|
-
type:
|
|
252
|
+
mmsi: a.m,
|
|
253
|
+
name: a.n,
|
|
254
|
+
imo: a.i,
|
|
255
|
+
callSign: a.c,
|
|
256
|
+
length: a.l,
|
|
257
|
+
breadth: a.b,
|
|
258
|
+
draught: a.dr,
|
|
259
|
+
type: a.t
|
|
260
260
|
};
|
|
261
|
-
return i = "https://www.hifleet.com/hifleetapi/sameShipSearch.do",
|
|
261
|
+
return i = "https://www.hifleet.com/hifleetapi/sameShipSearch.do", a = await B.post(i, o).json(), p == null || p.info("[%s] search vessel dead weight from: %s - %j", n.requestId, i, o), a instanceof Array && (a = a[0]), a && (s.deadweight = Number(a.dwt)), s;
|
|
262
262
|
}
|
|
263
263
|
async suggest(t, n = {}) {
|
|
264
|
-
const i = "https://www.hifleet.com/hifleetapi/getShipSuggest.do",
|
|
264
|
+
const i = "https://www.hifleet.com/hifleetapi/getShipSuggest.do", o = {
|
|
265
265
|
searchParams: {
|
|
266
266
|
q: t
|
|
267
267
|
},
|
|
@@ -270,10 +270,10 @@ class Et extends et {
|
|
|
270
270
|
Origin: "https://www.hifleet.com",
|
|
271
271
|
Host: "www.hifleet.com"
|
|
272
272
|
}
|
|
273
|
-
},
|
|
274
|
-
p == null || p.info("[%s] suggest vessel props from: %s - %j", n.requestId, i,
|
|
273
|
+
}, a = await B.post(i, o).json();
|
|
274
|
+
p == null || p.info("[%s] suggest vessel props from: %s - %j", n.requestId, i, o);
|
|
275
275
|
const s = [];
|
|
276
|
-
for (const d of
|
|
276
|
+
for (const d of a)
|
|
277
277
|
s.push({
|
|
278
278
|
mmsi: !d.mmsi || isNaN(d.mmsi) ? null : Number(d.mmsi),
|
|
279
279
|
name: d.name,
|
|
@@ -283,12 +283,12 @@ class Et extends et {
|
|
|
283
283
|
});
|
|
284
284
|
return s.sort((d, r) => r.score - d.score), s;
|
|
285
285
|
}
|
|
286
|
-
async trajectory(t, n, i,
|
|
286
|
+
async trajectory(t, n, i, o, a = !0, s = {}) {
|
|
287
287
|
var c, f, l;
|
|
288
288
|
const d = await this.realTimePosition(t, s);
|
|
289
289
|
let r = g(n);
|
|
290
290
|
const h = g(i), M = g();
|
|
291
|
-
if (
|
|
291
|
+
if (a) {
|
|
292
292
|
let u = h.diff(r, "d", !0);
|
|
293
293
|
u < 0 ? r = h.clone().subtract(40, "d") : u < 30 ? r.subtract(10, "d") : u < 60 ? r.subtract(5, "d") : r = h.clone().subtract(80, "d"), u = M.diff(h, "d", !0), h.add(u > 10 ? 240 : u * 24, "h");
|
|
294
294
|
}
|
|
@@ -301,17 +301,17 @@ class Et extends et {
|
|
|
301
301
|
}
|
|
302
302
|
}, v = "https://api.hifleet.com/position/trajectory/nocompressed/withstatic/token", m = await B.get(v, y).json();
|
|
303
303
|
p == null || p.info("[%s] fetch trajectory from: %s - %j", s.requestId, v, y);
|
|
304
|
-
let
|
|
305
|
-
m && (
|
|
306
|
-
const
|
|
304
|
+
let C;
|
|
305
|
+
m && (C = ((f = (c = m.ships) == null ? void 0 : c.offors) == null ? void 0 : f.ship) || [], C.length || p == null || p.warn("[%s] fetch trajectory failed: %j", s.requestId, m));
|
|
306
|
+
const S = [];
|
|
307
307
|
let w = -1;
|
|
308
|
-
const b = g(`${(l =
|
|
309
|
-
for (const u of
|
|
308
|
+
const b = g(`${(l = C == null ? void 0 : C[0]) == null ? void 0 : l.ti} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
309
|
+
for (const u of C) {
|
|
310
310
|
for (const P in u)
|
|
311
311
|
!isNaN(u[P]) && Number(u[P]) !== 1 / 0 && (u[P] = Number(u[P]));
|
|
312
312
|
const I = g(`${u.ti} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
313
313
|
u.status = u.sp > 4 ? 0 : 1;
|
|
314
|
-
const { labelEn:
|
|
314
|
+
const { labelEn: k, labelCn: D } = this.parseStatus(u.status), Y = {
|
|
315
315
|
mmsi: u.m,
|
|
316
316
|
name: u.n,
|
|
317
317
|
imo: d == null ? void 0 : d.imo,
|
|
@@ -325,19 +325,19 @@ class Et extends et {
|
|
|
325
325
|
utc: I.utc().format(),
|
|
326
326
|
status: u.status,
|
|
327
327
|
labelCn: D,
|
|
328
|
-
labelEn:
|
|
328
|
+
labelEn: k,
|
|
329
329
|
method: "trajectory",
|
|
330
330
|
vendor: "hifleet"
|
|
331
|
-
},
|
|
332
|
-
|
|
331
|
+
}, j = Math.floor(I.diff(b, "minute", !0) / (o || 1));
|
|
332
|
+
j !== w && (w = j, S.push(Y));
|
|
333
333
|
}
|
|
334
|
-
return
|
|
334
|
+
return S;
|
|
335
335
|
}
|
|
336
336
|
}
|
|
337
|
-
class
|
|
337
|
+
class jt extends et {
|
|
338
338
|
constructor(t) {
|
|
339
339
|
super();
|
|
340
|
-
|
|
340
|
+
K(this, "token");
|
|
341
341
|
this.token = t;
|
|
342
342
|
}
|
|
343
343
|
async realTimePosition(t, n = {}) {
|
|
@@ -347,10 +347,10 @@ class Nt extends et {
|
|
|
347
347
|
k: this.token,
|
|
348
348
|
enc: 1
|
|
349
349
|
}
|
|
350
|
-
},
|
|
351
|
-
if (p == null || p.info("[%s] fetch realtime position from: %s - %j", n.requestId,
|
|
352
|
-
return
|
|
353
|
-
const s =
|
|
350
|
+
}, o = "https://api.shipxy.com/apicall/GetSingleShip", a = await B.get(o, i).json();
|
|
351
|
+
if (p == null || p.info("[%s] fetch realtime position from: %s - %j", n.requestId, o, i), (a == null ? void 0 : a.status) !== 0)
|
|
352
|
+
return a;
|
|
353
|
+
const s = a.data[0];
|
|
354
354
|
for (const y in s)
|
|
355
355
|
!isNaN(s[y]) && Number(s[y]) !== 1 / 0 && (s[y] = Number(s[y]));
|
|
356
356
|
const { labelCn: d, labelEn: r } = await this.parseStatus(s.navistat), h = g.unix(s.lasttime);
|
|
@@ -377,7 +377,7 @@ class Nt extends et {
|
|
|
377
377
|
vendor: "shipxy"
|
|
378
378
|
};
|
|
379
379
|
}
|
|
380
|
-
async trajectory(t, n, i,
|
|
380
|
+
async trajectory(t, n, i, o, a = !0, s = {}) {
|
|
381
381
|
var b;
|
|
382
382
|
const d = await this.realTimePosition(t, s), r = g(n), h = g(i), M = "https://api.shipxy.com/apicall/GetShipTrack", y = {
|
|
383
383
|
searchParams: {
|
|
@@ -391,7 +391,7 @@ class Nt extends et {
|
|
|
391
391
|
}, v = await B.get(M, y).json();
|
|
392
392
|
if (p == null || p.info("[%s] fetch trajectory from: %s - %j", s.requestId, M, y), (v == null ? void 0 : v.status) !== 0)
|
|
393
393
|
return v;
|
|
394
|
-
const m = v == null ? void 0 : v.points,
|
|
394
|
+
const m = v == null ? void 0 : v.points, C = [], S = g.unix((b = m[0]) == null ? void 0 : b.utc);
|
|
395
395
|
let w = -1;
|
|
396
396
|
for (const c of m) {
|
|
397
397
|
const f = g.unix(c.utc), l = {
|
|
@@ -405,16 +405,16 @@ class Nt extends et {
|
|
|
405
405
|
utc: f.utc().format(),
|
|
406
406
|
method: "trajectory",
|
|
407
407
|
vendor: "shipxy"
|
|
408
|
-
}, u = Math.floor(f.diff(
|
|
409
|
-
u !== w && (w = u,
|
|
408
|
+
}, u = Math.floor(f.diff(S, "minute", !0) / (o || 1));
|
|
409
|
+
u !== w && (w = u, C.push(l));
|
|
410
410
|
}
|
|
411
|
-
return
|
|
411
|
+
return C;
|
|
412
412
|
}
|
|
413
413
|
}
|
|
414
|
-
class
|
|
414
|
+
class Nt extends et {
|
|
415
415
|
constructor(t) {
|
|
416
416
|
super();
|
|
417
|
-
|
|
417
|
+
K(this, "token");
|
|
418
418
|
this.token = t;
|
|
419
419
|
}
|
|
420
420
|
async getShipId(t, n = {}) {
|
|
@@ -425,8 +425,8 @@ class Tt extends et {
|
|
|
425
425
|
json: {
|
|
426
426
|
mmsiList: t
|
|
427
427
|
}
|
|
428
|
-
},
|
|
429
|
-
return p == null || p.info("[%s] fetch ship id from: %s - %j", n.requestId,
|
|
428
|
+
}, o = "https://api3.myships.com/sp/ships/getShipIdByMMSI", a = await B.post(o, i).json();
|
|
429
|
+
return p == null || p.info("[%s] fetch ship id from: %s - %j", n.requestId, o, i), a.code !== "0" ? a : a.data[0].shipId;
|
|
430
430
|
}
|
|
431
431
|
async getShipInfo(t, n = {}) {
|
|
432
432
|
const i = {
|
|
@@ -436,10 +436,10 @@ class Tt extends et {
|
|
|
436
436
|
json: {
|
|
437
437
|
shipId: t
|
|
438
438
|
}
|
|
439
|
-
},
|
|
440
|
-
if (p == null || p.info("[%s] fetch ship info from: %s - %j", n.requestId,
|
|
441
|
-
return
|
|
442
|
-
const s =
|
|
439
|
+
}, o = "https://api3.myships.com/sp/ships/aissta", a = await B.post(o, i).json();
|
|
440
|
+
if (p == null || p.info("[%s] fetch ship info from: %s - %j", n.requestId, o, i), a.code !== "0")
|
|
441
|
+
return a;
|
|
442
|
+
const s = a.data;
|
|
443
443
|
let d = s.imo;
|
|
444
444
|
return t === "407170" && (d = "9198379", p == null || p.warn("[%s] ship(%s) imo error: %s, should be %s", n.requestId, t, s.imo, d)), {
|
|
445
445
|
mmsi: s.mmsi,
|
|
@@ -452,21 +452,21 @@ class Tt extends et {
|
|
|
452
452
|
};
|
|
453
453
|
}
|
|
454
454
|
async realTimePosition(t, n = {}) {
|
|
455
|
-
const i = await this.getShipId(t, n),
|
|
455
|
+
const i = await this.getShipId(t, n), o = await this.getShipInfo(i, n), a = {
|
|
456
456
|
headers: {
|
|
457
457
|
appKey: this.token
|
|
458
458
|
},
|
|
459
459
|
json: {
|
|
460
460
|
shipId: i
|
|
461
461
|
}
|
|
462
|
-
}, s = "https://api3.myships.com/sp/ships/position/latest", d = await B.post(s,
|
|
463
|
-
p == null || p.info("[%s] fetch realtime position from: %s - %j", n.requestId, s,
|
|
462
|
+
}, s = "https://api3.myships.com/sp/ships/position/latest", d = await B.post(s, a).json();
|
|
463
|
+
p == null || p.info("[%s] fetch realtime position from: %s - %j", n.requestId, s, a);
|
|
464
464
|
const r = d.data[0];
|
|
465
465
|
for (const m in r)
|
|
466
466
|
!isNaN(r[m]) && Number(r[m]) !== 1 / 0 && (r[m] = Number(r[m]));
|
|
467
467
|
const { labelCn: h, labelEn: M } = await this.parseStatus(r.aisNavStatus), y = g.unix(r.posTime);
|
|
468
468
|
return {
|
|
469
|
-
...
|
|
469
|
+
...o,
|
|
470
470
|
mmsi: t,
|
|
471
471
|
lat: Math.round(r.lat / 1e4 / 60 * 1e5) / 1e5,
|
|
472
472
|
lng: Math.round(r.lon / 1e4 / 60 * 1e5) / 1e5,
|
|
@@ -483,14 +483,14 @@ class Tt extends et {
|
|
|
483
483
|
vendor: "myship"
|
|
484
484
|
};
|
|
485
485
|
}
|
|
486
|
-
async trajectory(t, n, i,
|
|
486
|
+
async trajectory(t, n, i, o, a = !0, s = {}) {
|
|
487
487
|
const d = g(n), r = g(i), h = await this.getShipId(t), M = await this.getShipInfo(h), y = [];
|
|
488
488
|
for (; r.diff(d, "day", !0) > 30; )
|
|
489
|
-
await this.trajectoryIn30Day(h, d.unix(), d.add(30, "day").unix(), M, t,
|
|
490
|
-
return await this.trajectoryIn30Day(h, d.unix(), r.unix(), M, t,
|
|
489
|
+
await this.trajectoryIn30Day(h, d.unix(), d.add(30, "day").unix(), M, t, o, y);
|
|
490
|
+
return await this.trajectoryIn30Day(h, d.unix(), r.unix(), M, t, o, y), y;
|
|
491
491
|
}
|
|
492
|
-
async trajectoryIn30Day(t, n, i,
|
|
493
|
-
var
|
|
492
|
+
async trajectoryIn30Day(t, n, i, o, a, s, d, r = {}) {
|
|
493
|
+
var S;
|
|
494
494
|
const h = {
|
|
495
495
|
headers: {
|
|
496
496
|
appKey: this.token
|
|
@@ -506,12 +506,12 @@ class Tt extends et {
|
|
|
506
506
|
const v = y.data;
|
|
507
507
|
for (const w in v)
|
|
508
508
|
!isNaN(v[w]) && Number(v[w]) !== 1 / 0 && (v[w] = Number(v[w]));
|
|
509
|
-
const m = g.unix((
|
|
510
|
-
let
|
|
509
|
+
const m = g.unix((S = v[0]) == null ? void 0 : S.posTime);
|
|
510
|
+
let C = -1;
|
|
511
511
|
for (const w of v) {
|
|
512
512
|
const b = g.unix(w.posTime), c = {
|
|
513
|
-
imo:
|
|
514
|
-
mmsi:
|
|
513
|
+
imo: o == null ? void 0 : o.imo,
|
|
514
|
+
mmsi: a,
|
|
515
515
|
lat: Math.round(w.lat / 1e4 / 60 * 1e5) / 1e5,
|
|
516
516
|
lng: Math.round(w.lon / 1e4 / 60 * 1e5) / 1e5,
|
|
517
517
|
sog: Math.round(w.sog / 10 * 100) / 100,
|
|
@@ -523,19 +523,19 @@ class Tt extends et {
|
|
|
523
523
|
method: "trajectory",
|
|
524
524
|
vendor: "myship"
|
|
525
525
|
}, f = Math.floor(b.diff(m, "minute", !0) / (s || 1));
|
|
526
|
-
f !==
|
|
526
|
+
f !== C && (C = f, d.push(c));
|
|
527
527
|
}
|
|
528
528
|
return d;
|
|
529
529
|
}
|
|
530
530
|
}
|
|
531
531
|
let _;
|
|
532
532
|
try {
|
|
533
|
-
_ =
|
|
533
|
+
_ = rt.getLogger("vessel");
|
|
534
534
|
} catch {
|
|
535
535
|
} finally {
|
|
536
536
|
}
|
|
537
|
-
var
|
|
538
|
-
class
|
|
537
|
+
var mt = /* @__PURE__ */ ((E) => (E.NOTICE = "NOTICE", E.WARN = "WARN", E.HEAVY = "HEAVY", E.SEVERE = "SEVERE", E.ERROR = "ERROR", E.FATAL = "FATAL", E))(mt || {});
|
|
538
|
+
class yt {
|
|
539
539
|
/**
|
|
540
540
|
* 解析告警规则, 多规则场景
|
|
541
541
|
* @param rule
|
|
@@ -547,21 +547,21 @@ class Mt {
|
|
|
547
547
|
parsePrinciple(e, t = {}) {
|
|
548
548
|
var s, d, r;
|
|
549
549
|
_ == null || _.info("[%s] parse rule: %s", t.requestId, e);
|
|
550
|
-
const n = new RegExp("(?<=\\[)(.+)(?=])", "g"), i = e.match(n) ? (s = e.match(n)) == null ? void 0 : s[0] : void 0,
|
|
551
|
-
if (!
|
|
550
|
+
const n = new RegExp("(?<=\\[)(.+)(?=])", "g"), i = e.match(n) ? (s = e.match(n)) == null ? void 0 : s[0] : void 0, o = i == null ? void 0 : i.split(";");
|
|
551
|
+
if (!o)
|
|
552
552
|
return;
|
|
553
|
-
const
|
|
554
|
-
for (let h = 0; h < (
|
|
555
|
-
const M = (r = (d =
|
|
553
|
+
const a = {};
|
|
554
|
+
for (let h = 0; h < (o == null ? void 0 : o.length); h++) {
|
|
555
|
+
const M = (r = (d = o[h].match(n)) == null ? void 0 : d[0]) == null ? void 0 : r.split("],");
|
|
556
556
|
if (h === 0 && !M)
|
|
557
|
-
|
|
557
|
+
a.scope = o[0];
|
|
558
558
|
else if (M)
|
|
559
559
|
for (let y = 0, v = M.length; y < v; y++) {
|
|
560
560
|
const m = this.parseRule(M[y]);
|
|
561
|
-
m && (
|
|
561
|
+
m && (a[m.level] ? m.key ? a[m.level][m == null ? void 0 : m.key] = m : a[m.level] = m : m.key ? a[m.level] = { [m == null ? void 0 : m.key]: m } : a[m.level] = m);
|
|
562
562
|
}
|
|
563
563
|
}
|
|
564
|
-
return
|
|
564
|
+
return a;
|
|
565
565
|
}
|
|
566
566
|
/**
|
|
567
567
|
* 解析单一告警规则
|
|
@@ -570,16 +570,16 @@ class Mt {
|
|
|
570
570
|
* @param options
|
|
571
571
|
*/
|
|
572
572
|
parseRule(e, t = {}) {
|
|
573
|
-
var
|
|
573
|
+
var a;
|
|
574
574
|
_ == null || _.info("[%s] parse rule: %s", t.requestId, e), e = e.startsWith("[") ? e : `[${e}`, e = e.endsWith("]") ? e : `${e}]`;
|
|
575
|
-
const n = new RegExp("(?<=\\[)(.+?)(?=])", "g"), i = (
|
|
576
|
-
if (
|
|
575
|
+
const n = new RegExp("(?<=\\[)(.+?)(?=])", "g"), i = (a = e == null ? void 0 : e.match(n)) == null ? void 0 : a[0], o = i == null ? void 0 : i.split(",");
|
|
576
|
+
if (o)
|
|
577
577
|
return {
|
|
578
|
-
operator:
|
|
579
|
-
number: Number.isNaN(Number(
|
|
580
|
-
level:
|
|
581
|
-
time: Number(
|
|
582
|
-
key:
|
|
578
|
+
operator: o[0],
|
|
579
|
+
number: Number.isNaN(Number(o[1])) ? o[1] : Number(o[1]),
|
|
580
|
+
level: o[2],
|
|
581
|
+
time: Number(o[3]),
|
|
582
|
+
key: o[4]
|
|
583
583
|
};
|
|
584
584
|
}
|
|
585
585
|
/**
|
|
@@ -589,25 +589,25 @@ class Mt {
|
|
|
589
589
|
* @param options
|
|
590
590
|
*/
|
|
591
591
|
checkWeather(e, t, n = {}) {
|
|
592
|
-
var m,
|
|
593
|
-
let i = 0,
|
|
594
|
-
const d = Math.round(((
|
|
592
|
+
var m, C, S, w, b, c, f, l, u, I, k, D, Y, j, P;
|
|
593
|
+
let i = 0, o = 0, a = 0, s = 0;
|
|
594
|
+
const d = Math.round(((C = (m = t == null ? void 0 : t.SEVERE) == null ? void 0 : m.sigWave) == null ? void 0 : C.number) * 1.6 * 100) / 100, r = (w = (S = t == null ? void 0 : t.SEVERE) == null ? void 0 : S.sigWave) == null ? void 0 : w.number, h = (c = (b = t == null ? void 0 : t.HEAVY) == null ? void 0 : b.sigWave) == null ? void 0 : c.number, M = Math.round((((l = (f = t == null ? void 0 : t.SEVERE) == null ? void 0 : f.wind) == null ? void 0 : l.number) + 2) * 100) / 100, y = (I = (u = t == null ? void 0 : t.SEVERE) == null ? void 0 : u.wind) == null ? void 0 : I.number, v = (D = (k = t == null ? void 0 : t.HEAVY) == null ? void 0 : k.wind) == null ? void 0 : D.number;
|
|
595
595
|
for (let T = 0; T < (e == null ? void 0 : e.length); T++) {
|
|
596
|
-
const N = e[T], A = (
|
|
597
|
-
s =
|
|
596
|
+
const N = e[T], A = (j = (Y = N == null ? void 0 : N.meteo) == null ? void 0 : Y.wave) == null ? void 0 : j.sig, R = (P = N == null ? void 0 : N.meteo) == null ? void 0 : P.wind, U = T ? g(N.eta).diff(g(e[T - 1].eta), "hour", !0) : 0;
|
|
597
|
+
s = U > s ? U : s, _ == null || _.info("[%s] check sig.wave: %j", n.requestId, { ...A, dgThd4Wv: d, svThd4Wv: r, hvThd4Wv: h }), (A == null ? void 0 : A.height) >= d ? N.isDangerous = !0 : (A == null ? void 0 : A.height) >= r ? N.isSevere = !0 : (A == null ? void 0 : A.height) >= h && (N.isHeavy = !0), _ == null || _.info("[%s] check wind: %j", n.requestId, { ...R, dgThd4Wd: M, svThd4Wd: y, hvThd4Wd: v }), (R == null ? void 0 : R.scale) >= M ? (N.isDangerous = !0, delete N.isSevere, delete N.isHeavy) : (R == null ? void 0 : R.scale) > y ? (N.isDangerous || (N.isSevere = !0), delete N.isHeavy) : (R == null ? void 0 : R.scale) === v && !N.isDangerous && !N.isSevere && (N.isHeavy = !0), i += N.isDangerous ? U : 0, o += N.isSevere ? U : 0, a += N.isHeavy ? U : 0;
|
|
598
598
|
}
|
|
599
|
-
return i = Math.round(i * 100) / 100,
|
|
599
|
+
return i = Math.round(i * 100) / 100, o = Math.round(o * 100) / 100, a = Math.round(a * 100) / 100, s = Math.round(s), { sample: e, dangerous: i, severe: o, heavy: a, step: s < 3 ? 3 : s, wind: { dgThd4Wd: M, svThd4Wd: y, hvThd4Wd: v }, sig: { dgThd4Wv: d, svThd4Wv: r, hvThd4Wv: h } };
|
|
600
600
|
}
|
|
601
601
|
}
|
|
602
|
-
const
|
|
603
|
-
let
|
|
602
|
+
const Tt = new yt();
|
|
603
|
+
let F;
|
|
604
604
|
try {
|
|
605
|
-
|
|
605
|
+
F = rt.getLogger("vessel");
|
|
606
606
|
} catch {
|
|
607
607
|
} finally {
|
|
608
608
|
}
|
|
609
|
-
const
|
|
610
|
-
var
|
|
609
|
+
const Mt = new ft("", !0);
|
|
610
|
+
var gt = /* @__PURE__ */ ((E) => (E.common = "common", E.container = "container", E.tugs = "tugs", E))(gt || {}), bt = /* @__PURE__ */ ((E) => (E.Ballast = "Ballast", E.Laden = "Laden", E))(bt || {}), pt = /* @__PURE__ */ ((E) => (E.Cp = "CP", E.Perf = "Basis", E.Instruct = "Other", E))(pt || {});
|
|
611
611
|
class O {
|
|
612
612
|
/**
|
|
613
613
|
* @see https://baike.baidu.com/item/%E6%96%B9%E5%BD%A2%E7%B3%BB%E6%95%B0/4965568?fr=aladdin
|
|
@@ -622,10 +622,10 @@ class O {
|
|
|
622
622
|
* @return [0.55, 0.85]
|
|
623
623
|
*/
|
|
624
624
|
static blockCoefficient(e, t, n, i) {
|
|
625
|
-
let
|
|
626
|
-
|
|
627
|
-
const
|
|
628
|
-
return
|
|
625
|
+
let o = Math.round(e / (t * n * i) * 100) / 100;
|
|
626
|
+
o = o < 0.55 ? 0.55 : o > 0.85 ? 0.85 : o;
|
|
627
|
+
const a = [0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85], s = a.map((d) => Math.abs(d - o));
|
|
628
|
+
return a[s.indexOf(Math.min(...s))];
|
|
629
629
|
}
|
|
630
630
|
/**
|
|
631
631
|
* @see https://baike.baidu.com/item/%E5%BC%97%E5%8A%B3%E5%BE%B7%E6%95%B0/228891?fromModule=search-result_lemma-recommend
|
|
@@ -659,7 +659,7 @@ class O {
|
|
|
659
659
|
0.8: [2.6, -13.1, -15.1],
|
|
660
660
|
0.85: [3.1, -18.7, 28]
|
|
661
661
|
};
|
|
662
|
-
let
|
|
662
|
+
let a = {
|
|
663
663
|
0.55: [1.7, -1.4, -7.4],
|
|
664
664
|
0.6: [2.2, -2.5, -9.7],
|
|
665
665
|
0.65: [2.6, -3.7, -11.6],
|
|
@@ -668,7 +668,7 @@ class O {
|
|
|
668
668
|
0.8: [3, -16.3, -21.6],
|
|
669
669
|
0.85: [3.4, -20.9, 31.8]
|
|
670
670
|
}[e];
|
|
671
|
-
return n === "Laden" && (
|
|
671
|
+
return n === "Laden" && (a = i[e]), a[0] + a[1] * t + a[2] * Math.pow(t, 2);
|
|
672
672
|
}
|
|
673
673
|
/**
|
|
674
674
|
* 失速方向因子
|
|
@@ -698,8 +698,8 @@ class O {
|
|
|
698
698
|
*/
|
|
699
699
|
static vesselTagFactor(e, t, n, i = 0) {
|
|
700
700
|
i = i > 6 ? i - 0.9 * (i - 6) : i;
|
|
701
|
-
let
|
|
702
|
-
return n === "container" ?
|
|
701
|
+
let o;
|
|
702
|
+
return n === "container" ? o = 0.7 * i + Math.pow(i, 6.5) / (22 * Math.pow(e, 2 / 3)) : t === "Ballast" ? o = 0.7 * i + Math.pow(i, 6.5) / (2.7 * Math.pow(e, 2 / 3)) : o = 0.5 * i + Math.pow(i, 6.5) / (2.7 * Math.pow(e, 2 / 3)), o;
|
|
703
703
|
}
|
|
704
704
|
/**
|
|
705
705
|
* 浪高影响因子
|
|
@@ -721,16 +721,16 @@ class O {
|
|
|
721
721
|
*/
|
|
722
722
|
static assembleProperties(e, t, n, i) {
|
|
723
723
|
var y;
|
|
724
|
-
const
|
|
724
|
+
const o = e.lbp ?? e.length ?? e.lengthOverall ?? 198.9642, a = e.draught ?? 8, s = e.breadthMoulded ?? e.breadth ?? e.breadthExtreme ?? 32.4572, d = e.deadweight ?? 67035.7773, r = ((y = e == null ? void 0 : e.type) == null ? void 0 : y.toLowerCase()) || "common";
|
|
725
725
|
return {
|
|
726
726
|
tag: r.indexOf("container") > -1 ? "container" : r.indexOf("tugs") > -1 ? "tugs" : "common",
|
|
727
|
-
lbp:
|
|
727
|
+
lbp: o,
|
|
728
728
|
loadCondition: t,
|
|
729
|
-
draught:
|
|
729
|
+
draught: a,
|
|
730
730
|
breadthMoulded: s,
|
|
731
731
|
// 排水量(吨)= 载重量(吨)/ 1.025 + 吃水(米)× 船舶型宽(米)× 船舶型长(米)× 0.7
|
|
732
732
|
// 其中,1.025是指海水的密度,吨是指公吨,吃水是指船舶的最大吃水深度。船舶型宽是指船舶的最大型宽,船舶型长是指船舶的设计型长。上述公式是针对常规船舶适用的,不同类型的船舶可能会有一些差异。
|
|
733
|
-
displacement: Math.round((d / 1.025 +
|
|
733
|
+
displacement: Math.round((d / 1.025 + a * s * o * 0.7) * 1e4) / 1e4,
|
|
734
734
|
// 换算为m/s
|
|
735
735
|
speed: Math.round((n ?? 14.1382) * 1852 / 3600 * 1e4) / 1e4,
|
|
736
736
|
bearing: i || 90
|
|
@@ -746,20 +746,22 @@ class O {
|
|
|
746
746
|
* @param useMeteo true 启用气象分析
|
|
747
747
|
* @param useRouteParam true 启用设置速度
|
|
748
748
|
*/
|
|
749
|
-
static async speedLoseAt(e, t, n, i = "",
|
|
749
|
+
static async speedLoseAt(e, t, n, i = "", o = 2, a = !0, s = !1, d = {}) {
|
|
750
750
|
let r;
|
|
751
|
-
if (t.velocity && s && (e.speed = J.roundPrecision(t.velocity * 1852 / 3600, 6)),
|
|
751
|
+
if (t.velocity && s && (e.speed = J.roundPrecision(t.velocity * 1852 / 3600, 6)), a) {
|
|
752
752
|
let h;
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
}
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
753
|
+
try {
|
|
754
|
+
i = (i == null ? void 0 : i.toUpperCase()) === "CMEMS" ? "ECMWF" : i, i = (i == null ? void 0 : i.toUpperCase()) === "METEO2" ? "best_match" : i;
|
|
755
|
+
const { weatherModels: m, marineModels: C } = await it.autoPickMeteoModel(i), S = await Mt.spotForecast(t.lat, t.lng, n.utc().format(), !1, !1, !0, {
|
|
756
|
+
...d,
|
|
757
|
+
weatherModels: m,
|
|
758
|
+
marineModels: C
|
|
759
|
+
}), [w] = it.pickHourly(S, n);
|
|
760
|
+
h = it.toLegacy(w);
|
|
761
|
+
} catch (m) {
|
|
762
|
+
F.warn("[%s] meteo2 spot(%j) forecast failed: %s", d.requestId, { ...t, eta: n.utc().format(), source: i }, m);
|
|
763
|
+
}
|
|
764
|
+
const M = O.weatherFactor(e, h), y = O.currentFactor(e.bearing, h == null ? void 0 : h.current, o), v = Math.round((e.speed * 1.943844 + M + y) * 100) / 100;
|
|
763
765
|
r = {
|
|
764
766
|
meteo: { ...h },
|
|
765
767
|
wxFactor: M,
|
|
@@ -791,53 +793,53 @@ class O {
|
|
|
791
793
|
* @param useRouteParam true 启用航线上设置的参数 { suspend: 停留时长(小时), velocity: 速度(kts)}
|
|
792
794
|
* @private
|
|
793
795
|
*/
|
|
794
|
-
static async speedLoseInHoursStep(e, t, n, i,
|
|
796
|
+
static async speedLoseInHoursStep(e, t, n, i, o, a, s = "", d = !0, r = !1, h = {}) {
|
|
795
797
|
t.utc();
|
|
796
798
|
const M = t.clone().add(14, "days"), y = [], v = [];
|
|
797
|
-
let m = 0,
|
|
798
|
-
for (let b = 0; b <
|
|
799
|
-
let c =
|
|
800
|
-
c.distanceFromStart = Math.round((
|
|
801
|
-
const f =
|
|
799
|
+
let m = 0, C = 0, S, w;
|
|
800
|
+
for (let b = 0; b < a.length - 1; b++) {
|
|
801
|
+
let c = a[b];
|
|
802
|
+
c.distanceFromStart = Math.round((o + C) * 1e4) / 1e4;
|
|
803
|
+
const f = a[b + 1];
|
|
802
804
|
if (e.bearing = W.calculateBearing(c, f, !f.gcToPrevious), c.bearing = e.bearing, c.suspend && r) {
|
|
803
805
|
c.eta = c.eta || t.utc().format(), c.elapsed = c.elapsed ?? 0;
|
|
804
806
|
const I = c.suspend - c.elapsed;
|
|
805
807
|
if (i - m > I)
|
|
806
808
|
i = i - m - I, t.add(I, "hour"), c.elapsed = c.suspend;
|
|
807
809
|
else {
|
|
808
|
-
const
|
|
809
|
-
c.elapsed +=
|
|
810
|
+
const k = i - m;
|
|
811
|
+
c.elapsed += k, t.add(k, "hour"), i = 0;
|
|
810
812
|
}
|
|
811
|
-
if (
|
|
812
|
-
return c.distanceFromPrevious =
|
|
813
|
+
if (F == null || F.info(`[%s] suspend ${c.elapsed} hours at %j, and remain ${i} hours need to go...`, h.requestId, c), i === 0)
|
|
814
|
+
return c.distanceFromPrevious = C, { etd: t, from: w || c, to: c, next: a.filter((k) => k), wps: y, days: v };
|
|
813
815
|
} else
|
|
814
816
|
c.suspend = 0;
|
|
815
817
|
d = t.isAfter(M) ? !1 : d, c = await O.speedLoseAt(e, c, t, s, 0, d, r, h), w = w || c, c.important && y.push(c), t.isSameOrAfter(n) && (v.push(c), n.add(24, "hour"));
|
|
816
818
|
const l = W.calculateDistance(c, f, !f.gcToPrevious);
|
|
817
819
|
let u = Math.round(l / w.speed * 1e5) / 1e5;
|
|
818
820
|
if (m + u < i) {
|
|
819
|
-
if (m += u, t.add(u, "hour"), delete
|
|
821
|
+
if (m += u, t.add(u, "hour"), delete a[b], F == null || F.debug(
|
|
820
822
|
`[%s] go to %j from %j with ${l}nm, and cost ${u} hours`,
|
|
821
823
|
h.requestId,
|
|
822
824
|
{ lat: f.lat, lng: f.lng },
|
|
823
825
|
{ lat: w.lat, lng: w.lng, etd: w.etd }
|
|
824
|
-
),
|
|
825
|
-
|
|
826
|
+
), C += l, a.filter((I) => I).length <= 1) {
|
|
827
|
+
S = f, S.eta = t.utc().format(), S.distanceFromPrevious = l, S.distanceFromStart = Math.round((o + C) * 1e4) / 1e4, y.push(S), delete a[b + 1];
|
|
826
828
|
break;
|
|
827
829
|
}
|
|
828
830
|
} else {
|
|
829
831
|
u = i - m, t.add(u, "hour");
|
|
830
832
|
const I = J.roundPrecision(w.speed * u, 5);
|
|
831
|
-
|
|
833
|
+
S = W.calculateCoordinate(c, e.bearing, I, "nauticalmiles", !f.gcToPrevious), S.eta = t.utc().format(), a[b] = S, F == null || F.debug(
|
|
832
834
|
`[%s] go to %j from %j with ${I}nm, and cost ${u} hours`,
|
|
833
835
|
h.requestId,
|
|
834
|
-
{ lat:
|
|
836
|
+
{ lat: S.lat, lng: S.lng },
|
|
835
837
|
{ lat: c.lat, lng: c.lng, etd: c.etd }
|
|
836
|
-
),
|
|
838
|
+
), C += I, S.distanceFromPrevious = Math.round(C * 1e4) / 1e4, S.distanceFromStart = Math.round((o + C) * 1e4) / 1e4;
|
|
837
839
|
break;
|
|
838
840
|
}
|
|
839
841
|
}
|
|
840
|
-
return { etd: t, from: w, to:
|
|
842
|
+
return { etd: t, from: w, to: S, next: a.filter((b) => b), wps: y, days: v };
|
|
841
843
|
}
|
|
842
844
|
/**
|
|
843
845
|
* 洋流影响因子
|
|
@@ -849,8 +851,8 @@ class O {
|
|
|
849
851
|
const i = (e - (t == null ? void 0 : t.degree) || 0) / 180 * Math.PI;
|
|
850
852
|
if (Math.abs(i) === Math.PI / 2)
|
|
851
853
|
return 0;
|
|
852
|
-
let
|
|
853
|
-
return n & 2 ?
|
|
854
|
+
let o = ((t == null ? void 0 : t.kts) || 0) * Math.cos(i);
|
|
855
|
+
return n & 2 ? o = Math.ceil(o * 100) / 100 : n & 1 ? o = Math.floor(o * 100) / 100 : o = Math.round(o * 100) / 100, Math.abs(o) > 5 ? 0 : o;
|
|
854
856
|
}
|
|
855
857
|
/**
|
|
856
858
|
* 风浪影响因子
|
|
@@ -858,16 +860,16 @@ class O {
|
|
|
858
860
|
* @param wwc 气象要素
|
|
859
861
|
*/
|
|
860
862
|
static weatherFactor(e, t) {
|
|
861
|
-
var M, y, v, m,
|
|
862
|
-
|
|
863
|
-
const n = O.blockCoefficient(e.displacement, e.lbp, e.breadthMoulded, e.draught), i = O.froudeNumber(e.speed, e.lbp),
|
|
864
|
-
let
|
|
865
|
-
|
|
866
|
-
const s = O.directionFactor(
|
|
867
|
-
let r = s *
|
|
868
|
-
r = Math.round(r * 1.943844 * 1e4) / 1e4 * -1, e.tag === "tugs" && Math.abs(r) > 1 && (r = r / (Math.abs(Math.round(r)) + 1)),
|
|
869
|
-
const h = O.waveHeightFactor(((w = (
|
|
870
|
-
return
|
|
863
|
+
var M, y, v, m, C, S, w;
|
|
864
|
+
F == null || F.debug("calculate weather factor via: %j", { ...e, ...t });
|
|
865
|
+
const n = O.blockCoefficient(e.displacement, e.lbp, e.breadthMoulded, e.draught), i = O.froudeNumber(e.speed, e.lbp), o = O.amendFactor(n, i, e.loadCondition);
|
|
866
|
+
let a = Math.abs(e.bearing % 360 - (((M = t == null ? void 0 : t.wind) == null ? void 0 : M.degree) % 360 || 0));
|
|
867
|
+
a = a > 180 ? 360 - a : a;
|
|
868
|
+
const s = O.directionFactor(a, (y = t == null ? void 0 : t.wind) == null ? void 0 : y.scale), d = O.vesselTagFactor(e.displacement, e.loadCondition, e.tag, (v = t == null ? void 0 : t.wind) == null ? void 0 : v.scale);
|
|
869
|
+
let r = s * o * d / 100 * e.speed;
|
|
870
|
+
r = Math.round(r * 1.943844 * 1e4) / 1e4 * -1, e.tag === "tugs" && Math.abs(r) > 1 && (r = r / (Math.abs(Math.round(r)) + 1)), F == null || F.debug("wind wx factor = %d", r), a = Math.abs(e.bearing % 360 - (((C = (m = t == null ? void 0 : t.wave) == null ? void 0 : m.sig) == null ? void 0 : C.degree) % 360 || 0));
|
|
871
|
+
const h = O.waveHeightFactor(((w = (S = t == null ? void 0 : t.wave) == null ? void 0 : S.sig) == null ? void 0 : w.height) ?? 1, a);
|
|
872
|
+
return F == null || F.debug("wave wx factor = %d", h), r = r * 0.4 + h, F == null || F.debug("weather factor = %d", r), r = Math.abs(r) > 4 ? 4 * (Math.abs(r) / r) + Math.abs(r) / r * (Math.abs(r) - 4) * 0.1 : r, Math.round((r || 0) * 100) / 100;
|
|
871
873
|
}
|
|
872
874
|
/**
|
|
873
875
|
* 全程失速分析(走完航程)
|
|
@@ -881,79 +883,79 @@ class O {
|
|
|
881
883
|
* @param useMeteo true 启用气象分析
|
|
882
884
|
* @param useRouteParam
|
|
883
885
|
*/
|
|
884
|
-
static async analyseInstant(e, t, n, i,
|
|
885
|
-
var
|
|
886
|
+
static async analyseInstant(e, t, n, i, o, a = "", s = 0, d = !0, r = !1, h = {}) {
|
|
887
|
+
var z, G, Q, X, Z, $;
|
|
886
888
|
const M = g().valueOf();
|
|
887
889
|
e.lng = J.convertToStdLng(e.lng);
|
|
888
|
-
const { route: y, waypoints: v } =
|
|
889
|
-
if (((
|
|
890
|
+
const { route: y, waypoints: v } = o.points, m = W.calculateSubRoute(e, y);
|
|
891
|
+
if (((z = m[0]) == null ? void 0 : z.length) <= 1)
|
|
890
892
|
return;
|
|
891
|
-
const { v0:
|
|
893
|
+
const { v0: C, label: S } = e.sog ? {
|
|
892
894
|
v0: e.sog,
|
|
893
|
-
label: "Other"
|
|
895
|
+
label: e.label || "Other"
|
|
894
896
|
/* Instruct */
|
|
895
897
|
} : {
|
|
896
898
|
v0: i.speed,
|
|
897
899
|
label: "CP"
|
|
898
900
|
/* Cp */
|
|
899
|
-
}, w = O.assembleProperties(n, i.loadCondition,
|
|
901
|
+
}, w = O.assembleProperties(n, i.loadCondition, C, 0), b = v.length ? W.calculateSubWaypoints(e, v) : [];
|
|
900
902
|
b.forEach((q) => q.important = !0);
|
|
901
903
|
const c = {
|
|
902
904
|
from: { ...e },
|
|
903
905
|
route: m,
|
|
904
906
|
waypoints: b,
|
|
905
|
-
v0:
|
|
906
|
-
label:
|
|
907
|
+
v0: C,
|
|
908
|
+
label: S
|
|
907
909
|
}, f = {
|
|
908
910
|
hours: [],
|
|
909
911
|
days: [],
|
|
910
912
|
wps: []
|
|
911
913
|
};
|
|
912
914
|
s || (W.calculateRouteDistance(m) / i.speed <= 72 ? s = 3 : s = 6);
|
|
913
|
-
let l = W.simplifyRouteToCoordinates(m, b, 0), u = 0, I = 0,
|
|
915
|
+
let l = W.simplifyRouteToCoordinates(m, b, 0), u = 0, I = 0, k = 0, D = 0;
|
|
914
916
|
t = g(t).utc();
|
|
915
917
|
const Y = t.clone();
|
|
916
918
|
for (; l.length > 0; ) {
|
|
917
|
-
const q = s - t.hour() % s, V = Math.ceil(t.clone().add(q, "h").set({ minute: 0, second: 0, millisecond: 0 }).diff(t, "h", !0) * 1e4) / 1e4,
|
|
919
|
+
const q = s - t.hour() % s, V = Math.ceil(t.clone().add(q, "h").set({ minute: 0, second: 0, millisecond: 0 }).diff(t, "h", !0) * 1e4) / 1e4, x = await O.speedLoseInHoursStep(
|
|
918
920
|
w,
|
|
919
921
|
t,
|
|
920
922
|
Y,
|
|
921
923
|
V,
|
|
922
924
|
u,
|
|
923
925
|
l,
|
|
924
|
-
|
|
926
|
+
a,
|
|
925
927
|
d,
|
|
926
928
|
r,
|
|
927
929
|
h
|
|
928
930
|
);
|
|
929
|
-
(
|
|
931
|
+
(G = x.from) != null && G.speed && (f.hours.push(x.from), f.wps.push(...x.wps), f.days.push(...x.days)), l = x == null ? void 0 : x.next, l.length || f.hours.push(x == null ? void 0 : x.to), u += Math.round((((Q = x == null ? void 0 : x.to) == null ? void 0 : Q.distanceFromPrevious) ?? 0) * 1e4) / 1e4;
|
|
930
932
|
}
|
|
931
|
-
const
|
|
932
|
-
for (let q = 0; q <
|
|
933
|
-
const V = g(
|
|
934
|
-
I += (
|
|
933
|
+
const j = f.hours;
|
|
934
|
+
for (let q = 0; q < j.length - 1; q++) {
|
|
935
|
+
const V = g(j[q + 1].eta).diff(j[q].etd, "hour", !0) || 1;
|
|
936
|
+
I += (j[q].wxFactor || 0) * V, k += (j[q].cFactor || 0) * V, D += V;
|
|
935
937
|
}
|
|
936
938
|
(X = f.wps) == null || X.forEach((q, V) => {
|
|
937
939
|
q.positionTime = g.utc(q.etd || q.eta).unix();
|
|
938
|
-
const
|
|
939
|
-
if (
|
|
940
|
-
const L = q.distanceFromStart -
|
|
940
|
+
const x = f.wps[V - 1];
|
|
941
|
+
if (x) {
|
|
942
|
+
const L = q.distanceFromStart - x.distanceFromStart, H = g(q.eta || q.etd).diff(g(x.etd || x.eta), "h", !0);
|
|
941
943
|
q.avgSpd = Math.round(L / H * 100) / 100;
|
|
942
|
-
const nt = W.calculateBearing(
|
|
943
|
-
|
|
944
|
+
const nt = W.calculateBearing(x, q);
|
|
945
|
+
x.bearing = nt;
|
|
944
946
|
}
|
|
945
|
-
}), f.wps = (Z = f.wps) == null ? void 0 : Z.reduce((q, V) => (q.some((
|
|
947
|
+
}), f.wps = (Z = f.wps) == null ? void 0 : Z.reduce((q, V) => (q.some((x) => Math.round(x.positionTime / 60) === Math.round(V.positionTime / 60)) || q.push(V), q), []), c.sample = f;
|
|
946
948
|
const P = f.hours.at(0), T = f.hours.at(-1);
|
|
947
|
-
c.distance = Math.round(T.distanceFromStart * 1e4) / 1e4, c.etd = g(P.eta).utc().format(), c.eta = g(T.eta).utc().format(), c.wxFactor = Math.round(I / D * 1e4) / 1e4, c.cFactor = Math.round(
|
|
948
|
-
const { distanceInECA: N, hoursInECA: A, totalDgoConsInECA: R, eca:
|
|
949
|
+
c.distance = Math.round(T.distanceFromStart * 1e4) / 1e4, c.etd = g(P.eta).utc().format(), c.eta = g(T.eta).utc().format(), c.wxFactor = Math.round(I / D * 1e4) / 1e4, c.cFactor = Math.round(k / D * 1e4) / 1e4, c.avgSpeed = Math.round(T.distanceFromStart / D * 1e4) / 1e4, c.totalHrs = Math.round(D * 1e4) / 1e4;
|
|
950
|
+
const { distanceInECA: N, hoursInECA: A, totalDgoConsInECA: R, eca: U } = await this.calculateECA(c, i, h), st = J.roundPrecision(i.fo / 24 * (D - A), 3), at = J.roundPrecision(i.dgo / 24 * D, 3);
|
|
949
951
|
c.extend = {
|
|
950
|
-
eca:
|
|
952
|
+
eca: U,
|
|
951
953
|
distanceInECA: N,
|
|
952
954
|
hoursInECA: A,
|
|
953
955
|
totalDgoConsInECA: R
|
|
954
956
|
}, c.totalFoCons = st, c.totalDgoCons = at;
|
|
955
957
|
const tt = g().valueOf() - M, ot = (($ = f == null ? void 0 : f.hours) == null ? void 0 : $.length) || 1;
|
|
956
|
-
return
|
|
958
|
+
return F == null || F.info("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms", h == null ? void 0 : h.requestId, tt, ot, Math.round(tt / ot * 1e3) / 1e3), c;
|
|
957
959
|
}
|
|
958
960
|
/**
|
|
959
961
|
* 分段失速分析(最多走hours 小时)
|
|
@@ -968,25 +970,25 @@ class O {
|
|
|
968
970
|
* @param useMeteo true 启用气象分析
|
|
969
971
|
* @param useRouteParam
|
|
970
972
|
*/
|
|
971
|
-
static async analyseInstantWithThreshed(e, t, n, i,
|
|
973
|
+
static async analyseInstantWithThreshed(e, t, n, i, o, a, s, d = "", r = 3, h = !0, M = !1, y = {}) {
|
|
972
974
|
var Q, X, Z, $, q, V;
|
|
973
975
|
const v = g().valueOf();
|
|
974
976
|
e.lng = J.convertToStdLng(e.lng);
|
|
975
|
-
const { v0: m, label:
|
|
977
|
+
const { v0: m, label: C } = e.sog ? {
|
|
976
978
|
v0: e.sog,
|
|
977
|
-
label: "Other"
|
|
979
|
+
label: e.label || "Other"
|
|
978
980
|
/* Instruct */
|
|
979
981
|
} : {
|
|
980
|
-
v0:
|
|
982
|
+
v0: o.speed,
|
|
981
983
|
label: "CP"
|
|
982
984
|
/* Cp */
|
|
983
|
-
},
|
|
985
|
+
}, S = O.assembleProperties(i, o.loadCondition, m, 0), w = W.calculateSubRoute(e, a);
|
|
984
986
|
if (((Q = w[0]) == null ? void 0 : Q.length) <= 1)
|
|
985
987
|
return;
|
|
986
988
|
const b = s.length ? W.calculateSubWaypoints(e, s) : [];
|
|
987
|
-
b.forEach((
|
|
989
|
+
b.forEach((x) => x.important = !0);
|
|
988
990
|
let c = W.simplifyRouteToCoordinates(w, b, 0), f = 0, l = 0, u = 0, I = 0;
|
|
989
|
-
const
|
|
991
|
+
const k = {
|
|
990
992
|
hours: [],
|
|
991
993
|
wps: [],
|
|
992
994
|
days: []
|
|
@@ -994,52 +996,52 @@ class O {
|
|
|
994
996
|
t = g(t).utc();
|
|
995
997
|
const D = t.clone();
|
|
996
998
|
for (; c.length > 0; ) {
|
|
997
|
-
const
|
|
998
|
-
let L = Math.ceil(t.clone().add(
|
|
999
|
+
const x = r - t.hour() % r;
|
|
1000
|
+
let L = Math.ceil(t.clone().add(x, "h").set({ minute: 0, second: 0, millisecond: 0 }).diff(t, "h", !0) * 1e4) / 1e4;
|
|
999
1001
|
L = t.clone().add(L, "h").isSameOrAfter(n) ? n.diff(t, "h", !0) * 1e4 / 1e4 : L;
|
|
1000
|
-
const H = await O.speedLoseInHoursStep(
|
|
1001
|
-
if ((X = H.from) != null && X.speed && (
|
|
1002
|
+
const H = await O.speedLoseInHoursStep(S, t, D, L, f, c, d, h, M, y);
|
|
1003
|
+
if ((X = H.from) != null && X.speed && (k.hours.push(H.from), H != null && H.wps && k.wps.push(...H.wps), k.days.push(...H.days)), c = H == null ? void 0 : H.next, c.length || k.hours.push(H == null ? void 0 : H.to), f += Math.round((((Z = H == null ? void 0 : H.to) == null ? void 0 : Z.distanceFromPrevious) ?? 0) * 1e4) / 1e4, !L)
|
|
1002
1004
|
break;
|
|
1003
1005
|
}
|
|
1004
|
-
|
|
1005
|
-
const H =
|
|
1006
|
+
k.wps = ($ = k.wps) == null ? void 0 : $.reduce((x, L) => (x.some((H) => Math.round(g(H.etd).unix() / 60) === Math.round(g(L.etd).unix() / 60)) || x.push(L), x), []), (q = k.wps) == null || q.forEach((x, L) => {
|
|
1007
|
+
const H = k.wps[L - 1];
|
|
1006
1008
|
if (H) {
|
|
1007
|
-
const nt =
|
|
1008
|
-
|
|
1009
|
-
const ut = W.calculateBearing(H,
|
|
1009
|
+
const nt = x.distanceFromStart - H.distanceFromStart, dt = g(x.eta || x.etd).diff(g(H.etd || H.eta), "h", !0);
|
|
1010
|
+
x.avgSpd = Math.round(nt / dt * 100) / 100;
|
|
1011
|
+
const ut = W.calculateBearing(H, x);
|
|
1010
1012
|
H.bearing = ut;
|
|
1011
1013
|
}
|
|
1012
1014
|
});
|
|
1013
|
-
const Y =
|
|
1014
|
-
for (let
|
|
1015
|
-
const L = g(Y[
|
|
1016
|
-
l += Y[
|
|
1015
|
+
const Y = k.hours;
|
|
1016
|
+
for (let x = 0; x < Y.length - 1; x++) {
|
|
1017
|
+
const L = g(Y[x + 1].eta).diff(Y[x].etd, "hour", !0);
|
|
1018
|
+
l += Y[x].wxFactor * L, u += Y[x].cFactor * L, I += L;
|
|
1017
1019
|
}
|
|
1018
|
-
const
|
|
1019
|
-
sample:
|
|
1020
|
+
const j = k.hours.at(0), P = k.hours.at(-1), T = await W.calculateRangeRoute(j, P, w), N = await W.calculateRangeWaypoints(j, P, w, b), A = {
|
|
1021
|
+
sample: k,
|
|
1020
1022
|
distance: Math.round(((P == null ? void 0 : P.distanceFromStart) || 0) * 1e4) / 1e4,
|
|
1021
1023
|
// 注意,可能会在first节点Drift,所有采用eta做为初始出发时间
|
|
1022
|
-
etd: g(
|
|
1024
|
+
etd: g(j.eta).utc().format(),
|
|
1023
1025
|
eta: g(P == null ? void 0 : P.eta).utc().format(),
|
|
1024
1026
|
wxFactor: Math.round(l / I * 1e4) / 1e4,
|
|
1025
1027
|
cFactor: Math.round(u / I * 1e4) / 1e4,
|
|
1026
1028
|
avgSpeed: Math.round(((P == null ? void 0 : P.distanceFromStart) || 0) / I * 1e4) / 1e4,
|
|
1027
1029
|
totalHrs: Math.round(I * 1e4) / 1e4,
|
|
1028
|
-
from:
|
|
1030
|
+
from: j,
|
|
1029
1031
|
to: P,
|
|
1030
1032
|
route: T,
|
|
1031
1033
|
waypoints: N,
|
|
1032
1034
|
v0: m,
|
|
1033
|
-
label:
|
|
1034
|
-
}, { distanceInECA: R, hoursInECA:
|
|
1035
|
+
label: C
|
|
1036
|
+
}, { distanceInECA: R, hoursInECA: U, totalDgoConsInECA: st, eca: at } = await this.calculateECA(A, o, y), ct = J.roundPrecision(o.fo / 24 * (I - U), 3), tt = J.roundPrecision(o.dgo / 24 * I, 3);
|
|
1035
1037
|
A.extend = {
|
|
1036
1038
|
eca: at,
|
|
1037
1039
|
distanceInECA: R,
|
|
1038
|
-
hoursInECA:
|
|
1040
|
+
hoursInECA: U,
|
|
1039
1041
|
totalDgoConsInECA: st
|
|
1040
|
-
}, A.totalDgoCons = tt, A.totalFoCons =
|
|
1041
|
-
const
|
|
1042
|
-
return
|
|
1042
|
+
}, A.totalDgoCons = tt, A.totalFoCons = ct;
|
|
1043
|
+
const z = g().valueOf() - v, G = ((V = k == null ? void 0 : k.hours) == null ? void 0 : V.length) || 1;
|
|
1044
|
+
return F == null || F.debug("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms", y == null ? void 0 : y.requestId, z, G, Math.round(z / G * 1e3) / 1e3), A;
|
|
1043
1045
|
}
|
|
1044
1046
|
/**
|
|
1045
1047
|
* 在指定航线条件下,基于多CP,动态计算最优成本(租金+油费)方案
|
|
@@ -1056,10 +1058,10 @@ class O {
|
|
|
1056
1058
|
* @param lane 基础航线(重要转向点)
|
|
1057
1059
|
* @param options
|
|
1058
1060
|
*/
|
|
1059
|
-
static async analyseCost(e, t, n, i,
|
|
1061
|
+
static async analyseCost(e, t, n, i, o = {}) {
|
|
1060
1062
|
var w, b;
|
|
1061
|
-
const
|
|
1062
|
-
|
|
1063
|
+
const a = g().valueOf(), s = [];
|
|
1064
|
+
e.speedStep = e.speedStep || 3, e.alterStep = e.alterStep ?? 1;
|
|
1063
1065
|
const d = W.calculateRouteDistance(i.route);
|
|
1064
1066
|
let r = 0;
|
|
1065
1067
|
n.forEach((c) => {
|
|
@@ -1081,9 +1083,9 @@ class O {
|
|
|
1081
1083
|
e.speedStep,
|
|
1082
1084
|
e.useMeteo,
|
|
1083
1085
|
e.useRouteParam,
|
|
1084
|
-
|
|
1086
|
+
o
|
|
1085
1087
|
);
|
|
1086
|
-
u && (await O.calculateCost(u, c, e,
|
|
1088
|
+
u && (await O.calculateCost(u, c, e, o), s.push(u), F == null || F.info("[%s][L%d-%d] analyse from %s to %s cost: %j", o.requestId, 1, M, e.etd, h.format(), {
|
|
1087
1089
|
cost: u.cost.total,
|
|
1088
1090
|
hire: u.cost.hire,
|
|
1089
1091
|
bunker: u.cost.bunker,
|
|
@@ -1096,19 +1098,19 @@ class O {
|
|
|
1096
1098
|
const y = s.at(0), v = s.at(1), m = [];
|
|
1097
1099
|
if (m.push({ combined: !1, speeds: [y], cost: (w = y.cost) == null ? void 0 : w.total }), v) {
|
|
1098
1100
|
const c = y.cost.cp, f = v.cost.cp, l = g(y.eta), u = g(y.etd), I = l.diff(u, "days", !0);
|
|
1099
|
-
let
|
|
1100
|
-
|
|
1101
|
-
let D = 2, Y = { combined: !1, speeds: [v], cost: (b = v.cost) == null ? void 0 : b.total },
|
|
1102
|
-
for (;
|
|
1103
|
-
const P = await O.combinedAnalyse(e, t, h, [c, f], i,
|
|
1104
|
-
if (Y.cost > P.cost ?
|
|
1101
|
+
let k = Math.ceil(I / 2);
|
|
1102
|
+
k = k > 7 ? 7 : k < e.alterStep ? e.alterStep : k;
|
|
1103
|
+
let D = 2, Y = { combined: !1, speeds: [v], cost: (b = v.cost) == null ? void 0 : b.total }, j;
|
|
1104
|
+
for (; k >= e.alterStep; ) {
|
|
1105
|
+
const P = await O.combinedAnalyse(e, t, h, [c, f], i, k, { ...o, level: D });
|
|
1106
|
+
if (Y.cost > P.cost ? j ? (j == null ? void 0 : j.cost) > P.cost && (j = P) : (j = Y, Y = P) : (!j || (j == null ? void 0 : j.cost) > P.cost) && (j = P), k <= e.alterStep)
|
|
1105
1107
|
break;
|
|
1106
|
-
|
|
1108
|
+
k = Math.ceil(k / 2), D += 1;
|
|
1107
1109
|
}
|
|
1108
|
-
m.push(Y),
|
|
1110
|
+
m.push(Y), j && m.push(j);
|
|
1109
1111
|
}
|
|
1110
|
-
const
|
|
1111
|
-
return
|
|
1112
|
+
const S = g().valueOf() - a;
|
|
1113
|
+
return F == null || F.info("[%s] analyse elapsed: %d ms", o == null ? void 0 : o.requestId, S), m.sort((c, f) => c.cost - f.cost);
|
|
1112
1114
|
}
|
|
1113
1115
|
/**
|
|
1114
1116
|
* 按步长多次减半,分别用7,4,2,1天步长及cpa,cpb交替计算各种组合下的成本
|
|
@@ -1120,24 +1122,24 @@ class O {
|
|
|
1120
1122
|
* @param step 步长,7,4,2,1
|
|
1121
1123
|
* @param options
|
|
1122
1124
|
*/
|
|
1123
|
-
static async combinedAnalyse(e, t, n, i,
|
|
1124
|
-
s.counter = 1,
|
|
1125
|
-
const d = await O.alternateAnalyse(e, t, n, i, 0,
|
|
1126
|
-
|
|
1125
|
+
static async combinedAnalyse(e, t, n, i, o, a, s = {}) {
|
|
1126
|
+
s.counter = 1, F == null || F.info("[%s][L%d] analyse with alternate cp in every %d days", s.requestId, s.level, a);
|
|
1127
|
+
const d = await O.alternateAnalyse(e, t, n, i, 0, o, a, s), r = d.reduce((f, l) => f + l.cost.total, 0), h = d.reduce((f, l) => f + l.cost.hire, 0), M = d.reduce((f, l) => f + l.cost.bunker, 0), y = d.reduce((f, l) => f + l.distance, 0), v = d.reduce((f, l) => f + l.totalHrs, 0);
|
|
1128
|
+
F == null || F.info("[%s][L%d] cost with cpa/cpb turn: %j", s.requestId, s.level, {
|
|
1127
1129
|
cost: r,
|
|
1128
1130
|
hire: h,
|
|
1129
1131
|
bunker: M,
|
|
1130
1132
|
distance: y,
|
|
1131
1133
|
hours: v
|
|
1132
1134
|
});
|
|
1133
|
-
const m = await O.alternateAnalyse(e, t, n, i, 1,
|
|
1134
|
-
return
|
|
1135
|
-
cost:
|
|
1136
|
-
hire:
|
|
1135
|
+
const m = await O.alternateAnalyse(e, t, n, i, 1, o, a, s), C = m.reduce((f, l) => f + l.cost.total, 0), S = m.reduce((f, l) => f + l.cost.hire, 0), w = m.reduce((f, l) => f + l.cost.bunker, 0), b = m.reduce((f, l) => f + l.distance, 0), c = m.reduce((f, l) => f + l.totalHrs, 0);
|
|
1136
|
+
return F == null || F.info("[%s][L%d] cost with cpb/cpa turn: %j", s.requestId, s.level, {
|
|
1137
|
+
cost: C,
|
|
1138
|
+
hire: S,
|
|
1137
1139
|
bunker: w,
|
|
1138
1140
|
distance: b,
|
|
1139
1141
|
hours: c
|
|
1140
|
-
}), r <
|
|
1142
|
+
}), r < C ? { combined: !0, cost: Math.round(r * 1e3) / 1e3, speeds: d, step: a } : { combined: !0, cost: Math.round(C * 1e3) / 1e3, speeds: m, step: a };
|
|
1141
1143
|
}
|
|
1142
1144
|
/**
|
|
1143
1145
|
* 基于cp索引,交替计算指定步长下的成本
|
|
@@ -1150,26 +1152,26 @@ class O {
|
|
|
1150
1152
|
* @param step 步长,7,4,2,1
|
|
1151
1153
|
* @param options
|
|
1152
1154
|
*/
|
|
1153
|
-
static async alternateAnalyse(e, t, n, i,
|
|
1155
|
+
static async alternateAnalyse(e, t, n, i, o, a, s, d = {}) {
|
|
1154
1156
|
var y, v;
|
|
1155
1157
|
let r = g.utc(e.etd);
|
|
1156
1158
|
const h = { lat: e.lat, lng: e.lng }, M = [];
|
|
1157
1159
|
for (; r.isBefore(n); ) {
|
|
1158
|
-
const m = r.clone().utc().add(s, "day"),
|
|
1160
|
+
const m = r.clone().utc().add(s, "day"), C = JSON.parse(JSON.stringify(a.route)), S = JSON.parse(JSON.stringify(a.waypoints)), w = i[o], b = await O.analyseInstantWithThreshed(
|
|
1159
1161
|
h,
|
|
1160
1162
|
r.utc().format(),
|
|
1161
1163
|
m,
|
|
1162
1164
|
t,
|
|
1163
1165
|
w,
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
+
C,
|
|
1167
|
+
S,
|
|
1166
1168
|
e.meteoVendor,
|
|
1167
1169
|
e.speedStep,
|
|
1168
1170
|
e.useMeteo,
|
|
1169
1171
|
e.useRouteParam,
|
|
1170
1172
|
d
|
|
1171
1173
|
);
|
|
1172
|
-
b && (await O.calculateCost(b, w, e, d),
|
|
1174
|
+
b && (await O.calculateCost(b, w, e, d), F == null || F.info(
|
|
1173
1175
|
"[%s][L%d-%d] analyse from %s to %s cost: %j",
|
|
1174
1176
|
d.requestId,
|
|
1175
1177
|
d.level,
|
|
@@ -1187,7 +1189,7 @@ class O {
|
|
|
1187
1189
|
)), d.counter = d.counter + 1;
|
|
1188
1190
|
const c = (v = (y = b == null ? void 0 : b.sample) == null ? void 0 : y.hours) == null ? void 0 : v.at(-1);
|
|
1189
1191
|
if (c)
|
|
1190
|
-
h.lat = c.lat, h.lng = c.lng, r = g(c.eta), M.push(b),
|
|
1192
|
+
h.lat = c.lat, h.lng = c.lng, r = g(c.eta), M.push(b), o = o ? 0 : 1;
|
|
1191
1193
|
else
|
|
1192
1194
|
break;
|
|
1193
1195
|
}
|
|
@@ -1201,12 +1203,12 @@ class O {
|
|
|
1201
1203
|
* @param options
|
|
1202
1204
|
*/
|
|
1203
1205
|
static async calculateCost(e, t, n, i = {}) {
|
|
1204
|
-
var
|
|
1206
|
+
var o;
|
|
1205
1207
|
if (e) {
|
|
1206
|
-
const
|
|
1208
|
+
const a = Math.round(e.totalHrs / 24 * (n.dailyHire || 0) * (1 - (n.addComm || 0)) * 1e3) / 1e3, s = Math.round(e.totalFoCons * (n.priceFO || 0) * 1e3) / 1e3, d = Math.round((e.totalDgoCons + (((o = e.extend) == null ? void 0 : o.totalDgoConsInECA) || 0)) * (n.priceDGO || 0) * 1e3) / 1e3;
|
|
1207
1209
|
e.cost = {
|
|
1208
|
-
total: Math.round((
|
|
1209
|
-
hire:
|
|
1210
|
+
total: Math.round((a + s + d) * 1e3) / 1e3,
|
|
1211
|
+
hire: a,
|
|
1210
1212
|
bunker: Math.round((s + d) * 1e3) / 1e3,
|
|
1211
1213
|
cp: t
|
|
1212
1214
|
};
|
|
@@ -1219,18 +1221,18 @@ class O {
|
|
|
1219
1221
|
static async calculateECA(e, t, n = {}) {
|
|
1220
1222
|
var d, r;
|
|
1221
1223
|
const i = await W.intersectInECA(e.route);
|
|
1222
|
-
let
|
|
1224
|
+
let o = 0, a = 0, s = 0;
|
|
1223
1225
|
e.sample.wps.forEach((h) => {
|
|
1224
1226
|
h.positionTime = g.utc(h.etd || h.eta).unix();
|
|
1225
1227
|
});
|
|
1226
1228
|
for (const h of i) {
|
|
1227
|
-
|
|
1229
|
+
o += h.distance;
|
|
1228
1230
|
const M = await W.deadReckoningTime((d = h.waypoints) == null ? void 0 : d.at(0), e.sample.wps), y = await W.deadReckoningTime((r = h.waypoints) == null ? void 0 : r.at(-1), e.sample.wps);
|
|
1229
|
-
h.in = M, h.out = y, h.totalHrs = J.roundPrecision((y.positionTime - M.positionTime) / 3600, 2), h.totalDgoCons = J.roundPrecision(t.fo / 24 * h.totalHrs, 3),
|
|
1231
|
+
h.in = M, h.out = y, h.totalHrs = J.roundPrecision((y.positionTime - M.positionTime) / 3600, 2), h.totalDgoCons = J.roundPrecision(t.fo / 24 * h.totalHrs, 3), a += h.totalHrs, s += h.totalDgoCons;
|
|
1230
1232
|
}
|
|
1231
|
-
return
|
|
1232
|
-
distanceInECA:
|
|
1233
|
-
hoursInECA:
|
|
1233
|
+
return o = J.roundPrecision(o, 3), a = J.roundPrecision(a, 3), s = J.roundPrecision(s, 3), {
|
|
1234
|
+
distanceInECA: o,
|
|
1235
|
+
hoursInECA: a,
|
|
1234
1236
|
totalDgoConsInECA: s,
|
|
1235
1237
|
eca: i
|
|
1236
1238
|
};
|
|
@@ -1246,35 +1248,35 @@ class O {
|
|
|
1246
1248
|
hours: [],
|
|
1247
1249
|
wps: [],
|
|
1248
1250
|
days: []
|
|
1249
|
-
}, i = e.reduce((l, u) => l + u.distance, 0),
|
|
1251
|
+
}, i = e.reduce((l, u) => l + u.distance, 0), o = e.reduce((l, u) => {
|
|
1250
1252
|
var I;
|
|
1251
1253
|
return l + (((I = u.extend) == null ? void 0 : I.distanceInECA) || 0);
|
|
1252
|
-
}, 0),
|
|
1254
|
+
}, 0), a = e.reduce((l, u) => l + u.totalHrs, 0), s = e.reduce((l, u) => {
|
|
1253
1255
|
var I;
|
|
1254
1256
|
return l + (((I = u.extend) == null ? void 0 : I.hoursInECA) || 0);
|
|
1255
1257
|
}, 0), d = e.reduce((l, u) => {
|
|
1256
1258
|
var I;
|
|
1257
1259
|
return l + (((I = u.extend) == null ? void 0 : I.totalDgoConsInECA) || 0);
|
|
1258
|
-
}, 0), r = e.reduce((l, u) => l + u.wxFactor * u.totalHrs /
|
|
1260
|
+
}, 0), r = e.reduce((l, u) => l + u.wxFactor * u.totalHrs / a, 0), h = e.reduce((l, u) => l + u.cFactor * u.totalHrs / a, 0), M = e.reduce((l, u) => l + u.totalFoCons, 0), y = e.reduce((l, u) => l + u.totalDgoCons, 0), v = e.reduce((l, u) => l + u.cost.total, 0), m = e.reduce((l, u) => l + u.cost.hire, 0), C = e.reduce((l, u) => l + u.cost.bunker, 0), S = [], w = [];
|
|
1259
1261
|
let b;
|
|
1260
1262
|
for (const l of e) {
|
|
1261
1263
|
w.push(...((c = l.extend) == null ? void 0 : c.eca) || []);
|
|
1262
|
-
const u = l.sample.hours, I = l.sample.wps,
|
|
1264
|
+
const u = l.sample.hours, I = l.sample.wps, k = l.sample.days, D = u.at(0);
|
|
1263
1265
|
b && (D.distanceFromPrevious = b.distanceFromPrevious, D.distanceFromStart = b.distanceFromStart, u.forEach((T, N) => {
|
|
1264
1266
|
N && (T.distanceFromStart = T.distanceFromStart + b.distanceFromStart);
|
|
1265
1267
|
}), I.at(0).distanceFromPrevious = b.distanceFromPrevious, I.at(0).distanceFromStart = b.distanceFromStart, I.forEach((T, N) => {
|
|
1266
1268
|
N && (T.distanceFromStart = T.distanceFromStart + b.distanceFromStart);
|
|
1267
|
-
}),
|
|
1269
|
+
}), k.at(0).distanceFromPrevious = b.distanceFromPrevious, k.at(0).distanceFromStart = b.distanceFromStart, k.forEach((T, N) => {
|
|
1268
1270
|
N && (T.distanceFromStart = T.distanceFromStart + b.distanceFromStart);
|
|
1269
1271
|
})), D.cp = l.cost.cp;
|
|
1270
|
-
const Y = [l.etd, l.eta],
|
|
1271
|
-
|
|
1272
|
+
const Y = [l.etd, l.eta], j = S.findIndex((T) => T.id === D.cp.id);
|
|
1273
|
+
j === -1 ? (D.cp.segment = [Y], S.push(D.cp)) : S[j].segment.push(Y), u.forEach((T) => {
|
|
1272
1274
|
var A;
|
|
1273
1275
|
((A = n.hours) == null ? void 0 : A.findIndex((R) => R.eta === T.eta)) === -1 && n.hours.push(T);
|
|
1274
1276
|
}), I.forEach((T) => {
|
|
1275
1277
|
var A;
|
|
1276
1278
|
((A = n.wps) == null ? void 0 : A.findIndex((R) => R.eta === T.eta)) === -1 && n.wps.push(T);
|
|
1277
|
-
}),
|
|
1279
|
+
}), k.forEach((T) => {
|
|
1278
1280
|
var A;
|
|
1279
1281
|
((A = n == null ? void 0 : n.days) == null ? void 0 : A.findIndex((R) => R.eta === T.eta)) === -1 && n.days.push(T);
|
|
1280
1282
|
});
|
|
@@ -1286,10 +1288,10 @@ class O {
|
|
|
1286
1288
|
}), n.wps.forEach((l, u) => {
|
|
1287
1289
|
const I = n.wps[u - 1];
|
|
1288
1290
|
if (I) {
|
|
1289
|
-
const
|
|
1291
|
+
const k = l.distanceFromStart - (I.distanceFromStart || 0), D = g(l.eta || l.etd).diff(g(I.etd || I.eta), "hour", !0), Y = Math.round(k / D * 100) / 100;
|
|
1290
1292
|
l.avgSpd = Y;
|
|
1291
|
-
const
|
|
1292
|
-
I.bearing =
|
|
1293
|
+
const j = W.calculateBearing(I, l);
|
|
1294
|
+
I.bearing = j;
|
|
1293
1295
|
}
|
|
1294
1296
|
}), {
|
|
1295
1297
|
sample: n,
|
|
@@ -1300,8 +1302,8 @@ class O {
|
|
|
1300
1302
|
v0: e.at(0).v0,
|
|
1301
1303
|
label: "Combined",
|
|
1302
1304
|
distance: Math.round(i * 1e4) / 1e4,
|
|
1303
|
-
totalHrs: Math.round(
|
|
1304
|
-
avgSpeed: Math.round(i /
|
|
1305
|
+
totalHrs: Math.round(a * 1e3) / 1e3,
|
|
1306
|
+
avgSpeed: Math.round(i / a * 1e3) / 1e3,
|
|
1305
1307
|
wxFactor: Math.round(r * 1e3) / 1e3,
|
|
1306
1308
|
cFactor: Math.round(h * 1e3) / 1e3,
|
|
1307
1309
|
totalFoCons: Math.round(M * 1e3) / 1e3,
|
|
@@ -1309,12 +1311,12 @@ class O {
|
|
|
1309
1311
|
cost: {
|
|
1310
1312
|
total: Math.round(v * 1e3) / 1e3,
|
|
1311
1313
|
hire: Math.round(m * 1e3) / 1e3,
|
|
1312
|
-
bunker: Math.round(
|
|
1314
|
+
bunker: Math.round(C * 1e3) / 1e3
|
|
1313
1315
|
},
|
|
1314
1316
|
extend: {
|
|
1315
|
-
cps:
|
|
1317
|
+
cps: S,
|
|
1316
1318
|
eca: w,
|
|
1317
|
-
distanceInECA: Math.round(
|
|
1319
|
+
distanceInECA: Math.round(o * 1e4) / 1e4,
|
|
1318
1320
|
hoursInECA: Math.round(s * 1e3) / 1e3,
|
|
1319
1321
|
totalDgoConsInECA: Math.round(d * 1e3) / 1e3,
|
|
1320
1322
|
speeds: e
|
|
@@ -1324,15 +1326,15 @@ class O {
|
|
|
1324
1326
|
}
|
|
1325
1327
|
export {
|
|
1326
1328
|
et as AISImpl,
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
+
yt as AlertHelper,
|
|
1330
|
+
mt as AlertLevel,
|
|
1329
1331
|
Et as HifleetImpl,
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1332
|
+
bt as LoadCondition,
|
|
1333
|
+
Nt as MyShipImpl,
|
|
1334
|
+
xt as MyVesselImpl,
|
|
1335
|
+
jt as ShipxyImpl,
|
|
1334
1336
|
O as SpeedHelper,
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1337
|
+
pt as SpeedLabel,
|
|
1338
|
+
gt as VesselTag,
|
|
1339
|
+
Tt as alertHelper
|
|
1338
1340
|
};
|