@idm-plugin/vessel 2.2.0 → 2.2.2
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 +91 -91
- package/dist/index.umd.cjs +1 -1
- package/package.json +7 -5
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@ var lt = (E, t, e) => t in E ? ht(E, t, { enumerable: !0, configurable: !0, writ
|
|
|
3
3
|
var K = (E, t, e) => (lt(E, typeof t != "symbol" ? t + "" : t, e), e);
|
|
4
4
|
import B from "got";
|
|
5
5
|
import ct from "@log4js-node/log4js-api";
|
|
6
|
-
import
|
|
6
|
+
import g from "moment";
|
|
7
7
|
import { LngLatHelper as J, LaneHelper as W } from "@idm-plugin/geo2";
|
|
8
8
|
import { MeteoHelper2 as ft } from "@idm-plugin/meteo2";
|
|
9
9
|
import { Meteo2Assist as rt } from "@idm-plugin/meteo";
|
|
@@ -76,12 +76,12 @@ class xt extends st {
|
|
|
76
76
|
expiresIn: n.expires_in,
|
|
77
77
|
scope: n.scope,
|
|
78
78
|
jti: n.jti,
|
|
79
|
-
issuedAt:
|
|
79
|
+
issuedAt: g().utc().format()
|
|
80
80
|
});
|
|
81
81
|
}
|
|
82
82
|
async realTimePosition(e, a = {}) {
|
|
83
83
|
var d, r, m;
|
|
84
|
-
(!this.token ||
|
|
84
|
+
(!this.token || g().diff(g(this.token.issuedAt), "seconds") > ((d = this.token) == null ? void 0 : d.expiresIn) - 300) && await this.authToken(a);
|
|
85
85
|
const i = "https://svc.data.myvessel.cn/sdc/v1/vessels/status/location/unit", n = {
|
|
86
86
|
headers: {
|
|
87
87
|
Authorization: `${(r = this.token) == null ? void 0 : r.tokenType} ${(m = this.token) == null ? void 0 : m.accessToken}`
|
|
@@ -96,7 +96,7 @@ class xt extends st {
|
|
|
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) {
|
|
99
|
-
const M =
|
|
99
|
+
const M = g(`${s.postime} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
100
100
|
return {
|
|
101
101
|
mmsi: s.mmsi,
|
|
102
102
|
name: s.vesselName || s.aisVesselName,
|
|
@@ -111,7 +111,7 @@ class xt extends st {
|
|
|
111
111
|
cog: s.cog,
|
|
112
112
|
hdg: s.hdg,
|
|
113
113
|
rot: s.rot,
|
|
114
|
-
eta: /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(s.eta) ?
|
|
114
|
+
eta: /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(s.eta) ? g.utc(s.eta).format() : void 0,
|
|
115
115
|
destination: s.dest,
|
|
116
116
|
positionTime: M.unix(),
|
|
117
117
|
status: s.status,
|
|
@@ -132,8 +132,8 @@ class xt extends st {
|
|
|
132
132
|
return {};
|
|
133
133
|
}
|
|
134
134
|
async trajectory(e, a, i, n, o = !0, s = {}) {
|
|
135
|
-
(!this.token ||
|
|
136
|
-
const d = await this.realTimePosition(e, s), r =
|
|
135
|
+
(!this.token || g().diff(g(this.token.issuedAt), "seconds") > this.token.expiresIn - 300) && await this.authToken(s);
|
|
136
|
+
const d = await this.realTimePosition(e, s), r = g(a), m = g(i), M = [];
|
|
137
137
|
for (; m.diff(r, "day", !0) > 30; )
|
|
138
138
|
await this.trajectoryIn30Day(e, r, r.clone().add(30, "day"), d, n, M, s), r.add(30, "day");
|
|
139
139
|
return await this.trajectoryIn30Day(e, r, m, d, n, M, s), M;
|
|
@@ -155,11 +155,11 @@ class xt extends st {
|
|
|
155
155
|
if (M.code)
|
|
156
156
|
return v == null || v.warn("[%s] fetch trajectory failed: %j", d.requestId, r, { message: M.message, status: M.status, code: M.code }), M;
|
|
157
157
|
let l = -1;
|
|
158
|
-
const
|
|
158
|
+
const b = g(`${(p = (S = M.data) == null ? void 0 : S[0]) == null ? void 0 : p.postime} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
159
159
|
return (w = M.data) == null || w.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 y =
|
|
162
|
+
const y = g(`${c.postime} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00"), h = c.status, { labelCn: u, labelEn: I } = this.parseStatus(h), k = {
|
|
163
163
|
mmsi: c.mmsi,
|
|
164
164
|
imo: n == null ? void 0 : n.imo,
|
|
165
165
|
lat: c.lat,
|
|
@@ -169,7 +169,7 @@ class xt extends st {
|
|
|
169
169
|
hdg: c.hdg,
|
|
170
170
|
draught: c.draught,
|
|
171
171
|
status: h,
|
|
172
|
-
eta: /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(c.eta) ?
|
|
172
|
+
eta: /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(c.eta) ? g(`${c.eta} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00").utc().format() : void 0,
|
|
173
173
|
destination: c.dest,
|
|
174
174
|
positionTime: y.unix(),
|
|
175
175
|
labelCn: u,
|
|
@@ -177,7 +177,7 @@ class xt extends st {
|
|
|
177
177
|
method: "trajectory",
|
|
178
178
|
vendor: "myVessel",
|
|
179
179
|
utc: y.utc().format()
|
|
180
|
-
}, D = Math.floor(y.diff(
|
|
180
|
+
}, D = Math.floor(y.diff(b, "minute", !0) / (o || 1));
|
|
181
181
|
D !== l && (l = D, s.push(k));
|
|
182
182
|
}), s;
|
|
183
183
|
}
|
|
@@ -199,10 +199,10 @@ class Et extends st {
|
|
|
199
199
|
const s = o == null ? void 0 : o.list;
|
|
200
200
|
if (!s)
|
|
201
201
|
return v == null || v.warn("[%s] fetch realtime position failed: %j", a.requestId, i, o), o;
|
|
202
|
-
for (const
|
|
203
|
-
!isNaN(s[
|
|
202
|
+
for (const b in s)
|
|
203
|
+
!isNaN(s[b]) && Number(s[b]) !== 1 / 0 && (s[b] = Number(s[b]));
|
|
204
204
|
s.status = s.sp > 3 ? 0 : 1;
|
|
205
|
-
const d = s.status, { labelCn: r, labelEn: m } = this.parseStatus(d), M =
|
|
205
|
+
const d = s.status, { labelCn: r, labelEn: m } = this.parseStatus(d), M = g(`${s.ti} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
206
206
|
return {
|
|
207
207
|
mmsi: s.m,
|
|
208
208
|
name: s.n,
|
|
@@ -217,7 +217,7 @@ class Et extends st {
|
|
|
217
217
|
cog: s.co,
|
|
218
218
|
hdg: s.h,
|
|
219
219
|
rot: isNaN(s.rot) ? 0 : s.rot,
|
|
220
|
-
eta: /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(s.eta) ?
|
|
220
|
+
eta: /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(s.eta) ? g.utc(s.eta).format() : void 0,
|
|
221
221
|
destination: s.destination,
|
|
222
222
|
vesselType: s.type,
|
|
223
223
|
dwt: s.dwt,
|
|
@@ -286,8 +286,8 @@ class Et extends st {
|
|
|
286
286
|
async trajectory(e, a, i, n, o = !0, s = {}) {
|
|
287
287
|
var c, y, h;
|
|
288
288
|
const d = await this.realTimePosition(e, s);
|
|
289
|
-
let r =
|
|
290
|
-
const m =
|
|
289
|
+
let r = g(a);
|
|
290
|
+
const m = g(i), M = g();
|
|
291
291
|
if (o) {
|
|
292
292
|
let u = m.diff(r, "d", !0);
|
|
293
293
|
u < 0 ? r = m.clone().subtract(40, "d") : u < 30 ? r.subtract(10, "d") : u < 60 ? r.subtract(5, "d") : r = m.clone().subtract(80, "d"), u = M.diff(m, "d", !0), m.add(u > 10 ? 240 : u * 24, "h");
|
|
@@ -299,17 +299,17 @@ class Et extends st {
|
|
|
299
299
|
mmsi: e,
|
|
300
300
|
usertoken: this.token
|
|
301
301
|
}
|
|
302
|
-
},
|
|
303
|
-
v == null || v.info("[%s] fetch trajectory from: %s - %j", s.requestId,
|
|
302
|
+
}, b = "https://api.hifleet.com/position/trajectory/nocompressed/withstatic/token", f = await B.get(b, l).json();
|
|
303
|
+
v == null || v.info("[%s] fetch trajectory from: %s - %j", s.requestId, b, l);
|
|
304
304
|
let C;
|
|
305
305
|
f && (C = ((y = (c = f.ships) == null ? void 0 : c.offors) == null ? void 0 : y.ship) || [], C.length || v == null || v.warn("[%s] fetch trajectory failed: %j", s.requestId, f));
|
|
306
306
|
const S = [];
|
|
307
307
|
let p = -1;
|
|
308
|
-
const w =
|
|
308
|
+
const w = g(`${(h = C == null ? void 0 : C[0]) == null ? void 0 : h.ti} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
309
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
|
-
const I =
|
|
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
314
|
const { labelEn: k, labelCn: D } = this.parseStatus(u.status), Y = {
|
|
315
315
|
mmsi: u.m,
|
|
@@ -353,7 +353,7 @@ class jt extends st {
|
|
|
353
353
|
const s = o.data[0];
|
|
354
354
|
for (const l in s)
|
|
355
355
|
!isNaN(s[l]) && Number(s[l]) !== 1 / 0 && (s[l] = Number(s[l]));
|
|
356
|
-
const { labelCn: d, labelEn: r } = await this.parseStatus(s.navistat), m =
|
|
356
|
+
const { labelCn: d, labelEn: r } = await this.parseStatus(s.navistat), m = g.unix(s.lasttime);
|
|
357
357
|
return {
|
|
358
358
|
mmsi: s.ShipID,
|
|
359
359
|
name: s.name,
|
|
@@ -379,7 +379,7 @@ class jt extends st {
|
|
|
379
379
|
}
|
|
380
380
|
async trajectory(e, a, i, n, o = !0, s = {}) {
|
|
381
381
|
var w;
|
|
382
|
-
const d = await this.realTimePosition(e, s), r =
|
|
382
|
+
const d = await this.realTimePosition(e, s), r = g(a), m = g(i), M = "https://api.shipxy.com/apicall/GetShipTrack", l = {
|
|
383
383
|
searchParams: {
|
|
384
384
|
id: e,
|
|
385
385
|
k: this.token,
|
|
@@ -388,13 +388,13 @@ class jt extends st {
|
|
|
388
388
|
btm: r.unix(),
|
|
389
389
|
etm: m.unix()
|
|
390
390
|
}
|
|
391
|
-
},
|
|
392
|
-
if (v == null || v.info("[%s] fetch trajectory from: %s - %j", s.requestId, M, l), (
|
|
393
|
-
return
|
|
394
|
-
const f =
|
|
391
|
+
}, b = await B.get(M, l).json();
|
|
392
|
+
if (v == null || v.info("[%s] fetch trajectory from: %s - %j", s.requestId, M, l), (b == null ? void 0 : b.status) !== 0)
|
|
393
|
+
return b;
|
|
394
|
+
const f = b == null ? void 0 : b.points, C = [], S = g.unix((w = f[0]) == null ? void 0 : w.utc);
|
|
395
395
|
let p = -1;
|
|
396
396
|
for (const c of f) {
|
|
397
|
-
const y =
|
|
397
|
+
const y = g.unix(c.utc), h = {
|
|
398
398
|
imo: d == null ? void 0 : d.imo,
|
|
399
399
|
mmsi: e,
|
|
400
400
|
sog: Math.round(c.sog * 3600 / 1e3 / 1852 * 100) / 100,
|
|
@@ -464,7 +464,7 @@ class Nt extends st {
|
|
|
464
464
|
const r = d.data[0];
|
|
465
465
|
for (const f in r)
|
|
466
466
|
!isNaN(r[f]) && Number(r[f]) !== 1 / 0 && (r[f] = Number(r[f]));
|
|
467
|
-
const { labelCn: m, labelEn: M } = await this.parseStatus(r.aisNavStatus), l =
|
|
467
|
+
const { labelCn: m, labelEn: M } = await this.parseStatus(r.aisNavStatus), l = g.unix(r.posTime);
|
|
468
468
|
return {
|
|
469
469
|
...n,
|
|
470
470
|
mmsi: e,
|
|
@@ -484,7 +484,7 @@ class Nt extends st {
|
|
|
484
484
|
};
|
|
485
485
|
}
|
|
486
486
|
async trajectory(e, a, i, n, o = !0, s = {}) {
|
|
487
|
-
const d =
|
|
487
|
+
const d = g(a), r = g(i), m = await this.getShipId(e), M = await this.getShipInfo(m), l = [];
|
|
488
488
|
for (; r.diff(d, "day", !0) > 30; )
|
|
489
489
|
await this.trajectoryIn30Day(m, d.unix(), d.add(30, "day").unix(), M, e, n, l);
|
|
490
490
|
return await this.trajectoryIn30Day(m, d.unix(), r.unix(), M, e, n, l), l;
|
|
@@ -503,13 +503,13 @@ class Nt extends st {
|
|
|
503
503
|
}, M = "https://api3.myships.com/sp/ships/position/history", l = await B.post(M, m).json();
|
|
504
504
|
if (v == null || v.info("[%s] fetch trajectory from: %s - %j", r.requestId, M, m), l.code !== "0")
|
|
505
505
|
return v == null || v.warn("[%s] invoke myship trajectory failed: %j", r.requestId, l), l;
|
|
506
|
-
const
|
|
507
|
-
for (const p in
|
|
508
|
-
!isNaN(
|
|
509
|
-
const f =
|
|
506
|
+
const b = l.data;
|
|
507
|
+
for (const p in b)
|
|
508
|
+
!isNaN(b[p]) && Number(b[p]) !== 1 / 0 && (b[p] = Number(b[p]));
|
|
509
|
+
const f = g.unix((S = b[0]) == null ? void 0 : S.posTime);
|
|
510
510
|
let C = -1;
|
|
511
|
-
for (const p of
|
|
512
|
-
const w =
|
|
511
|
+
for (const p of b) {
|
|
512
|
+
const w = g.unix(p.posTime), c = {
|
|
513
513
|
imo: n == null ? void 0 : n.imo,
|
|
514
514
|
mmsi: o,
|
|
515
515
|
lat: Math.round(p.lat / 1e4 / 60 * 1e5) / 1e5,
|
|
@@ -556,7 +556,7 @@ class yt {
|
|
|
556
556
|
if (m === 0 && !M)
|
|
557
557
|
o.scope = n[0];
|
|
558
558
|
else if (M)
|
|
559
|
-
for (let l = 0,
|
|
559
|
+
for (let l = 0, b = M.length; l < b; l++) {
|
|
560
560
|
const f = this.parseRule(M[l]);
|
|
561
561
|
f && (o[f.level] ? f.key ? o[f.level][f == null ? void 0 : f.key] = f : o[f.level] = f : f.key ? o[f.level] = { [f == null ? void 0 : f.key]: f } : o[f.level] = f);
|
|
562
562
|
}
|
|
@@ -591,12 +591,12 @@ class yt {
|
|
|
591
591
|
checkWeather(t, e, a = {}) {
|
|
592
592
|
var f, C, S, p, w, c, y, h, u, I, k, D, Y, j, P;
|
|
593
593
|
let i = 0, n = 0, o = 0, s = 0;
|
|
594
|
-
const d = Math.round(((C = (f = e == null ? void 0 : e.SEVERE) == null ? void 0 : f.sigWave) == null ? void 0 : C.number) * 1.6 * 100) / 100, r = (p = (S = e == null ? void 0 : e.SEVERE) == null ? void 0 : S.sigWave) == null ? void 0 : p.number, m = (c = (w = e == null ? void 0 : e.HEAVY) == null ? void 0 : w.sigWave) == null ? void 0 : c.number, M = Math.round((((h = (y = e == null ? void 0 : e.SEVERE) == null ? void 0 : y.wind) == null ? void 0 : h.number) + 2) * 100) / 100, l = (I = (u = e == null ? void 0 : e.SEVERE) == null ? void 0 : u.wind) == null ? void 0 : I.number,
|
|
594
|
+
const d = Math.round(((C = (f = e == null ? void 0 : e.SEVERE) == null ? void 0 : f.sigWave) == null ? void 0 : C.number) * 1.6 * 100) / 100, r = (p = (S = e == null ? void 0 : e.SEVERE) == null ? void 0 : S.sigWave) == null ? void 0 : p.number, m = (c = (w = e == null ? void 0 : e.HEAVY) == null ? void 0 : w.sigWave) == null ? void 0 : c.number, M = Math.round((((h = (y = e == null ? void 0 : e.SEVERE) == null ? void 0 : y.wind) == null ? void 0 : h.number) + 2) * 100) / 100, l = (I = (u = e == null ? void 0 : e.SEVERE) == null ? void 0 : u.wind) == null ? void 0 : I.number, b = (D = (k = e == null ? void 0 : e.HEAVY) == null ? void 0 : k.wind) == null ? void 0 : D.number;
|
|
595
595
|
for (let T = 0; T < (t == null ? void 0 : t.length); T++) {
|
|
596
|
-
const N = t[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 ?
|
|
597
|
-
s = U > s ? U : s, _ == null || _.debug("[%s] check sig.wave: %j", a.requestId, { ...A, dgThd4Wv: d, svThd4Wv: r, hvThd4Wv: m }), (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) >= m && (N.isHeavy = !0), _ == null || _.debug("[%s] check wind: %j", a.requestId, { ...R, dgThd4Wd: M, svThd4Wd: l, hvThd4Wd:
|
|
596
|
+
const N = t[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(t[T - 1].eta), "hour", !0) : 0;
|
|
597
|
+
s = U > s ? U : s, _ == null || _.debug("[%s] check sig.wave: %j", a.requestId, { ...A, dgThd4Wv: d, svThd4Wv: r, hvThd4Wv: m }), (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) >= m && (N.isHeavy = !0), _ == null || _.debug("[%s] check wind: %j", a.requestId, { ...R, dgThd4Wd: M, svThd4Wd: l, hvThd4Wd: b }), (R == null ? void 0 : R.scale) >= M ? (N.isDangerous = !0, delete N.isSevere, delete N.isHeavy) : (R == null ? void 0 : R.scale) > l ? (N.isDangerous || (N.isSevere = !0), delete N.isHeavy) : (R == null ? void 0 : R.scale) === b && !N.isDangerous && !N.isSevere && (N.isHeavy = !0), i += N.isDangerous ? U : 0, n += N.isSevere ? U : 0, o += N.isHeavy ? U : 0;
|
|
598
598
|
}
|
|
599
|
-
return i = Math.round(i * 100) / 100, n = Math.round(n * 100) / 100, o = Math.round(o * 100) / 100, s = Math.round(s), { sample: t, dangerous: i, severe: n, heavy: o, step: s < 3 ? 3 : s, wind: { dgThd4Wd: M, svThd4Wd: l, hvThd4Wd:
|
|
599
|
+
return i = Math.round(i * 100) / 100, n = Math.round(n * 100) / 100, o = Math.round(o * 100) / 100, s = Math.round(s), { sample: t, dangerous: i, severe: n, heavy: o, step: s < 3 ? 3 : s, wind: { dgThd4Wd: M, svThd4Wd: l, hvThd4Wd: b }, sig: { dgThd4Wv: d, svThd4Wv: r, hvThd4Wv: m } };
|
|
600
600
|
}
|
|
601
601
|
}
|
|
602
602
|
const Tt = new yt();
|
|
@@ -607,7 +607,7 @@ try {
|
|
|
607
607
|
} finally {
|
|
608
608
|
}
|
|
609
609
|
const Mt = new ft("", !0);
|
|
610
|
-
var
|
|
610
|
+
var bt = /* @__PURE__ */ ((E) => (E.common = "common", E.container = "container", E.tugs = "tugs", E))(bt || {}), gt = /* @__PURE__ */ ((E) => (E.Ballast = "Ballast", E.Laden = "Laden", E))(gt || {}), wt = /* @__PURE__ */ ((E) => (E.Cp = "CP", E.Perf = "Basis", E.Instruct = "Other", E))(wt || {});
|
|
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
|
|
@@ -709,7 +709,7 @@ class O {
|
|
|
709
709
|
static waveHeightFactor(t, e) {
|
|
710
710
|
t = t < 3 ? t * 0.7 : t, t = t < 0 ? 0.2 : t, t = t > 6 ? t - 0.9 * (t - 6) : t, t = t > 9 ? 9 : t;
|
|
711
711
|
let a;
|
|
712
|
-
return e > 30 && e <= 60 ? a = -0.6 : e > 60 && e <= 90 ? a = -0.4 : e > 90 && e <= 120 ? a = t < 3 ? 0.4 : -0.3 : e > 120 && e <= 150 ? a = t < 3 ? 0.6 : -0.5 : e > 150 && e <= 180 ? a = t < 3 ? 0.7 : -0.6 : a = -0.7, Math.round(a * (0.
|
|
712
|
+
return e > 30 && e <= 60 ? a = -0.6 : e > 60 && e <= 90 ? a = -0.4 : e > 90 && e <= 120 ? a = t < 3 ? 0.4 : -0.3 : e > 120 && e <= 150 ? a = t < 3 ? 0.6 : -0.5 : e > 150 && e <= 180 ? a = t < 3 ? 0.7 : -0.6 : a = -0.7, Math.round(a * (0.144 * Math.pow(t, 3) + 0.178 * t) * 1e4) / 1e4;
|
|
713
713
|
}
|
|
714
714
|
/**
|
|
715
715
|
* 组装船舶运行参数
|
|
@@ -763,12 +763,12 @@ class O {
|
|
|
763
763
|
} catch (f) {
|
|
764
764
|
F.warn("[%s] meteo2 spot(%j) forecast failed: %s", d.requestId, { ...e, eta: a.utc().format(), source: i }, f);
|
|
765
765
|
}
|
|
766
|
-
const M = O.weatherFactor(t, m), l = O.currentFactor(t.bearing, m == null ? void 0 : m.current, n),
|
|
766
|
+
const M = O.weatherFactor(t, m), l = O.currentFactor(t.bearing, m == null ? void 0 : m.current, n), b = Math.round((t.speed * 1.943844 + M + l) * 100) / 100;
|
|
767
767
|
r = {
|
|
768
768
|
meteo: { ...m },
|
|
769
769
|
wxFactor: M,
|
|
770
770
|
cFactor: l,
|
|
771
|
-
speed: e.velocity && s ? e.velocity :
|
|
771
|
+
speed: e.velocity && s ? e.velocity : b < 0 ? 1 : b,
|
|
772
772
|
eta: a.utc().format(),
|
|
773
773
|
etd: a.utc().format()
|
|
774
774
|
};
|
|
@@ -797,7 +797,7 @@ class O {
|
|
|
797
797
|
*/
|
|
798
798
|
static async speedLoseInHoursStep(t, e, a, i, n, o, s = "", d = !0, r = !1, m = {}) {
|
|
799
799
|
e.utc();
|
|
800
|
-
const M = e.clone().add(14, "days"), l = [],
|
|
800
|
+
const M = e.clone().add(14, "days"), l = [], b = [];
|
|
801
801
|
let f = 0, C = 0, S, p;
|
|
802
802
|
for (let w = 0; w < o.length - 1; w++) {
|
|
803
803
|
let c = o[w];
|
|
@@ -813,10 +813,10 @@ class O {
|
|
|
813
813
|
c.elapsed += k, e.add(k, "hour"), i = 0;
|
|
814
814
|
}
|
|
815
815
|
if (F == null || F.info(`[%s] suspend ${c.elapsed} hours at %j, and remain ${i} hours need to go...`, m.requestId, c), i === 0)
|
|
816
|
-
return c.distanceFromPrevious = C, { etd: e, from: p || c, to: c, next: o.filter((k) => k), wps: l, days:
|
|
816
|
+
return c.distanceFromPrevious = C, { etd: e, from: p || c, to: c, next: o.filter((k) => k), wps: l, days: b };
|
|
817
817
|
} else
|
|
818
818
|
c.suspend = 0;
|
|
819
|
-
d = e.isAfter(M) ? !1 : d, c = await O.speedLoseAt(t, c, e, s, 0, d, r, m), p = p || c, c.important && l.push(c), e.isSameOrAfter(a) && (
|
|
819
|
+
d = e.isAfter(M) ? !1 : d, c = await O.speedLoseAt(t, c, e, s, 0, d, r, m), p = p || c, c.important && l.push(c), e.isSameOrAfter(a) && (b.push(c), a.add(24, "hour"));
|
|
820
820
|
const h = W.calculateDistance(c, y, !y.gcToPrevious);
|
|
821
821
|
let u = Math.round(h / p.speed * 1e5) / 1e5;
|
|
822
822
|
if (f + u < i) {
|
|
@@ -841,7 +841,7 @@ class O {
|
|
|
841
841
|
break;
|
|
842
842
|
}
|
|
843
843
|
}
|
|
844
|
-
return { etd: e, from: p, to: S, next: o.filter((w) => w), wps: l, days:
|
|
844
|
+
return { etd: e, from: p, to: S, next: o.filter((w) => w), wps: l, days: b };
|
|
845
845
|
}
|
|
846
846
|
/**
|
|
847
847
|
* 洋流影响因子
|
|
@@ -862,16 +862,16 @@ class O {
|
|
|
862
862
|
* @param wwc 气象要素
|
|
863
863
|
*/
|
|
864
864
|
static weatherFactor(t, e) {
|
|
865
|
-
var M, l,
|
|
865
|
+
var M, l, b, f, C, S, p;
|
|
866
866
|
F == null || F.debug("calculate weather factor via: %j", { ...t, ...e });
|
|
867
867
|
const a = O.blockCoefficient(t.displacement, t.lbp, t.breadthMoulded, t.draught), i = O.froudeNumber(t.speed, t.lbp), n = O.amendFactor(a, i, t.loadCondition);
|
|
868
868
|
let o = Math.abs(t.bearing % 360 - (((M = e == null ? void 0 : e.wind) == null ? void 0 : M.degree) % 360 || 0));
|
|
869
869
|
o = o > 180 ? 360 - o : o;
|
|
870
|
-
const s = O.directionFactor(o, (l = e == null ? void 0 : e.wind) == null ? void 0 : l.scale), d = O.vesselTagFactor(t.displacement, t.loadCondition, t.tag, (
|
|
870
|
+
const s = O.directionFactor(o, (l = e == null ? void 0 : e.wind) == null ? void 0 : l.scale), d = O.vesselTagFactor(t.displacement, t.loadCondition, t.tag, (b = e == null ? void 0 : e.wind) == null ? void 0 : b.scale);
|
|
871
871
|
let r = s * n * d / 100 * t.speed;
|
|
872
872
|
r = Math.round(r * 1.943844 * 1e4) / 1e4 * -1, t.tag === "tugs" && Math.abs(r) > 1 && (r = r / (Math.abs(Math.round(r)) + 1)), F == null || F.debug("wind wx factor = %d", r), o = Math.abs(t.bearing % 360 - (((C = (f = e == null ? void 0 : e.wave) == null ? void 0 : f.sig) == null ? void 0 : C.degree) % 360 || 0));
|
|
873
873
|
const m = O.waveHeightFactor(((p = (S = e == null ? void 0 : e.wave) == null ? void 0 : S.sig) == null ? void 0 : p.height) ?? 1, o);
|
|
874
|
-
return F == null || F.debug("wave wx factor = %d", m), r = r * 0.3 + m * 0.7, F == null || F.debug("weather factor = %d", r), r = Math.abs(r) >
|
|
874
|
+
return F == null || F.debug("wave wx factor = %d", m), r = Math.abs(r) > Math.abs(m) ? r : r * 0.3 + m * 0.7, F == null || F.debug("weather factor = %d", r), r = Math.abs(r) > 3 ? 3 * (Math.abs(r) / r) + Math.abs(r) / r * (Math.abs(r) - 2) * 0.1 : r, Math.round((r || 0) * 100) / 100;
|
|
875
875
|
}
|
|
876
876
|
/**
|
|
877
877
|
* 全程失速分析(走完航程)
|
|
@@ -887,9 +887,9 @@ class O {
|
|
|
887
887
|
*/
|
|
888
888
|
static async analyseInstant(t, e, a, i, n, o = "", s = 0, d = !0, r = !1, m = {}) {
|
|
889
889
|
var z, G, Q, X, Z, $;
|
|
890
|
-
const M =
|
|
890
|
+
const M = g().valueOf();
|
|
891
891
|
t.lng = J.convertToStdLng(t.lng);
|
|
892
|
-
const { route: l, waypoints:
|
|
892
|
+
const { route: l, waypoints: b } = n.points, f = W.calculateSubRoute(t, l);
|
|
893
893
|
if (((z = f[0]) == null ? void 0 : z.length) <= 1)
|
|
894
894
|
return;
|
|
895
895
|
const { v0: C, label: S } = t.sog ? {
|
|
@@ -900,7 +900,7 @@ class O {
|
|
|
900
900
|
v0: i.speed,
|
|
901
901
|
label: "CP"
|
|
902
902
|
/* Cp */
|
|
903
|
-
}, p = O.assembleProperties(a, i.loadCondition, C, 0), w =
|
|
903
|
+
}, p = O.assembleProperties(a, i.loadCondition, C, 0), w = b.length ? W.calculateSubWaypoints(t, b) : [];
|
|
904
904
|
w.forEach((q) => q.important = !0);
|
|
905
905
|
const c = {
|
|
906
906
|
from: { ...t },
|
|
@@ -915,7 +915,7 @@ class O {
|
|
|
915
915
|
};
|
|
916
916
|
s || (W.calculateRouteDistance(f) / i.speed <= 72 ? s = 3 : s = 6);
|
|
917
917
|
let h = W.simplifyRouteToCoordinates(f, w, 0), u = 0, I = 0, k = 0, D = 0;
|
|
918
|
-
e =
|
|
918
|
+
e = g(e).utc();
|
|
919
919
|
const Y = e.clone();
|
|
920
920
|
for (; h.length > 0; ) {
|
|
921
921
|
const q = s - e.hour() % s, V = Math.ceil(e.clone().add(q, "h").set({ minute: 0, second: 0, millisecond: 0 }).diff(e, "h", !0) * 1e4) / 1e4, x = await O.speedLoseInHoursStep(
|
|
@@ -934,21 +934,21 @@ class O {
|
|
|
934
934
|
}
|
|
935
935
|
const j = y.hours;
|
|
936
936
|
for (let q = 0; q < j.length - 1; q++) {
|
|
937
|
-
const V =
|
|
937
|
+
const V = g(j[q + 1].eta).diff(j[q].etd, "hour", !0) || 1;
|
|
938
938
|
I += (j[q].wxFactor || 0) * V, k += (j[q].cFactor || 0) * V, D += V;
|
|
939
939
|
}
|
|
940
940
|
(X = y.wps) == null || X.forEach((q, V) => {
|
|
941
|
-
q.positionTime =
|
|
941
|
+
q.positionTime = g.utc(q.etd || q.eta).unix();
|
|
942
942
|
const x = y.wps[V - 1];
|
|
943
943
|
if (x) {
|
|
944
|
-
const L = q.distanceFromStart - x.distanceFromStart, H =
|
|
944
|
+
const L = q.distanceFromStart - x.distanceFromStart, H = g(q.eta || q.etd).diff(g(x.etd || x.eta), "h", !0);
|
|
945
945
|
q.avgSpd = Math.round(L / H * 100) / 100;
|
|
946
946
|
const it = W.calculateBearing(x, q);
|
|
947
947
|
x.bearing = it;
|
|
948
948
|
}
|
|
949
949
|
}), y.wps = (Z = y.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 = y;
|
|
950
950
|
const P = y.hours.at(0), T = y.hours.at(-1);
|
|
951
|
-
c.distance = Math.round(T.distanceFromStart * 1e3) / 1e3, c.etd =
|
|
951
|
+
c.distance = Math.round(T.distanceFromStart * 1e3) / 1e3, c.etd = g(P.eta).utc().format(), c.eta = g(T.eta).utc().format(), c.wxFactor = Math.round(I / D * 1e3) / 1e3, c.cFactor = Math.round(k / D * 1e3) / 1e3, c.avgSpeed = Math.round(T.distanceFromStart / D * 1e3) / 1e3, c.totalHrs = Math.round(D * 1e3) / 1e3;
|
|
952
952
|
const { distanceInECA: N, hoursInECA: A, totalDgoConsInECA: R, eca: U } = await this.calculateECA(c, i, m), tt = J.roundPrecision(i.fo / 24 * (D - A), 3), at = J.roundPrecision(i.dgo / 24 * D, 3);
|
|
953
953
|
c.extend = {
|
|
954
954
|
eca: U,
|
|
@@ -956,7 +956,7 @@ class O {
|
|
|
956
956
|
hoursInECA: A,
|
|
957
957
|
totalDgoConsInECA: R
|
|
958
958
|
}, c.totalFoCons = tt < 0 ? 0 : tt, c.totalDgoCons = at;
|
|
959
|
-
const et =
|
|
959
|
+
const et = g().valueOf() - M, nt = (($ = y == null ? void 0 : y.hours) == null ? void 0 : $.length) || 1;
|
|
960
960
|
return F == null || F.info("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms", m == null ? void 0 : m.requestId, et, nt, Math.round(et / nt * 1e3) / 1e3), c;
|
|
961
961
|
}
|
|
962
962
|
/**
|
|
@@ -974,7 +974,7 @@ class O {
|
|
|
974
974
|
*/
|
|
975
975
|
static async analyseInstantWithThreshed(t, e, a, i, n, o, s, d = "", r = 3, m = !0, M = !1, l = {}) {
|
|
976
976
|
var Q, X, Z, $, q, V;
|
|
977
|
-
const
|
|
977
|
+
const b = g().valueOf();
|
|
978
978
|
t.lng = J.convertToStdLng(t.lng);
|
|
979
979
|
const { v0: f, label: C } = t.sog ? {
|
|
980
980
|
v0: t.sog,
|
|
@@ -995,7 +995,7 @@ class O {
|
|
|
995
995
|
wps: [],
|
|
996
996
|
days: []
|
|
997
997
|
};
|
|
998
|
-
e =
|
|
998
|
+
e = g(e).utc();
|
|
999
999
|
const D = e.clone();
|
|
1000
1000
|
for (; c.length > 0; ) {
|
|
1001
1001
|
const x = r - e.hour() % r;
|
|
@@ -1005,10 +1005,10 @@ class O {
|
|
|
1005
1005
|
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), y += Math.round((((Z = H == null ? void 0 : H.to) == null ? void 0 : Z.distanceFromPrevious) ?? 0) * 1e4) / 1e4, !L)
|
|
1006
1006
|
break;
|
|
1007
1007
|
}
|
|
1008
|
-
k.wps = ($ = k.wps) == null ? void 0 : $.reduce((x, L) => (x.some((H) => Math.round(
|
|
1008
|
+
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) => {
|
|
1009
1009
|
const H = k.wps[L - 1];
|
|
1010
1010
|
if (H) {
|
|
1011
|
-
const it = x.distanceFromStart - H.distanceFromStart, dt =
|
|
1011
|
+
const it = x.distanceFromStart - H.distanceFromStart, dt = g(x.eta || x.etd).diff(g(H.etd || H.eta), "h", !0);
|
|
1012
1012
|
x.avgSpd = Math.round(it / dt * 100) / 100;
|
|
1013
1013
|
const ut = W.calculateBearing(H, x);
|
|
1014
1014
|
H.bearing = ut;
|
|
@@ -1016,15 +1016,15 @@ class O {
|
|
|
1016
1016
|
});
|
|
1017
1017
|
const Y = k.hours;
|
|
1018
1018
|
for (let x = 0; x < Y.length - 1; x++) {
|
|
1019
|
-
const L =
|
|
1019
|
+
const L = g(Y[x + 1].eta).diff(Y[x].etd, "hour", !0);
|
|
1020
1020
|
h += Y[x].wxFactor * L, u += Y[x].cFactor * L, I += L;
|
|
1021
1021
|
}
|
|
1022
1022
|
const j = k.hours.at(0), P = k.hours.at(-1), T = await W.calculateRangeRoute(j, P, p), N = await W.calculateRangeWaypoints(j, P, p, w), A = {
|
|
1023
1023
|
sample: k,
|
|
1024
1024
|
distance: Math.round(((P == null ? void 0 : P.distanceFromStart) || 0) * 1e4) / 1e4,
|
|
1025
1025
|
// 注意,可能会在first节点Drift,所有采用eta做为初始出发时间
|
|
1026
|
-
etd:
|
|
1027
|
-
eta:
|
|
1026
|
+
etd: g(j.eta).utc().format(),
|
|
1027
|
+
eta: g(P == null ? void 0 : P.eta).utc().format(),
|
|
1028
1028
|
wxFactor: Math.round(h / I * 1e3) / 1e3,
|
|
1029
1029
|
cFactor: Math.round(u / I * 1e3) / 1e3,
|
|
1030
1030
|
avgSpeed: Math.round(((P == null ? void 0 : P.distanceFromStart) || 0) / I * 1e3) / 1e3,
|
|
@@ -1042,7 +1042,7 @@ class O {
|
|
|
1042
1042
|
hoursInECA: U,
|
|
1043
1043
|
totalDgoConsInECA: tt
|
|
1044
1044
|
}, A.totalDgoCons = et, A.totalFoCons = ot < 0 ? 0 : ot;
|
|
1045
|
-
const z =
|
|
1045
|
+
const z = g().valueOf() - b, G = ((V = k == null ? void 0 : k.hours) == null ? void 0 : V.length) || 1;
|
|
1046
1046
|
return F == null || F.debug("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms", l == null ? void 0 : l.requestId, z, G, Math.round(z / G * 1e3) / 1e3), A;
|
|
1047
1047
|
}
|
|
1048
1048
|
/**
|
|
@@ -1062,7 +1062,7 @@ class O {
|
|
|
1062
1062
|
*/
|
|
1063
1063
|
static async analyseCost(t, e, a, i, n = {}) {
|
|
1064
1064
|
var p, w;
|
|
1065
|
-
const o =
|
|
1065
|
+
const o = g().valueOf(), s = [];
|
|
1066
1066
|
t.speedStep = t.speedStep || 3, t.alterStep = t.alterStep ?? 1;
|
|
1067
1067
|
const d = W.calculateRouteDistance(i.route);
|
|
1068
1068
|
let r = 0;
|
|
@@ -1070,7 +1070,7 @@ class O {
|
|
|
1070
1070
|
const y = Math.ceil(d / c.speed / 24);
|
|
1071
1071
|
r = r < y ? y : r;
|
|
1072
1072
|
}), r = r * 1.3;
|
|
1073
|
-
const m =
|
|
1073
|
+
const m = g.utc(t.etd).add(r ?? 14, "day");
|
|
1074
1074
|
let M = 1;
|
|
1075
1075
|
for (const c of a) {
|
|
1076
1076
|
const y = JSON.parse(JSON.stringify(i.route)), h = JSON.parse(JSON.stringify(i.waypoints)), u = await O.analyseInstantWithThreshed(
|
|
@@ -1097,12 +1097,12 @@ class O {
|
|
|
1097
1097
|
})), M++;
|
|
1098
1098
|
}
|
|
1099
1099
|
s.sort((c, y) => c.cost.total - y.cost.total);
|
|
1100
|
-
const l = s.at(0),
|
|
1101
|
-
if (f.push({ combined: !1, speeds: [l], cost: (p = l.cost) == null ? void 0 : p.total }),
|
|
1102
|
-
const c = l.cost.cp, y =
|
|
1100
|
+
const l = s.at(0), b = s.at(1), f = [];
|
|
1101
|
+
if (f.push({ combined: !1, speeds: [l], cost: (p = l.cost) == null ? void 0 : p.total }), b) {
|
|
1102
|
+
const c = l.cost.cp, y = b.cost.cp, h = g(l.eta), u = g(l.etd), I = h.diff(u, "days", !0);
|
|
1103
1103
|
let k = Math.ceil(I / 2);
|
|
1104
1104
|
k = k > 7 ? 7 : k < t.alterStep ? t.alterStep : k;
|
|
1105
|
-
let D = 2, Y = { combined: !1, speeds: [
|
|
1105
|
+
let D = 2, Y = { combined: !1, speeds: [b], cost: (w = b.cost) == null ? void 0 : w.total }, j;
|
|
1106
1106
|
for (; k >= t.alterStep; ) {
|
|
1107
1107
|
const P = await O.combinedAnalyse(t, e, m, [c, y], i, k, { ...n, level: D });
|
|
1108
1108
|
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 <= t.alterStep)
|
|
@@ -1111,7 +1111,7 @@ class O {
|
|
|
1111
1111
|
}
|
|
1112
1112
|
f.push(Y), j && f.push(j);
|
|
1113
1113
|
}
|
|
1114
|
-
const S =
|
|
1114
|
+
const S = g().valueOf() - o;
|
|
1115
1115
|
return F == null || F.info("[%s] analyse elapsed: %d ms", n == null ? void 0 : n.requestId, S), f.sort((c, y) => c.cost - y.cost);
|
|
1116
1116
|
}
|
|
1117
1117
|
/**
|
|
@@ -1126,13 +1126,13 @@ class O {
|
|
|
1126
1126
|
*/
|
|
1127
1127
|
static async combinedAnalyse(t, e, a, i, n, o, s = {}) {
|
|
1128
1128
|
s.counter = 1, F == null || F.info("[%s][L%d] analyse with alternate cp in every %d days", s.requestId, s.level, o);
|
|
1129
|
-
const d = await O.alternateAnalyse(t, e, a, i, 0, n, o, s), r = d.reduce((y, h) => y + h.cost.total, 0), m = d.reduce((y, h) => y + h.cost.hire, 0), M = d.reduce((y, h) => y + h.cost.bunker, 0), l = d.reduce((y, h) => y + h.distance, 0),
|
|
1129
|
+
const d = await O.alternateAnalyse(t, e, a, i, 0, n, o, s), r = d.reduce((y, h) => y + h.cost.total, 0), m = d.reduce((y, h) => y + h.cost.hire, 0), M = d.reduce((y, h) => y + h.cost.bunker, 0), l = d.reduce((y, h) => y + h.distance, 0), b = d.reduce((y, h) => y + h.totalHrs, 0);
|
|
1130
1130
|
F == null || F.info("[%s][L%d] cost with cpa/cpb turn: %j", s.requestId, s.level, {
|
|
1131
1131
|
cost: r,
|
|
1132
1132
|
hire: m,
|
|
1133
1133
|
bunker: M,
|
|
1134
1134
|
distance: l,
|
|
1135
|
-
hours:
|
|
1135
|
+
hours: b
|
|
1136
1136
|
});
|
|
1137
1137
|
const f = await O.alternateAnalyse(t, e, a, i, 1, n, o, s), C = f.reduce((y, h) => y + h.cost.total, 0), S = f.reduce((y, h) => y + h.cost.hire, 0), p = f.reduce((y, h) => y + h.cost.bunker, 0), w = f.reduce((y, h) => y + h.distance, 0), c = f.reduce((y, h) => y + h.totalHrs, 0);
|
|
1138
1138
|
return F == null || F.info("[%s][L%d] cost with cpb/cpa turn: %j", s.requestId, s.level, {
|
|
@@ -1155,8 +1155,8 @@ class O {
|
|
|
1155
1155
|
* @param options
|
|
1156
1156
|
*/
|
|
1157
1157
|
static async alternateAnalyse(t, e, a, i, n, o, s, d = {}) {
|
|
1158
|
-
var l,
|
|
1159
|
-
let r =
|
|
1158
|
+
var l, b;
|
|
1159
|
+
let r = g.utc(t.etd);
|
|
1160
1160
|
const m = { lat: t.lat, lng: t.lng }, M = [];
|
|
1161
1161
|
for (; r.isBefore(a); ) {
|
|
1162
1162
|
const f = r.clone().utc().add(s, "day"), C = JSON.parse(JSON.stringify(o.route)), S = JSON.parse(JSON.stringify(o.waypoints)), p = i[n], w = await O.analyseInstantWithThreshed(
|
|
@@ -1189,9 +1189,9 @@ class O {
|
|
|
1189
1189
|
cp: `${p.speed}/${p.fo}/${p.dgo}`
|
|
1190
1190
|
}
|
|
1191
1191
|
)), d.counter = d.counter + 1;
|
|
1192
|
-
const c = (
|
|
1192
|
+
const c = (b = (l = w == null ? void 0 : w.sample) == null ? void 0 : l.hours) == null ? void 0 : b.at(-1);
|
|
1193
1193
|
if (c)
|
|
1194
|
-
m.lat = c.lat, m.lng = c.lng, r =
|
|
1194
|
+
m.lat = c.lat, m.lng = c.lng, r = g(c.eta), M.push(w), n = n ? 0 : 1;
|
|
1195
1195
|
else
|
|
1196
1196
|
break;
|
|
1197
1197
|
}
|
|
@@ -1226,12 +1226,12 @@ class O {
|
|
|
1226
1226
|
const i = await W.intersectInECA((t == null ? void 0 : t.route) || []);
|
|
1227
1227
|
let n = 0, o = 0, s = 0;
|
|
1228
1228
|
(r = (d = t == null ? void 0 : t.sample) == null ? void 0 : d.wps) == null || r.forEach((l) => {
|
|
1229
|
-
l.positionTime =
|
|
1229
|
+
l.positionTime = g.utc(l.etd || l.eta).unix();
|
|
1230
1230
|
});
|
|
1231
1231
|
for (const l of i) {
|
|
1232
1232
|
n += l.distance;
|
|
1233
|
-
const
|
|
1234
|
-
l.in =
|
|
1233
|
+
const b = await W.deadReckoningTime((m = l.waypoints) == null ? void 0 : m.at(0), t.sample.wps), f = await W.deadReckoningTime((M = l.waypoints) == null ? void 0 : M.at(-1), t.sample.wps);
|
|
1234
|
+
l.in = b, l.out = f, l.totalHrs = J.roundPrecision((f.positionTime - b.positionTime) / 3600, 3), l.totalDgoCons = J.roundPrecision(e.fo / 24 * l.totalHrs, 3), o += l.totalHrs, s += l.totalDgoCons;
|
|
1235
1235
|
}
|
|
1236
1236
|
return n = J.roundPrecision(n, 3), o = J.roundPrecision(o, 3), s = J.roundPrecision(s, 3), {
|
|
1237
1237
|
distanceInECA: n,
|
|
@@ -1260,7 +1260,7 @@ class O {
|
|
|
1260
1260
|
}, 0), d = t.reduce((h, u) => {
|
|
1261
1261
|
var I;
|
|
1262
1262
|
return h + (((I = u.extend) == null ? void 0 : I.totalDgoConsInECA) || 0);
|
|
1263
|
-
}, 0), r = t.reduce((h, u) => h + u.wxFactor * u.totalHrs / o, 0), m = t.reduce((h, u) => h + u.cFactor * u.totalHrs / o, 0), M = t.reduce((h, u) => h + u.totalFoCons, 0), l = t.reduce((h, u) => h + u.totalDgoCons, 0),
|
|
1263
|
+
}, 0), r = t.reduce((h, u) => h + u.wxFactor * u.totalHrs / o, 0), m = t.reduce((h, u) => h + u.cFactor * u.totalHrs / o, 0), M = t.reduce((h, u) => h + u.totalFoCons, 0), l = t.reduce((h, u) => h + u.totalDgoCons, 0), b = t.reduce((h, u) => h + u.cost.total, 0), f = t.reduce((h, u) => h + u.cost.hire, 0), C = t.reduce((h, u) => h + u.cost.bunker, 0), S = [], p = [];
|
|
1264
1264
|
let w;
|
|
1265
1265
|
for (const h of t) {
|
|
1266
1266
|
p.push(...((c = h.extend) == null ? void 0 : c.eca) || []);
|
|
@@ -1287,11 +1287,11 @@ class O {
|
|
|
1287
1287
|
P === -1 ? a.wps.push(D) : a.wps[P] = D, w = u.at(-1);
|
|
1288
1288
|
}
|
|
1289
1289
|
return a.wps.sort((h, u) => {
|
|
1290
|
-
|
|
1290
|
+
g(h.etd).unix() - g(u.etd).unix();
|
|
1291
1291
|
}), a.wps.forEach((h, u) => {
|
|
1292
1292
|
const I = a.wps[u - 1];
|
|
1293
1293
|
if (I) {
|
|
1294
|
-
const k = h.distanceFromStart - (I.distanceFromStart || 0), D =
|
|
1294
|
+
const k = h.distanceFromStart - (I.distanceFromStart || 0), D = g(h.eta || h.etd).diff(g(I.etd || I.eta), "hour", !0), Y = Math.round(k / D * 100) / 100;
|
|
1295
1295
|
h.avgSpd = Y;
|
|
1296
1296
|
const j = W.calculateBearing(I, h);
|
|
1297
1297
|
I.bearing = j;
|
|
@@ -1312,7 +1312,7 @@ class O {
|
|
|
1312
1312
|
totalFoCons: Math.round(M * 1e3) / 1e3,
|
|
1313
1313
|
totalDgoCons: Math.round(l * 1e3) / 1e3,
|
|
1314
1314
|
cost: {
|
|
1315
|
-
total: Math.round(
|
|
1315
|
+
total: Math.round(b * 1e3) / 1e3,
|
|
1316
1316
|
hire: Math.round(f * 1e3) / 1e3,
|
|
1317
1317
|
bunker: Math.round(C * 1e3) / 1e3
|
|
1318
1318
|
},
|
|
@@ -1332,12 +1332,12 @@ export {
|
|
|
1332
1332
|
yt as AlertHelper,
|
|
1333
1333
|
mt as AlertLevel,
|
|
1334
1334
|
Et as HifleetImpl,
|
|
1335
|
-
|
|
1335
|
+
gt as LoadCondition,
|
|
1336
1336
|
Nt as MyShipImpl,
|
|
1337
1337
|
xt as MyVesselImpl,
|
|
1338
1338
|
jt as ShipxyImpl,
|
|
1339
1339
|
O as SpeedHelper,
|
|
1340
1340
|
wt as SpeedLabel,
|
|
1341
|
-
|
|
1341
|
+
bt as VesselTag,
|
|
1342
1342
|
Tt as alertHelper
|
|
1343
1343
|
};
|
package/dist/index.umd.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(A,R){typeof exports=="object"&&typeof module<"u"?R(exports,require("got"),require("@log4js-node/log4js-api"),require("moment"),require("@idm-plugin/geo2"),require("@idm-plugin/meteo2"),require("@idm-plugin/meteo")):typeof define=="function"&&define.amd?define(["exports","got","@log4js-node/log4js-api","moment","@idm-plugin/geo2","@idm-plugin/meteo2","@idm-plugin/meteo"],R):(A=typeof globalThis<"u"?globalThis:A||self,R(A["idm-plugin-vessel"]={},A.got,A["@log4js-node/log4js-api"],A.moment,A["@idm-plugin/geo2"],A["@idm-plugin/meteo2"],A["@idm-plugin/meteo"]))})(this,function(A,R,K,p,T,mt,nt){"use strict";var St=Object.defineProperty;var kt=(A,R,K)=>R in A?St(A,R,{enumerable:!0,configurable:!0,writable:!0,value:K}):A[R]=K;var z=(A,R,K)=>(kt(A,typeof R!="symbol"?R+"":R,K),K);let g;try{g=K.getLogger("vessel")}catch{}finally{}class G{parseStatus(t){let e,a;switch(t){case 0:e="在航(主机推动)",a="Underway Using Engine";break;case 1:e="锚泊",a="Anchored";break;case 2:e="失控",a="Not operated";break;case 3:e="操纵受限",a="Limited airworthiness";break;case 4:e="吃水受限",a="Limited by ship's draft";break;case 5:e="靠泊",a="Mooring";break;case 6:e="搁浅",a="Stranded";break;case 7:e="捕捞作业",a="Engaged in fishing";break;case 8:e="靠帆船提供动力",a="Sailing";break;default:e="未定义",a="Undefined"}return{labelCn:e,labelEn:a}}}class yt extends G{constructor(e,a){super();z(this,"clientId");z(this,"clientSecret");z(this,"token");this.clientId=e,this.clientSecret=a}async authToken(e={}){const a="https://svc.data.myvessel.cn/ada/oauth/token",i={searchParams:{client_id:this.clientId,client_secret:this.clientSecret,grant_type:"client_credentials"}},o=await R.post(a,i).json();g==null||g.info("[%s] fetch access token from: %s - %j",e.requestId,a,o),o.error||(this.token={accessToken:o.access_token,tokenType:o.token_type,expiresIn:o.expires_in,scope:o.scope,jti:o.jti,issuedAt:p().utc().format()})}async realTimePosition(e,a={}){var d,r,m;(!this.token||p().diff(p(this.token.issuedAt),"seconds")>((d=this.token)==null?void 0:d.expiresIn)-300)&&await this.authToken(a);const i="https://svc.data.myvessel.cn/sdc/v1/vessels/status/location/unit",o={headers:{Authorization:`${(r=this.token)==null?void 0:r.tokenType} ${(m=this.token)==null?void 0:m.accessToken}`},searchParams:{mmsi:e}};g==null||g.info("[%s] fetch realtime position from: %s - %j",a.requestId,i,o);const n=await R.get(i,o).json();if(n.code)return g==null||g.warn("[%s] fetch realtime position failed: %j",a.requestId,i,{message:n.message,status:n.status,code:n.code}),n;const s=n.data;for(const M in s)!isNaN(s[M])&&Number(s[M])!==1/0&&(s[M]=Number(s[M]));if(s){const M=p(`${s.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return{mmsi:s.mmsi,name:s.vesselName||s.aisVesselName,imo:s.imo,callSign:s.callsign||s.aisCallSign,lat:s.lat,lng:s.lon,length:s.length,width:s.width,draught:s.currDraught,sog:s.sog,cog:s.cog,hdg:s.hdg,rot:s.rot,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(s.eta)?p.utc(s.eta).format():void 0,destination:s.dest,positionTime:M.unix(),status:s.status,labelCn:s.statusNameCn,labelEn:s.statusNameEn,vesselType:s.vesselTypeNameEn,flag:s.flagCtryNameEn,clasz:s.classSociety,build:s.buildYear,dwt:s.dwt,grt:s.grt,net:s.net,method:"position",vendor:"myVessel",utc:M.utc().format()}}else return{}}async trajectory(e,a,i,o,n=!0,s={}){(!this.token||p().diff(p(this.token.issuedAt),"seconds")>this.token.expiresIn-300)&&await this.authToken(s);const d=await this.realTimePosition(e,s),r=p(a),m=p(i),M=[];for(;m.diff(r,"day",!0)>30;)await this.trajectoryIn30Day(e,r,r.clone().add(30,"day"),d,o,M,s),r.add(30,"day");return await this.trajectoryIn30Day(e,r,m,d,o,M,s),M}async trajectoryIn30Day(e,a,i,o,n,s,d={}){var f,C,k,w,v;const r="https://svc.data.myvessel.cn/sdc/v1/vessels/status/track",m={headers:{Authorization:`${(f=this.token)==null?void 0:f.tokenType} ${(C=this.token)==null?void 0:C.accessToken}`},json:{mmsi:e,startTime:a.utcOffset(8).format("YYYY-MM-DD HH:mm:ss"),endTime:i.utcOffset(8).format("YYYY-MM-DD HH:mm:ss")}};g==null||g.info("[%s] fetch trajectory from: %s - %j",d.requestId,r,m);const M=await R.post(r,m).json();if(M.code)return g==null||g.warn("[%s] fetch trajectory failed: %j",d.requestId,r,{message:M.message,status:M.status,code:M.code}),M;let h=-1;const b=p(`${(w=(k=M.data)==null?void 0:k[0])==null?void 0:w.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return(v=M.data)==null||v.forEach(c=>{for(const P in c)!isNaN(c[P])&&Number(c[P])!==1/0&&(c[P]=Number(c[P]));const y=p(`${c.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00"),l=c.status,{labelCn:u,labelEn:I}=this.parseStatus(l),F={mmsi:c.mmsi,imo:o==null?void 0:o.imo,lat:c.lat,lng:c.lon,sog:c.sog,cog:c.cog,hdg:c.hdg,draught:c.draught,status:l,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(c.eta)?p(`${c.eta} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00").utc().format():void 0,destination:c.dest,positionTime:y.unix(),labelCn:u,labelEn:I,method:"trajectory",vendor:"myVessel",utc:y.utc().format()},N=Math.floor(y.diff(b,"minute",!0)/(n||1));N!==h&&(h=N,s.push(F))}),s}}class Mt extends G{constructor(e){super();z(this,"token");this.token=e}async realTimePosition(e,a={}){const i="https://api.hifleet.com/position/position/get/token",o={searchParams:{mmsi:e,usertoken:this.token}},n=await R.post(i,o).json();g==null||g.info("[%s] fetch realtime position from: %s - %j",a.requestId,i,o);const s=n==null?void 0:n.list;if(!s)return g==null||g.warn("[%s] fetch realtime position failed: %j",a.requestId,i,n),n;for(const b in s)!isNaN(s[b])&&Number(s[b])!==1/0&&(s[b]=Number(s[b]));s.status=s.sp>3?0:1;const d=s.status,{labelCn:r,labelEn:m}=this.parseStatus(d),M=p(`${s.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return{mmsi:s.m,name:s.n,imo:s.imonumber,callSign:s.callsign,lat:Math.round(s.la/60*1e5)/1e5,lng:Math.round(s.lo/60*1e5)/1e5,length:s.l,width:s.w,draught:s.draught,sog:s.sp,cog:s.co,hdg:s.h,rot:isNaN(s.rot)?0:s.rot,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(s.eta)?p.utc(s.eta).format():void 0,destination:s.destination,vesselType:s.type,dwt:s.dwt,build:s.buildyear,flag:s.fn,positionTime:M.unix(),utc:M.utc().format(),status:d,labelCn:r,labelEn:m,method:"position",vendor:"hifleet"}}async search(e,a={}){let i="https://www.hifleet.com/hifleetapi/searchVesselOL.do";const o={searchParams:{keyword:e},headers:{Referer:"https://www.hifleet.com",Origin:"https://www.hifleet.com",Host:"www.hifleet.com"}};let n=await R.post(i,o).json();g==null||g.info("[%s] fetch vessel props from: %s - %j",a.requestId,i,o),n instanceof Array&&(n=n[0]);for(const d in n)!isNaN(n[d])&&Number(n[d])!==1/0&&(n[d]=Number(n[d]));const s={mmsi:n.m,name:n.n,imo:n.i,callSign:n.c,length:n.l,breadth:n.b,draught:n.dr,type:n.t};return i="https://www.hifleet.com/hifleetapi/sameShipSearch.do",n=await R.post(i,o).json(),g==null||g.info("[%s] search vessel dead weight from: %s - %j",a.requestId,i,o),n instanceof Array&&(n=n[0]),n&&(s.deadweight=Number(n.dwt)),s}async suggest(e,a={}){const i="https://www.hifleet.com/hifleetapi/getShipSuggest.do",o={searchParams:{q:e},headers:{Referer:"https://www.hifleet.com",Origin:"https://www.hifleet.com",Host:"www.hifleet.com"}},n=await R.post(i,o).json();g==null||g.info("[%s] suggest vessel props from: %s - %j",a.requestId,i,o);const s=[];for(const d of n)s.push({mmsi:!d.mmsi||isNaN(d.mmsi)?null:Number(d.mmsi),name:d.name,callSign:d.callsign,imo:!d.imo||isNaN(d.imo)?null:Number(d.imo),score:d._score});return s.sort((d,r)=>r.score-d.score),s}async trajectory(e,a,i,o,n=!0,s={}){var c,y,l;const d=await this.realTimePosition(e,s);let r=p(a);const m=p(i),M=p();if(n){let u=m.diff(r,"d",!0);u<0?r=m.clone().subtract(40,"d"):u<30?r.subtract(10,"d"):u<60?r.subtract(5,"d"):r=m.clone().subtract(80,"d"),u=M.diff(m,"d",!0),m.add(u>10?240:u*24,"h")}const h={searchParams:{endtime:m.utcOffset("+8:00").format("YYYY-MM-DD HH:mm:ss"),starttime:r.utcOffset("+8:00").format("YYYY-MM-DD HH:mm:ss"),mmsi:e,usertoken:this.token}},b="https://api.hifleet.com/position/trajectory/nocompressed/withstatic/token",f=await R.get(b,h).json();g==null||g.info("[%s] fetch trajectory from: %s - %j",s.requestId,b,h);let C;f&&(C=((y=(c=f.ships)==null?void 0:c.offors)==null?void 0:y.ship)||[],C.length||g==null||g.warn("[%s] fetch trajectory failed: %j",s.requestId,f));const k=[];let w=-1;const v=p(`${(l=C==null?void 0:C[0])==null?void 0:l.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");for(const u of C){for(const L in u)!isNaN(u[L])&&Number(u[L])!==1/0&&(u[L]=Number(u[L]));const I=p(`${u.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");u.status=u.sp>4?0:1;const{labelEn:F,labelCn:N}=this.parseStatus(u.status),P={mmsi:u.m,name:u.n,imo:d==null?void 0:d.imo,lat:u.la,lng:u.lo,draught:u.draught,sog:u.sp,cog:u.co,hdg:u.hdg,positionTime:I.unix(),utc:I.utc().format(),status:u.status,labelCn:N,labelEn:F,method:"trajectory",vendor:"hifleet"},E=Math.floor(I.diff(v,"minute",!0)/(o||1));E!==w&&(w=E,k.push(P))}return k}}class pt extends G{constructor(e){super();z(this,"token");this.token=e}async realTimePosition(e,a={}){const i={searchParams:{id:e,k:this.token,enc:1}},o="https://api.shipxy.com/apicall/GetSingleShip",n=await R.get(o,i).json();if(g==null||g.info("[%s] fetch realtime position from: %s - %j",a.requestId,o,i),(n==null?void 0:n.status)!==0)return n;const s=n.data[0];for(const h in s)!isNaN(s[h])&&Number(s[h])!==1/0&&(s[h]=Number(s[h]));const{labelCn:d,labelEn:r}=await this.parseStatus(s.navistat),m=p.unix(s.lasttime);return{mmsi:s.ShipID,name:s.name,imo:s.imo,callSign:s.callsign,lat:Math.round(s.lat/1e6*1e5)/1e5,lng:Math.round(s.lon/1e6*1e5)/1e5,length:Math.round(s.length/10*100)/100,width:Math.round(s.width/10*100)/100,draught:Math.round(s.draught/1e3*100)/100,sog:Math.round(s.sog*3600/1e3/1852*100)/100,cog:Math.round(s.cog/100*100)/100,hdg:Math.round(s.hdg/100*100)/100,rot:Math.round(s.rot/100*100)/100,positionTime:s.lasttime,utc:m.utc().format(),status:s.navistat,labelEn:r,labelCn:d,method:"position",vendor:"shipxy"}}async trajectory(e,a,i,o,n=!0,s={}){var v;const d=await this.realTimePosition(e,s),r=p(a),m=p(i),M="https://api.shipxy.com/apicall/GetShipTrack",h={searchParams:{id:e,k:this.token,enc:1,cut:0,btm:r.unix(),etm:m.unix()}},b=await R.get(M,h).json();if(g==null||g.info("[%s] fetch trajectory from: %s - %j",s.requestId,M,h),(b==null?void 0:b.status)!==0)return b;const f=b==null?void 0:b.points,C=[],k=p.unix((v=f[0])==null?void 0:v.utc);let w=-1;for(const c of f){const y=p.unix(c.utc),l={imo:d==null?void 0:d.imo,mmsi:e,sog:Math.round(c.sog*3600/1e3/1852*100)/100,cog:Math.round(c.cog/100*100)/100,lat:Math.round(c.lat/1e6*1e5)/1e5,lng:Math.round(c.lon/1e6*1e5)/1e5,positionTime:y.unix(),utc:y.utc().format(),method:"trajectory",vendor:"shipxy"},u=Math.floor(y.diff(k,"minute",!0)/(o||1));u!==w&&(w=u,C.push(l))}return C}}class bt extends G{constructor(e){super();z(this,"token");this.token=e}async getShipId(e,a={}){const i={headers:{appKey:this.token},json:{mmsiList:e}},o="https://api3.myships.com/sp/ships/getShipIdByMMSI",n=await R.post(o,i).json();return g==null||g.info("[%s] fetch ship id from: %s - %j",a.requestId,o,i),n.code!=="0"?n:n.data[0].shipId}async getShipInfo(e,a={}){const i={headers:{appKey:this.token},json:{shipId:e}},o="https://api3.myships.com/sp/ships/aissta",n=await R.post(o,i).json();if(g==null||g.info("[%s] fetch ship info from: %s - %j",a.requestId,o,i),n.code!=="0")return n;const s=n.data;let d=s.imo;return e==="407170"&&(d="9198379",g==null||g.warn("[%s] ship(%s) imo error: %s, should be %s",a.requestId,e,s.imo,d)),{mmsi:s.mmsi,name:s.shipnameEn,imo:d,callSign:s.callSign,length:s.length,width:s.breadth,draught:(s.draught||100)/10}}async realTimePosition(e,a={}){const i=await this.getShipId(e,a),o=await this.getShipInfo(i,a),n={headers:{appKey:this.token},json:{shipId:i}},s="https://api3.myships.com/sp/ships/position/latest",d=await R.post(s,n).json();g==null||g.info("[%s] fetch realtime position from: %s - %j",a.requestId,s,n);const r=d.data[0];for(const f in r)!isNaN(r[f])&&Number(r[f])!==1/0&&(r[f]=Number(r[f]));const{labelCn:m,labelEn:M}=await this.parseStatus(r.aisNavStatus),h=p.unix(r.posTime);return{...o,mmsi:e,lat:Math.round(r.lat/1e4/60*1e5)/1e5,lng:Math.round(r.lon/1e4/60*1e5)/1e5,sog:Math.round(r.sog/10*100)/100,cog:Math.round(r.cog/10*100)/100,hdg:Math.round(r.heading*100)/100,rot:Math.round(r.rot*100)/100,positionTime:r.posTime,utc:h.utc().format(),status:r.aisNavStatus,labelEn:M,labelCn:m,method:"position",vendor:"myship"}}async trajectory(e,a,i,o,n=!0,s={}){const d=p(a),r=p(i),m=await this.getShipId(e),M=await this.getShipInfo(m),h=[];for(;r.diff(d,"day",!0)>30;)await this.trajectoryIn30Day(m,d.unix(),d.add(30,"day").unix(),M,e,o,h);return await this.trajectoryIn30Day(m,d.unix(),r.unix(),M,e,o,h),h}async trajectoryIn30Day(e,a,i,o,n,s,d,r={}){var k;const m={headers:{appKey:this.token},json:{shipId:e,startTime:a,endTime:i}},M="https://api3.myships.com/sp/ships/position/history",h=await R.post(M,m).json();if(g==null||g.info("[%s] fetch trajectory from: %s - %j",r.requestId,M,m),h.code!=="0")return g==null||g.warn("[%s] invoke myship trajectory failed: %j",r.requestId,h),h;const b=h.data;for(const w in b)!isNaN(b[w])&&Number(b[w])!==1/0&&(b[w]=Number(b[w]));const f=p.unix((k=b[0])==null?void 0:k.posTime);let C=-1;for(const w of b){const v=p.unix(w.posTime),c={imo:o==null?void 0:o.imo,mmsi:n,lat:Math.round(w.lat/1e4/60*1e5)/1e5,lng:Math.round(w.lon/1e4/60*1e5)/1e5,sog:Math.round(w.sog/10*100)/100,cog:Math.round(w.cog/10*100)/100,hdg:Math.round(w.heading*100)/100,rot:Math.round(w.rot*100)/100,positionTime:v.unix(),utc:v.utc().format(),method:"trajectory",vendor:"myship"},y=Math.floor(v.diff(f,"minute",!0)/(s||1));y!==C&&(C=y,d.push(c))}return d}}let _;try{_=K.getLogger("vessel")}catch{}finally{}var dt=(D=>(D.NOTICE="NOTICE",D.WARN="WARN",D.HEAVY="HEAVY",D.SEVERE="SEVERE",D.ERROR="ERROR",D.FATAL="FATAL",D))(dt||{});class ut{parsePrinciple(t,e={}){var s,d,r;_==null||_.info("[%s] parse rule: %s",e.requestId,t);const a=new RegExp("(?<=\\[)(.+)(?=])","g"),i=t.match(a)?(s=t.match(a))==null?void 0:s[0]:void 0,o=i==null?void 0:i.split(";");if(!o)return;const n={};for(let m=0;m<(o==null?void 0:o.length);m++){const M=(r=(d=o[m].match(a))==null?void 0:d[0])==null?void 0:r.split("],");if(m===0&&!M)n.scope=o[0];else if(M)for(let h=0,b=M.length;h<b;h++){const f=this.parseRule(M[h]);f&&(n[f.level]?f.key?n[f.level][f==null?void 0:f.key]=f:n[f.level]=f:f.key?n[f.level]={[f==null?void 0:f.key]:f}:n[f.level]=f)}}return n}parseRule(t,e={}){var n;_==null||_.debug("[%s] parse rule: %s",e.requestId,t),t=t.startsWith("[")?t:`[${t}`,t=t.endsWith("]")?t:`${t}]`;const a=new RegExp("(?<=\\[)(.+?)(?=])","g"),i=(n=t==null?void 0:t.match(a))==null?void 0:n[0],o=i==null?void 0:i.split(",");if(o)return{operator:o[0],number:Number.isNaN(Number(o[1]))?o[1]:Number(o[1]),level:o[2],time:Number(o[3]),key:o[4]}}checkWeather(t,e,a={}){var f,C,k,w,v,c,y,l,u,I,F,N,P,E,L;let i=0,o=0,n=0,s=0;const d=Math.round(((C=(f=e==null?void 0:e.SEVERE)==null?void 0:f.sigWave)==null?void 0:C.number)*1.6*100)/100,r=(w=(k=e==null?void 0:e.SEVERE)==null?void 0:k.sigWave)==null?void 0:w.number,m=(c=(v=e==null?void 0:e.HEAVY)==null?void 0:v.sigWave)==null?void 0:c.number,M=Math.round((((l=(y=e==null?void 0:e.SEVERE)==null?void 0:y.wind)==null?void 0:l.number)+2)*100)/100,h=(I=(u=e==null?void 0:e.SEVERE)==null?void 0:u.wind)==null?void 0:I.number,b=(N=(F=e==null?void 0:e.HEAVY)==null?void 0:F.wind)==null?void 0:N.number;for(let x=0;x<(t==null?void 0:t.length);x++){const H=t[x],q=(E=(P=H==null?void 0:H.meteo)==null?void 0:P.wave)==null?void 0:E.sig,V=(L=H==null?void 0:H.meteo)==null?void 0:L.wind,U=x?p(H.eta).diff(p(t[x-1].eta),"hour",!0):0;s=U>s?U:s,_==null||_.debug("[%s] check sig.wave: %j",a.requestId,{...q,dgThd4Wv:d,svThd4Wv:r,hvThd4Wv:m}),(q==null?void 0:q.height)>=d?H.isDangerous=!0:(q==null?void 0:q.height)>=r?H.isSevere=!0:(q==null?void 0:q.height)>=m&&(H.isHeavy=!0),_==null||_.debug("[%s] check wind: %j",a.requestId,{...V,dgThd4Wd:M,svThd4Wd:h,hvThd4Wd:b}),(V==null?void 0:V.scale)>=M?(H.isDangerous=!0,delete H.isSevere,delete H.isHeavy):(V==null?void 0:V.scale)>h?(H.isDangerous||(H.isSevere=!0),delete H.isHeavy):(V==null?void 0:V.scale)===b&&!H.isDangerous&&!H.isSevere&&(H.isHeavy=!0),i+=H.isDangerous?U:0,o+=H.isSevere?U:0,n+=H.isHeavy?U:0}return i=Math.round(i*100)/100,o=Math.round(o*100)/100,n=Math.round(n*100)/100,s=Math.round(s),{sample:t,dangerous:i,severe:o,heavy:n,step:s<3?3:s,wind:{dgThd4Wd:M,svThd4Wd:h,hvThd4Wd:b},sig:{dgThd4Wv:d,svThd4Wv:r,hvThd4Wv:m}}}}const gt=new ut;let S;try{S=K.getLogger("vessel")}catch{}finally{}const vt=new mt.MeteoHelper2("",!0);var lt=(D=>(D.common="common",D.container="container",D.tugs="tugs",D))(lt||{}),ht=(D=>(D.Ballast="Ballast",D.Laden="Laden",D))(ht||{}),ft=(D=>(D.Cp="CP",D.Perf="Basis",D.Instruct="Other",D))(ft||{});class W{static blockCoefficient(t,e,a,i){let o=Math.round(t/(e*a*i)*100)/100;o=o<.55?.55:o>.85?.85:o;const n=[.55,.6,.65,.7,.75,.8,.85],s=n.map(d=>Math.abs(d-o));return n[s.indexOf(Math.min(...s))]}static froudeNumber(t,e,a=9.8){let i=Math.round(Math.sqrt(t*t/(a*e))*100)/100;return i=i<.05?.05:i>.3?.3:i,i}static amendFactor(t,e,a){const i={.55:[1.7,-1.4,-7.4],.6:[2.2,-2.5,-9.7],.65:[2.6,-3.7,-11.6],.7:[3.1,-5.3,-12.4],.75:[2.4,-10.6,-9.5],.8:[2.6,-13.1,-15.1],.85:[3.1,-18.7,28]};let n={.55:[1.7,-1.4,-7.4],.6:[2.2,-2.5,-9.7],.65:[2.6,-3.7,-11.6],.7:[3.1,-5.3,-12.4],.75:[2.6,-12.5,-13.5],.8:[3,-16.3,-21.6],.85:[3.4,-20.9,31.8]}[t];return a==="Laden"&&(n=i[t]),n[0]+n[1]*e+n[2]*Math.pow(e,2)}static directionFactor(t,e=0){let a;return t>30&&t<=60?a=(1.7-.03*Math.pow(e-4,2))/2:t>60&&t<=150?a=(.9-.06*Math.pow(e-6,2))/2:t>150&&t<=180?a=(.4-.03*Math.pow(e-8,2))/2:a=1,Math.round(a*1e5)/1e5}static vesselTagFactor(t,e,a,i=0){i=i>6?i-.9*(i-6):i;let o;return a==="container"?o=.7*i+Math.pow(i,6.5)/(22*Math.pow(t,2/3)):e==="Ballast"?o=.7*i+Math.pow(i,6.5)/(2.7*Math.pow(t,2/3)):o=.5*i+Math.pow(i,6.5)/(2.7*Math.pow(t,2/3)),o}static waveHeightFactor(t,e){t=t<3?t*.7:t,t=t<0?.2:t,t=t>6?t-.9*(t-6):t,t=t>9?9:t;let a;return e>30&&e<=60?a=-.6:e>60&&e<=90?a=-.4:e>90&&e<=120?a=t<3?.4:-.3:e>120&&e<=150?a=t<3?.6:-.5:e>150&&e<=180?a=t<3?.7:-.6:a=-.7,Math.round(a*(.102*Math.pow(t,2)+.178*t)*1e4)/1e4}static assembleProperties(t,e,a,i){var h;const o=t.lbp??t.length??t.lengthOverall??198.9642,n=t.draught??8,s=t.breadthMoulded??t.breadth??t.breadthExtreme??32.4572,d=t.deadweight??67035.7773,r=((h=t==null?void 0:t.type)==null?void 0:h.toLowerCase())||"common";return{tag:r.indexOf("container")>-1?"container":r.indexOf("tugs")>-1?"tugs":"common",lbp:o,loadCondition:e,draught:n,breadthMoulded:s,displacement:Math.round((d/1.025+n*s*o*.7)*1e4)/1e4,speed:Math.round((a??14.1382)*1852/3600*1e4)/1e4,bearing:i||90}}static async speedLoseAt(t,e,a,i="",o=2,n=!0,s=!1,d={}){let r;if(e.velocity&&s&&(t.speed=T.LngLatHelper.roundPrecision(e.velocity*1852/3600,6)),n){let m;try{i=(i==null?void 0:i.toUpperCase())==="CMEMS"?"ECMWF":i,i=(i==null?void 0:i.toUpperCase())==="METEO2"?"best_match":i;const{weatherModels:f,marineModels:C}=await nt.Meteo2Assist.autoPickMeteoModel(i),k=await vt.spotForecast(e.lat,e.lng,a.utc().format(),!1,!1,!0,{...d,pastDays:1,forecastDays:1,weatherModels:f,marineModels:C}),[w]=nt.Meteo2Assist.pickHourly(k,a);m=nt.Meteo2Assist.toLegacy(w)}catch(f){S.warn("[%s] meteo2 spot(%j) forecast failed: %s",d.requestId,{...e,eta:a.utc().format(),source:i},f)}const M=W.weatherFactor(t,m),h=W.currentFactor(t.bearing,m==null?void 0:m.current,o),b=Math.round((t.speed*1.943844+M+h)*100)/100;r={meteo:{...m},wxFactor:M,cFactor:h,speed:e.velocity&&s?e.velocity:b<0?1:b,eta:a.utc().format(),etd:a.utc().format()}}else r={wxFactor:0,cFactor:0,speed:e.velocity&&s?e.velocity:Math.round((t.speed*1.943844+0+0)*100)/100,eta:a.utc().format(),etd:a.utc().format()};return delete e.meteo,delete e.wxFactor,delete e.cFactor,delete e.speed,delete e.etd,{...r,...e}}static async speedLoseInHoursStep(t,e,a,i,o,n,s="",d=!0,r=!1,m={}){e.utc();const M=e.clone().add(14,"days"),h=[],b=[];let f=0,C=0,k,w;for(let v=0;v<n.length-1;v++){let c=n[v];c.distanceFromStart=Math.round((o+C)*1e3)/1e3;const y=n[v+1];if(t.bearing=T.LaneHelper.calculateBearing(c,y,!y.gcToPrevious),c.bearing=t.bearing,c.suspend&&r){c.eta=c.eta||e.utc().format(),c.elapsed=c.elapsed??0;const I=c.suspend-c.elapsed;if(i-f>I)i=i-f-I,e.add(I,"hour"),c.elapsed=c.suspend;else{const F=i-f;c.elapsed+=F,e.add(F,"hour"),i=0}if(S==null||S.info(`[%s] suspend ${c.elapsed} hours at %j, and remain ${i} hours need to go...`,m.requestId,c),i===0)return c.distanceFromPrevious=C,{etd:e,from:w||c,to:c,next:n.filter(F=>F),wps:h,days:b}}else c.suspend=0;d=e.isAfter(M)?!1:d,c=await W.speedLoseAt(t,c,e,s,0,d,r,m),w=w||c,c.important&&h.push(c),e.isSameOrAfter(a)&&(b.push(c),a.add(24,"hour"));const l=T.LaneHelper.calculateDistance(c,y,!y.gcToPrevious);let u=Math.round(l/w.speed*1e5)/1e5;if(f+u<i){if(f+=u,e.add(u,"hour"),delete n[v],S==null||S.debug(`[%s] go to %j from %j with ${l}nm, and cost ${u} hours`,m.requestId,{lat:y.lat,lng:y.lng},{lat:w.lat,lng:w.lng,etd:w.etd}),C+=l,n.filter(I=>I).length<=1){k=y,k.eta=e.utc().format(),k.distanceFromPrevious=l,k.distanceFromStart=Math.round((o+C)*1e4)/1e4,h.push(k),delete n[v+1];break}}else{u=i-f,e.add(u,"hour");const I=T.LngLatHelper.roundPrecision(w.speed*u,5);k=T.LaneHelper.calculateCoordinate(c,t.bearing,I,"nauticalmiles",!y.gcToPrevious),k.eta=e.utc().format(),n[v]=k,S==null||S.debug(`[%s] go to %j from %j with ${I}nm, and cost ${u} hours`,m.requestId,{lat:k.lat,lng:k.lng},{lat:c.lat,lng:c.lng,etd:c.etd}),C+=I,k.distanceFromPrevious=Math.round(C*1e4)/1e4,k.distanceFromStart=Math.round((o+C)*1e4)/1e4;break}}return{etd:e,from:w,to:k,next:n.filter(v=>v),wps:h,days:b}}static currentFactor(t,e,a=0){const i=(t-(e==null?void 0:e.degree)||0)/180*Math.PI;if(Math.abs(i)===Math.PI/2)return 0;let o=((e==null?void 0:e.kts)||0)*Math.cos(i);return a&2?o=Math.ceil(o*100)/100:a&1?o=Math.floor(o*100)/100:o=Math.round(o*100)/100,Math.abs(o)>5?0:o}static weatherFactor(t,e){var M,h,b,f,C,k,w;S==null||S.debug("calculate weather factor via: %j",{...t,...e});const a=W.blockCoefficient(t.displacement,t.lbp,t.breadthMoulded,t.draught),i=W.froudeNumber(t.speed,t.lbp),o=W.amendFactor(a,i,t.loadCondition);let n=Math.abs(t.bearing%360-(((M=e==null?void 0:e.wind)==null?void 0:M.degree)%360||0));n=n>180?360-n:n;const s=W.directionFactor(n,(h=e==null?void 0:e.wind)==null?void 0:h.scale),d=W.vesselTagFactor(t.displacement,t.loadCondition,t.tag,(b=e==null?void 0:e.wind)==null?void 0:b.scale);let r=s*o*d/100*t.speed;r=Math.round(r*1.943844*1e4)/1e4*-1,t.tag==="tugs"&&Math.abs(r)>1&&(r=r/(Math.abs(Math.round(r))+1)),S==null||S.debug("wind wx factor = %d",r),n=Math.abs(t.bearing%360-(((C=(f=e==null?void 0:e.wave)==null?void 0:f.sig)==null?void 0:C.degree)%360||0));const m=W.waveHeightFactor(((w=(k=e==null?void 0:e.wave)==null?void 0:k.sig)==null?void 0:w.height)??1,n);return S==null||S.debug("wave wx factor = %d",m),r=r*.3+m*.7,S==null||S.debug("weather factor = %d",r),r=Math.abs(r)>2?2*(Math.abs(r)/r)+Math.abs(r)/r*(Math.abs(r)-2)*.1:r,Math.round((r||0)*100)/100}static async analyseInstant(t,e,a,i,o,n="",s=0,d=!0,r=!1,m={}){var Q,X,Z,$,tt,et;const M=p().valueOf();t.lng=T.LngLatHelper.convertToStdLng(t.lng);const{route:h,waypoints:b}=o.points,f=T.LaneHelper.calculateSubRoute(t,h);if(((Q=f[0])==null?void 0:Q.length)<=1)return;const{v0:C,label:k}=t.sog?{v0:t.sog,label:t.label||"Other"}:{v0:i.speed,label:"CP"},w=W.assembleProperties(a,i.loadCondition,C,0),v=b.length?T.LaneHelper.calculateSubWaypoints(t,b):[];v.forEach(Y=>Y.important=!0);const c={from:{...t},route:f,waypoints:v,v0:C,label:k},y={hours:[],days:[],wps:[]};s||(T.LaneHelper.calculateRouteDistance(f)/i.speed<=72?s=3:s=6);let l=T.LaneHelper.simplifyRouteToCoordinates(f,v,0),u=0,I=0,F=0,N=0;e=p(e).utc();const P=e.clone();for(;l.length>0;){const Y=s-e.hour()%s,J=Math.ceil(e.clone().add(Y,"h").set({minute:0,second:0,millisecond:0}).diff(e,"h",!0)*1e4)/1e4,j=await W.speedLoseInHoursStep(w,e,P,J,u,l,n,d,r,m);(X=j.from)!=null&&X.speed&&(y.hours.push(j.from),y.wps.push(...j.wps),y.days.push(...j.days)),l=j==null?void 0:j.next,l.length||y.hours.push(j==null?void 0:j.to),u+=Math.round((((Z=j==null?void 0:j.to)==null?void 0:Z.distanceFromPrevious)??0)*1e4)/1e4}const E=y.hours;for(let Y=0;Y<E.length-1;Y++){const J=p(E[Y+1].eta).diff(E[Y].etd,"hour",!0)||1;I+=(E[Y].wxFactor||0)*J,F+=(E[Y].cFactor||0)*J,N+=J}($=y.wps)==null||$.forEach((Y,J)=>{Y.positionTime=p.utc(Y.etd||Y.eta).unix();const j=y.wps[J-1];if(j){const B=Y.distanceFromStart-j.distanceFromStart,O=p(Y.eta||Y.etd).diff(p(j.etd||j.eta),"h",!0);Y.avgSpd=Math.round(B/O*100)/100;const ct=T.LaneHelper.calculateBearing(j,Y);j.bearing=ct}}),y.wps=(tt=y.wps)==null?void 0:tt.reduce((Y,J)=>(Y.some(j=>Math.round(j.positionTime/60)===Math.round(J.positionTime/60))||Y.push(J),Y),[]),c.sample=y;const L=y.hours.at(0),x=y.hours.at(-1);c.distance=Math.round(x.distanceFromStart*1e3)/1e3,c.etd=p(L.eta).utc().format(),c.eta=p(x.eta).utc().format(),c.wxFactor=Math.round(I/N*1e3)/1e3,c.cFactor=Math.round(F/N*1e3)/1e3,c.avgSpeed=Math.round(x.distanceFromStart/N*1e3)/1e3,c.totalHrs=Math.round(N*1e3)/1e3;const{distanceInECA:H,hoursInECA:q,totalDgoConsInECA:V,eca:U}=await this.calculateECA(c,i,m),st=T.LngLatHelper.roundPrecision(i.fo/24*(N-q),3),ot=T.LngLatHelper.roundPrecision(i.dgo/24*N,3);c.extend={eca:U,distanceInECA:H,hoursInECA:q,totalDgoConsInECA:V},c.totalFoCons=st<0?0:st,c.totalDgoCons=ot;const at=p().valueOf()-M,rt=((et=y==null?void 0:y.hours)==null?void 0:et.length)||1;return S==null||S.info("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms",m==null?void 0:m.requestId,at,rt,Math.round(at/rt*1e3)/1e3),c}static async analyseInstantWithThreshed(t,e,a,i,o,n,s,d="",r=3,m=!0,M=!1,h={}){var Z,$,tt,et,Y,J;const b=p().valueOf();t.lng=T.LngLatHelper.convertToStdLng(t.lng);const{v0:f,label:C}=t.sog?{v0:t.sog,label:t.label||"Other"}:{v0:o.speed,label:"CP"},k=W.assembleProperties(i,o.loadCondition,f,0),w=T.LaneHelper.calculateSubRoute(t,n);if(((Z=w[0])==null?void 0:Z.length)<=1)return;const v=s.length?T.LaneHelper.calculateSubWaypoints(t,s):[];v.forEach(j=>j.important=!0);let c=T.LaneHelper.simplifyRouteToCoordinates(w,v,0),y=0,l=0,u=0,I=0;const F={hours:[],wps:[],days:[]};e=p(e).utc();const N=e.clone();for(;c.length>0;){const j=r-e.hour()%r;let B=Math.ceil(e.clone().add(j,"h").set({minute:0,second:0,millisecond:0}).diff(e,"h",!0)*1e4)/1e4;B=e.clone().add(B,"h").isSameOrAfter(a)?a.diff(e,"h",!0)*1e4/1e4:B;const O=await W.speedLoseInHoursStep(k,e,N,B,y,c,d,m,M,h);if(($=O.from)!=null&&$.speed&&(F.hours.push(O.from),O!=null&&O.wps&&F.wps.push(...O.wps),F.days.push(...O.days)),c=O==null?void 0:O.next,c.length||F.hours.push(O==null?void 0:O.to),y+=Math.round((((tt=O==null?void 0:O.to)==null?void 0:tt.distanceFromPrevious)??0)*1e4)/1e4,!B)break}F.wps=(et=F.wps)==null?void 0:et.reduce((j,B)=>(j.some(O=>Math.round(p(O.etd).unix()/60)===Math.round(p(B.etd).unix()/60))||j.push(B),j),[]),(Y=F.wps)==null||Y.forEach((j,B)=>{const O=F.wps[B-1];if(O){const ct=j.distanceFromStart-O.distanceFromStart,wt=p(j.eta||j.etd).diff(p(O.etd||O.eta),"h",!0);j.avgSpd=Math.round(ct/wt*100)/100;const It=T.LaneHelper.calculateBearing(O,j);O.bearing=It}});const P=F.hours;for(let j=0;j<P.length-1;j++){const B=p(P[j+1].eta).diff(P[j].etd,"hour",!0);l+=P[j].wxFactor*B,u+=P[j].cFactor*B,I+=B}const E=F.hours.at(0),L=F.hours.at(-1),x=await T.LaneHelper.calculateRangeRoute(E,L,w),H=await T.LaneHelper.calculateRangeWaypoints(E,L,w,v),q={sample:F,distance:Math.round(((L==null?void 0:L.distanceFromStart)||0)*1e4)/1e4,etd:p(E.eta).utc().format(),eta:p(L==null?void 0:L.eta).utc().format(),wxFactor:Math.round(l/I*1e3)/1e3,cFactor:Math.round(u/I*1e3)/1e3,avgSpeed:Math.round(((L==null?void 0:L.distanceFromStart)||0)/I*1e3)/1e3,totalHrs:Math.round(I*1e3)/1e3,from:E,to:L,route:x,waypoints:H,v0:f,label:C},{distanceInECA:V,hoursInECA:U,totalDgoConsInECA:st,eca:ot}=await this.calculateECA(q,o,h),it=T.LngLatHelper.roundPrecision(o.fo/24*(I-U),3),at=T.LngLatHelper.roundPrecision(o.dgo/24*I,3);q.extend={eca:ot,distanceInECA:V,hoursInECA:U,totalDgoConsInECA:st},q.totalDgoCons=at,q.totalFoCons=it<0?0:it;const Q=p().valueOf()-b,X=((J=F==null?void 0:F.hours)==null?void 0:J.length)||1;return S==null||S.debug("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms",h==null?void 0:h.requestId,Q,X,Math.round(Q/X*1e3)/1e3),q}static async analyseCost(t,e,a,i,o={}){var w,v;const n=p().valueOf(),s=[];t.speedStep=t.speedStep||3,t.alterStep=t.alterStep??1;const d=T.LaneHelper.calculateRouteDistance(i.route);let r=0;a.forEach(c=>{const y=Math.ceil(d/c.speed/24);r=r<y?y:r}),r=r*1.3;const m=p.utc(t.etd).add(r??14,"day");let M=1;for(const c of a){const y=JSON.parse(JSON.stringify(i.route)),l=JSON.parse(JSON.stringify(i.waypoints)),u=await W.analyseInstantWithThreshed({lat:t.lat,lng:t.lng},t.etd,m,e,c,y,l,t.meteoVendor,t.speedStep,t.useMeteo,t.useRouteParam,o);u&&(await W.calculateCost(u,c,t,o),s.push(u),S==null||S.info("[%s][L%d-%d] analyse from %s to %s cost: %j",o.requestId,1,M,t.etd,m.format(),{cost:u.cost.total,hire:u.cost.hire,bunker:u.cost.bunker,distance:u.distance,hours:u.totalHrs,cp:`${c.speed}/${c.fo}/${c.dgo}`})),M++}s.sort((c,y)=>c.cost.total-y.cost.total);const h=s.at(0),b=s.at(1),f=[];if(f.push({combined:!1,speeds:[h],cost:(w=h.cost)==null?void 0:w.total}),b){const c=h.cost.cp,y=b.cost.cp,l=p(h.eta),u=p(h.etd),I=l.diff(u,"days",!0);let F=Math.ceil(I/2);F=F>7?7:F<t.alterStep?t.alterStep:F;let N=2,P={combined:!1,speeds:[b],cost:(v=b.cost)==null?void 0:v.total},E;for(;F>=t.alterStep;){const L=await W.combinedAnalyse(t,e,m,[c,y],i,F,{...o,level:N});if(P.cost>L.cost?E?(E==null?void 0:E.cost)>L.cost&&(E=L):(E=P,P=L):(!E||(E==null?void 0:E.cost)>L.cost)&&(E=L),F<=t.alterStep)break;F=Math.ceil(F/2),N+=1}f.push(P),E&&f.push(E)}const k=p().valueOf()-n;return S==null||S.info("[%s] analyse elapsed: %d ms",o==null?void 0:o.requestId,k),f.sort((c,y)=>c.cost-y.cost)}static async combinedAnalyse(t,e,a,i,o,n,s={}){s.counter=1,S==null||S.info("[%s][L%d] analyse with alternate cp in every %d days",s.requestId,s.level,n);const d=await W.alternateAnalyse(t,e,a,i,0,o,n,s),r=d.reduce((y,l)=>y+l.cost.total,0),m=d.reduce((y,l)=>y+l.cost.hire,0),M=d.reduce((y,l)=>y+l.cost.bunker,0),h=d.reduce((y,l)=>y+l.distance,0),b=d.reduce((y,l)=>y+l.totalHrs,0);S==null||S.info("[%s][L%d] cost with cpa/cpb turn: %j",s.requestId,s.level,{cost:r,hire:m,bunker:M,distance:h,hours:b});const f=await W.alternateAnalyse(t,e,a,i,1,o,n,s),C=f.reduce((y,l)=>y+l.cost.total,0),k=f.reduce((y,l)=>y+l.cost.hire,0),w=f.reduce((y,l)=>y+l.cost.bunker,0),v=f.reduce((y,l)=>y+l.distance,0),c=f.reduce((y,l)=>y+l.totalHrs,0);return S==null||S.info("[%s][L%d] cost with cpb/cpa turn: %j",s.requestId,s.level,{cost:C,hire:k,bunker:w,distance:v,hours:c}),r<C?{combined:!0,cost:Math.round(r*1e3)/1e3,speeds:d,step:n}:{combined:!0,cost:Math.round(C*1e3)/1e3,speeds:f,step:n}}static async alternateAnalyse(t,e,a,i,o,n,s,d={}){var h,b;let r=p.utc(t.etd);const m={lat:t.lat,lng:t.lng},M=[];for(;r.isBefore(a);){const f=r.clone().utc().add(s,"day"),C=JSON.parse(JSON.stringify(n.route)),k=JSON.parse(JSON.stringify(n.waypoints)),w=i[o],v=await W.analyseInstantWithThreshed(m,r.utc().format(),f,e,w,C,k,t.meteoVendor,t.speedStep,t.useMeteo,t.useRouteParam,d);v&&(await W.calculateCost(v,w,t,d),S==null||S.info("[%s][L%d-%d] analyse from %s to %s cost: %j",d.requestId,d.level,d.counter,r.utc().format(),f.utc().format(),{cost:v.cost.total,hire:v.cost.hire,bunker:v.cost.bunker,distance:v.distance,hours:v.totalHrs,cp:`${w.speed}/${w.fo}/${w.dgo}`})),d.counter=d.counter+1;const c=(b=(h=v==null?void 0:v.sample)==null?void 0:h.hours)==null?void 0:b.at(-1);if(c)m.lat=c.lat,m.lng=c.lng,r=p(c.eta),M.push(v),o=o?0:1;else break}return M}static async calculateCost(t,e,a,i={}){var o;if(t){const n=(a.addComm||0)>=1?(a.addComm||0)/100:a.addComm||0,s=Math.round(t.totalHrs/24*(a.dailyHire||0)*(1-n)*1e3)/1e3,d=Math.round(t.totalFoCons*(a.priceFO||0)*1e3)/1e3,r=Math.round((t.totalDgoCons+(((o=t.extend)==null?void 0:o.totalDgoConsInECA)||0))*(a.priceDGO||0)*1e3)/1e3;t.cost={total:Math.round((s+d+r)*1e3)/1e3,hire:s,bunker:Math.round((d+r)*1e3)/1e3,cp:e}}return t}static async calculateECA(t,e,a={}){var d,r,m,M;const i=await T.LaneHelper.intersectInECA((t==null?void 0:t.route)||[]);let o=0,n=0,s=0;(r=(d=t==null?void 0:t.sample)==null?void 0:d.wps)==null||r.forEach(h=>{h.positionTime=p.utc(h.etd||h.eta).unix()});for(const h of i){o+=h.distance;const b=await T.LaneHelper.deadReckoningTime((m=h.waypoints)==null?void 0:m.at(0),t.sample.wps),f=await T.LaneHelper.deadReckoningTime((M=h.waypoints)==null?void 0:M.at(-1),t.sample.wps);h.in=b,h.out=f,h.totalHrs=T.LngLatHelper.roundPrecision((f.positionTime-b.positionTime)/3600,3),h.totalDgoCons=T.LngLatHelper.roundPrecision(e.fo/24*h.totalHrs,3),n+=h.totalHrs,s+=h.totalDgoCons}return o=T.LngLatHelper.roundPrecision(o,3),n=T.LngLatHelper.roundPrecision(n,3),s=T.LngLatHelper.roundPrecision(s,3),{distanceInECA:o,hoursInECA:n,totalDgoConsInECA:s,eca:i}}static async mergeSpeeds(t,e={}){var c,y;const a={hours:[],wps:[],days:[]},i=t.reduce((l,u)=>l+u.distance,0),o=t.reduce((l,u)=>{var I;return l+(((I=u.extend)==null?void 0:I.distanceInECA)||0)},0),n=t.reduce((l,u)=>l+u.totalHrs,0),s=t.reduce((l,u)=>{var I;return l+(((I=u.extend)==null?void 0:I.hoursInECA)||0)},0),d=t.reduce((l,u)=>{var I;return l+(((I=u.extend)==null?void 0:I.totalDgoConsInECA)||0)},0),r=t.reduce((l,u)=>l+u.wxFactor*u.totalHrs/n,0),m=t.reduce((l,u)=>l+u.cFactor*u.totalHrs/n,0),M=t.reduce((l,u)=>l+u.totalFoCons,0),h=t.reduce((l,u)=>l+u.totalDgoCons,0),b=t.reduce((l,u)=>l+u.cost.total,0),f=t.reduce((l,u)=>l+u.cost.hire,0),C=t.reduce((l,u)=>l+u.cost.bunker,0),k=[],w=[];let v;for(const l of t){w.push(...((c=l.extend)==null?void 0:c.eca)||[]);const u=l.sample.hours,I=l.sample.wps,F=l.sample.days,N=u.at(0);v&&(N.distanceFromPrevious=v.distanceFromPrevious,N.distanceFromStart=v.distanceFromStart,u.forEach((x,H)=>{H&&(x.distanceFromStart=x.distanceFromStart+v.distanceFromStart)}),I.at(0).distanceFromPrevious=v.distanceFromPrevious,I.at(0).distanceFromStart=v.distanceFromStart,I.forEach((x,H)=>{H&&(x.distanceFromStart=x.distanceFromStart+v.distanceFromStart)}),F.at(0).distanceFromPrevious=v.distanceFromPrevious,F.at(0).distanceFromStart=v.distanceFromStart,F.forEach((x,H)=>{H&&(x.distanceFromStart=x.distanceFromStart+v.distanceFromStart)})),N.cp=l.cost.cp;const P=[l.etd,l.eta],E=k.findIndex(x=>x.id===N.cp.id);E===-1?(N.cp.segment=[P],k.push(N.cp)):k[E].segment.push(P),u.forEach(x=>{var q;((q=a.hours)==null?void 0:q.findIndex(V=>V.eta===x.eta))===-1&&a.hours.push(x)}),I.forEach(x=>{var q;((q=a.wps)==null?void 0:q.findIndex(V=>V.eta===x.eta))===-1&&a.wps.push(x)}),F.forEach(x=>{var q;((q=a==null?void 0:a.days)==null?void 0:q.findIndex(V=>V.eta===x.eta))===-1&&a.days.push(x)});const L=(y=a.wps)==null?void 0:y.findIndex(x=>x.eta===N.eta);L===-1?a.wps.push(N):a.wps[L]=N,v=u.at(-1)}return a.wps.sort((l,u)=>{p(l.etd).unix()-p(u.etd).unix()}),a.wps.forEach((l,u)=>{const I=a.wps[u-1];if(I){const F=l.distanceFromStart-(I.distanceFromStart||0),N=p(l.eta||l.etd).diff(p(I.etd||I.eta),"hour",!0),P=Math.round(F/N*100)/100;l.avgSpd=P;const E=T.LaneHelper.calculateBearing(I,l);I.bearing=E}}),{sample:a,etd:t.at(0).etd,eta:t.at(-1).eta,from:t.at(0).from,to:t.at(-1).to,v0:t.at(0).v0,label:"Combined",distance:Math.round(i*1e3)/1e3,totalHrs:Math.round(n*1e3)/1e3,avgSpeed:Math.round(i/n*1e3)/1e3,wxFactor:Math.round(r*1e3)/1e3,cFactor:Math.round(m*1e3)/1e3,totalFoCons:Math.round(M*1e3)/1e3,totalDgoCons:Math.round(h*1e3)/1e3,cost:{total:Math.round(b*1e3)/1e3,hire:Math.round(f*1e3)/1e3,bunker:Math.round(C*1e3)/1e3},extend:{cps:k,eca:w,distanceInECA:Math.round(o*1e3)/1e3,hoursInECA:Math.round(s*1e3)/1e3,totalDgoConsInECA:Math.round(d*1e3)/1e3,speeds:t}}}}A.AISImpl=G,A.AlertHelper=ut,A.AlertLevel=dt,A.HifleetImpl=Mt,A.LoadCondition=ht,A.MyShipImpl=bt,A.MyVesselImpl=yt,A.ShipxyImpl=pt,A.SpeedHelper=W,A.SpeedLabel=ft,A.VesselTag=lt,A.alertHelper=gt,Object.defineProperty(A,Symbol.toStringTag,{value:"Module"})});
|
|
1
|
+
(function(A,R){typeof exports=="object"&&typeof module<"u"?R(exports,require("got"),require("@log4js-node/log4js-api"),require("moment"),require("@idm-plugin/geo2"),require("@idm-plugin/meteo2"),require("@idm-plugin/meteo")):typeof define=="function"&&define.amd?define(["exports","got","@log4js-node/log4js-api","moment","@idm-plugin/geo2","@idm-plugin/meteo2","@idm-plugin/meteo"],R):(A=typeof globalThis<"u"?globalThis:A||self,R(A["idm-plugin-vessel"]={},A.got,A["@log4js-node/log4js-api"],A.moment,A["@idm-plugin/geo2"],A["@idm-plugin/meteo2"],A["@idm-plugin/meteo"]))})(this,function(A,R,K,p,T,mt,nt){"use strict";var St=Object.defineProperty;var kt=(A,R,K)=>R in A?St(A,R,{enumerable:!0,configurable:!0,writable:!0,value:K}):A[R]=K;var z=(A,R,K)=>(kt(A,typeof R!="symbol"?R+"":R,K),K);let g;try{g=K.getLogger("vessel")}catch{}finally{}class G{parseStatus(t){let e,a;switch(t){case 0:e="在航(主机推动)",a="Underway Using Engine";break;case 1:e="锚泊",a="Anchored";break;case 2:e="失控",a="Not operated";break;case 3:e="操纵受限",a="Limited airworthiness";break;case 4:e="吃水受限",a="Limited by ship's draft";break;case 5:e="靠泊",a="Mooring";break;case 6:e="搁浅",a="Stranded";break;case 7:e="捕捞作业",a="Engaged in fishing";break;case 8:e="靠帆船提供动力",a="Sailing";break;default:e="未定义",a="Undefined"}return{labelCn:e,labelEn:a}}}class yt extends G{constructor(e,a){super();z(this,"clientId");z(this,"clientSecret");z(this,"token");this.clientId=e,this.clientSecret=a}async authToken(e={}){const a="https://svc.data.myvessel.cn/ada/oauth/token",i={searchParams:{client_id:this.clientId,client_secret:this.clientSecret,grant_type:"client_credentials"}},o=await R.post(a,i).json();g==null||g.info("[%s] fetch access token from: %s - %j",e.requestId,a,o),o.error||(this.token={accessToken:o.access_token,tokenType:o.token_type,expiresIn:o.expires_in,scope:o.scope,jti:o.jti,issuedAt:p().utc().format()})}async realTimePosition(e,a={}){var d,r,m;(!this.token||p().diff(p(this.token.issuedAt),"seconds")>((d=this.token)==null?void 0:d.expiresIn)-300)&&await this.authToken(a);const i="https://svc.data.myvessel.cn/sdc/v1/vessels/status/location/unit",o={headers:{Authorization:`${(r=this.token)==null?void 0:r.tokenType} ${(m=this.token)==null?void 0:m.accessToken}`},searchParams:{mmsi:e}};g==null||g.info("[%s] fetch realtime position from: %s - %j",a.requestId,i,o);const n=await R.get(i,o).json();if(n.code)return g==null||g.warn("[%s] fetch realtime position failed: %j",a.requestId,i,{message:n.message,status:n.status,code:n.code}),n;const s=n.data;for(const M in s)!isNaN(s[M])&&Number(s[M])!==1/0&&(s[M]=Number(s[M]));if(s){const M=p(`${s.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return{mmsi:s.mmsi,name:s.vesselName||s.aisVesselName,imo:s.imo,callSign:s.callsign||s.aisCallSign,lat:s.lat,lng:s.lon,length:s.length,width:s.width,draught:s.currDraught,sog:s.sog,cog:s.cog,hdg:s.hdg,rot:s.rot,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(s.eta)?p.utc(s.eta).format():void 0,destination:s.dest,positionTime:M.unix(),status:s.status,labelCn:s.statusNameCn,labelEn:s.statusNameEn,vesselType:s.vesselTypeNameEn,flag:s.flagCtryNameEn,clasz:s.classSociety,build:s.buildYear,dwt:s.dwt,grt:s.grt,net:s.net,method:"position",vendor:"myVessel",utc:M.utc().format()}}else return{}}async trajectory(e,a,i,o,n=!0,s={}){(!this.token||p().diff(p(this.token.issuedAt),"seconds")>this.token.expiresIn-300)&&await this.authToken(s);const d=await this.realTimePosition(e,s),r=p(a),m=p(i),M=[];for(;m.diff(r,"day",!0)>30;)await this.trajectoryIn30Day(e,r,r.clone().add(30,"day"),d,o,M,s),r.add(30,"day");return await this.trajectoryIn30Day(e,r,m,d,o,M,s),M}async trajectoryIn30Day(e,a,i,o,n,s,d={}){var f,C,k,w,v;const r="https://svc.data.myvessel.cn/sdc/v1/vessels/status/track",m={headers:{Authorization:`${(f=this.token)==null?void 0:f.tokenType} ${(C=this.token)==null?void 0:C.accessToken}`},json:{mmsi:e,startTime:a.utcOffset(8).format("YYYY-MM-DD HH:mm:ss"),endTime:i.utcOffset(8).format("YYYY-MM-DD HH:mm:ss")}};g==null||g.info("[%s] fetch trajectory from: %s - %j",d.requestId,r,m);const M=await R.post(r,m).json();if(M.code)return g==null||g.warn("[%s] fetch trajectory failed: %j",d.requestId,r,{message:M.message,status:M.status,code:M.code}),M;let h=-1;const b=p(`${(w=(k=M.data)==null?void 0:k[0])==null?void 0:w.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return(v=M.data)==null||v.forEach(c=>{for(const P in c)!isNaN(c[P])&&Number(c[P])!==1/0&&(c[P]=Number(c[P]));const y=p(`${c.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00"),l=c.status,{labelCn:u,labelEn:I}=this.parseStatus(l),F={mmsi:c.mmsi,imo:o==null?void 0:o.imo,lat:c.lat,lng:c.lon,sog:c.sog,cog:c.cog,hdg:c.hdg,draught:c.draught,status:l,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(c.eta)?p(`${c.eta} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00").utc().format():void 0,destination:c.dest,positionTime:y.unix(),labelCn:u,labelEn:I,method:"trajectory",vendor:"myVessel",utc:y.utc().format()},N=Math.floor(y.diff(b,"minute",!0)/(n||1));N!==h&&(h=N,s.push(F))}),s}}class Mt extends G{constructor(e){super();z(this,"token");this.token=e}async realTimePosition(e,a={}){const i="https://api.hifleet.com/position/position/get/token",o={searchParams:{mmsi:e,usertoken:this.token}},n=await R.post(i,o).json();g==null||g.info("[%s] fetch realtime position from: %s - %j",a.requestId,i,o);const s=n==null?void 0:n.list;if(!s)return g==null||g.warn("[%s] fetch realtime position failed: %j",a.requestId,i,n),n;for(const b in s)!isNaN(s[b])&&Number(s[b])!==1/0&&(s[b]=Number(s[b]));s.status=s.sp>3?0:1;const d=s.status,{labelCn:r,labelEn:m}=this.parseStatus(d),M=p(`${s.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return{mmsi:s.m,name:s.n,imo:s.imonumber,callSign:s.callsign,lat:Math.round(s.la/60*1e5)/1e5,lng:Math.round(s.lo/60*1e5)/1e5,length:s.l,width:s.w,draught:s.draught,sog:s.sp,cog:s.co,hdg:s.h,rot:isNaN(s.rot)?0:s.rot,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(s.eta)?p.utc(s.eta).format():void 0,destination:s.destination,vesselType:s.type,dwt:s.dwt,build:s.buildyear,flag:s.fn,positionTime:M.unix(),utc:M.utc().format(),status:d,labelCn:r,labelEn:m,method:"position",vendor:"hifleet"}}async search(e,a={}){let i="https://www.hifleet.com/hifleetapi/searchVesselOL.do";const o={searchParams:{keyword:e},headers:{Referer:"https://www.hifleet.com",Origin:"https://www.hifleet.com",Host:"www.hifleet.com"}};let n=await R.post(i,o).json();g==null||g.info("[%s] fetch vessel props from: %s - %j",a.requestId,i,o),n instanceof Array&&(n=n[0]);for(const d in n)!isNaN(n[d])&&Number(n[d])!==1/0&&(n[d]=Number(n[d]));const s={mmsi:n.m,name:n.n,imo:n.i,callSign:n.c,length:n.l,breadth:n.b,draught:n.dr,type:n.t};return i="https://www.hifleet.com/hifleetapi/sameShipSearch.do",n=await R.post(i,o).json(),g==null||g.info("[%s] search vessel dead weight from: %s - %j",a.requestId,i,o),n instanceof Array&&(n=n[0]),n&&(s.deadweight=Number(n.dwt)),s}async suggest(e,a={}){const i="https://www.hifleet.com/hifleetapi/getShipSuggest.do",o={searchParams:{q:e},headers:{Referer:"https://www.hifleet.com",Origin:"https://www.hifleet.com",Host:"www.hifleet.com"}},n=await R.post(i,o).json();g==null||g.info("[%s] suggest vessel props from: %s - %j",a.requestId,i,o);const s=[];for(const d of n)s.push({mmsi:!d.mmsi||isNaN(d.mmsi)?null:Number(d.mmsi),name:d.name,callSign:d.callsign,imo:!d.imo||isNaN(d.imo)?null:Number(d.imo),score:d._score});return s.sort((d,r)=>r.score-d.score),s}async trajectory(e,a,i,o,n=!0,s={}){var c,y,l;const d=await this.realTimePosition(e,s);let r=p(a);const m=p(i),M=p();if(n){let u=m.diff(r,"d",!0);u<0?r=m.clone().subtract(40,"d"):u<30?r.subtract(10,"d"):u<60?r.subtract(5,"d"):r=m.clone().subtract(80,"d"),u=M.diff(m,"d",!0),m.add(u>10?240:u*24,"h")}const h={searchParams:{endtime:m.utcOffset("+8:00").format("YYYY-MM-DD HH:mm:ss"),starttime:r.utcOffset("+8:00").format("YYYY-MM-DD HH:mm:ss"),mmsi:e,usertoken:this.token}},b="https://api.hifleet.com/position/trajectory/nocompressed/withstatic/token",f=await R.get(b,h).json();g==null||g.info("[%s] fetch trajectory from: %s - %j",s.requestId,b,h);let C;f&&(C=((y=(c=f.ships)==null?void 0:c.offors)==null?void 0:y.ship)||[],C.length||g==null||g.warn("[%s] fetch trajectory failed: %j",s.requestId,f));const k=[];let w=-1;const v=p(`${(l=C==null?void 0:C[0])==null?void 0:l.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");for(const u of C){for(const L in u)!isNaN(u[L])&&Number(u[L])!==1/0&&(u[L]=Number(u[L]));const I=p(`${u.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");u.status=u.sp>4?0:1;const{labelEn:F,labelCn:N}=this.parseStatus(u.status),P={mmsi:u.m,name:u.n,imo:d==null?void 0:d.imo,lat:u.la,lng:u.lo,draught:u.draught,sog:u.sp,cog:u.co,hdg:u.hdg,positionTime:I.unix(),utc:I.utc().format(),status:u.status,labelCn:N,labelEn:F,method:"trajectory",vendor:"hifleet"},E=Math.floor(I.diff(v,"minute",!0)/(o||1));E!==w&&(w=E,k.push(P))}return k}}class pt extends G{constructor(e){super();z(this,"token");this.token=e}async realTimePosition(e,a={}){const i={searchParams:{id:e,k:this.token,enc:1}},o="https://api.shipxy.com/apicall/GetSingleShip",n=await R.get(o,i).json();if(g==null||g.info("[%s] fetch realtime position from: %s - %j",a.requestId,o,i),(n==null?void 0:n.status)!==0)return n;const s=n.data[0];for(const h in s)!isNaN(s[h])&&Number(s[h])!==1/0&&(s[h]=Number(s[h]));const{labelCn:d,labelEn:r}=await this.parseStatus(s.navistat),m=p.unix(s.lasttime);return{mmsi:s.ShipID,name:s.name,imo:s.imo,callSign:s.callsign,lat:Math.round(s.lat/1e6*1e5)/1e5,lng:Math.round(s.lon/1e6*1e5)/1e5,length:Math.round(s.length/10*100)/100,width:Math.round(s.width/10*100)/100,draught:Math.round(s.draught/1e3*100)/100,sog:Math.round(s.sog*3600/1e3/1852*100)/100,cog:Math.round(s.cog/100*100)/100,hdg:Math.round(s.hdg/100*100)/100,rot:Math.round(s.rot/100*100)/100,positionTime:s.lasttime,utc:m.utc().format(),status:s.navistat,labelEn:r,labelCn:d,method:"position",vendor:"shipxy"}}async trajectory(e,a,i,o,n=!0,s={}){var v;const d=await this.realTimePosition(e,s),r=p(a),m=p(i),M="https://api.shipxy.com/apicall/GetShipTrack",h={searchParams:{id:e,k:this.token,enc:1,cut:0,btm:r.unix(),etm:m.unix()}},b=await R.get(M,h).json();if(g==null||g.info("[%s] fetch trajectory from: %s - %j",s.requestId,M,h),(b==null?void 0:b.status)!==0)return b;const f=b==null?void 0:b.points,C=[],k=p.unix((v=f[0])==null?void 0:v.utc);let w=-1;for(const c of f){const y=p.unix(c.utc),l={imo:d==null?void 0:d.imo,mmsi:e,sog:Math.round(c.sog*3600/1e3/1852*100)/100,cog:Math.round(c.cog/100*100)/100,lat:Math.round(c.lat/1e6*1e5)/1e5,lng:Math.round(c.lon/1e6*1e5)/1e5,positionTime:y.unix(),utc:y.utc().format(),method:"trajectory",vendor:"shipxy"},u=Math.floor(y.diff(k,"minute",!0)/(o||1));u!==w&&(w=u,C.push(l))}return C}}class bt extends G{constructor(e){super();z(this,"token");this.token=e}async getShipId(e,a={}){const i={headers:{appKey:this.token},json:{mmsiList:e}},o="https://api3.myships.com/sp/ships/getShipIdByMMSI",n=await R.post(o,i).json();return g==null||g.info("[%s] fetch ship id from: %s - %j",a.requestId,o,i),n.code!=="0"?n:n.data[0].shipId}async getShipInfo(e,a={}){const i={headers:{appKey:this.token},json:{shipId:e}},o="https://api3.myships.com/sp/ships/aissta",n=await R.post(o,i).json();if(g==null||g.info("[%s] fetch ship info from: %s - %j",a.requestId,o,i),n.code!=="0")return n;const s=n.data;let d=s.imo;return e==="407170"&&(d="9198379",g==null||g.warn("[%s] ship(%s) imo error: %s, should be %s",a.requestId,e,s.imo,d)),{mmsi:s.mmsi,name:s.shipnameEn,imo:d,callSign:s.callSign,length:s.length,width:s.breadth,draught:(s.draught||100)/10}}async realTimePosition(e,a={}){const i=await this.getShipId(e,a),o=await this.getShipInfo(i,a),n={headers:{appKey:this.token},json:{shipId:i}},s="https://api3.myships.com/sp/ships/position/latest",d=await R.post(s,n).json();g==null||g.info("[%s] fetch realtime position from: %s - %j",a.requestId,s,n);const r=d.data[0];for(const f in r)!isNaN(r[f])&&Number(r[f])!==1/0&&(r[f]=Number(r[f]));const{labelCn:m,labelEn:M}=await this.parseStatus(r.aisNavStatus),h=p.unix(r.posTime);return{...o,mmsi:e,lat:Math.round(r.lat/1e4/60*1e5)/1e5,lng:Math.round(r.lon/1e4/60*1e5)/1e5,sog:Math.round(r.sog/10*100)/100,cog:Math.round(r.cog/10*100)/100,hdg:Math.round(r.heading*100)/100,rot:Math.round(r.rot*100)/100,positionTime:r.posTime,utc:h.utc().format(),status:r.aisNavStatus,labelEn:M,labelCn:m,method:"position",vendor:"myship"}}async trajectory(e,a,i,o,n=!0,s={}){const d=p(a),r=p(i),m=await this.getShipId(e),M=await this.getShipInfo(m),h=[];for(;r.diff(d,"day",!0)>30;)await this.trajectoryIn30Day(m,d.unix(),d.add(30,"day").unix(),M,e,o,h);return await this.trajectoryIn30Day(m,d.unix(),r.unix(),M,e,o,h),h}async trajectoryIn30Day(e,a,i,o,n,s,d,r={}){var k;const m={headers:{appKey:this.token},json:{shipId:e,startTime:a,endTime:i}},M="https://api3.myships.com/sp/ships/position/history",h=await R.post(M,m).json();if(g==null||g.info("[%s] fetch trajectory from: %s - %j",r.requestId,M,m),h.code!=="0")return g==null||g.warn("[%s] invoke myship trajectory failed: %j",r.requestId,h),h;const b=h.data;for(const w in b)!isNaN(b[w])&&Number(b[w])!==1/0&&(b[w]=Number(b[w]));const f=p.unix((k=b[0])==null?void 0:k.posTime);let C=-1;for(const w of b){const v=p.unix(w.posTime),c={imo:o==null?void 0:o.imo,mmsi:n,lat:Math.round(w.lat/1e4/60*1e5)/1e5,lng:Math.round(w.lon/1e4/60*1e5)/1e5,sog:Math.round(w.sog/10*100)/100,cog:Math.round(w.cog/10*100)/100,hdg:Math.round(w.heading*100)/100,rot:Math.round(w.rot*100)/100,positionTime:v.unix(),utc:v.utc().format(),method:"trajectory",vendor:"myship"},y=Math.floor(v.diff(f,"minute",!0)/(s||1));y!==C&&(C=y,d.push(c))}return d}}let _;try{_=K.getLogger("vessel")}catch{}finally{}var dt=(D=>(D.NOTICE="NOTICE",D.WARN="WARN",D.HEAVY="HEAVY",D.SEVERE="SEVERE",D.ERROR="ERROR",D.FATAL="FATAL",D))(dt||{});class ut{parsePrinciple(t,e={}){var s,d,r;_==null||_.info("[%s] parse rule: %s",e.requestId,t);const a=new RegExp("(?<=\\[)(.+)(?=])","g"),i=t.match(a)?(s=t.match(a))==null?void 0:s[0]:void 0,o=i==null?void 0:i.split(";");if(!o)return;const n={};for(let m=0;m<(o==null?void 0:o.length);m++){const M=(r=(d=o[m].match(a))==null?void 0:d[0])==null?void 0:r.split("],");if(m===0&&!M)n.scope=o[0];else if(M)for(let h=0,b=M.length;h<b;h++){const f=this.parseRule(M[h]);f&&(n[f.level]?f.key?n[f.level][f==null?void 0:f.key]=f:n[f.level]=f:f.key?n[f.level]={[f==null?void 0:f.key]:f}:n[f.level]=f)}}return n}parseRule(t,e={}){var n;_==null||_.debug("[%s] parse rule: %s",e.requestId,t),t=t.startsWith("[")?t:`[${t}`,t=t.endsWith("]")?t:`${t}]`;const a=new RegExp("(?<=\\[)(.+?)(?=])","g"),i=(n=t==null?void 0:t.match(a))==null?void 0:n[0],o=i==null?void 0:i.split(",");if(o)return{operator:o[0],number:Number.isNaN(Number(o[1]))?o[1]:Number(o[1]),level:o[2],time:Number(o[3]),key:o[4]}}checkWeather(t,e,a={}){var f,C,k,w,v,c,y,l,u,I,F,N,P,E,L;let i=0,o=0,n=0,s=0;const d=Math.round(((C=(f=e==null?void 0:e.SEVERE)==null?void 0:f.sigWave)==null?void 0:C.number)*1.6*100)/100,r=(w=(k=e==null?void 0:e.SEVERE)==null?void 0:k.sigWave)==null?void 0:w.number,m=(c=(v=e==null?void 0:e.HEAVY)==null?void 0:v.sigWave)==null?void 0:c.number,M=Math.round((((l=(y=e==null?void 0:e.SEVERE)==null?void 0:y.wind)==null?void 0:l.number)+2)*100)/100,h=(I=(u=e==null?void 0:e.SEVERE)==null?void 0:u.wind)==null?void 0:I.number,b=(N=(F=e==null?void 0:e.HEAVY)==null?void 0:F.wind)==null?void 0:N.number;for(let x=0;x<(t==null?void 0:t.length);x++){const H=t[x],q=(E=(P=H==null?void 0:H.meteo)==null?void 0:P.wave)==null?void 0:E.sig,V=(L=H==null?void 0:H.meteo)==null?void 0:L.wind,U=x?p(H.eta).diff(p(t[x-1].eta),"hour",!0):0;s=U>s?U:s,_==null||_.debug("[%s] check sig.wave: %j",a.requestId,{...q,dgThd4Wv:d,svThd4Wv:r,hvThd4Wv:m}),(q==null?void 0:q.height)>=d?H.isDangerous=!0:(q==null?void 0:q.height)>=r?H.isSevere=!0:(q==null?void 0:q.height)>=m&&(H.isHeavy=!0),_==null||_.debug("[%s] check wind: %j",a.requestId,{...V,dgThd4Wd:M,svThd4Wd:h,hvThd4Wd:b}),(V==null?void 0:V.scale)>=M?(H.isDangerous=!0,delete H.isSevere,delete H.isHeavy):(V==null?void 0:V.scale)>h?(H.isDangerous||(H.isSevere=!0),delete H.isHeavy):(V==null?void 0:V.scale)===b&&!H.isDangerous&&!H.isSevere&&(H.isHeavy=!0),i+=H.isDangerous?U:0,o+=H.isSevere?U:0,n+=H.isHeavy?U:0}return i=Math.round(i*100)/100,o=Math.round(o*100)/100,n=Math.round(n*100)/100,s=Math.round(s),{sample:t,dangerous:i,severe:o,heavy:n,step:s<3?3:s,wind:{dgThd4Wd:M,svThd4Wd:h,hvThd4Wd:b},sig:{dgThd4Wv:d,svThd4Wv:r,hvThd4Wv:m}}}}const gt=new ut;let S;try{S=K.getLogger("vessel")}catch{}finally{}const vt=new mt.MeteoHelper2("",!0);var lt=(D=>(D.common="common",D.container="container",D.tugs="tugs",D))(lt||{}),ht=(D=>(D.Ballast="Ballast",D.Laden="Laden",D))(ht||{}),ft=(D=>(D.Cp="CP",D.Perf="Basis",D.Instruct="Other",D))(ft||{});class W{static blockCoefficient(t,e,a,i){let o=Math.round(t/(e*a*i)*100)/100;o=o<.55?.55:o>.85?.85:o;const n=[.55,.6,.65,.7,.75,.8,.85],s=n.map(d=>Math.abs(d-o));return n[s.indexOf(Math.min(...s))]}static froudeNumber(t,e,a=9.8){let i=Math.round(Math.sqrt(t*t/(a*e))*100)/100;return i=i<.05?.05:i>.3?.3:i,i}static amendFactor(t,e,a){const i={.55:[1.7,-1.4,-7.4],.6:[2.2,-2.5,-9.7],.65:[2.6,-3.7,-11.6],.7:[3.1,-5.3,-12.4],.75:[2.4,-10.6,-9.5],.8:[2.6,-13.1,-15.1],.85:[3.1,-18.7,28]};let n={.55:[1.7,-1.4,-7.4],.6:[2.2,-2.5,-9.7],.65:[2.6,-3.7,-11.6],.7:[3.1,-5.3,-12.4],.75:[2.6,-12.5,-13.5],.8:[3,-16.3,-21.6],.85:[3.4,-20.9,31.8]}[t];return a==="Laden"&&(n=i[t]),n[0]+n[1]*e+n[2]*Math.pow(e,2)}static directionFactor(t,e=0){let a;return t>30&&t<=60?a=(1.7-.03*Math.pow(e-4,2))/2:t>60&&t<=150?a=(.9-.06*Math.pow(e-6,2))/2:t>150&&t<=180?a=(.4-.03*Math.pow(e-8,2))/2:a=1,Math.round(a*1e5)/1e5}static vesselTagFactor(t,e,a,i=0){i=i>6?i-.9*(i-6):i;let o;return a==="container"?o=.7*i+Math.pow(i,6.5)/(22*Math.pow(t,2/3)):e==="Ballast"?o=.7*i+Math.pow(i,6.5)/(2.7*Math.pow(t,2/3)):o=.5*i+Math.pow(i,6.5)/(2.7*Math.pow(t,2/3)),o}static waveHeightFactor(t,e){t=t<3?t*.7:t,t=t<0?.2:t,t=t>6?t-.9*(t-6):t,t=t>9?9:t;let a;return e>30&&e<=60?a=-.6:e>60&&e<=90?a=-.4:e>90&&e<=120?a=t<3?.4:-.3:e>120&&e<=150?a=t<3?.6:-.5:e>150&&e<=180?a=t<3?.7:-.6:a=-.7,Math.round(a*(.144*Math.pow(t,3)+.178*t)*1e4)/1e4}static assembleProperties(t,e,a,i){var h;const o=t.lbp??t.length??t.lengthOverall??198.9642,n=t.draught??8,s=t.breadthMoulded??t.breadth??t.breadthExtreme??32.4572,d=t.deadweight??67035.7773,r=((h=t==null?void 0:t.type)==null?void 0:h.toLowerCase())||"common";return{tag:r.indexOf("container")>-1?"container":r.indexOf("tugs")>-1?"tugs":"common",lbp:o,loadCondition:e,draught:n,breadthMoulded:s,displacement:Math.round((d/1.025+n*s*o*.7)*1e4)/1e4,speed:Math.round((a??14.1382)*1852/3600*1e4)/1e4,bearing:i||90}}static async speedLoseAt(t,e,a,i="",o=2,n=!0,s=!1,d={}){let r;if(e.velocity&&s&&(t.speed=T.LngLatHelper.roundPrecision(e.velocity*1852/3600,6)),n){let m;try{i=(i==null?void 0:i.toUpperCase())==="CMEMS"?"ECMWF":i,i=(i==null?void 0:i.toUpperCase())==="METEO2"?"best_match":i;const{weatherModels:f,marineModels:C}=await nt.Meteo2Assist.autoPickMeteoModel(i),k=await vt.spotForecast(e.lat,e.lng,a.utc().format(),!1,!1,!0,{...d,pastDays:1,forecastDays:1,weatherModels:f,marineModels:C}),[w]=nt.Meteo2Assist.pickHourly(k,a);m=nt.Meteo2Assist.toLegacy(w)}catch(f){S.warn("[%s] meteo2 spot(%j) forecast failed: %s",d.requestId,{...e,eta:a.utc().format(),source:i},f)}const M=W.weatherFactor(t,m),h=W.currentFactor(t.bearing,m==null?void 0:m.current,o),b=Math.round((t.speed*1.943844+M+h)*100)/100;r={meteo:{...m},wxFactor:M,cFactor:h,speed:e.velocity&&s?e.velocity:b<0?1:b,eta:a.utc().format(),etd:a.utc().format()}}else r={wxFactor:0,cFactor:0,speed:e.velocity&&s?e.velocity:Math.round((t.speed*1.943844+0+0)*100)/100,eta:a.utc().format(),etd:a.utc().format()};return delete e.meteo,delete e.wxFactor,delete e.cFactor,delete e.speed,delete e.etd,{...r,...e}}static async speedLoseInHoursStep(t,e,a,i,o,n,s="",d=!0,r=!1,m={}){e.utc();const M=e.clone().add(14,"days"),h=[],b=[];let f=0,C=0,k,w;for(let v=0;v<n.length-1;v++){let c=n[v];c.distanceFromStart=Math.round((o+C)*1e3)/1e3;const y=n[v+1];if(t.bearing=T.LaneHelper.calculateBearing(c,y,!y.gcToPrevious),c.bearing=t.bearing,c.suspend&&r){c.eta=c.eta||e.utc().format(),c.elapsed=c.elapsed??0;const I=c.suspend-c.elapsed;if(i-f>I)i=i-f-I,e.add(I,"hour"),c.elapsed=c.suspend;else{const F=i-f;c.elapsed+=F,e.add(F,"hour"),i=0}if(S==null||S.info(`[%s] suspend ${c.elapsed} hours at %j, and remain ${i} hours need to go...`,m.requestId,c),i===0)return c.distanceFromPrevious=C,{etd:e,from:w||c,to:c,next:n.filter(F=>F),wps:h,days:b}}else c.suspend=0;d=e.isAfter(M)?!1:d,c=await W.speedLoseAt(t,c,e,s,0,d,r,m),w=w||c,c.important&&h.push(c),e.isSameOrAfter(a)&&(b.push(c),a.add(24,"hour"));const l=T.LaneHelper.calculateDistance(c,y,!y.gcToPrevious);let u=Math.round(l/w.speed*1e5)/1e5;if(f+u<i){if(f+=u,e.add(u,"hour"),delete n[v],S==null||S.debug(`[%s] go to %j from %j with ${l}nm, and cost ${u} hours`,m.requestId,{lat:y.lat,lng:y.lng},{lat:w.lat,lng:w.lng,etd:w.etd}),C+=l,n.filter(I=>I).length<=1){k=y,k.eta=e.utc().format(),k.distanceFromPrevious=l,k.distanceFromStart=Math.round((o+C)*1e4)/1e4,h.push(k),delete n[v+1];break}}else{u=i-f,e.add(u,"hour");const I=T.LngLatHelper.roundPrecision(w.speed*u,5);k=T.LaneHelper.calculateCoordinate(c,t.bearing,I,"nauticalmiles",!y.gcToPrevious),k.eta=e.utc().format(),n[v]=k,S==null||S.debug(`[%s] go to %j from %j with ${I}nm, and cost ${u} hours`,m.requestId,{lat:k.lat,lng:k.lng},{lat:c.lat,lng:c.lng,etd:c.etd}),C+=I,k.distanceFromPrevious=Math.round(C*1e4)/1e4,k.distanceFromStart=Math.round((o+C)*1e4)/1e4;break}}return{etd:e,from:w,to:k,next:n.filter(v=>v),wps:h,days:b}}static currentFactor(t,e,a=0){const i=(t-(e==null?void 0:e.degree)||0)/180*Math.PI;if(Math.abs(i)===Math.PI/2)return 0;let o=((e==null?void 0:e.kts)||0)*Math.cos(i);return a&2?o=Math.ceil(o*100)/100:a&1?o=Math.floor(o*100)/100:o=Math.round(o*100)/100,Math.abs(o)>5?0:o}static weatherFactor(t,e){var M,h,b,f,C,k,w;S==null||S.debug("calculate weather factor via: %j",{...t,...e});const a=W.blockCoefficient(t.displacement,t.lbp,t.breadthMoulded,t.draught),i=W.froudeNumber(t.speed,t.lbp),o=W.amendFactor(a,i,t.loadCondition);let n=Math.abs(t.bearing%360-(((M=e==null?void 0:e.wind)==null?void 0:M.degree)%360||0));n=n>180?360-n:n;const s=W.directionFactor(n,(h=e==null?void 0:e.wind)==null?void 0:h.scale),d=W.vesselTagFactor(t.displacement,t.loadCondition,t.tag,(b=e==null?void 0:e.wind)==null?void 0:b.scale);let r=s*o*d/100*t.speed;r=Math.round(r*1.943844*1e4)/1e4*-1,t.tag==="tugs"&&Math.abs(r)>1&&(r=r/(Math.abs(Math.round(r))+1)),S==null||S.debug("wind wx factor = %d",r),n=Math.abs(t.bearing%360-(((C=(f=e==null?void 0:e.wave)==null?void 0:f.sig)==null?void 0:C.degree)%360||0));const m=W.waveHeightFactor(((w=(k=e==null?void 0:e.wave)==null?void 0:k.sig)==null?void 0:w.height)??1,n);return S==null||S.debug("wave wx factor = %d",m),r=Math.abs(r)>Math.abs(m)?r:r*.3+m*.7,S==null||S.debug("weather factor = %d",r),r=Math.abs(r)>3?3*(Math.abs(r)/r)+Math.abs(r)/r*(Math.abs(r)-2)*.1:r,Math.round((r||0)*100)/100}static async analyseInstant(t,e,a,i,o,n="",s=0,d=!0,r=!1,m={}){var Q,X,Z,$,tt,et;const M=p().valueOf();t.lng=T.LngLatHelper.convertToStdLng(t.lng);const{route:h,waypoints:b}=o.points,f=T.LaneHelper.calculateSubRoute(t,h);if(((Q=f[0])==null?void 0:Q.length)<=1)return;const{v0:C,label:k}=t.sog?{v0:t.sog,label:t.label||"Other"}:{v0:i.speed,label:"CP"},w=W.assembleProperties(a,i.loadCondition,C,0),v=b.length?T.LaneHelper.calculateSubWaypoints(t,b):[];v.forEach(Y=>Y.important=!0);const c={from:{...t},route:f,waypoints:v,v0:C,label:k},y={hours:[],days:[],wps:[]};s||(T.LaneHelper.calculateRouteDistance(f)/i.speed<=72?s=3:s=6);let l=T.LaneHelper.simplifyRouteToCoordinates(f,v,0),u=0,I=0,F=0,N=0;e=p(e).utc();const P=e.clone();for(;l.length>0;){const Y=s-e.hour()%s,J=Math.ceil(e.clone().add(Y,"h").set({minute:0,second:0,millisecond:0}).diff(e,"h",!0)*1e4)/1e4,j=await W.speedLoseInHoursStep(w,e,P,J,u,l,n,d,r,m);(X=j.from)!=null&&X.speed&&(y.hours.push(j.from),y.wps.push(...j.wps),y.days.push(...j.days)),l=j==null?void 0:j.next,l.length||y.hours.push(j==null?void 0:j.to),u+=Math.round((((Z=j==null?void 0:j.to)==null?void 0:Z.distanceFromPrevious)??0)*1e4)/1e4}const E=y.hours;for(let Y=0;Y<E.length-1;Y++){const J=p(E[Y+1].eta).diff(E[Y].etd,"hour",!0)||1;I+=(E[Y].wxFactor||0)*J,F+=(E[Y].cFactor||0)*J,N+=J}($=y.wps)==null||$.forEach((Y,J)=>{Y.positionTime=p.utc(Y.etd||Y.eta).unix();const j=y.wps[J-1];if(j){const B=Y.distanceFromStart-j.distanceFromStart,O=p(Y.eta||Y.etd).diff(p(j.etd||j.eta),"h",!0);Y.avgSpd=Math.round(B/O*100)/100;const ct=T.LaneHelper.calculateBearing(j,Y);j.bearing=ct}}),y.wps=(tt=y.wps)==null?void 0:tt.reduce((Y,J)=>(Y.some(j=>Math.round(j.positionTime/60)===Math.round(J.positionTime/60))||Y.push(J),Y),[]),c.sample=y;const L=y.hours.at(0),x=y.hours.at(-1);c.distance=Math.round(x.distanceFromStart*1e3)/1e3,c.etd=p(L.eta).utc().format(),c.eta=p(x.eta).utc().format(),c.wxFactor=Math.round(I/N*1e3)/1e3,c.cFactor=Math.round(F/N*1e3)/1e3,c.avgSpeed=Math.round(x.distanceFromStart/N*1e3)/1e3,c.totalHrs=Math.round(N*1e3)/1e3;const{distanceInECA:H,hoursInECA:q,totalDgoConsInECA:V,eca:U}=await this.calculateECA(c,i,m),st=T.LngLatHelper.roundPrecision(i.fo/24*(N-q),3),ot=T.LngLatHelper.roundPrecision(i.dgo/24*N,3);c.extend={eca:U,distanceInECA:H,hoursInECA:q,totalDgoConsInECA:V},c.totalFoCons=st<0?0:st,c.totalDgoCons=ot;const at=p().valueOf()-M,rt=((et=y==null?void 0:y.hours)==null?void 0:et.length)||1;return S==null||S.info("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms",m==null?void 0:m.requestId,at,rt,Math.round(at/rt*1e3)/1e3),c}static async analyseInstantWithThreshed(t,e,a,i,o,n,s,d="",r=3,m=!0,M=!1,h={}){var Z,$,tt,et,Y,J;const b=p().valueOf();t.lng=T.LngLatHelper.convertToStdLng(t.lng);const{v0:f,label:C}=t.sog?{v0:t.sog,label:t.label||"Other"}:{v0:o.speed,label:"CP"},k=W.assembleProperties(i,o.loadCondition,f,0),w=T.LaneHelper.calculateSubRoute(t,n);if(((Z=w[0])==null?void 0:Z.length)<=1)return;const v=s.length?T.LaneHelper.calculateSubWaypoints(t,s):[];v.forEach(j=>j.important=!0);let c=T.LaneHelper.simplifyRouteToCoordinates(w,v,0),y=0,l=0,u=0,I=0;const F={hours:[],wps:[],days:[]};e=p(e).utc();const N=e.clone();for(;c.length>0;){const j=r-e.hour()%r;let B=Math.ceil(e.clone().add(j,"h").set({minute:0,second:0,millisecond:0}).diff(e,"h",!0)*1e4)/1e4;B=e.clone().add(B,"h").isSameOrAfter(a)?a.diff(e,"h",!0)*1e4/1e4:B;const O=await W.speedLoseInHoursStep(k,e,N,B,y,c,d,m,M,h);if(($=O.from)!=null&&$.speed&&(F.hours.push(O.from),O!=null&&O.wps&&F.wps.push(...O.wps),F.days.push(...O.days)),c=O==null?void 0:O.next,c.length||F.hours.push(O==null?void 0:O.to),y+=Math.round((((tt=O==null?void 0:O.to)==null?void 0:tt.distanceFromPrevious)??0)*1e4)/1e4,!B)break}F.wps=(et=F.wps)==null?void 0:et.reduce((j,B)=>(j.some(O=>Math.round(p(O.etd).unix()/60)===Math.round(p(B.etd).unix()/60))||j.push(B),j),[]),(Y=F.wps)==null||Y.forEach((j,B)=>{const O=F.wps[B-1];if(O){const ct=j.distanceFromStart-O.distanceFromStart,wt=p(j.eta||j.etd).diff(p(O.etd||O.eta),"h",!0);j.avgSpd=Math.round(ct/wt*100)/100;const It=T.LaneHelper.calculateBearing(O,j);O.bearing=It}});const P=F.hours;for(let j=0;j<P.length-1;j++){const B=p(P[j+1].eta).diff(P[j].etd,"hour",!0);l+=P[j].wxFactor*B,u+=P[j].cFactor*B,I+=B}const E=F.hours.at(0),L=F.hours.at(-1),x=await T.LaneHelper.calculateRangeRoute(E,L,w),H=await T.LaneHelper.calculateRangeWaypoints(E,L,w,v),q={sample:F,distance:Math.round(((L==null?void 0:L.distanceFromStart)||0)*1e4)/1e4,etd:p(E.eta).utc().format(),eta:p(L==null?void 0:L.eta).utc().format(),wxFactor:Math.round(l/I*1e3)/1e3,cFactor:Math.round(u/I*1e3)/1e3,avgSpeed:Math.round(((L==null?void 0:L.distanceFromStart)||0)/I*1e3)/1e3,totalHrs:Math.round(I*1e3)/1e3,from:E,to:L,route:x,waypoints:H,v0:f,label:C},{distanceInECA:V,hoursInECA:U,totalDgoConsInECA:st,eca:ot}=await this.calculateECA(q,o,h),it=T.LngLatHelper.roundPrecision(o.fo/24*(I-U),3),at=T.LngLatHelper.roundPrecision(o.dgo/24*I,3);q.extend={eca:ot,distanceInECA:V,hoursInECA:U,totalDgoConsInECA:st},q.totalDgoCons=at,q.totalFoCons=it<0?0:it;const Q=p().valueOf()-b,X=((J=F==null?void 0:F.hours)==null?void 0:J.length)||1;return S==null||S.debug("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms",h==null?void 0:h.requestId,Q,X,Math.round(Q/X*1e3)/1e3),q}static async analyseCost(t,e,a,i,o={}){var w,v;const n=p().valueOf(),s=[];t.speedStep=t.speedStep||3,t.alterStep=t.alterStep??1;const d=T.LaneHelper.calculateRouteDistance(i.route);let r=0;a.forEach(c=>{const y=Math.ceil(d/c.speed/24);r=r<y?y:r}),r=r*1.3;const m=p.utc(t.etd).add(r??14,"day");let M=1;for(const c of a){const y=JSON.parse(JSON.stringify(i.route)),l=JSON.parse(JSON.stringify(i.waypoints)),u=await W.analyseInstantWithThreshed({lat:t.lat,lng:t.lng},t.etd,m,e,c,y,l,t.meteoVendor,t.speedStep,t.useMeteo,t.useRouteParam,o);u&&(await W.calculateCost(u,c,t,o),s.push(u),S==null||S.info("[%s][L%d-%d] analyse from %s to %s cost: %j",o.requestId,1,M,t.etd,m.format(),{cost:u.cost.total,hire:u.cost.hire,bunker:u.cost.bunker,distance:u.distance,hours:u.totalHrs,cp:`${c.speed}/${c.fo}/${c.dgo}`})),M++}s.sort((c,y)=>c.cost.total-y.cost.total);const h=s.at(0),b=s.at(1),f=[];if(f.push({combined:!1,speeds:[h],cost:(w=h.cost)==null?void 0:w.total}),b){const c=h.cost.cp,y=b.cost.cp,l=p(h.eta),u=p(h.etd),I=l.diff(u,"days",!0);let F=Math.ceil(I/2);F=F>7?7:F<t.alterStep?t.alterStep:F;let N=2,P={combined:!1,speeds:[b],cost:(v=b.cost)==null?void 0:v.total},E;for(;F>=t.alterStep;){const L=await W.combinedAnalyse(t,e,m,[c,y],i,F,{...o,level:N});if(P.cost>L.cost?E?(E==null?void 0:E.cost)>L.cost&&(E=L):(E=P,P=L):(!E||(E==null?void 0:E.cost)>L.cost)&&(E=L),F<=t.alterStep)break;F=Math.ceil(F/2),N+=1}f.push(P),E&&f.push(E)}const k=p().valueOf()-n;return S==null||S.info("[%s] analyse elapsed: %d ms",o==null?void 0:o.requestId,k),f.sort((c,y)=>c.cost-y.cost)}static async combinedAnalyse(t,e,a,i,o,n,s={}){s.counter=1,S==null||S.info("[%s][L%d] analyse with alternate cp in every %d days",s.requestId,s.level,n);const d=await W.alternateAnalyse(t,e,a,i,0,o,n,s),r=d.reduce((y,l)=>y+l.cost.total,0),m=d.reduce((y,l)=>y+l.cost.hire,0),M=d.reduce((y,l)=>y+l.cost.bunker,0),h=d.reduce((y,l)=>y+l.distance,0),b=d.reduce((y,l)=>y+l.totalHrs,0);S==null||S.info("[%s][L%d] cost with cpa/cpb turn: %j",s.requestId,s.level,{cost:r,hire:m,bunker:M,distance:h,hours:b});const f=await W.alternateAnalyse(t,e,a,i,1,o,n,s),C=f.reduce((y,l)=>y+l.cost.total,0),k=f.reduce((y,l)=>y+l.cost.hire,0),w=f.reduce((y,l)=>y+l.cost.bunker,0),v=f.reduce((y,l)=>y+l.distance,0),c=f.reduce((y,l)=>y+l.totalHrs,0);return S==null||S.info("[%s][L%d] cost with cpb/cpa turn: %j",s.requestId,s.level,{cost:C,hire:k,bunker:w,distance:v,hours:c}),r<C?{combined:!0,cost:Math.round(r*1e3)/1e3,speeds:d,step:n}:{combined:!0,cost:Math.round(C*1e3)/1e3,speeds:f,step:n}}static async alternateAnalyse(t,e,a,i,o,n,s,d={}){var h,b;let r=p.utc(t.etd);const m={lat:t.lat,lng:t.lng},M=[];for(;r.isBefore(a);){const f=r.clone().utc().add(s,"day"),C=JSON.parse(JSON.stringify(n.route)),k=JSON.parse(JSON.stringify(n.waypoints)),w=i[o],v=await W.analyseInstantWithThreshed(m,r.utc().format(),f,e,w,C,k,t.meteoVendor,t.speedStep,t.useMeteo,t.useRouteParam,d);v&&(await W.calculateCost(v,w,t,d),S==null||S.info("[%s][L%d-%d] analyse from %s to %s cost: %j",d.requestId,d.level,d.counter,r.utc().format(),f.utc().format(),{cost:v.cost.total,hire:v.cost.hire,bunker:v.cost.bunker,distance:v.distance,hours:v.totalHrs,cp:`${w.speed}/${w.fo}/${w.dgo}`})),d.counter=d.counter+1;const c=(b=(h=v==null?void 0:v.sample)==null?void 0:h.hours)==null?void 0:b.at(-1);if(c)m.lat=c.lat,m.lng=c.lng,r=p(c.eta),M.push(v),o=o?0:1;else break}return M}static async calculateCost(t,e,a,i={}){var o;if(t){const n=(a.addComm||0)>=1?(a.addComm||0)/100:a.addComm||0,s=Math.round(t.totalHrs/24*(a.dailyHire||0)*(1-n)*1e3)/1e3,d=Math.round(t.totalFoCons*(a.priceFO||0)*1e3)/1e3,r=Math.round((t.totalDgoCons+(((o=t.extend)==null?void 0:o.totalDgoConsInECA)||0))*(a.priceDGO||0)*1e3)/1e3;t.cost={total:Math.round((s+d+r)*1e3)/1e3,hire:s,bunker:Math.round((d+r)*1e3)/1e3,cp:e}}return t}static async calculateECA(t,e,a={}){var d,r,m,M;const i=await T.LaneHelper.intersectInECA((t==null?void 0:t.route)||[]);let o=0,n=0,s=0;(r=(d=t==null?void 0:t.sample)==null?void 0:d.wps)==null||r.forEach(h=>{h.positionTime=p.utc(h.etd||h.eta).unix()});for(const h of i){o+=h.distance;const b=await T.LaneHelper.deadReckoningTime((m=h.waypoints)==null?void 0:m.at(0),t.sample.wps),f=await T.LaneHelper.deadReckoningTime((M=h.waypoints)==null?void 0:M.at(-1),t.sample.wps);h.in=b,h.out=f,h.totalHrs=T.LngLatHelper.roundPrecision((f.positionTime-b.positionTime)/3600,3),h.totalDgoCons=T.LngLatHelper.roundPrecision(e.fo/24*h.totalHrs,3),n+=h.totalHrs,s+=h.totalDgoCons}return o=T.LngLatHelper.roundPrecision(o,3),n=T.LngLatHelper.roundPrecision(n,3),s=T.LngLatHelper.roundPrecision(s,3),{distanceInECA:o,hoursInECA:n,totalDgoConsInECA:s,eca:i}}static async mergeSpeeds(t,e={}){var c,y;const a={hours:[],wps:[],days:[]},i=t.reduce((l,u)=>l+u.distance,0),o=t.reduce((l,u)=>{var I;return l+(((I=u.extend)==null?void 0:I.distanceInECA)||0)},0),n=t.reduce((l,u)=>l+u.totalHrs,0),s=t.reduce((l,u)=>{var I;return l+(((I=u.extend)==null?void 0:I.hoursInECA)||0)},0),d=t.reduce((l,u)=>{var I;return l+(((I=u.extend)==null?void 0:I.totalDgoConsInECA)||0)},0),r=t.reduce((l,u)=>l+u.wxFactor*u.totalHrs/n,0),m=t.reduce((l,u)=>l+u.cFactor*u.totalHrs/n,0),M=t.reduce((l,u)=>l+u.totalFoCons,0),h=t.reduce((l,u)=>l+u.totalDgoCons,0),b=t.reduce((l,u)=>l+u.cost.total,0),f=t.reduce((l,u)=>l+u.cost.hire,0),C=t.reduce((l,u)=>l+u.cost.bunker,0),k=[],w=[];let v;for(const l of t){w.push(...((c=l.extend)==null?void 0:c.eca)||[]);const u=l.sample.hours,I=l.sample.wps,F=l.sample.days,N=u.at(0);v&&(N.distanceFromPrevious=v.distanceFromPrevious,N.distanceFromStart=v.distanceFromStart,u.forEach((x,H)=>{H&&(x.distanceFromStart=x.distanceFromStart+v.distanceFromStart)}),I.at(0).distanceFromPrevious=v.distanceFromPrevious,I.at(0).distanceFromStart=v.distanceFromStart,I.forEach((x,H)=>{H&&(x.distanceFromStart=x.distanceFromStart+v.distanceFromStart)}),F.at(0).distanceFromPrevious=v.distanceFromPrevious,F.at(0).distanceFromStart=v.distanceFromStart,F.forEach((x,H)=>{H&&(x.distanceFromStart=x.distanceFromStart+v.distanceFromStart)})),N.cp=l.cost.cp;const P=[l.etd,l.eta],E=k.findIndex(x=>x.id===N.cp.id);E===-1?(N.cp.segment=[P],k.push(N.cp)):k[E].segment.push(P),u.forEach(x=>{var q;((q=a.hours)==null?void 0:q.findIndex(V=>V.eta===x.eta))===-1&&a.hours.push(x)}),I.forEach(x=>{var q;((q=a.wps)==null?void 0:q.findIndex(V=>V.eta===x.eta))===-1&&a.wps.push(x)}),F.forEach(x=>{var q;((q=a==null?void 0:a.days)==null?void 0:q.findIndex(V=>V.eta===x.eta))===-1&&a.days.push(x)});const L=(y=a.wps)==null?void 0:y.findIndex(x=>x.eta===N.eta);L===-1?a.wps.push(N):a.wps[L]=N,v=u.at(-1)}return a.wps.sort((l,u)=>{p(l.etd).unix()-p(u.etd).unix()}),a.wps.forEach((l,u)=>{const I=a.wps[u-1];if(I){const F=l.distanceFromStart-(I.distanceFromStart||0),N=p(l.eta||l.etd).diff(p(I.etd||I.eta),"hour",!0),P=Math.round(F/N*100)/100;l.avgSpd=P;const E=T.LaneHelper.calculateBearing(I,l);I.bearing=E}}),{sample:a,etd:t.at(0).etd,eta:t.at(-1).eta,from:t.at(0).from,to:t.at(-1).to,v0:t.at(0).v0,label:"Combined",distance:Math.round(i*1e3)/1e3,totalHrs:Math.round(n*1e3)/1e3,avgSpeed:Math.round(i/n*1e3)/1e3,wxFactor:Math.round(r*1e3)/1e3,cFactor:Math.round(m*1e3)/1e3,totalFoCons:Math.round(M*1e3)/1e3,totalDgoCons:Math.round(h*1e3)/1e3,cost:{total:Math.round(b*1e3)/1e3,hire:Math.round(f*1e3)/1e3,bunker:Math.round(C*1e3)/1e3},extend:{cps:k,eca:w,distanceInECA:Math.round(o*1e3)/1e3,hoursInECA:Math.round(s*1e3)/1e3,totalDgoConsInECA:Math.round(d*1e3)/1e3,speeds:t}}}}A.AISImpl=G,A.AlertHelper=ut,A.AlertLevel=dt,A.HifleetImpl=Mt,A.LoadCondition=ht,A.MyShipImpl=bt,A.MyVesselImpl=yt,A.ShipxyImpl=pt,A.SpeedHelper=W,A.SpeedLabel=ft,A.VesselTag=lt,A.alertHelper=gt,Object.defineProperty(A,Symbol.toStringTag,{value:"Module"})});
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@idm-plugin/vessel",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "2.2.
|
|
4
|
+
"version": "2.2.2",
|
|
5
5
|
"description": "idm plugin for vessel",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"keywords": [
|
|
@@ -33,13 +33,15 @@
|
|
|
33
33
|
},
|
|
34
34
|
"peerDependencies": {
|
|
35
35
|
"@idm-plugin/geo2": "^1.4.7",
|
|
36
|
-
"@idm-plugin/meteo": "^0.
|
|
37
|
-
"@idm-plugin/meteo2": "^0.
|
|
36
|
+
"@idm-plugin/meteo": "^0.5.2",
|
|
37
|
+
"@idm-plugin/meteo2": "^0.6.8",
|
|
38
|
+
"@idm-plugin/tag": "^0.2.3"
|
|
38
39
|
},
|
|
39
40
|
"devDependencies": {
|
|
40
41
|
"@idm-plugin/geo2": "^1.4.7",
|
|
41
|
-
"@idm-plugin/meteo": "^0.
|
|
42
|
-
"@idm-plugin/meteo2": "^0.
|
|
42
|
+
"@idm-plugin/meteo": "^0.5.2",
|
|
43
|
+
"@idm-plugin/meteo2": "^0.6.8",
|
|
44
|
+
"@idm-plugin/tag": "^0.2.3",
|
|
43
45
|
"@types/jest": "^25.2.2",
|
|
44
46
|
"@types/node": "^18.14.2",
|
|
45
47
|
"@typescript-eslint/eslint-plugin": "^5.53.0",
|