@idm-plugin/vessel 2.3.0 → 2.3.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 +121 -117
- package/dist/index.umd.cjs +1 -1
- package/dist/speed/src/index.d.ts +2 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -133,31 +133,33 @@ class jt extends st {
|
|
|
133
133
|
if (r.status !== 200)
|
|
134
134
|
return M == null || M.warn("[%s] fetch suggest vessels failed: %j", a.requestId, { message: r.message, status: r.status, code: r.code }), {};
|
|
135
135
|
{
|
|
136
|
-
const
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
136
|
+
const l = r.data;
|
|
137
|
+
if (l)
|
|
138
|
+
return {
|
|
139
|
+
mmsi: l.mmsi,
|
|
140
|
+
imo: Number.isNaN(l.imo) ? null : Number(l.imo),
|
|
141
|
+
callSign: l.callsign,
|
|
142
|
+
name: l.nameEn,
|
|
143
|
+
nameCn: l.nameCn,
|
|
144
|
+
type: l.vesselTypeNameEn,
|
|
145
|
+
flagName: l.flagCtry,
|
|
146
|
+
clasz: l.classSociety,
|
|
147
|
+
dateOfBuild: l.buildYearMonth,
|
|
148
|
+
deadweight: l.dwt,
|
|
149
|
+
grossTonnage: l.grt,
|
|
150
|
+
netTonnage: l.net,
|
|
151
|
+
teu: l.teu,
|
|
152
|
+
length: l.length,
|
|
153
|
+
breadth: l.width,
|
|
154
|
+
height: l.height,
|
|
155
|
+
draught: l.draught,
|
|
156
|
+
speed: l.speed,
|
|
157
|
+
passengerCapacity: l.passengercapacity,
|
|
158
|
+
vendor: "myvessel",
|
|
159
|
+
raw: l
|
|
160
|
+
};
|
|
160
161
|
}
|
|
162
|
+
return {};
|
|
161
163
|
}
|
|
162
164
|
async archives(t, a = {}) {
|
|
163
165
|
var s, r;
|
|
@@ -228,10 +230,10 @@ class jt extends st {
|
|
|
228
230
|
}
|
|
229
231
|
async trajectory(t, a, i, o, n = !0, s = {}) {
|
|
230
232
|
await this.checkToken(s);
|
|
231
|
-
const r = await this.realTimePosition(t, s), c = w(a), u = w(i),
|
|
233
|
+
const r = await this.realTimePosition(t, s), c = w(a), u = w(i), l = [];
|
|
232
234
|
for (; u.diff(c, "day", !0) > 30; )
|
|
233
|
-
await this.trajectoryIn30Day(t, c, c.clone().add(30, "day"), r, o,
|
|
234
|
-
return await this.trajectoryIn30Day(t, c, u, r, o,
|
|
235
|
+
await this.trajectoryIn30Day(t, c, c.clone().add(30, "day"), r, o, l, s), c.add(30, "day");
|
|
236
|
+
return await this.trajectoryIn30Day(t, c, u, r, o, l, s), l;
|
|
235
237
|
}
|
|
236
238
|
async trajectoryIn30Day(t, a, i, o, n, s, r = {}) {
|
|
237
239
|
var y, F, I, p, v;
|
|
@@ -246,15 +248,15 @@ class jt extends st {
|
|
|
246
248
|
}
|
|
247
249
|
};
|
|
248
250
|
M == null || M.info("[%s] fetch trajectory from: %s - %j", r.requestId, c, u);
|
|
249
|
-
const
|
|
250
|
-
if (
|
|
251
|
-
return M == null || M.warn("[%s] fetch trajectory failed: %j", r.requestId, c, { message:
|
|
251
|
+
const l = await L.post(c, u).json();
|
|
252
|
+
if (l.code)
|
|
253
|
+
return M == null || M.warn("[%s] fetch trajectory failed: %j", r.requestId, c, { message: l.message, status: l.status, code: l.code }), l;
|
|
252
254
|
let f = -1;
|
|
253
|
-
const b = w(`${(p = (I =
|
|
254
|
-
return (v =
|
|
255
|
+
const b = w(`${(p = (I = l.data) == null ? void 0 : I[0]) == null ? void 0 : p.postime} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
256
|
+
return (v = l.data) == null || v.forEach((d) => {
|
|
255
257
|
for (const P in d)
|
|
256
258
|
!isNaN(d[P]) && Number(d[P]) !== 1 / 0 && (d[P] = Number(d[P]));
|
|
257
|
-
const g = w(`${d.postime} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00"),
|
|
259
|
+
const g = w(`${d.postime} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00"), m = d.status, { labelCn: h, labelEn: k } = this.parseStatus(m), S = {
|
|
258
260
|
mmsi: d.mmsi,
|
|
259
261
|
imo: o == null ? void 0 : o.imo,
|
|
260
262
|
lat: d.lat,
|
|
@@ -263,7 +265,7 @@ class jt extends st {
|
|
|
263
265
|
cog: d.cog,
|
|
264
266
|
hdg: d.hdg,
|
|
265
267
|
draught: d.draught,
|
|
266
|
-
status:
|
|
268
|
+
status: m,
|
|
267
269
|
eta: /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(d.eta) ? w(`${d.eta} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00").utc().format() : void 0,
|
|
268
270
|
destination: d.dest,
|
|
269
271
|
positionTime: g.unix(),
|
|
@@ -297,7 +299,7 @@ class Et extends st {
|
|
|
297
299
|
for (const b in s)
|
|
298
300
|
!isNaN(s[b]) && Number(s[b]) !== 1 / 0 && (s[b] = Number(s[b]));
|
|
299
301
|
s.status = s.sp > 3 ? 0 : 1;
|
|
300
|
-
const r = s.status, { labelCn: c, labelEn: u } = this.parseStatus(r),
|
|
302
|
+
const r = s.status, { labelCn: c, labelEn: u } = this.parseStatus(r), l = w(`${s.ti} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
301
303
|
return {
|
|
302
304
|
mmsi: s.m,
|
|
303
305
|
name: s.n,
|
|
@@ -318,8 +320,8 @@ class Et extends st {
|
|
|
318
320
|
dwt: s.dwt,
|
|
319
321
|
build: s.buildyear,
|
|
320
322
|
flag: s.fn,
|
|
321
|
-
positionTime:
|
|
322
|
-
utc:
|
|
323
|
+
positionTime: l.unix(),
|
|
324
|
+
utc: l.utc().format(),
|
|
323
325
|
status: r,
|
|
324
326
|
labelCn: c,
|
|
325
327
|
labelEn: u,
|
|
@@ -379,13 +381,13 @@ class Et extends st {
|
|
|
379
381
|
return s.sort((r, c) => c.score - r.score), s;
|
|
380
382
|
}
|
|
381
383
|
async trajectory(t, a, i, o, n = !0, s = {}) {
|
|
382
|
-
var d, g,
|
|
384
|
+
var d, g, m;
|
|
383
385
|
const r = await this.realTimePosition(t, s);
|
|
384
386
|
let c = w(a);
|
|
385
|
-
const u = w(i),
|
|
387
|
+
const u = w(i), l = w();
|
|
386
388
|
if (n) {
|
|
387
389
|
let h = u.diff(c, "d", !0);
|
|
388
|
-
h < 0 ? c = u.clone().subtract(40, "d") : h < 30 ? c.subtract(10, "d") : h < 60 ? c.subtract(5, "d") : c = u.clone().subtract(80, "d"), h =
|
|
390
|
+
h < 0 ? c = u.clone().subtract(40, "d") : h < 30 ? c.subtract(10, "d") : h < 60 ? c.subtract(5, "d") : c = u.clone().subtract(80, "d"), h = l.diff(u, "d", !0), u.add(h > 10 ? 240 : h * 24, "h");
|
|
389
391
|
}
|
|
390
392
|
const f = {
|
|
391
393
|
searchParams: {
|
|
@@ -400,7 +402,7 @@ class Et extends st {
|
|
|
400
402
|
y && (F = ((g = (d = y.ships) == null ? void 0 : d.offors) == null ? void 0 : g.ship) || [], F.length || M == null || M.warn("[%s] fetch trajectory failed: %j", s.requestId, y));
|
|
401
403
|
const I = [];
|
|
402
404
|
let p = -1;
|
|
403
|
-
const v = w(`${(
|
|
405
|
+
const v = w(`${(m = F == null ? void 0 : F[0]) == null ? void 0 : m.ti} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
404
406
|
for (const h of F) {
|
|
405
407
|
for (const A in h)
|
|
406
408
|
!isNaN(h[A]) && Number(h[A]) !== 1 / 0 && (h[A] = Number(h[A]));
|
|
@@ -474,7 +476,7 @@ class Nt extends st {
|
|
|
474
476
|
}
|
|
475
477
|
async trajectory(t, a, i, o, n = !0, s = {}) {
|
|
476
478
|
var v;
|
|
477
|
-
const r = await this.realTimePosition(t, s), c = w(a), u = w(i),
|
|
479
|
+
const r = await this.realTimePosition(t, s), c = w(a), u = w(i), l = "https://api.shipxy.com/apicall/GetShipTrack", f = {
|
|
478
480
|
searchParams: {
|
|
479
481
|
id: t,
|
|
480
482
|
k: this.token,
|
|
@@ -483,13 +485,13 @@ class Nt extends st {
|
|
|
483
485
|
btm: c.unix(),
|
|
484
486
|
etm: u.unix()
|
|
485
487
|
}
|
|
486
|
-
}, b = await L.get(
|
|
487
|
-
if (M == null || M.info("[%s] fetch trajectory from: %s - %j", s.requestId,
|
|
488
|
+
}, b = await L.get(l, f).json();
|
|
489
|
+
if (M == null || M.info("[%s] fetch trajectory from: %s - %j", s.requestId, l, f), (b == null ? void 0 : b.status) !== 0)
|
|
488
490
|
return b;
|
|
489
491
|
const y = b == null ? void 0 : b.points, F = [], I = w.unix((v = y[0]) == null ? void 0 : v.utc);
|
|
490
492
|
let p = -1;
|
|
491
493
|
for (const d of y) {
|
|
492
|
-
const g = w.unix(d.utc),
|
|
494
|
+
const g = w.unix(d.utc), m = {
|
|
493
495
|
imo: r == null ? void 0 : r.imo,
|
|
494
496
|
mmsi: t,
|
|
495
497
|
sog: Math.round(d.sog * 3600 / 1e3 / 1852 * 100) / 100,
|
|
@@ -501,7 +503,7 @@ class Nt extends st {
|
|
|
501
503
|
method: "trajectory",
|
|
502
504
|
vendor: "shipxy"
|
|
503
505
|
}, h = Math.floor(g.diff(I, "minute", !0) / (o || 1));
|
|
504
|
-
h !== p && (p = h, F.push(
|
|
506
|
+
h !== p && (p = h, F.push(m));
|
|
505
507
|
}
|
|
506
508
|
return F;
|
|
507
509
|
}
|
|
@@ -559,7 +561,7 @@ class Tt extends st {
|
|
|
559
561
|
const c = r.data[0];
|
|
560
562
|
for (const y in c)
|
|
561
563
|
!isNaN(c[y]) && Number(c[y]) !== 1 / 0 && (c[y] = Number(c[y]));
|
|
562
|
-
const { labelCn: u, labelEn:
|
|
564
|
+
const { labelCn: u, labelEn: l } = await this.parseStatus(c.aisNavStatus), f = w.unix(c.posTime);
|
|
563
565
|
return {
|
|
564
566
|
...o,
|
|
565
567
|
mmsi: t,
|
|
@@ -572,17 +574,17 @@ class Tt extends st {
|
|
|
572
574
|
positionTime: c.posTime,
|
|
573
575
|
utc: f.utc().format(),
|
|
574
576
|
status: c.aisNavStatus,
|
|
575
|
-
labelEn:
|
|
577
|
+
labelEn: l,
|
|
576
578
|
labelCn: u,
|
|
577
579
|
method: "position",
|
|
578
580
|
vendor: "myship"
|
|
579
581
|
};
|
|
580
582
|
}
|
|
581
583
|
async trajectory(t, a, i, o, n = !0, s = {}) {
|
|
582
|
-
const r = w(a), c = w(i), u = await this.getShipId(t),
|
|
584
|
+
const r = w(a), c = w(i), u = await this.getShipId(t), l = await this.getShipInfo(u), f = [];
|
|
583
585
|
for (; c.diff(r, "day", !0) > 30; )
|
|
584
|
-
await this.trajectoryIn30Day(u, r.unix(), r.add(30, "day").unix(),
|
|
585
|
-
return await this.trajectoryIn30Day(u, r.unix(), c.unix(),
|
|
586
|
+
await this.trajectoryIn30Day(u, r.unix(), r.add(30, "day").unix(), l, t, o, f);
|
|
587
|
+
return await this.trajectoryIn30Day(u, r.unix(), c.unix(), l, t, o, f), f;
|
|
586
588
|
}
|
|
587
589
|
async trajectoryIn30Day(t, a, i, o, n, s, r, c = {}) {
|
|
588
590
|
var I;
|
|
@@ -595,8 +597,8 @@ class Tt extends st {
|
|
|
595
597
|
startTime: a,
|
|
596
598
|
endTime: i
|
|
597
599
|
}
|
|
598
|
-
},
|
|
599
|
-
if (M == null || M.info("[%s] fetch trajectory from: %s - %j", c.requestId,
|
|
600
|
+
}, l = "https://api3.myships.com/sp/ships/position/history", f = await L.post(l, u).json();
|
|
601
|
+
if (M == null || M.info("[%s] fetch trajectory from: %s - %j", c.requestId, l, u), f.code !== "0")
|
|
600
602
|
return M == null || M.warn("[%s] invoke myship trajectory failed: %j", c.requestId, f), f;
|
|
601
603
|
const b = f.data;
|
|
602
604
|
for (const p in b)
|
|
@@ -647,12 +649,12 @@ class yt {
|
|
|
647
649
|
return;
|
|
648
650
|
const n = {};
|
|
649
651
|
for (let u = 0; u < (o == null ? void 0 : o.length); u++) {
|
|
650
|
-
const
|
|
651
|
-
if (u === 0 && !
|
|
652
|
+
const l = (c = (r = o[u].match(a)) == null ? void 0 : r[0]) == null ? void 0 : c.split("],");
|
|
653
|
+
if (u === 0 && !l)
|
|
652
654
|
n.scope = o[0];
|
|
653
|
-
else if (
|
|
654
|
-
for (let f = 0, b =
|
|
655
|
-
const y = this.parseRule(
|
|
655
|
+
else if (l)
|
|
656
|
+
for (let f = 0, b = l.length; f < b; f++) {
|
|
657
|
+
const y = this.parseRule(l[f]);
|
|
656
658
|
y && (n[y.level] ? y.key ? n[y.level][y == null ? void 0 : y.key] = y : n[y.level] = y : y.key ? n[y.level] = { [y == null ? void 0 : y.key]: y } : n[y.level] = y);
|
|
657
659
|
}
|
|
658
660
|
}
|
|
@@ -686,14 +688,14 @@ class yt {
|
|
|
686
688
|
* @param options
|
|
687
689
|
*/
|
|
688
690
|
checkWeather(e, t, a = {}) {
|
|
689
|
-
var y, F, I, p, v, d, g,
|
|
691
|
+
var y, F, I, p, v, d, g, m, h, k, S, D, P, N, A;
|
|
690
692
|
let i = 0, o = 0, n = 0, s = 0;
|
|
691
|
-
const r = Math.round(((F = (y = t == null ? void 0 : t.SEVERE) == null ? void 0 : y.sigWave) == null ? void 0 : F.number) * 1.6 * 100) / 100, c = (p = (I = t == null ? void 0 : t.SEVERE) == null ? void 0 : I.sigWave) == null ? void 0 : p.number, u = (d = (v = t == null ? void 0 : t.HEAVY) == null ? void 0 : v.sigWave) == null ? void 0 : d.number,
|
|
693
|
+
const r = Math.round(((F = (y = t == null ? void 0 : t.SEVERE) == null ? void 0 : y.sigWave) == null ? void 0 : F.number) * 1.6 * 100) / 100, c = (p = (I = t == null ? void 0 : t.SEVERE) == null ? void 0 : I.sigWave) == null ? void 0 : p.number, u = (d = (v = t == null ? void 0 : t.HEAVY) == null ? void 0 : v.sigWave) == null ? void 0 : d.number, l = Math.round((((m = (g = t == null ? void 0 : t.SEVERE) == null ? void 0 : g.wind) == null ? void 0 : m.number) + 2) * 100) / 100, f = (k = (h = t == null ? void 0 : t.SEVERE) == null ? void 0 : h.wind) == null ? void 0 : k.number, b = (D = (S = t == null ? void 0 : t.HEAVY) == null ? void 0 : S.wind) == null ? void 0 : D.number;
|
|
692
694
|
for (let x = 0; x < (e == null ? void 0 : e.length); x++) {
|
|
693
695
|
const T = e[x], q = (N = (P = T == null ? void 0 : T.meteo) == null ? void 0 : P.wave) == null ? void 0 : N.sig, R = (A = T == null ? void 0 : T.meteo) == null ? void 0 : A.wind, J = x ? w(T.eta).diff(w(e[x - 1].eta), "hour", !0) : 0;
|
|
694
|
-
s = J > s ? J : s, z == null || z.debug("[%s] check sig.wave: %j", a.requestId, { ...q, dgThd4Wv: r, svThd4Wv: c, hvThd4Wv: u }), (q == null ? void 0 : q.height) >= r ? T.isDangerous = !0 : (q == null ? void 0 : q.height) >= c ? T.isSevere = !0 : (q == null ? void 0 : q.height) >= u && (T.isHeavy = !0), z == null || z.debug("[%s] check wind: %j", a.requestId, { ...R, dgThd4Wd:
|
|
696
|
+
s = J > s ? J : s, z == null || z.debug("[%s] check sig.wave: %j", a.requestId, { ...q, dgThd4Wv: r, svThd4Wv: c, hvThd4Wv: u }), (q == null ? void 0 : q.height) >= r ? T.isDangerous = !0 : (q == null ? void 0 : q.height) >= c ? T.isSevere = !0 : (q == null ? void 0 : q.height) >= u && (T.isHeavy = !0), z == null || z.debug("[%s] check wind: %j", a.requestId, { ...R, dgThd4Wd: l, svThd4Wd: f, hvThd4Wd: b }), (R == null ? void 0 : R.scale) >= l ? (T.isDangerous = !0, delete T.isSevere, delete T.isHeavy) : (R == null ? void 0 : R.scale) > f ? (T.isDangerous || (T.isSevere = !0), delete T.isHeavy) : (R == null ? void 0 : R.scale) === b && !T.isDangerous && !T.isSevere && (T.isHeavy = !0), i += T.isDangerous ? J : 0, o += T.isSevere ? J : 0, n += T.isHeavy ? J : 0;
|
|
695
697
|
}
|
|
696
|
-
return i = Math.round(i * 100) / 100, o = Math.round(o * 100) / 100, n = Math.round(n * 100) / 100, s = Math.round(s), { sample: e, dangerous: i, severe: o, heavy: n, step: s < 3 ? 3 : s, wind: { dgThd4Wd:
|
|
698
|
+
return i = Math.round(i * 100) / 100, o = Math.round(o * 100) / 100, n = Math.round(n * 100) / 100, s = Math.round(s), { sample: e, dangerous: i, severe: o, heavy: n, step: s < 3 ? 3 : s, wind: { dgThd4Wd: l, svThd4Wd: f, hvThd4Wd: b }, sig: { dgThd4Wv: r, svThd4Wv: c, hvThd4Wv: u } };
|
|
697
699
|
}
|
|
698
700
|
}
|
|
699
701
|
const xt = new yt();
|
|
@@ -861,10 +863,10 @@ class O {
|
|
|
861
863
|
} catch (y) {
|
|
862
864
|
C.warn("[%s] meteo2 spot(%j) forecast failed: %s", r.requestId, { ...t, eta: a.utc().format(), source: i }, y);
|
|
863
865
|
}
|
|
864
|
-
const
|
|
866
|
+
const l = O.weatherFactor(e, u), f = O.currentFactor(e.bearing, u == null ? void 0 : u.current, o), b = Math.round((e.speed * 1.943844 + l + f) * 100) / 100;
|
|
865
867
|
c = {
|
|
866
868
|
meteo: { ...u },
|
|
867
|
-
wxFactor:
|
|
869
|
+
wxFactor: l,
|
|
868
870
|
cFactor: f,
|
|
869
871
|
speed: t.velocity && s ? t.velocity : b < 0 ? 1 : b,
|
|
870
872
|
eta: a.utc().format(),
|
|
@@ -896,7 +898,7 @@ class O {
|
|
|
896
898
|
*/
|
|
897
899
|
static async speedLoseInHoursStep(e, t, a, i, o, n, s = "", r = !0, c = !1, u = {}) {
|
|
898
900
|
t.utc();
|
|
899
|
-
const
|
|
901
|
+
const l = t.clone().add(14, "days"), f = [], b = [];
|
|
900
902
|
let y = 0, F = 0, I, p;
|
|
901
903
|
for (let v = 0; v < n.length - 1; v++) {
|
|
902
904
|
let d = n[v];
|
|
@@ -915,17 +917,17 @@ class O {
|
|
|
915
917
|
return d.distanceFromPrevious = F, { etd: t, from: p || d, to: d, next: n.filter((S) => S), wps: f, days: b };
|
|
916
918
|
} else
|
|
917
919
|
d.suspend = 0;
|
|
918
|
-
r = t.isAfter(
|
|
919
|
-
const
|
|
920
|
-
let h = Math.round(
|
|
920
|
+
r = t.isAfter(l) ? !1 : r, d = await O.speedLoseAt(e, d, t, s, 0, r, c, u), p = p || d, d.important && f.push(d), t.isSameOrAfter(a) && (b.push(d), a.add(24, "hour"));
|
|
921
|
+
const m = W.calculateDistance(d, g, !g.gcToPrevious);
|
|
922
|
+
let h = Math.round(m / p.speed * 1e5) / 1e5;
|
|
921
923
|
if (y + h < i) {
|
|
922
924
|
if (y += h, t.add(h, "hour"), delete n[v], C == null || C.debug(
|
|
923
|
-
`[%s] go to %j from %j with ${
|
|
925
|
+
`[%s] go to %j from %j with ${m}nm, and cost ${h} hours`,
|
|
924
926
|
u.requestId,
|
|
925
927
|
{ lat: g.lat, lng: g.lng },
|
|
926
928
|
{ lat: p.lat, lng: p.lng, etd: p.etd }
|
|
927
|
-
), F +=
|
|
928
|
-
I = g, I.eta = t.utc().format(), I.distanceFromPrevious =
|
|
929
|
+
), F += m, n.filter((k) => k).length <= 1) {
|
|
930
|
+
I = g, I.eta = t.utc().format(), I.distanceFromPrevious = m, I.distanceFromStart = Math.round((o + F) * 1e4) / 1e4, f.push(I), delete n[v + 1];
|
|
929
931
|
break;
|
|
930
932
|
}
|
|
931
933
|
} else {
|
|
@@ -961,10 +963,10 @@ class O {
|
|
|
961
963
|
* @param wwc 气象要素
|
|
962
964
|
*/
|
|
963
965
|
static weatherFactor(e, t) {
|
|
964
|
-
var
|
|
966
|
+
var l, f, b, y, F, I, p;
|
|
965
967
|
C == null || C.debug("calculate weather factor via: %j", { ...e, ...t });
|
|
966
968
|
const a = O.blockCoefficient(e.displacement, e.lbp, e.breadthMoulded, e.draught), i = O.froudeNumber(e.speed, e.lbp), o = O.amendFactor(a, i, e.loadCondition);
|
|
967
|
-
let n = Math.abs(e.bearing % 360 - (((
|
|
969
|
+
let n = Math.abs(e.bearing % 360 - (((l = t == null ? void 0 : t.wind) == null ? void 0 : l.degree) % 360 || 0));
|
|
968
970
|
n = n > 180 ? 360 - n : n;
|
|
969
971
|
const s = O.directionFactor(n, (f = t == null ? void 0 : t.wind) == null ? void 0 : f.scale), r = O.vesselTagFactor(e.displacement, e.loadCondition, e.tag, (b = t == null ? void 0 : t.wind) == null ? void 0 : b.scale);
|
|
970
972
|
let c = s * o * r / 100 * e.speed;
|
|
@@ -987,7 +989,7 @@ class O {
|
|
|
987
989
|
*/
|
|
988
990
|
static async analyseInstant(e, t, a, i, o, n = "", s = 0, r = !0, c = !1, u = {}) {
|
|
989
991
|
var K, G, X, Q, Z, $;
|
|
990
|
-
const
|
|
992
|
+
const l = w().valueOf();
|
|
991
993
|
e.lng = _.convertToStdLng(e.lng);
|
|
992
994
|
const { route: f, waypoints: b } = o.points, y = W.calculateSubRoute(e, f);
|
|
993
995
|
if (((K = y[0]) == null ? void 0 : K.length) <= 1)
|
|
@@ -1014,23 +1016,23 @@ class O {
|
|
|
1014
1016
|
wps: []
|
|
1015
1017
|
};
|
|
1016
1018
|
s || (W.calculateRouteDistance(y) / i.speed <= 72 ? s = 3 : s = 6);
|
|
1017
|
-
let
|
|
1019
|
+
let m = W.simplifyRouteToCoordinates(y, v, 0), h = 0, k = 0, S = 0, D = 0;
|
|
1018
1020
|
t = w(t).utc();
|
|
1019
1021
|
const P = t.clone();
|
|
1020
|
-
for (;
|
|
1022
|
+
for (; m.length > 0; ) {
|
|
1021
1023
|
const Y = s - t.hour() % s, B = Math.ceil(t.clone().add(Y, "h").set({ minute: 0, second: 0, millisecond: 0 }).diff(t, "h", !0) * 1e4) / 1e4, j = await O.speedLoseInHoursStep(
|
|
1022
1024
|
p,
|
|
1023
1025
|
t,
|
|
1024
1026
|
P,
|
|
1025
1027
|
B,
|
|
1026
1028
|
h,
|
|
1027
|
-
|
|
1029
|
+
m,
|
|
1028
1030
|
n,
|
|
1029
1031
|
r,
|
|
1030
1032
|
c,
|
|
1031
1033
|
u
|
|
1032
1034
|
);
|
|
1033
|
-
(G = j.from) != null && G.speed && (g.hours.push(j.from), g.wps.push(...j.wps), g.days.push(...j.days)),
|
|
1035
|
+
(G = j.from) != null && G.speed && (g.hours.push(j.from), g.wps.push(...j.wps), g.days.push(...j.days)), m = j == null ? void 0 : j.next, m.length || g.hours.push(j == null ? void 0 : j.to), h += Math.round((((X = j == null ? void 0 : j.to) == null ? void 0 : X.distanceFromPrevious) ?? 0) * 1e4) / 1e4;
|
|
1034
1036
|
}
|
|
1035
1037
|
const N = g.hours;
|
|
1036
1038
|
for (let Y = 0; Y < N.length - 1; Y++) {
|
|
@@ -1054,7 +1056,7 @@ class O {
|
|
|
1054
1056
|
hoursInECA: q,
|
|
1055
1057
|
totalDgoConsInECA: R
|
|
1056
1058
|
}, d.totalFoCons = tt < 0 ? 0 : tt, d.totalDgoCons = at;
|
|
1057
|
-
const et = w().valueOf() -
|
|
1059
|
+
const et = w().valueOf() - l, ot = (($ = g == null ? void 0 : g.hours) == null ? void 0 : $.length) || 1;
|
|
1058
1060
|
return C == null || C.info("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms", u == null ? void 0 : u.requestId, et, ot, Math.round(et / ot * 1e3) / 1e3), d;
|
|
1059
1061
|
}
|
|
1060
1062
|
/**
|
|
@@ -1065,12 +1067,14 @@ class O {
|
|
|
1065
1067
|
* @param vessel 船舶属性 @see VesselAssemble, 注意吃水为船舶实时吃水,非档案中的固定吃水,一般可以从ais获取; 如获取不得,用档案吃水代替
|
|
1066
1068
|
* @param cp { loadCondition, speed } LoadCondition: Ballast or Laden, speed(kts)
|
|
1067
1069
|
* @param route 航路[[[lng, lat]]]
|
|
1070
|
+
* @param waypoints
|
|
1068
1071
|
* @param source 气象数据源,GFS or CMEMES, 默认CMEMS
|
|
1069
1072
|
* @param stepHrs
|
|
1070
1073
|
* @param useMeteo true 启用气象分析
|
|
1071
1074
|
* @param useRouteParam
|
|
1075
|
+
* @param options
|
|
1072
1076
|
*/
|
|
1073
|
-
static async analyseInstantWithThreshed(e, t, a, i, o, n, s, r = "", c = 3, u = !0,
|
|
1077
|
+
static async analyseInstantWithThreshed(e, t, a, i, o, n, s, r = "", c = 3, u = !0, l = !1, f = {}) {
|
|
1074
1078
|
var X, Q, Z, $, Y, B;
|
|
1075
1079
|
const b = w().valueOf();
|
|
1076
1080
|
e.lng = _.convertToStdLng(e.lng);
|
|
@@ -1087,7 +1091,7 @@ class O {
|
|
|
1087
1091
|
return;
|
|
1088
1092
|
const v = s.length ? W.calculateSubWaypoints(e, s) : [];
|
|
1089
1093
|
v.forEach((j) => j.important = !0);
|
|
1090
|
-
let d = W.simplifyRouteToCoordinates(p, v, 0), g = 0,
|
|
1094
|
+
let d = W.simplifyRouteToCoordinates(p, v, 0), g = 0, m = 0, h = 0, k = 0;
|
|
1091
1095
|
const S = {
|
|
1092
1096
|
hours: [],
|
|
1093
1097
|
wps: [],
|
|
@@ -1099,7 +1103,7 @@ class O {
|
|
|
1099
1103
|
const j = c - t.hour() % c;
|
|
1100
1104
|
let V = Math.ceil(t.clone().add(j, "h").set({ minute: 0, second: 0, millisecond: 0 }).diff(t, "h", !0) * 1e4) / 1e4;
|
|
1101
1105
|
V = t.clone().add(V, "h").isSameOrAfter(a) ? a.diff(t, "h", !0) * 1e4 / 1e4 : V;
|
|
1102
|
-
const H = await O.speedLoseInHoursStep(I, t, D, V, g, d, r, u,
|
|
1106
|
+
const H = await O.speedLoseInHoursStep(I, t, D, V, g, d, r, u, l, f);
|
|
1103
1107
|
if ((Q = H.from) != null && Q.speed && (S.hours.push(H.from), H != null && H.wps && S.wps.push(...H.wps), S.days.push(...H.days)), d = H == null ? void 0 : H.next, d.length || S.hours.push(H == null ? void 0 : H.to), g += Math.round((((Z = H == null ? void 0 : H.to) == null ? void 0 : Z.distanceFromPrevious) ?? 0) * 1e4) / 1e4, !V)
|
|
1104
1108
|
break;
|
|
1105
1109
|
}
|
|
@@ -1115,7 +1119,7 @@ class O {
|
|
|
1115
1119
|
const P = S.hours;
|
|
1116
1120
|
for (let j = 0; j < P.length - 1; j++) {
|
|
1117
1121
|
const V = w(P[j + 1].eta).diff(P[j].etd, "hour", !0);
|
|
1118
|
-
|
|
1122
|
+
m += P[j].wxFactor * V, h += P[j].cFactor * V, k += V;
|
|
1119
1123
|
}
|
|
1120
1124
|
const N = S.hours.at(0), A = S.hours.at(-1), x = await W.calculateRangeRoute(N, A, p), T = await W.calculateRangeWaypoints(N, A, p, v), q = {
|
|
1121
1125
|
sample: S,
|
|
@@ -1123,7 +1127,7 @@ class O {
|
|
|
1123
1127
|
// 注意,可能会在first节点Drift,所有采用eta做为初始出发时间
|
|
1124
1128
|
etd: w(N.eta).utc().format(),
|
|
1125
1129
|
eta: w(A == null ? void 0 : A.eta).utc().format(),
|
|
1126
|
-
wxFactor: Math.round(
|
|
1130
|
+
wxFactor: Math.round(m / k * 1e3) / 1e3,
|
|
1127
1131
|
cFactor: Math.round(h / k * 1e3) / 1e3,
|
|
1128
1132
|
avgSpeed: Math.round(((A == null ? void 0 : A.distanceFromStart) || 0) / k * 1e3) / 1e3,
|
|
1129
1133
|
totalHrs: Math.round(k * 1e3) / 1e3,
|
|
@@ -1169,35 +1173,35 @@ class O {
|
|
|
1169
1173
|
c = c < g ? g : c;
|
|
1170
1174
|
}), c = c * 1.3;
|
|
1171
1175
|
const u = w.utc(e.etd).add(c ?? 14, "day");
|
|
1172
|
-
let
|
|
1176
|
+
let l = 1;
|
|
1173
1177
|
for (const d of a) {
|
|
1174
|
-
const g = JSON.parse(JSON.stringify(i.route)),
|
|
1178
|
+
const g = JSON.parse(JSON.stringify(i.route)), m = JSON.parse(JSON.stringify(i.waypoints)), h = await O.analyseInstantWithThreshed(
|
|
1175
1179
|
{ lat: e.lat, lng: e.lng },
|
|
1176
1180
|
e.etd,
|
|
1177
1181
|
u,
|
|
1178
1182
|
t,
|
|
1179
1183
|
d,
|
|
1180
1184
|
g,
|
|
1181
|
-
|
|
1185
|
+
m,
|
|
1182
1186
|
e.meteoVendor,
|
|
1183
1187
|
e.speedStep,
|
|
1184
1188
|
e.useMeteo,
|
|
1185
1189
|
e.useRouteParam,
|
|
1186
1190
|
o
|
|
1187
1191
|
);
|
|
1188
|
-
h && (await O.calculateCost(h, d, e, o), s.push(h), C == null || C.info("[%s][L%d-%d] analyse from %s to %s cost: %j", o.requestId, 1,
|
|
1192
|
+
h && (await O.calculateCost(h, d, e, o), s.push(h), C == null || C.info("[%s][L%d-%d] analyse from %s to %s cost: %j", o.requestId, 1, l, e.etd, u.format(), {
|
|
1189
1193
|
cost: h.cost.total,
|
|
1190
1194
|
hire: h.cost.hire,
|
|
1191
1195
|
bunker: h.cost.bunker,
|
|
1192
1196
|
distance: h.distance,
|
|
1193
1197
|
hours: h.totalHrs,
|
|
1194
1198
|
cp: `${d.speed}/${d.fo}/${d.dgo}`
|
|
1195
|
-
})),
|
|
1199
|
+
})), l++;
|
|
1196
1200
|
}
|
|
1197
1201
|
s.sort((d, g) => d.cost.total - g.cost.total);
|
|
1198
1202
|
const f = s.at(0), b = s.at(1), y = [];
|
|
1199
1203
|
if (y.push({ combined: !1, speeds: [f], cost: (p = f.cost) == null ? void 0 : p.total }), b) {
|
|
1200
|
-
const d = f.cost.cp, g = b.cost.cp,
|
|
1204
|
+
const d = f.cost.cp, g = b.cost.cp, m = w(f.eta), h = w(f.etd), k = m.diff(h, "days", !0);
|
|
1201
1205
|
let S = Math.ceil(k / 2);
|
|
1202
1206
|
S = S > 7 ? 7 : S < e.alterStep ? e.alterStep : S;
|
|
1203
1207
|
let D = 2, P = { combined: !1, speeds: [b], cost: (v = b.cost) == null ? void 0 : v.total }, N;
|
|
@@ -1224,15 +1228,15 @@ class O {
|
|
|
1224
1228
|
*/
|
|
1225
1229
|
static async combinedAnalyse(e, t, a, i, o, n, s = {}) {
|
|
1226
1230
|
s.counter = 1, C == null || C.info("[%s][L%d] analyse with alternate cp in every %d days", s.requestId, s.level, n);
|
|
1227
|
-
const r = await O.alternateAnalyse(e, t, a, i, 0, o, n, s), c = r.reduce((g,
|
|
1231
|
+
const r = await O.alternateAnalyse(e, t, a, i, 0, o, n, s), c = r.reduce((g, m) => g + m.cost.total, 0), u = r.reduce((g, m) => g + m.cost.hire, 0), l = r.reduce((g, m) => g + m.cost.bunker, 0), f = r.reduce((g, m) => g + m.distance, 0), b = r.reduce((g, m) => g + m.totalHrs, 0);
|
|
1228
1232
|
C == null || C.info("[%s][L%d] cost with cpa/cpb turn: %j", s.requestId, s.level, {
|
|
1229
1233
|
cost: c,
|
|
1230
1234
|
hire: u,
|
|
1231
|
-
bunker:
|
|
1235
|
+
bunker: l,
|
|
1232
1236
|
distance: f,
|
|
1233
1237
|
hours: b
|
|
1234
1238
|
});
|
|
1235
|
-
const y = await O.alternateAnalyse(e, t, a, i, 1, o, n, s), F = y.reduce((g,
|
|
1239
|
+
const y = await O.alternateAnalyse(e, t, a, i, 1, o, n, s), F = y.reduce((g, m) => g + m.cost.total, 0), I = y.reduce((g, m) => g + m.cost.hire, 0), p = y.reduce((g, m) => g + m.cost.bunker, 0), v = y.reduce((g, m) => g + m.distance, 0), d = y.reduce((g, m) => g + m.totalHrs, 0);
|
|
1236
1240
|
return C == null || C.info("[%s][L%d] cost with cpb/cpa turn: %j", s.requestId, s.level, {
|
|
1237
1241
|
cost: F,
|
|
1238
1242
|
hire: I,
|
|
@@ -1255,7 +1259,7 @@ class O {
|
|
|
1255
1259
|
static async alternateAnalyse(e, t, a, i, o, n, s, r = {}) {
|
|
1256
1260
|
var f, b;
|
|
1257
1261
|
let c = w.utc(e.etd);
|
|
1258
|
-
const u = { lat: e.lat, lng: e.lng },
|
|
1262
|
+
const u = { lat: e.lat, lng: e.lng }, l = [];
|
|
1259
1263
|
for (; c.isBefore(a); ) {
|
|
1260
1264
|
const y = c.clone().utc().add(s, "day"), F = JSON.parse(JSON.stringify(n.route)), I = JSON.parse(JSON.stringify(n.waypoints)), p = i[o], v = await O.analyseInstantWithThreshed(
|
|
1261
1265
|
u,
|
|
@@ -1289,11 +1293,11 @@ class O {
|
|
|
1289
1293
|
)), r.counter = r.counter + 1;
|
|
1290
1294
|
const d = (b = (f = v == null ? void 0 : v.sample) == null ? void 0 : f.hours) == null ? void 0 : b.at(-1);
|
|
1291
1295
|
if (d)
|
|
1292
|
-
u.lat = d.lat, u.lng = d.lng, c = w(d.eta),
|
|
1296
|
+
u.lat = d.lat, u.lng = d.lng, c = w(d.eta), l.push(v), o = o ? 0 : 1;
|
|
1293
1297
|
else
|
|
1294
1298
|
break;
|
|
1295
1299
|
}
|
|
1296
|
-
return
|
|
1300
|
+
return l;
|
|
1297
1301
|
}
|
|
1298
1302
|
/**
|
|
1299
1303
|
* 计算Speed的cost
|
|
@@ -1320,7 +1324,7 @@ class O {
|
|
|
1320
1324
|
*
|
|
1321
1325
|
*/
|
|
1322
1326
|
static async calculateECA(e, t, a = {}) {
|
|
1323
|
-
var r, c, u,
|
|
1327
|
+
var r, c, u, l;
|
|
1324
1328
|
const i = await W.intersectInECA((e == null ? void 0 : e.route) || []);
|
|
1325
1329
|
let o = 0, n = 0, s = 0;
|
|
1326
1330
|
(c = (r = e == null ? void 0 : e.sample) == null ? void 0 : r.wps) == null || c.forEach((f) => {
|
|
@@ -1328,7 +1332,7 @@ class O {
|
|
|
1328
1332
|
});
|
|
1329
1333
|
for (const f of i) {
|
|
1330
1334
|
o += f.distance;
|
|
1331
|
-
const b = await W.deadReckoningTime((u = f.waypoints) == null ? void 0 : u.at(0), e.sample.wps), y = await W.deadReckoningTime((
|
|
1335
|
+
const b = await W.deadReckoningTime((u = f.waypoints) == null ? void 0 : u.at(0), e.sample.wps), y = await W.deadReckoningTime((l = f.waypoints) == null ? void 0 : l.at(-1), e.sample.wps);
|
|
1332
1336
|
f.in = b, f.out = y, f.totalHrs = _.roundPrecision((y.positionTime - b.positionTime) / 3600, 3), f.totalDgoCons = _.roundPrecision(t.fo / 24 * f.totalHrs, 3), n += f.totalHrs, s += f.totalDgoCons;
|
|
1333
1337
|
}
|
|
1334
1338
|
return o = _.roundPrecision(o, 3), n = _.roundPrecision(n, 3), s = _.roundPrecision(s, 3), {
|
|
@@ -1349,28 +1353,28 @@ class O {
|
|
|
1349
1353
|
hours: [],
|
|
1350
1354
|
wps: [],
|
|
1351
1355
|
days: []
|
|
1352
|
-
}, i = e.reduce((
|
|
1356
|
+
}, i = e.reduce((m, h) => m + h.distance, 0), o = e.reduce((m, h) => {
|
|
1353
1357
|
var k;
|
|
1354
|
-
return
|
|
1355
|
-
}, 0), n = e.reduce((
|
|
1358
|
+
return m + (((k = h.extend) == null ? void 0 : k.distanceInECA) || 0);
|
|
1359
|
+
}, 0), n = e.reduce((m, h) => m + h.totalHrs, 0), s = e.reduce((m, h) => {
|
|
1356
1360
|
var k;
|
|
1357
|
-
return
|
|
1358
|
-
}, 0), r = e.reduce((
|
|
1361
|
+
return m + (((k = h.extend) == null ? void 0 : k.hoursInECA) || 0);
|
|
1362
|
+
}, 0), r = e.reduce((m, h) => {
|
|
1359
1363
|
var k;
|
|
1360
|
-
return
|
|
1361
|
-
}, 0), c = e.reduce((
|
|
1364
|
+
return m + (((k = h.extend) == null ? void 0 : k.totalDgoConsInECA) || 0);
|
|
1365
|
+
}, 0), c = e.reduce((m, h) => m + h.wxFactor * h.totalHrs / n, 0), u = e.reduce((m, h) => m + h.cFactor * h.totalHrs / n, 0), l = e.reduce((m, h) => m + h.totalFoCons, 0), f = e.reduce((m, h) => m + h.totalDgoCons, 0), b = e.reduce((m, h) => m + h.cost.total, 0), y = e.reduce((m, h) => m + h.cost.hire, 0), F = e.reduce((m, h) => m + h.cost.bunker, 0), I = [], p = [];
|
|
1362
1366
|
let v;
|
|
1363
|
-
for (const
|
|
1364
|
-
p.push(...((d =
|
|
1365
|
-
const h =
|
|
1367
|
+
for (const m of e) {
|
|
1368
|
+
p.push(...((d = m.extend) == null ? void 0 : d.eca) || []);
|
|
1369
|
+
const h = m.sample.hours, k = m.sample.wps, S = m.sample.days, D = h.at(0);
|
|
1366
1370
|
v && (D.distanceFromPrevious = v.distanceFromPrevious, D.distanceFromStart = v.distanceFromStart, h.forEach((x, T) => {
|
|
1367
1371
|
T && (x.distanceFromStart = x.distanceFromStart + v.distanceFromStart);
|
|
1368
1372
|
}), k.at(0).distanceFromPrevious = v.distanceFromPrevious, k.at(0).distanceFromStart = v.distanceFromStart, k.forEach((x, T) => {
|
|
1369
1373
|
T && (x.distanceFromStart = x.distanceFromStart + v.distanceFromStart);
|
|
1370
1374
|
}), S.at(0).distanceFromPrevious = v.distanceFromPrevious, S.at(0).distanceFromStart = v.distanceFromStart, S.forEach((x, T) => {
|
|
1371
1375
|
T && (x.distanceFromStart = x.distanceFromStart + v.distanceFromStart);
|
|
1372
|
-
})), D.cp =
|
|
1373
|
-
const P = [
|
|
1376
|
+
})), D.cp = m.cost.cp;
|
|
1377
|
+
const P = [m.etd, m.eta], N = I.findIndex((x) => x.id === D.cp.id);
|
|
1374
1378
|
N === -1 ? (D.cp.segment = [P], I.push(D.cp)) : I[N].segment.push(P), h.forEach((x) => {
|
|
1375
1379
|
var q;
|
|
1376
1380
|
((q = a.hours) == null ? void 0 : q.findIndex((R) => R.eta === x.eta)) === -1 && a.hours.push(x);
|
|
@@ -1384,14 +1388,14 @@ class O {
|
|
|
1384
1388
|
const A = (g = a.wps) == null ? void 0 : g.findIndex((x) => x.eta === D.eta);
|
|
1385
1389
|
A === -1 ? a.wps.push(D) : a.wps[A] = D, v = h.at(-1);
|
|
1386
1390
|
}
|
|
1387
|
-
return a.wps.sort((
|
|
1388
|
-
w(
|
|
1389
|
-
}), a.wps.forEach((
|
|
1391
|
+
return a.wps.sort((m, h) => {
|
|
1392
|
+
w(m.etd).unix() - w(h.etd).unix();
|
|
1393
|
+
}), a.wps.forEach((m, h) => {
|
|
1390
1394
|
const k = a.wps[h - 1];
|
|
1391
1395
|
if (k) {
|
|
1392
|
-
const S =
|
|
1393
|
-
|
|
1394
|
-
const N = W.calculateBearing(k,
|
|
1396
|
+
const S = m.distanceFromStart - (k.distanceFromStart || 0), D = w(m.eta || m.etd).diff(w(k.etd || k.eta), "hour", !0), P = Math.round(S / D * 100) / 100;
|
|
1397
|
+
m.avgSpd = P;
|
|
1398
|
+
const N = W.calculateBearing(k, m);
|
|
1395
1399
|
k.bearing = N;
|
|
1396
1400
|
}
|
|
1397
1401
|
}), {
|
|
@@ -1407,7 +1411,7 @@ class O {
|
|
|
1407
1411
|
avgSpeed: Math.round(i / n * 1e3) / 1e3,
|
|
1408
1412
|
wxFactor: Math.round(c * 1e3) / 1e3,
|
|
1409
1413
|
cFactor: Math.round(u * 1e3) / 1e3,
|
|
1410
|
-
totalFoCons: Math.round(
|
|
1414
|
+
totalFoCons: Math.round(l * 1e3) / 1e3,
|
|
1411
1415
|
totalDgoCons: Math.round(f * 1e3) / 1e3,
|
|
1412
1416
|
cost: {
|
|
1413
1417
|
total: Math.round(b * 1e3) / 1e3,
|
package/dist/index.umd.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(q,A){typeof exports=="object"&&typeof module<"u"?A(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"],A):(q=typeof globalThis<"u"?globalThis:q||self,A(q["idm-plugin-vessel"]={},q.got,q["@log4js-node/log4js-api"],q.moment,q["@idm-plugin/geo2"],q["@idm-plugin/meteo2"],q["@idm-plugin/meteo"]))})(this,function(q,A,U,g,H,ft,nt){"use strict";var It=Object.defineProperty;var St=(q,A,U)=>A in q?It(q,A,{enumerable:!0,configurable:!0,writable:!0,value:U}):q[A]=U;var K=(q,A,U)=>(St(q,typeof A!="symbol"?A+"":A,U),U);let p;try{p=U.getLogger("vessel")}catch{}finally{}class G{parseStatus(s){let t,a;switch(s){case 0:t="在航(主机推动)",a="Underway Using Engine";break;case 1:t="锚泊",a="Anchored";break;case 2:t="失控",a="Not under command";break;case 3:t="操纵受限",a="Limited airworthiness";break;case 4:t="吃水受限",a="Limited by ship's draft";break;case 5:t="靠泊",a="Mooring";break;case 6:t="搁浅",a="Stranded";break;case 7:t="捕捞作业",a="Engaged in fishing";break;case 8:t="靠帆船提供动力",a="Sailing";break;default:t="未定义",a="Undefined"}return{labelCn:t,labelEn:a}}}class mt extends G{constructor(t,a){super();K(this,"clientId");K(this,"clientSecret");K(this,"token");this.clientId=t,this.clientSecret=a}async authToken(t={}){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 A.post(a,i).json();p==null||p.info("[%s] fetch access token from: %s - %j",t.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:g().utc().format()})}async checkToken(t={}){var a;return(!this.token||g().diff(g(this.token.issuedAt),"seconds")>(((a=this.token)==null?void 0:a.expiresIn)||0)-300)&&await this.authToken(t),this.token}async suggest(t,a={}){var e,c;await this.checkToken(a);const i="https://market.myvessel.cn/sdc/v1/mkt/vessels/fuzzy",o={headers:{Authorization:`${(e=this.token)==null?void 0:e.tokenType} ${(c=this.token)==null?void 0:c.accessToken}`},json:{kw:t,recordNum:a.ps||10}};p==null||p.info("[%s] fetch suggest vessels from: %s - %j",a.requestId,i,o);const n=await A.post(i,o).json();return n.code?(p==null||p.warn("[%s] fetch suggest vessels failed: %j",a.requestId,{message:n.message,status:n.status,code:n.code}),[]):n.data.map(u=>({mmsi:u.mmsi,name:u.nameEn,nameCn:u.nameCn,imo:Number.isNaN(u.imo)?null:Number(u.imo),callSign:u.callsign,type:u.vesselTypeNameEn,flagName:u.flagCtry,vendor:"myvessel",raw:u}))}async search(t,a={}){var r,u;await this.checkToken(a);const i=/^\d{7}$/.test(t.toString()),o=i?"https://market.myvessel.cn/sdc/v1/mkt/vessels/detail/imo":"https://market.myvessel.cn/sdc/v1/mkt/vessels/detail/mmsi",n=i?{imo:t}:{mmsi:t},e={headers:{Authorization:`${(r=this.token)==null?void 0:r.tokenType} ${(u=this.token)==null?void 0:u.accessToken}`},searchParams:n};p==null||p.info("[%s] fetch vessel from: %s - %j",a.requestId,o,e);const c=await A.get(o,e).json();if(c.status!==200)return p==null||p.warn("[%s] fetch suggest vessels failed: %j",a.requestId,{message:c.message,status:c.status,code:c.code}),{};{const f=c.data;return{mmsi:f.mmsi,imo:Number.isNaN(f.imo)?null:Number(f.imo),callSign:f.callsign,name:f.nameEn,nameCn:f.nameCn,type:f.vesselTypeNameEn,flagName:f.flagCtry,clasz:f.classSociety,dateOfBuild:f.buildYearMonth,deadweight:f.dwt,grossTonnage:f.grt,netTonnage:f.net,teu:f.teu,length:f.length,breadth:f.width,height:f.height,draught:f.draught,speed:f.speed,passengerCapacity:f.passengercapacity,vendor:"myvessel",raw:f}}}async archives(t,a={}){var e,c;await this.checkToken(a);const i="https://svc.data.myvessel.cn/sdc/v1/ship/info/batch",o={headers:{Authorization:`${(e=this.token)==null?void 0:e.tokenType} ${(c=this.token)==null?void 0:c.accessToken}`},json:{mmsiList:typeof t=="number"?[t]:t}};p==null||p.info("[%s] fetch vessel archive from: %s - %j",a.requestId,i,o);const n=await A.post(i,o).json();return n.status!==200?(p==null||p.warn("[%s] fetch vessel archive failed: %j",a.requestId,{message:n.message,status:n.status,code:n.code}),{}):n.data}async realTimePosition(t,a={}){var c,r;await this.checkToken(a);const i="https://svc.data.myvessel.cn/sdc/v1/vessels/status/location/unit",o={headers:{Authorization:`${(c=this.token)==null?void 0:c.tokenType} ${(r=this.token)==null?void 0:r.accessToken}`},searchParams:{mmsi:t}};p==null||p.info("[%s] fetch realtime position from: %s - %j",a.requestId,i,o);const n=await A.get(i,o).json();if(n.code)return p==null||p.warn("[%s] fetch realtime position failed: %j",a.requestId,{message:n.message,status:n.status,code:n.code}),n;const e=n.data;for(const u in e)!isNaN(e[u])&&Number(e[u])!==1/0&&(e[u]=Number(e[u]));if(e){const u=g(`${e.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return{mmsi:e.mmsi,name:e.vesselName||e.aisVesselName,imo:e.imo,callSign:e.callsign||e.aisCallSign,lat:e.lat,lng:e.lon,length:e.length,width:e.width,draught:e.currDraught,sog:e.sog,cog:e.cog,hdg:e.hdg,rot:e.rot,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(e.eta)?g.utc(e.eta).format():void 0,destination:e.dest,positionTime:u.unix(),status:e.status,labelCn:e.statusNameCn,labelEn:e.statusNameEn,vesselType:e.vesselTypeNameEn,flag:e.flagCtryNameEn,clasz:e.classSociety,build:e.buildYear,dwt:e.dwt,grt:e.grt,net:e.net,method:"position",vendor:"myVessel",utc:u.utc().format()}}else return{}}async trajectory(t,a,i,o,n=!0,e={}){await this.checkToken(e);const c=await this.realTimePosition(t,e),r=g(a),u=g(i),f=[];for(;u.diff(r,"day",!0)>30;)await this.trajectoryIn30Day(t,r,r.clone().add(30,"day"),c,o,f,e),r.add(30,"day");return await this.trajectoryIn30Day(t,r,u,c,o,f,e),f}async trajectoryIn30Day(t,a,i,o,n,e,c={}){var y,j,S,w,v;const r="https://svc.data.myvessel.cn/sdc/v1/vessels/status/track",u={headers:{Authorization:`${(y=this.token)==null?void 0:y.tokenType} ${(j=this.token)==null?void 0:j.accessToken}`},json:{mmsi:t,startTime:a.utcOffset(8).format("YYYY-MM-DD HH:mm:ss"),endTime:i.utcOffset(8).format("YYYY-MM-DD HH:mm:ss")}};p==null||p.info("[%s] fetch trajectory from: %s - %j",c.requestId,r,u);const f=await A.post(r,u).json();if(f.code)return p==null||p.warn("[%s] fetch trajectory failed: %j",c.requestId,r,{message:f.message,status:f.status,code:f.code}),f;let m=-1;const b=g(`${(w=(S=f.data)==null?void 0:S[0])==null?void 0:w.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return(v=f.data)==null||v.forEach(d=>{for(const Y in d)!isNaN(d[Y])&&Number(d[Y])!==1/0&&(d[Y]=Number(d[Y]));const M=g(`${d.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00"),h=d.status,{labelCn:l,labelEn:k}=this.parseStatus(h),C={mmsi:d.mmsi,imo:o==null?void 0:o.imo,lat:d.lat,lng:d.lon,sog:d.sog,cog:d.cog,hdg:d.hdg,draught:d.draught,status:h,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(d.eta)?g(`${d.eta} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00").utc().format():void 0,destination:d.dest,positionTime:M.unix(),labelCn:l,labelEn:k,method:"trajectory",vendor:"myVessel",utc:M.utc().format()},x=Math.floor(M.diff(b,"minute",!0)/(n||1));x!==m&&(m=x,e.push(C))}),e}}class yt extends G{constructor(t){super();K(this,"token");this.token=t}async realTimePosition(t,a={}){const i="https://api.hifleet.com/position/position/get/token",o={searchParams:{mmsi:t,usertoken:this.token}},n=await A.post(i,o).json();p==null||p.info("[%s] fetch realtime position from: %s - %j",a.requestId,i,o);const e=n==null?void 0:n.list;if(!e)return p==null||p.warn("[%s] fetch realtime position failed: %j",a.requestId,i,n),n;for(const b in e)!isNaN(e[b])&&Number(e[b])!==1/0&&(e[b]=Number(e[b]));e.status=e.sp>3?0:1;const c=e.status,{labelCn:r,labelEn:u}=this.parseStatus(c),f=g(`${e.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return{mmsi:e.m,name:e.n,imo:e.imonumber,callSign:e.callsign,lat:Math.round(e.la/60*1e5)/1e5,lng:Math.round(e.lo/60*1e5)/1e5,length:e.l,width:e.w,draught:e.draught,sog:e.sp,cog:e.co,hdg:e.h,rot:isNaN(e.rot)?0:e.rot,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(e.eta)?g.utc(e.eta).format():void 0,destination:e.destination,vesselType:e.type,dwt:e.dwt,build:e.buildyear,flag:e.fn,positionTime:f.unix(),utc:f.utc().format(),status:c,labelCn:r,labelEn:u,method:"position",vendor:"hifleet"}}async search(t,a={}){let i="https://www.hifleet.com/hifleetapi/searchVesselOL.do";const o={searchParams:{keyword:t},headers:{Referer:"https://www.hifleet.com",Origin:"https://www.hifleet.com",Host:"www.hifleet.com"}};let n=await A.post(i,o).json();p==null||p.info("[%s] fetch vessel props from: %s - %j",a.requestId,i,o),n instanceof Array&&(n=n[0]);for(const c in n)!isNaN(n[c])&&Number(n[c])!==1/0&&(n[c]=Number(n[c]));const e={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 A.post(i,o).json(),p==null||p.info("[%s] search vessel dead weight from: %s - %j",a.requestId,i,o),n instanceof Array&&(n=n[0]),n&&(e.deadweight=Number(n.dwt)),e}async suggest(t,a={}){const i="https://www.hifleet.com/hifleetapi/getShipSuggest.do",o={searchParams:{q:t},headers:{Referer:"https://www.hifleet.com",Origin:"https://www.hifleet.com",Host:"www.hifleet.com"}},n=await A.post(i,o).json();p==null||p.info("[%s] suggest vessel props from: %s - %j",a.requestId,i,o);const e=[];for(const c of n)e.push({mmsi:!c.mmsi||isNaN(c.mmsi)?null:Number(c.mmsi),name:c.name,callSign:c.callsign,imo:!c.imo||isNaN(c.imo)?null:Number(c.imo),score:c._score});return e.sort((c,r)=>r.score-c.score),e}async trajectory(t,a,i,o,n=!0,e={}){var d,M,h;const c=await this.realTimePosition(t,e);let r=g(a);const u=g(i),f=g();if(n){let l=u.diff(r,"d",!0);l<0?r=u.clone().subtract(40,"d"):l<30?r.subtract(10,"d"):l<60?r.subtract(5,"d"):r=u.clone().subtract(80,"d"),l=f.diff(u,"d",!0),u.add(l>10?240:l*24,"h")}const m={searchParams:{endtime:u.utcOffset("+8:00").format("YYYY-MM-DD HH:mm:ss"),starttime:r.utcOffset("+8:00").format("YYYY-MM-DD HH:mm:ss"),mmsi:t,usertoken:this.token}},b="https://api.hifleet.com/position/trajectory/nocompressed/withstatic/token",y=await A.get(b,m).json();p==null||p.info("[%s] fetch trajectory from: %s - %j",e.requestId,b,m);let j;y&&(j=((M=(d=y.ships)==null?void 0:d.offors)==null?void 0:M.ship)||[],j.length||p==null||p.warn("[%s] fetch trajectory failed: %j",e.requestId,y));const S=[];let w=-1;const v=g(`${(h=j==null?void 0:j[0])==null?void 0:h.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");for(const l of j){for(const L in l)!isNaN(l[L])&&Number(l[L])!==1/0&&(l[L]=Number(l[L]));const k=g(`${l.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");l.status=l.sp>4?0:1;const{labelEn:C,labelCn:x}=this.parseStatus(l.status),Y={mmsi:l.m,name:l.n,imo:c==null?void 0:c.imo,lat:l.la,lng:l.lo,draught:l.draught,sog:l.sp,cog:l.co,hdg:l.hdg,positionTime:k.unix(),utc:k.utc().format(),status:l.status,labelCn:x,labelEn:C,method:"trajectory",vendor:"hifleet"},T=Math.floor(k.diff(v,"minute",!0)/(o||1));T!==w&&(w=T,S.push(Y))}return S}}class pt extends G{constructor(t){super();K(this,"token");this.token=t}async realTimePosition(t,a={}){const i={searchParams:{id:t,k:this.token,enc:1}},o="https://api.shipxy.com/apicall/GetSingleShip",n=await A.get(o,i).json();if(p==null||p.info("[%s] fetch realtime position from: %s - %j",a.requestId,o,i),(n==null?void 0:n.status)!==0)return n;const e=n.data[0];for(const m in e)!isNaN(e[m])&&Number(e[m])!==1/0&&(e[m]=Number(e[m]));const{labelCn:c,labelEn:r}=await this.parseStatus(e.navistat),u=g.unix(e.lasttime);return{mmsi:e.ShipID,name:e.name,imo:e.imo,callSign:e.callsign,lat:Math.round(e.lat/1e6*1e5)/1e5,lng:Math.round(e.lon/1e6*1e5)/1e5,length:Math.round(e.length/10*100)/100,width:Math.round(e.width/10*100)/100,draught:Math.round(e.draught/1e3*100)/100,sog:Math.round(e.sog*3600/1e3/1852*100)/100,cog:Math.round(e.cog/100*100)/100,hdg:Math.round(e.hdg/100*100)/100,rot:Math.round(e.rot/100*100)/100,positionTime:e.lasttime,utc:u.utc().format(),status:e.navistat,labelEn:r,labelCn:c,method:"position",vendor:"shipxy"}}async trajectory(t,a,i,o,n=!0,e={}){var v;const c=await this.realTimePosition(t,e),r=g(a),u=g(i),f="https://api.shipxy.com/apicall/GetShipTrack",m={searchParams:{id:t,k:this.token,enc:1,cut:0,btm:r.unix(),etm:u.unix()}},b=await A.get(f,m).json();if(p==null||p.info("[%s] fetch trajectory from: %s - %j",e.requestId,f,m),(b==null?void 0:b.status)!==0)return b;const y=b==null?void 0:b.points,j=[],S=g.unix((v=y[0])==null?void 0:v.utc);let w=-1;for(const d of y){const M=g.unix(d.utc),h={imo:c==null?void 0:c.imo,mmsi:t,sog:Math.round(d.sog*3600/1e3/1852*100)/100,cog:Math.round(d.cog/100*100)/100,lat:Math.round(d.lat/1e6*1e5)/1e5,lng:Math.round(d.lon/1e6*1e5)/1e5,positionTime:M.unix(),utc:M.utc().format(),method:"trajectory",vendor:"shipxy"},l=Math.floor(M.diff(S,"minute",!0)/(o||1));l!==w&&(w=l,j.push(h))}return j}}class Mt extends G{constructor(t){super();K(this,"token");this.token=t}async getShipId(t,a={}){const i={headers:{appKey:this.token},json:{mmsiList:t}},o="https://api3.myships.com/sp/ships/getShipIdByMMSI",n=await A.post(o,i).json();return p==null||p.info("[%s] fetch ship id from: %s - %j",a.requestId,o,i),n.code!=="0"?n:n.data[0].shipId}async getShipInfo(t,a={}){const i={headers:{appKey:this.token},json:{shipId:t}},o="https://api3.myships.com/sp/ships/aissta",n=await A.post(o,i).json();if(p==null||p.info("[%s] fetch ship info from: %s - %j",a.requestId,o,i),n.code!=="0")return n;const e=n.data;let c=e.imo;return t==="407170"&&(c="9198379",p==null||p.warn("[%s] ship(%s) imo error: %s, should be %s",a.requestId,t,e.imo,c)),{mmsi:e.mmsi,name:e.shipnameEn,imo:c,callSign:e.callSign,length:e.length,width:e.breadth,draught:(e.draught||100)/10}}async realTimePosition(t,a={}){const i=await this.getShipId(t,a),o=await this.getShipInfo(i,a),n={headers:{appKey:this.token},json:{shipId:i}},e="https://api3.myships.com/sp/ships/position/latest",c=await A.post(e,n).json();p==null||p.info("[%s] fetch realtime position from: %s - %j",a.requestId,e,n);const r=c.data[0];for(const y in r)!isNaN(r[y])&&Number(r[y])!==1/0&&(r[y]=Number(r[y]));const{labelCn:u,labelEn:f}=await this.parseStatus(r.aisNavStatus),m=g.unix(r.posTime);return{...o,mmsi:t,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:m.utc().format(),status:r.aisNavStatus,labelEn:f,labelCn:u,method:"position",vendor:"myship"}}async trajectory(t,a,i,o,n=!0,e={}){const c=g(a),r=g(i),u=await this.getShipId(t),f=await this.getShipInfo(u),m=[];for(;r.diff(c,"day",!0)>30;)await this.trajectoryIn30Day(u,c.unix(),c.add(30,"day").unix(),f,t,o,m);return await this.trajectoryIn30Day(u,c.unix(),r.unix(),f,t,o,m),m}async trajectoryIn30Day(t,a,i,o,n,e,c,r={}){var S;const u={headers:{appKey:this.token},json:{shipId:t,startTime:a,endTime:i}},f="https://api3.myships.com/sp/ships/position/history",m=await A.post(f,u).json();if(p==null||p.info("[%s] fetch trajectory from: %s - %j",r.requestId,f,u),m.code!=="0")return p==null||p.warn("[%s] invoke myship trajectory failed: %j",r.requestId,m),m;const b=m.data;for(const w in b)!isNaN(b[w])&&Number(b[w])!==1/0&&(b[w]=Number(b[w]));const y=g.unix((S=b[0])==null?void 0:S.posTime);let j=-1;for(const w of b){const v=g.unix(w.posTime),d={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"},M=Math.floor(v.diff(y,"minute",!0)/(e||1));M!==j&&(j=M,c.push(d))}return c}}let z;try{z=U.getLogger("vessel")}catch{}finally{}var ct=(D=>(D.NOTICE="NOTICE",D.WARN="WARN",D.HEAVY="HEAVY",D.SEVERE="SEVERE",D.ERROR="ERROR",D.FATAL="FATAL",D))(ct||{});class dt{parsePrinciple(s,t={}){var e,c,r;z==null||z.debug("[%s] parse rule: %s",t.requestId,s);const a=new RegExp("(?<=\\[)(.+)(?=])","g"),i=s.match(a)?(e=s.match(a))==null?void 0:e[0]:void 0,o=i==null?void 0:i.split(";");if(!o)return;const n={};for(let u=0;u<(o==null?void 0:o.length);u++){const f=(r=(c=o[u].match(a))==null?void 0:c[0])==null?void 0:r.split("],");if(u===0&&!f)n.scope=o[0];else if(f)for(let m=0,b=f.length;m<b;m++){const y=this.parseRule(f[m]);y&&(n[y.level]?y.key?n[y.level][y==null?void 0:y.key]=y:n[y.level]=y:y.key?n[y.level]={[y==null?void 0:y.key]:y}:n[y.level]=y)}}return n}parseRule(s,t={}){var n;z==null||z.debug("[%s] parse rule: %s",t.requestId,s),s=s.startsWith("[")?s:`[${s}`,s=s.endsWith("]")?s:`${s}]`;const a=new RegExp("(?<=\\[)(.+?)(?=])","g"),i=(n=s==null?void 0:s.match(a))==null?void 0:n[0],o=i==null?void 0:i.split(",");if(o){let e=o[3]==="Number.MAX_VALUE"?100:Number(o[3]);return e=isNaN(e)?1:e,{operator:o[0],number:Number.isNaN(Number(o[1]))?o[1]:Number(o[1]),level:o[2],time:e,key:o[4]}}}checkWeather(s,t,a={}){var y,j,S,w,v,d,M,h,l,k,C,x,Y,T,L;let i=0,o=0,n=0,e=0;const c=Math.round(((j=(y=t==null?void 0:t.SEVERE)==null?void 0:y.sigWave)==null?void 0:j.number)*1.6*100)/100,r=(w=(S=t==null?void 0:t.SEVERE)==null?void 0:S.sigWave)==null?void 0:w.number,u=(d=(v=t==null?void 0:t.HEAVY)==null?void 0:v.sigWave)==null?void 0:d.number,f=Math.round((((h=(M=t==null?void 0:t.SEVERE)==null?void 0:M.wind)==null?void 0:h.number)+2)*100)/100,m=(k=(l=t==null?void 0:t.SEVERE)==null?void 0:l.wind)==null?void 0:k.number,b=(x=(C=t==null?void 0:t.HEAVY)==null?void 0:C.wind)==null?void 0:x.number;for(let N=0;N<(s==null?void 0:s.length);N++){const E=s[N],P=(T=(Y=E==null?void 0:E.meteo)==null?void 0:Y.wave)==null?void 0:T.sig,V=(L=E==null?void 0:E.meteo)==null?void 0:L.wind,J=N?g(E.eta).diff(g(s[N-1].eta),"hour",!0):0;e=J>e?J:e,z==null||z.debug("[%s] check sig.wave: %j",a.requestId,{...P,dgThd4Wv:c,svThd4Wv:r,hvThd4Wv:u}),(P==null?void 0:P.height)>=c?E.isDangerous=!0:(P==null?void 0:P.height)>=r?E.isSevere=!0:(P==null?void 0:P.height)>=u&&(E.isHeavy=!0),z==null||z.debug("[%s] check wind: %j",a.requestId,{...V,dgThd4Wd:f,svThd4Wd:m,hvThd4Wd:b}),(V==null?void 0:V.scale)>=f?(E.isDangerous=!0,delete E.isSevere,delete E.isHeavy):(V==null?void 0:V.scale)>m?(E.isDangerous||(E.isSevere=!0),delete E.isHeavy):(V==null?void 0:V.scale)===b&&!E.isDangerous&&!E.isSevere&&(E.isHeavy=!0),i+=E.isDangerous?J:0,o+=E.isSevere?J:0,n+=E.isHeavy?J:0}return i=Math.round(i*100)/100,o=Math.round(o*100)/100,n=Math.round(n*100)/100,e=Math.round(e),{sample:s,dangerous:i,severe:o,heavy:n,step:e<3?3:e,wind:{dgThd4Wd:f,svThd4Wd:m,hvThd4Wd:b},sig:{dgThd4Wv:c,svThd4Wv:r,hvThd4Wv:u}}}}const bt=new dt;let I;try{I=U.getLogger("vessel")}catch{}finally{}const vt=new ft.MeteoHelper2("",!0);var ut=(D=>(D.common="common",D.container="container",D.tugs="tugs",D))(ut||{}),lt=(D=>(D.Ballast="Ballast",D.Laden="Laden",D))(lt||{}),ht=(D=>(D.Cp="CP",D.Perf="Basis",D.Instruct="Other",D))(ht||{});class W{static blockCoefficient(s,t,a,i){let o=Math.round(s/(t*a*i)*100)/100;o=o<.55?.55:o>.85?.85:o;const n=[.55,.6,.65,.7,.75,.8,.85],e=n.map(c=>Math.abs(c-o));return n[e.indexOf(Math.min(...e))]}static froudeNumber(s,t,a=9.8){let i=Math.round(Math.sqrt(s*s/(a*t))*100)/100;return i=i<.05?.05:i>.3?.3:i,i}static amendFactor(s,t,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]}[s];return a==="Laden"&&(n=i[s]),n[0]+n[1]*t+n[2]*Math.pow(t,2)}static directionFactor(s,t=0){let a;return s>30&&s<=60?a=(1.7-.03*Math.pow(t-4,2))/2:s>60&&s<=150?a=(.9-.06*Math.pow(t-6,2))/2:s>150&&s<=180?a=(.4-.03*Math.pow(t-8,2))/2:a=1,Math.round(a*1e5)/1e5}static vesselTagFactor(s,t,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(s,2/3)):t==="Ballast"?o=.7*i+Math.pow(i,6.5)/(2.7*Math.pow(s,2/3)):o=.5*i+Math.pow(i,6.5)/(2.7*Math.pow(s,2/3)),o}static waveHeightFactor(s,t){s=s<3?s*.7:s,s=s<0?.2:s,s=s>6?s-.9*(s-6):s,s=s>9?9:s;let a;return t>30&&t<=60?a=-.6:t>60&&t<=90?a=-.4:t>90&&t<=120?a=s<3?.4:-.3:t>120&&t<=150?a=s<3?.6:-.5:t>150&&t<=180?a=s<3?.7:-.6:a=-.7,Math.round(a*(.144*Math.pow(s,2)+.278*s)*1e4)/1e4}static assembleProperties(s,t,a,i){var m;const o=s.lbp??s.length??s.lengthOverall??198.9642,n=s.draught??8,e=s.breadthMoulded??s.breadth??s.breadthExtreme??32.4572,c=s.deadweight??67035.7773,r=((m=s==null?void 0:s.type)==null?void 0:m.toLowerCase())||"common";return{tag:r.indexOf("container")>-1?"container":r.indexOf("tugs")>-1?"tugs":"common",lbp:o,loadCondition:t,draught:n,breadthMoulded:e,displacement:Math.round((c/1.025+n*e*o*.7)*1e4)/1e4,speed:Math.round((a??14.1382)*1852/3600*1e4)/1e4,bearing:i||90}}static async speedLoseAt(s,t,a,i="",o=2,n=!0,e=!1,c={}){let r;if(t.velocity&&e&&(s.speed=H.LngLatHelper.roundPrecision(t.velocity*1852/3600,6)),n){let u;try{i=(i==null?void 0:i.toUpperCase())==="CMEMS"?"ECMWF":i,i=(i==null?void 0:i.toUpperCase())==="METEO2"?"best_match":i;const{weatherModels:y,marineModels:j}=await nt.Meteo2Assist.autoPickMeteoModel(i),S=await vt.spotForecast(t.lat,t.lng,a.utc().format(),!1,!1,!0,{...c,pastDays:1,forecastDays:1,weatherModels:y,marineModels:j}),[w]=nt.Meteo2Assist.pickHourly(S,a);u=nt.Meteo2Assist.toLegacy(w)}catch(y){I.warn("[%s] meteo2 spot(%j) forecast failed: %s",c.requestId,{...t,eta:a.utc().format(),source:i},y)}const f=W.weatherFactor(s,u),m=W.currentFactor(s.bearing,u==null?void 0:u.current,o),b=Math.round((s.speed*1.943844+f+m)*100)/100;r={meteo:{...u},wxFactor:f,cFactor:m,speed:t.velocity&&e?t.velocity:b<0?1:b,eta:a.utc().format(),etd:a.utc().format()}}else r={wxFactor:0,cFactor:0,speed:t.velocity&&e?t.velocity:Math.round((s.speed*1.943844+0+0)*100)/100,eta:a.utc().format(),etd:a.utc().format()};return delete t.meteo,delete t.wxFactor,delete t.cFactor,delete t.speed,delete t.etd,{...r,...t}}static async speedLoseInHoursStep(s,t,a,i,o,n,e="",c=!0,r=!1,u={}){t.utc();const f=t.clone().add(14,"days"),m=[],b=[];let y=0,j=0,S,w;for(let v=0;v<n.length-1;v++){let d=n[v];d.distanceFromStart=Math.round((o+j)*1e3)/1e3;const M=n[v+1];if(s.bearing=H.LaneHelper.calculateBearing(d,M,!M.gcToPrevious),d.bearing=s.bearing,d.suspend&&r){d.eta=d.eta||t.utc().format(),d.elapsed=d.elapsed??0;const k=d.suspend-d.elapsed;if(i-y>k)i=i-y-k,t.add(k,"hour"),d.elapsed=d.suspend;else{const C=i-y;d.elapsed+=C,t.add(C,"hour"),i=0}if(I==null||I.info(`[%s] suspend ${d.elapsed} hours at %j, and remain ${i} hours need to go...`,u.requestId,d),i===0)return d.distanceFromPrevious=j,{etd:t,from:w||d,to:d,next:n.filter(C=>C),wps:m,days:b}}else d.suspend=0;c=t.isAfter(f)?!1:c,d=await W.speedLoseAt(s,d,t,e,0,c,r,u),w=w||d,d.important&&m.push(d),t.isSameOrAfter(a)&&(b.push(d),a.add(24,"hour"));const h=H.LaneHelper.calculateDistance(d,M,!M.gcToPrevious);let l=Math.round(h/w.speed*1e5)/1e5;if(y+l<i){if(y+=l,t.add(l,"hour"),delete n[v],I==null||I.debug(`[%s] go to %j from %j with ${h}nm, and cost ${l} hours`,u.requestId,{lat:M.lat,lng:M.lng},{lat:w.lat,lng:w.lng,etd:w.etd}),j+=h,n.filter(k=>k).length<=1){S=M,S.eta=t.utc().format(),S.distanceFromPrevious=h,S.distanceFromStart=Math.round((o+j)*1e4)/1e4,m.push(S),delete n[v+1];break}}else{l=i-y,t.add(l,"hour");const k=H.LngLatHelper.roundPrecision(w.speed*l,5);S=H.LaneHelper.calculateCoordinate(d,s.bearing,k,"nauticalmiles",!M.gcToPrevious),S.eta=t.utc().format(),n[v]=S,I==null||I.debug(`[%s] go to %j from %j with ${k}nm, and cost ${l} hours`,u.requestId,{lat:S.lat,lng:S.lng},{lat:d.lat,lng:d.lng,etd:d.etd}),j+=k,S.distanceFromPrevious=Math.round(j*1e4)/1e4,S.distanceFromStart=Math.round((o+j)*1e4)/1e4;break}}return{etd:t,from:w,to:S,next:n.filter(v=>v),wps:m,days:b}}static currentFactor(s,t,a=0){const i=(s-(t==null?void 0:t.degree)||0)/180*Math.PI;if(Math.abs(i)===Math.PI/2)return 0;let o=((t==null?void 0:t.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(s,t){var f,m,b,y,j,S,w;I==null||I.debug("calculate weather factor via: %j",{...s,...t});const a=W.blockCoefficient(s.displacement,s.lbp,s.breadthMoulded,s.draught),i=W.froudeNumber(s.speed,s.lbp),o=W.amendFactor(a,i,s.loadCondition);let n=Math.abs(s.bearing%360-(((f=t==null?void 0:t.wind)==null?void 0:f.degree)%360||0));n=n>180?360-n:n;const e=W.directionFactor(n,(m=t==null?void 0:t.wind)==null?void 0:m.scale),c=W.vesselTagFactor(s.displacement,s.loadCondition,s.tag,(b=t==null?void 0:t.wind)==null?void 0:b.scale);let r=e*o*c/100*s.speed;r=Math.round(r*1.943844*1e4)/1e4*-1,s.tag==="tugs"&&Math.abs(r)>1&&(r=r/(Math.abs(Math.round(r))+1)),I==null||I.debug("wind wx factor = %d",r),n=Math.abs(s.bearing%360-(((j=(y=t==null?void 0:t.wave)==null?void 0:y.sig)==null?void 0:j.degree)%360||0));const u=W.waveHeightFactor(((w=(S=t==null?void 0:t.wave)==null?void 0:S.sig)==null?void 0:w.height)??1,n);return I==null||I.debug("wave wx factor = %d",u),r=Math.abs(r)>Math.abs(u)?r:r*.3+u*.7,I==null||I.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(s,t,a,i,o,n="",e=0,c=!0,r=!1,u={}){var X,Q,Z,$,tt,et;const f=g().valueOf();s.lng=H.LngLatHelper.convertToStdLng(s.lng);const{route:m,waypoints:b}=o.points,y=H.LaneHelper.calculateSubRoute(s,m);if(((X=y[0])==null?void 0:X.length)<=1)return;const{v0:j,label:S}=s.sog?{v0:s.sog,label:s.label||"Other"}:{v0:i.speed,label:"CP"},w=W.assembleProperties(a,i.loadCondition,j,0),v=b.length?H.LaneHelper.calculateSubWaypoints(s,b):[];v.forEach(O=>O.important=!0);const d={from:{...s},route:y,waypoints:v,v0:j,label:S},M={hours:[],days:[],wps:[]};e||(H.LaneHelper.calculateRouteDistance(y)/i.speed<=72?e=3:e=6);let h=H.LaneHelper.simplifyRouteToCoordinates(y,v,0),l=0,k=0,C=0,x=0;t=g(t).utc();const Y=t.clone();for(;h.length>0;){const O=e-t.hour()%e,_=Math.ceil(t.clone().add(O,"h").set({minute:0,second:0,millisecond:0}).diff(t,"h",!0)*1e4)/1e4,F=await W.speedLoseInHoursStep(w,t,Y,_,l,h,n,c,r,u);(Q=F.from)!=null&&Q.speed&&(M.hours.push(F.from),M.wps.push(...F.wps),M.days.push(...F.days)),h=F==null?void 0:F.next,h.length||M.hours.push(F==null?void 0:F.to),l+=Math.round((((Z=F==null?void 0:F.to)==null?void 0:Z.distanceFromPrevious)??0)*1e4)/1e4}const T=M.hours;for(let O=0;O<T.length-1;O++){const _=g(T[O+1].eta).diff(T[O].etd,"hour",!0)||1;k+=(T[O].wxFactor||0)*_,C+=(T[O].cFactor||0)*_,x+=_}($=M.wps)==null||$.forEach((O,_)=>{O.positionTime=g.utc(O.etd||O.eta).unix();const F=M.wps[_-1];if(F){const B=O.distanceFromStart-F.distanceFromStart,R=g(O.eta||O.etd).diff(g(F.etd||F.eta),"h",!0);O.avgSpd=Math.round(B/R*100)/100,F.bearing=H.LaneHelper.calculateBearing(F,O)}}),M.wps=(tt=M.wps)==null?void 0:tt.reduce((O,_)=>(O.some(F=>Math.round(F.positionTime/60)===Math.round(_.positionTime/60))||O.push(_),O),[]),d.sample=M;const L=M.hours.at(0),N=M.hours.at(-1);d.distance=Math.round(N.distanceFromStart*1e3)/1e3,d.etd=g(L.eta).utc().format(),d.eta=g(N.eta).utc().format(),d.wxFactor=Math.round(k/x*1e3)/1e3,d.cFactor=Math.round(C/x*1e3)/1e3,d.avgSpeed=Math.round(N.distanceFromStart/x*1e3)/1e3,d.totalHrs=Math.round(x*1e3)/1e3;const{distanceInECA:E,hoursInECA:P,totalDgoConsInECA:V,eca:J}=await this.calculateECA(d,i,u),st=H.LngLatHelper.roundPrecision(i.fo/24*(x-P),3),ot=H.LngLatHelper.roundPrecision(i.dgo/24*x,3);d.extend={eca:J,distanceInECA:E,hoursInECA:P,totalDgoConsInECA:V},d.totalFoCons=st<0?0:st,d.totalDgoCons=ot;const at=g().valueOf()-f,rt=((et=M==null?void 0:M.hours)==null?void 0:et.length)||1;return I==null||I.info("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms",u==null?void 0:u.requestId,at,rt,Math.round(at/rt*1e3)/1e3),d}static async analyseInstantWithThreshed(s,t,a,i,o,n,e,c="",r=3,u=!0,f=!1,m={}){var Z,$,tt,et,O,_;const b=g().valueOf();s.lng=H.LngLatHelper.convertToStdLng(s.lng);const{v0:y,label:j}=s.sog?{v0:s.sog,label:s.label||"Other"}:{v0:o.speed,label:"CP"},S=W.assembleProperties(i,o.loadCondition,y,0),w=H.LaneHelper.calculateSubRoute(s,n);if(((Z=w[0])==null?void 0:Z.length)<=1)return;const v=e.length?H.LaneHelper.calculateSubWaypoints(s,e):[];v.forEach(F=>F.important=!0);let d=H.LaneHelper.simplifyRouteToCoordinates(w,v,0),M=0,h=0,l=0,k=0;const C={hours:[],wps:[],days:[]};t=g(t).utc();const x=t.clone();for(;d.length>0;){const F=r-t.hour()%r;let B=Math.ceil(t.clone().add(F,"h").set({minute:0,second:0,millisecond:0}).diff(t,"h",!0)*1e4)/1e4;B=t.clone().add(B,"h").isSameOrAfter(a)?a.diff(t,"h",!0)*1e4/1e4:B;const R=await W.speedLoseInHoursStep(S,t,x,B,M,d,c,u,f,m);if(($=R.from)!=null&&$.speed&&(C.hours.push(R.from),R!=null&&R.wps&&C.wps.push(...R.wps),C.days.push(...R.days)),d=R==null?void 0:R.next,d.length||C.hours.push(R==null?void 0:R.to),M+=Math.round((((tt=R==null?void 0:R.to)==null?void 0:tt.distanceFromPrevious)??0)*1e4)/1e4,!B)break}C.wps=(et=C.wps)==null?void 0:et.reduce((F,B)=>(F.some(R=>Math.round(g(R.etd).unix()/60)===Math.round(g(B.etd).unix()/60))||F.push(B),F),[]),(O=C.wps)==null||O.forEach((F,B)=>{const R=C.wps[B-1];if(R){const gt=F.distanceFromStart-R.distanceFromStart,wt=g(F.eta||F.etd).diff(g(R.etd||R.eta),"h",!0);F.avgSpd=Math.round(gt/wt*100)/100;const kt=H.LaneHelper.calculateBearing(R,F);R.bearing=kt}});const Y=C.hours;for(let F=0;F<Y.length-1;F++){const B=g(Y[F+1].eta).diff(Y[F].etd,"hour",!0);h+=Y[F].wxFactor*B,l+=Y[F].cFactor*B,k+=B}const T=C.hours.at(0),L=C.hours.at(-1),N=await H.LaneHelper.calculateRangeRoute(T,L,w),E=await H.LaneHelper.calculateRangeWaypoints(T,L,w,v),P={sample:C,distance:Math.round(((L==null?void 0:L.distanceFromStart)||0)*1e4)/1e4,etd:g(T.eta).utc().format(),eta:g(L==null?void 0:L.eta).utc().format(),wxFactor:Math.round(h/k*1e3)/1e3,cFactor:Math.round(l/k*1e3)/1e3,avgSpeed:Math.round(((L==null?void 0:L.distanceFromStart)||0)/k*1e3)/1e3,totalHrs:Math.round(k*1e3)/1e3,from:T,to:L,route:N,waypoints:E,v0:y,label:j},{distanceInECA:V,hoursInECA:J,totalDgoConsInECA:st,eca:ot}=await this.calculateECA(P,o,m),it=H.LngLatHelper.roundPrecision(o.fo/24*(k-J),3),at=H.LngLatHelper.roundPrecision(o.dgo/24*k,3);P.extend={eca:ot,distanceInECA:V,hoursInECA:J,totalDgoConsInECA:st},P.totalDgoCons=at,P.totalFoCons=it<0?0:it;const X=g().valueOf()-b,Q=((_=C==null?void 0:C.hours)==null?void 0:_.length)||1;return I==null||I.debug("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms",m==null?void 0:m.requestId,X,Q,Math.round(X/Q*1e3)/1e3),P}static async analyseCost(s,t,a,i,o={}){var w,v;const n=g().valueOf(),e=[];s.speedStep=s.speedStep||3,s.alterStep=s.alterStep??1;const c=H.LaneHelper.calculateRouteDistance(i.route);let r=0;a.forEach(d=>{const M=Math.ceil(c/d.speed/24);r=r<M?M:r}),r=r*1.3;const u=g.utc(s.etd).add(r??14,"day");let f=1;for(const d of a){const M=JSON.parse(JSON.stringify(i.route)),h=JSON.parse(JSON.stringify(i.waypoints)),l=await W.analyseInstantWithThreshed({lat:s.lat,lng:s.lng},s.etd,u,t,d,M,h,s.meteoVendor,s.speedStep,s.useMeteo,s.useRouteParam,o);l&&(await W.calculateCost(l,d,s,o),e.push(l),I==null||I.info("[%s][L%d-%d] analyse from %s to %s cost: %j",o.requestId,1,f,s.etd,u.format(),{cost:l.cost.total,hire:l.cost.hire,bunker:l.cost.bunker,distance:l.distance,hours:l.totalHrs,cp:`${d.speed}/${d.fo}/${d.dgo}`})),f++}e.sort((d,M)=>d.cost.total-M.cost.total);const m=e.at(0),b=e.at(1),y=[];if(y.push({combined:!1,speeds:[m],cost:(w=m.cost)==null?void 0:w.total}),b){const d=m.cost.cp,M=b.cost.cp,h=g(m.eta),l=g(m.etd),k=h.diff(l,"days",!0);let C=Math.ceil(k/2);C=C>7?7:C<s.alterStep?s.alterStep:C;let x=2,Y={combined:!1,speeds:[b],cost:(v=b.cost)==null?void 0:v.total},T;for(;C>=s.alterStep;){const L=await W.combinedAnalyse(s,t,u,[d,M],i,C,{...o,level:x});if(Y.cost>L.cost?T?(T==null?void 0:T.cost)>L.cost&&(T=L):(T=Y,Y=L):(!T||(T==null?void 0:T.cost)>L.cost)&&(T=L),C<=s.alterStep)break;C=Math.ceil(C/2),x+=1}y.push(Y),T&&y.push(T)}const S=g().valueOf()-n;return I==null||I.info("[%s] analyse elapsed: %d ms",o==null?void 0:o.requestId,S),y.sort((d,M)=>d.cost-M.cost)}static async combinedAnalyse(s,t,a,i,o,n,e={}){e.counter=1,I==null||I.info("[%s][L%d] analyse with alternate cp in every %d days",e.requestId,e.level,n);const c=await W.alternateAnalyse(s,t,a,i,0,o,n,e),r=c.reduce((M,h)=>M+h.cost.total,0),u=c.reduce((M,h)=>M+h.cost.hire,0),f=c.reduce((M,h)=>M+h.cost.bunker,0),m=c.reduce((M,h)=>M+h.distance,0),b=c.reduce((M,h)=>M+h.totalHrs,0);I==null||I.info("[%s][L%d] cost with cpa/cpb turn: %j",e.requestId,e.level,{cost:r,hire:u,bunker:f,distance:m,hours:b});const y=await W.alternateAnalyse(s,t,a,i,1,o,n,e),j=y.reduce((M,h)=>M+h.cost.total,0),S=y.reduce((M,h)=>M+h.cost.hire,0),w=y.reduce((M,h)=>M+h.cost.bunker,0),v=y.reduce((M,h)=>M+h.distance,0),d=y.reduce((M,h)=>M+h.totalHrs,0);return I==null||I.info("[%s][L%d] cost with cpb/cpa turn: %j",e.requestId,e.level,{cost:j,hire:S,bunker:w,distance:v,hours:d}),r<j?{combined:!0,cost:Math.round(r*1e3)/1e3,speeds:c,step:n}:{combined:!0,cost:Math.round(j*1e3)/1e3,speeds:y,step:n}}static async alternateAnalyse(s,t,a,i,o,n,e,c={}){var m,b;let r=g.utc(s.etd);const u={lat:s.lat,lng:s.lng},f=[];for(;r.isBefore(a);){const y=r.clone().utc().add(e,"day"),j=JSON.parse(JSON.stringify(n.route)),S=JSON.parse(JSON.stringify(n.waypoints)),w=i[o],v=await W.analyseInstantWithThreshed(u,r.utc().format(),y,t,w,j,S,s.meteoVendor,s.speedStep,s.useMeteo,s.useRouteParam,c);v&&(await W.calculateCost(v,w,s,c),I==null||I.info("[%s][L%d-%d] analyse from %s to %s cost: %j",c.requestId,c.level,c.counter,r.utc().format(),y.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}`})),c.counter=c.counter+1;const d=(b=(m=v==null?void 0:v.sample)==null?void 0:m.hours)==null?void 0:b.at(-1);if(d)u.lat=d.lat,u.lng=d.lng,r=g(d.eta),f.push(v),o=o?0:1;else break}return f}static async calculateCost(s,t,a,i={}){var o;if(s){const n=(a.addComm||0)>=1?(a.addComm||0)/100:a.addComm||0,e=Math.round(s.totalHrs/24*(a.dailyHire||0)*(1-n)*1e3)/1e3,c=Math.round(s.totalFoCons*(a.priceFO||0)*1e3)/1e3,r=Math.round((s.totalDgoCons+(((o=s.extend)==null?void 0:o.totalDgoConsInECA)||0))*(a.priceDGO||0)*1e3)/1e3;s.cost={total:Math.round((e+c+r)*1e3)/1e3,hire:e,bunker:Math.round((c+r)*1e3)/1e3,cp:t}}return s}static async calculateECA(s,t,a={}){var c,r,u,f;const i=await H.LaneHelper.intersectInECA((s==null?void 0:s.route)||[]);let o=0,n=0,e=0;(r=(c=s==null?void 0:s.sample)==null?void 0:c.wps)==null||r.forEach(m=>{m.positionTime=g.utc(m.etd||m.eta).unix()});for(const m of i){o+=m.distance;const b=await H.LaneHelper.deadReckoningTime((u=m.waypoints)==null?void 0:u.at(0),s.sample.wps),y=await H.LaneHelper.deadReckoningTime((f=m.waypoints)==null?void 0:f.at(-1),s.sample.wps);m.in=b,m.out=y,m.totalHrs=H.LngLatHelper.roundPrecision((y.positionTime-b.positionTime)/3600,3),m.totalDgoCons=H.LngLatHelper.roundPrecision(t.fo/24*m.totalHrs,3),n+=m.totalHrs,e+=m.totalDgoCons}return o=H.LngLatHelper.roundPrecision(o,3),n=H.LngLatHelper.roundPrecision(n,3),e=H.LngLatHelper.roundPrecision(e,3),{distanceInECA:o,hoursInECA:n,totalDgoConsInECA:e,eca:i}}static async mergeSpeeds(s,t={}){var d,M;const a={hours:[],wps:[],days:[]},i=s.reduce((h,l)=>h+l.distance,0),o=s.reduce((h,l)=>{var k;return h+(((k=l.extend)==null?void 0:k.distanceInECA)||0)},0),n=s.reduce((h,l)=>h+l.totalHrs,0),e=s.reduce((h,l)=>{var k;return h+(((k=l.extend)==null?void 0:k.hoursInECA)||0)},0),c=s.reduce((h,l)=>{var k;return h+(((k=l.extend)==null?void 0:k.totalDgoConsInECA)||0)},0),r=s.reduce((h,l)=>h+l.wxFactor*l.totalHrs/n,0),u=s.reduce((h,l)=>h+l.cFactor*l.totalHrs/n,0),f=s.reduce((h,l)=>h+l.totalFoCons,0),m=s.reduce((h,l)=>h+l.totalDgoCons,0),b=s.reduce((h,l)=>h+l.cost.total,0),y=s.reduce((h,l)=>h+l.cost.hire,0),j=s.reduce((h,l)=>h+l.cost.bunker,0),S=[],w=[];let v;for(const h of s){w.push(...((d=h.extend)==null?void 0:d.eca)||[]);const l=h.sample.hours,k=h.sample.wps,C=h.sample.days,x=l.at(0);v&&(x.distanceFromPrevious=v.distanceFromPrevious,x.distanceFromStart=v.distanceFromStart,l.forEach((N,E)=>{E&&(N.distanceFromStart=N.distanceFromStart+v.distanceFromStart)}),k.at(0).distanceFromPrevious=v.distanceFromPrevious,k.at(0).distanceFromStart=v.distanceFromStart,k.forEach((N,E)=>{E&&(N.distanceFromStart=N.distanceFromStart+v.distanceFromStart)}),C.at(0).distanceFromPrevious=v.distanceFromPrevious,C.at(0).distanceFromStart=v.distanceFromStart,C.forEach((N,E)=>{E&&(N.distanceFromStart=N.distanceFromStart+v.distanceFromStart)})),x.cp=h.cost.cp;const Y=[h.etd,h.eta],T=S.findIndex(N=>N.id===x.cp.id);T===-1?(x.cp.segment=[Y],S.push(x.cp)):S[T].segment.push(Y),l.forEach(N=>{var P;((P=a.hours)==null?void 0:P.findIndex(V=>V.eta===N.eta))===-1&&a.hours.push(N)}),k.forEach(N=>{var P;((P=a.wps)==null?void 0:P.findIndex(V=>V.eta===N.eta))===-1&&a.wps.push(N)}),C.forEach(N=>{var P;((P=a==null?void 0:a.days)==null?void 0:P.findIndex(V=>V.eta===N.eta))===-1&&a.days.push(N)});const L=(M=a.wps)==null?void 0:M.findIndex(N=>N.eta===x.eta);L===-1?a.wps.push(x):a.wps[L]=x,v=l.at(-1)}return a.wps.sort((h,l)=>{g(h.etd).unix()-g(l.etd).unix()}),a.wps.forEach((h,l)=>{const k=a.wps[l-1];if(k){const C=h.distanceFromStart-(k.distanceFromStart||0),x=g(h.eta||h.etd).diff(g(k.etd||k.eta),"hour",!0),Y=Math.round(C/x*100)/100;h.avgSpd=Y;const T=H.LaneHelper.calculateBearing(k,h);k.bearing=T}}),{sample:a,etd:s.at(0).etd,eta:s.at(-1).eta,from:s.at(0).from,to:s.at(-1).to,v0:s.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(u*1e3)/1e3,totalFoCons:Math.round(f*1e3)/1e3,totalDgoCons:Math.round(m*1e3)/1e3,cost:{total:Math.round(b*1e3)/1e3,hire:Math.round(y*1e3)/1e3,bunker:Math.round(j*1e3)/1e3},extend:{cps:S,eca:w,distanceInECA:Math.round(o*1e3)/1e3,hoursInECA:Math.round(e*1e3)/1e3,totalDgoConsInECA:Math.round(c*1e3)/1e3,speeds:s}}}}q.AISImpl=G,q.AlertHelper=dt,q.AlertLevel=ct,q.HifleetImpl=yt,q.LoadCondition=lt,q.MyShipImpl=Mt,q.MyVesselImpl=mt,q.ShipxyImpl=pt,q.SpeedHelper=W,q.SpeedLabel=ht,q.VesselTag=ut,q.alertHelper=bt,Object.defineProperty(q,Symbol.toStringTag,{value:"Module"})});
|
|
1
|
+
(function(q,A){typeof exports=="object"&&typeof module<"u"?A(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"],A):(q=typeof globalThis<"u"?globalThis:q||self,A(q["idm-plugin-vessel"]={},q.got,q["@log4js-node/log4js-api"],q.moment,q["@idm-plugin/geo2"],q["@idm-plugin/meteo2"],q["@idm-plugin/meteo"]))})(this,function(q,A,U,g,H,ft,nt){"use strict";var It=Object.defineProperty;var St=(q,A,U)=>A in q?It(q,A,{enumerable:!0,configurable:!0,writable:!0,value:U}):q[A]=U;var K=(q,A,U)=>(St(q,typeof A!="symbol"?A+"":A,U),U);let p;try{p=U.getLogger("vessel")}catch{}finally{}class G{parseStatus(s){let t,a;switch(s){case 0:t="在航(主机推动)",a="Underway Using Engine";break;case 1:t="锚泊",a="Anchored";break;case 2:t="失控",a="Not under command";break;case 3:t="操纵受限",a="Limited airworthiness";break;case 4:t="吃水受限",a="Limited by ship's draft";break;case 5:t="靠泊",a="Mooring";break;case 6:t="搁浅",a="Stranded";break;case 7:t="捕捞作业",a="Engaged in fishing";break;case 8:t="靠帆船提供动力",a="Sailing";break;default:t="未定义",a="Undefined"}return{labelCn:t,labelEn:a}}}class mt extends G{constructor(t,a){super();K(this,"clientId");K(this,"clientSecret");K(this,"token");this.clientId=t,this.clientSecret=a}async authToken(t={}){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 A.post(a,i).json();p==null||p.info("[%s] fetch access token from: %s - %j",t.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:g().utc().format()})}async checkToken(t={}){var a;return(!this.token||g().diff(g(this.token.issuedAt),"seconds")>(((a=this.token)==null?void 0:a.expiresIn)||0)-300)&&await this.authToken(t),this.token}async suggest(t,a={}){var e,c;await this.checkToken(a);const i="https://market.myvessel.cn/sdc/v1/mkt/vessels/fuzzy",o={headers:{Authorization:`${(e=this.token)==null?void 0:e.tokenType} ${(c=this.token)==null?void 0:c.accessToken}`},json:{kw:t,recordNum:a.ps||10}};p==null||p.info("[%s] fetch suggest vessels from: %s - %j",a.requestId,i,o);const n=await A.post(i,o).json();return n.code?(p==null||p.warn("[%s] fetch suggest vessels failed: %j",a.requestId,{message:n.message,status:n.status,code:n.code}),[]):n.data.map(u=>({mmsi:u.mmsi,name:u.nameEn,nameCn:u.nameCn,imo:Number.isNaN(u.imo)?null:Number(u.imo),callSign:u.callsign,type:u.vesselTypeNameEn,flagName:u.flagCtry,vendor:"myvessel",raw:u}))}async search(t,a={}){var r,u;await this.checkToken(a);const i=/^\d{7}$/.test(t.toString()),o=i?"https://market.myvessel.cn/sdc/v1/mkt/vessels/detail/imo":"https://market.myvessel.cn/sdc/v1/mkt/vessels/detail/mmsi",n=i?{imo:t}:{mmsi:t},e={headers:{Authorization:`${(r=this.token)==null?void 0:r.tokenType} ${(u=this.token)==null?void 0:u.accessToken}`},searchParams:n};p==null||p.info("[%s] fetch vessel from: %s - %j",a.requestId,o,e);const c=await A.get(o,e).json();if(c.status!==200)return p==null||p.warn("[%s] fetch suggest vessels failed: %j",a.requestId,{message:c.message,status:c.status,code:c.code}),{};{const h=c.data;if(h)return{mmsi:h.mmsi,imo:Number.isNaN(h.imo)?null:Number(h.imo),callSign:h.callsign,name:h.nameEn,nameCn:h.nameCn,type:h.vesselTypeNameEn,flagName:h.flagCtry,clasz:h.classSociety,dateOfBuild:h.buildYearMonth,deadweight:h.dwt,grossTonnage:h.grt,netTonnage:h.net,teu:h.teu,length:h.length,breadth:h.width,height:h.height,draught:h.draught,speed:h.speed,passengerCapacity:h.passengercapacity,vendor:"myvessel",raw:h}}return{}}async archives(t,a={}){var e,c;await this.checkToken(a);const i="https://svc.data.myvessel.cn/sdc/v1/ship/info/batch",o={headers:{Authorization:`${(e=this.token)==null?void 0:e.tokenType} ${(c=this.token)==null?void 0:c.accessToken}`},json:{mmsiList:typeof t=="number"?[t]:t}};p==null||p.info("[%s] fetch vessel archive from: %s - %j",a.requestId,i,o);const n=await A.post(i,o).json();return n.status!==200?(p==null||p.warn("[%s] fetch vessel archive failed: %j",a.requestId,{message:n.message,status:n.status,code:n.code}),{}):n.data}async realTimePosition(t,a={}){var c,r;await this.checkToken(a);const i="https://svc.data.myvessel.cn/sdc/v1/vessels/status/location/unit",o={headers:{Authorization:`${(c=this.token)==null?void 0:c.tokenType} ${(r=this.token)==null?void 0:r.accessToken}`},searchParams:{mmsi:t}};p==null||p.info("[%s] fetch realtime position from: %s - %j",a.requestId,i,o);const n=await A.get(i,o).json();if(n.code)return p==null||p.warn("[%s] fetch realtime position failed: %j",a.requestId,{message:n.message,status:n.status,code:n.code}),n;const e=n.data;for(const u in e)!isNaN(e[u])&&Number(e[u])!==1/0&&(e[u]=Number(e[u]));if(e){const u=g(`${e.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return{mmsi:e.mmsi,name:e.vesselName||e.aisVesselName,imo:e.imo,callSign:e.callsign||e.aisCallSign,lat:e.lat,lng:e.lon,length:e.length,width:e.width,draught:e.currDraught,sog:e.sog,cog:e.cog,hdg:e.hdg,rot:e.rot,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(e.eta)?g.utc(e.eta).format():void 0,destination:e.dest,positionTime:u.unix(),status:e.status,labelCn:e.statusNameCn,labelEn:e.statusNameEn,vesselType:e.vesselTypeNameEn,flag:e.flagCtryNameEn,clasz:e.classSociety,build:e.buildYear,dwt:e.dwt,grt:e.grt,net:e.net,method:"position",vendor:"myVessel",utc:u.utc().format()}}else return{}}async trajectory(t,a,i,o,n=!0,e={}){await this.checkToken(e);const c=await this.realTimePosition(t,e),r=g(a),u=g(i),h=[];for(;u.diff(r,"day",!0)>30;)await this.trajectoryIn30Day(t,r,r.clone().add(30,"day"),c,o,h,e),r.add(30,"day");return await this.trajectoryIn30Day(t,r,u,c,o,h,e),h}async trajectoryIn30Day(t,a,i,o,n,e,c={}){var y,j,S,w,v;const r="https://svc.data.myvessel.cn/sdc/v1/vessels/status/track",u={headers:{Authorization:`${(y=this.token)==null?void 0:y.tokenType} ${(j=this.token)==null?void 0:j.accessToken}`},json:{mmsi:t,startTime:a.utcOffset(8).format("YYYY-MM-DD HH:mm:ss"),endTime:i.utcOffset(8).format("YYYY-MM-DD HH:mm:ss")}};p==null||p.info("[%s] fetch trajectory from: %s - %j",c.requestId,r,u);const h=await A.post(r,u).json();if(h.code)return p==null||p.warn("[%s] fetch trajectory failed: %j",c.requestId,r,{message:h.message,status:h.status,code:h.code}),h;let m=-1;const b=g(`${(w=(S=h.data)==null?void 0:S[0])==null?void 0:w.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return(v=h.data)==null||v.forEach(d=>{for(const Y in d)!isNaN(d[Y])&&Number(d[Y])!==1/0&&(d[Y]=Number(d[Y]));const M=g(`${d.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00"),f=d.status,{labelCn:l,labelEn:k}=this.parseStatus(f),C={mmsi:d.mmsi,imo:o==null?void 0:o.imo,lat:d.lat,lng:d.lon,sog:d.sog,cog:d.cog,hdg:d.hdg,draught:d.draught,status:f,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(d.eta)?g(`${d.eta} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00").utc().format():void 0,destination:d.dest,positionTime:M.unix(),labelCn:l,labelEn:k,method:"trajectory",vendor:"myVessel",utc:M.utc().format()},x=Math.floor(M.diff(b,"minute",!0)/(n||1));x!==m&&(m=x,e.push(C))}),e}}class yt extends G{constructor(t){super();K(this,"token");this.token=t}async realTimePosition(t,a={}){const i="https://api.hifleet.com/position/position/get/token",o={searchParams:{mmsi:t,usertoken:this.token}},n=await A.post(i,o).json();p==null||p.info("[%s] fetch realtime position from: %s - %j",a.requestId,i,o);const e=n==null?void 0:n.list;if(!e)return p==null||p.warn("[%s] fetch realtime position failed: %j",a.requestId,i,n),n;for(const b in e)!isNaN(e[b])&&Number(e[b])!==1/0&&(e[b]=Number(e[b]));e.status=e.sp>3?0:1;const c=e.status,{labelCn:r,labelEn:u}=this.parseStatus(c),h=g(`${e.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return{mmsi:e.m,name:e.n,imo:e.imonumber,callSign:e.callsign,lat:Math.round(e.la/60*1e5)/1e5,lng:Math.round(e.lo/60*1e5)/1e5,length:e.l,width:e.w,draught:e.draught,sog:e.sp,cog:e.co,hdg:e.h,rot:isNaN(e.rot)?0:e.rot,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(e.eta)?g.utc(e.eta).format():void 0,destination:e.destination,vesselType:e.type,dwt:e.dwt,build:e.buildyear,flag:e.fn,positionTime:h.unix(),utc:h.utc().format(),status:c,labelCn:r,labelEn:u,method:"position",vendor:"hifleet"}}async search(t,a={}){let i="https://www.hifleet.com/hifleetapi/searchVesselOL.do";const o={searchParams:{keyword:t},headers:{Referer:"https://www.hifleet.com",Origin:"https://www.hifleet.com",Host:"www.hifleet.com"}};let n=await A.post(i,o).json();p==null||p.info("[%s] fetch vessel props from: %s - %j",a.requestId,i,o),n instanceof Array&&(n=n[0]);for(const c in n)!isNaN(n[c])&&Number(n[c])!==1/0&&(n[c]=Number(n[c]));const e={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 A.post(i,o).json(),p==null||p.info("[%s] search vessel dead weight from: %s - %j",a.requestId,i,o),n instanceof Array&&(n=n[0]),n&&(e.deadweight=Number(n.dwt)),e}async suggest(t,a={}){const i="https://www.hifleet.com/hifleetapi/getShipSuggest.do",o={searchParams:{q:t},headers:{Referer:"https://www.hifleet.com",Origin:"https://www.hifleet.com",Host:"www.hifleet.com"}},n=await A.post(i,o).json();p==null||p.info("[%s] suggest vessel props from: %s - %j",a.requestId,i,o);const e=[];for(const c of n)e.push({mmsi:!c.mmsi||isNaN(c.mmsi)?null:Number(c.mmsi),name:c.name,callSign:c.callsign,imo:!c.imo||isNaN(c.imo)?null:Number(c.imo),score:c._score});return e.sort((c,r)=>r.score-c.score),e}async trajectory(t,a,i,o,n=!0,e={}){var d,M,f;const c=await this.realTimePosition(t,e);let r=g(a);const u=g(i),h=g();if(n){let l=u.diff(r,"d",!0);l<0?r=u.clone().subtract(40,"d"):l<30?r.subtract(10,"d"):l<60?r.subtract(5,"d"):r=u.clone().subtract(80,"d"),l=h.diff(u,"d",!0),u.add(l>10?240:l*24,"h")}const m={searchParams:{endtime:u.utcOffset("+8:00").format("YYYY-MM-DD HH:mm:ss"),starttime:r.utcOffset("+8:00").format("YYYY-MM-DD HH:mm:ss"),mmsi:t,usertoken:this.token}},b="https://api.hifleet.com/position/trajectory/nocompressed/withstatic/token",y=await A.get(b,m).json();p==null||p.info("[%s] fetch trajectory from: %s - %j",e.requestId,b,m);let j;y&&(j=((M=(d=y.ships)==null?void 0:d.offors)==null?void 0:M.ship)||[],j.length||p==null||p.warn("[%s] fetch trajectory failed: %j",e.requestId,y));const S=[];let w=-1;const v=g(`${(f=j==null?void 0:j[0])==null?void 0:f.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");for(const l of j){for(const L in l)!isNaN(l[L])&&Number(l[L])!==1/0&&(l[L]=Number(l[L]));const k=g(`${l.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");l.status=l.sp>4?0:1;const{labelEn:C,labelCn:x}=this.parseStatus(l.status),Y={mmsi:l.m,name:l.n,imo:c==null?void 0:c.imo,lat:l.la,lng:l.lo,draught:l.draught,sog:l.sp,cog:l.co,hdg:l.hdg,positionTime:k.unix(),utc:k.utc().format(),status:l.status,labelCn:x,labelEn:C,method:"trajectory",vendor:"hifleet"},T=Math.floor(k.diff(v,"minute",!0)/(o||1));T!==w&&(w=T,S.push(Y))}return S}}class pt extends G{constructor(t){super();K(this,"token");this.token=t}async realTimePosition(t,a={}){const i={searchParams:{id:t,k:this.token,enc:1}},o="https://api.shipxy.com/apicall/GetSingleShip",n=await A.get(o,i).json();if(p==null||p.info("[%s] fetch realtime position from: %s - %j",a.requestId,o,i),(n==null?void 0:n.status)!==0)return n;const e=n.data[0];for(const m in e)!isNaN(e[m])&&Number(e[m])!==1/0&&(e[m]=Number(e[m]));const{labelCn:c,labelEn:r}=await this.parseStatus(e.navistat),u=g.unix(e.lasttime);return{mmsi:e.ShipID,name:e.name,imo:e.imo,callSign:e.callsign,lat:Math.round(e.lat/1e6*1e5)/1e5,lng:Math.round(e.lon/1e6*1e5)/1e5,length:Math.round(e.length/10*100)/100,width:Math.round(e.width/10*100)/100,draught:Math.round(e.draught/1e3*100)/100,sog:Math.round(e.sog*3600/1e3/1852*100)/100,cog:Math.round(e.cog/100*100)/100,hdg:Math.round(e.hdg/100*100)/100,rot:Math.round(e.rot/100*100)/100,positionTime:e.lasttime,utc:u.utc().format(),status:e.navistat,labelEn:r,labelCn:c,method:"position",vendor:"shipxy"}}async trajectory(t,a,i,o,n=!0,e={}){var v;const c=await this.realTimePosition(t,e),r=g(a),u=g(i),h="https://api.shipxy.com/apicall/GetShipTrack",m={searchParams:{id:t,k:this.token,enc:1,cut:0,btm:r.unix(),etm:u.unix()}},b=await A.get(h,m).json();if(p==null||p.info("[%s] fetch trajectory from: %s - %j",e.requestId,h,m),(b==null?void 0:b.status)!==0)return b;const y=b==null?void 0:b.points,j=[],S=g.unix((v=y[0])==null?void 0:v.utc);let w=-1;for(const d of y){const M=g.unix(d.utc),f={imo:c==null?void 0:c.imo,mmsi:t,sog:Math.round(d.sog*3600/1e3/1852*100)/100,cog:Math.round(d.cog/100*100)/100,lat:Math.round(d.lat/1e6*1e5)/1e5,lng:Math.round(d.lon/1e6*1e5)/1e5,positionTime:M.unix(),utc:M.utc().format(),method:"trajectory",vendor:"shipxy"},l=Math.floor(M.diff(S,"minute",!0)/(o||1));l!==w&&(w=l,j.push(f))}return j}}class Mt extends G{constructor(t){super();K(this,"token");this.token=t}async getShipId(t,a={}){const i={headers:{appKey:this.token},json:{mmsiList:t}},o="https://api3.myships.com/sp/ships/getShipIdByMMSI",n=await A.post(o,i).json();return p==null||p.info("[%s] fetch ship id from: %s - %j",a.requestId,o,i),n.code!=="0"?n:n.data[0].shipId}async getShipInfo(t,a={}){const i={headers:{appKey:this.token},json:{shipId:t}},o="https://api3.myships.com/sp/ships/aissta",n=await A.post(o,i).json();if(p==null||p.info("[%s] fetch ship info from: %s - %j",a.requestId,o,i),n.code!=="0")return n;const e=n.data;let c=e.imo;return t==="407170"&&(c="9198379",p==null||p.warn("[%s] ship(%s) imo error: %s, should be %s",a.requestId,t,e.imo,c)),{mmsi:e.mmsi,name:e.shipnameEn,imo:c,callSign:e.callSign,length:e.length,width:e.breadth,draught:(e.draught||100)/10}}async realTimePosition(t,a={}){const i=await this.getShipId(t,a),o=await this.getShipInfo(i,a),n={headers:{appKey:this.token},json:{shipId:i}},e="https://api3.myships.com/sp/ships/position/latest",c=await A.post(e,n).json();p==null||p.info("[%s] fetch realtime position from: %s - %j",a.requestId,e,n);const r=c.data[0];for(const y in r)!isNaN(r[y])&&Number(r[y])!==1/0&&(r[y]=Number(r[y]));const{labelCn:u,labelEn:h}=await this.parseStatus(r.aisNavStatus),m=g.unix(r.posTime);return{...o,mmsi:t,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:m.utc().format(),status:r.aisNavStatus,labelEn:h,labelCn:u,method:"position",vendor:"myship"}}async trajectory(t,a,i,o,n=!0,e={}){const c=g(a),r=g(i),u=await this.getShipId(t),h=await this.getShipInfo(u),m=[];for(;r.diff(c,"day",!0)>30;)await this.trajectoryIn30Day(u,c.unix(),c.add(30,"day").unix(),h,t,o,m);return await this.trajectoryIn30Day(u,c.unix(),r.unix(),h,t,o,m),m}async trajectoryIn30Day(t,a,i,o,n,e,c,r={}){var S;const u={headers:{appKey:this.token},json:{shipId:t,startTime:a,endTime:i}},h="https://api3.myships.com/sp/ships/position/history",m=await A.post(h,u).json();if(p==null||p.info("[%s] fetch trajectory from: %s - %j",r.requestId,h,u),m.code!=="0")return p==null||p.warn("[%s] invoke myship trajectory failed: %j",r.requestId,m),m;const b=m.data;for(const w in b)!isNaN(b[w])&&Number(b[w])!==1/0&&(b[w]=Number(b[w]));const y=g.unix((S=b[0])==null?void 0:S.posTime);let j=-1;for(const w of b){const v=g.unix(w.posTime),d={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"},M=Math.floor(v.diff(y,"minute",!0)/(e||1));M!==j&&(j=M,c.push(d))}return c}}let z;try{z=U.getLogger("vessel")}catch{}finally{}var ct=(D=>(D.NOTICE="NOTICE",D.WARN="WARN",D.HEAVY="HEAVY",D.SEVERE="SEVERE",D.ERROR="ERROR",D.FATAL="FATAL",D))(ct||{});class dt{parsePrinciple(s,t={}){var e,c,r;z==null||z.debug("[%s] parse rule: %s",t.requestId,s);const a=new RegExp("(?<=\\[)(.+)(?=])","g"),i=s.match(a)?(e=s.match(a))==null?void 0:e[0]:void 0,o=i==null?void 0:i.split(";");if(!o)return;const n={};for(let u=0;u<(o==null?void 0:o.length);u++){const h=(r=(c=o[u].match(a))==null?void 0:c[0])==null?void 0:r.split("],");if(u===0&&!h)n.scope=o[0];else if(h)for(let m=0,b=h.length;m<b;m++){const y=this.parseRule(h[m]);y&&(n[y.level]?y.key?n[y.level][y==null?void 0:y.key]=y:n[y.level]=y:y.key?n[y.level]={[y==null?void 0:y.key]:y}:n[y.level]=y)}}return n}parseRule(s,t={}){var n;z==null||z.debug("[%s] parse rule: %s",t.requestId,s),s=s.startsWith("[")?s:`[${s}`,s=s.endsWith("]")?s:`${s}]`;const a=new RegExp("(?<=\\[)(.+?)(?=])","g"),i=(n=s==null?void 0:s.match(a))==null?void 0:n[0],o=i==null?void 0:i.split(",");if(o){let e=o[3]==="Number.MAX_VALUE"?100:Number(o[3]);return e=isNaN(e)?1:e,{operator:o[0],number:Number.isNaN(Number(o[1]))?o[1]:Number(o[1]),level:o[2],time:e,key:o[4]}}}checkWeather(s,t,a={}){var y,j,S,w,v,d,M,f,l,k,C,x,Y,T,L;let i=0,o=0,n=0,e=0;const c=Math.round(((j=(y=t==null?void 0:t.SEVERE)==null?void 0:y.sigWave)==null?void 0:j.number)*1.6*100)/100,r=(w=(S=t==null?void 0:t.SEVERE)==null?void 0:S.sigWave)==null?void 0:w.number,u=(d=(v=t==null?void 0:t.HEAVY)==null?void 0:v.sigWave)==null?void 0:d.number,h=Math.round((((f=(M=t==null?void 0:t.SEVERE)==null?void 0:M.wind)==null?void 0:f.number)+2)*100)/100,m=(k=(l=t==null?void 0:t.SEVERE)==null?void 0:l.wind)==null?void 0:k.number,b=(x=(C=t==null?void 0:t.HEAVY)==null?void 0:C.wind)==null?void 0:x.number;for(let N=0;N<(s==null?void 0:s.length);N++){const E=s[N],P=(T=(Y=E==null?void 0:E.meteo)==null?void 0:Y.wave)==null?void 0:T.sig,V=(L=E==null?void 0:E.meteo)==null?void 0:L.wind,J=N?g(E.eta).diff(g(s[N-1].eta),"hour",!0):0;e=J>e?J:e,z==null||z.debug("[%s] check sig.wave: %j",a.requestId,{...P,dgThd4Wv:c,svThd4Wv:r,hvThd4Wv:u}),(P==null?void 0:P.height)>=c?E.isDangerous=!0:(P==null?void 0:P.height)>=r?E.isSevere=!0:(P==null?void 0:P.height)>=u&&(E.isHeavy=!0),z==null||z.debug("[%s] check wind: %j",a.requestId,{...V,dgThd4Wd:h,svThd4Wd:m,hvThd4Wd:b}),(V==null?void 0:V.scale)>=h?(E.isDangerous=!0,delete E.isSevere,delete E.isHeavy):(V==null?void 0:V.scale)>m?(E.isDangerous||(E.isSevere=!0),delete E.isHeavy):(V==null?void 0:V.scale)===b&&!E.isDangerous&&!E.isSevere&&(E.isHeavy=!0),i+=E.isDangerous?J:0,o+=E.isSevere?J:0,n+=E.isHeavy?J:0}return i=Math.round(i*100)/100,o=Math.round(o*100)/100,n=Math.round(n*100)/100,e=Math.round(e),{sample:s,dangerous:i,severe:o,heavy:n,step:e<3?3:e,wind:{dgThd4Wd:h,svThd4Wd:m,hvThd4Wd:b},sig:{dgThd4Wv:c,svThd4Wv:r,hvThd4Wv:u}}}}const bt=new dt;let I;try{I=U.getLogger("vessel")}catch{}finally{}const vt=new ft.MeteoHelper2("",!0);var ut=(D=>(D.common="common",D.container="container",D.tugs="tugs",D))(ut||{}),lt=(D=>(D.Ballast="Ballast",D.Laden="Laden",D))(lt||{}),ht=(D=>(D.Cp="CP",D.Perf="Basis",D.Instruct="Other",D))(ht||{});class W{static blockCoefficient(s,t,a,i){let o=Math.round(s/(t*a*i)*100)/100;o=o<.55?.55:o>.85?.85:o;const n=[.55,.6,.65,.7,.75,.8,.85],e=n.map(c=>Math.abs(c-o));return n[e.indexOf(Math.min(...e))]}static froudeNumber(s,t,a=9.8){let i=Math.round(Math.sqrt(s*s/(a*t))*100)/100;return i=i<.05?.05:i>.3?.3:i,i}static amendFactor(s,t,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]}[s];return a==="Laden"&&(n=i[s]),n[0]+n[1]*t+n[2]*Math.pow(t,2)}static directionFactor(s,t=0){let a;return s>30&&s<=60?a=(1.7-.03*Math.pow(t-4,2))/2:s>60&&s<=150?a=(.9-.06*Math.pow(t-6,2))/2:s>150&&s<=180?a=(.4-.03*Math.pow(t-8,2))/2:a=1,Math.round(a*1e5)/1e5}static vesselTagFactor(s,t,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(s,2/3)):t==="Ballast"?o=.7*i+Math.pow(i,6.5)/(2.7*Math.pow(s,2/3)):o=.5*i+Math.pow(i,6.5)/(2.7*Math.pow(s,2/3)),o}static waveHeightFactor(s,t){s=s<3?s*.7:s,s=s<0?.2:s,s=s>6?s-.9*(s-6):s,s=s>9?9:s;let a;return t>30&&t<=60?a=-.6:t>60&&t<=90?a=-.4:t>90&&t<=120?a=s<3?.4:-.3:t>120&&t<=150?a=s<3?.6:-.5:t>150&&t<=180?a=s<3?.7:-.6:a=-.7,Math.round(a*(.144*Math.pow(s,2)+.278*s)*1e4)/1e4}static assembleProperties(s,t,a,i){var m;const o=s.lbp??s.length??s.lengthOverall??198.9642,n=s.draught??8,e=s.breadthMoulded??s.breadth??s.breadthExtreme??32.4572,c=s.deadweight??67035.7773,r=((m=s==null?void 0:s.type)==null?void 0:m.toLowerCase())||"common";return{tag:r.indexOf("container")>-1?"container":r.indexOf("tugs")>-1?"tugs":"common",lbp:o,loadCondition:t,draught:n,breadthMoulded:e,displacement:Math.round((c/1.025+n*e*o*.7)*1e4)/1e4,speed:Math.round((a??14.1382)*1852/3600*1e4)/1e4,bearing:i||90}}static async speedLoseAt(s,t,a,i="",o=2,n=!0,e=!1,c={}){let r;if(t.velocity&&e&&(s.speed=H.LngLatHelper.roundPrecision(t.velocity*1852/3600,6)),n){let u;try{i=(i==null?void 0:i.toUpperCase())==="CMEMS"?"ECMWF":i,i=(i==null?void 0:i.toUpperCase())==="METEO2"?"best_match":i;const{weatherModels:y,marineModels:j}=await nt.Meteo2Assist.autoPickMeteoModel(i),S=await vt.spotForecast(t.lat,t.lng,a.utc().format(),!1,!1,!0,{...c,pastDays:1,forecastDays:1,weatherModels:y,marineModels:j}),[w]=nt.Meteo2Assist.pickHourly(S,a);u=nt.Meteo2Assist.toLegacy(w)}catch(y){I.warn("[%s] meteo2 spot(%j) forecast failed: %s",c.requestId,{...t,eta:a.utc().format(),source:i},y)}const h=W.weatherFactor(s,u),m=W.currentFactor(s.bearing,u==null?void 0:u.current,o),b=Math.round((s.speed*1.943844+h+m)*100)/100;r={meteo:{...u},wxFactor:h,cFactor:m,speed:t.velocity&&e?t.velocity:b<0?1:b,eta:a.utc().format(),etd:a.utc().format()}}else r={wxFactor:0,cFactor:0,speed:t.velocity&&e?t.velocity:Math.round((s.speed*1.943844+0+0)*100)/100,eta:a.utc().format(),etd:a.utc().format()};return delete t.meteo,delete t.wxFactor,delete t.cFactor,delete t.speed,delete t.etd,{...r,...t}}static async speedLoseInHoursStep(s,t,a,i,o,n,e="",c=!0,r=!1,u={}){t.utc();const h=t.clone().add(14,"days"),m=[],b=[];let y=0,j=0,S,w;for(let v=0;v<n.length-1;v++){let d=n[v];d.distanceFromStart=Math.round((o+j)*1e3)/1e3;const M=n[v+1];if(s.bearing=H.LaneHelper.calculateBearing(d,M,!M.gcToPrevious),d.bearing=s.bearing,d.suspend&&r){d.eta=d.eta||t.utc().format(),d.elapsed=d.elapsed??0;const k=d.suspend-d.elapsed;if(i-y>k)i=i-y-k,t.add(k,"hour"),d.elapsed=d.suspend;else{const C=i-y;d.elapsed+=C,t.add(C,"hour"),i=0}if(I==null||I.info(`[%s] suspend ${d.elapsed} hours at %j, and remain ${i} hours need to go...`,u.requestId,d),i===0)return d.distanceFromPrevious=j,{etd:t,from:w||d,to:d,next:n.filter(C=>C),wps:m,days:b}}else d.suspend=0;c=t.isAfter(h)?!1:c,d=await W.speedLoseAt(s,d,t,e,0,c,r,u),w=w||d,d.important&&m.push(d),t.isSameOrAfter(a)&&(b.push(d),a.add(24,"hour"));const f=H.LaneHelper.calculateDistance(d,M,!M.gcToPrevious);let l=Math.round(f/w.speed*1e5)/1e5;if(y+l<i){if(y+=l,t.add(l,"hour"),delete n[v],I==null||I.debug(`[%s] go to %j from %j with ${f}nm, and cost ${l} hours`,u.requestId,{lat:M.lat,lng:M.lng},{lat:w.lat,lng:w.lng,etd:w.etd}),j+=f,n.filter(k=>k).length<=1){S=M,S.eta=t.utc().format(),S.distanceFromPrevious=f,S.distanceFromStart=Math.round((o+j)*1e4)/1e4,m.push(S),delete n[v+1];break}}else{l=i-y,t.add(l,"hour");const k=H.LngLatHelper.roundPrecision(w.speed*l,5);S=H.LaneHelper.calculateCoordinate(d,s.bearing,k,"nauticalmiles",!M.gcToPrevious),S.eta=t.utc().format(),n[v]=S,I==null||I.debug(`[%s] go to %j from %j with ${k}nm, and cost ${l} hours`,u.requestId,{lat:S.lat,lng:S.lng},{lat:d.lat,lng:d.lng,etd:d.etd}),j+=k,S.distanceFromPrevious=Math.round(j*1e4)/1e4,S.distanceFromStart=Math.round((o+j)*1e4)/1e4;break}}return{etd:t,from:w,to:S,next:n.filter(v=>v),wps:m,days:b}}static currentFactor(s,t,a=0){const i=(s-(t==null?void 0:t.degree)||0)/180*Math.PI;if(Math.abs(i)===Math.PI/2)return 0;let o=((t==null?void 0:t.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(s,t){var h,m,b,y,j,S,w;I==null||I.debug("calculate weather factor via: %j",{...s,...t});const a=W.blockCoefficient(s.displacement,s.lbp,s.breadthMoulded,s.draught),i=W.froudeNumber(s.speed,s.lbp),o=W.amendFactor(a,i,s.loadCondition);let n=Math.abs(s.bearing%360-(((h=t==null?void 0:t.wind)==null?void 0:h.degree)%360||0));n=n>180?360-n:n;const e=W.directionFactor(n,(m=t==null?void 0:t.wind)==null?void 0:m.scale),c=W.vesselTagFactor(s.displacement,s.loadCondition,s.tag,(b=t==null?void 0:t.wind)==null?void 0:b.scale);let r=e*o*c/100*s.speed;r=Math.round(r*1.943844*1e4)/1e4*-1,s.tag==="tugs"&&Math.abs(r)>1&&(r=r/(Math.abs(Math.round(r))+1)),I==null||I.debug("wind wx factor = %d",r),n=Math.abs(s.bearing%360-(((j=(y=t==null?void 0:t.wave)==null?void 0:y.sig)==null?void 0:j.degree)%360||0));const u=W.waveHeightFactor(((w=(S=t==null?void 0:t.wave)==null?void 0:S.sig)==null?void 0:w.height)??1,n);return I==null||I.debug("wave wx factor = %d",u),r=Math.abs(r)>Math.abs(u)?r:r*.3+u*.7,I==null||I.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(s,t,a,i,o,n="",e=0,c=!0,r=!1,u={}){var X,Q,Z,$,tt,et;const h=g().valueOf();s.lng=H.LngLatHelper.convertToStdLng(s.lng);const{route:m,waypoints:b}=o.points,y=H.LaneHelper.calculateSubRoute(s,m);if(((X=y[0])==null?void 0:X.length)<=1)return;const{v0:j,label:S}=s.sog?{v0:s.sog,label:s.label||"Other"}:{v0:i.speed,label:"CP"},w=W.assembleProperties(a,i.loadCondition,j,0),v=b.length?H.LaneHelper.calculateSubWaypoints(s,b):[];v.forEach(O=>O.important=!0);const d={from:{...s},route:y,waypoints:v,v0:j,label:S},M={hours:[],days:[],wps:[]};e||(H.LaneHelper.calculateRouteDistance(y)/i.speed<=72?e=3:e=6);let f=H.LaneHelper.simplifyRouteToCoordinates(y,v,0),l=0,k=0,C=0,x=0;t=g(t).utc();const Y=t.clone();for(;f.length>0;){const O=e-t.hour()%e,_=Math.ceil(t.clone().add(O,"h").set({minute:0,second:0,millisecond:0}).diff(t,"h",!0)*1e4)/1e4,F=await W.speedLoseInHoursStep(w,t,Y,_,l,f,n,c,r,u);(Q=F.from)!=null&&Q.speed&&(M.hours.push(F.from),M.wps.push(...F.wps),M.days.push(...F.days)),f=F==null?void 0:F.next,f.length||M.hours.push(F==null?void 0:F.to),l+=Math.round((((Z=F==null?void 0:F.to)==null?void 0:Z.distanceFromPrevious)??0)*1e4)/1e4}const T=M.hours;for(let O=0;O<T.length-1;O++){const _=g(T[O+1].eta).diff(T[O].etd,"hour",!0)||1;k+=(T[O].wxFactor||0)*_,C+=(T[O].cFactor||0)*_,x+=_}($=M.wps)==null||$.forEach((O,_)=>{O.positionTime=g.utc(O.etd||O.eta).unix();const F=M.wps[_-1];if(F){const B=O.distanceFromStart-F.distanceFromStart,R=g(O.eta||O.etd).diff(g(F.etd||F.eta),"h",!0);O.avgSpd=Math.round(B/R*100)/100,F.bearing=H.LaneHelper.calculateBearing(F,O)}}),M.wps=(tt=M.wps)==null?void 0:tt.reduce((O,_)=>(O.some(F=>Math.round(F.positionTime/60)===Math.round(_.positionTime/60))||O.push(_),O),[]),d.sample=M;const L=M.hours.at(0),N=M.hours.at(-1);d.distance=Math.round(N.distanceFromStart*1e3)/1e3,d.etd=g(L.eta).utc().format(),d.eta=g(N.eta).utc().format(),d.wxFactor=Math.round(k/x*1e3)/1e3,d.cFactor=Math.round(C/x*1e3)/1e3,d.avgSpeed=Math.round(N.distanceFromStart/x*1e3)/1e3,d.totalHrs=Math.round(x*1e3)/1e3;const{distanceInECA:E,hoursInECA:P,totalDgoConsInECA:V,eca:J}=await this.calculateECA(d,i,u),st=H.LngLatHelper.roundPrecision(i.fo/24*(x-P),3),ot=H.LngLatHelper.roundPrecision(i.dgo/24*x,3);d.extend={eca:J,distanceInECA:E,hoursInECA:P,totalDgoConsInECA:V},d.totalFoCons=st<0?0:st,d.totalDgoCons=ot;const at=g().valueOf()-h,rt=((et=M==null?void 0:M.hours)==null?void 0:et.length)||1;return I==null||I.info("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms",u==null?void 0:u.requestId,at,rt,Math.round(at/rt*1e3)/1e3),d}static async analyseInstantWithThreshed(s,t,a,i,o,n,e,c="",r=3,u=!0,h=!1,m={}){var Z,$,tt,et,O,_;const b=g().valueOf();s.lng=H.LngLatHelper.convertToStdLng(s.lng);const{v0:y,label:j}=s.sog?{v0:s.sog,label:s.label||"Other"}:{v0:o.speed,label:"CP"},S=W.assembleProperties(i,o.loadCondition,y,0),w=H.LaneHelper.calculateSubRoute(s,n);if(((Z=w[0])==null?void 0:Z.length)<=1)return;const v=e.length?H.LaneHelper.calculateSubWaypoints(s,e):[];v.forEach(F=>F.important=!0);let d=H.LaneHelper.simplifyRouteToCoordinates(w,v,0),M=0,f=0,l=0,k=0;const C={hours:[],wps:[],days:[]};t=g(t).utc();const x=t.clone();for(;d.length>0;){const F=r-t.hour()%r;let B=Math.ceil(t.clone().add(F,"h").set({minute:0,second:0,millisecond:0}).diff(t,"h",!0)*1e4)/1e4;B=t.clone().add(B,"h").isSameOrAfter(a)?a.diff(t,"h",!0)*1e4/1e4:B;const R=await W.speedLoseInHoursStep(S,t,x,B,M,d,c,u,h,m);if(($=R.from)!=null&&$.speed&&(C.hours.push(R.from),R!=null&&R.wps&&C.wps.push(...R.wps),C.days.push(...R.days)),d=R==null?void 0:R.next,d.length||C.hours.push(R==null?void 0:R.to),M+=Math.round((((tt=R==null?void 0:R.to)==null?void 0:tt.distanceFromPrevious)??0)*1e4)/1e4,!B)break}C.wps=(et=C.wps)==null?void 0:et.reduce((F,B)=>(F.some(R=>Math.round(g(R.etd).unix()/60)===Math.round(g(B.etd).unix()/60))||F.push(B),F),[]),(O=C.wps)==null||O.forEach((F,B)=>{const R=C.wps[B-1];if(R){const gt=F.distanceFromStart-R.distanceFromStart,wt=g(F.eta||F.etd).diff(g(R.etd||R.eta),"h",!0);F.avgSpd=Math.round(gt/wt*100)/100;const kt=H.LaneHelper.calculateBearing(R,F);R.bearing=kt}});const Y=C.hours;for(let F=0;F<Y.length-1;F++){const B=g(Y[F+1].eta).diff(Y[F].etd,"hour",!0);f+=Y[F].wxFactor*B,l+=Y[F].cFactor*B,k+=B}const T=C.hours.at(0),L=C.hours.at(-1),N=await H.LaneHelper.calculateRangeRoute(T,L,w),E=await H.LaneHelper.calculateRangeWaypoints(T,L,w,v),P={sample:C,distance:Math.round(((L==null?void 0:L.distanceFromStart)||0)*1e4)/1e4,etd:g(T.eta).utc().format(),eta:g(L==null?void 0:L.eta).utc().format(),wxFactor:Math.round(f/k*1e3)/1e3,cFactor:Math.round(l/k*1e3)/1e3,avgSpeed:Math.round(((L==null?void 0:L.distanceFromStart)||0)/k*1e3)/1e3,totalHrs:Math.round(k*1e3)/1e3,from:T,to:L,route:N,waypoints:E,v0:y,label:j},{distanceInECA:V,hoursInECA:J,totalDgoConsInECA:st,eca:ot}=await this.calculateECA(P,o,m),it=H.LngLatHelper.roundPrecision(o.fo/24*(k-J),3),at=H.LngLatHelper.roundPrecision(o.dgo/24*k,3);P.extend={eca:ot,distanceInECA:V,hoursInECA:J,totalDgoConsInECA:st},P.totalDgoCons=at,P.totalFoCons=it<0?0:it;const X=g().valueOf()-b,Q=((_=C==null?void 0:C.hours)==null?void 0:_.length)||1;return I==null||I.debug("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms",m==null?void 0:m.requestId,X,Q,Math.round(X/Q*1e3)/1e3),P}static async analyseCost(s,t,a,i,o={}){var w,v;const n=g().valueOf(),e=[];s.speedStep=s.speedStep||3,s.alterStep=s.alterStep??1;const c=H.LaneHelper.calculateRouteDistance(i.route);let r=0;a.forEach(d=>{const M=Math.ceil(c/d.speed/24);r=r<M?M:r}),r=r*1.3;const u=g.utc(s.etd).add(r??14,"day");let h=1;for(const d of a){const M=JSON.parse(JSON.stringify(i.route)),f=JSON.parse(JSON.stringify(i.waypoints)),l=await W.analyseInstantWithThreshed({lat:s.lat,lng:s.lng},s.etd,u,t,d,M,f,s.meteoVendor,s.speedStep,s.useMeteo,s.useRouteParam,o);l&&(await W.calculateCost(l,d,s,o),e.push(l),I==null||I.info("[%s][L%d-%d] analyse from %s to %s cost: %j",o.requestId,1,h,s.etd,u.format(),{cost:l.cost.total,hire:l.cost.hire,bunker:l.cost.bunker,distance:l.distance,hours:l.totalHrs,cp:`${d.speed}/${d.fo}/${d.dgo}`})),h++}e.sort((d,M)=>d.cost.total-M.cost.total);const m=e.at(0),b=e.at(1),y=[];if(y.push({combined:!1,speeds:[m],cost:(w=m.cost)==null?void 0:w.total}),b){const d=m.cost.cp,M=b.cost.cp,f=g(m.eta),l=g(m.etd),k=f.diff(l,"days",!0);let C=Math.ceil(k/2);C=C>7?7:C<s.alterStep?s.alterStep:C;let x=2,Y={combined:!1,speeds:[b],cost:(v=b.cost)==null?void 0:v.total},T;for(;C>=s.alterStep;){const L=await W.combinedAnalyse(s,t,u,[d,M],i,C,{...o,level:x});if(Y.cost>L.cost?T?(T==null?void 0:T.cost)>L.cost&&(T=L):(T=Y,Y=L):(!T||(T==null?void 0:T.cost)>L.cost)&&(T=L),C<=s.alterStep)break;C=Math.ceil(C/2),x+=1}y.push(Y),T&&y.push(T)}const S=g().valueOf()-n;return I==null||I.info("[%s] analyse elapsed: %d ms",o==null?void 0:o.requestId,S),y.sort((d,M)=>d.cost-M.cost)}static async combinedAnalyse(s,t,a,i,o,n,e={}){e.counter=1,I==null||I.info("[%s][L%d] analyse with alternate cp in every %d days",e.requestId,e.level,n);const c=await W.alternateAnalyse(s,t,a,i,0,o,n,e),r=c.reduce((M,f)=>M+f.cost.total,0),u=c.reduce((M,f)=>M+f.cost.hire,0),h=c.reduce((M,f)=>M+f.cost.bunker,0),m=c.reduce((M,f)=>M+f.distance,0),b=c.reduce((M,f)=>M+f.totalHrs,0);I==null||I.info("[%s][L%d] cost with cpa/cpb turn: %j",e.requestId,e.level,{cost:r,hire:u,bunker:h,distance:m,hours:b});const y=await W.alternateAnalyse(s,t,a,i,1,o,n,e),j=y.reduce((M,f)=>M+f.cost.total,0),S=y.reduce((M,f)=>M+f.cost.hire,0),w=y.reduce((M,f)=>M+f.cost.bunker,0),v=y.reduce((M,f)=>M+f.distance,0),d=y.reduce((M,f)=>M+f.totalHrs,0);return I==null||I.info("[%s][L%d] cost with cpb/cpa turn: %j",e.requestId,e.level,{cost:j,hire:S,bunker:w,distance:v,hours:d}),r<j?{combined:!0,cost:Math.round(r*1e3)/1e3,speeds:c,step:n}:{combined:!0,cost:Math.round(j*1e3)/1e3,speeds:y,step:n}}static async alternateAnalyse(s,t,a,i,o,n,e,c={}){var m,b;let r=g.utc(s.etd);const u={lat:s.lat,lng:s.lng},h=[];for(;r.isBefore(a);){const y=r.clone().utc().add(e,"day"),j=JSON.parse(JSON.stringify(n.route)),S=JSON.parse(JSON.stringify(n.waypoints)),w=i[o],v=await W.analyseInstantWithThreshed(u,r.utc().format(),y,t,w,j,S,s.meteoVendor,s.speedStep,s.useMeteo,s.useRouteParam,c);v&&(await W.calculateCost(v,w,s,c),I==null||I.info("[%s][L%d-%d] analyse from %s to %s cost: %j",c.requestId,c.level,c.counter,r.utc().format(),y.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}`})),c.counter=c.counter+1;const d=(b=(m=v==null?void 0:v.sample)==null?void 0:m.hours)==null?void 0:b.at(-1);if(d)u.lat=d.lat,u.lng=d.lng,r=g(d.eta),h.push(v),o=o?0:1;else break}return h}static async calculateCost(s,t,a,i={}){var o;if(s){const n=(a.addComm||0)>=1?(a.addComm||0)/100:a.addComm||0,e=Math.round(s.totalHrs/24*(a.dailyHire||0)*(1-n)*1e3)/1e3,c=Math.round(s.totalFoCons*(a.priceFO||0)*1e3)/1e3,r=Math.round((s.totalDgoCons+(((o=s.extend)==null?void 0:o.totalDgoConsInECA)||0))*(a.priceDGO||0)*1e3)/1e3;s.cost={total:Math.round((e+c+r)*1e3)/1e3,hire:e,bunker:Math.round((c+r)*1e3)/1e3,cp:t}}return s}static async calculateECA(s,t,a={}){var c,r,u,h;const i=await H.LaneHelper.intersectInECA((s==null?void 0:s.route)||[]);let o=0,n=0,e=0;(r=(c=s==null?void 0:s.sample)==null?void 0:c.wps)==null||r.forEach(m=>{m.positionTime=g.utc(m.etd||m.eta).unix()});for(const m of i){o+=m.distance;const b=await H.LaneHelper.deadReckoningTime((u=m.waypoints)==null?void 0:u.at(0),s.sample.wps),y=await H.LaneHelper.deadReckoningTime((h=m.waypoints)==null?void 0:h.at(-1),s.sample.wps);m.in=b,m.out=y,m.totalHrs=H.LngLatHelper.roundPrecision((y.positionTime-b.positionTime)/3600,3),m.totalDgoCons=H.LngLatHelper.roundPrecision(t.fo/24*m.totalHrs,3),n+=m.totalHrs,e+=m.totalDgoCons}return o=H.LngLatHelper.roundPrecision(o,3),n=H.LngLatHelper.roundPrecision(n,3),e=H.LngLatHelper.roundPrecision(e,3),{distanceInECA:o,hoursInECA:n,totalDgoConsInECA:e,eca:i}}static async mergeSpeeds(s,t={}){var d,M;const a={hours:[],wps:[],days:[]},i=s.reduce((f,l)=>f+l.distance,0),o=s.reduce((f,l)=>{var k;return f+(((k=l.extend)==null?void 0:k.distanceInECA)||0)},0),n=s.reduce((f,l)=>f+l.totalHrs,0),e=s.reduce((f,l)=>{var k;return f+(((k=l.extend)==null?void 0:k.hoursInECA)||0)},0),c=s.reduce((f,l)=>{var k;return f+(((k=l.extend)==null?void 0:k.totalDgoConsInECA)||0)},0),r=s.reduce((f,l)=>f+l.wxFactor*l.totalHrs/n,0),u=s.reduce((f,l)=>f+l.cFactor*l.totalHrs/n,0),h=s.reduce((f,l)=>f+l.totalFoCons,0),m=s.reduce((f,l)=>f+l.totalDgoCons,0),b=s.reduce((f,l)=>f+l.cost.total,0),y=s.reduce((f,l)=>f+l.cost.hire,0),j=s.reduce((f,l)=>f+l.cost.bunker,0),S=[],w=[];let v;for(const f of s){w.push(...((d=f.extend)==null?void 0:d.eca)||[]);const l=f.sample.hours,k=f.sample.wps,C=f.sample.days,x=l.at(0);v&&(x.distanceFromPrevious=v.distanceFromPrevious,x.distanceFromStart=v.distanceFromStart,l.forEach((N,E)=>{E&&(N.distanceFromStart=N.distanceFromStart+v.distanceFromStart)}),k.at(0).distanceFromPrevious=v.distanceFromPrevious,k.at(0).distanceFromStart=v.distanceFromStart,k.forEach((N,E)=>{E&&(N.distanceFromStart=N.distanceFromStart+v.distanceFromStart)}),C.at(0).distanceFromPrevious=v.distanceFromPrevious,C.at(0).distanceFromStart=v.distanceFromStart,C.forEach((N,E)=>{E&&(N.distanceFromStart=N.distanceFromStart+v.distanceFromStart)})),x.cp=f.cost.cp;const Y=[f.etd,f.eta],T=S.findIndex(N=>N.id===x.cp.id);T===-1?(x.cp.segment=[Y],S.push(x.cp)):S[T].segment.push(Y),l.forEach(N=>{var P;((P=a.hours)==null?void 0:P.findIndex(V=>V.eta===N.eta))===-1&&a.hours.push(N)}),k.forEach(N=>{var P;((P=a.wps)==null?void 0:P.findIndex(V=>V.eta===N.eta))===-1&&a.wps.push(N)}),C.forEach(N=>{var P;((P=a==null?void 0:a.days)==null?void 0:P.findIndex(V=>V.eta===N.eta))===-1&&a.days.push(N)});const L=(M=a.wps)==null?void 0:M.findIndex(N=>N.eta===x.eta);L===-1?a.wps.push(x):a.wps[L]=x,v=l.at(-1)}return a.wps.sort((f,l)=>{g(f.etd).unix()-g(l.etd).unix()}),a.wps.forEach((f,l)=>{const k=a.wps[l-1];if(k){const C=f.distanceFromStart-(k.distanceFromStart||0),x=g(f.eta||f.etd).diff(g(k.etd||k.eta),"hour",!0),Y=Math.round(C/x*100)/100;f.avgSpd=Y;const T=H.LaneHelper.calculateBearing(k,f);k.bearing=T}}),{sample:a,etd:s.at(0).etd,eta:s.at(-1).eta,from:s.at(0).from,to:s.at(-1).to,v0:s.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(u*1e3)/1e3,totalFoCons:Math.round(h*1e3)/1e3,totalDgoCons:Math.round(m*1e3)/1e3,cost:{total:Math.round(b*1e3)/1e3,hire:Math.round(y*1e3)/1e3,bunker:Math.round(j*1e3)/1e3},extend:{cps:S,eca:w,distanceInECA:Math.round(o*1e3)/1e3,hoursInECA:Math.round(e*1e3)/1e3,totalDgoConsInECA:Math.round(c*1e3)/1e3,speeds:s}}}}q.AISImpl=G,q.AlertHelper=dt,q.AlertLevel=ct,q.HifleetImpl=yt,q.LoadCondition=lt,q.MyShipImpl=Mt,q.MyVesselImpl=mt,q.ShipxyImpl=pt,q.SpeedHelper=W,q.SpeedLabel=ht,q.VesselTag=ut,q.alertHelper=bt,Object.defineProperty(q,Symbol.toStringTag,{value:"Module"})});
|
|
@@ -230,10 +230,12 @@ export declare class SpeedHelper {
|
|
|
230
230
|
* @param vessel 船舶属性 @see VesselAssemble, 注意吃水为船舶实时吃水,非档案中的固定吃水,一般可以从ais获取; 如获取不得,用档案吃水代替
|
|
231
231
|
* @param cp { loadCondition, speed } LoadCondition: Ballast or Laden, speed(kts)
|
|
232
232
|
* @param route 航路[[[lng, lat]]]
|
|
233
|
+
* @param waypoints
|
|
233
234
|
* @param source 气象数据源,GFS or CMEMES, 默认CMEMS
|
|
234
235
|
* @param stepHrs
|
|
235
236
|
* @param useMeteo true 启用气象分析
|
|
236
237
|
* @param useRouteParam
|
|
238
|
+
* @param options
|
|
237
239
|
*/
|
|
238
240
|
static analyseInstantWithThreshed(from: any, etd: string | moment.Moment | number, threshed: moment.Moment, vessel: VesselAssemble, cp: CpProps, route: number[][][], waypoints: any[], source?: string, stepHrs?: number, useMeteo?: boolean, useRouteParam?: boolean, options?: {
|
|
239
241
|
requestId?: string;
|