@idm-plugin/vessel 3.7.9 → 3.8.1
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 +118 -118
- package/dist/index.umd.cjs +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -260,9 +260,9 @@ class Tt extends nt {
|
|
|
260
260
|
json: l
|
|
261
261
|
};
|
|
262
262
|
g == null || g.info("[%s] fetch route from: %s - %j", s.requestId, u, h);
|
|
263
|
-
const
|
|
264
|
-
if (
|
|
265
|
-
return g == null || g.warn("[%s] fetch route failed: %j", s.requestId, { message:
|
|
263
|
+
const c = await z.post(u, h).json();
|
|
264
|
+
if (c.status !== 200)
|
|
265
|
+
return g == null || g.warn("[%s] fetch route failed: %j", s.requestId, { message: c.message, status: c.status, code: c.code }), {};
|
|
266
266
|
{
|
|
267
267
|
const k = {
|
|
268
268
|
status: "Success",
|
|
@@ -273,7 +273,7 @@ class Tt extends nt {
|
|
|
273
273
|
route: [],
|
|
274
274
|
distance: 0,
|
|
275
275
|
memo: ""
|
|
276
|
-
}, { nodes: w, seas: v, tracks: m, specialRegions:
|
|
276
|
+
}, { nodes: w, seas: v, tracks: m, specialRegions: d, ecaLength: f } = c.data;
|
|
277
277
|
k.nodes = w == null ? void 0 : w.map((M) => ({
|
|
278
278
|
code: M.nodeCode,
|
|
279
279
|
nameEn: M.nameEn,
|
|
@@ -314,7 +314,7 @@ class Tt extends nt {
|
|
|
314
314
|
lng: Math.round(M.maxLon * 1e6) / 1e6
|
|
315
315
|
},
|
|
316
316
|
level: M.mapLevel
|
|
317
|
-
})),
|
|
317
|
+
})), d == null || d.map((M) => {
|
|
318
318
|
M.regionLength && k.regions.push({
|
|
319
319
|
type: M.regionType,
|
|
320
320
|
distance: M.regionLength,
|
|
@@ -357,12 +357,12 @@ class Tt extends nt {
|
|
|
357
357
|
const h = await z.post(u, l).json();
|
|
358
358
|
if (h.code)
|
|
359
359
|
return g == null || g.warn("[%s] fetch trajectory failed: %j", r.requestId, u, { message: h.message, status: h.status, code: h.code }), h;
|
|
360
|
-
let
|
|
360
|
+
let c = -1;
|
|
361
361
|
const I = p(`${(w = (k = h.data) == null ? void 0 : k[0]) == null ? void 0 : w.postime} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
362
362
|
return (v = h.data) == null || v.forEach((m) => {
|
|
363
363
|
for (const N in m)
|
|
364
364
|
!isNaN(m[N]) && Number(m[N]) !== 1 / 0 && (m[N] = Number(m[N]));
|
|
365
|
-
const
|
|
365
|
+
const d = p(`${m.postime} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00"), f = m.status, { labelCn: y, labelEn: S } = this.parseStatus(f), M = {
|
|
366
366
|
mmsi: m.mmsi,
|
|
367
367
|
imo: i == null ? void 0 : i.imo,
|
|
368
368
|
lat: m.lat,
|
|
@@ -374,14 +374,14 @@ class Tt extends nt {
|
|
|
374
374
|
status: f,
|
|
375
375
|
eta: /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(m.eta) ? p(`${m.eta} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00").utc().format() : void 0,
|
|
376
376
|
destination: m.dest,
|
|
377
|
-
positionTime:
|
|
377
|
+
positionTime: d.unix(),
|
|
378
378
|
labelCn: y,
|
|
379
379
|
labelEn: S,
|
|
380
380
|
method: "trajectory",
|
|
381
381
|
vendor: "myVessel",
|
|
382
|
-
utc:
|
|
383
|
-
}, j = Math.floor(
|
|
384
|
-
j !==
|
|
382
|
+
utc: d.utc().format()
|
|
383
|
+
}, j = Math.floor(d.diff(I, "minute", !0) / (a || 1));
|
|
384
|
+
j !== c && (c = j, s.push(M));
|
|
385
385
|
}), s;
|
|
386
386
|
}
|
|
387
387
|
}
|
|
@@ -487,7 +487,7 @@ class jt extends nt {
|
|
|
487
487
|
return s.sort((r, u) => u.score - r.score), s;
|
|
488
488
|
}
|
|
489
489
|
async trajectory(t, n, o, i, a = !0, s = {}) {
|
|
490
|
-
var m,
|
|
490
|
+
var m, d, f;
|
|
491
491
|
const r = await this.realTimePosition(t, s);
|
|
492
492
|
let u = p(n);
|
|
493
493
|
const l = p(o), h = p();
|
|
@@ -495,17 +495,17 @@ class jt extends nt {
|
|
|
495
495
|
let y = l.diff(u, "d", !0);
|
|
496
496
|
y < 0 ? u = l.clone().subtract(40, "d") : y < 30 ? u.subtract(10, "d") : y < 60 ? u.subtract(5, "d") : u = l.clone().subtract(80, "d"), y = h.diff(l, "d", !0), l.add(y > 10 ? 240 : y * 24, "h");
|
|
497
497
|
}
|
|
498
|
-
const
|
|
498
|
+
const c = {
|
|
499
499
|
searchParams: {
|
|
500
500
|
endtime: l.utcOffset("+8:00").format("YYYY-MM-DD HH:mm:ss"),
|
|
501
501
|
starttime: u.utcOffset("+8:00").format("YYYY-MM-DD HH:mm:ss"),
|
|
502
502
|
mmsi: t,
|
|
503
503
|
usertoken: this.token
|
|
504
504
|
}
|
|
505
|
-
}, I = "https://api.hifleet.com/position/trajectory/nocompressed/withstatic/token", b = await z.get(I,
|
|
506
|
-
g == null || g.info("[%s] fetch trajectory from: %s - %j", s.requestId, I,
|
|
505
|
+
}, I = "https://api.hifleet.com/position/trajectory/nocompressed/withstatic/token", b = await z.get(I, c).json();
|
|
506
|
+
g == null || g.info("[%s] fetch trajectory from: %s - %j", s.requestId, I, c);
|
|
507
507
|
let E;
|
|
508
|
-
b && (E = ((
|
|
508
|
+
b && (E = ((d = (m = b.ships) == null ? void 0 : m.offors) == null ? void 0 : d.ship) || [], E.length || g == null || g.warn("[%s] fetch trajectory failed: %j", s.requestId, b));
|
|
509
509
|
const k = [];
|
|
510
510
|
let w = -1;
|
|
511
511
|
const v = p(`${(f = E == null ? void 0 : E[0]) == null ? void 0 : f.ti} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
@@ -554,8 +554,8 @@ class xt extends nt {
|
|
|
554
554
|
if (g == null || g.info("[%s] fetch realtime position from: %s - %j", n.requestId, i, o), (a == null ? void 0 : a.status) !== 0)
|
|
555
555
|
return a;
|
|
556
556
|
const s = a.data[0];
|
|
557
|
-
for (const
|
|
558
|
-
!isNaN(s[
|
|
557
|
+
for (const c in s)
|
|
558
|
+
!isNaN(s[c]) && Number(s[c]) !== 1 / 0 && (s[c] = Number(s[c]));
|
|
559
559
|
const { labelCn: r, labelEn: u } = await this.parseStatus(s.navistat), l = p.unix(s.lasttime);
|
|
560
560
|
return {
|
|
561
561
|
mmsi: s.ShipID,
|
|
@@ -582,7 +582,7 @@ class xt extends nt {
|
|
|
582
582
|
}
|
|
583
583
|
async trajectory(t, n, o, i, a = !0, s = {}) {
|
|
584
584
|
var v;
|
|
585
|
-
const r = await this.realTimePosition(t, s), u = p(n), l = p(o), h = "https://api.shipxy.com/apicall/GetShipTrack",
|
|
585
|
+
const r = await this.realTimePosition(t, s), u = p(n), l = p(o), h = "https://api.shipxy.com/apicall/GetShipTrack", c = {
|
|
586
586
|
searchParams: {
|
|
587
587
|
id: t,
|
|
588
588
|
k: this.token,
|
|
@@ -591,24 +591,24 @@ class xt extends nt {
|
|
|
591
591
|
btm: u.unix(),
|
|
592
592
|
etm: l.unix()
|
|
593
593
|
}
|
|
594
|
-
}, I = await z.get(h,
|
|
595
|
-
if (g == null || g.info("[%s] fetch trajectory from: %s - %j", s.requestId, h,
|
|
594
|
+
}, I = await z.get(h, c).json();
|
|
595
|
+
if (g == null || g.info("[%s] fetch trajectory from: %s - %j", s.requestId, h, c), (I == null ? void 0 : I.status) !== 0)
|
|
596
596
|
return I;
|
|
597
597
|
const b = I == null ? void 0 : I.points, E = [], k = p.unix((v = b[0]) == null ? void 0 : v.utc);
|
|
598
598
|
let w = -1;
|
|
599
599
|
for (const m of b) {
|
|
600
|
-
const
|
|
600
|
+
const d = p.unix(m.utc), f = {
|
|
601
601
|
imo: r == null ? void 0 : r.imo,
|
|
602
602
|
mmsi: t,
|
|
603
603
|
sog: Math.round(m.sog * 3600 / 1e3 / 1852 * 100) / 100,
|
|
604
604
|
cog: Math.round(m.cog / 100 * 100) / 100,
|
|
605
605
|
lat: Math.round(m.lat / 1e6 * 1e5) / 1e5,
|
|
606
606
|
lng: Math.round(m.lon / 1e6 * 1e5) / 1e5,
|
|
607
|
-
positionTime:
|
|
608
|
-
utc:
|
|
607
|
+
positionTime: d.unix(),
|
|
608
|
+
utc: d.utc().format(),
|
|
609
609
|
method: "trajectory",
|
|
610
610
|
vendor: "shipxy"
|
|
611
|
-
}, y = Math.floor(
|
|
611
|
+
}, y = Math.floor(d.diff(k, "minute", !0) / (i || 1));
|
|
612
612
|
y !== w && (w = y, E.push(f));
|
|
613
613
|
}
|
|
614
614
|
return E;
|
|
@@ -667,7 +667,7 @@ class Nt extends nt {
|
|
|
667
667
|
const u = r.data[0];
|
|
668
668
|
for (const b in u)
|
|
669
669
|
!isNaN(u[b]) && Number(u[b]) !== 1 / 0 && (u[b] = Number(u[b]));
|
|
670
|
-
const { labelCn: l, labelEn: h } = await this.parseStatus(u.aisNavStatus),
|
|
670
|
+
const { labelCn: l, labelEn: h } = await this.parseStatus(u.aisNavStatus), c = p.unix(u.posTime);
|
|
671
671
|
return {
|
|
672
672
|
...i,
|
|
673
673
|
mmsi: t,
|
|
@@ -678,7 +678,7 @@ class Nt extends nt {
|
|
|
678
678
|
hdg: Math.round(u.heading * 100) / 100,
|
|
679
679
|
rot: Math.round(u.rot * 100) / 100,
|
|
680
680
|
positionTime: u.posTime,
|
|
681
|
-
utc:
|
|
681
|
+
utc: c.utc().format(),
|
|
682
682
|
status: u.aisNavStatus,
|
|
683
683
|
labelEn: h,
|
|
684
684
|
labelCn: l,
|
|
@@ -687,10 +687,10 @@ class Nt extends nt {
|
|
|
687
687
|
};
|
|
688
688
|
}
|
|
689
689
|
async trajectory(t, n, o, i, a = !0, s = {}) {
|
|
690
|
-
const r = p(n), u = p(o), l = await this.getShipId(t), h = await this.getShipInfo(l),
|
|
690
|
+
const r = p(n), u = p(o), l = await this.getShipId(t), h = await this.getShipInfo(l), c = [];
|
|
691
691
|
for (; u.diff(r, "day", !0) > 30; )
|
|
692
|
-
await this.trajectoryIn30Day(l, r.unix(), r.add(30, "day").unix(), h, t, i,
|
|
693
|
-
return await this.trajectoryIn30Day(l, r.unix(), u.unix(), h, t, i,
|
|
692
|
+
await this.trajectoryIn30Day(l, r.unix(), r.add(30, "day").unix(), h, t, i, c);
|
|
693
|
+
return await this.trajectoryIn30Day(l, r.unix(), u.unix(), h, t, i, c), c;
|
|
694
694
|
}
|
|
695
695
|
async trajectoryIn30Day(t, n, o, i, a, s, r, u = {}) {
|
|
696
696
|
var k;
|
|
@@ -703,10 +703,10 @@ class Nt extends nt {
|
|
|
703
703
|
startTime: n,
|
|
704
704
|
endTime: o
|
|
705
705
|
}
|
|
706
|
-
}, h = "https://api3.myships.com/sp/ships/position/history",
|
|
707
|
-
if (g == null || g.info("[%s] fetch trajectory from: %s - %j", u.requestId, h, l),
|
|
708
|
-
return g == null || g.warn("[%s] invoke myship trajectory failed: %j", u.requestId,
|
|
709
|
-
const I =
|
|
706
|
+
}, h = "https://api3.myships.com/sp/ships/position/history", c = await z.post(h, l).json();
|
|
707
|
+
if (g == null || g.info("[%s] fetch trajectory from: %s - %j", u.requestId, h, l), c.code !== "0")
|
|
708
|
+
return g == null || g.warn("[%s] invoke myship trajectory failed: %j", u.requestId, c), c;
|
|
709
|
+
const I = c.data;
|
|
710
710
|
for (const w in I)
|
|
711
711
|
!isNaN(I[w]) && Number(I[w]) !== 1 / 0 && (I[w] = Number(I[w]));
|
|
712
712
|
const b = p.unix((k = I[0]) == null ? void 0 : k.posTime);
|
|
@@ -725,8 +725,8 @@ class Nt extends nt {
|
|
|
725
725
|
utc: v.utc().format(),
|
|
726
726
|
method: "trajectory",
|
|
727
727
|
vendor: "myship"
|
|
728
|
-
},
|
|
729
|
-
|
|
728
|
+
}, d = Math.floor(v.diff(b, "minute", !0) / (s || 1));
|
|
729
|
+
d !== E && (E = d, r.push(m));
|
|
730
730
|
}
|
|
731
731
|
return r;
|
|
732
732
|
}
|
|
@@ -759,8 +759,8 @@ class Mt {
|
|
|
759
759
|
if (l === 0 && !h)
|
|
760
760
|
a.scope = i[0];
|
|
761
761
|
else if (h)
|
|
762
|
-
for (let
|
|
763
|
-
const b = this.parseRule(h[
|
|
762
|
+
for (let c = 0, I = h.length; c < I; c++) {
|
|
763
|
+
const b = this.parseRule(h[c]);
|
|
764
764
|
b && (a[b.level] ? b.key ? a[b.level][b == null ? void 0 : b.key] = b : a[b.level] = b : b.key ? a[b.level] = { [b == null ? void 0 : b.key]: b } : a[b.level] = b);
|
|
765
765
|
}
|
|
766
766
|
}
|
|
@@ -794,14 +794,14 @@ class Mt {
|
|
|
794
794
|
* @param options
|
|
795
795
|
*/
|
|
796
796
|
checkWeather(e, t, n = {}) {
|
|
797
|
-
var b, E, k, w, v, m,
|
|
797
|
+
var b, E, k, w, v, m, d, f, y, S, M, j, N, D, L;
|
|
798
798
|
let o = 0, i = 0, a = 0, s = 0;
|
|
799
|
-
const r = Math.round(((E = (b = t == null ? void 0 : t.SEVERE) == null ? void 0 : b.sigWave) == null ? void 0 : E.number) * 1.6 * 100) / 100, u = (w = (k = t == null ? void 0 : t.SEVERE) == null ? void 0 : k.sigWave) == null ? void 0 : w.number, l = (m = (v = t == null ? void 0 : t.HEAVY) == null ? void 0 : v.sigWave) == null ? void 0 : m.number, h = Math.round((((f = (
|
|
799
|
+
const r = Math.round(((E = (b = t == null ? void 0 : t.SEVERE) == null ? void 0 : b.sigWave) == null ? void 0 : E.number) * 1.6 * 100) / 100, u = (w = (k = t == null ? void 0 : t.SEVERE) == null ? void 0 : k.sigWave) == null ? void 0 : w.number, l = (m = (v = t == null ? void 0 : t.HEAVY) == null ? void 0 : v.sigWave) == null ? void 0 : m.number, h = Math.round((((f = (d = t == null ? void 0 : t.SEVERE) == null ? void 0 : d.wind) == null ? void 0 : f.number) + 2) * 100) / 100, c = (S = (y = t == null ? void 0 : t.SEVERE) == null ? void 0 : y.wind) == null ? void 0 : S.number, I = (j = (M = t == null ? void 0 : t.HEAVY) == null ? void 0 : M.wind) == null ? void 0 : j.number;
|
|
800
800
|
for (let W = 0; W < (e == null ? void 0 : e.length); W++) {
|
|
801
801
|
const F = e[W], Y = (D = (N = F == null ? void 0 : F.meteo) == null ? void 0 : N.wave) == null ? void 0 : D.sig, A = (L = F == null ? void 0 : F.meteo) == null ? void 0 : L.wind, V = W ? p(F.eta).diff(p(e[W - 1].eta), "hour", !0) : 0;
|
|
802
|
-
s = V > s ? V : s, _ == null || _.debug("[%s] check sig.wave: %j", n.requestId, { ...Y, dgThd4Wv: r, svThd4Wv: u, hvThd4Wv: l }), (Y == null ? void 0 : Y.height) >= r ? F.isDangerous = !0 : (Y == null ? void 0 : Y.height) >= u ? F.isSevere = !0 : (Y == null ? void 0 : Y.height) >= l && (F.isHeavy = !0), _ == null || _.debug("[%s] check wind: %j", n.requestId, { ...A, dgThd4Wd: h, svThd4Wd:
|
|
802
|
+
s = V > s ? V : s, _ == null || _.debug("[%s] check sig.wave: %j", n.requestId, { ...Y, dgThd4Wv: r, svThd4Wv: u, hvThd4Wv: l }), (Y == null ? void 0 : Y.height) >= r ? F.isDangerous = !0 : (Y == null ? void 0 : Y.height) >= u ? F.isSevere = !0 : (Y == null ? void 0 : Y.height) >= l && (F.isHeavy = !0), _ == null || _.debug("[%s] check wind: %j", n.requestId, { ...A, dgThd4Wd: h, svThd4Wd: c, hvThd4Wd: I }), (A == null ? void 0 : A.scale) >= h ? (F.isDangerous = !0, delete F.isSevere, delete F.isHeavy) : (A == null ? void 0 : A.scale) > c ? (F.isDangerous || (F.isSevere = !0), delete F.isHeavy) : (A == null ? void 0 : A.scale) === I && !F.isDangerous && !F.isSevere && (F.isHeavy = !0), o += F.isDangerous ? V : 0, i += F.isSevere ? V : 0, a += F.isHeavy ? V : 0;
|
|
803
803
|
}
|
|
804
|
-
return o = Math.round(o * 100) / 100, i = Math.round(i * 100) / 100, a = Math.round(a * 100) / 100, s = Math.round(s), { sample: e, dangerous: o, severe: i, heavy: a, step: s < 3 ? 3 : s, wind: { dgThd4Wd: h, svThd4Wd:
|
|
804
|
+
return o = Math.round(o * 100) / 100, i = Math.round(i * 100) / 100, a = Math.round(a * 100) / 100, s = Math.round(s), { sample: e, dangerous: o, severe: i, heavy: a, step: s < 3 ? 3 : s, wind: { dgThd4Wd: h, svThd4Wd: c, hvThd4Wd: I }, sig: { dgThd4Wv: r, svThd4Wv: u, hvThd4Wv: l } };
|
|
805
805
|
}
|
|
806
806
|
}
|
|
807
807
|
const Dt = new Mt();
|
|
@@ -929,8 +929,8 @@ class H {
|
|
|
929
929
|
* @private
|
|
930
930
|
*/
|
|
931
931
|
static assembleProperties(e, t, n, o) {
|
|
932
|
-
var
|
|
933
|
-
const i = e.lbp ?? e.length ?? e.lengthOverall ?? 198.9642, a = e.draught ?? 8, s = e.breadthMoulded ?? e.breadth ?? e.breadthExtreme ?? 32.4572, r = e.deadweight ?? 67035.7773, u = ((
|
|
932
|
+
var c;
|
|
933
|
+
const i = e.lbp ?? e.length ?? e.lengthOverall ?? 198.9642, a = e.draught ?? 8, s = e.breadthMoulded ?? e.breadth ?? e.breadthExtreme ?? 32.4572, r = e.deadweight ?? 67035.7773, u = ((c = e == null ? void 0 : e.type) == null ? void 0 : c.toLowerCase()) || "common";
|
|
934
934
|
return {
|
|
935
935
|
tag: u.indexOf("container") > -1 ? "container" : u.indexOf("tugs") > -1 ? "tugs" : "common",
|
|
936
936
|
lbp: i,
|
|
@@ -968,27 +968,27 @@ class H {
|
|
|
968
968
|
forecastDays: 2,
|
|
969
969
|
weatherModels: k,
|
|
970
970
|
marineModels: w
|
|
971
|
-
}), [
|
|
972
|
-
l = dt.toLegacy(
|
|
971
|
+
}), [d] = dt.pickHourly(m, v);
|
|
972
|
+
l = dt.toLegacy(d);
|
|
973
973
|
} catch (k) {
|
|
974
974
|
C.warn("[%s] meteo2 spot(%j) forecast failed: %s", r.requestId, { ...t, eta: n.utc().format(), source: o }, k);
|
|
975
975
|
}
|
|
976
|
-
let h = H.currentFactor(e.bearing, l == null ? void 0 : l.current, i, r),
|
|
976
|
+
let h = H.currentFactor(e.bearing, l == null ? void 0 : l.current, i, r), c = H.weatherFactor(e, l, h, r);
|
|
977
977
|
const I = e.speed * 1.943844;
|
|
978
|
-
I + h +
|
|
978
|
+
I + h + c <= 0 && (C.warn(
|
|
979
979
|
"[%s] v0(%d) is less then factor(%d) = wxFactor(%d) + cFactor(%d), scale factor with 0.6",
|
|
980
980
|
r.requestId,
|
|
981
981
|
I,
|
|
982
|
-
|
|
983
|
-
|
|
982
|
+
c + h,
|
|
983
|
+
c,
|
|
984
984
|
h
|
|
985
|
-
), h = Math.round(h * 0.6 * 1e3) / 1e3,
|
|
986
|
-
const b =
|
|
987
|
-
C == null || C.info("[%s] calculate speed lose with v0Factor(%d), cFactor(%d) and wxFactor(%d)", r.requestId, b, h,
|
|
988
|
-
let E = Math.round((I + h +
|
|
985
|
+
), h = Math.round(h * 0.6 * 1e3) / 1e3, c = Math.round(c * 0.6 * 1e3) / 1e3);
|
|
986
|
+
const b = c <= (r.minV0Factor || -1) ? Math.max(r.maxV0Factor || -2.5, -1 * c * (c / 1.2)) : 0;
|
|
987
|
+
C == null || C.info("[%s] calculate speed lose with v0Factor(%d), cFactor(%d) and wxFactor(%d)", r.requestId, b, h, c), c += b;
|
|
988
|
+
let E = Math.round((I + h + c) * 100) / 100;
|
|
989
989
|
E = E <= 0 ? 1 : E, u = {
|
|
990
990
|
meteo: { ...l },
|
|
991
|
-
wxFactor:
|
|
991
|
+
wxFactor: c,
|
|
992
992
|
v0Factor: b,
|
|
993
993
|
cFactor: h,
|
|
994
994
|
speed: t.velocity && s ? t.velocity : E,
|
|
@@ -1022,27 +1022,27 @@ class H {
|
|
|
1022
1022
|
*/
|
|
1023
1023
|
static async speedLoseInHoursStep(e, t, n, o, i, a, s = "", r = !0, u = !1, l = {}) {
|
|
1024
1024
|
t.utc();
|
|
1025
|
-
const h = t.clone().add(14, "days"),
|
|
1025
|
+
const h = t.clone().add(14, "days"), c = [], I = [], b = [];
|
|
1026
1026
|
let E = 0, k = 0, w, v;
|
|
1027
1027
|
for (let m = 0; m < a.length - 1; m++) {
|
|
1028
|
-
let
|
|
1029
|
-
|
|
1028
|
+
let d = a[m];
|
|
1029
|
+
d.distanceFromStart = Math.round((i + k) * 1e3) / 1e3;
|
|
1030
1030
|
const f = a[m + 1];
|
|
1031
|
-
if (e.bearing = R.calculateBearing(
|
|
1032
|
-
|
|
1033
|
-
const M =
|
|
1031
|
+
if (e.bearing = R.calculateBearing(d, f, !f.gcToPrevious), d.bearing = e.bearing, d.suspend && u) {
|
|
1032
|
+
d.eta = d.eta || t.utc().format(), d.elapsed = d.elapsed ?? 0;
|
|
1033
|
+
const M = d.suspend - d.elapsed;
|
|
1034
1034
|
if (o - E > M)
|
|
1035
|
-
o = o - E - M, t.add(M, "hour"),
|
|
1035
|
+
o = o - E - M, t.add(M, "hour"), d.elapsed = d.suspend;
|
|
1036
1036
|
else {
|
|
1037
1037
|
const j = o - E;
|
|
1038
|
-
|
|
1038
|
+
d.elapsed += j, t.add(j, "hour"), o = 0;
|
|
1039
1039
|
}
|
|
1040
|
-
if (C == null || C.info(`[%s] suspend ${
|
|
1041
|
-
return
|
|
1040
|
+
if (C == null || C.info(`[%s] suspend ${d.elapsed} hours at %j, and remain ${o} hours need to go...`, l.requestId, d), o === 0)
|
|
1041
|
+
return d.distanceFromPrevious = k, { etd: t, from: v || d, to: d, next: a.filter((j) => j), wps: c, days: I, all: b };
|
|
1042
1042
|
} else
|
|
1043
|
-
|
|
1044
|
-
r = t.isAfter(h) ? !1 : r,
|
|
1045
|
-
const y = R.calculateDistance(
|
|
1043
|
+
d.suspend = 0;
|
|
1044
|
+
r = t.isAfter(h) ? !1 : r, d = await H.speedLoseAt(e, d, t, s, 0, r, u, l), b.push(d), v = v || d, d.important && c.push(d), t.isSameOrAfter(n) && (I.push(d), n.add(24, "hour"));
|
|
1045
|
+
const y = R.calculateDistance(d, f, !f.gcToPrevious);
|
|
1046
1046
|
let S = Math.round(y / v.speed * 1e5) / 1e5;
|
|
1047
1047
|
if (E + S < o) {
|
|
1048
1048
|
if (E += S, t.add(S, "hour"), delete a[m], C == null || C.debug(
|
|
@@ -1051,22 +1051,22 @@ class H {
|
|
|
1051
1051
|
{ lat: f.lat, lng: f.lng },
|
|
1052
1052
|
{ lat: v.lat, lng: v.lng, etd: v.etd }
|
|
1053
1053
|
), k += y, a.filter((M) => M).length <= 1) {
|
|
1054
|
-
w = f, w.eta = t.utc().format(), w.distanceFromPrevious = y, w.distanceFromStart = Math.round((i + k) * 1e4) / 1e4,
|
|
1054
|
+
w = f, w.eta = t.utc().format(), w.distanceFromPrevious = y, w.distanceFromStart = Math.round((i + k) * 1e4) / 1e4, c.push(w), b.push(w), delete a[m + 1];
|
|
1055
1055
|
break;
|
|
1056
1056
|
}
|
|
1057
1057
|
} else {
|
|
1058
1058
|
S = o - E, t.add(S, "hour");
|
|
1059
1059
|
const M = J.roundPrecision(v.speed * S, 5);
|
|
1060
|
-
w = R.calculateCoordinate(
|
|
1060
|
+
w = R.calculateCoordinate(d, e.bearing, M, "nauticalmiles", !f.gcToPrevious), w.eta = t.utc().format(), a[m] = w, C == null || C.debug(
|
|
1061
1061
|
`[%s] go to %j from %j with ${M}nm, and cost ${S} hours`,
|
|
1062
1062
|
l.requestId,
|
|
1063
1063
|
{ lat: w.lat, lng: w.lng },
|
|
1064
|
-
{ lat:
|
|
1064
|
+
{ lat: d.lat, lng: d.lng, etd: d.etd }
|
|
1065
1065
|
), k += M, w.distanceFromPrevious = Math.round(k * 1e4) / 1e4, w.distanceFromStart = Math.round((i + k) * 1e4) / 1e4;
|
|
1066
1066
|
break;
|
|
1067
1067
|
}
|
|
1068
1068
|
}
|
|
1069
|
-
return { etd: t, from: v, to: w, next: a.filter((m) => m), wps:
|
|
1069
|
+
return { etd: t, from: v, to: w, next: a.filter((m) => m), wps: c, days: I, all: b };
|
|
1070
1070
|
}
|
|
1071
1071
|
/**
|
|
1072
1072
|
* 洋流影响因子
|
|
@@ -1088,15 +1088,15 @@ class H {
|
|
|
1088
1088
|
* @param options
|
|
1089
1089
|
*/
|
|
1090
1090
|
static weatherFactor(e, t, n = 0, o = {}) {
|
|
1091
|
-
var b, E, k, w, v, m,
|
|
1091
|
+
var b, E, k, w, v, m, d;
|
|
1092
1092
|
C == null || C.info("[%s] calculate weather factor via: %j", o.requestId, { ...e, ...t });
|
|
1093
1093
|
const i = H.blockCoefficient(e.displacement, e.lbp, e.breadthMoulded, e.draught), a = J.roundPrecision(n * 1852 / 3600, 6), s = H.froudeNumber(e.speed - a, e.lbp), r = H.amendFactor(i, s, e.loadCondition);
|
|
1094
1094
|
let u = R.includedAngle(e.bearing, (b = t == null ? void 0 : t.wind) == null ? void 0 : b.degree);
|
|
1095
1095
|
const l = H.directionFactor(u, (E = t == null ? void 0 : t.wind) == null ? void 0 : E.scale), h = H.vesselTagFactor(e.displacement, e.loadCondition, e.tag, ((k = t == null ? void 0 : t.wind) == null ? void 0 : k.kts) || 10);
|
|
1096
|
-
let
|
|
1097
|
-
|
|
1098
|
-
const I = H.waveHeightFactor(((
|
|
1099
|
-
return C == null || C.info("[%s] calculate wave wx factor: %d", o.requestId, I),
|
|
1096
|
+
let c = l * r * h / 100 * (e.speed - a);
|
|
1097
|
+
c = Math.round(c * 1.943844 * 1e4) / 1e4 * -1, e.tag === "tugs" && Math.abs(c) > 1 && (c = c / (Math.abs(Math.round(c)) + 1)), C == null || C.info("[%s] calculate wind wx factor: %d", o.requestId, c), u = R.includedAngle(e.bearing, (v = (w = t == null ? void 0 : t.wave) == null ? void 0 : w.sig) == null ? void 0 : v.degree);
|
|
1098
|
+
const I = H.waveHeightFactor(((d = (m = t == null ? void 0 : t.wave) == null ? void 0 : m.sig) == null ? void 0 : d.height) ?? 1, u, e.draught, o);
|
|
1099
|
+
return C == null || C.info("[%s] calculate wave wx factor: %d", o.requestId, I), c = Math.abs(c) > Math.abs(I) ? c : 0.7 * c + 0.9 * I, C == null || C.info("[%s] calculate finial weather factor: %d (0.7 * wf) + (0.9 * hf)", o.requestId, c), c = Math.abs(c) > 4 ? 4 * (Math.abs(c) / c) + Math.abs(c) / c * (Math.abs(c) - 2) * 0.1 : c, Math.round((c || 0) * 100) / 100;
|
|
1100
1100
|
}
|
|
1101
1101
|
/**
|
|
1102
1102
|
* 以12小时级别去掉重复的days
|
|
@@ -1131,7 +1131,7 @@ class H {
|
|
|
1131
1131
|
var U, G, X, Q, Z, $;
|
|
1132
1132
|
const h = p().valueOf();
|
|
1133
1133
|
e.lng = J.convertToStdLng(e.lng);
|
|
1134
|
-
const { route:
|
|
1134
|
+
const { route: c, waypoints: I } = i.points, b = R.calculateSubRoute(e, c);
|
|
1135
1135
|
if (((U = b[0]) == null ? void 0 : U.length) <= 1)
|
|
1136
1136
|
return;
|
|
1137
1137
|
const { v0: E, label: k } = e.sog ? {
|
|
@@ -1150,7 +1150,7 @@ class H {
|
|
|
1150
1150
|
waypoints: v,
|
|
1151
1151
|
v0: E,
|
|
1152
1152
|
label: k
|
|
1153
|
-
},
|
|
1153
|
+
}, d = {
|
|
1154
1154
|
hours: [],
|
|
1155
1155
|
days: [],
|
|
1156
1156
|
wps: [],
|
|
@@ -1173,29 +1173,29 @@ class H {
|
|
|
1173
1173
|
u,
|
|
1174
1174
|
l
|
|
1175
1175
|
);
|
|
1176
|
-
if (
|
|
1176
|
+
if (d.all.push(...T.all), (G = T.from) != null && G.speed && (d.hours.push(T.from), d.wps.push(...T.wps), d.days.push(...T.days)), f = T == null ? void 0 : T.next, !f.length) {
|
|
1177
1177
|
const O = await H.speedLoseAt(w, T.to, p(T.to.eta), a, 0, r, u, l);
|
|
1178
|
-
O.bearing = w.bearing,
|
|
1178
|
+
O.bearing = w.bearing, d.hours.push(O), d.all.push(O);
|
|
1179
1179
|
}
|
|
1180
1180
|
y += Math.round((((X = T == null ? void 0 : T.to) == null ? void 0 : X.distanceFromPrevious) ?? 0) * 1e4) / 1e4;
|
|
1181
1181
|
}
|
|
1182
|
-
const D =
|
|
1182
|
+
const D = d.hours;
|
|
1183
1183
|
for (let q = 0; q < D.length - 1; q++) {
|
|
1184
1184
|
const B = p(D[q + 1].eta).diff(D[q].etd, "hour", !0) || 1;
|
|
1185
1185
|
S += (D[q].wxFactor || 0) * B, M += (D[q].cFactor || 0) * B, j += B;
|
|
1186
1186
|
}
|
|
1187
1187
|
const L = D.reduce((q, B) => q + (B.suspend || 0), 0);
|
|
1188
|
-
(Q =
|
|
1188
|
+
(Q = d.wps) == null || Q.forEach((q, B) => {
|
|
1189
1189
|
q.positionTime = p.utc(q.etd || q.eta).unix();
|
|
1190
|
-
const T =
|
|
1190
|
+
const T = d.wps[B - 1];
|
|
1191
1191
|
if (T) {
|
|
1192
1192
|
const O = q.distanceFromStart - T.distanceFromStart, P = p(q.eta || q.etd).diff(p(T.etd || T.eta), "h", !0);
|
|
1193
1193
|
q.avgSpd = Math.round(O / P * 100) / 100;
|
|
1194
1194
|
const at = R.calculateBearing(T, q);
|
|
1195
1195
|
q.avgBearing = at, T.bearing = at;
|
|
1196
1196
|
}
|
|
1197
|
-
}),
|
|
1198
|
-
const W =
|
|
1197
|
+
}), d.wps = await H.reduceWPS(d.wps), d.days = await H.reduceDays(d.days), d.all = (Z = d.all) == null ? void 0 : Z.reduce((q, B) => (B.positionTime = p.utc(B.etd || B.eta).unix(), q.some((T) => Math.round(T.positionTime / 60) === Math.round(B.positionTime / 60)) || q.push(B), q), []), m.sample = d;
|
|
1198
|
+
const W = d.hours.at(0), F = d.hours.at(-1);
|
|
1199
1199
|
m.distance = Math.round(F.distanceFromStart * 1e3) / 1e3, m.etd = p(W.eta).utc().format(), m.eta = p(F.eta).utc().format(), m.wxFactor = Math.round(S / j * 1e3) / 1e3, m.cFactor = Math.round(M / j * 1e3) / 1e3, m.avgSpeed = Math.round(F.distanceFromStart / j * 1e3) / 1e3, m.totalHrs = Math.round(j * 1e3) / 1e3, m.suspend = Math.round(L * 1e3) / 1e3;
|
|
1200
1200
|
const Y = J.roundPrecision(o.dgo / 24 * L, 3), { distanceInECA: A, hoursInECA: V, totalDgoConsInECA: ot, eca: tt } = await this.calculateECA(m, o, l), et = J.roundPrecision(o.fo / 24 * (j - V), 3), it = J.roundPrecision(o.dgo / 24 * j + Y, 3);
|
|
1201
1201
|
m.extend = {
|
|
@@ -1205,7 +1205,7 @@ class H {
|
|
|
1205
1205
|
totalDgoConsInECA: ot,
|
|
1206
1206
|
totalDgoConsInSuspend: Y
|
|
1207
1207
|
}, m.totalFoCons = et < 0 ? 0 : et, m.totalDgoCons = it;
|
|
1208
|
-
const st = p().valueOf() - h, ct = (($ =
|
|
1208
|
+
const st = p().valueOf() - h, ct = (($ = d == null ? void 0 : d.hours) == null ? void 0 : $.length) || 1;
|
|
1209
1209
|
return C == null || C.info("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms", l == null ? void 0 : l.requestId, st, ct, Math.round(st / ct * 1e3) / 1e3), m;
|
|
1210
1210
|
}
|
|
1211
1211
|
/**
|
|
@@ -1223,7 +1223,7 @@ class H {
|
|
|
1223
1223
|
* @param useRouteParam
|
|
1224
1224
|
* @param options
|
|
1225
1225
|
*/
|
|
1226
|
-
static async analyseInstantWithThreshed(e, t, n, o, i, a, s, r = "", u = 3, l = !0, h = !1,
|
|
1226
|
+
static async analyseInstantWithThreshed(e, t, n, o, i, a, s, r = "", u = 3, l = !0, h = !1, c = {}) {
|
|
1227
1227
|
var X, Q, Z, $, q, B;
|
|
1228
1228
|
const I = p().valueOf();
|
|
1229
1229
|
e.lng = J.convertToStdLng(e.lng);
|
|
@@ -1240,7 +1240,7 @@ class H {
|
|
|
1240
1240
|
return;
|
|
1241
1241
|
const v = s.length ? R.calculateSubWaypoints(e, s) : [];
|
|
1242
1242
|
v.forEach((T) => T.important = !0);
|
|
1243
|
-
let m = R.simplifyRouteToCoordinates(w, v, 0),
|
|
1243
|
+
let m = R.simplifyRouteToCoordinates(w, v, 0), d = 0, f = 0, y = 0, S = 0;
|
|
1244
1244
|
const M = {
|
|
1245
1245
|
hours: [],
|
|
1246
1246
|
wps: [],
|
|
@@ -1253,8 +1253,8 @@ class H {
|
|
|
1253
1253
|
const T = u - t.hour() % u;
|
|
1254
1254
|
let O = Math.ceil(t.clone().add(T, "h").set({ minute: 0, second: 0, millisecond: 0 }).diff(t, "h", !0) * 1e4) / 1e4;
|
|
1255
1255
|
O = t.clone().add(O, "h").isSameOrAfter(n) ? n.diff(t, "h", !0) * 1e4 / 1e4 : O;
|
|
1256
|
-
const P = await H.speedLoseInHoursStep(k, t, j, O,
|
|
1257
|
-
if (M.all.push(...P.all), (Q = P.from) != null && Q.speed && (M.hours.push(P.from), P != null && P.wps && M.wps.push(...P.wps), M.days.push(...P.days)), m = P == null ? void 0 : P.next, m.length || M.hours.push(P == null ? void 0 : P.to),
|
|
1256
|
+
const P = await H.speedLoseInHoursStep(k, t, j, O, d, m, r, l, h, c);
|
|
1257
|
+
if (M.all.push(...P.all), (Q = P.from) != null && Q.speed && (M.hours.push(P.from), P != null && P.wps && M.wps.push(...P.wps), M.days.push(...P.days)), m = P == null ? void 0 : P.next, m.length || M.hours.push(P == null ? void 0 : P.to), d += Math.round((((Z = P == null ? void 0 : P.to) == null ? void 0 : Z.distanceFromPrevious) ?? 0) * 1e4) / 1e4, !O)
|
|
1258
1258
|
break;
|
|
1259
1259
|
}
|
|
1260
1260
|
M.wps = await H.reduceWPS(M.wps), M.days = await H.reduceDays(M.days), M.all = ($ = M.all) == null ? void 0 : $.reduce((T, O) => (O.positionTime = p.utc(O.etd || O.eta).unix(), T.some((P) => Math.round(p(P.etd).unix() / 60) === Math.round(p(O.etd).unix() / 60)) || T.push(O), T), []), (q = M.wps) == null || q.forEach((T, O) => {
|
|
@@ -1286,7 +1286,7 @@ class H {
|
|
|
1286
1286
|
waypoints: Y,
|
|
1287
1287
|
v0: b,
|
|
1288
1288
|
label: E
|
|
1289
|
-
}, V = J.roundPrecision(i.dgo / 24 * D, 3), { distanceInECA: ot, hoursInECA: tt, totalDgoConsInECA: et, eca: it } = await this.calculateECA(A, i,
|
|
1289
|
+
}, V = J.roundPrecision(i.dgo / 24 * D, 3), { distanceInECA: ot, hoursInECA: tt, totalDgoConsInECA: et, eca: it } = await this.calculateECA(A, i, c), rt = J.roundPrecision(i.fo / 24 * (S - tt), 3), st = J.roundPrecision(i.dgo / 24 * S + V, 3);
|
|
1290
1290
|
A.extend = {
|
|
1291
1291
|
eca: it,
|
|
1292
1292
|
distanceInECA: ot,
|
|
@@ -1295,7 +1295,7 @@ class H {
|
|
|
1295
1295
|
totalDgoConsInSuspend: V
|
|
1296
1296
|
}, A.totalDgoCons = st, A.totalFoCons = rt < 0 ? 0 : rt;
|
|
1297
1297
|
const U = p().valueOf() - I, G = ((B = M == null ? void 0 : M.hours) == null ? void 0 : B.length) || 1;
|
|
1298
|
-
return C == null || C.debug("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms",
|
|
1298
|
+
return C == null || C.debug("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms", c == null ? void 0 : c.requestId, U, G, Math.round(U / G * 1e3) / 1e3), A;
|
|
1299
1299
|
}
|
|
1300
1300
|
/**
|
|
1301
1301
|
* 在指定航线条件下,基于多CP,动态计算最优成本(租金+油费)方案
|
|
@@ -1319,19 +1319,19 @@ class H {
|
|
|
1319
1319
|
const r = R.calculateRouteDistance(o.route);
|
|
1320
1320
|
let u = 0;
|
|
1321
1321
|
n.forEach((m) => {
|
|
1322
|
-
const
|
|
1323
|
-
u = u <
|
|
1322
|
+
const d = Math.ceil(r / m.speed / 24);
|
|
1323
|
+
u = u < d ? d : u;
|
|
1324
1324
|
}), u = u * 1.3;
|
|
1325
1325
|
const l = p.utc(e.etd).add(u ?? 14, "day");
|
|
1326
1326
|
let h = 1;
|
|
1327
1327
|
for (const m of n) {
|
|
1328
|
-
const
|
|
1328
|
+
const d = JSON.parse(JSON.stringify(o.route)), f = JSON.parse(JSON.stringify(o.waypoints)), y = await H.analyseInstantWithThreshed(
|
|
1329
1329
|
{ lat: e.lat, lng: e.lng },
|
|
1330
1330
|
e.etd,
|
|
1331
1331
|
l,
|
|
1332
1332
|
t,
|
|
1333
1333
|
m,
|
|
1334
|
-
|
|
1334
|
+
d,
|
|
1335
1335
|
f,
|
|
1336
1336
|
e.meteoVendor,
|
|
1337
1337
|
e.speedStep,
|
|
@@ -1348,15 +1348,15 @@ class H {
|
|
|
1348
1348
|
cp: `${m.speed}/${m.fo}/${m.dgo}`
|
|
1349
1349
|
})), h++;
|
|
1350
1350
|
}
|
|
1351
|
-
s.sort((m,
|
|
1352
|
-
const
|
|
1353
|
-
if (b.push({ combined: !1, speeds: [
|
|
1354
|
-
const m =
|
|
1351
|
+
s.sort((m, d) => m.cost.total - d.cost.total);
|
|
1352
|
+
const c = s.at(0), I = s.at(1), b = [];
|
|
1353
|
+
if (b.push({ combined: !1, speeds: [c], cost: (w = c.cost) == null ? void 0 : w.total }), I) {
|
|
1354
|
+
const m = c.cost.cp, d = I.cost.cp, f = p(c.eta), y = p(c.etd), S = f.diff(y, "days", !0);
|
|
1355
1355
|
let M = Math.ceil(S / 2);
|
|
1356
1356
|
M = M > 7 ? 7 : M < e.alterStep ? e.alterStep : M;
|
|
1357
1357
|
let j = 2, N = { combined: !1, speeds: [I], cost: (v = I.cost) == null ? void 0 : v.total }, D;
|
|
1358
1358
|
for (; M >= e.alterStep; ) {
|
|
1359
|
-
const L = await H.combinedAnalyse(e, t, l, [m,
|
|
1359
|
+
const L = await H.combinedAnalyse(e, t, l, [m, d], o, M, { ...i, level: j });
|
|
1360
1360
|
if (N.cost > L.cost ? D ? (D == null ? void 0 : D.cost) > L.cost && (D = L) : (D = N, N = L) : (!D || (D == null ? void 0 : D.cost) > L.cost) && (D = L), M <= e.alterStep)
|
|
1361
1361
|
break;
|
|
1362
1362
|
M = Math.ceil(M / 2), j += 1;
|
|
@@ -1364,7 +1364,7 @@ class H {
|
|
|
1364
1364
|
b.push(N), D && b.push(D);
|
|
1365
1365
|
}
|
|
1366
1366
|
const k = p().valueOf() - a;
|
|
1367
|
-
return C == null || C.info("[%s] analyse elapsed: %d ms", i == null ? void 0 : i.requestId, k), b.sort((m,
|
|
1367
|
+
return C == null || C.info("[%s] analyse elapsed: %d ms", i == null ? void 0 : i.requestId, k), b.sort((m, d) => m.cost - d.cost);
|
|
1368
1368
|
}
|
|
1369
1369
|
/**
|
|
1370
1370
|
* 按步长多次减半,分别用7,4,2,1天步长及cpa,cpb交替计算各种组合下的成本
|
|
@@ -1378,15 +1378,15 @@ class H {
|
|
|
1378
1378
|
*/
|
|
1379
1379
|
static async combinedAnalyse(e, t, n, o, i, a, s = {}) {
|
|
1380
1380
|
s.counter = 1, C == null || C.info("[%s][L%d] analyse with alternate cp in every %d days", s.requestId, s.level, a);
|
|
1381
|
-
const r = await H.alternateAnalyse(e, t, n, o, 0, i, a, s), u = r.reduce((
|
|
1381
|
+
const r = await H.alternateAnalyse(e, t, n, o, 0, i, a, s), u = r.reduce((d, f) => d + f.cost.total, 0), l = r.reduce((d, f) => d + f.cost.hire, 0), h = r.reduce((d, f) => d + f.cost.bunker, 0), c = r.reduce((d, f) => d + f.distance, 0), I = r.reduce((d, f) => d + f.totalHrs, 0);
|
|
1382
1382
|
C == null || C.info("[%s][L%d] cost with cpa/cpb turn: %j", s.requestId, s.level, {
|
|
1383
1383
|
cost: u,
|
|
1384
1384
|
hire: l,
|
|
1385
1385
|
bunker: h,
|
|
1386
|
-
distance:
|
|
1386
|
+
distance: c,
|
|
1387
1387
|
hours: I
|
|
1388
1388
|
});
|
|
1389
|
-
const b = await H.alternateAnalyse(e, t, n, o, 1, i, a, s), E = b.reduce((
|
|
1389
|
+
const b = await H.alternateAnalyse(e, t, n, o, 1, i, a, s), E = b.reduce((d, f) => d + f.cost.total, 0), k = b.reduce((d, f) => d + f.cost.hire, 0), w = b.reduce((d, f) => d + f.cost.bunker, 0), v = b.reduce((d, f) => d + f.distance, 0), m = b.reduce((d, f) => d + f.totalHrs, 0);
|
|
1390
1390
|
return C == null || C.info("[%s][L%d] cost with cpb/cpa turn: %j", s.requestId, s.level, {
|
|
1391
1391
|
cost: E,
|
|
1392
1392
|
hire: k,
|
|
@@ -1407,7 +1407,7 @@ class H {
|
|
|
1407
1407
|
* @param options
|
|
1408
1408
|
*/
|
|
1409
1409
|
static async alternateAnalyse(e, t, n, o, i, a, s, r = {}) {
|
|
1410
|
-
var
|
|
1410
|
+
var c, I;
|
|
1411
1411
|
let u = p.utc(e.etd);
|
|
1412
1412
|
const l = { lat: e.lat, lng: e.lng }, h = [];
|
|
1413
1413
|
for (; u.isBefore(n); ) {
|
|
@@ -1441,7 +1441,7 @@ class H {
|
|
|
1441
1441
|
cp: `${w.speed}/${w.fo}/${w.dgo}`
|
|
1442
1442
|
}
|
|
1443
1443
|
)), r.counter = r.counter + 1;
|
|
1444
|
-
const m = (I = (
|
|
1444
|
+
const m = (I = (c = v == null ? void 0 : v.sample) == null ? void 0 : c.hours) == null ? void 0 : I.at(-1);
|
|
1445
1445
|
if (m)
|
|
1446
1446
|
l.lat = m.lat, l.lng = m.lng, u = p(m.eta), h.push(v), i = i ? 0 : 1;
|
|
1447
1447
|
else
|
|
@@ -1478,13 +1478,13 @@ class H {
|
|
|
1478
1478
|
var r, u, l, h;
|
|
1479
1479
|
const o = await R.intersectInECA((e == null ? void 0 : e.route) || []);
|
|
1480
1480
|
let i = 0, a = 0, s = 0;
|
|
1481
|
-
(u = (r = e == null ? void 0 : e.sample) == null ? void 0 : r.wps) == null || u.forEach((
|
|
1482
|
-
|
|
1481
|
+
(u = (r = e == null ? void 0 : e.sample) == null ? void 0 : r.wps) == null || u.forEach((c) => {
|
|
1482
|
+
c.positionTime = p.utc(c.etd || c.eta).unix();
|
|
1483
1483
|
});
|
|
1484
|
-
for (const
|
|
1485
|
-
i +=
|
|
1486
|
-
const I = await R.deadReckoningTime((l =
|
|
1487
|
-
|
|
1484
|
+
for (const c of o) {
|
|
1485
|
+
i += c.distance;
|
|
1486
|
+
const I = await R.deadReckoningTime((l = c.waypoints) == null ? void 0 : l.at(0), e.sample.all || e.sample.wps), b = await R.deadReckoningTime((h = c.waypoints) == null ? void 0 : h.at(-1), e.sample.all || e.sample.wps);
|
|
1487
|
+
c.in = I, c.out = b, c.totalHrs = J.roundPrecision((b.positionTime - I.positionTime) / 3600, 3), c.totalDgoCons = J.roundPrecision(t.fo / 24 * c.totalHrs, 3), a += c.totalHrs, s += c.totalDgoCons;
|
|
1488
1488
|
}
|
|
1489
1489
|
return i = J.roundPrecision(i, 3), a = J.roundPrecision(a, 3), s = J.roundPrecision(s, 3), {
|
|
1490
1490
|
distanceInECA: i,
|
|
@@ -1499,7 +1499,7 @@ class H {
|
|
|
1499
1499
|
* @param options
|
|
1500
1500
|
*/
|
|
1501
1501
|
static async mergeSpeeds(e, t = {}) {
|
|
1502
|
-
var m,
|
|
1502
|
+
var m, d;
|
|
1503
1503
|
const n = {
|
|
1504
1504
|
hours: [],
|
|
1505
1505
|
wps: [],
|
|
@@ -1514,7 +1514,7 @@ class H {
|
|
|
1514
1514
|
}, 0), r = e.reduce((f, y) => {
|
|
1515
1515
|
var S;
|
|
1516
1516
|
return f + (((S = y.extend) == null ? void 0 : S.totalDgoConsInECA) || 0);
|
|
1517
|
-
}, 0), u = e.reduce((f, y) => f + y.wxFactor * y.totalHrs / a, 0), l = e.reduce((f, y) => f + y.cFactor * y.totalHrs / a, 0), h = e.reduce((f, y) => f + y.totalFoCons, 0),
|
|
1517
|
+
}, 0), u = e.reduce((f, y) => f + y.wxFactor * y.totalHrs / a, 0), l = e.reduce((f, y) => f + y.cFactor * y.totalHrs / a, 0), h = e.reduce((f, y) => f + y.totalFoCons, 0), c = e.reduce((f, y) => f + y.totalDgoCons, 0), I = e.reduce((f, y) => f + y.cost.total, 0), b = e.reduce((f, y) => f + y.cost.hire, 0), E = e.reduce((f, y) => f + y.cost.bunker, 0), k = [], w = [];
|
|
1518
1518
|
let v;
|
|
1519
1519
|
for (const f of e) {
|
|
1520
1520
|
w.push(...((m = f.extend) == null ? void 0 : m.eca) || []);
|
|
@@ -1542,7 +1542,7 @@ class H {
|
|
|
1542
1542
|
var A;
|
|
1543
1543
|
((A = n == null ? void 0 : n.days) == null ? void 0 : A.findIndex((V) => V.eta === F.eta)) === -1 && n.days.push(F);
|
|
1544
1544
|
});
|
|
1545
|
-
const W = (
|
|
1545
|
+
const W = (d = n.wps) == null ? void 0 : d.findIndex((F) => F.eta === N.eta);
|
|
1546
1546
|
W === -1 ? n.wps.push(N) : n.wps[W] = N, v = y.at(-1);
|
|
1547
1547
|
}
|
|
1548
1548
|
return n.wps.sort((f, y) => p(f.etd).unix() - p(y.etd).unix()), n.wps.forEach((f, y) => {
|
|
@@ -1567,7 +1567,7 @@ class H {
|
|
|
1567
1567
|
wxFactor: Math.round(u * 1e3) / 1e3,
|
|
1568
1568
|
cFactor: Math.round(l * 1e3) / 1e3,
|
|
1569
1569
|
totalFoCons: Math.round(h * 1e3) / 1e3,
|
|
1570
|
-
totalDgoCons: Math.round(
|
|
1570
|
+
totalDgoCons: Math.round(c * 1e3) / 1e3,
|
|
1571
1571
|
cost: {
|
|
1572
1572
|
total: Math.round(I * 1e3) / 1e3,
|
|
1573
1573
|
hire: Math.round(b * 1e3) / 1e3,
|
package/dist/index.umd.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(P,x){typeof exports=="object"&&typeof module<"u"?x(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"],x):(P=typeof globalThis<"u"?globalThis:P||self,x(P["idm-plugin-vessel"]={},P.got,P["@log4js-node/log4js-api"],P.moment,P["@idm-plugin/geo2"],P["@idm-plugin/meteo2"],P["@idm-plugin/meteo"]))})(this,function(P,x,K,w,E,pt,it){"use strict";var St=Object.defineProperty;var Ct=(P,x,K)=>x in P?St(P,x,{enumerable:!0,configurable:!0,writable:!0,value:K}):P[x]=K;var U=(P,x,K)=>(Ct(P,typeof x!="symbol"?x+"":x,K),K);let M;try{M=K.getLogger("vessel")}catch{}finally{}class G{parseStatus(e){let t,n;switch(e){case 0:t="在航(主机推动)",n="Underway Using Engine";break;case 1:t="锚泊",n="Anchored";break;case 2:t="失控",n="Not under command";break;case 3:t="操纵受限",n="Limited airworthiness";break;case 4:t="吃水受限",n="Limited by ship's draft";break;case 5:t="靠泊",n="Mooring";break;case 6:t="搁浅",n="Stranded";break;case 7:t="捕捞作业",n="Engaged in fishing";break;case 8:t="靠帆船提供动力",n="Sailing";break;default:t="未定义",n="Undefined"}return{labelCn:t,labelEn:n}}}class Mt extends G{constructor(t,n){super();U(this,"clientId");U(this,"clientSecret");U(this,"token");this.clientId=t,this.clientSecret=n}async authToken(t={}){const n="https://svc.data.myvessel.cn/ada/oauth/token",o={searchParams:{client_id:this.clientId,client_secret:this.clientSecret,grant_type:"client_credentials"}},i=await x.post(n,o).json();M==null||M.info("[%s] fetch access token from: %s - %j",t.requestId,n,i),i.error||(this.token={accessToken:i.access_token,tokenType:i.token_type,expiresIn:i.expires_in,scope:i.scope,jti:i.jti,issuedAt:w().utc().format()})}async checkToken(t={}){var n;return(!this.token||w().diff(w(this.token.issuedAt),"seconds")>(((n=this.token)==null?void 0:n.expiresIn)||0)-300)&&await this.authToken(t),this.token}async suggest(t,n={}){var s,r;await this.checkToken(n);const o="https://market.myvessel.cn/sdc/v1/mkt/vessels/fuzzy",i={headers:{Authorization:`${(s=this.token)==null?void 0:s.tokenType} ${(r=this.token)==null?void 0:r.accessToken}`},json:{kw:t,recordNum:n.ps||10}};M==null||M.info("[%s] fetch suggest vessels from: %s - %j",n.requestId,o,i);const a=await x.post(o,i).json();return a.status!==200?(M==null||M.warn("[%s] fetch suggest vessels failed: %j",n.requestId,{message:a.message,status:a.status,code:a.code}),[]):(a.data||[]).map(l=>({mmsi:l.mmsi,name:l.nameEn,nameCn:l.nameCn,imo:Number.isNaN(l.imo)?null:Number(l.imo),callSign:l.callsign,type:l.vesselTypeNameEn,flagName:l.flagCtry,vendor:"myvessel",raw:l}))}async search(t,n={}){var u,l;await this.checkToken(n);const o=/^\d{7}$/.test(t.toString()),i=o?"https://market.myvessel.cn/sdc/v1/mkt/vessels/detail/imo":"https://market.myvessel.cn/sdc/v1/mkt/vessels/detail/mmsi",a=o?{imo:t}:{mmsi:t},s={headers:{Authorization:`${(u=this.token)==null?void 0:u.tokenType} ${(l=this.token)==null?void 0:l.accessToken}`},searchParams:a};M==null||M.info("[%s] fetch vessel from: %s - %j",n.requestId,i,s);const r=await x.get(i,s).json();if(r.status!==200)return M==null||M.warn("[%s] fetch suggest vessels failed: %j",n.requestId,{message:r.message,status:r.status,code:r.code}),{};{const h=r.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,n={}){var s,r;await this.checkToken(n);const o="https://svc.data.myvessel.cn/sdc/v1/ship/info/batch",i={headers:{Authorization:`${(s=this.token)==null?void 0:s.tokenType} ${(r=this.token)==null?void 0:r.accessToken}`},json:{mmsiList:typeof t=="number"?[t]:t}};M==null||M.info("[%s] fetch vessel archive from: %s - %j",n.requestId,o,i);const a=await x.post(o,i).json();return a.status!==200?(M==null||M.warn("[%s] fetch vessel archive failed: %j",n.requestId,{message:a.message,status:a.status,code:a.code}),{}):a.data}async realTimePosition(t,n={}){var r,u;await this.checkToken(n);const o="https://svc.data.myvessel.cn/sdc/v1/vessels/status/location/unit",i={headers:{Authorization:`${(r=this.token)==null?void 0:r.tokenType} ${(u=this.token)==null?void 0:u.accessToken}`},searchParams:{mmsi:t}};M==null||M.info("[%s] fetch realtime position from: %s - %j",n.requestId,o,i);const a=await x.get(o,i).json();if(a.code)return M==null||M.warn("[%s] fetch realtime position failed: %j",n.requestId,{message:a.message,status:a.status,code:a.code}),a;const s=a.data;for(const l in s)!isNaN(s[l])&&Number(s[l])!==1/0&&(s[l]=Number(s[l]));if(s){const l=w(`${s.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return{mmsi:s.mmsi,name:s.vesselName||s.aisVesselName,imo:s.imo,callSign:s.callsign||s.aisCallSign,lat:s.lat,lng:s.lon,length:s.length,width:s.width,draught:s.currDraught,sog:s.sog,cog:s.cog,hdg:s.hdg,rot:s.rot,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(s.eta)?w.utc(s.eta).format():void 0,destination:s.dest,positionTime:l.unix(),status:s.status,labelCn:s.statusNameCn,labelEn:s.statusNameEn,vesselType:s.vesselTypeNameEn,flag:s.flagCtryNameEn,clasz:s.classSociety,build:s.buildYear,dwt:s.dwt,grt:s.grt,net:s.net,method:"position",vendor:"myVessel",utc:l.utc().format()}}else return{}}async calculateRoute(t,n,o,i,a,s={}){var I,v,T;const r=w();await this.checkToken(s);const u="https://market.myvessel.cn/sdc/v1/mkt/routes/plan",l={maxDraught:s.draught||10,useAIModel:s.useAIModel??!0,withECA:s.withECA||!1,withSpecialRegion:s.withSpecial||!1};t.code&&(l.startPortCode=t.code),t.lng!==void 0&&t.lat!==void 0&&(l.startPoint={lon:t.lng,lat:t.lat}),n.code&&(l.endPortCode=n.code),n.lng!==void 0&&n.lat!==void 0&&(l.endPoint={lon:n.lng,lat:n.lat}),o!=null&&o.length&&(l.crossMonthList=o),i!=null&&i.length&&(l.excludeNodes=i),a!=null&&a.length&&(l.excludeSeaAreas=a);const h={headers:{Authorization:`${(I=this.token)==null?void 0:I.tokenType} ${(v=this.token)==null?void 0:v.accessToken}`},json:l};M==null||M.info("[%s] fetch route from: %s - %j",s.requestId,u,h);const d=await x.post(u,h).json();if(d.status!==200)return M==null||M.warn("[%s] fetch route failed: %j",s.requestId,{message:d.message,status:d.status,code:d.code}),{};{const k={status:"Success",nodes:[],seas:[],regions:[],waypoints:[],route:[],distance:0,memo:""},{nodes:g,seas:b,tracks:f,specialRegions:c,ecaLength:m}=d.data;k.nodes=g==null?void 0:g.map(p=>({code:p.nodeCode,nameEn:p.nameEn,nameCn:p.nameCn,center:{lat:Math.round(p.lat*1e6)/1e6,lng:Math.round(p.lon*1e6)/1e6},start:{lat:Math.round(p.startLat*1e6)/1e6,lng:Math.round(p.startLon*1e6)/1e6},end:{lat:Math.round(p.endLat*1e6)/1e6,lng:Math.round(p.endLat*1e6)/1e6},isKey:p.isKeyNode,isHub:p.isHubNode})),k.seas=b==null?void 0:b.map(p=>({code:p.mrgidSea,nameEn:p.nameEn,nameCn:p.nameCn,center:{lat:Math.round(p.centerLat*1e6)/1e6,lng:Math.round(p.centerLon*1e6)/1e6},min:{lat:Math.round(p.minLat*1e6)/1e6,lng:Math.round(p.minLon*1e6)/1e6},max:{lat:Math.round(p.maxLat*1e6)/1e6,lng:Math.round(p.maxLon*1e6)/1e6},level:p.mapLevel})),c==null||c.map(p=>{p.regionLength&&k.regions.push({type:p.regionType,distance:p.regionLength,rows:p.regions.map(L=>({code:L.regionCode,nameCn:L.nameCn,nameEn:L.nameEn,type:L.regionType,distance:L.length}))})}),k.waypoints=f==null?void 0:f.map(p=>({lat:Math.round(p.lat*1e5)/1e5,lng:Math.round(p.lon*1e5)/1e5})),(T=k.waypoints)!=null&&T.length&&(k.waypoints=E.LaneHelper.simplifyCoordinates(k.waypoints),k.route=E.LaneHelper.divideAccordingToLng(k.waypoints),k.distance=E.LaneHelper.calculateRouteDistance(k.route),k.distanceInECA=m);const F=w().diff(r,"second");return k.memo=`time cost: ${F}s`,M.info("[%s] calculate route cost: %d seconds",s.requestId,F),k}}async trajectory(t,n,o,i,a=!0,s={}){await this.checkToken(s);const r=await this.realTimePosition(t,s),u=w(n),l=w(o),h=[];for(;l.diff(u,"day",!0)>30;)await this.trajectoryIn30Day(t,u,u.clone().add(30,"day"),r,i,h,s),u.add(30,"day");return await this.trajectoryIn30Day(t,u,l,r,i,h,s),h}async trajectoryIn30Day(t,n,o,i,a,s,r={}){var v,T,k,g,b;const u="https://svc.data.myvessel.cn/sdc/v1/vessels/status/track",l={headers:{Authorization:`${(v=this.token)==null?void 0:v.tokenType} ${(T=this.token)==null?void 0:T.accessToken}`},json:{mmsi:t,startTime:n.utcOffset(8).format("YYYY-MM-DD HH:mm:ss"),endTime:o.utcOffset(8).format("YYYY-MM-DD HH:mm:ss")}};M==null||M.info("[%s] fetch trajectory from: %s - %j",r.requestId,u,l);const h=await x.post(u,l).json();if(h.code)return M==null||M.warn("[%s] fetch trajectory failed: %j",r.requestId,u,{message:h.message,status:h.status,code:h.code}),h;let d=-1;const I=w(`${(g=(k=h.data)==null?void 0:k[0])==null?void 0:g.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return(b=h.data)==null||b.forEach(f=>{for(const H in f)!isNaN(f[H])&&Number(f[H])!==1/0&&(f[H]=Number(f[H]));const c=w(`${f.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00"),m=f.status,{labelCn:y,labelEn:F}=this.parseStatus(m),p={mmsi:f.mmsi,imo:i==null?void 0:i.imo,lat:f.lat,lng:f.lon,sog:f.sog,cog:f.cog,hdg:f.hdg,draught:f.draught,status:m,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(f.eta)?w(`${f.eta} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00").utc().format():void 0,destination:f.dest,positionTime:c.unix(),labelCn:y,labelEn:F,method:"trajectory",vendor:"myVessel",utc:c.utc().format()},L=Math.floor(c.diff(I,"minute",!0)/(a||1));L!==d&&(d=L,s.push(p))}),s}}class vt extends G{constructor(t){super();U(this,"token");this.token=t}async realTimePosition(t,n={}){const o="https://api.hifleet.com/position/position/get/token",i={searchParams:{mmsi:t,usertoken:this.token}},a=await x.post(o,i).json();M==null||M.info("[%s] fetch realtime position from: %s - %j",n.requestId,o,i);const s=a==null?void 0:a.list;if(!s)return M==null||M.warn("[%s] fetch realtime position failed: %j",n.requestId,o,a),a;for(const I in s)!isNaN(s[I])&&Number(s[I])!==1/0&&(s[I]=Number(s[I]));s.status=s.sp>3?0:1;const r=s.status,{labelCn:u,labelEn:l}=this.parseStatus(r),h=w(`${s.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return{mmsi:s.m,name:s.n,imo:s.imonumber,callSign:s.callsign,lat:Math.round(s.la/60*1e5)/1e5,lng:Math.round(s.lo/60*1e5)/1e5,length:s.l,width:s.w,draught:s.draught,sog:s.sp,cog:s.co,hdg:s.h,rot:isNaN(s.rot)?0:s.rot,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(s.eta)?w.utc(s.eta).format():void 0,destination:s.destination,vesselType:s.type,dwt:s.dwt,build:s.buildyear,flag:s.fn,positionTime:h.unix(),utc:h.utc().format(),status:r,labelCn:u,labelEn:l,method:"position",vendor:"hifleet"}}async search(t,n={}){let o="https://www.hifleet.com/hifleetapi/searchVesselOL.do";const i={searchParams:{keyword:t},headers:{Referer:"https://www.hifleet.com",Origin:"https://www.hifleet.com",Host:"www.hifleet.com"}};let a=await x.post(o,i).json();M==null||M.info("[%s] fetch vessel props from: %s - %j",n.requestId,o,i),a instanceof Array&&(a=a[0]);for(const r in a)!isNaN(a[r])&&Number(a[r])!==1/0&&(a[r]=Number(a[r]));const s={mmsi:a.m,name:a.n,imo:a.i,callSign:a.c,length:a.l,breadth:a.b,draught:a.dr,type:a.t};return o="https://www.hifleet.com/hifleetapi/sameShipSearch.do",a=await x.post(o,i).json(),M==null||M.info("[%s] search vessel dead weight from: %s - %j",n.requestId,o,i),a instanceof Array&&(a=a[0]),a&&(s.deadweight=Number(a.dwt)),s}async suggest(t,n={}){const o="https://www.hifleet.com/hifleetapi/getShipSuggest.do",i={searchParams:{q:t},headers:{Referer:"https://www.hifleet.com",Origin:"https://www.hifleet.com",Host:"www.hifleet.com"}},a=await x.post(o,i).json();M==null||M.info("[%s] suggest vessel props from: %s - %j",n.requestId,o,i);const s=[];for(const r of a)s.push({mmsi:!r.mmsi||isNaN(r.mmsi)?null:Number(r.mmsi),name:r.name,callSign:r.callsign,imo:!r.imo||isNaN(r.imo)?null:Number(r.imo),score:r._score});return s.sort((r,u)=>u.score-r.score),s}async trajectory(t,n,o,i,a=!0,s={}){var f,c,m;const r=await this.realTimePosition(t,s);let u=w(n);const l=w(o),h=w();if(a){let y=l.diff(u,"d",!0);y<0?u=l.clone().subtract(40,"d"):y<30?u.subtract(10,"d"):y<60?u.subtract(5,"d"):u=l.clone().subtract(80,"d"),y=h.diff(l,"d",!0),l.add(y>10?240:y*24,"h")}const d={searchParams:{endtime:l.utcOffset("+8:00").format("YYYY-MM-DD HH:mm:ss"),starttime:u.utcOffset("+8:00").format("YYYY-MM-DD HH:mm:ss"),mmsi:t,usertoken:this.token}},I="https://api.hifleet.com/position/trajectory/nocompressed/withstatic/token",v=await x.get(I,d).json();M==null||M.info("[%s] fetch trajectory from: %s - %j",s.requestId,I,d);let T;v&&(T=((c=(f=v.ships)==null?void 0:f.offors)==null?void 0:c.ship)||[],T.length||M==null||M.warn("[%s] fetch trajectory failed: %j",s.requestId,v));const k=[];let g=-1;const b=w(`${(m=T==null?void 0:T[0])==null?void 0:m.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");for(const y of T){for(const W in y)!isNaN(y[W])&&Number(y[W])!==1/0&&(y[W]=Number(y[W]));const F=w(`${y.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");y.status=y.sp>4?0:1;const{labelEn:p,labelCn:L}=this.parseStatus(y.status),H={mmsi:y.m,name:y.n,imo:r==null?void 0:r.imo,lat:y.la,lng:y.lo,draught:y.draught,sog:y.sp,cog:y.co,hdg:y.hdg,positionTime:F.unix(),utc:F.utc().format(),status:y.status,labelCn:L,labelEn:p,method:"trajectory",vendor:"hifleet"},N=Math.floor(F.diff(b,"minute",!0)/(i||1));N!==g&&(g=N,k.push(H))}return k}}class bt extends G{constructor(t){super();U(this,"token");this.token=t}async realTimePosition(t,n={}){const o={searchParams:{id:t,k:this.token,enc:1}},i="https://api.shipxy.com/apicall/GetSingleShip",a=await x.get(i,o).json();if(M==null||M.info("[%s] fetch realtime position from: %s - %j",n.requestId,i,o),(a==null?void 0:a.status)!==0)return a;const s=a.data[0];for(const d in s)!isNaN(s[d])&&Number(s[d])!==1/0&&(s[d]=Number(s[d]));const{labelCn:r,labelEn:u}=await this.parseStatus(s.navistat),l=w.unix(s.lasttime);return{mmsi:s.ShipID,name:s.name,imo:s.imo,callSign:s.callsign,lat:Math.round(s.lat/1e6*1e5)/1e5,lng:Math.round(s.lon/1e6*1e5)/1e5,length:Math.round(s.length/10*100)/100,width:Math.round(s.width/10*100)/100,draught:Math.round(s.draught/1e3*100)/100,sog:Math.round(s.sog*3600/1e3/1852*100)/100,cog:Math.round(s.cog/100*100)/100,hdg:Math.round(s.hdg/100*100)/100,rot:Math.round(s.rot/100*100)/100,positionTime:s.lasttime,utc:l.utc().format(),status:s.navistat,labelEn:u,labelCn:r,method:"position",vendor:"shipxy"}}async trajectory(t,n,o,i,a=!0,s={}){var b;const r=await this.realTimePosition(t,s),u=w(n),l=w(o),h="https://api.shipxy.com/apicall/GetShipTrack",d={searchParams:{id:t,k:this.token,enc:1,cut:0,btm:u.unix(),etm:l.unix()}},I=await x.get(h,d).json();if(M==null||M.info("[%s] fetch trajectory from: %s - %j",s.requestId,h,d),(I==null?void 0:I.status)!==0)return I;const v=I==null?void 0:I.points,T=[],k=w.unix((b=v[0])==null?void 0:b.utc);let g=-1;for(const f of v){const c=w.unix(f.utc),m={imo:r==null?void 0:r.imo,mmsi:t,sog:Math.round(f.sog*3600/1e3/1852*100)/100,cog:Math.round(f.cog/100*100)/100,lat:Math.round(f.lat/1e6*1e5)/1e5,lng:Math.round(f.lon/1e6*1e5)/1e5,positionTime:c.unix(),utc:c.utc().format(),method:"trajectory",vendor:"shipxy"},y=Math.floor(c.diff(k,"minute",!0)/(i||1));y!==g&&(g=y,T.push(m))}return T}}class gt extends G{constructor(t){super();U(this,"token");this.token=t}async getShipId(t,n={}){const o={headers:{appKey:this.token},json:{mmsiList:t}},i="https://api3.myships.com/sp/ships/getShipIdByMMSI",a=await x.post(i,o).json();return M==null||M.info("[%s] fetch ship id from: %s - %j",n.requestId,i,o),a.code!=="0"?a:a.data[0].shipId}async getShipInfo(t,n={}){const o={headers:{appKey:this.token},json:{shipId:t}},i="https://api3.myships.com/sp/ships/aissta",a=await x.post(i,o).json();if(M==null||M.info("[%s] fetch ship info from: %s - %j",n.requestId,i,o),a.code!=="0")return a;const s=a.data;let r=s.imo;return t==="407170"&&(r="9198379",M==null||M.warn("[%s] ship(%s) imo error: %s, should be %s",n.requestId,t,s.imo,r)),{mmsi:s.mmsi,name:s.shipnameEn,imo:r,callSign:s.callSign,length:s.length,width:s.breadth,draught:(s.draught||100)/10}}async realTimePosition(t,n={}){const o=await this.getShipId(t,n),i=await this.getShipInfo(o,n),a={headers:{appKey:this.token},json:{shipId:o}},s="https://api3.myships.com/sp/ships/position/latest",r=await x.post(s,a).json();M==null||M.info("[%s] fetch realtime position from: %s - %j",n.requestId,s,a);const u=r.data[0];for(const v in u)!isNaN(u[v])&&Number(u[v])!==1/0&&(u[v]=Number(u[v]));const{labelCn:l,labelEn:h}=await this.parseStatus(u.aisNavStatus),d=w.unix(u.posTime);return{...i,mmsi:t,lat:Math.round(u.lat/1e4/60*1e5)/1e5,lng:Math.round(u.lon/1e4/60*1e5)/1e5,sog:Math.round(u.sog/10*100)/100,cog:Math.round(u.cog/10*100)/100,hdg:Math.round(u.heading*100)/100,rot:Math.round(u.rot*100)/100,positionTime:u.posTime,utc:d.utc().format(),status:u.aisNavStatus,labelEn:h,labelCn:l,method:"position",vendor:"myship"}}async trajectory(t,n,o,i,a=!0,s={}){const r=w(n),u=w(o),l=await this.getShipId(t),h=await this.getShipInfo(l),d=[];for(;u.diff(r,"day",!0)>30;)await this.trajectoryIn30Day(l,r.unix(),r.add(30,"day").unix(),h,t,i,d);return await this.trajectoryIn30Day(l,r.unix(),u.unix(),h,t,i,d),d}async trajectoryIn30Day(t,n,o,i,a,s,r,u={}){var k;const l={headers:{appKey:this.token},json:{shipId:t,startTime:n,endTime:o}},h="https://api3.myships.com/sp/ships/position/history",d=await x.post(h,l).json();if(M==null||M.info("[%s] fetch trajectory from: %s - %j",u.requestId,h,l),d.code!=="0")return M==null||M.warn("[%s] invoke myship trajectory failed: %j",u.requestId,d),d;const I=d.data;for(const g in I)!isNaN(I[g])&&Number(I[g])!==1/0&&(I[g]=Number(I[g]));const v=w.unix((k=I[0])==null?void 0:k.posTime);let T=-1;for(const g of I){const b=w.unix(g.posTime),f={imo:i==null?void 0:i.imo,mmsi:a,lat:Math.round(g.lat/1e4/60*1e5)/1e5,lng:Math.round(g.lon/1e4/60*1e5)/1e5,sog:Math.round(g.sog/10*100)/100,cog:Math.round(g.cog/10*100)/100,hdg:Math.round(g.heading*100)/100,rot:Math.round(g.rot*100)/100,positionTime:b.unix(),utc:b.utc().format(),method:"trajectory",vendor:"myship"},c=Math.floor(b.diff(v,"minute",!0)/(s||1));c!==T&&(T=c,r.push(f))}return r}}let _;try{_=K.getLogger("vessel")}catch{}finally{}var lt=(A=>(A.NOTICE="NOTICE",A.WARN="WARN",A.HEAVY="HEAVY",A.SEVERE="SEVERE",A.ERROR="ERROR",A.FATAL="FATAL",A))(lt||{});class ht{parsePrinciple(e,t={}){var s,r,u;_==null||_.debug("[%s] parse rule: %s",t.requestId,e);const n=new RegExp("(?<=\\[)(.+)(?=])","g"),o=e.match(n)?(s=e.match(n))==null?void 0:s[0]:void 0,i=o==null?void 0:o.split(";");if(!i)return;const a={};for(let l=0;l<(i==null?void 0:i.length);l++){const h=(u=(r=i[l].match(n))==null?void 0:r[0])==null?void 0:u.split("],");if(l===0&&!h)a.scope=i[0];else if(h)for(let d=0,I=h.length;d<I;d++){const v=this.parseRule(h[d]);v&&(a[v.level]?v.key?a[v.level][v==null?void 0:v.key]=v:a[v.level]=v:v.key?a[v.level]={[v==null?void 0:v.key]:v}:a[v.level]=v)}}return a}parseRule(e,t={}){var a;_==null||_.debug("[%s] parse rule: %s",t.requestId,e),e=e.startsWith("[")?e:`[${e}`,e=e.endsWith("]")?e:`${e}]`;const n=new RegExp("(?<=\\[)(.+?)(?=])","g"),o=(a=e==null?void 0:e.match(n))==null?void 0:a[0],i=o==null?void 0:o.split(",");if(i){let s=i[3]==="Number.MAX_VALUE"?100:Number(i[3]);return s=isNaN(s)?1:s,{operator:i[0],number:Number.isNaN(Number(i[1]))?i[1]:Number(i[1]),level:i[2],time:s,key:i[4]}}}checkWeather(e,t,n={}){var v,T,k,g,b,f,c,m,y,F,p,L,H,N,W;let o=0,i=0,a=0,s=0;const r=Math.round(((T=(v=t==null?void 0:t.SEVERE)==null?void 0:v.sigWave)==null?void 0:T.number)*1.6*100)/100,u=(g=(k=t==null?void 0:t.SEVERE)==null?void 0:k.sigWave)==null?void 0:g.number,l=(f=(b=t==null?void 0:t.HEAVY)==null?void 0:b.sigWave)==null?void 0:f.number,h=Math.round((((m=(c=t==null?void 0:t.SEVERE)==null?void 0:c.wind)==null?void 0:m.number)+2)*100)/100,d=(F=(y=t==null?void 0:t.SEVERE)==null?void 0:y.wind)==null?void 0:F.number,I=(L=(p=t==null?void 0:t.HEAVY)==null?void 0:p.wind)==null?void 0:L.number;for(let B=0;B<(e==null?void 0:e.length);B++){const C=e[B],R=(N=(H=C==null?void 0:C.meteo)==null?void 0:H.wave)==null?void 0:N.sig,q=(W=C==null?void 0:C.meteo)==null?void 0:W.wind,z=B?w(C.eta).diff(w(e[B-1].eta),"hour",!0):0;s=z>s?z:s,_==null||_.debug("[%s] check sig.wave: %j",n.requestId,{...R,dgThd4Wv:r,svThd4Wv:u,hvThd4Wv:l}),(R==null?void 0:R.height)>=r?C.isDangerous=!0:(R==null?void 0:R.height)>=u?C.isSevere=!0:(R==null?void 0:R.height)>=l&&(C.isHeavy=!0),_==null||_.debug("[%s] check wind: %j",n.requestId,{...q,dgThd4Wd:h,svThd4Wd:d,hvThd4Wd:I}),(q==null?void 0:q.scale)>=h?(C.isDangerous=!0,delete C.isSevere,delete C.isHeavy):(q==null?void 0:q.scale)>d?(C.isDangerous||(C.isSevere=!0),delete C.isHeavy):(q==null?void 0:q.scale)===I&&!C.isDangerous&&!C.isSevere&&(C.isHeavy=!0),o+=C.isDangerous?z:0,i+=C.isSevere?z:0,a+=C.isHeavy?z:0}return o=Math.round(o*100)/100,i=Math.round(i*100)/100,a=Math.round(a*100)/100,s=Math.round(s),{sample:e,dangerous:o,severe:i,heavy:a,step:s<3?3:s,wind:{dgThd4Wd:h,svThd4Wd:d,hvThd4Wd:I},sig:{dgThd4Wv:r,svThd4Wv:u,hvThd4Wv:l}}}}const wt=new ht;let S;try{S=K.getLogger("vessel")}catch{}finally{}const It=new pt.MeteoHelper2("",!0);var ft=(A=>(A.common="common",A.container="container",A.tugs="tugs",A))(ft||{}),mt=(A=>(A.Ballast="Ballast",A.Laden="Laden",A))(mt||{}),yt=(A=>(A.Cp="CP",A.Perf="Basis",A.Instruct="Other",A))(yt||{});class O{static blockCoefficient(e,t,n,o){let i=Math.round(e/(t*n*o)*100)/100;i=i<.55?.55:i>.85?.85:i;const a=[.55,.6,.65,.7,.75,.8,.85],s=a.map(r=>Math.abs(r-i));return a[s.indexOf(Math.min(...s))]}static froudeNumber(e,t,n=9.8){let o=Math.round(Math.sqrt(e*e/(n*t))*100)/100;return o=o<.05?.05:o>.3?.3:o,o}static amendFactor(e,t,n){const o={.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 a={.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]}[e];return n==="Laden"&&(a=o[e]),a[0]+a[1]*t+a[2]*Math.pow(t,2)}static directionFactor(e,t=0){let n;return e>30&&e<=60?n=(1.7-.03*Math.pow(t-4,2))/2:e>60&&e<=150?n=(.9-.06*Math.pow(t-6,2))/2:e>150&&e<=180?n=(.4-.03*Math.pow(t-8,2))/2:n=1,Math.round(n*1e5)/1e5}static vesselTagFactor(e,t,n,o){let i;return n==="container"?i=.7*o/2+Math.pow(o,3)/(22*Math.pow(e,2/3)):t==="Ballast"?i=.7*o/2+Math.pow(o,3)/(2.7*Math.pow(e,2/3)):i=.5*o/2+Math.pow(o,3)/(2.7*Math.pow(e,2/3)),i}static waveHeightFactor(e,t,n=10,o={}){e=e<3?e*.7:e,e=e<0?.2:e,e=e>6?e-.9*(e-6):e,e=e>9?9:e;const i=Math.max(n>10?n-10:2.8);let a;return t>30&&t<=60?a=-.6:t>60&&t<=90?a=-.5:t>90&&t<=120?a=e<i?.2:-.3:t>120&&t<=150?a=e<i?.25:-.2:t>150&&t<=180?a=e<i?.3:-.1:a=-.7,S==null||S.info("[%s] calculate wave height factor with ht(%d), beta(%d), draught(%d) and factor(%d)",o.requestId,e,t,n,a),Math.round(a*(.144*Math.pow(e,2)+.378*e)*1e4)/1e4}static assembleProperties(e,t,n,o){var d;const i=e.lbp??e.length??e.lengthOverall??198.9642,a=e.draught??8,s=e.breadthMoulded??e.breadth??e.breadthExtreme??32.4572,r=e.deadweight??67035.7773,u=((d=e==null?void 0:e.type)==null?void 0:d.toLowerCase())||"common";return{tag:u.indexOf("container")>-1?"container":u.indexOf("tugs")>-1?"tugs":"common",lbp:i,loadCondition:t,draught:a,breadthMoulded:s,displacement:Math.round((r/1.025+a*s*i*.7)*1e4)/1e4,speed:Math.round((n??14.1382)*1852/3600*1e4)/1e4,bearing:o||90}}static async speedLoseAt(e,t,n,o="",i=2,a=!0,s=!1,r={}){let u;if(t.velocity&&s&&(e.speed=E.LngLatHelper.roundPrecision(t.velocity*1852/3600,6)),a){let l;try{o=(o==null?void 0:o.toUpperCase())==="CMEMS"?"ECMWF":o,o=(o==null?void 0:o.toUpperCase())==="METEO2"?"best_match":o;const{weatherModels:k,marineModels:g}=await it.Meteo2Assist.autoPickMeteoModel(o),b=n.utc().format(),f=await It.spotForecast(t.lat,t.lng,b,!1,!1,!0,{...r,pastDays:1,forecastDays:2,weatherModels:k,marineModels:g}),[c]=it.Meteo2Assist.pickHourly(f,b);l=it.Meteo2Assist.toLegacy(c)}catch(k){S.warn("[%s] meteo2 spot(%j) forecast failed: %s",r.requestId,{...t,eta:n.utc().format(),source:o},k)}let h=O.currentFactor(e.bearing,l==null?void 0:l.current,i,r),d=O.weatherFactor(e,l,h,r);const I=e.speed*1.943844;I+h+d<=0&&(S.warn("[%s] v0(%d) is less then factor(%d) = wxFactor(%d) + cFactor(%d), scale factor with 0.6",r.requestId,I,d+h,d,h),h=Math.round(h*.6*1e3)/1e3,d=Math.round(d*.6*1e3)/1e3);const v=d<=(r.minV0Factor||-1)?Math.max(r.maxV0Factor||-3,-1*d*(d/1.2)):0;S==null||S.info("[%s] calculate speed lose with v0Factor(%d), cFactor(%d) and wxFactor(%d)",r.requestId,v,h,d),d+=v;let T=Math.round((I+h+d)*100)/100;T=T<=0?1:T,u={meteo:{...l},wxFactor:d,v0Factor:v,cFactor:h,speed:t.velocity&&s?t.velocity:T,eta:n.utc().format(),etd:n.utc().format()}}else u={wxFactor:0,v0Factor:0,cFactor:0,speed:t.velocity&&s?t.velocity:Math.round(e.speed*1.943844*100)/100,eta:n.utc().format(),etd:n.utc().format()};return delete t.meteo,delete t.wxFactor,delete t.cFactor,delete t.speed,delete t.etd,{...u,...t}}static async speedLoseInHoursStep(e,t,n,o,i,a,s="",r=!0,u=!1,l={}){t.utc();const h=t.clone().add(14,"days"),d=[],I=[],v=[];let T=0,k=0,g,b;for(let f=0;f<a.length-1;f++){let c=a[f];c.distanceFromStart=Math.round((i+k)*1e3)/1e3;const m=a[f+1];if(e.bearing=E.LaneHelper.calculateBearing(c,m,!m.gcToPrevious),c.bearing=e.bearing,c.suspend&&u){c.eta=c.eta||t.utc().format(),c.elapsed=c.elapsed??0;const p=c.suspend-c.elapsed;if(o-T>p)o=o-T-p,t.add(p,"hour"),c.elapsed=c.suspend;else{const L=o-T;c.elapsed+=L,t.add(L,"hour"),o=0}if(S==null||S.info(`[%s] suspend ${c.elapsed} hours at %j, and remain ${o} hours need to go...`,l.requestId,c),o===0)return c.distanceFromPrevious=k,{etd:t,from:b||c,to:c,next:a.filter(L=>L),wps:d,days:I,all:v}}else c.suspend=0;r=t.isAfter(h)?!1:r,c=await O.speedLoseAt(e,c,t,s,0,r,u,l),v.push(c),b=b||c,c.important&&d.push(c),t.isSameOrAfter(n)&&(I.push(c),n.add(24,"hour"));const y=E.LaneHelper.calculateDistance(c,m,!m.gcToPrevious);let F=Math.round(y/b.speed*1e5)/1e5;if(T+F<o){if(T+=F,t.add(F,"hour"),delete a[f],S==null||S.debug(`[%s] go to %j from %j with ${y}nm, and cost ${F} hours`,l.requestId,{lat:m.lat,lng:m.lng},{lat:b.lat,lng:b.lng,etd:b.etd}),k+=y,a.filter(p=>p).length<=1){g=m,g.eta=t.utc().format(),g.distanceFromPrevious=y,g.distanceFromStart=Math.round((i+k)*1e4)/1e4,d.push(g),v.push(g),delete a[f+1];break}}else{F=o-T,t.add(F,"hour");const p=E.LngLatHelper.roundPrecision(b.speed*F,5);g=E.LaneHelper.calculateCoordinate(c,e.bearing,p,"nauticalmiles",!m.gcToPrevious),g.eta=t.utc().format(),a[f]=g,S==null||S.debug(`[%s] go to %j from %j with ${p}nm, and cost ${F} hours`,l.requestId,{lat:g.lat,lng:g.lng},{lat:c.lat,lng:c.lng,etd:c.etd}),k+=p,g.distanceFromPrevious=Math.round(k*1e4)/1e4,g.distanceFromStart=Math.round((i+k)*1e4)/1e4;break}}return{etd:t,from:b,to:g,next:a.filter(f=>f),wps:d,days:I,all:v}}static currentFactor(e,t,n=0,o={}){const i=E.LaneHelper.includedAngle(e,(t==null?void 0:t.degree)||0)/180*Math.PI;let a;return Math.abs(i)===Math.PI/2&&(a=0),a=((t==null?void 0:t.kts)||0)*Math.cos(i),n&2?a=Math.ceil(a*100)/100:n&1?a=Math.floor(a*100)/100:a=Math.round(a*100)/100,S==null||S.info("[%s] calculate current factor with %j",o.requestId,{beta:i,current:t,factor:a,role:n}),Math.abs(a)>5?0:a}static weatherFactor(e,t,n=0,o={}){var v,T,k,g,b,f,c;S==null||S.info("[%s] calculate weather factor via: %j",o.requestId,{...e,...t});const i=O.blockCoefficient(e.displacement,e.lbp,e.breadthMoulded,e.draught),a=E.LngLatHelper.roundPrecision(n*1852/3600,6),s=O.froudeNumber(e.speed-a,e.lbp),r=O.amendFactor(i,s,e.loadCondition);let u=E.LaneHelper.includedAngle(e.bearing,(v=t==null?void 0:t.wind)==null?void 0:v.degree);const l=O.directionFactor(u,(T=t==null?void 0:t.wind)==null?void 0:T.scale),h=O.vesselTagFactor(e.displacement,e.loadCondition,e.tag,((k=t==null?void 0:t.wind)==null?void 0:k.kts)||10);let d=l*r*h/100*(e.speed-a);d=Math.round(d*1.943844*1e4)/1e4*-1,e.tag==="tugs"&&Math.abs(d)>1&&(d=d/(Math.abs(Math.round(d))+1)),S==null||S.info("[%s] calculate wind wx factor: %d",o.requestId,d),u=E.LaneHelper.includedAngle(e.bearing,(b=(g=t==null?void 0:t.wave)==null?void 0:g.sig)==null?void 0:b.degree);const I=O.waveHeightFactor(((c=(f=t==null?void 0:t.wave)==null?void 0:f.sig)==null?void 0:c.height)??1,u,e.draught,o);return S==null||S.info("[%s] calculate wave wx factor: %d",o.requestId,I),d=Math.abs(d)>Math.abs(I)?d:.7*d+.9*I,S==null||S.info("[%s] calculate finial weather factor: %d (0.7 * wf) + (0.9 * hf)",o.requestId,d),Math.round((d||0)*100)/100}static async reduceDays(e,t=12*60*60){return e=e==null?void 0:e.reduce((n,o)=>(o.positionTime||(o.positionTime=w.utc(o.etd||o.eta).unix()),n.some(i=>Math.floor(i.positionTime/t)===Math.floor(o.positionTime/t))||n.push(o),n),[]),e}static async reduceWPS(e,t=60){return e=e==null?void 0:e.reduce((n,o)=>(n.some(i=>Math.floor(w(i.etd).unix()/t)===Math.floor(w(o.etd).unix()/t))||n.push(o),n),[]),e}static async analyseInstant(e,t,n,o,i,a="",s=0,r=!0,u=!1,l={}){var X,Q,Z,$,tt,et;const h=w().valueOf();e.lng=E.LngLatHelper.convertToStdLng(e.lng);const{route:d,waypoints:I}=i.points,v=E.LaneHelper.calculateSubRoute(e,d);if(((X=v[0])==null?void 0:X.length)<=1)return;const{v0:T,label:k}=e.sog?{v0:e.sog,label:e.label||"Other"}:{v0:o.speed,label:"CP"},g=O.assembleProperties(n,o.loadCondition,T,0),b=I.length?E.LaneHelper.calculateSubWaypoints(e,I):[];b.forEach(D=>D.important=!0);const f={from:{...e},route:v,waypoints:b,v0:T,label:k},c={hours:[],days:[],wps:[],all:[]};s||(E.LaneHelper.calculateRouteDistance(v)/o.speed<=72?s=3:s=6);let m=E.LaneHelper.simplifyRouteToCoordinates(v,b,0),y=0,F=0,p=0,L=0;t=w(t).utc();const H=t.clone();for(;m.length>0;){const D=s-t.hour()%s,J=Math.ceil(t.clone().add(D,"h").set({minute:0,second:0,millisecond:0}).diff(t,"h",!0)*1e4)/1e4,j=await O.speedLoseInHoursStep(g,t,H,J,y,m,a,r,u,l);if(c.all.push(...j.all),(Q=j.from)!=null&&Q.speed&&(c.hours.push(j.from),c.wps.push(...j.wps),c.days.push(...j.days)),m=j==null?void 0:j.next,!m.length){const V=await O.speedLoseAt(g,j.to,w(j.to.eta),a,0,r,u,l);V.bearing=g.bearing,c.hours.push(V),c.all.push(V)}y+=Math.round((((Z=j==null?void 0:j.to)==null?void 0:Z.distanceFromPrevious)??0)*1e4)/1e4}const N=c.hours;for(let D=0;D<N.length-1;D++){const J=w(N[D+1].eta).diff(N[D].etd,"hour",!0)||1;F+=(N[D].wxFactor||0)*J,p+=(N[D].cFactor||0)*J,L+=J}const W=N.reduce((D,J)=>D+(J.suspend||0),0);($=c.wps)==null||$.forEach((D,J)=>{D.positionTime=w.utc(D.etd||D.eta).unix();const j=c.wps[J-1];if(j){const V=D.distanceFromStart-j.distanceFromStart,Y=w(D.eta||D.etd).diff(w(j.etd||j.eta),"h",!0);D.avgSpd=Math.round(V/Y*100)/100;const ot=E.LaneHelper.calculateBearing(j,D);D.avgBearing=ot,j.bearing=ot}}),c.wps=await O.reduceWPS(c.wps),c.days=await O.reduceDays(c.days),c.all=(tt=c.all)==null?void 0:tt.reduce((D,J)=>(J.positionTime=w.utc(J.etd||J.eta).unix(),D.some(j=>Math.round(j.positionTime/60)===Math.round(J.positionTime/60))||D.push(J),D),[]),f.sample=c;const B=c.hours.at(0),C=c.hours.at(-1);f.distance=Math.round(C.distanceFromStart*1e3)/1e3,f.etd=w(B.eta).utc().format(),f.eta=w(C.eta).utc().format(),f.wxFactor=Math.round(F/L*1e3)/1e3,f.cFactor=Math.round(p/L*1e3)/1e3,f.avgSpeed=Math.round(C.distanceFromStart/L*1e3)/1e3,f.totalHrs=Math.round(L*1e3)/1e3,f.suspend=Math.round(W*1e3)/1e3;const R=E.LngLatHelper.roundPrecision(o.dgo/24*W,3),{distanceInECA:q,hoursInECA:z,totalDgoConsInECA:rt,eca:st}=await this.calculateECA(f,o,l),at=E.LngLatHelper.roundPrecision(o.fo/24*(L-z),3),ct=E.LngLatHelper.roundPrecision(o.dgo/24*L+R,3);f.extend={eca:st,distanceInECA:q,hoursInECA:z,totalDgoConsInECA:rt,totalDgoConsInSuspend:R},f.totalFoCons=at<0?0:at,f.totalDgoCons=ct;const nt=w().valueOf()-h,ut=((et=c==null?void 0:c.hours)==null?void 0:et.length)||1;return S==null||S.info("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms",l==null?void 0:l.requestId,nt,ut,Math.round(nt/ut*1e3)/1e3),f}static async analyseInstantWithThreshed(e,t,n,o,i,a,s,r="",u=3,l=!0,h=!1,d={}){var Z,$,tt,et,D,J;const I=w().valueOf();e.lng=E.LngLatHelper.convertToStdLng(e.lng);const{v0:v,label:T}=e.sog?{v0:e.sog,label:e.label||"Other"}:{v0:i.speed,label:"CP"},k=O.assembleProperties(o,i.loadCondition,v,0),g=E.LaneHelper.calculateSubRoute(e,a);if(((Z=g[0])==null?void 0:Z.length)<=1)return;const b=s.length?E.LaneHelper.calculateSubWaypoints(e,s):[];b.forEach(j=>j.important=!0);let f=E.LaneHelper.simplifyRouteToCoordinates(g,b,0),c=0,m=0,y=0,F=0;const p={hours:[],wps:[],days:[],all:[]};t=w(t).utc();const L=t.clone();for(;f.length>0;){const j=u-t.hour()%u;let V=Math.ceil(t.clone().add(j,"h").set({minute:0,second:0,millisecond:0}).diff(t,"h",!0)*1e4)/1e4;V=t.clone().add(V,"h").isSameOrAfter(n)?n.diff(t,"h",!0)*1e4/1e4:V;const Y=await O.speedLoseInHoursStep(k,t,L,V,c,f,r,l,h,d);if(p.all.push(...Y.all),($=Y.from)!=null&&$.speed&&(p.hours.push(Y.from),Y!=null&&Y.wps&&p.wps.push(...Y.wps),p.days.push(...Y.days)),f=Y==null?void 0:Y.next,f.length||p.hours.push(Y==null?void 0:Y.to),c+=Math.round((((tt=Y==null?void 0:Y.to)==null?void 0:tt.distanceFromPrevious)??0)*1e4)/1e4,!V)break}p.wps=await O.reduceWPS(p.wps),p.days=await O.reduceDays(p.days),p.all=(et=p.all)==null?void 0:et.reduce((j,V)=>(V.positionTime=w.utc(V.etd||V.eta).unix(),j.some(Y=>Math.round(w(Y.etd).unix()/60)===Math.round(w(V.etd).unix()/60))||j.push(V),j),[]),(D=p.wps)==null||D.forEach((j,V)=>{const Y=p.wps[V-1];if(Y){const ot=j.distanceFromStart-Y.distanceFromStart,kt=w(j.eta||j.etd).diff(w(Y.etd||Y.eta),"h",!0);Y.bearing=E.LaneHelper.calculateBearing(Y,j),j.avgSpd=Math.round(ot/kt*100)/100}});const H=p.hours;for(let j=0;j<H.length-1;j++){const V=w(H[j+1].eta).diff(H[j].etd,"hour",!0);m+=H[j].wxFactor*V,y+=H[j].cFactor*V,F+=V}const N=H.reduce((j,V)=>j+(V.suspend||0),0),W=p.hours.at(0),B=p.hours.at(-1),C=await E.LaneHelper.calculateRangeRoute(W,B,g),R=await E.LaneHelper.calculateRangeWaypoints(W,B,g,b),q={sample:p,distance:Math.round(((B==null?void 0:B.distanceFromStart)||0)*1e4)/1e4,etd:w(W.eta).utc().format(),eta:w(B==null?void 0:B.eta).utc().format(),wxFactor:Math.round(m/F*1e3)/1e3,cFactor:Math.round(y/F*1e3)/1e3,avgSpeed:Math.round(((B==null?void 0:B.distanceFromStart)||0)/F*1e3)/1e3,totalHrs:Math.round(F*1e3)/1e3,suspend:Math.round(N*1e3)/1e3,from:W,to:B,route:C,waypoints:R,v0:v,label:T},z=E.LngLatHelper.roundPrecision(i.dgo/24*N,3),{distanceInECA:rt,hoursInECA:st,totalDgoConsInECA:at,eca:ct}=await this.calculateECA(q,i,d),dt=E.LngLatHelper.roundPrecision(i.fo/24*(F-st),3),nt=E.LngLatHelper.roundPrecision(i.dgo/24*F+z,3);q.extend={eca:ct,distanceInECA:rt,hoursInECA:st,totalDgoConsInECA:at,totalDgoConsInSuspend:z},q.totalDgoCons=nt,q.totalFoCons=dt<0?0:dt;const X=w().valueOf()-I,Q=((J=p==null?void 0:p.hours)==null?void 0:J.length)||1;return S==null||S.debug("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms",d==null?void 0:d.requestId,X,Q,Math.round(X/Q*1e3)/1e3),q}static async analyseCost(e,t,n,o,i={}){var g,b;const a=w().valueOf(),s=[];e.speedStep=e.speedStep||3,e.alterStep=e.alterStep??1;const r=E.LaneHelper.calculateRouteDistance(o.route);let u=0;n.forEach(f=>{const c=Math.ceil(r/f.speed/24);u=u<c?c:u}),u=u*1.3;const l=w.utc(e.etd).add(u??14,"day");let h=1;for(const f of n){const c=JSON.parse(JSON.stringify(o.route)),m=JSON.parse(JSON.stringify(o.waypoints)),y=await O.analyseInstantWithThreshed({lat:e.lat,lng:e.lng},e.etd,l,t,f,c,m,e.meteoVendor,e.speedStep,e.useMeteo,e.useRouteParam,i);y&&(await O.calculateCost(y,f,e,i),s.push(y),S==null||S.info("[%s][L%d-%d] analyse from %s to %s cost: %j",i.requestId,1,h,e.etd,l.format(),{cost:y.cost.total,hire:y.cost.hire,bunker:y.cost.bunker,distance:y.distance,hours:y.totalHrs,cp:`${f.speed}/${f.fo}/${f.dgo}`})),h++}s.sort((f,c)=>f.cost.total-c.cost.total);const d=s.at(0),I=s.at(1),v=[];if(v.push({combined:!1,speeds:[d],cost:(g=d.cost)==null?void 0:g.total}),I){const f=d.cost.cp,c=I.cost.cp,m=w(d.eta),y=w(d.etd),F=m.diff(y,"days",!0);let p=Math.ceil(F/2);p=p>7?7:p<e.alterStep?e.alterStep:p;let L=2,H={combined:!1,speeds:[I],cost:(b=I.cost)==null?void 0:b.total},N;for(;p>=e.alterStep;){const W=await O.combinedAnalyse(e,t,l,[f,c],o,p,{...i,level:L});if(H.cost>W.cost?N?(N==null?void 0:N.cost)>W.cost&&(N=W):(N=H,H=W):(!N||(N==null?void 0:N.cost)>W.cost)&&(N=W),p<=e.alterStep)break;p=Math.ceil(p/2),L+=1}v.push(H),N&&v.push(N)}const k=w().valueOf()-a;return S==null||S.info("[%s] analyse elapsed: %d ms",i==null?void 0:i.requestId,k),v.sort((f,c)=>f.cost-c.cost)}static async combinedAnalyse(e,t,n,o,i,a,s={}){s.counter=1,S==null||S.info("[%s][L%d] analyse with alternate cp in every %d days",s.requestId,s.level,a);const r=await O.alternateAnalyse(e,t,n,o,0,i,a,s),u=r.reduce((c,m)=>c+m.cost.total,0),l=r.reduce((c,m)=>c+m.cost.hire,0),h=r.reduce((c,m)=>c+m.cost.bunker,0),d=r.reduce((c,m)=>c+m.distance,0),I=r.reduce((c,m)=>c+m.totalHrs,0);S==null||S.info("[%s][L%d] cost with cpa/cpb turn: %j",s.requestId,s.level,{cost:u,hire:l,bunker:h,distance:d,hours:I});const v=await O.alternateAnalyse(e,t,n,o,1,i,a,s),T=v.reduce((c,m)=>c+m.cost.total,0),k=v.reduce((c,m)=>c+m.cost.hire,0),g=v.reduce((c,m)=>c+m.cost.bunker,0),b=v.reduce((c,m)=>c+m.distance,0),f=v.reduce((c,m)=>c+m.totalHrs,0);return S==null||S.info("[%s][L%d] cost with cpb/cpa turn: %j",s.requestId,s.level,{cost:T,hire:k,bunker:g,distance:b,hours:f}),u<T?{combined:!0,cost:Math.round(u*1e3)/1e3,speeds:r,step:a}:{combined:!0,cost:Math.round(T*1e3)/1e3,speeds:v,step:a}}static async alternateAnalyse(e,t,n,o,i,a,s,r={}){var d,I;let u=w.utc(e.etd);const l={lat:e.lat,lng:e.lng},h=[];for(;u.isBefore(n);){const v=u.clone().utc().add(s,"day"),T=JSON.parse(JSON.stringify(a.route)),k=JSON.parse(JSON.stringify(a.waypoints)),g=o[i],b=await O.analyseInstantWithThreshed(l,u.utc().format(),v,t,g,T,k,e.meteoVendor,e.speedStep,e.useMeteo,e.useRouteParam,r);b&&(await O.calculateCost(b,g,e,r),S==null||S.info("[%s][L%d-%d] analyse from %s to %s cost: %j",r.requestId,r.level,r.counter,u.utc().format(),v.utc().format(),{cost:b.cost.total,hire:b.cost.hire,bunker:b.cost.bunker,distance:b.distance,hours:b.totalHrs,cp:`${g.speed}/${g.fo}/${g.dgo}`})),r.counter=r.counter+1;const f=(I=(d=b==null?void 0:b.sample)==null?void 0:d.hours)==null?void 0:I.at(-1);if(f)l.lat=f.lat,l.lng=f.lng,u=w(f.eta),h.push(b),i=i?0:1;else break}return h}static async calculateCost(e,t,n,o={}){var i;if(e){const a=(n.addComm||0)>=1?(n.addComm||0)/100:n.addComm||0,s=Math.round((n.dailyHire||0)*(e.suspend||0)/24*1e3)/1e3,r=Math.round(e.totalHrs/24*(n.dailyHire||0)*(1-a)*1e3)/1e3+s,u=Math.round(e.totalFoCons*(n.priceFO||0)*1e3)/1e3,l=Math.round((e.totalDgoCons+(((i=e.extend)==null?void 0:i.totalDgoConsInECA)||0))*(n.priceDGO||0)*1e3)/1e3;e.cost={total:Math.round((r+u+l)*1e3)/1e3,hire:Math.round(r*1e3)/1e3,suspendHire:s,bunker:Math.round((u+l)*1e3)/1e3,cp:t}}return e}static async calculateECA(e,t,n={}){var r,u,l,h;const o=await E.LaneHelper.intersectInECA((e==null?void 0:e.route)||[]);let i=0,a=0,s=0;(u=(r=e==null?void 0:e.sample)==null?void 0:r.wps)==null||u.forEach(d=>{d.positionTime=w.utc(d.etd||d.eta).unix()});for(const d of o){i+=d.distance;const I=await E.LaneHelper.deadReckoningTime((l=d.waypoints)==null?void 0:l.at(0),e.sample.all||e.sample.wps),v=await E.LaneHelper.deadReckoningTime((h=d.waypoints)==null?void 0:h.at(-1),e.sample.all||e.sample.wps);d.in=I,d.out=v,d.totalHrs=E.LngLatHelper.roundPrecision((v.positionTime-I.positionTime)/3600,3),d.totalDgoCons=E.LngLatHelper.roundPrecision(t.fo/24*d.totalHrs,3),a+=d.totalHrs,s+=d.totalDgoCons}return i=E.LngLatHelper.roundPrecision(i,3),a=E.LngLatHelper.roundPrecision(a,3),s=E.LngLatHelper.roundPrecision(s,3),{distanceInECA:i,hoursInECA:a,totalDgoConsInECA:s,eca:o}}static async mergeSpeeds(e,t={}){var f,c;const n={hours:[],wps:[],days:[],all:[]},o=e.reduce((m,y)=>m+y.distance,0),i=e.reduce((m,y)=>{var F;return m+(((F=y.extend)==null?void 0:F.distanceInECA)||0)},0),a=e.reduce((m,y)=>m+y.totalHrs,0),s=e.reduce((m,y)=>{var F;return m+(((F=y.extend)==null?void 0:F.hoursInECA)||0)},0),r=e.reduce((m,y)=>{var F;return m+(((F=y.extend)==null?void 0:F.totalDgoConsInECA)||0)},0),u=e.reduce((m,y)=>m+y.wxFactor*y.totalHrs/a,0),l=e.reduce((m,y)=>m+y.cFactor*y.totalHrs/a,0),h=e.reduce((m,y)=>m+y.totalFoCons,0),d=e.reduce((m,y)=>m+y.totalDgoCons,0),I=e.reduce((m,y)=>m+y.cost.total,0),v=e.reduce((m,y)=>m+y.cost.hire,0),T=e.reduce((m,y)=>m+y.cost.bunker,0),k=[],g=[];let b;for(const m of e){g.push(...((f=m.extend)==null?void 0:f.eca)||[]);const y=m.sample.hours,F=m.sample.all,p=m.sample.wps,L=m.sample.days,H=y.at(0);b&&(H.distanceFromPrevious=b.distanceFromPrevious,H.distanceFromStart=b.distanceFromStart,y.forEach((C,R)=>{R&&(C.distanceFromStart=C.distanceFromStart+b.distanceFromStart)}),F.at(0).distanceFromPrevious=b.distanceFromPrevious,F.at(0).distanceFromStart=b.distanceFromStart,F.forEach((C,R)=>{R&&(C.distanceFromStart=C.distanceFromStart+b.distanceFromStart)}),p.at(0).distanceFromPrevious=b.distanceFromPrevious,p.at(0).distanceFromStart=b.distanceFromStart,p.forEach((C,R)=>{R&&(C.distanceFromStart=C.distanceFromStart+b.distanceFromStart)}),L.at(0).distanceFromPrevious=b.distanceFromPrevious,L.at(0).distanceFromStart=b.distanceFromStart,L.forEach((C,R)=>{R&&(C.distanceFromStart=C.distanceFromStart+b.distanceFromStart)})),H.cp=m.cost.cp;const N=[m.etd,m.eta],W=k.findIndex(C=>C.id===H.cp.id);W===-1?(H.cp.segment=[N],k.push(H.cp)):k[W].segment.push(N),y.forEach(C=>{var q;((q=n.hours)==null?void 0:q.findIndex(z=>z.eta===C.eta))===-1&&n.hours.push(C)}),F.forEach(C=>{var q;((q=n.all)==null?void 0:q.findIndex(z=>z.eta===C.eta))===-1&&n.all.push(C)}),p.forEach(C=>{var q;((q=n.wps)==null?void 0:q.findIndex(z=>z.eta===C.eta))===-1&&n.wps.push(C)}),L.forEach(C=>{var q;((q=n==null?void 0:n.days)==null?void 0:q.findIndex(z=>z.eta===C.eta))===-1&&n.days.push(C)});const B=(c=n.wps)==null?void 0:c.findIndex(C=>C.eta===H.eta);B===-1?n.wps.push(H):n.wps[B]=H,b=y.at(-1)}return n.wps.sort((m,y)=>w(m.etd).unix()-w(y.etd).unix()),n.wps.forEach((m,y)=>{const F=n.wps[y-1];if(F){const p=m.distanceFromStart-(F.distanceFromStart||0),L=w(m.eta||m.etd).diff(w(F.etd||F.eta),"hour",!0),H=Math.round(p/L*100)/100;m.avgSpd=H;const N=E.LaneHelper.calculateBearing(F,m);F.bearing=N}}),{sample:n,etd:e.at(0).etd,eta:e.at(-1).eta,from:e.at(0).from,to:e.at(-1).to,v0:e.at(0).v0,label:"Combined",distance:Math.round(o*1e3)/1e3,totalHrs:Math.round(a*1e3)/1e3,avgSpeed:Math.round(o/a*1e3)/1e3,wxFactor:Math.round(u*1e3)/1e3,cFactor:Math.round(l*1e3)/1e3,totalFoCons:Math.round(h*1e3)/1e3,totalDgoCons:Math.round(d*1e3)/1e3,cost:{total:Math.round(I*1e3)/1e3,hire:Math.round(v*1e3)/1e3,bunker:Math.round(T*1e3)/1e3},extend:{cps:k,eca:g,distanceInECA:Math.round(i*1e3)/1e3,hoursInECA:Math.round(s*1e3)/1e3,totalDgoConsInECA:Math.round(r*1e3)/1e3,speeds:e}}}}P.AISImpl=G,P.AlertHelper=ht,P.AlertLevel=lt,P.HifleetImpl=vt,P.LoadCondition=mt,P.MyShipImpl=gt,P.MyVesselImpl=Mt,P.ShipxyImpl=bt,P.SpeedHelper=O,P.SpeedLabel=yt,P.VesselTag=ft,P.alertHelper=wt,Object.defineProperty(P,Symbol.toStringTag,{value:"Module"})});
|
|
1
|
+
(function(P,x){typeof exports=="object"&&typeof module<"u"?x(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"],x):(P=typeof globalThis<"u"?globalThis:P||self,x(P["idm-plugin-vessel"]={},P.got,P["@log4js-node/log4js-api"],P.moment,P["@idm-plugin/geo2"],P["@idm-plugin/meteo2"],P["@idm-plugin/meteo"]))})(this,function(P,x,K,w,E,Mt,it){"use strict";var St=Object.defineProperty;var Ct=(P,x,K)=>x in P?St(P,x,{enumerable:!0,configurable:!0,writable:!0,value:K}):P[x]=K;var U=(P,x,K)=>(Ct(P,typeof x!="symbol"?x+"":x,K),K);let p;try{p=K.getLogger("vessel")}catch{}finally{}class G{parseStatus(e){let t,n;switch(e){case 0:t="在航(主机推动)",n="Underway Using Engine";break;case 1:t="锚泊",n="Anchored";break;case 2:t="失控",n="Not under command";break;case 3:t="操纵受限",n="Limited airworthiness";break;case 4:t="吃水受限",n="Limited by ship's draft";break;case 5:t="靠泊",n="Mooring";break;case 6:t="搁浅",n="Stranded";break;case 7:t="捕捞作业",n="Engaged in fishing";break;case 8:t="靠帆船提供动力",n="Sailing";break;default:t="未定义",n="Undefined"}return{labelCn:t,labelEn:n}}}class pt extends G{constructor(t,n){super();U(this,"clientId");U(this,"clientSecret");U(this,"token");this.clientId=t,this.clientSecret=n}async authToken(t={}){const n="https://svc.data.myvessel.cn/ada/oauth/token",o={searchParams:{client_id:this.clientId,client_secret:this.clientSecret,grant_type:"client_credentials"}},i=await x.post(n,o).json();p==null||p.info("[%s] fetch access token from: %s - %j",t.requestId,n,i),i.error||(this.token={accessToken:i.access_token,tokenType:i.token_type,expiresIn:i.expires_in,scope:i.scope,jti:i.jti,issuedAt:w().utc().format()})}async checkToken(t={}){var n;return(!this.token||w().diff(w(this.token.issuedAt),"seconds")>(((n=this.token)==null?void 0:n.expiresIn)||0)-300)&&await this.authToken(t),this.token}async suggest(t,n={}){var a,r;await this.checkToken(n);const o="https://market.myvessel.cn/sdc/v1/mkt/vessels/fuzzy",i={headers:{Authorization:`${(a=this.token)==null?void 0:a.tokenType} ${(r=this.token)==null?void 0:r.accessToken}`},json:{kw:t,recordNum:n.ps||10}};p==null||p.info("[%s] fetch suggest vessels from: %s - %j",n.requestId,o,i);const s=await x.post(o,i).json();return s.status!==200?(p==null||p.warn("[%s] fetch suggest vessels failed: %j",n.requestId,{message:s.message,status:s.status,code:s.code}),[]):(s.data||[]).map(l=>({mmsi:l.mmsi,name:l.nameEn,nameCn:l.nameCn,imo:Number.isNaN(l.imo)?null:Number(l.imo),callSign:l.callsign,type:l.vesselTypeNameEn,flagName:l.flagCtry,vendor:"myvessel",raw:l}))}async search(t,n={}){var u,l;await this.checkToken(n);const o=/^\d{7}$/.test(t.toString()),i=o?"https://market.myvessel.cn/sdc/v1/mkt/vessels/detail/imo":"https://market.myvessel.cn/sdc/v1/mkt/vessels/detail/mmsi",s=o?{imo:t}:{mmsi:t},a={headers:{Authorization:`${(u=this.token)==null?void 0:u.tokenType} ${(l=this.token)==null?void 0:l.accessToken}`},searchParams:s};p==null||p.info("[%s] fetch vessel from: %s - %j",n.requestId,i,a);const r=await x.get(i,a).json();if(r.status!==200)return p==null||p.warn("[%s] fetch suggest vessels failed: %j",n.requestId,{message:r.message,status:r.status,code:r.code}),{};{const h=r.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,n={}){var a,r;await this.checkToken(n);const o="https://svc.data.myvessel.cn/sdc/v1/ship/info/batch",i={headers:{Authorization:`${(a=this.token)==null?void 0:a.tokenType} ${(r=this.token)==null?void 0:r.accessToken}`},json:{mmsiList:typeof t=="number"?[t]:t}};p==null||p.info("[%s] fetch vessel archive from: %s - %j",n.requestId,o,i);const s=await x.post(o,i).json();return s.status!==200?(p==null||p.warn("[%s] fetch vessel archive failed: %j",n.requestId,{message:s.message,status:s.status,code:s.code}),{}):s.data}async realTimePosition(t,n={}){var r,u;await this.checkToken(n);const o="https://svc.data.myvessel.cn/sdc/v1/vessels/status/location/unit",i={headers:{Authorization:`${(r=this.token)==null?void 0:r.tokenType} ${(u=this.token)==null?void 0:u.accessToken}`},searchParams:{mmsi:t}};p==null||p.info("[%s] fetch realtime position from: %s - %j",n.requestId,o,i);const s=await x.get(o,i).json();if(s.code)return p==null||p.warn("[%s] fetch realtime position failed: %j",n.requestId,{message:s.message,status:s.status,code:s.code}),s;const a=s.data;for(const l in a)!isNaN(a[l])&&Number(a[l])!==1/0&&(a[l]=Number(a[l]));if(a){const l=w(`${a.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return{mmsi:a.mmsi,name:a.vesselName||a.aisVesselName,imo:a.imo,callSign:a.callsign||a.aisCallSign,lat:a.lat,lng:a.lon,length:a.length,width:a.width,draught:a.currDraught,sog:a.sog,cog:a.cog,hdg:a.hdg,rot:a.rot,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(a.eta)?w.utc(a.eta).format():void 0,destination:a.dest,positionTime:l.unix(),status:a.status,labelCn:a.statusNameCn,labelEn:a.statusNameEn,vesselType:a.vesselTypeNameEn,flag:a.flagCtryNameEn,clasz:a.classSociety,build:a.buildYear,dwt:a.dwt,grt:a.grt,net:a.net,method:"position",vendor:"myVessel",utc:l.utc().format()}}else return{}}async calculateRoute(t,n,o,i,s,a={}){var I,b,T;const r=w();await this.checkToken(a);const u="https://market.myvessel.cn/sdc/v1/mkt/routes/plan",l={maxDraught:a.draught||10,useAIModel:a.useAIModel??!0,withECA:a.withECA||!1,withSpecialRegion:a.withSpecial||!1};t.code&&(l.startPortCode=t.code),t.lng!==void 0&&t.lat!==void 0&&(l.startPoint={lon:t.lng,lat:t.lat}),n.code&&(l.endPortCode=n.code),n.lng!==void 0&&n.lat!==void 0&&(l.endPoint={lon:n.lng,lat:n.lat}),o!=null&&o.length&&(l.crossMonthList=o),i!=null&&i.length&&(l.excludeNodes=i),s!=null&&s.length&&(l.excludeSeaAreas=s);const h={headers:{Authorization:`${(I=this.token)==null?void 0:I.tokenType} ${(b=this.token)==null?void 0:b.accessToken}`},json:l};p==null||p.info("[%s] fetch route from: %s - %j",a.requestId,u,h);const c=await x.post(u,h).json();if(c.status!==200)return p==null||p.warn("[%s] fetch route failed: %j",a.requestId,{message:c.message,status:c.status,code:c.code}),{};{const k={status:"Success",nodes:[],seas:[],regions:[],waypoints:[],route:[],distance:0,memo:""},{nodes:g,seas:v,tracks:f,specialRegions:d,ecaLength:m}=c.data;k.nodes=g==null?void 0:g.map(M=>({code:M.nodeCode,nameEn:M.nameEn,nameCn:M.nameCn,center:{lat:Math.round(M.lat*1e6)/1e6,lng:Math.round(M.lon*1e6)/1e6},start:{lat:Math.round(M.startLat*1e6)/1e6,lng:Math.round(M.startLon*1e6)/1e6},end:{lat:Math.round(M.endLat*1e6)/1e6,lng:Math.round(M.endLat*1e6)/1e6},isKey:M.isKeyNode,isHub:M.isHubNode})),k.seas=v==null?void 0:v.map(M=>({code:M.mrgidSea,nameEn:M.nameEn,nameCn:M.nameCn,center:{lat:Math.round(M.centerLat*1e6)/1e6,lng:Math.round(M.centerLon*1e6)/1e6},min:{lat:Math.round(M.minLat*1e6)/1e6,lng:Math.round(M.minLon*1e6)/1e6},max:{lat:Math.round(M.maxLat*1e6)/1e6,lng:Math.round(M.maxLon*1e6)/1e6},level:M.mapLevel})),d==null||d.map(M=>{M.regionLength&&k.regions.push({type:M.regionType,distance:M.regionLength,rows:M.regions.map(L=>({code:L.regionCode,nameCn:L.nameCn,nameEn:L.nameEn,type:L.regionType,distance:L.length}))})}),k.waypoints=f==null?void 0:f.map(M=>({lat:Math.round(M.lat*1e5)/1e5,lng:Math.round(M.lon*1e5)/1e5})),(T=k.waypoints)!=null&&T.length&&(k.waypoints=E.LaneHelper.simplifyCoordinates(k.waypoints),k.route=E.LaneHelper.divideAccordingToLng(k.waypoints),k.distance=E.LaneHelper.calculateRouteDistance(k.route),k.distanceInECA=m);const F=w().diff(r,"second");return k.memo=`time cost: ${F}s`,p.info("[%s] calculate route cost: %d seconds",a.requestId,F),k}}async trajectory(t,n,o,i,s=!0,a={}){await this.checkToken(a);const r=await this.realTimePosition(t,a),u=w(n),l=w(o),h=[];for(;l.diff(u,"day",!0)>30;)await this.trajectoryIn30Day(t,u,u.clone().add(30,"day"),r,i,h,a),u.add(30,"day");return await this.trajectoryIn30Day(t,u,l,r,i,h,a),h}async trajectoryIn30Day(t,n,o,i,s,a,r={}){var b,T,k,g,v;const u="https://svc.data.myvessel.cn/sdc/v1/vessels/status/track",l={headers:{Authorization:`${(b=this.token)==null?void 0:b.tokenType} ${(T=this.token)==null?void 0:T.accessToken}`},json:{mmsi:t,startTime:n.utcOffset(8).format("YYYY-MM-DD HH:mm:ss"),endTime:o.utcOffset(8).format("YYYY-MM-DD HH:mm:ss")}};p==null||p.info("[%s] fetch trajectory from: %s - %j",r.requestId,u,l);const h=await x.post(u,l).json();if(h.code)return p==null||p.warn("[%s] fetch trajectory failed: %j",r.requestId,u,{message:h.message,status:h.status,code:h.code}),h;let c=-1;const I=w(`${(g=(k=h.data)==null?void 0:k[0])==null?void 0:g.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return(v=h.data)==null||v.forEach(f=>{for(const H in f)!isNaN(f[H])&&Number(f[H])!==1/0&&(f[H]=Number(f[H]));const d=w(`${f.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00"),m=f.status,{labelCn:y,labelEn:F}=this.parseStatus(m),M={mmsi:f.mmsi,imo:i==null?void 0:i.imo,lat:f.lat,lng:f.lon,sog:f.sog,cog:f.cog,hdg:f.hdg,draught:f.draught,status:m,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(f.eta)?w(`${f.eta} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00").utc().format():void 0,destination:f.dest,positionTime:d.unix(),labelCn:y,labelEn:F,method:"trajectory",vendor:"myVessel",utc:d.utc().format()},L=Math.floor(d.diff(I,"minute",!0)/(s||1));L!==c&&(c=L,a.push(M))}),a}}class bt extends G{constructor(t){super();U(this,"token");this.token=t}async realTimePosition(t,n={}){const o="https://api.hifleet.com/position/position/get/token",i={searchParams:{mmsi:t,usertoken:this.token}},s=await x.post(o,i).json();p==null||p.info("[%s] fetch realtime position from: %s - %j",n.requestId,o,i);const a=s==null?void 0:s.list;if(!a)return p==null||p.warn("[%s] fetch realtime position failed: %j",n.requestId,o,s),s;for(const I in a)!isNaN(a[I])&&Number(a[I])!==1/0&&(a[I]=Number(a[I]));a.status=a.sp>3?0:1;const r=a.status,{labelCn:u,labelEn:l}=this.parseStatus(r),h=w(`${a.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return{mmsi:a.m,name:a.n,imo:a.imonumber,callSign:a.callsign,lat:Math.round(a.la/60*1e5)/1e5,lng:Math.round(a.lo/60*1e5)/1e5,length:a.l,width:a.w,draught:a.draught,sog:a.sp,cog:a.co,hdg:a.h,rot:isNaN(a.rot)?0:a.rot,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(a.eta)?w.utc(a.eta).format():void 0,destination:a.destination,vesselType:a.type,dwt:a.dwt,build:a.buildyear,flag:a.fn,positionTime:h.unix(),utc:h.utc().format(),status:r,labelCn:u,labelEn:l,method:"position",vendor:"hifleet"}}async search(t,n={}){let o="https://www.hifleet.com/hifleetapi/searchVesselOL.do";const i={searchParams:{keyword:t},headers:{Referer:"https://www.hifleet.com",Origin:"https://www.hifleet.com",Host:"www.hifleet.com"}};let s=await x.post(o,i).json();p==null||p.info("[%s] fetch vessel props from: %s - %j",n.requestId,o,i),s instanceof Array&&(s=s[0]);for(const r in s)!isNaN(s[r])&&Number(s[r])!==1/0&&(s[r]=Number(s[r]));const a={mmsi:s.m,name:s.n,imo:s.i,callSign:s.c,length:s.l,breadth:s.b,draught:s.dr,type:s.t};return o="https://www.hifleet.com/hifleetapi/sameShipSearch.do",s=await x.post(o,i).json(),p==null||p.info("[%s] search vessel dead weight from: %s - %j",n.requestId,o,i),s instanceof Array&&(s=s[0]),s&&(a.deadweight=Number(s.dwt)),a}async suggest(t,n={}){const o="https://www.hifleet.com/hifleetapi/getShipSuggest.do",i={searchParams:{q:t},headers:{Referer:"https://www.hifleet.com",Origin:"https://www.hifleet.com",Host:"www.hifleet.com"}},s=await x.post(o,i).json();p==null||p.info("[%s] suggest vessel props from: %s - %j",n.requestId,o,i);const a=[];for(const r of s)a.push({mmsi:!r.mmsi||isNaN(r.mmsi)?null:Number(r.mmsi),name:r.name,callSign:r.callsign,imo:!r.imo||isNaN(r.imo)?null:Number(r.imo),score:r._score});return a.sort((r,u)=>u.score-r.score),a}async trajectory(t,n,o,i,s=!0,a={}){var f,d,m;const r=await this.realTimePosition(t,a);let u=w(n);const l=w(o),h=w();if(s){let y=l.diff(u,"d",!0);y<0?u=l.clone().subtract(40,"d"):y<30?u.subtract(10,"d"):y<60?u.subtract(5,"d"):u=l.clone().subtract(80,"d"),y=h.diff(l,"d",!0),l.add(y>10?240:y*24,"h")}const c={searchParams:{endtime:l.utcOffset("+8:00").format("YYYY-MM-DD HH:mm:ss"),starttime:u.utcOffset("+8:00").format("YYYY-MM-DD HH:mm:ss"),mmsi:t,usertoken:this.token}},I="https://api.hifleet.com/position/trajectory/nocompressed/withstatic/token",b=await x.get(I,c).json();p==null||p.info("[%s] fetch trajectory from: %s - %j",a.requestId,I,c);let T;b&&(T=((d=(f=b.ships)==null?void 0:f.offors)==null?void 0:d.ship)||[],T.length||p==null||p.warn("[%s] fetch trajectory failed: %j",a.requestId,b));const k=[];let g=-1;const v=w(`${(m=T==null?void 0:T[0])==null?void 0:m.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");for(const y of T){for(const W in y)!isNaN(y[W])&&Number(y[W])!==1/0&&(y[W]=Number(y[W]));const F=w(`${y.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");y.status=y.sp>4?0:1;const{labelEn:M,labelCn:L}=this.parseStatus(y.status),H={mmsi:y.m,name:y.n,imo:r==null?void 0:r.imo,lat:y.la,lng:y.lo,draught:y.draught,sog:y.sp,cog:y.co,hdg:y.hdg,positionTime:F.unix(),utc:F.utc().format(),status:y.status,labelCn:L,labelEn:M,method:"trajectory",vendor:"hifleet"},N=Math.floor(F.diff(v,"minute",!0)/(i||1));N!==g&&(g=N,k.push(H))}return k}}class vt extends G{constructor(t){super();U(this,"token");this.token=t}async realTimePosition(t,n={}){const o={searchParams:{id:t,k:this.token,enc:1}},i="https://api.shipxy.com/apicall/GetSingleShip",s=await x.get(i,o).json();if(p==null||p.info("[%s] fetch realtime position from: %s - %j",n.requestId,i,o),(s==null?void 0:s.status)!==0)return s;const a=s.data[0];for(const c in a)!isNaN(a[c])&&Number(a[c])!==1/0&&(a[c]=Number(a[c]));const{labelCn:r,labelEn:u}=await this.parseStatus(a.navistat),l=w.unix(a.lasttime);return{mmsi:a.ShipID,name:a.name,imo:a.imo,callSign:a.callsign,lat:Math.round(a.lat/1e6*1e5)/1e5,lng:Math.round(a.lon/1e6*1e5)/1e5,length:Math.round(a.length/10*100)/100,width:Math.round(a.width/10*100)/100,draught:Math.round(a.draught/1e3*100)/100,sog:Math.round(a.sog*3600/1e3/1852*100)/100,cog:Math.round(a.cog/100*100)/100,hdg:Math.round(a.hdg/100*100)/100,rot:Math.round(a.rot/100*100)/100,positionTime:a.lasttime,utc:l.utc().format(),status:a.navistat,labelEn:u,labelCn:r,method:"position",vendor:"shipxy"}}async trajectory(t,n,o,i,s=!0,a={}){var v;const r=await this.realTimePosition(t,a),u=w(n),l=w(o),h="https://api.shipxy.com/apicall/GetShipTrack",c={searchParams:{id:t,k:this.token,enc:1,cut:0,btm:u.unix(),etm:l.unix()}},I=await x.get(h,c).json();if(p==null||p.info("[%s] fetch trajectory from: %s - %j",a.requestId,h,c),(I==null?void 0:I.status)!==0)return I;const b=I==null?void 0:I.points,T=[],k=w.unix((v=b[0])==null?void 0:v.utc);let g=-1;for(const f of b){const d=w.unix(f.utc),m={imo:r==null?void 0:r.imo,mmsi:t,sog:Math.round(f.sog*3600/1e3/1852*100)/100,cog:Math.round(f.cog/100*100)/100,lat:Math.round(f.lat/1e6*1e5)/1e5,lng:Math.round(f.lon/1e6*1e5)/1e5,positionTime:d.unix(),utc:d.utc().format(),method:"trajectory",vendor:"shipxy"},y=Math.floor(d.diff(k,"minute",!0)/(i||1));y!==g&&(g=y,T.push(m))}return T}}class gt extends G{constructor(t){super();U(this,"token");this.token=t}async getShipId(t,n={}){const o={headers:{appKey:this.token},json:{mmsiList:t}},i="https://api3.myships.com/sp/ships/getShipIdByMMSI",s=await x.post(i,o).json();return p==null||p.info("[%s] fetch ship id from: %s - %j",n.requestId,i,o),s.code!=="0"?s:s.data[0].shipId}async getShipInfo(t,n={}){const o={headers:{appKey:this.token},json:{shipId:t}},i="https://api3.myships.com/sp/ships/aissta",s=await x.post(i,o).json();if(p==null||p.info("[%s] fetch ship info from: %s - %j",n.requestId,i,o),s.code!=="0")return s;const a=s.data;let r=a.imo;return t==="407170"&&(r="9198379",p==null||p.warn("[%s] ship(%s) imo error: %s, should be %s",n.requestId,t,a.imo,r)),{mmsi:a.mmsi,name:a.shipnameEn,imo:r,callSign:a.callSign,length:a.length,width:a.breadth,draught:(a.draught||100)/10}}async realTimePosition(t,n={}){const o=await this.getShipId(t,n),i=await this.getShipInfo(o,n),s={headers:{appKey:this.token},json:{shipId:o}},a="https://api3.myships.com/sp/ships/position/latest",r=await x.post(a,s).json();p==null||p.info("[%s] fetch realtime position from: %s - %j",n.requestId,a,s);const u=r.data[0];for(const b in u)!isNaN(u[b])&&Number(u[b])!==1/0&&(u[b]=Number(u[b]));const{labelCn:l,labelEn:h}=await this.parseStatus(u.aisNavStatus),c=w.unix(u.posTime);return{...i,mmsi:t,lat:Math.round(u.lat/1e4/60*1e5)/1e5,lng:Math.round(u.lon/1e4/60*1e5)/1e5,sog:Math.round(u.sog/10*100)/100,cog:Math.round(u.cog/10*100)/100,hdg:Math.round(u.heading*100)/100,rot:Math.round(u.rot*100)/100,positionTime:u.posTime,utc:c.utc().format(),status:u.aisNavStatus,labelEn:h,labelCn:l,method:"position",vendor:"myship"}}async trajectory(t,n,o,i,s=!0,a={}){const r=w(n),u=w(o),l=await this.getShipId(t),h=await this.getShipInfo(l),c=[];for(;u.diff(r,"day",!0)>30;)await this.trajectoryIn30Day(l,r.unix(),r.add(30,"day").unix(),h,t,i,c);return await this.trajectoryIn30Day(l,r.unix(),u.unix(),h,t,i,c),c}async trajectoryIn30Day(t,n,o,i,s,a,r,u={}){var k;const l={headers:{appKey:this.token},json:{shipId:t,startTime:n,endTime:o}},h="https://api3.myships.com/sp/ships/position/history",c=await x.post(h,l).json();if(p==null||p.info("[%s] fetch trajectory from: %s - %j",u.requestId,h,l),c.code!=="0")return p==null||p.warn("[%s] invoke myship trajectory failed: %j",u.requestId,c),c;const I=c.data;for(const g in I)!isNaN(I[g])&&Number(I[g])!==1/0&&(I[g]=Number(I[g]));const b=w.unix((k=I[0])==null?void 0:k.posTime);let T=-1;for(const g of I){const v=w.unix(g.posTime),f={imo:i==null?void 0:i.imo,mmsi:s,lat:Math.round(g.lat/1e4/60*1e5)/1e5,lng:Math.round(g.lon/1e4/60*1e5)/1e5,sog:Math.round(g.sog/10*100)/100,cog:Math.round(g.cog/10*100)/100,hdg:Math.round(g.heading*100)/100,rot:Math.round(g.rot*100)/100,positionTime:v.unix(),utc:v.utc().format(),method:"trajectory",vendor:"myship"},d=Math.floor(v.diff(b,"minute",!0)/(a||1));d!==T&&(T=d,r.push(f))}return r}}let _;try{_=K.getLogger("vessel")}catch{}finally{}var lt=(A=>(A.NOTICE="NOTICE",A.WARN="WARN",A.HEAVY="HEAVY",A.SEVERE="SEVERE",A.ERROR="ERROR",A.FATAL="FATAL",A))(lt||{});class ht{parsePrinciple(e,t={}){var a,r,u;_==null||_.debug("[%s] parse rule: %s",t.requestId,e);const n=new RegExp("(?<=\\[)(.+)(?=])","g"),o=e.match(n)?(a=e.match(n))==null?void 0:a[0]:void 0,i=o==null?void 0:o.split(";");if(!i)return;const s={};for(let l=0;l<(i==null?void 0:i.length);l++){const h=(u=(r=i[l].match(n))==null?void 0:r[0])==null?void 0:u.split("],");if(l===0&&!h)s.scope=i[0];else if(h)for(let c=0,I=h.length;c<I;c++){const b=this.parseRule(h[c]);b&&(s[b.level]?b.key?s[b.level][b==null?void 0:b.key]=b:s[b.level]=b:b.key?s[b.level]={[b==null?void 0:b.key]:b}:s[b.level]=b)}}return s}parseRule(e,t={}){var s;_==null||_.debug("[%s] parse rule: %s",t.requestId,e),e=e.startsWith("[")?e:`[${e}`,e=e.endsWith("]")?e:`${e}]`;const n=new RegExp("(?<=\\[)(.+?)(?=])","g"),o=(s=e==null?void 0:e.match(n))==null?void 0:s[0],i=o==null?void 0:o.split(",");if(i){let a=i[3]==="Number.MAX_VALUE"?100:Number(i[3]);return a=isNaN(a)?1:a,{operator:i[0],number:Number.isNaN(Number(i[1]))?i[1]:Number(i[1]),level:i[2],time:a,key:i[4]}}}checkWeather(e,t,n={}){var b,T,k,g,v,f,d,m,y,F,M,L,H,N,W;let o=0,i=0,s=0,a=0;const r=Math.round(((T=(b=t==null?void 0:t.SEVERE)==null?void 0:b.sigWave)==null?void 0:T.number)*1.6*100)/100,u=(g=(k=t==null?void 0:t.SEVERE)==null?void 0:k.sigWave)==null?void 0:g.number,l=(f=(v=t==null?void 0:t.HEAVY)==null?void 0:v.sigWave)==null?void 0:f.number,h=Math.round((((m=(d=t==null?void 0:t.SEVERE)==null?void 0:d.wind)==null?void 0:m.number)+2)*100)/100,c=(F=(y=t==null?void 0:t.SEVERE)==null?void 0:y.wind)==null?void 0:F.number,I=(L=(M=t==null?void 0:t.HEAVY)==null?void 0:M.wind)==null?void 0:L.number;for(let B=0;B<(e==null?void 0:e.length);B++){const C=e[B],R=(N=(H=C==null?void 0:C.meteo)==null?void 0:H.wave)==null?void 0:N.sig,q=(W=C==null?void 0:C.meteo)==null?void 0:W.wind,z=B?w(C.eta).diff(w(e[B-1].eta),"hour",!0):0;a=z>a?z:a,_==null||_.debug("[%s] check sig.wave: %j",n.requestId,{...R,dgThd4Wv:r,svThd4Wv:u,hvThd4Wv:l}),(R==null?void 0:R.height)>=r?C.isDangerous=!0:(R==null?void 0:R.height)>=u?C.isSevere=!0:(R==null?void 0:R.height)>=l&&(C.isHeavy=!0),_==null||_.debug("[%s] check wind: %j",n.requestId,{...q,dgThd4Wd:h,svThd4Wd:c,hvThd4Wd:I}),(q==null?void 0:q.scale)>=h?(C.isDangerous=!0,delete C.isSevere,delete C.isHeavy):(q==null?void 0:q.scale)>c?(C.isDangerous||(C.isSevere=!0),delete C.isHeavy):(q==null?void 0:q.scale)===I&&!C.isDangerous&&!C.isSevere&&(C.isHeavy=!0),o+=C.isDangerous?z:0,i+=C.isSevere?z:0,s+=C.isHeavy?z:0}return o=Math.round(o*100)/100,i=Math.round(i*100)/100,s=Math.round(s*100)/100,a=Math.round(a),{sample:e,dangerous:o,severe:i,heavy:s,step:a<3?3:a,wind:{dgThd4Wd:h,svThd4Wd:c,hvThd4Wd:I},sig:{dgThd4Wv:r,svThd4Wv:u,hvThd4Wv:l}}}}const wt=new ht;let S;try{S=K.getLogger("vessel")}catch{}finally{}const It=new Mt.MeteoHelper2("",!0);var ft=(A=>(A.common="common",A.container="container",A.tugs="tugs",A))(ft||{}),mt=(A=>(A.Ballast="Ballast",A.Laden="Laden",A))(mt||{}),yt=(A=>(A.Cp="CP",A.Perf="Basis",A.Instruct="Other",A))(yt||{});class O{static blockCoefficient(e,t,n,o){let i=Math.round(e/(t*n*o)*100)/100;i=i<.55?.55:i>.85?.85:i;const s=[.55,.6,.65,.7,.75,.8,.85],a=s.map(r=>Math.abs(r-i));return s[a.indexOf(Math.min(...a))]}static froudeNumber(e,t,n=9.8){let o=Math.round(Math.sqrt(e*e/(n*t))*100)/100;return o=o<.05?.05:o>.3?.3:o,o}static amendFactor(e,t,n){const o={.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 s={.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]}[e];return n==="Laden"&&(s=o[e]),s[0]+s[1]*t+s[2]*Math.pow(t,2)}static directionFactor(e,t=0){let n;return e>30&&e<=60?n=(1.7-.03*Math.pow(t-4,2))/2:e>60&&e<=150?n=(.9-.06*Math.pow(t-6,2))/2:e>150&&e<=180?n=(.4-.03*Math.pow(t-8,2))/2:n=1,Math.round(n*1e5)/1e5}static vesselTagFactor(e,t,n,o){let i;return n==="container"?i=.7*o/2+Math.pow(o,3)/(22*Math.pow(e,2/3)):t==="Ballast"?i=.7*o/2+Math.pow(o,3)/(2.7*Math.pow(e,2/3)):i=.5*o/2+Math.pow(o,3)/(2.7*Math.pow(e,2/3)),i}static waveHeightFactor(e,t,n=10,o={}){e=e<3?e*.7:e,e=e<0?.2:e,e=e>6?e-.9*(e-6):e,e=e>9?9:e;const i=Math.max(n>10?n-10:2.8);let s;return t>30&&t<=60?s=-.6:t>60&&t<=90?s=-.5:t>90&&t<=120?s=e<i?.2:-.3:t>120&&t<=150?s=e<i?.25:-.2:t>150&&t<=180?s=e<i?.3:-.1:s=-.7,S==null||S.info("[%s] calculate wave height factor with ht(%d), beta(%d), draught(%d) and factor(%d)",o.requestId,e,t,n,s),Math.round(s*(.144*Math.pow(e,2)+.378*e)*1e4)/1e4}static assembleProperties(e,t,n,o){var c;const i=e.lbp??e.length??e.lengthOverall??198.9642,s=e.draught??8,a=e.breadthMoulded??e.breadth??e.breadthExtreme??32.4572,r=e.deadweight??67035.7773,u=((c=e==null?void 0:e.type)==null?void 0:c.toLowerCase())||"common";return{tag:u.indexOf("container")>-1?"container":u.indexOf("tugs")>-1?"tugs":"common",lbp:i,loadCondition:t,draught:s,breadthMoulded:a,displacement:Math.round((r/1.025+s*a*i*.7)*1e4)/1e4,speed:Math.round((n??14.1382)*1852/3600*1e4)/1e4,bearing:o||90}}static async speedLoseAt(e,t,n,o="",i=2,s=!0,a=!1,r={}){let u;if(t.velocity&&a&&(e.speed=E.LngLatHelper.roundPrecision(t.velocity*1852/3600,6)),s){let l;try{o=(o==null?void 0:o.toUpperCase())==="CMEMS"?"ECMWF":o,o=(o==null?void 0:o.toUpperCase())==="METEO2"?"best_match":o;const{weatherModels:k,marineModels:g}=await it.Meteo2Assist.autoPickMeteoModel(o),v=n.utc().format(),f=await It.spotForecast(t.lat,t.lng,v,!1,!1,!0,{...r,pastDays:1,forecastDays:2,weatherModels:k,marineModels:g}),[d]=it.Meteo2Assist.pickHourly(f,v);l=it.Meteo2Assist.toLegacy(d)}catch(k){S.warn("[%s] meteo2 spot(%j) forecast failed: %s",r.requestId,{...t,eta:n.utc().format(),source:o},k)}let h=O.currentFactor(e.bearing,l==null?void 0:l.current,i,r),c=O.weatherFactor(e,l,h,r);const I=e.speed*1.943844;I+h+c<=0&&(S.warn("[%s] v0(%d) is less then factor(%d) = wxFactor(%d) + cFactor(%d), scale factor with 0.6",r.requestId,I,c+h,c,h),h=Math.round(h*.6*1e3)/1e3,c=Math.round(c*.6*1e3)/1e3);const b=c<=(r.minV0Factor||-1)?Math.max(r.maxV0Factor||-2.5,-1*c*(c/1.2)):0;S==null||S.info("[%s] calculate speed lose with v0Factor(%d), cFactor(%d) and wxFactor(%d)",r.requestId,b,h,c),c+=b;let T=Math.round((I+h+c)*100)/100;T=T<=0?1:T,u={meteo:{...l},wxFactor:c,v0Factor:b,cFactor:h,speed:t.velocity&&a?t.velocity:T,eta:n.utc().format(),etd:n.utc().format()}}else u={wxFactor:0,v0Factor:0,cFactor:0,speed:t.velocity&&a?t.velocity:Math.round(e.speed*1.943844*100)/100,eta:n.utc().format(),etd:n.utc().format()};return delete t.meteo,delete t.wxFactor,delete t.cFactor,delete t.speed,delete t.etd,{...u,...t}}static async speedLoseInHoursStep(e,t,n,o,i,s,a="",r=!0,u=!1,l={}){t.utc();const h=t.clone().add(14,"days"),c=[],I=[],b=[];let T=0,k=0,g,v;for(let f=0;f<s.length-1;f++){let d=s[f];d.distanceFromStart=Math.round((i+k)*1e3)/1e3;const m=s[f+1];if(e.bearing=E.LaneHelper.calculateBearing(d,m,!m.gcToPrevious),d.bearing=e.bearing,d.suspend&&u){d.eta=d.eta||t.utc().format(),d.elapsed=d.elapsed??0;const M=d.suspend-d.elapsed;if(o-T>M)o=o-T-M,t.add(M,"hour"),d.elapsed=d.suspend;else{const L=o-T;d.elapsed+=L,t.add(L,"hour"),o=0}if(S==null||S.info(`[%s] suspend ${d.elapsed} hours at %j, and remain ${o} hours need to go...`,l.requestId,d),o===0)return d.distanceFromPrevious=k,{etd:t,from:v||d,to:d,next:s.filter(L=>L),wps:c,days:I,all:b}}else d.suspend=0;r=t.isAfter(h)?!1:r,d=await O.speedLoseAt(e,d,t,a,0,r,u,l),b.push(d),v=v||d,d.important&&c.push(d),t.isSameOrAfter(n)&&(I.push(d),n.add(24,"hour"));const y=E.LaneHelper.calculateDistance(d,m,!m.gcToPrevious);let F=Math.round(y/v.speed*1e5)/1e5;if(T+F<o){if(T+=F,t.add(F,"hour"),delete s[f],S==null||S.debug(`[%s] go to %j from %j with ${y}nm, and cost ${F} hours`,l.requestId,{lat:m.lat,lng:m.lng},{lat:v.lat,lng:v.lng,etd:v.etd}),k+=y,s.filter(M=>M).length<=1){g=m,g.eta=t.utc().format(),g.distanceFromPrevious=y,g.distanceFromStart=Math.round((i+k)*1e4)/1e4,c.push(g),b.push(g),delete s[f+1];break}}else{F=o-T,t.add(F,"hour");const M=E.LngLatHelper.roundPrecision(v.speed*F,5);g=E.LaneHelper.calculateCoordinate(d,e.bearing,M,"nauticalmiles",!m.gcToPrevious),g.eta=t.utc().format(),s[f]=g,S==null||S.debug(`[%s] go to %j from %j with ${M}nm, and cost ${F} hours`,l.requestId,{lat:g.lat,lng:g.lng},{lat:d.lat,lng:d.lng,etd:d.etd}),k+=M,g.distanceFromPrevious=Math.round(k*1e4)/1e4,g.distanceFromStart=Math.round((i+k)*1e4)/1e4;break}}return{etd:t,from:v,to:g,next:s.filter(f=>f),wps:c,days:I,all:b}}static currentFactor(e,t,n=0,o={}){const i=E.LaneHelper.includedAngle(e,(t==null?void 0:t.degree)||0)/180*Math.PI;let s;return Math.abs(i)===Math.PI/2&&(s=0),s=((t==null?void 0:t.kts)||0)*Math.cos(i),n&2?s=Math.ceil(s*100)/100:n&1?s=Math.floor(s*100)/100:s=Math.round(s*100)/100,S==null||S.info("[%s] calculate current factor with %j",o.requestId,{beta:i,current:t,factor:s,role:n}),Math.abs(s)>5?0:s}static weatherFactor(e,t,n=0,o={}){var b,T,k,g,v,f,d;S==null||S.info("[%s] calculate weather factor via: %j",o.requestId,{...e,...t});const i=O.blockCoefficient(e.displacement,e.lbp,e.breadthMoulded,e.draught),s=E.LngLatHelper.roundPrecision(n*1852/3600,6),a=O.froudeNumber(e.speed-s,e.lbp),r=O.amendFactor(i,a,e.loadCondition);let u=E.LaneHelper.includedAngle(e.bearing,(b=t==null?void 0:t.wind)==null?void 0:b.degree);const l=O.directionFactor(u,(T=t==null?void 0:t.wind)==null?void 0:T.scale),h=O.vesselTagFactor(e.displacement,e.loadCondition,e.tag,((k=t==null?void 0:t.wind)==null?void 0:k.kts)||10);let c=l*r*h/100*(e.speed-s);c=Math.round(c*1.943844*1e4)/1e4*-1,e.tag==="tugs"&&Math.abs(c)>1&&(c=c/(Math.abs(Math.round(c))+1)),S==null||S.info("[%s] calculate wind wx factor: %d",o.requestId,c),u=E.LaneHelper.includedAngle(e.bearing,(v=(g=t==null?void 0:t.wave)==null?void 0:g.sig)==null?void 0:v.degree);const I=O.waveHeightFactor(((d=(f=t==null?void 0:t.wave)==null?void 0:f.sig)==null?void 0:d.height)??1,u,e.draught,o);return S==null||S.info("[%s] calculate wave wx factor: %d",o.requestId,I),c=Math.abs(c)>Math.abs(I)?c:.7*c+.9*I,S==null||S.info("[%s] calculate finial weather factor: %d (0.7 * wf) + (0.9 * hf)",o.requestId,c),c=Math.abs(c)>4?4*(Math.abs(c)/c)+Math.abs(c)/c*(Math.abs(c)-2)*.1:c,Math.round((c||0)*100)/100}static async reduceDays(e,t=12*60*60){return e=e==null?void 0:e.reduce((n,o)=>(o.positionTime||(o.positionTime=w.utc(o.etd||o.eta).unix()),n.some(i=>Math.floor(i.positionTime/t)===Math.floor(o.positionTime/t))||n.push(o),n),[]),e}static async reduceWPS(e,t=60){return e=e==null?void 0:e.reduce((n,o)=>(n.some(i=>Math.floor(w(i.etd).unix()/t)===Math.floor(w(o.etd).unix()/t))||n.push(o),n),[]),e}static async analyseInstant(e,t,n,o,i,s="",a=0,r=!0,u=!1,l={}){var X,Q,Z,$,tt,et;const h=w().valueOf();e.lng=E.LngLatHelper.convertToStdLng(e.lng);const{route:c,waypoints:I}=i.points,b=E.LaneHelper.calculateSubRoute(e,c);if(((X=b[0])==null?void 0:X.length)<=1)return;const{v0:T,label:k}=e.sog?{v0:e.sog,label:e.label||"Other"}:{v0:o.speed,label:"CP"},g=O.assembleProperties(n,o.loadCondition,T,0),v=I.length?E.LaneHelper.calculateSubWaypoints(e,I):[];v.forEach(D=>D.important=!0);const f={from:{...e},route:b,waypoints:v,v0:T,label:k},d={hours:[],days:[],wps:[],all:[]};a||(E.LaneHelper.calculateRouteDistance(b)/o.speed<=72?a=3:a=6);let m=E.LaneHelper.simplifyRouteToCoordinates(b,v,0),y=0,F=0,M=0,L=0;t=w(t).utc();const H=t.clone();for(;m.length>0;){const D=a-t.hour()%a,J=Math.ceil(t.clone().add(D,"h").set({minute:0,second:0,millisecond:0}).diff(t,"h",!0)*1e4)/1e4,j=await O.speedLoseInHoursStep(g,t,H,J,y,m,s,r,u,l);if(d.all.push(...j.all),(Q=j.from)!=null&&Q.speed&&(d.hours.push(j.from),d.wps.push(...j.wps),d.days.push(...j.days)),m=j==null?void 0:j.next,!m.length){const V=await O.speedLoseAt(g,j.to,w(j.to.eta),s,0,r,u,l);V.bearing=g.bearing,d.hours.push(V),d.all.push(V)}y+=Math.round((((Z=j==null?void 0:j.to)==null?void 0:Z.distanceFromPrevious)??0)*1e4)/1e4}const N=d.hours;for(let D=0;D<N.length-1;D++){const J=w(N[D+1].eta).diff(N[D].etd,"hour",!0)||1;F+=(N[D].wxFactor||0)*J,M+=(N[D].cFactor||0)*J,L+=J}const W=N.reduce((D,J)=>D+(J.suspend||0),0);($=d.wps)==null||$.forEach((D,J)=>{D.positionTime=w.utc(D.etd||D.eta).unix();const j=d.wps[J-1];if(j){const V=D.distanceFromStart-j.distanceFromStart,Y=w(D.eta||D.etd).diff(w(j.etd||j.eta),"h",!0);D.avgSpd=Math.round(V/Y*100)/100;const ot=E.LaneHelper.calculateBearing(j,D);D.avgBearing=ot,j.bearing=ot}}),d.wps=await O.reduceWPS(d.wps),d.days=await O.reduceDays(d.days),d.all=(tt=d.all)==null?void 0:tt.reduce((D,J)=>(J.positionTime=w.utc(J.etd||J.eta).unix(),D.some(j=>Math.round(j.positionTime/60)===Math.round(J.positionTime/60))||D.push(J),D),[]),f.sample=d;const B=d.hours.at(0),C=d.hours.at(-1);f.distance=Math.round(C.distanceFromStart*1e3)/1e3,f.etd=w(B.eta).utc().format(),f.eta=w(C.eta).utc().format(),f.wxFactor=Math.round(F/L*1e3)/1e3,f.cFactor=Math.round(M/L*1e3)/1e3,f.avgSpeed=Math.round(C.distanceFromStart/L*1e3)/1e3,f.totalHrs=Math.round(L*1e3)/1e3,f.suspend=Math.round(W*1e3)/1e3;const R=E.LngLatHelper.roundPrecision(o.dgo/24*W,3),{distanceInECA:q,hoursInECA:z,totalDgoConsInECA:rt,eca:at}=await this.calculateECA(f,o,l),st=E.LngLatHelper.roundPrecision(o.fo/24*(L-z),3),ct=E.LngLatHelper.roundPrecision(o.dgo/24*L+R,3);f.extend={eca:at,distanceInECA:q,hoursInECA:z,totalDgoConsInECA:rt,totalDgoConsInSuspend:R},f.totalFoCons=st<0?0:st,f.totalDgoCons=ct;const nt=w().valueOf()-h,ut=((et=d==null?void 0:d.hours)==null?void 0:et.length)||1;return S==null||S.info("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms",l==null?void 0:l.requestId,nt,ut,Math.round(nt/ut*1e3)/1e3),f}static async analyseInstantWithThreshed(e,t,n,o,i,s,a,r="",u=3,l=!0,h=!1,c={}){var Z,$,tt,et,D,J;const I=w().valueOf();e.lng=E.LngLatHelper.convertToStdLng(e.lng);const{v0:b,label:T}=e.sog?{v0:e.sog,label:e.label||"Other"}:{v0:i.speed,label:"CP"},k=O.assembleProperties(o,i.loadCondition,b,0),g=E.LaneHelper.calculateSubRoute(e,s);if(((Z=g[0])==null?void 0:Z.length)<=1)return;const v=a.length?E.LaneHelper.calculateSubWaypoints(e,a):[];v.forEach(j=>j.important=!0);let f=E.LaneHelper.simplifyRouteToCoordinates(g,v,0),d=0,m=0,y=0,F=0;const M={hours:[],wps:[],days:[],all:[]};t=w(t).utc();const L=t.clone();for(;f.length>0;){const j=u-t.hour()%u;let V=Math.ceil(t.clone().add(j,"h").set({minute:0,second:0,millisecond:0}).diff(t,"h",!0)*1e4)/1e4;V=t.clone().add(V,"h").isSameOrAfter(n)?n.diff(t,"h",!0)*1e4/1e4:V;const Y=await O.speedLoseInHoursStep(k,t,L,V,d,f,r,l,h,c);if(M.all.push(...Y.all),($=Y.from)!=null&&$.speed&&(M.hours.push(Y.from),Y!=null&&Y.wps&&M.wps.push(...Y.wps),M.days.push(...Y.days)),f=Y==null?void 0:Y.next,f.length||M.hours.push(Y==null?void 0:Y.to),d+=Math.round((((tt=Y==null?void 0:Y.to)==null?void 0:tt.distanceFromPrevious)??0)*1e4)/1e4,!V)break}M.wps=await O.reduceWPS(M.wps),M.days=await O.reduceDays(M.days),M.all=(et=M.all)==null?void 0:et.reduce((j,V)=>(V.positionTime=w.utc(V.etd||V.eta).unix(),j.some(Y=>Math.round(w(Y.etd).unix()/60)===Math.round(w(V.etd).unix()/60))||j.push(V),j),[]),(D=M.wps)==null||D.forEach((j,V)=>{const Y=M.wps[V-1];if(Y){const ot=j.distanceFromStart-Y.distanceFromStart,kt=w(j.eta||j.etd).diff(w(Y.etd||Y.eta),"h",!0);Y.bearing=E.LaneHelper.calculateBearing(Y,j),j.avgSpd=Math.round(ot/kt*100)/100}});const H=M.hours;for(let j=0;j<H.length-1;j++){const V=w(H[j+1].eta).diff(H[j].etd,"hour",!0);m+=H[j].wxFactor*V,y+=H[j].cFactor*V,F+=V}const N=H.reduce((j,V)=>j+(V.suspend||0),0),W=M.hours.at(0),B=M.hours.at(-1),C=await E.LaneHelper.calculateRangeRoute(W,B,g),R=await E.LaneHelper.calculateRangeWaypoints(W,B,g,v),q={sample:M,distance:Math.round(((B==null?void 0:B.distanceFromStart)||0)*1e4)/1e4,etd:w(W.eta).utc().format(),eta:w(B==null?void 0:B.eta).utc().format(),wxFactor:Math.round(m/F*1e3)/1e3,cFactor:Math.round(y/F*1e3)/1e3,avgSpeed:Math.round(((B==null?void 0:B.distanceFromStart)||0)/F*1e3)/1e3,totalHrs:Math.round(F*1e3)/1e3,suspend:Math.round(N*1e3)/1e3,from:W,to:B,route:C,waypoints:R,v0:b,label:T},z=E.LngLatHelper.roundPrecision(i.dgo/24*N,3),{distanceInECA:rt,hoursInECA:at,totalDgoConsInECA:st,eca:ct}=await this.calculateECA(q,i,c),dt=E.LngLatHelper.roundPrecision(i.fo/24*(F-at),3),nt=E.LngLatHelper.roundPrecision(i.dgo/24*F+z,3);q.extend={eca:ct,distanceInECA:rt,hoursInECA:at,totalDgoConsInECA:st,totalDgoConsInSuspend:z},q.totalDgoCons=nt,q.totalFoCons=dt<0?0:dt;const X=w().valueOf()-I,Q=((J=M==null?void 0:M.hours)==null?void 0:J.length)||1;return S==null||S.debug("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms",c==null?void 0:c.requestId,X,Q,Math.round(X/Q*1e3)/1e3),q}static async analyseCost(e,t,n,o,i={}){var g,v;const s=w().valueOf(),a=[];e.speedStep=e.speedStep||3,e.alterStep=e.alterStep??1;const r=E.LaneHelper.calculateRouteDistance(o.route);let u=0;n.forEach(f=>{const d=Math.ceil(r/f.speed/24);u=u<d?d:u}),u=u*1.3;const l=w.utc(e.etd).add(u??14,"day");let h=1;for(const f of n){const d=JSON.parse(JSON.stringify(o.route)),m=JSON.parse(JSON.stringify(o.waypoints)),y=await O.analyseInstantWithThreshed({lat:e.lat,lng:e.lng},e.etd,l,t,f,d,m,e.meteoVendor,e.speedStep,e.useMeteo,e.useRouteParam,i);y&&(await O.calculateCost(y,f,e,i),a.push(y),S==null||S.info("[%s][L%d-%d] analyse from %s to %s cost: %j",i.requestId,1,h,e.etd,l.format(),{cost:y.cost.total,hire:y.cost.hire,bunker:y.cost.bunker,distance:y.distance,hours:y.totalHrs,cp:`${f.speed}/${f.fo}/${f.dgo}`})),h++}a.sort((f,d)=>f.cost.total-d.cost.total);const c=a.at(0),I=a.at(1),b=[];if(b.push({combined:!1,speeds:[c],cost:(g=c.cost)==null?void 0:g.total}),I){const f=c.cost.cp,d=I.cost.cp,m=w(c.eta),y=w(c.etd),F=m.diff(y,"days",!0);let M=Math.ceil(F/2);M=M>7?7:M<e.alterStep?e.alterStep:M;let L=2,H={combined:!1,speeds:[I],cost:(v=I.cost)==null?void 0:v.total},N;for(;M>=e.alterStep;){const W=await O.combinedAnalyse(e,t,l,[f,d],o,M,{...i,level:L});if(H.cost>W.cost?N?(N==null?void 0:N.cost)>W.cost&&(N=W):(N=H,H=W):(!N||(N==null?void 0:N.cost)>W.cost)&&(N=W),M<=e.alterStep)break;M=Math.ceil(M/2),L+=1}b.push(H),N&&b.push(N)}const k=w().valueOf()-s;return S==null||S.info("[%s] analyse elapsed: %d ms",i==null?void 0:i.requestId,k),b.sort((f,d)=>f.cost-d.cost)}static async combinedAnalyse(e,t,n,o,i,s,a={}){a.counter=1,S==null||S.info("[%s][L%d] analyse with alternate cp in every %d days",a.requestId,a.level,s);const r=await O.alternateAnalyse(e,t,n,o,0,i,s,a),u=r.reduce((d,m)=>d+m.cost.total,0),l=r.reduce((d,m)=>d+m.cost.hire,0),h=r.reduce((d,m)=>d+m.cost.bunker,0),c=r.reduce((d,m)=>d+m.distance,0),I=r.reduce((d,m)=>d+m.totalHrs,0);S==null||S.info("[%s][L%d] cost with cpa/cpb turn: %j",a.requestId,a.level,{cost:u,hire:l,bunker:h,distance:c,hours:I});const b=await O.alternateAnalyse(e,t,n,o,1,i,s,a),T=b.reduce((d,m)=>d+m.cost.total,0),k=b.reduce((d,m)=>d+m.cost.hire,0),g=b.reduce((d,m)=>d+m.cost.bunker,0),v=b.reduce((d,m)=>d+m.distance,0),f=b.reduce((d,m)=>d+m.totalHrs,0);return S==null||S.info("[%s][L%d] cost with cpb/cpa turn: %j",a.requestId,a.level,{cost:T,hire:k,bunker:g,distance:v,hours:f}),u<T?{combined:!0,cost:Math.round(u*1e3)/1e3,speeds:r,step:s}:{combined:!0,cost:Math.round(T*1e3)/1e3,speeds:b,step:s}}static async alternateAnalyse(e,t,n,o,i,s,a,r={}){var c,I;let u=w.utc(e.etd);const l={lat:e.lat,lng:e.lng},h=[];for(;u.isBefore(n);){const b=u.clone().utc().add(a,"day"),T=JSON.parse(JSON.stringify(s.route)),k=JSON.parse(JSON.stringify(s.waypoints)),g=o[i],v=await O.analyseInstantWithThreshed(l,u.utc().format(),b,t,g,T,k,e.meteoVendor,e.speedStep,e.useMeteo,e.useRouteParam,r);v&&(await O.calculateCost(v,g,e,r),S==null||S.info("[%s][L%d-%d] analyse from %s to %s cost: %j",r.requestId,r.level,r.counter,u.utc().format(),b.utc().format(),{cost:v.cost.total,hire:v.cost.hire,bunker:v.cost.bunker,distance:v.distance,hours:v.totalHrs,cp:`${g.speed}/${g.fo}/${g.dgo}`})),r.counter=r.counter+1;const f=(I=(c=v==null?void 0:v.sample)==null?void 0:c.hours)==null?void 0:I.at(-1);if(f)l.lat=f.lat,l.lng=f.lng,u=w(f.eta),h.push(v),i=i?0:1;else break}return h}static async calculateCost(e,t,n,o={}){var i;if(e){const s=(n.addComm||0)>=1?(n.addComm||0)/100:n.addComm||0,a=Math.round((n.dailyHire||0)*(e.suspend||0)/24*1e3)/1e3,r=Math.round(e.totalHrs/24*(n.dailyHire||0)*(1-s)*1e3)/1e3+a,u=Math.round(e.totalFoCons*(n.priceFO||0)*1e3)/1e3,l=Math.round((e.totalDgoCons+(((i=e.extend)==null?void 0:i.totalDgoConsInECA)||0))*(n.priceDGO||0)*1e3)/1e3;e.cost={total:Math.round((r+u+l)*1e3)/1e3,hire:Math.round(r*1e3)/1e3,suspendHire:a,bunker:Math.round((u+l)*1e3)/1e3,cp:t}}return e}static async calculateECA(e,t,n={}){var r,u,l,h;const o=await E.LaneHelper.intersectInECA((e==null?void 0:e.route)||[]);let i=0,s=0,a=0;(u=(r=e==null?void 0:e.sample)==null?void 0:r.wps)==null||u.forEach(c=>{c.positionTime=w.utc(c.etd||c.eta).unix()});for(const c of o){i+=c.distance;const I=await E.LaneHelper.deadReckoningTime((l=c.waypoints)==null?void 0:l.at(0),e.sample.all||e.sample.wps),b=await E.LaneHelper.deadReckoningTime((h=c.waypoints)==null?void 0:h.at(-1),e.sample.all||e.sample.wps);c.in=I,c.out=b,c.totalHrs=E.LngLatHelper.roundPrecision((b.positionTime-I.positionTime)/3600,3),c.totalDgoCons=E.LngLatHelper.roundPrecision(t.fo/24*c.totalHrs,3),s+=c.totalHrs,a+=c.totalDgoCons}return i=E.LngLatHelper.roundPrecision(i,3),s=E.LngLatHelper.roundPrecision(s,3),a=E.LngLatHelper.roundPrecision(a,3),{distanceInECA:i,hoursInECA:s,totalDgoConsInECA:a,eca:o}}static async mergeSpeeds(e,t={}){var f,d;const n={hours:[],wps:[],days:[],all:[]},o=e.reduce((m,y)=>m+y.distance,0),i=e.reduce((m,y)=>{var F;return m+(((F=y.extend)==null?void 0:F.distanceInECA)||0)},0),s=e.reduce((m,y)=>m+y.totalHrs,0),a=e.reduce((m,y)=>{var F;return m+(((F=y.extend)==null?void 0:F.hoursInECA)||0)},0),r=e.reduce((m,y)=>{var F;return m+(((F=y.extend)==null?void 0:F.totalDgoConsInECA)||0)},0),u=e.reduce((m,y)=>m+y.wxFactor*y.totalHrs/s,0),l=e.reduce((m,y)=>m+y.cFactor*y.totalHrs/s,0),h=e.reduce((m,y)=>m+y.totalFoCons,0),c=e.reduce((m,y)=>m+y.totalDgoCons,0),I=e.reduce((m,y)=>m+y.cost.total,0),b=e.reduce((m,y)=>m+y.cost.hire,0),T=e.reduce((m,y)=>m+y.cost.bunker,0),k=[],g=[];let v;for(const m of e){g.push(...((f=m.extend)==null?void 0:f.eca)||[]);const y=m.sample.hours,F=m.sample.all,M=m.sample.wps,L=m.sample.days,H=y.at(0);v&&(H.distanceFromPrevious=v.distanceFromPrevious,H.distanceFromStart=v.distanceFromStart,y.forEach((C,R)=>{R&&(C.distanceFromStart=C.distanceFromStart+v.distanceFromStart)}),F.at(0).distanceFromPrevious=v.distanceFromPrevious,F.at(0).distanceFromStart=v.distanceFromStart,F.forEach((C,R)=>{R&&(C.distanceFromStart=C.distanceFromStart+v.distanceFromStart)}),M.at(0).distanceFromPrevious=v.distanceFromPrevious,M.at(0).distanceFromStart=v.distanceFromStart,M.forEach((C,R)=>{R&&(C.distanceFromStart=C.distanceFromStart+v.distanceFromStart)}),L.at(0).distanceFromPrevious=v.distanceFromPrevious,L.at(0).distanceFromStart=v.distanceFromStart,L.forEach((C,R)=>{R&&(C.distanceFromStart=C.distanceFromStart+v.distanceFromStart)})),H.cp=m.cost.cp;const N=[m.etd,m.eta],W=k.findIndex(C=>C.id===H.cp.id);W===-1?(H.cp.segment=[N],k.push(H.cp)):k[W].segment.push(N),y.forEach(C=>{var q;((q=n.hours)==null?void 0:q.findIndex(z=>z.eta===C.eta))===-1&&n.hours.push(C)}),F.forEach(C=>{var q;((q=n.all)==null?void 0:q.findIndex(z=>z.eta===C.eta))===-1&&n.all.push(C)}),M.forEach(C=>{var q;((q=n.wps)==null?void 0:q.findIndex(z=>z.eta===C.eta))===-1&&n.wps.push(C)}),L.forEach(C=>{var q;((q=n==null?void 0:n.days)==null?void 0:q.findIndex(z=>z.eta===C.eta))===-1&&n.days.push(C)});const B=(d=n.wps)==null?void 0:d.findIndex(C=>C.eta===H.eta);B===-1?n.wps.push(H):n.wps[B]=H,v=y.at(-1)}return n.wps.sort((m,y)=>w(m.etd).unix()-w(y.etd).unix()),n.wps.forEach((m,y)=>{const F=n.wps[y-1];if(F){const M=m.distanceFromStart-(F.distanceFromStart||0),L=w(m.eta||m.etd).diff(w(F.etd||F.eta),"hour",!0),H=Math.round(M/L*100)/100;m.avgSpd=H;const N=E.LaneHelper.calculateBearing(F,m);F.bearing=N}}),{sample:n,etd:e.at(0).etd,eta:e.at(-1).eta,from:e.at(0).from,to:e.at(-1).to,v0:e.at(0).v0,label:"Combined",distance:Math.round(o*1e3)/1e3,totalHrs:Math.round(s*1e3)/1e3,avgSpeed:Math.round(o/s*1e3)/1e3,wxFactor:Math.round(u*1e3)/1e3,cFactor:Math.round(l*1e3)/1e3,totalFoCons:Math.round(h*1e3)/1e3,totalDgoCons:Math.round(c*1e3)/1e3,cost:{total:Math.round(I*1e3)/1e3,hire:Math.round(b*1e3)/1e3,bunker:Math.round(T*1e3)/1e3},extend:{cps:k,eca:g,distanceInECA:Math.round(i*1e3)/1e3,hoursInECA:Math.round(a*1e3)/1e3,totalDgoConsInECA:Math.round(r*1e3)/1e3,speeds:e}}}}P.AISImpl=G,P.AlertHelper=ht,P.AlertLevel=lt,P.HifleetImpl=bt,P.LoadCondition=mt,P.MyShipImpl=gt,P.MyVesselImpl=pt,P.ShipxyImpl=vt,P.SpeedHelper=O,P.SpeedLabel=yt,P.VesselTag=ft,P.alertHelper=wt,Object.defineProperty(P,Symbol.toStringTag,{value:"Module"})});
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@idm-plugin/vessel",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "3.
|
|
4
|
+
"version": "3.8.1",
|
|
5
5
|
"description": "idm plugin for vessel",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"keywords": [
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@idm-plugin/geo2": "^1.6.8",
|
|
36
|
-
"@idm-plugin/meteo": "^0.6.
|
|
37
|
-
"@idm-plugin/meteo2": "^0.9.
|
|
36
|
+
"@idm-plugin/meteo": "^0.6.7",
|
|
37
|
+
"@idm-plugin/meteo2": "^0.9.9",
|
|
38
38
|
"@idm-plugin/tag": "^0.3.0",
|
|
39
39
|
"@turf/turf": "^6.5.0",
|
|
40
40
|
"@types/jest": "^25.2.2",
|