@idm-plugin/vessel 2.3.8 → 3.4.0
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 +137 -137
- package/dist/index.umd.cjs +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -120,11 +120,11 @@ class Ft extends st {
|
|
|
120
120
|
* @param options
|
|
121
121
|
*/
|
|
122
122
|
async search(t, a = {}) {
|
|
123
|
-
var
|
|
123
|
+
var u, h;
|
|
124
124
|
await this.checkToken(a);
|
|
125
125
|
const i = /^\d{7}$/.test(t.toString()), n = i ? "https://market.myvessel.cn/sdc/v1/mkt/vessels/detail/imo" : "https://market.myvessel.cn/sdc/v1/mkt/vessels/detail/mmsi", o = i ? { imo: t } : { mmsi: t }, e = {
|
|
126
126
|
headers: {
|
|
127
|
-
Authorization: `${(
|
|
127
|
+
Authorization: `${(u = this.token) == null ? void 0 : u.tokenType} ${(h = this.token) == null ? void 0 : h.accessToken}`
|
|
128
128
|
},
|
|
129
129
|
searchParams: o
|
|
130
130
|
};
|
|
@@ -133,30 +133,30 @@ class Ft extends st {
|
|
|
133
133
|
if (c.status !== 200)
|
|
134
134
|
return f == null || f.warn("[%s] fetch suggest vessels failed: %j", a.requestId, { message: c.message, status: c.status, code: c.code }), {};
|
|
135
135
|
{
|
|
136
|
-
const
|
|
137
|
-
if (
|
|
136
|
+
const d = c.data;
|
|
137
|
+
if (d)
|
|
138
138
|
return {
|
|
139
|
-
mmsi:
|
|
140
|
-
imo: Number.isNaN(
|
|
141
|
-
callSign:
|
|
142
|
-
name:
|
|
143
|
-
nameCn:
|
|
144
|
-
type:
|
|
145
|
-
flagName:
|
|
146
|
-
clasz:
|
|
147
|
-
dateOfBuild:
|
|
148
|
-
deadweight:
|
|
149
|
-
grossTonnage:
|
|
150
|
-
netTonnage:
|
|
151
|
-
teu:
|
|
152
|
-
length:
|
|
153
|
-
breadth:
|
|
154
|
-
height:
|
|
155
|
-
draught:
|
|
156
|
-
speed:
|
|
157
|
-
passengerCapacity:
|
|
139
|
+
mmsi: d.mmsi,
|
|
140
|
+
imo: Number.isNaN(d.imo) ? null : Number(d.imo),
|
|
141
|
+
callSign: d.callsign,
|
|
142
|
+
name: d.nameEn,
|
|
143
|
+
nameCn: d.nameCn,
|
|
144
|
+
type: d.vesselTypeNameEn,
|
|
145
|
+
flagName: d.flagCtry,
|
|
146
|
+
clasz: d.classSociety,
|
|
147
|
+
dateOfBuild: d.buildYearMonth,
|
|
148
|
+
deadweight: d.dwt,
|
|
149
|
+
grossTonnage: d.grt,
|
|
150
|
+
netTonnage: d.net,
|
|
151
|
+
teu: d.teu,
|
|
152
|
+
length: d.length,
|
|
153
|
+
breadth: d.width,
|
|
154
|
+
height: d.height,
|
|
155
|
+
draught: d.draught,
|
|
156
|
+
speed: d.speed,
|
|
157
|
+
passengerCapacity: d.passengercapacity,
|
|
158
158
|
vendor: "myvessel",
|
|
159
|
-
raw:
|
|
159
|
+
raw: d
|
|
160
160
|
};
|
|
161
161
|
}
|
|
162
162
|
return {};
|
|
@@ -177,11 +177,11 @@ class Ft extends st {
|
|
|
177
177
|
return o.status !== 200 ? (f == null || f.warn("[%s] fetch vessel archive failed: %j", a.requestId, { message: o.message, status: o.status, code: o.code }), {}) : o.data;
|
|
178
178
|
}
|
|
179
179
|
async realTimePosition(t, a = {}) {
|
|
180
|
-
var c,
|
|
180
|
+
var c, u;
|
|
181
181
|
await this.checkToken(a);
|
|
182
182
|
const i = "https://svc.data.myvessel.cn/sdc/v1/vessels/status/location/unit", n = {
|
|
183
183
|
headers: {
|
|
184
|
-
Authorization: `${(c = this.token) == null ? void 0 : c.tokenType} ${(
|
|
184
|
+
Authorization: `${(c = this.token) == null ? void 0 : c.tokenType} ${(u = this.token) == null ? void 0 : u.accessToken}`
|
|
185
185
|
},
|
|
186
186
|
searchParams: { mmsi: t }
|
|
187
187
|
};
|
|
@@ -229,11 +229,11 @@ class Ft extends st {
|
|
|
229
229
|
return {};
|
|
230
230
|
}
|
|
231
231
|
async calculateRoute(t, a, i = {}) {
|
|
232
|
-
var c,
|
|
232
|
+
var c, u;
|
|
233
233
|
await this.checkToken(i);
|
|
234
234
|
const n = "https://svc.data.myvessel.cn/sdc/v1/routes/routing/nodes", o = {
|
|
235
235
|
headers: {
|
|
236
|
-
Authorization: `${(c = this.token) == null ? void 0 : c.tokenType} ${(
|
|
236
|
+
Authorization: `${(c = this.token) == null ? void 0 : c.tokenType} ${(u = this.token) == null ? void 0 : u.accessToken}`
|
|
237
237
|
},
|
|
238
238
|
json: {
|
|
239
239
|
startPoint: {
|
|
@@ -255,14 +255,14 @@ class Ft extends st {
|
|
|
255
255
|
}
|
|
256
256
|
async trajectory(t, a, i, n, o = !0, e = {}) {
|
|
257
257
|
await this.checkToken(e);
|
|
258
|
-
const c = await this.realTimePosition(t, e),
|
|
259
|
-
for (; h.diff(
|
|
260
|
-
await this.trajectoryIn30Day(t,
|
|
261
|
-
return await this.trajectoryIn30Day(t,
|
|
258
|
+
const c = await this.realTimePosition(t, e), u = p(a), h = p(i), d = [];
|
|
259
|
+
for (; h.diff(u, "day", !0) > 30; )
|
|
260
|
+
await this.trajectoryIn30Day(t, u, u.clone().add(30, "day"), c, n, d, e), u.add(30, "day");
|
|
261
|
+
return await this.trajectoryIn30Day(t, u, h, c, n, d, e), d;
|
|
262
262
|
}
|
|
263
263
|
async trajectoryIn30Day(t, a, i, n, o, e, c = {}) {
|
|
264
264
|
var M, j, I, w, g;
|
|
265
|
-
const
|
|
265
|
+
const u = "https://svc.data.myvessel.cn/sdc/v1/vessels/status/track", h = {
|
|
266
266
|
headers: {
|
|
267
267
|
Authorization: `${(M = this.token) == null ? void 0 : M.tokenType} ${(j = this.token) == null ? void 0 : j.accessToken}`
|
|
268
268
|
},
|
|
@@ -272,13 +272,13 @@ class Ft extends st {
|
|
|
272
272
|
endTime: i.utcOffset(8).format("YYYY-MM-DD HH:mm:ss")
|
|
273
273
|
}
|
|
274
274
|
};
|
|
275
|
-
f == null || f.info("[%s] fetch trajectory from: %s - %j", c.requestId,
|
|
276
|
-
const
|
|
277
|
-
if (
|
|
278
|
-
return f == null || f.warn("[%s] fetch trajectory failed: %j", c.requestId,
|
|
275
|
+
f == null || f.info("[%s] fetch trajectory from: %s - %j", c.requestId, u, h);
|
|
276
|
+
const d = await V.post(u, h).json();
|
|
277
|
+
if (d.code)
|
|
278
|
+
return f == null || f.warn("[%s] fetch trajectory failed: %j", c.requestId, u, { message: d.message, status: d.status, code: d.code }), d;
|
|
279
279
|
let y = -1;
|
|
280
|
-
const v = p(`${(w = (I =
|
|
281
|
-
return (g =
|
|
280
|
+
const v = p(`${(w = (I = d.data) == null ? void 0 : I[0]) == null ? void 0 : w.postime} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
281
|
+
return (g = d.data) == null || g.forEach((r) => {
|
|
282
282
|
for (const P in r)
|
|
283
283
|
!isNaN(r[P]) && Number(r[P]) !== 1 / 0 && (r[P] = Number(r[P]));
|
|
284
284
|
const b = p(`${r.postime} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00"), m = r.status, { labelCn: l, labelEn: k } = this.parseStatus(m), S = {
|
|
@@ -324,7 +324,7 @@ class Et extends st {
|
|
|
324
324
|
for (const v in e)
|
|
325
325
|
!isNaN(e[v]) && Number(e[v]) !== 1 / 0 && (e[v] = Number(e[v]));
|
|
326
326
|
e.status = e.sp > 3 ? 0 : 1;
|
|
327
|
-
const c = e.status, { labelCn:
|
|
327
|
+
const c = e.status, { labelCn: u, labelEn: h } = this.parseStatus(c), d = p(`${e.ti} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
328
328
|
return {
|
|
329
329
|
mmsi: e.m,
|
|
330
330
|
name: e.n,
|
|
@@ -345,10 +345,10 @@ class Et extends st {
|
|
|
345
345
|
dwt: e.dwt,
|
|
346
346
|
build: e.buildyear,
|
|
347
347
|
flag: e.fn,
|
|
348
|
-
positionTime:
|
|
349
|
-
utc:
|
|
348
|
+
positionTime: d.unix(),
|
|
349
|
+
utc: d.utc().format(),
|
|
350
350
|
status: c,
|
|
351
|
-
labelCn:
|
|
351
|
+
labelCn: u,
|
|
352
352
|
labelEn: h,
|
|
353
353
|
method: "position",
|
|
354
354
|
vendor: "hifleet"
|
|
@@ -403,21 +403,21 @@ class Et extends st {
|
|
|
403
403
|
imo: !c.imo || isNaN(c.imo) ? null : Number(c.imo),
|
|
404
404
|
score: c._score
|
|
405
405
|
});
|
|
406
|
-
return e.sort((c,
|
|
406
|
+
return e.sort((c, u) => u.score - c.score), e;
|
|
407
407
|
}
|
|
408
408
|
async trajectory(t, a, i, n, o = !0, e = {}) {
|
|
409
409
|
var r, b, m;
|
|
410
410
|
const c = await this.realTimePosition(t, e);
|
|
411
|
-
let
|
|
412
|
-
const h = p(i),
|
|
411
|
+
let u = p(a);
|
|
412
|
+
const h = p(i), d = p();
|
|
413
413
|
if (o) {
|
|
414
|
-
let l = h.diff(
|
|
415
|
-
l < 0 ?
|
|
414
|
+
let l = h.diff(u, "d", !0);
|
|
415
|
+
l < 0 ? u = h.clone().subtract(40, "d") : l < 30 ? u.subtract(10, "d") : l < 60 ? u.subtract(5, "d") : u = h.clone().subtract(80, "d"), l = d.diff(h, "d", !0), h.add(l > 10 ? 240 : l * 24, "h");
|
|
416
416
|
}
|
|
417
417
|
const y = {
|
|
418
418
|
searchParams: {
|
|
419
419
|
endtime: h.utcOffset("+8:00").format("YYYY-MM-DD HH:mm:ss"),
|
|
420
|
-
starttime:
|
|
420
|
+
starttime: u.utcOffset("+8:00").format("YYYY-MM-DD HH:mm:ss"),
|
|
421
421
|
mmsi: t,
|
|
422
422
|
usertoken: this.token
|
|
423
423
|
}
|
|
@@ -475,7 +475,7 @@ class Nt extends st {
|
|
|
475
475
|
const e = o.data[0];
|
|
476
476
|
for (const y in e)
|
|
477
477
|
!isNaN(e[y]) && Number(e[y]) !== 1 / 0 && (e[y] = Number(e[y]));
|
|
478
|
-
const { labelCn: c, labelEn:
|
|
478
|
+
const { labelCn: c, labelEn: u } = await this.parseStatus(e.navistat), h = p.unix(e.lasttime);
|
|
479
479
|
return {
|
|
480
480
|
mmsi: e.ShipID,
|
|
481
481
|
name: e.name,
|
|
@@ -493,7 +493,7 @@ class Nt extends st {
|
|
|
493
493
|
positionTime: e.lasttime,
|
|
494
494
|
utc: h.utc().format(),
|
|
495
495
|
status: e.navistat,
|
|
496
|
-
labelEn:
|
|
496
|
+
labelEn: u,
|
|
497
497
|
labelCn: c,
|
|
498
498
|
method: "position",
|
|
499
499
|
vendor: "shipxy"
|
|
@@ -501,17 +501,17 @@ class Nt extends st {
|
|
|
501
501
|
}
|
|
502
502
|
async trajectory(t, a, i, n, o = !0, e = {}) {
|
|
503
503
|
var g;
|
|
504
|
-
const c = await this.realTimePosition(t, e),
|
|
504
|
+
const c = await this.realTimePosition(t, e), u = p(a), h = p(i), d = "https://api.shipxy.com/apicall/GetShipTrack", y = {
|
|
505
505
|
searchParams: {
|
|
506
506
|
id: t,
|
|
507
507
|
k: this.token,
|
|
508
508
|
enc: 1,
|
|
509
509
|
cut: 0,
|
|
510
|
-
btm:
|
|
510
|
+
btm: u.unix(),
|
|
511
511
|
etm: h.unix()
|
|
512
512
|
}
|
|
513
|
-
}, v = await V.get(
|
|
514
|
-
if (f == null || f.info("[%s] fetch trajectory from: %s - %j", e.requestId,
|
|
513
|
+
}, v = await V.get(d, y).json();
|
|
514
|
+
if (f == null || f.info("[%s] fetch trajectory from: %s - %j", e.requestId, d, y), (v == null ? void 0 : v.status) !== 0)
|
|
515
515
|
return v;
|
|
516
516
|
const M = v == null ? void 0 : v.points, j = [], I = p.unix((g = M[0]) == null ? void 0 : g.utc);
|
|
517
517
|
let w = -1;
|
|
@@ -583,35 +583,35 @@ class Tt extends st {
|
|
|
583
583
|
}
|
|
584
584
|
}, e = "https://api3.myships.com/sp/ships/position/latest", c = await V.post(e, o).json();
|
|
585
585
|
f == null || f.info("[%s] fetch realtime position from: %s - %j", a.requestId, e, o);
|
|
586
|
-
const
|
|
587
|
-
for (const M in
|
|
588
|
-
!isNaN(
|
|
589
|
-
const { labelCn: h, labelEn:
|
|
586
|
+
const u = c.data[0];
|
|
587
|
+
for (const M in u)
|
|
588
|
+
!isNaN(u[M]) && Number(u[M]) !== 1 / 0 && (u[M] = Number(u[M]));
|
|
589
|
+
const { labelCn: h, labelEn: d } = await this.parseStatus(u.aisNavStatus), y = p.unix(u.posTime);
|
|
590
590
|
return {
|
|
591
591
|
...n,
|
|
592
592
|
mmsi: t,
|
|
593
|
-
lat: Math.round(
|
|
594
|
-
lng: Math.round(
|
|
595
|
-
sog: Math.round(
|
|
596
|
-
cog: Math.round(
|
|
597
|
-
hdg: Math.round(
|
|
598
|
-
rot: Math.round(
|
|
599
|
-
positionTime:
|
|
593
|
+
lat: Math.round(u.lat / 1e4 / 60 * 1e5) / 1e5,
|
|
594
|
+
lng: Math.round(u.lon / 1e4 / 60 * 1e5) / 1e5,
|
|
595
|
+
sog: Math.round(u.sog / 10 * 100) / 100,
|
|
596
|
+
cog: Math.round(u.cog / 10 * 100) / 100,
|
|
597
|
+
hdg: Math.round(u.heading * 100) / 100,
|
|
598
|
+
rot: Math.round(u.rot * 100) / 100,
|
|
599
|
+
positionTime: u.posTime,
|
|
600
600
|
utc: y.utc().format(),
|
|
601
|
-
status:
|
|
602
|
-
labelEn:
|
|
601
|
+
status: u.aisNavStatus,
|
|
602
|
+
labelEn: d,
|
|
603
603
|
labelCn: h,
|
|
604
604
|
method: "position",
|
|
605
605
|
vendor: "myship"
|
|
606
606
|
};
|
|
607
607
|
}
|
|
608
608
|
async trajectory(t, a, i, n, o = !0, e = {}) {
|
|
609
|
-
const c = p(a),
|
|
610
|
-
for (;
|
|
611
|
-
await this.trajectoryIn30Day(h, c.unix(), c.add(30, "day").unix(),
|
|
612
|
-
return await this.trajectoryIn30Day(h, c.unix(),
|
|
609
|
+
const c = p(a), u = p(i), h = await this.getShipId(t), d = await this.getShipInfo(h), y = [];
|
|
610
|
+
for (; u.diff(c, "day", !0) > 30; )
|
|
611
|
+
await this.trajectoryIn30Day(h, c.unix(), c.add(30, "day").unix(), d, t, n, y);
|
|
612
|
+
return await this.trajectoryIn30Day(h, c.unix(), u.unix(), d, t, n, y), y;
|
|
613
613
|
}
|
|
614
|
-
async trajectoryIn30Day(t, a, i, n, o, e, c,
|
|
614
|
+
async trajectoryIn30Day(t, a, i, n, o, e, c, u = {}) {
|
|
615
615
|
var I;
|
|
616
616
|
const h = {
|
|
617
617
|
headers: {
|
|
@@ -622,9 +622,9 @@ class Tt extends st {
|
|
|
622
622
|
startTime: a,
|
|
623
623
|
endTime: i
|
|
624
624
|
}
|
|
625
|
-
},
|
|
626
|
-
if (f == null || f.info("[%s] fetch trajectory from: %s - %j",
|
|
627
|
-
return f == null || f.warn("[%s] invoke myship trajectory failed: %j",
|
|
625
|
+
}, d = "https://api3.myships.com/sp/ships/position/history", y = await V.post(d, h).json();
|
|
626
|
+
if (f == null || f.info("[%s] fetch trajectory from: %s - %j", u.requestId, d, h), y.code !== "0")
|
|
627
|
+
return f == null || f.warn("[%s] invoke myship trajectory failed: %j", u.requestId, y), y;
|
|
628
628
|
const v = y.data;
|
|
629
629
|
for (const w in v)
|
|
630
630
|
!isNaN(v[w]) && Number(v[w]) !== 1 / 0 && (v[w] = Number(v[w]));
|
|
@@ -667,19 +667,19 @@ class yt {
|
|
|
667
667
|
* @param options
|
|
668
668
|
*/
|
|
669
669
|
parsePrinciple(s, t = {}) {
|
|
670
|
-
var e, c,
|
|
670
|
+
var e, c, u;
|
|
671
671
|
_ == null || _.debug("[%s] parse rule: %s", t.requestId, s);
|
|
672
672
|
const a = new RegExp("(?<=\\[)(.+)(?=])", "g"), i = s.match(a) ? (e = s.match(a)) == null ? void 0 : e[0] : void 0, n = i == null ? void 0 : i.split(";");
|
|
673
673
|
if (!n)
|
|
674
674
|
return;
|
|
675
675
|
const o = {};
|
|
676
676
|
for (let h = 0; h < (n == null ? void 0 : n.length); h++) {
|
|
677
|
-
const
|
|
678
|
-
if (h === 0 && !
|
|
677
|
+
const d = (u = (c = n[h].match(a)) == null ? void 0 : c[0]) == null ? void 0 : u.split("],");
|
|
678
|
+
if (h === 0 && !d)
|
|
679
679
|
o.scope = n[0];
|
|
680
|
-
else if (
|
|
681
|
-
for (let y = 0, v =
|
|
682
|
-
const M = this.parseRule(
|
|
680
|
+
else if (d)
|
|
681
|
+
for (let y = 0, v = d.length; y < v; y++) {
|
|
682
|
+
const M = this.parseRule(d[y]);
|
|
683
683
|
M && (o[M.level] ? M.key ? o[M.level][M == null ? void 0 : M.key] = M : o[M.level] = M : M.key ? o[M.level] = { [M == null ? void 0 : M.key]: M } : o[M.level] = M);
|
|
684
684
|
}
|
|
685
685
|
}
|
|
@@ -715,12 +715,12 @@ class yt {
|
|
|
715
715
|
checkWeather(s, t, a = {}) {
|
|
716
716
|
var M, j, I, w, g, r, b, m, l, k, S, D, P, N, A;
|
|
717
717
|
let i = 0, n = 0, o = 0, e = 0;
|
|
718
|
-
const c = Math.round(((j = (M = t == null ? void 0 : t.SEVERE) == null ? void 0 : M.sigWave) == null ? void 0 : j.number) * 1.6 * 100) / 100,
|
|
718
|
+
const c = Math.round(((j = (M = t == null ? void 0 : t.SEVERE) == null ? void 0 : M.sigWave) == null ? void 0 : j.number) * 1.6 * 100) / 100, u = (w = (I = t == null ? void 0 : t.SEVERE) == null ? void 0 : I.sigWave) == null ? void 0 : w.number, h = (r = (g = t == null ? void 0 : t.HEAVY) == null ? void 0 : g.sigWave) == null ? void 0 : r.number, d = Math.round((((m = (b = t == null ? void 0 : t.SEVERE) == null ? void 0 : b.wind) == null ? void 0 : m.number) + 2) * 100) / 100, y = (k = (l = t == null ? void 0 : t.SEVERE) == null ? void 0 : l.wind) == null ? void 0 : k.number, v = (D = (S = t == null ? void 0 : t.HEAVY) == null ? void 0 : S.wind) == null ? void 0 : D.number;
|
|
719
719
|
for (let x = 0; x < (s == null ? void 0 : s.length); x++) {
|
|
720
720
|
const T = s[x], q = (N = (P = T == null ? void 0 : T.meteo) == null ? void 0 : P.wave) == null ? void 0 : N.sig, R = (A = T == null ? void 0 : T.meteo) == null ? void 0 : A.wind, J = x ? p(T.eta).diff(p(s[x - 1].eta), "hour", !0) : 0;
|
|
721
|
-
e = J > e ? J : e, _ == null || _.debug("[%s] check sig.wave: %j", a.requestId, { ...q, dgThd4Wv: c, svThd4Wv:
|
|
721
|
+
e = J > e ? J : e, _ == null || _.debug("[%s] check sig.wave: %j", a.requestId, { ...q, dgThd4Wv: c, svThd4Wv: u, hvThd4Wv: h }), (q == null ? void 0 : q.height) >= c ? T.isDangerous = !0 : (q == null ? void 0 : q.height) >= u ? T.isSevere = !0 : (q == null ? void 0 : q.height) >= h && (T.isHeavy = !0), _ == null || _.debug("[%s] check wind: %j", a.requestId, { ...R, dgThd4Wd: d, svThd4Wd: y, hvThd4Wd: v }), (R == null ? void 0 : R.scale) >= d ? (T.isDangerous = !0, delete T.isSevere, delete T.isHeavy) : (R == null ? void 0 : R.scale) > y ? (T.isDangerous || (T.isSevere = !0), delete T.isHeavy) : (R == null ? void 0 : R.scale) === v && !T.isDangerous && !T.isSevere && (T.isHeavy = !0), i += T.isDangerous ? J : 0, n += T.isSevere ? J : 0, o += T.isHeavy ? J : 0;
|
|
722
722
|
}
|
|
723
|
-
return i = Math.round(i * 100) / 100, n = Math.round(n * 100) / 100, o = Math.round(o * 100) / 100, e = Math.round(e), { sample: s, dangerous: i, severe: n, heavy: o, step: e < 3 ? 3 : e, wind: { dgThd4Wd:
|
|
723
|
+
return i = Math.round(i * 100) / 100, n = Math.round(n * 100) / 100, o = Math.round(o * 100) / 100, e = Math.round(e), { sample: s, dangerous: i, severe: n, heavy: o, step: e < 3 ? 3 : e, wind: { dgThd4Wd: d, svThd4Wd: y, hvThd4Wd: v }, sig: { dgThd4Wv: c, svThd4Wv: u, hvThd4Wv: h } };
|
|
724
724
|
}
|
|
725
725
|
}
|
|
726
726
|
const xt = new yt();
|
|
@@ -846,9 +846,9 @@ class O {
|
|
|
846
846
|
*/
|
|
847
847
|
static assembleProperties(s, t, a, i) {
|
|
848
848
|
var y;
|
|
849
|
-
const n = s.lbp ?? s.length ?? s.lengthOverall ?? 198.9642, o = s.draught ?? 8, e = s.breadthMoulded ?? s.breadth ?? s.breadthExtreme ?? 32.4572, c = s.deadweight ?? 67035.7773,
|
|
849
|
+
const n = s.lbp ?? s.length ?? s.lengthOverall ?? 198.9642, o = s.draught ?? 8, e = s.breadthMoulded ?? s.breadth ?? s.breadthExtreme ?? 32.4572, c = s.deadweight ?? 67035.7773, u = ((y = s == null ? void 0 : s.type) == null ? void 0 : y.toLowerCase()) || "common";
|
|
850
850
|
return {
|
|
851
|
-
tag:
|
|
851
|
+
tag: u.indexOf("container") > -1 ? "container" : u.indexOf("tugs") > -1 ? "tugs" : "common",
|
|
852
852
|
lbp: n,
|
|
853
853
|
loadCondition: t,
|
|
854
854
|
draught: o,
|
|
@@ -873,7 +873,7 @@ class O {
|
|
|
873
873
|
* @param options
|
|
874
874
|
*/
|
|
875
875
|
static async speedLoseAt(s, t, a, i = "", n = 2, o = !0, e = !1, c = {}) {
|
|
876
|
-
let
|
|
876
|
+
let u;
|
|
877
877
|
if (t.velocity && e && (s.speed = z.roundPrecision(t.velocity * 1852 / 3600, 6)), o) {
|
|
878
878
|
let h;
|
|
879
879
|
try {
|
|
@@ -889,24 +889,24 @@ class O {
|
|
|
889
889
|
} catch (M) {
|
|
890
890
|
C.warn("[%s] meteo2 spot(%j) forecast failed: %s", c.requestId, { ...t, eta: a.utc().format(), source: i }, M);
|
|
891
891
|
}
|
|
892
|
-
const
|
|
893
|
-
|
|
892
|
+
const d = O.currentFactor(s.bearing, h == null ? void 0 : h.current, n), y = O.weatherFactor(s, h, d), v = Math.round((s.speed * 1.943844 + y + d) * 100) / 100;
|
|
893
|
+
u = {
|
|
894
894
|
meteo: { ...h },
|
|
895
895
|
wxFactor: y,
|
|
896
|
-
cFactor:
|
|
896
|
+
cFactor: d,
|
|
897
897
|
speed: t.velocity && e ? t.velocity : v < 0 ? 1 : v,
|
|
898
898
|
eta: a.utc().format(),
|
|
899
899
|
etd: a.utc().format()
|
|
900
900
|
};
|
|
901
901
|
} else
|
|
902
|
-
|
|
902
|
+
u = {
|
|
903
903
|
wxFactor: 0,
|
|
904
904
|
cFactor: 0,
|
|
905
905
|
speed: t.velocity && e ? t.velocity : Math.round(s.speed * 1.943844 * 100) / 100,
|
|
906
906
|
eta: a.utc().format(),
|
|
907
907
|
etd: a.utc().format()
|
|
908
908
|
};
|
|
909
|
-
return delete t.meteo, delete t.wxFactor, delete t.cFactor, delete t.speed, delete t.etd, { ...
|
|
909
|
+
return delete t.meteo, delete t.wxFactor, delete t.cFactor, delete t.speed, delete t.etd, { ...u, ...t };
|
|
910
910
|
}
|
|
911
911
|
/**
|
|
912
912
|
* 基于步长计算失速样本
|
|
@@ -922,15 +922,15 @@ class O {
|
|
|
922
922
|
* @param options
|
|
923
923
|
* @private
|
|
924
924
|
*/
|
|
925
|
-
static async speedLoseInHoursStep(s, t, a, i, n, o, e = "", c = !0,
|
|
925
|
+
static async speedLoseInHoursStep(s, t, a, i, n, o, e = "", c = !0, u = !1, h = {}) {
|
|
926
926
|
t.utc();
|
|
927
|
-
const
|
|
927
|
+
const d = t.clone().add(14, "days"), y = [], v = [];
|
|
928
928
|
let M = 0, j = 0, I, w;
|
|
929
929
|
for (let g = 0; g < o.length - 1; g++) {
|
|
930
930
|
let r = o[g];
|
|
931
931
|
r.distanceFromStart = Math.round((n + j) * 1e3) / 1e3;
|
|
932
932
|
const b = o[g + 1];
|
|
933
|
-
if (s.bearing = L.calculateBearing(r, b, !b.gcToPrevious), r.bearing = s.bearing, r.suspend &&
|
|
933
|
+
if (s.bearing = L.calculateBearing(r, b, !b.gcToPrevious), r.bearing = s.bearing, r.suspend && u) {
|
|
934
934
|
r.eta = r.eta || t.utc().format(), r.elapsed = r.elapsed ?? 0;
|
|
935
935
|
const k = r.suspend - r.elapsed;
|
|
936
936
|
if (i - M > k)
|
|
@@ -943,7 +943,7 @@ class O {
|
|
|
943
943
|
return r.distanceFromPrevious = j, { etd: t, from: w || r, to: r, next: o.filter((S) => S), wps: y, days: v };
|
|
944
944
|
} else
|
|
945
945
|
r.suspend = 0;
|
|
946
|
-
c = t.isAfter(
|
|
946
|
+
c = t.isAfter(d) ? !1 : c, r = await O.speedLoseAt(s, r, t, e, 0, c, u, h), w = w || r, r.important && y.push(r), t.isSameOrAfter(a) && (v.push(r), a.add(24, "hour"));
|
|
947
947
|
const m = L.calculateDistance(r, b, !b.gcToPrevious);
|
|
948
948
|
let l = Math.round(m / w.speed * 1e5) / 1e5;
|
|
949
949
|
if (M + l < i) {
|
|
@@ -995,11 +995,11 @@ class O {
|
|
|
995
995
|
const i = O.blockCoefficient(s.displacement, s.lbp, s.breadthMoulded, s.draught), n = z.roundPrecision(a * 1852 / 3600, 6), o = O.froudeNumber(s.speed - n, s.lbp), e = O.amendFactor(i, o, s.loadCondition);
|
|
996
996
|
let c = Math.abs(s.bearing % 360 - (((v = t == null ? void 0 : t.wind) == null ? void 0 : v.degree) % 360 || 0));
|
|
997
997
|
c = c > 180 ? 360 - c : c;
|
|
998
|
-
const
|
|
999
|
-
let
|
|
1000
|
-
|
|
998
|
+
const u = O.directionFactor(c, (M = t == null ? void 0 : t.wind) == null ? void 0 : M.scale), h = O.vesselTagFactor(s.displacement, s.loadCondition, s.tag, (j = t == null ? void 0 : t.wind) == null ? void 0 : j.kts);
|
|
999
|
+
let d = u * e * h / 100 * (s.speed - n);
|
|
1000
|
+
d = Math.round(d * 1.943844 * 1e4) / 1e4 * -1, s.tag === "tugs" && Math.abs(d) > 1 && (d = d / (Math.abs(Math.round(d)) + 1)), C == null || C.debug("wind wx factor = %d", d), c = Math.abs(s.bearing % 360 - (((w = (I = t == null ? void 0 : t.wave) == null ? void 0 : I.sig) == null ? void 0 : w.degree) % 360 || 0)), c = c > 180 ? 360 - c : c;
|
|
1001
1001
|
const y = O.waveHeightFactor(((r = (g = t == null ? void 0 : t.wave) == null ? void 0 : g.sig) == null ? void 0 : r.height) ?? 1, c);
|
|
1002
|
-
return C == null || C.debug("wave wx factor = %d", y),
|
|
1002
|
+
return C == null || C.debug("wave wx factor = %d", y), d = Math.abs(d) > Math.abs(y) ? d : d * 0.3 + y * 0.7, C == null || C.debug("weather factor = %d", d), d = Math.abs(d) > 3 ? 3 * (Math.abs(d) / d) + Math.abs(d) / d * (Math.abs(d) - 2) * 0.1 : d, Math.round((d || 0) * 100) / 100;
|
|
1003
1003
|
}
|
|
1004
1004
|
/**
|
|
1005
1005
|
* 全程失速分析(走完航程)
|
|
@@ -1014,9 +1014,9 @@ class O {
|
|
|
1014
1014
|
* @param useRouteParam
|
|
1015
1015
|
* @param options
|
|
1016
1016
|
*/
|
|
1017
|
-
static async analyseInstant(s, t, a, i, n, o = "", e = 0, c = !0,
|
|
1017
|
+
static async analyseInstant(s, t, a, i, n, o = "", e = 0, c = !0, u = !1, h = {}) {
|
|
1018
1018
|
var K, G, X, Q, Z, $;
|
|
1019
|
-
const
|
|
1019
|
+
const d = p().valueOf();
|
|
1020
1020
|
s.lng = z.convertToStdLng(s.lng);
|
|
1021
1021
|
const { route: y, waypoints: v } = n.points, M = L.calculateSubRoute(s, y);
|
|
1022
1022
|
if (((K = M[0]) == null ? void 0 : K.length) <= 1)
|
|
@@ -1056,11 +1056,11 @@ class O {
|
|
|
1056
1056
|
m,
|
|
1057
1057
|
o,
|
|
1058
1058
|
c,
|
|
1059
|
-
|
|
1059
|
+
u,
|
|
1060
1060
|
h
|
|
1061
1061
|
);
|
|
1062
1062
|
if ((G = F.from) != null && G.speed && (b.hours.push(F.from), b.wps.push(...F.wps), b.days.push(...F.days)), m = F == null ? void 0 : F.next, !m.length) {
|
|
1063
|
-
const W = await O.speedLoseAt(w, F.to, p(F.to.eta), o, 0, c,
|
|
1063
|
+
const W = await O.speedLoseAt(w, F.to, p(F.to.eta), o, 0, c, u, h);
|
|
1064
1064
|
b.hours.push(W);
|
|
1065
1065
|
}
|
|
1066
1066
|
l += Math.round((((X = F == null ? void 0 : F.to) == null ? void 0 : X.distanceFromPrevious) ?? 0) * 1e4) / 1e4;
|
|
@@ -1087,7 +1087,7 @@ class O {
|
|
|
1087
1087
|
hoursInECA: q,
|
|
1088
1088
|
totalDgoConsInECA: R
|
|
1089
1089
|
}, r.totalFoCons = tt < 0 ? 0 : tt, r.totalDgoCons = at;
|
|
1090
|
-
const et = p().valueOf() -
|
|
1090
|
+
const et = p().valueOf() - d, ot = (($ = b == null ? void 0 : b.hours) == null ? void 0 : $.length) || 1;
|
|
1091
1091
|
return C == null || C.info("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms", h == null ? void 0 : h.requestId, et, ot, Math.round(et / ot * 1e3) / 1e3), r;
|
|
1092
1092
|
}
|
|
1093
1093
|
/**
|
|
@@ -1105,7 +1105,7 @@ class O {
|
|
|
1105
1105
|
* @param useRouteParam
|
|
1106
1106
|
* @param options
|
|
1107
1107
|
*/
|
|
1108
|
-
static async analyseInstantWithThreshed(s, t, a, i, n, o, e, c = "",
|
|
1108
|
+
static async analyseInstantWithThreshed(s, t, a, i, n, o, e, c = "", u = 3, h = !0, d = !1, y = {}) {
|
|
1109
1109
|
var X, Q, Z, $, Y, B;
|
|
1110
1110
|
const v = p().valueOf();
|
|
1111
1111
|
s.lng = z.convertToStdLng(s.lng);
|
|
@@ -1131,10 +1131,10 @@ class O {
|
|
|
1131
1131
|
t = p(t).utc();
|
|
1132
1132
|
const D = t.clone();
|
|
1133
1133
|
for (; r.length > 0; ) {
|
|
1134
|
-
const F =
|
|
1134
|
+
const F = u - t.hour() % u;
|
|
1135
1135
|
let W = Math.ceil(t.clone().add(F, "h").set({ minute: 0, second: 0, millisecond: 0 }).diff(t, "h", !0) * 1e4) / 1e4;
|
|
1136
1136
|
W = t.clone().add(W, "h").isSameOrAfter(a) ? a.diff(t, "h", !0) * 1e4 / 1e4 : W;
|
|
1137
|
-
const H = await O.speedLoseInHoursStep(I, t, D, W, b, r, c, h,
|
|
1137
|
+
const H = await O.speedLoseInHoursStep(I, t, D, W, b, r, c, h, d, y);
|
|
1138
1138
|
if ((Q = H.from) != null && Q.speed && (S.hours.push(H.from), H != null && H.wps && S.wps.push(...H.wps), S.days.push(...H.days)), r = H == null ? void 0 : H.next, r.length || S.hours.push(H == null ? void 0 : H.to), b += Math.round((((Z = H == null ? void 0 : H.to) == null ? void 0 : Z.distanceFromPrevious) ?? 0) * 1e4) / 1e4, !W)
|
|
1139
1139
|
break;
|
|
1140
1140
|
}
|
|
@@ -1198,13 +1198,13 @@ class O {
|
|
|
1198
1198
|
const o = p().valueOf(), e = [];
|
|
1199
1199
|
s.speedStep = s.speedStep || 3, s.alterStep = s.alterStep ?? 1;
|
|
1200
1200
|
const c = L.calculateRouteDistance(i.route);
|
|
1201
|
-
let
|
|
1201
|
+
let u = 0;
|
|
1202
1202
|
a.forEach((r) => {
|
|
1203
1203
|
const b = Math.ceil(c / r.speed / 24);
|
|
1204
|
-
|
|
1205
|
-
}),
|
|
1206
|
-
const h = p.utc(s.etd).add(
|
|
1207
|
-
let
|
|
1204
|
+
u = u < b ? b : u;
|
|
1205
|
+
}), u = u * 1.3;
|
|
1206
|
+
const h = p.utc(s.etd).add(u ?? 14, "day");
|
|
1207
|
+
let d = 1;
|
|
1208
1208
|
for (const r of a) {
|
|
1209
1209
|
const b = JSON.parse(JSON.stringify(i.route)), m = JSON.parse(JSON.stringify(i.waypoints)), l = await O.analyseInstantWithThreshed(
|
|
1210
1210
|
{ lat: s.lat, lng: s.lng },
|
|
@@ -1220,14 +1220,14 @@ class O {
|
|
|
1220
1220
|
s.useRouteParam,
|
|
1221
1221
|
n
|
|
1222
1222
|
);
|
|
1223
|
-
l && (await O.calculateCost(l, r, s, n), e.push(l), C == null || C.info("[%s][L%d-%d] analyse from %s to %s cost: %j", n.requestId, 1,
|
|
1223
|
+
l && (await O.calculateCost(l, r, s, n), e.push(l), C == null || C.info("[%s][L%d-%d] analyse from %s to %s cost: %j", n.requestId, 1, d, s.etd, h.format(), {
|
|
1224
1224
|
cost: l.cost.total,
|
|
1225
1225
|
hire: l.cost.hire,
|
|
1226
1226
|
bunker: l.cost.bunker,
|
|
1227
1227
|
distance: l.distance,
|
|
1228
1228
|
hours: l.totalHrs,
|
|
1229
1229
|
cp: `${r.speed}/${r.fo}/${r.dgo}`
|
|
1230
|
-
})),
|
|
1230
|
+
})), d++;
|
|
1231
1231
|
}
|
|
1232
1232
|
e.sort((r, b) => r.cost.total - b.cost.total);
|
|
1233
1233
|
const y = e.at(0), v = e.at(1), M = [];
|
|
@@ -1259,11 +1259,11 @@ class O {
|
|
|
1259
1259
|
*/
|
|
1260
1260
|
static async combinedAnalyse(s, t, a, i, n, o, e = {}) {
|
|
1261
1261
|
e.counter = 1, C == null || C.info("[%s][L%d] analyse with alternate cp in every %d days", e.requestId, e.level, o);
|
|
1262
|
-
const c = await O.alternateAnalyse(s, t, a, i, 0, n, o, e),
|
|
1262
|
+
const c = await O.alternateAnalyse(s, t, a, i, 0, n, o, e), u = c.reduce((b, m) => b + m.cost.total, 0), h = c.reduce((b, m) => b + m.cost.hire, 0), d = c.reduce((b, m) => b + m.cost.bunker, 0), y = c.reduce((b, m) => b + m.distance, 0), v = c.reduce((b, m) => b + m.totalHrs, 0);
|
|
1263
1263
|
C == null || C.info("[%s][L%d] cost with cpa/cpb turn: %j", e.requestId, e.level, {
|
|
1264
|
-
cost:
|
|
1264
|
+
cost: u,
|
|
1265
1265
|
hire: h,
|
|
1266
|
-
bunker:
|
|
1266
|
+
bunker: d,
|
|
1267
1267
|
distance: y,
|
|
1268
1268
|
hours: v
|
|
1269
1269
|
});
|
|
@@ -1274,7 +1274,7 @@ class O {
|
|
|
1274
1274
|
bunker: w,
|
|
1275
1275
|
distance: g,
|
|
1276
1276
|
hours: r
|
|
1277
|
-
}),
|
|
1277
|
+
}), u < j ? { combined: !0, cost: Math.round(u * 1e3) / 1e3, speeds: c, step: o } : { combined: !0, cost: Math.round(j * 1e3) / 1e3, speeds: M, step: o };
|
|
1278
1278
|
}
|
|
1279
1279
|
/**
|
|
1280
1280
|
* 基于cp索引,交替计算指定步长下的成本
|
|
@@ -1289,12 +1289,12 @@ class O {
|
|
|
1289
1289
|
*/
|
|
1290
1290
|
static async alternateAnalyse(s, t, a, i, n, o, e, c = {}) {
|
|
1291
1291
|
var y, v;
|
|
1292
|
-
let
|
|
1293
|
-
const h = { lat: s.lat, lng: s.lng },
|
|
1294
|
-
for (;
|
|
1295
|
-
const M =
|
|
1292
|
+
let u = p.utc(s.etd);
|
|
1293
|
+
const h = { lat: s.lat, lng: s.lng }, d = [];
|
|
1294
|
+
for (; u.isBefore(a); ) {
|
|
1295
|
+
const M = u.clone().utc().add(e, "day"), j = JSON.parse(JSON.stringify(o.route)), I = JSON.parse(JSON.stringify(o.waypoints)), w = i[n], g = await O.analyseInstantWithThreshed(
|
|
1296
1296
|
h,
|
|
1297
|
-
|
|
1297
|
+
u.utc().format(),
|
|
1298
1298
|
M,
|
|
1299
1299
|
t,
|
|
1300
1300
|
w,
|
|
@@ -1311,7 +1311,7 @@ class O {
|
|
|
1311
1311
|
c.requestId,
|
|
1312
1312
|
c.level,
|
|
1313
1313
|
c.counter,
|
|
1314
|
-
|
|
1314
|
+
u.utc().format(),
|
|
1315
1315
|
M.utc().format(),
|
|
1316
1316
|
{
|
|
1317
1317
|
cost: g.cost.total,
|
|
@@ -1324,11 +1324,11 @@ class O {
|
|
|
1324
1324
|
)), c.counter = c.counter + 1;
|
|
1325
1325
|
const r = (v = (y = g == null ? void 0 : g.sample) == null ? void 0 : y.hours) == null ? void 0 : v.at(-1);
|
|
1326
1326
|
if (r)
|
|
1327
|
-
h.lat = r.lat, h.lng = r.lng,
|
|
1327
|
+
h.lat = r.lat, h.lng = r.lng, u = p(r.eta), d.push(g), n = n ? 0 : 1;
|
|
1328
1328
|
else
|
|
1329
1329
|
break;
|
|
1330
1330
|
}
|
|
1331
|
-
return
|
|
1331
|
+
return d;
|
|
1332
1332
|
}
|
|
1333
1333
|
/**
|
|
1334
1334
|
* 计算Speed的cost
|
|
@@ -1340,11 +1340,11 @@ class O {
|
|
|
1340
1340
|
static async calculateCost(s, t, a, i = {}) {
|
|
1341
1341
|
var n;
|
|
1342
1342
|
if (s) {
|
|
1343
|
-
const o = (a.addComm || 0) >= 1 ? (a.addComm || 0) / 100 : a.addComm || 0, e = Math.round(s.totalHrs / 24 * (a.dailyHire || 0) * (1 - o) * 1e3) / 1e3, c = Math.round(s.totalFoCons * (a.priceFO || 0) * 1e3) / 1e3,
|
|
1343
|
+
const o = (a.addComm || 0) >= 1 ? (a.addComm || 0) / 100 : a.addComm || 0, e = Math.round(s.totalHrs / 24 * (a.dailyHire || 0) * (1 - o) * 1e3) / 1e3, c = Math.round(s.totalFoCons * (a.priceFO || 0) * 1e3) / 1e3, u = Math.round((s.totalDgoCons + (((n = s.extend) == null ? void 0 : n.totalDgoConsInECA) || 0)) * (a.priceDGO || 0) * 1e3) / 1e3;
|
|
1344
1344
|
s.cost = {
|
|
1345
|
-
total: Math.round((e + c +
|
|
1345
|
+
total: Math.round((e + c + u) * 1e3) / 1e3,
|
|
1346
1346
|
hire: e,
|
|
1347
|
-
bunker: Math.round((c +
|
|
1347
|
+
bunker: Math.round((c + u) * 1e3) / 1e3,
|
|
1348
1348
|
cp: t
|
|
1349
1349
|
};
|
|
1350
1350
|
}
|
|
@@ -1355,15 +1355,15 @@ class O {
|
|
|
1355
1355
|
*
|
|
1356
1356
|
*/
|
|
1357
1357
|
static async calculateECA(s, t, a = {}) {
|
|
1358
|
-
var c,
|
|
1358
|
+
var c, u, h, d;
|
|
1359
1359
|
const i = await L.intersectInECA((s == null ? void 0 : s.route) || []);
|
|
1360
1360
|
let n = 0, o = 0, e = 0;
|
|
1361
|
-
(
|
|
1361
|
+
(u = (c = s == null ? void 0 : s.sample) == null ? void 0 : c.wps) == null || u.forEach((y) => {
|
|
1362
1362
|
y.positionTime = p.utc(y.etd || y.eta).unix();
|
|
1363
1363
|
});
|
|
1364
1364
|
for (const y of i) {
|
|
1365
1365
|
n += y.distance;
|
|
1366
|
-
const v = await L.deadReckoningTime((h = y.waypoints) == null ? void 0 : h.at(0), s.sample.wps), M = await L.deadReckoningTime((
|
|
1366
|
+
const v = await L.deadReckoningTime((h = y.waypoints) == null ? void 0 : h.at(0), s.sample.wps), M = await L.deadReckoningTime((d = y.waypoints) == null ? void 0 : d.at(-1), s.sample.wps);
|
|
1367
1367
|
y.in = v, y.out = M, y.totalHrs = z.roundPrecision((M.positionTime - v.positionTime) / 3600, 3), y.totalDgoCons = z.roundPrecision(t.fo / 24 * y.totalHrs, 3), o += y.totalHrs, e += y.totalDgoCons;
|
|
1368
1368
|
}
|
|
1369
1369
|
return n = z.roundPrecision(n, 3), o = z.roundPrecision(o, 3), e = z.roundPrecision(e, 3), {
|
|
@@ -1393,7 +1393,7 @@ class O {
|
|
|
1393
1393
|
}, 0), c = s.reduce((m, l) => {
|
|
1394
1394
|
var k;
|
|
1395
1395
|
return m + (((k = l.extend) == null ? void 0 : k.totalDgoConsInECA) || 0);
|
|
1396
|
-
}, 0),
|
|
1396
|
+
}, 0), u = s.reduce((m, l) => m + l.wxFactor * l.totalHrs / o, 0), h = s.reduce((m, l) => m + l.cFactor * l.totalHrs / o, 0), d = s.reduce((m, l) => m + l.totalFoCons, 0), y = s.reduce((m, l) => m + l.totalDgoCons, 0), v = s.reduce((m, l) => m + l.cost.total, 0), M = s.reduce((m, l) => m + l.cost.hire, 0), j = s.reduce((m, l) => m + l.cost.bunker, 0), I = [], w = [];
|
|
1397
1397
|
let g;
|
|
1398
1398
|
for (const m of s) {
|
|
1399
1399
|
w.push(...((r = m.extend) == null ? void 0 : r.eca) || []);
|
|
@@ -1440,9 +1440,9 @@ class O {
|
|
|
1440
1440
|
distance: Math.round(i * 1e3) / 1e3,
|
|
1441
1441
|
totalHrs: Math.round(o * 1e3) / 1e3,
|
|
1442
1442
|
avgSpeed: Math.round(i / o * 1e3) / 1e3,
|
|
1443
|
-
wxFactor: Math.round(
|
|
1443
|
+
wxFactor: Math.round(u * 1e3) / 1e3,
|
|
1444
1444
|
cFactor: Math.round(h * 1e3) / 1e3,
|
|
1445
|
-
totalFoCons: Math.round(
|
|
1445
|
+
totalFoCons: Math.round(d * 1e3) / 1e3,
|
|
1446
1446
|
totalDgoCons: Math.round(y * 1e3) / 1e3,
|
|
1447
1447
|
cost: {
|
|
1448
1448
|
total: Math.round(v * 1e3) / 1e3,
|
package/dist/index.umd.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(q,A){typeof exports=="object"&&typeof module<"u"?A(exports,require("got"),require("@log4js-node/log4js-api"),require("moment"),require("@idm-plugin/geo2"),require("@idm-plugin/meteo2"),require("@idm-plugin/meteo")):typeof define=="function"&&define.amd?define(["exports","got","@log4js-node/log4js-api","moment","@idm-plugin/geo2","@idm-plugin/meteo2","@idm-plugin/meteo"],A):(q=typeof globalThis<"u"?globalThis:q||self,A(q["idm-plugin-vessel"]={},q.got,q["@log4js-node/log4js-api"],q.moment,q["@idm-plugin/geo2"],q["@idm-plugin/meteo2"],q["@idm-plugin/meteo"]))})(this,function(q,A,U,g,N,ft,nt){"use strict";var It=Object.defineProperty;var St=(q,A,U)=>A in q?It(q,A,{enumerable:!0,configurable:!0,writable:!0,value:U}):q[A]=U;var K=(q,A,U)=>(St(q,typeof A!="symbol"?A+"":A,U),U);let m;try{m=U.getLogger("vessel")}catch{}finally{}class G{parseStatus(s){let t,a;switch(s){case 0:t="在航(主机推动)",a="Underway Using Engine";break;case 1:t="锚泊",a="Anchored";break;case 2:t="失控",a="Not under command";break;case 3:t="操纵受限",a="Limited airworthiness";break;case 4:t="吃水受限",a="Limited by ship's draft";break;case 5:t="靠泊",a="Mooring";break;case 6:t="搁浅",a="Stranded";break;case 7:t="捕捞作业",a="Engaged in fishing";break;case 8:t="靠帆船提供动力",a="Sailing";break;default:t="未定义",a="Undefined"}return{labelCn:t,labelEn:a}}}class mt extends G{constructor(t,a){super();K(this,"clientId");K(this,"clientSecret");K(this,"token");this.clientId=t,this.clientSecret=a}async authToken(t={}){const a="https://svc.data.myvessel.cn/ada/oauth/token",i={searchParams:{client_id:this.clientId,client_secret:this.clientSecret,grant_type:"client_credentials"}},n=await A.post(a,i).json();m==null||m.info("[%s] fetch access token from: %s - %j",t.requestId,a,n),n.error||(this.token={accessToken:n.access_token,tokenType:n.token_type,expiresIn:n.expires_in,scope:n.scope,jti:n.jti,issuedAt:g().utc().format()})}async checkToken(t={}){var a;return(!this.token||g().diff(g(this.token.issuedAt),"seconds")>(((a=this.token)==null?void 0:a.expiresIn)||0)-300)&&await this.authToken(t),this.token}async suggest(t,a={}){var e,r;await this.checkToken(a);const i="https://market.myvessel.cn/sdc/v1/mkt/vessels/fuzzy",n={headers:{Authorization:`${(e=this.token)==null?void 0:e.tokenType} ${(r=this.token)==null?void 0:r.accessToken}`},json:{kw:t,recordNum:a.ps||10}};m==null||m.info("[%s] fetch suggest vessels from: %s - %j",a.requestId,i,n);const o=await A.post(i,n).json();return o.status!==200?(m==null||m.warn("[%s] fetch suggest vessels failed: %j",a.requestId,{message:o.message,status:o.status,code:o.code}),[]):(o.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,a={}){var d,l;await this.checkToken(a);const i=/^\d{7}$/.test(t.toString()),n=i?"https://market.myvessel.cn/sdc/v1/mkt/vessels/detail/imo":"https://market.myvessel.cn/sdc/v1/mkt/vessels/detail/mmsi",o=i?{imo:t}:{mmsi:t},e={headers:{Authorization:`${(d=this.token)==null?void 0:d.tokenType} ${(l=this.token)==null?void 0:l.accessToken}`},searchParams:o};m==null||m.info("[%s] fetch vessel from: %s - %j",a.requestId,n,e);const r=await A.get(n,e).json();if(r.status!==200)return m==null||m.warn("[%s] fetch suggest vessels failed: %j",a.requestId,{message:r.message,status:r.status,code:r.code}),{};{const u=r.data;if(u)return{mmsi:u.mmsi,imo:Number.isNaN(u.imo)?null:Number(u.imo),callSign:u.callsign,name:u.nameEn,nameCn:u.nameCn,type:u.vesselTypeNameEn,flagName:u.flagCtry,clasz:u.classSociety,dateOfBuild:u.buildYearMonth,deadweight:u.dwt,grossTonnage:u.grt,netTonnage:u.net,teu:u.teu,length:u.length,breadth:u.width,height:u.height,draught:u.draught,speed:u.speed,passengerCapacity:u.passengercapacity,vendor:"myvessel",raw:u}}return{}}async archives(t,a={}){var e,r;await this.checkToken(a);const i="https://svc.data.myvessel.cn/sdc/v1/ship/info/batch",n={headers:{Authorization:`${(e=this.token)==null?void 0:e.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",a.requestId,i,n);const o=await A.post(i,n).json();return o.status!==200?(m==null||m.warn("[%s] fetch vessel archive failed: %j",a.requestId,{message:o.message,status:o.status,code:o.code}),{}):o.data}async realTimePosition(t,a={}){var r,d;await this.checkToken(a);const i="https://svc.data.myvessel.cn/sdc/v1/vessels/status/location/unit",n={headers:{Authorization:`${(r=this.token)==null?void 0:r.tokenType} ${(d=this.token)==null?void 0:d.accessToken}`},searchParams:{mmsi:t}};m==null||m.info("[%s] fetch realtime position from: %s - %j",a.requestId,i,n);const o=await A.get(i,n).json();if(o.code)return m==null||m.warn("[%s] fetch realtime position failed: %j",a.requestId,{message:o.message,status:o.status,code:o.code}),o;const e=o.data;for(const l in e)!isNaN(e[l])&&Number(e[l])!==1/0&&(e[l]=Number(e[l]));if(e){const l=g(`${e.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return{mmsi:e.mmsi,name:e.vesselName||e.aisVesselName,imo:e.imo,callSign:e.callsign||e.aisCallSign,lat:e.lat,lng:e.lon,length:e.length,width:e.width,draught:e.currDraught,sog:e.sog,cog:e.cog,hdg:e.hdg,rot:e.rot,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(e.eta)?g.utc(e.eta).format():void 0,destination:e.dest,positionTime:l.unix(),status:e.status,labelCn:e.statusNameCn,labelEn:e.statusNameEn,vesselType:e.vesselTypeNameEn,flag:e.flagCtryNameEn,clasz:e.classSociety,build:e.buildYear,dwt:e.dwt,grt:e.grt,net:e.net,method:"position",vendor:"myVessel",utc:l.utc().format()}}else return{}}async calculateRoute(t,a,i={}){var r,d;await this.checkToken(i);const n="https://svc.data.myvessel.cn/sdc/v1/routes/routing/nodes",o={headers:{Authorization:`${(r=this.token)==null?void 0:r.tokenType} ${(d=this.token)==null?void 0:d.accessToken}`},json:{startPoint:{lon:t.lng,lat:t.lat},endPoint:{lon:a.lng,lat:a.lat},maxDraught:i.maxDraught||10,useAIModel:i.useAIModel||!1,withECA:i.withECA||!1}};m==null||m.info("[%s] fetch route from: %s - %j",i.requestId,n,o);const e=await A.post(n,o).json();return e.status!==200?(m==null||m.warn("[%s] fetch route failed: %j",i.requestId,{message:e.message,status:e.status,code:e.code}),{}):e.data}async trajectory(t,a,i,n,o=!0,e={}){await this.checkToken(e);const r=await this.realTimePosition(t,e),d=g(a),l=g(i),u=[];for(;l.diff(d,"day",!0)>30;)await this.trajectoryIn30Day(t,d,d.clone().add(30,"day"),r,n,u,e),d.add(30,"day");return await this.trajectoryIn30Day(t,d,l,r,n,u,e),u}async trajectoryIn30Day(t,a,i,n,o,e,r={}){var M,C,S,w,b;const d="https://svc.data.myvessel.cn/sdc/v1/vessels/status/track",l={headers:{Authorization:`${(M=this.token)==null?void 0:M.tokenType} ${(C=this.token)==null?void 0:C.accessToken}`},json:{mmsi:t,startTime:a.utcOffset(8).format("YYYY-MM-DD HH:mm:ss"),endTime:i.utcOffset(8).format("YYYY-MM-DD HH:mm:ss")}};m==null||m.info("[%s] fetch trajectory from: %s - %j",r.requestId,d,l);const u=await A.post(d,l).json();if(u.code)return m==null||m.warn("[%s] fetch trajectory failed: %j",r.requestId,d,{message:u.message,status:u.status,code:u.code}),u;let y=-1;const v=g(`${(w=(S=u.data)==null?void 0:S[0])==null?void 0:w.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return(b=u.data)==null||b.forEach(c=>{for(const Y in c)!isNaN(c[Y])&&Number(c[Y])!==1/0&&(c[Y]=Number(c[Y]));const p=g(`${c.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00"),f=c.status,{labelCn:h,labelEn:k}=this.parseStatus(f),j={mmsi:c.mmsi,imo:n==null?void 0:n.imo,lat:c.lat,lng:c.lon,sog:c.sog,cog:c.cog,hdg:c.hdg,draught:c.draught,status:f,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(c.eta)?g(`${c.eta} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00").utc().format():void 0,destination:c.dest,positionTime:p.unix(),labelCn:h,labelEn:k,method:"trajectory",vendor:"myVessel",utc:p.utc().format()},x=Math.floor(p.diff(v,"minute",!0)/(o||1));x!==y&&(y=x,e.push(j))}),e}}class yt extends G{constructor(t){super();K(this,"token");this.token=t}async realTimePosition(t,a={}){const i="https://api.hifleet.com/position/position/get/token",n={searchParams:{mmsi:t,usertoken:this.token}},o=await A.post(i,n).json();m==null||m.info("[%s] fetch realtime position from: %s - %j",a.requestId,i,n);const e=o==null?void 0:o.list;if(!e)return m==null||m.warn("[%s] fetch realtime position failed: %j",a.requestId,i,o),o;for(const v in e)!isNaN(e[v])&&Number(e[v])!==1/0&&(e[v]=Number(e[v]));e.status=e.sp>3?0:1;const r=e.status,{labelCn:d,labelEn:l}=this.parseStatus(r),u=g(`${e.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return{mmsi:e.m,name:e.n,imo:e.imonumber,callSign:e.callsign,lat:Math.round(e.la/60*1e5)/1e5,lng:Math.round(e.lo/60*1e5)/1e5,length:e.l,width:e.w,draught:e.draught,sog:e.sp,cog:e.co,hdg:e.h,rot:isNaN(e.rot)?0:e.rot,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(e.eta)?g.utc(e.eta).format():void 0,destination:e.destination,vesselType:e.type,dwt:e.dwt,build:e.buildyear,flag:e.fn,positionTime:u.unix(),utc:u.utc().format(),status:r,labelCn:d,labelEn:l,method:"position",vendor:"hifleet"}}async search(t,a={}){let i="https://www.hifleet.com/hifleetapi/searchVesselOL.do";const n={searchParams:{keyword:t},headers:{Referer:"https://www.hifleet.com",Origin:"https://www.hifleet.com",Host:"www.hifleet.com"}};let o=await A.post(i,n).json();m==null||m.info("[%s] fetch vessel props from: %s - %j",a.requestId,i,n),o instanceof Array&&(o=o[0]);for(const r in o)!isNaN(o[r])&&Number(o[r])!==1/0&&(o[r]=Number(o[r]));const e={mmsi:o.m,name:o.n,imo:o.i,callSign:o.c,length:o.l,breadth:o.b,draught:o.dr,type:o.t};return i="https://www.hifleet.com/hifleetapi/sameShipSearch.do",o=await A.post(i,n).json(),m==null||m.info("[%s] search vessel dead weight from: %s - %j",a.requestId,i,n),o instanceof Array&&(o=o[0]),o&&(e.deadweight=Number(o.dwt)),e}async suggest(t,a={}){const i="https://www.hifleet.com/hifleetapi/getShipSuggest.do",n={searchParams:{q:t},headers:{Referer:"https://www.hifleet.com",Origin:"https://www.hifleet.com",Host:"www.hifleet.com"}},o=await A.post(i,n).json();m==null||m.info("[%s] suggest vessel props from: %s - %j",a.requestId,i,n);const e=[];for(const r of o)e.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 e.sort((r,d)=>d.score-r.score),e}async trajectory(t,a,i,n,o=!0,e={}){var c,p,f;const r=await this.realTimePosition(t,e);let d=g(a);const l=g(i),u=g();if(o){let h=l.diff(d,"d",!0);h<0?d=l.clone().subtract(40,"d"):h<30?d.subtract(10,"d"):h<60?d.subtract(5,"d"):d=l.clone().subtract(80,"d"),h=u.diff(l,"d",!0),l.add(h>10?240:h*24,"h")}const y={searchParams:{endtime:l.utcOffset("+8:00").format("YYYY-MM-DD HH:mm:ss"),starttime:d.utcOffset("+8:00").format("YYYY-MM-DD HH:mm:ss"),mmsi:t,usertoken:this.token}},v="https://api.hifleet.com/position/trajectory/nocompressed/withstatic/token",M=await A.get(v,y).json();m==null||m.info("[%s] fetch trajectory from: %s - %j",e.requestId,v,y);let C;M&&(C=((p=(c=M.ships)==null?void 0:c.offors)==null?void 0:p.ship)||[],C.length||m==null||m.warn("[%s] fetch trajectory failed: %j",e.requestId,M));const S=[];let w=-1;const b=g(`${(f=C==null?void 0:C[0])==null?void 0:f.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");for(const h of C){for(const L in h)!isNaN(h[L])&&Number(h[L])!==1/0&&(h[L]=Number(h[L]));const k=g(`${h.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");h.status=h.sp>4?0:1;const{labelEn:j,labelCn:x}=this.parseStatus(h.status),Y={mmsi:h.m,name:h.n,imo:r==null?void 0:r.imo,lat:h.la,lng:h.lo,draught:h.draught,sog:h.sp,cog:h.co,hdg:h.hdg,positionTime:k.unix(),utc:k.utc().format(),status:h.status,labelCn:x,labelEn:j,method:"trajectory",vendor:"hifleet"},F=Math.floor(k.diff(b,"minute",!0)/(n||1));F!==w&&(w=F,S.push(Y))}return S}}class Mt extends G{constructor(t){super();K(this,"token");this.token=t}async realTimePosition(t,a={}){const i={searchParams:{id:t,k:this.token,enc:1}},n="https://api.shipxy.com/apicall/GetSingleShip",o=await A.get(n,i).json();if(m==null||m.info("[%s] fetch realtime position from: %s - %j",a.requestId,n,i),(o==null?void 0:o.status)!==0)return o;const e=o.data[0];for(const y in e)!isNaN(e[y])&&Number(e[y])!==1/0&&(e[y]=Number(e[y]));const{labelCn:r,labelEn:d}=await this.parseStatus(e.navistat),l=g.unix(e.lasttime);return{mmsi:e.ShipID,name:e.name,imo:e.imo,callSign:e.callsign,lat:Math.round(e.lat/1e6*1e5)/1e5,lng:Math.round(e.lon/1e6*1e5)/1e5,length:Math.round(e.length/10*100)/100,width:Math.round(e.width/10*100)/100,draught:Math.round(e.draught/1e3*100)/100,sog:Math.round(e.sog*3600/1e3/1852*100)/100,cog:Math.round(e.cog/100*100)/100,hdg:Math.round(e.hdg/100*100)/100,rot:Math.round(e.rot/100*100)/100,positionTime:e.lasttime,utc:l.utc().format(),status:e.navistat,labelEn:d,labelCn:r,method:"position",vendor:"shipxy"}}async trajectory(t,a,i,n,o=!0,e={}){var b;const r=await this.realTimePosition(t,e),d=g(a),l=g(i),u="https://api.shipxy.com/apicall/GetShipTrack",y={searchParams:{id:t,k:this.token,enc:1,cut:0,btm:d.unix(),etm:l.unix()}},v=await A.get(u,y).json();if(m==null||m.info("[%s] fetch trajectory from: %s - %j",e.requestId,u,y),(v==null?void 0:v.status)!==0)return v;const M=v==null?void 0:v.points,C=[],S=g.unix((b=M[0])==null?void 0:b.utc);let w=-1;for(const c of M){const p=g.unix(c.utc),f={imo:r==null?void 0:r.imo,mmsi:t,sog:Math.round(c.sog*3600/1e3/1852*100)/100,cog:Math.round(c.cog/100*100)/100,lat:Math.round(c.lat/1e6*1e5)/1e5,lng:Math.round(c.lon/1e6*1e5)/1e5,positionTime:p.unix(),utc:p.utc().format(),method:"trajectory",vendor:"shipxy"},h=Math.floor(p.diff(S,"minute",!0)/(n||1));h!==w&&(w=h,C.push(f))}return C}}class pt extends G{constructor(t){super();K(this,"token");this.token=t}async getShipId(t,a={}){const i={headers:{appKey:this.token},json:{mmsiList:t}},n="https://api3.myships.com/sp/ships/getShipIdByMMSI",o=await A.post(n,i).json();return m==null||m.info("[%s] fetch ship id from: %s - %j",a.requestId,n,i),o.code!=="0"?o:o.data[0].shipId}async getShipInfo(t,a={}){const i={headers:{appKey:this.token},json:{shipId:t}},n="https://api3.myships.com/sp/ships/aissta",o=await A.post(n,i).json();if(m==null||m.info("[%s] fetch ship info from: %s - %j",a.requestId,n,i),o.code!=="0")return o;const e=o.data;let r=e.imo;return t==="407170"&&(r="9198379",m==null||m.warn("[%s] ship(%s) imo error: %s, should be %s",a.requestId,t,e.imo,r)),{mmsi:e.mmsi,name:e.shipnameEn,imo:r,callSign:e.callSign,length:e.length,width:e.breadth,draught:(e.draught||100)/10}}async realTimePosition(t,a={}){const i=await this.getShipId(t,a),n=await this.getShipInfo(i,a),o={headers:{appKey:this.token},json:{shipId:i}},e="https://api3.myships.com/sp/ships/position/latest",r=await A.post(e,o).json();m==null||m.info("[%s] fetch realtime position from: %s - %j",a.requestId,e,o);const d=r.data[0];for(const M in d)!isNaN(d[M])&&Number(d[M])!==1/0&&(d[M]=Number(d[M]));const{labelCn:l,labelEn:u}=await this.parseStatus(d.aisNavStatus),y=g.unix(d.posTime);return{...n,mmsi:t,lat:Math.round(d.lat/1e4/60*1e5)/1e5,lng:Math.round(d.lon/1e4/60*1e5)/1e5,sog:Math.round(d.sog/10*100)/100,cog:Math.round(d.cog/10*100)/100,hdg:Math.round(d.heading*100)/100,rot:Math.round(d.rot*100)/100,positionTime:d.posTime,utc:y.utc().format(),status:d.aisNavStatus,labelEn:u,labelCn:l,method:"position",vendor:"myship"}}async trajectory(t,a,i,n,o=!0,e={}){const r=g(a),d=g(i),l=await this.getShipId(t),u=await this.getShipInfo(l),y=[];for(;d.diff(r,"day",!0)>30;)await this.trajectoryIn30Day(l,r.unix(),r.add(30,"day").unix(),u,t,n,y);return await this.trajectoryIn30Day(l,r.unix(),d.unix(),u,t,n,y),y}async trajectoryIn30Day(t,a,i,n,o,e,r,d={}){var S;const l={headers:{appKey:this.token},json:{shipId:t,startTime:a,endTime:i}},u="https://api3.myships.com/sp/ships/position/history",y=await A.post(u,l).json();if(m==null||m.info("[%s] fetch trajectory from: %s - %j",d.requestId,u,l),y.code!=="0")return m==null||m.warn("[%s] invoke myship trajectory failed: %j",d.requestId,y),y;const v=y.data;for(const w in v)!isNaN(v[w])&&Number(v[w])!==1/0&&(v[w]=Number(v[w]));const M=g.unix((S=v[0])==null?void 0:S.posTime);let C=-1;for(const w of v){const b=g.unix(w.posTime),c={imo:n==null?void 0:n.imo,mmsi:o,lat:Math.round(w.lat/1e4/60*1e5)/1e5,lng:Math.round(w.lon/1e4/60*1e5)/1e5,sog:Math.round(w.sog/10*100)/100,cog:Math.round(w.cog/10*100)/100,hdg:Math.round(w.heading*100)/100,rot:Math.round(w.rot*100)/100,positionTime:b.unix(),utc:b.utc().format(),method:"trajectory",vendor:"myship"},p=Math.floor(b.diff(M,"minute",!0)/(e||1));p!==C&&(C=p,r.push(c))}return r}}let _;try{_=U.getLogger("vessel")}catch{}finally{}var ct=(D=>(D.NOTICE="NOTICE",D.WARN="WARN",D.HEAVY="HEAVY",D.SEVERE="SEVERE",D.ERROR="ERROR",D.FATAL="FATAL",D))(ct||{});class dt{parsePrinciple(s,t={}){var e,r,d;_==null||_.debug("[%s] parse rule: %s",t.requestId,s);const a=new RegExp("(?<=\\[)(.+)(?=])","g"),i=s.match(a)?(e=s.match(a))==null?void 0:e[0]:void 0,n=i==null?void 0:i.split(";");if(!n)return;const o={};for(let l=0;l<(n==null?void 0:n.length);l++){const u=(d=(r=n[l].match(a))==null?void 0:r[0])==null?void 0:d.split("],");if(l===0&&!u)o.scope=n[0];else if(u)for(let y=0,v=u.length;y<v;y++){const M=this.parseRule(u[y]);M&&(o[M.level]?M.key?o[M.level][M==null?void 0:M.key]=M:o[M.level]=M:M.key?o[M.level]={[M==null?void 0:M.key]:M}:o[M.level]=M)}}return o}parseRule(s,t={}){var o;_==null||_.debug("[%s] parse rule: %s",t.requestId,s),s=s.startsWith("[")?s:`[${s}`,s=s.endsWith("]")?s:`${s}]`;const a=new RegExp("(?<=\\[)(.+?)(?=])","g"),i=(o=s==null?void 0:s.match(a))==null?void 0:o[0],n=i==null?void 0:i.split(",");if(n){let e=n[3]==="Number.MAX_VALUE"?100:Number(n[3]);return e=isNaN(e)?1:e,{operator:n[0],number:Number.isNaN(Number(n[1]))?n[1]:Number(n[1]),level:n[2],time:e,key:n[4]}}}checkWeather(s,t,a={}){var M,C,S,w,b,c,p,f,h,k,j,x,Y,F,L;let i=0,n=0,o=0,e=0;const r=Math.round(((C=(M=t==null?void 0:t.SEVERE)==null?void 0:M.sigWave)==null?void 0:C.number)*1.6*100)/100,d=(w=(S=t==null?void 0:t.SEVERE)==null?void 0:S.sigWave)==null?void 0:w.number,l=(c=(b=t==null?void 0:t.HEAVY)==null?void 0:b.sigWave)==null?void 0:c.number,u=Math.round((((f=(p=t==null?void 0:t.SEVERE)==null?void 0:p.wind)==null?void 0:f.number)+2)*100)/100,y=(k=(h=t==null?void 0:t.SEVERE)==null?void 0:h.wind)==null?void 0:k.number,v=(x=(j=t==null?void 0:t.HEAVY)==null?void 0:j.wind)==null?void 0:x.number;for(let H=0;H<(s==null?void 0:s.length);H++){const E=s[H],P=(F=(Y=E==null?void 0:E.meteo)==null?void 0:Y.wave)==null?void 0:F.sig,V=(L=E==null?void 0:E.meteo)==null?void 0:L.wind,J=H?g(E.eta).diff(g(s[H-1].eta),"hour",!0):0;e=J>e?J:e,_==null||_.debug("[%s] check sig.wave: %j",a.requestId,{...P,dgThd4Wv:r,svThd4Wv:d,hvThd4Wv:l}),(P==null?void 0:P.height)>=r?E.isDangerous=!0:(P==null?void 0:P.height)>=d?E.isSevere=!0:(P==null?void 0:P.height)>=l&&(E.isHeavy=!0),_==null||_.debug("[%s] check wind: %j",a.requestId,{...V,dgThd4Wd:u,svThd4Wd:y,hvThd4Wd:v}),(V==null?void 0:V.scale)>=u?(E.isDangerous=!0,delete E.isSevere,delete E.isHeavy):(V==null?void 0:V.scale)>y?(E.isDangerous||(E.isSevere=!0),delete E.isHeavy):(V==null?void 0:V.scale)===v&&!E.isDangerous&&!E.isSevere&&(E.isHeavy=!0),i+=E.isDangerous?J:0,n+=E.isSevere?J:0,o+=E.isHeavy?J:0}return i=Math.round(i*100)/100,n=Math.round(n*100)/100,o=Math.round(o*100)/100,e=Math.round(e),{sample:s,dangerous:i,severe:n,heavy:o,step:e<3?3:e,wind:{dgThd4Wd:u,svThd4Wd:y,hvThd4Wd:v},sig:{dgThd4Wv:r,svThd4Wv:d,hvThd4Wv:l}}}}const bt=new dt;let I;try{I=U.getLogger("vessel")}catch{}finally{}const vt=new ft.MeteoHelper2("",!0);var ut=(D=>(D.common="common",D.container="container",D.tugs="tugs",D))(ut||{}),lt=(D=>(D.Ballast="Ballast",D.Laden="Laden",D))(lt||{}),ht=(D=>(D.Cp="CP",D.Perf="Basis",D.Instruct="Other",D))(ht||{});class W{static blockCoefficient(s,t,a,i){let n=Math.round(s/(t*a*i)*100)/100;n=n<.55?.55:n>.85?.85:n;const o=[.55,.6,.65,.7,.75,.8,.85],e=o.map(r=>Math.abs(r-n));return o[e.indexOf(Math.min(...e))]}static froudeNumber(s,t,a=9.8){let i=Math.round(Math.sqrt(s*s/(a*t))*100)/100;return i=i<.05?.05:i>.3?.3:i,i}static amendFactor(s,t,a){const i={.55:[1.7,-1.4,-7.4],.6:[2.2,-2.5,-9.7],.65:[2.6,-3.7,-11.6],.7:[3.1,-5.3,-12.4],.75:[2.4,-10.6,-9.5],.8:[2.6,-13.1,-15.1],.85:[3.1,-18.7,28]};let 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.6,-12.5,-13.5],.8:[3,-16.3,-21.6],.85:[3.4,-20.9,31.8]}[s];return a==="Laden"&&(o=i[s]),o[0]+o[1]*t+o[2]*Math.pow(t,2)}static directionFactor(s,t=0){let a;return s>30&&s<=60?a=(1.7-.03*Math.pow(t-4,2))/2:s>60&&s<=150?a=(.9-.06*Math.pow(t-6,2))/2:s>150&&s<=180?a=(.4-.03*Math.pow(t-8,2))/2:a=1,Math.round(a*1e5)/1e5}static vesselTagFactor(s,t,a,i){let n;return a==="container"?n=.7*i/2+Math.pow(i,3)/(22*Math.pow(s,2/3)):t==="Ballast"?n=.7*i/2+Math.pow(i,3)/(2.7*Math.pow(s,2/3)):n=.5*i/2+Math.pow(i,3)/(2.7*Math.pow(s,2/3)),n}static waveHeightFactor(s,t){s=s<3?s*.7:s,s=s<0?.2:s,s=s>6?s-.9*(s-6):s,s=s>9?9:s;let a;return t>30&&t<=60?a=-.6:t>60&&t<=90?a=-.4:t>90&&t<=120?a=s<3?.4:-.3:t>120&&t<=150?a=s<3?.6:-.5:t>150&&t<=180?a=s<3?.7:-.6:a=-.7,Math.round(a*(.144*Math.pow(s,2)+.278*s)*1e4)/1e4}static assembleProperties(s,t,a,i){var y;const n=s.lbp??s.length??s.lengthOverall??198.9642,o=s.draught??8,e=s.breadthMoulded??s.breadth??s.breadthExtreme??32.4572,r=s.deadweight??67035.7773,d=((y=s==null?void 0:s.type)==null?void 0:y.toLowerCase())||"common";return{tag:d.indexOf("container")>-1?"container":d.indexOf("tugs")>-1?"tugs":"common",lbp:n,loadCondition:t,draught:o,breadthMoulded:e,displacement:Math.round((r/1.025+o*e*n*.7)*1e4)/1e4,speed:Math.round((a??14.1382)*1852/3600*1e4)/1e4,bearing:i||90}}static async speedLoseAt(s,t,a,i="",n=2,o=!0,e=!1,r={}){let d;if(t.velocity&&e&&(s.speed=N.LngLatHelper.roundPrecision(t.velocity*1852/3600,6)),o){let l;try{i=(i==null?void 0:i.toUpperCase())==="CMEMS"?"ECMWF":i,i=(i==null?void 0:i.toUpperCase())==="METEO2"?"best_match":i;const{weatherModels:M,marineModels:C}=await nt.Meteo2Assist.autoPickMeteoModel(i),S=await vt.spotForecast(t.lat,t.lng,a.utc().format(),!1,!1,!0,{...r,pastDays:1,forecastDays:1,weatherModels:M,marineModels:C}),[w]=nt.Meteo2Assist.pickHourly(S,a);l=nt.Meteo2Assist.toLegacy(w)}catch(M){I.warn("[%s] meteo2 spot(%j) forecast failed: %s",r.requestId,{...t,eta:a.utc().format(),source:i},M)}const u=W.currentFactor(s.bearing,l==null?void 0:l.current,n),y=W.weatherFactor(s,l,u),v=Math.round(s.speed*1.943844*100)/100;d={meteo:{...l},wxFactor:y,cFactor:u,speed:t.velocity&&e?t.velocity:v<0?1:v,eta:a.utc().format(),etd:a.utc().format()}}else d={wxFactor:0,cFactor:0,speed:t.velocity&&e?t.velocity:Math.round(s.speed*1.943844*100)/100,eta:a.utc().format(),etd:a.utc().format()};return delete t.meteo,delete t.wxFactor,delete t.cFactor,delete t.speed,delete t.etd,{...d,...t}}static async speedLoseInHoursStep(s,t,a,i,n,o,e="",r=!0,d=!1,l={}){t.utc();const u=t.clone().add(14,"days"),y=[],v=[];let M=0,C=0,S,w;for(let b=0;b<o.length-1;b++){let c=o[b];c.distanceFromStart=Math.round((n+C)*1e3)/1e3;const p=o[b+1];if(s.bearing=N.LaneHelper.calculateBearing(c,p,!p.gcToPrevious),c.bearing=s.bearing,c.suspend&&d){c.eta=c.eta||t.utc().format(),c.elapsed=c.elapsed??0;const k=c.suspend-c.elapsed;if(i-M>k)i=i-M-k,t.add(k,"hour"),c.elapsed=c.suspend;else{const j=i-M;c.elapsed+=j,t.add(j,"hour"),i=0}if(I==null||I.info(`[%s] suspend ${c.elapsed} hours at %j, and remain ${i} hours need to go...`,l.requestId,c),i===0)return c.distanceFromPrevious=C,{etd:t,from:w||c,to:c,next:o.filter(j=>j),wps:y,days:v}}else c.suspend=0;r=t.isAfter(u)?!1:r,c=await W.speedLoseAt(s,c,t,e,0,r,d,l),w=w||c,c.important&&y.push(c),t.isSameOrAfter(a)&&(v.push(c),a.add(24,"hour"));const f=N.LaneHelper.calculateDistance(c,p,!p.gcToPrevious);let h=Math.round(f/w.speed*1e5)/1e5;if(M+h<i){if(M+=h,t.add(h,"hour"),delete o[b],I==null||I.debug(`[%s] go to %j from %j with ${f}nm, and cost ${h} hours`,l.requestId,{lat:p.lat,lng:p.lng},{lat:w.lat,lng:w.lng,etd:w.etd}),C+=f,o.filter(k=>k).length<=1){S=p,S.eta=t.utc().format(),S.distanceFromPrevious=f,S.distanceFromStart=Math.round((n+C)*1e4)/1e4,y.push(S),delete o[b+1];break}}else{h=i-M,t.add(h,"hour");const k=N.LngLatHelper.roundPrecision(w.speed*h,5);S=N.LaneHelper.calculateCoordinate(c,s.bearing,k,"nauticalmiles",!p.gcToPrevious),S.eta=t.utc().format(),o[b]=S,I==null||I.debug(`[%s] go to %j from %j with ${k}nm, and cost ${h} hours`,l.requestId,{lat:S.lat,lng:S.lng},{lat:c.lat,lng:c.lng,etd:c.etd}),C+=k,S.distanceFromPrevious=Math.round(C*1e4)/1e4,S.distanceFromStart=Math.round((n+C)*1e4)/1e4;break}}return{etd:t,from:w,to:S,next:o.filter(b=>b),wps:y,days:v}}static currentFactor(s,t,a=0){const i=(s-(t==null?void 0:t.degree)||0)/180*Math.PI;if(Math.abs(i)===Math.PI/2)return 0;let n=((t==null?void 0:t.kts)||0)*Math.cos(i);return a&2?n=Math.ceil(n*100)/100:a&1?n=Math.floor(n*100)/100:n=Math.round(n*100)/100,Math.abs(n)>5?0:n}static weatherFactor(s,t,a=0){var v,M,C,S,w,b,c;I==null||I.debug("calculate weather factor via: %j",{...s,...t});const i=W.blockCoefficient(s.displacement,s.lbp,s.breadthMoulded,s.draught),n=N.LngLatHelper.roundPrecision(a*1852/3600,6),o=W.froudeNumber(s.speed-n,s.lbp),e=W.amendFactor(i,o,s.loadCondition);let r=Math.abs(s.bearing%360-(((v=t==null?void 0:t.wind)==null?void 0:v.degree)%360||0));r=r>180?360-r:r;const d=W.directionFactor(r,(M=t==null?void 0:t.wind)==null?void 0:M.scale),l=W.vesselTagFactor(s.displacement,s.loadCondition,s.tag,(C=t==null?void 0:t.wind)==null?void 0:C.kts);let u=d*e*l/100*(s.speed-n);u=Math.round(u*1.943844*1e4)/1e4,s.tag==="tugs"&&Math.abs(u)>1&&(u=u/(Math.abs(Math.round(u))+1)),I==null||I.debug("wind wx factor = %d",u),r=Math.abs(s.bearing%360-(((w=(S=t==null?void 0:t.wave)==null?void 0:S.sig)==null?void 0:w.degree)%360||0)),r=r>180?360-r:r;const y=W.waveHeightFactor(((c=(b=t==null?void 0:t.wave)==null?void 0:b.sig)==null?void 0:c.height)??1,r);return I==null||I.debug("wave wx factor = %d",y),u=Math.abs(u)>Math.abs(y)?u:u*.3+y*.7,I==null||I.debug("weather factor = %d",u),u=Math.abs(u)>3?3*(Math.abs(u)/u)+Math.abs(u)/u*(Math.abs(u)-2)*.1:u,Math.round((u||0)*100)/100}static async analyseInstant(s,t,a,i,n,o="",e=0,r=!0,d=!1,l={}){var X,Q,Z,$,tt,et;const u=g().valueOf();s.lng=N.LngLatHelper.convertToStdLng(s.lng);const{route:y,waypoints:v}=n.points,M=N.LaneHelper.calculateSubRoute(s,y);if(((X=M[0])==null?void 0:X.length)<=1)return;const{v0:C,label:S}=s.sog?{v0:s.sog,label:s.label||"Other"}:{v0:i.speed,label:"CP"},w=W.assembleProperties(a,i.loadCondition,C,0),b=v.length?N.LaneHelper.calculateSubWaypoints(s,v):[];b.forEach(O=>O.important=!0);const c={from:{...s},route:M,waypoints:b,v0:C,label:S},p={hours:[],days:[],wps:[]};e||(N.LaneHelper.calculateRouteDistance(M)/i.speed<=72?e=3:e=6);let f=N.LaneHelper.simplifyRouteToCoordinates(M,b,0),h=0,k=0,j=0,x=0;t=g(t).utc();const Y=t.clone();for(;f.length>0;){const O=e-t.hour()%e,z=Math.ceil(t.clone().add(O,"h").set({minute:0,second:0,millisecond:0}).diff(t,"h",!0)*1e4)/1e4,T=await W.speedLoseInHoursStep(w,t,Y,z,h,f,o,r,d,l);if((Q=T.from)!=null&&Q.speed&&(p.hours.push(T.from),p.wps.push(...T.wps),p.days.push(...T.days)),f=T==null?void 0:T.next,!f.length){const B=await W.speedLoseAt(w,T.to,g(T.to.eta),o,0,r,d,l);p.hours.push(B)}h+=Math.round((((Z=T==null?void 0:T.to)==null?void 0:Z.distanceFromPrevious)??0)*1e4)/1e4}const F=p.hours;for(let O=0;O<F.length-1;O++){const z=g(F[O+1].eta).diff(F[O].etd,"hour",!0)||1;k+=(F[O].wxFactor||0)*z,j+=(F[O].cFactor||0)*z,x+=z}($=p.wps)==null||$.forEach((O,z)=>{O.positionTime=g.utc(O.etd||O.eta).unix();const T=p.wps[z-1];if(T){const B=O.distanceFromStart-T.distanceFromStart,R=g(O.eta||O.etd).diff(g(T.etd||T.eta),"h",!0);O.avgSpd=Math.round(B/R*100)/100,T.bearing=N.LaneHelper.calculateBearing(T,O)}}),p.wps=(tt=p.wps)==null?void 0:tt.reduce((O,z)=>(O.some(T=>Math.round(T.positionTime/60)===Math.round(z.positionTime/60))||O.push(z),O),[]),c.sample=p;const L=p.hours.at(0),H=p.hours.at(-1);c.distance=Math.round(H.distanceFromStart*1e3)/1e3,c.etd=g(L.eta).utc().format(),c.eta=g(H.eta).utc().format(),c.wxFactor=Math.round(k/x*1e3)/1e3,c.cFactor=Math.round(j/x*1e3)/1e3,c.avgSpeed=Math.round(H.distanceFromStart/x*1e3)/1e3,c.totalHrs=Math.round(x*1e3)/1e3;const{distanceInECA:E,hoursInECA:P,totalDgoConsInECA:V,eca:J}=await this.calculateECA(c,i,l),st=N.LngLatHelper.roundPrecision(i.fo/24*(x-P),3),ot=N.LngLatHelper.roundPrecision(i.dgo/24*x,3);c.extend={eca:J,distanceInECA:E,hoursInECA:P,totalDgoConsInECA:V},c.totalFoCons=st<0?0:st,c.totalDgoCons=ot;const at=g().valueOf()-u,rt=((et=p==null?void 0:p.hours)==null?void 0:et.length)||1;return I==null||I.info("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms",l==null?void 0:l.requestId,at,rt,Math.round(at/rt*1e3)/1e3),c}static async analyseInstantWithThreshed(s,t,a,i,n,o,e,r="",d=3,l=!0,u=!1,y={}){var Z,$,tt,et,O,z;const v=g().valueOf();s.lng=N.LngLatHelper.convertToStdLng(s.lng);const{v0:M,label:C}=s.sog?{v0:s.sog,label:s.label||"Other"}:{v0:n.speed,label:"CP"},S=W.assembleProperties(i,n.loadCondition,M,0),w=N.LaneHelper.calculateSubRoute(s,o);if(((Z=w[0])==null?void 0:Z.length)<=1)return;const b=e.length?N.LaneHelper.calculateSubWaypoints(s,e):[];b.forEach(T=>T.important=!0);let c=N.LaneHelper.simplifyRouteToCoordinates(w,b,0),p=0,f=0,h=0,k=0;const j={hours:[],wps:[],days:[]};t=g(t).utc();const x=t.clone();for(;c.length>0;){const T=d-t.hour()%d;let B=Math.ceil(t.clone().add(T,"h").set({minute:0,second:0,millisecond:0}).diff(t,"h",!0)*1e4)/1e4;B=t.clone().add(B,"h").isSameOrAfter(a)?a.diff(t,"h",!0)*1e4/1e4:B;const R=await W.speedLoseInHoursStep(S,t,x,B,p,c,r,l,u,y);if(($=R.from)!=null&&$.speed&&(j.hours.push(R.from),R!=null&&R.wps&&j.wps.push(...R.wps),j.days.push(...R.days)),c=R==null?void 0:R.next,c.length||j.hours.push(R==null?void 0:R.to),p+=Math.round((((tt=R==null?void 0:R.to)==null?void 0:tt.distanceFromPrevious)??0)*1e4)/1e4,!B)break}j.wps=(et=j.wps)==null?void 0:et.reduce((T,B)=>(T.some(R=>Math.round(g(R.etd).unix()/60)===Math.round(g(B.etd).unix()/60))||T.push(B),T),[]),(O=j.wps)==null||O.forEach((T,B)=>{const R=j.wps[B-1];if(R){const gt=T.distanceFromStart-R.distanceFromStart,wt=g(T.eta||T.etd).diff(g(R.etd||R.eta),"h",!0);T.avgSpd=Math.round(gt/wt*100)/100;const kt=N.LaneHelper.calculateBearing(R,T);R.bearing=kt}});const Y=j.hours;for(let T=0;T<Y.length-1;T++){const B=g(Y[T+1].eta).diff(Y[T].etd,"hour",!0);f+=Y[T].wxFactor*B,h+=Y[T].cFactor*B,k+=B}const F=j.hours.at(0),L=j.hours.at(-1),H=await N.LaneHelper.calculateRangeRoute(F,L,w),E=await N.LaneHelper.calculateRangeWaypoints(F,L,w,b),P={sample:j,distance:Math.round(((L==null?void 0:L.distanceFromStart)||0)*1e4)/1e4,etd:g(F.eta).utc().format(),eta:g(L==null?void 0:L.eta).utc().format(),wxFactor:Math.round(f/k*1e3)/1e3,cFactor:Math.round(h/k*1e3)/1e3,avgSpeed:Math.round(((L==null?void 0:L.distanceFromStart)||0)/k*1e3)/1e3,totalHrs:Math.round(k*1e3)/1e3,from:F,to:L,route:H,waypoints:E,v0:M,label:C},{distanceInECA:V,hoursInECA:J,totalDgoConsInECA:st,eca:ot}=await this.calculateECA(P,n,y),it=N.LngLatHelper.roundPrecision(n.fo/24*(k-J),3),at=N.LngLatHelper.roundPrecision(n.dgo/24*k,3);P.extend={eca:ot,distanceInECA:V,hoursInECA:J,totalDgoConsInECA:st},P.totalDgoCons=at,P.totalFoCons=it<0?0:it;const X=g().valueOf()-v,Q=((z=j==null?void 0:j.hours)==null?void 0:z.length)||1;return I==null||I.debug("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms",y==null?void 0:y.requestId,X,Q,Math.round(X/Q*1e3)/1e3),P}static async analyseCost(s,t,a,i,n={}){var w,b;const o=g().valueOf(),e=[];s.speedStep=s.speedStep||3,s.alterStep=s.alterStep??1;const r=N.LaneHelper.calculateRouteDistance(i.route);let d=0;a.forEach(c=>{const p=Math.ceil(r/c.speed/24);d=d<p?p:d}),d=d*1.3;const l=g.utc(s.etd).add(d??14,"day");let u=1;for(const c of a){const p=JSON.parse(JSON.stringify(i.route)),f=JSON.parse(JSON.stringify(i.waypoints)),h=await W.analyseInstantWithThreshed({lat:s.lat,lng:s.lng},s.etd,l,t,c,p,f,s.meteoVendor,s.speedStep,s.useMeteo,s.useRouteParam,n);h&&(await W.calculateCost(h,c,s,n),e.push(h),I==null||I.info("[%s][L%d-%d] analyse from %s to %s cost: %j",n.requestId,1,u,s.etd,l.format(),{cost:h.cost.total,hire:h.cost.hire,bunker:h.cost.bunker,distance:h.distance,hours:h.totalHrs,cp:`${c.speed}/${c.fo}/${c.dgo}`})),u++}e.sort((c,p)=>c.cost.total-p.cost.total);const y=e.at(0),v=e.at(1),M=[];if(M.push({combined:!1,speeds:[y],cost:(w=y.cost)==null?void 0:w.total}),v){const c=y.cost.cp,p=v.cost.cp,f=g(y.eta),h=g(y.etd),k=f.diff(h,"days",!0);let j=Math.ceil(k/2);j=j>7?7:j<s.alterStep?s.alterStep:j;let x=2,Y={combined:!1,speeds:[v],cost:(b=v.cost)==null?void 0:b.total},F;for(;j>=s.alterStep;){const L=await W.combinedAnalyse(s,t,l,[c,p],i,j,{...n,level:x});if(Y.cost>L.cost?F?(F==null?void 0:F.cost)>L.cost&&(F=L):(F=Y,Y=L):(!F||(F==null?void 0:F.cost)>L.cost)&&(F=L),j<=s.alterStep)break;j=Math.ceil(j/2),x+=1}M.push(Y),F&&M.push(F)}const S=g().valueOf()-o;return I==null||I.info("[%s] analyse elapsed: %d ms",n==null?void 0:n.requestId,S),M.sort((c,p)=>c.cost-p.cost)}static async combinedAnalyse(s,t,a,i,n,o,e={}){e.counter=1,I==null||I.info("[%s][L%d] analyse with alternate cp in every %d days",e.requestId,e.level,o);const r=await W.alternateAnalyse(s,t,a,i,0,n,o,e),d=r.reduce((p,f)=>p+f.cost.total,0),l=r.reduce((p,f)=>p+f.cost.hire,0),u=r.reduce((p,f)=>p+f.cost.bunker,0),y=r.reduce((p,f)=>p+f.distance,0),v=r.reduce((p,f)=>p+f.totalHrs,0);I==null||I.info("[%s][L%d] cost with cpa/cpb turn: %j",e.requestId,e.level,{cost:d,hire:l,bunker:u,distance:y,hours:v});const M=await W.alternateAnalyse(s,t,a,i,1,n,o,e),C=M.reduce((p,f)=>p+f.cost.total,0),S=M.reduce((p,f)=>p+f.cost.hire,0),w=M.reduce((p,f)=>p+f.cost.bunker,0),b=M.reduce((p,f)=>p+f.distance,0),c=M.reduce((p,f)=>p+f.totalHrs,0);return I==null||I.info("[%s][L%d] cost with cpb/cpa turn: %j",e.requestId,e.level,{cost:C,hire:S,bunker:w,distance:b,hours:c}),d<C?{combined:!0,cost:Math.round(d*1e3)/1e3,speeds:r,step:o}:{combined:!0,cost:Math.round(C*1e3)/1e3,speeds:M,step:o}}static async alternateAnalyse(s,t,a,i,n,o,e,r={}){var y,v;let d=g.utc(s.etd);const l={lat:s.lat,lng:s.lng},u=[];for(;d.isBefore(a);){const M=d.clone().utc().add(e,"day"),C=JSON.parse(JSON.stringify(o.route)),S=JSON.parse(JSON.stringify(o.waypoints)),w=i[n],b=await W.analyseInstantWithThreshed(l,d.utc().format(),M,t,w,C,S,s.meteoVendor,s.speedStep,s.useMeteo,s.useRouteParam,r);b&&(await W.calculateCost(b,w,s,r),I==null||I.info("[%s][L%d-%d] analyse from %s to %s cost: %j",r.requestId,r.level,r.counter,d.utc().format(),M.utc().format(),{cost:b.cost.total,hire:b.cost.hire,bunker:b.cost.bunker,distance:b.distance,hours:b.totalHrs,cp:`${w.speed}/${w.fo}/${w.dgo}`})),r.counter=r.counter+1;const c=(v=(y=b==null?void 0:b.sample)==null?void 0:y.hours)==null?void 0:v.at(-1);if(c)l.lat=c.lat,l.lng=c.lng,d=g(c.eta),u.push(b),n=n?0:1;else break}return u}static async calculateCost(s,t,a,i={}){var n;if(s){const o=(a.addComm||0)>=1?(a.addComm||0)/100:a.addComm||0,e=Math.round(s.totalHrs/24*(a.dailyHire||0)*(1-o)*1e3)/1e3,r=Math.round(s.totalFoCons*(a.priceFO||0)*1e3)/1e3,d=Math.round((s.totalDgoCons+(((n=s.extend)==null?void 0:n.totalDgoConsInECA)||0))*(a.priceDGO||0)*1e3)/1e3;s.cost={total:Math.round((e+r+d)*1e3)/1e3,hire:e,bunker:Math.round((r+d)*1e3)/1e3,cp:t}}return s}static async calculateECA(s,t,a={}){var r,d,l,u;const i=await N.LaneHelper.intersectInECA((s==null?void 0:s.route)||[]);let n=0,o=0,e=0;(d=(r=s==null?void 0:s.sample)==null?void 0:r.wps)==null||d.forEach(y=>{y.positionTime=g.utc(y.etd||y.eta).unix()});for(const y of i){n+=y.distance;const v=await N.LaneHelper.deadReckoningTime((l=y.waypoints)==null?void 0:l.at(0),s.sample.wps),M=await N.LaneHelper.deadReckoningTime((u=y.waypoints)==null?void 0:u.at(-1),s.sample.wps);y.in=v,y.out=M,y.totalHrs=N.LngLatHelper.roundPrecision((M.positionTime-v.positionTime)/3600,3),y.totalDgoCons=N.LngLatHelper.roundPrecision(t.fo/24*y.totalHrs,3),o+=y.totalHrs,e+=y.totalDgoCons}return n=N.LngLatHelper.roundPrecision(n,3),o=N.LngLatHelper.roundPrecision(o,3),e=N.LngLatHelper.roundPrecision(e,3),{distanceInECA:n,hoursInECA:o,totalDgoConsInECA:e,eca:i}}static async mergeSpeeds(s,t={}){var c,p;const a={hours:[],wps:[],days:[]},i=s.reduce((f,h)=>f+h.distance,0),n=s.reduce((f,h)=>{var k;return f+(((k=h.extend)==null?void 0:k.distanceInECA)||0)},0),o=s.reduce((f,h)=>f+h.totalHrs,0),e=s.reduce((f,h)=>{var k;return f+(((k=h.extend)==null?void 0:k.hoursInECA)||0)},0),r=s.reduce((f,h)=>{var k;return f+(((k=h.extend)==null?void 0:k.totalDgoConsInECA)||0)},0),d=s.reduce((f,h)=>f+h.wxFactor*h.totalHrs/o,0),l=s.reduce((f,h)=>f+h.cFactor*h.totalHrs/o,0),u=s.reduce((f,h)=>f+h.totalFoCons,0),y=s.reduce((f,h)=>f+h.totalDgoCons,0),v=s.reduce((f,h)=>f+h.cost.total,0),M=s.reduce((f,h)=>f+h.cost.hire,0),C=s.reduce((f,h)=>f+h.cost.bunker,0),S=[],w=[];let b;for(const f of s){w.push(...((c=f.extend)==null?void 0:c.eca)||[]);const h=f.sample.hours,k=f.sample.wps,j=f.sample.days,x=h.at(0);b&&(x.distanceFromPrevious=b.distanceFromPrevious,x.distanceFromStart=b.distanceFromStart,h.forEach((H,E)=>{E&&(H.distanceFromStart=H.distanceFromStart+b.distanceFromStart)}),k.at(0).distanceFromPrevious=b.distanceFromPrevious,k.at(0).distanceFromStart=b.distanceFromStart,k.forEach((H,E)=>{E&&(H.distanceFromStart=H.distanceFromStart+b.distanceFromStart)}),j.at(0).distanceFromPrevious=b.distanceFromPrevious,j.at(0).distanceFromStart=b.distanceFromStart,j.forEach((H,E)=>{E&&(H.distanceFromStart=H.distanceFromStart+b.distanceFromStart)})),x.cp=f.cost.cp;const Y=[f.etd,f.eta],F=S.findIndex(H=>H.id===x.cp.id);F===-1?(x.cp.segment=[Y],S.push(x.cp)):S[F].segment.push(Y),h.forEach(H=>{var P;((P=a.hours)==null?void 0:P.findIndex(V=>V.eta===H.eta))===-1&&a.hours.push(H)}),k.forEach(H=>{var P;((P=a.wps)==null?void 0:P.findIndex(V=>V.eta===H.eta))===-1&&a.wps.push(H)}),j.forEach(H=>{var P;((P=a==null?void 0:a.days)==null?void 0:P.findIndex(V=>V.eta===H.eta))===-1&&a.days.push(H)});const L=(p=a.wps)==null?void 0:p.findIndex(H=>H.eta===x.eta);L===-1?a.wps.push(x):a.wps[L]=x,b=h.at(-1)}return a.wps.sort((f,h)=>{g(f.etd).unix()-g(h.etd).unix()}),a.wps.forEach((f,h)=>{const k=a.wps[h-1];if(k){const j=f.distanceFromStart-(k.distanceFromStart||0),x=g(f.eta||f.etd).diff(g(k.etd||k.eta),"hour",!0),Y=Math.round(j/x*100)/100;f.avgSpd=Y;const F=N.LaneHelper.calculateBearing(k,f);k.bearing=F}}),{sample:a,etd:s.at(0).etd,eta:s.at(-1).eta,from:s.at(0).from,to:s.at(-1).to,v0:s.at(0).v0,label:"Combined",distance:Math.round(i*1e3)/1e3,totalHrs:Math.round(o*1e3)/1e3,avgSpeed:Math.round(i/o*1e3)/1e3,wxFactor:Math.round(d*1e3)/1e3,cFactor:Math.round(l*1e3)/1e3,totalFoCons:Math.round(u*1e3)/1e3,totalDgoCons:Math.round(y*1e3)/1e3,cost:{total:Math.round(v*1e3)/1e3,hire:Math.round(M*1e3)/1e3,bunker:Math.round(C*1e3)/1e3},extend:{cps:S,eca:w,distanceInECA:Math.round(n*1e3)/1e3,hoursInECA:Math.round(e*1e3)/1e3,totalDgoConsInECA:Math.round(r*1e3)/1e3,speeds:s}}}}q.AISImpl=G,q.AlertHelper=dt,q.AlertLevel=ct,q.HifleetImpl=yt,q.LoadCondition=lt,q.MyShipImpl=pt,q.MyVesselImpl=mt,q.ShipxyImpl=Mt,q.SpeedHelper=W,q.SpeedLabel=ht,q.VesselTag=ut,q.alertHelper=bt,Object.defineProperty(q,Symbol.toStringTag,{value:"Module"})});
|
|
1
|
+
(function(q,A){typeof exports=="object"&&typeof module<"u"?A(exports,require("got"),require("@log4js-node/log4js-api"),require("moment"),require("@idm-plugin/geo2"),require("@idm-plugin/meteo2"),require("@idm-plugin/meteo")):typeof define=="function"&&define.amd?define(["exports","got","@log4js-node/log4js-api","moment","@idm-plugin/geo2","@idm-plugin/meteo2","@idm-plugin/meteo"],A):(q=typeof globalThis<"u"?globalThis:q||self,A(q["idm-plugin-vessel"]={},q.got,q["@log4js-node/log4js-api"],q.moment,q["@idm-plugin/geo2"],q["@idm-plugin/meteo2"],q["@idm-plugin/meteo"]))})(this,function(q,A,U,g,N,ft,nt){"use strict";var It=Object.defineProperty;var St=(q,A,U)=>A in q?It(q,A,{enumerable:!0,configurable:!0,writable:!0,value:U}):q[A]=U;var K=(q,A,U)=>(St(q,typeof A!="symbol"?A+"":A,U),U);let m;try{m=U.getLogger("vessel")}catch{}finally{}class G{parseStatus(s){let t,a;switch(s){case 0:t="在航(主机推动)",a="Underway Using Engine";break;case 1:t="锚泊",a="Anchored";break;case 2:t="失控",a="Not under command";break;case 3:t="操纵受限",a="Limited airworthiness";break;case 4:t="吃水受限",a="Limited by ship's draft";break;case 5:t="靠泊",a="Mooring";break;case 6:t="搁浅",a="Stranded";break;case 7:t="捕捞作业",a="Engaged in fishing";break;case 8:t="靠帆船提供动力",a="Sailing";break;default:t="未定义",a="Undefined"}return{labelCn:t,labelEn:a}}}class mt extends G{constructor(t,a){super();K(this,"clientId");K(this,"clientSecret");K(this,"token");this.clientId=t,this.clientSecret=a}async authToken(t={}){const a="https://svc.data.myvessel.cn/ada/oauth/token",i={searchParams:{client_id:this.clientId,client_secret:this.clientSecret,grant_type:"client_credentials"}},n=await A.post(a,i).json();m==null||m.info("[%s] fetch access token from: %s - %j",t.requestId,a,n),n.error||(this.token={accessToken:n.access_token,tokenType:n.token_type,expiresIn:n.expires_in,scope:n.scope,jti:n.jti,issuedAt:g().utc().format()})}async checkToken(t={}){var a;return(!this.token||g().diff(g(this.token.issuedAt),"seconds")>(((a=this.token)==null?void 0:a.expiresIn)||0)-300)&&await this.authToken(t),this.token}async suggest(t,a={}){var e,r;await this.checkToken(a);const i="https://market.myvessel.cn/sdc/v1/mkt/vessels/fuzzy",n={headers:{Authorization:`${(e=this.token)==null?void 0:e.tokenType} ${(r=this.token)==null?void 0:r.accessToken}`},json:{kw:t,recordNum:a.ps||10}};m==null||m.info("[%s] fetch suggest vessels from: %s - %j",a.requestId,i,n);const o=await A.post(i,n).json();return o.status!==200?(m==null||m.warn("[%s] fetch suggest vessels failed: %j",a.requestId,{message:o.message,status:o.status,code:o.code}),[]):(o.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,a={}){var u,l;await this.checkToken(a);const i=/^\d{7}$/.test(t.toString()),n=i?"https://market.myvessel.cn/sdc/v1/mkt/vessels/detail/imo":"https://market.myvessel.cn/sdc/v1/mkt/vessels/detail/mmsi",o=i?{imo:t}:{mmsi:t},e={headers:{Authorization:`${(u=this.token)==null?void 0:u.tokenType} ${(l=this.token)==null?void 0:l.accessToken}`},searchParams:o};m==null||m.info("[%s] fetch vessel from: %s - %j",a.requestId,n,e);const r=await A.get(n,e).json();if(r.status!==200)return m==null||m.warn("[%s] fetch suggest vessels failed: %j",a.requestId,{message:r.message,status:r.status,code:r.code}),{};{const d=r.data;if(d)return{mmsi:d.mmsi,imo:Number.isNaN(d.imo)?null:Number(d.imo),callSign:d.callsign,name:d.nameEn,nameCn:d.nameCn,type:d.vesselTypeNameEn,flagName:d.flagCtry,clasz:d.classSociety,dateOfBuild:d.buildYearMonth,deadweight:d.dwt,grossTonnage:d.grt,netTonnage:d.net,teu:d.teu,length:d.length,breadth:d.width,height:d.height,draught:d.draught,speed:d.speed,passengerCapacity:d.passengercapacity,vendor:"myvessel",raw:d}}return{}}async archives(t,a={}){var e,r;await this.checkToken(a);const i="https://svc.data.myvessel.cn/sdc/v1/ship/info/batch",n={headers:{Authorization:`${(e=this.token)==null?void 0:e.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",a.requestId,i,n);const o=await A.post(i,n).json();return o.status!==200?(m==null||m.warn("[%s] fetch vessel archive failed: %j",a.requestId,{message:o.message,status:o.status,code:o.code}),{}):o.data}async realTimePosition(t,a={}){var r,u;await this.checkToken(a);const i="https://svc.data.myvessel.cn/sdc/v1/vessels/status/location/unit",n={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",a.requestId,i,n);const o=await A.get(i,n).json();if(o.code)return m==null||m.warn("[%s] fetch realtime position failed: %j",a.requestId,{message:o.message,status:o.status,code:o.code}),o;const e=o.data;for(const l in e)!isNaN(e[l])&&Number(e[l])!==1/0&&(e[l]=Number(e[l]));if(e){const l=g(`${e.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return{mmsi:e.mmsi,name:e.vesselName||e.aisVesselName,imo:e.imo,callSign:e.callsign||e.aisCallSign,lat:e.lat,lng:e.lon,length:e.length,width:e.width,draught:e.currDraught,sog:e.sog,cog:e.cog,hdg:e.hdg,rot:e.rot,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(e.eta)?g.utc(e.eta).format():void 0,destination:e.dest,positionTime:l.unix(),status:e.status,labelCn:e.statusNameCn,labelEn:e.statusNameEn,vesselType:e.vesselTypeNameEn,flag:e.flagCtryNameEn,clasz:e.classSociety,build:e.buildYear,dwt:e.dwt,grt:e.grt,net:e.net,method:"position",vendor:"myVessel",utc:l.utc().format()}}else return{}}async calculateRoute(t,a,i={}){var r,u;await this.checkToken(i);const n="https://svc.data.myvessel.cn/sdc/v1/routes/routing/nodes",o={headers:{Authorization:`${(r=this.token)==null?void 0:r.tokenType} ${(u=this.token)==null?void 0:u.accessToken}`},json:{startPoint:{lon:t.lng,lat:t.lat},endPoint:{lon:a.lng,lat:a.lat},maxDraught:i.maxDraught||10,useAIModel:i.useAIModel||!1,withECA:i.withECA||!1}};m==null||m.info("[%s] fetch route from: %s - %j",i.requestId,n,o);const e=await A.post(n,o).json();return e.status!==200?(m==null||m.warn("[%s] fetch route failed: %j",i.requestId,{message:e.message,status:e.status,code:e.code}),{}):e.data}async trajectory(t,a,i,n,o=!0,e={}){await this.checkToken(e);const r=await this.realTimePosition(t,e),u=g(a),l=g(i),d=[];for(;l.diff(u,"day",!0)>30;)await this.trajectoryIn30Day(t,u,u.clone().add(30,"day"),r,n,d,e),u.add(30,"day");return await this.trajectoryIn30Day(t,u,l,r,n,d,e),d}async trajectoryIn30Day(t,a,i,n,o,e,r={}){var M,C,S,w,b;const u="https://svc.data.myvessel.cn/sdc/v1/vessels/status/track",l={headers:{Authorization:`${(M=this.token)==null?void 0:M.tokenType} ${(C=this.token)==null?void 0:C.accessToken}`},json:{mmsi:t,startTime:a.utcOffset(8).format("YYYY-MM-DD HH:mm:ss"),endTime:i.utcOffset(8).format("YYYY-MM-DD HH:mm:ss")}};m==null||m.info("[%s] fetch trajectory from: %s - %j",r.requestId,u,l);const d=await A.post(u,l).json();if(d.code)return m==null||m.warn("[%s] fetch trajectory failed: %j",r.requestId,u,{message:d.message,status:d.status,code:d.code}),d;let y=-1;const v=g(`${(w=(S=d.data)==null?void 0:S[0])==null?void 0:w.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return(b=d.data)==null||b.forEach(c=>{for(const Y in c)!isNaN(c[Y])&&Number(c[Y])!==1/0&&(c[Y]=Number(c[Y]));const p=g(`${c.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00"),f=c.status,{labelCn:h,labelEn:k}=this.parseStatus(f),j={mmsi:c.mmsi,imo:n==null?void 0:n.imo,lat:c.lat,lng:c.lon,sog:c.sog,cog:c.cog,hdg:c.hdg,draught:c.draught,status:f,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(c.eta)?g(`${c.eta} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00").utc().format():void 0,destination:c.dest,positionTime:p.unix(),labelCn:h,labelEn:k,method:"trajectory",vendor:"myVessel",utc:p.utc().format()},x=Math.floor(p.diff(v,"minute",!0)/(o||1));x!==y&&(y=x,e.push(j))}),e}}class yt extends G{constructor(t){super();K(this,"token");this.token=t}async realTimePosition(t,a={}){const i="https://api.hifleet.com/position/position/get/token",n={searchParams:{mmsi:t,usertoken:this.token}},o=await A.post(i,n).json();m==null||m.info("[%s] fetch realtime position from: %s - %j",a.requestId,i,n);const e=o==null?void 0:o.list;if(!e)return m==null||m.warn("[%s] fetch realtime position failed: %j",a.requestId,i,o),o;for(const v in e)!isNaN(e[v])&&Number(e[v])!==1/0&&(e[v]=Number(e[v]));e.status=e.sp>3?0:1;const r=e.status,{labelCn:u,labelEn:l}=this.parseStatus(r),d=g(`${e.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return{mmsi:e.m,name:e.n,imo:e.imonumber,callSign:e.callsign,lat:Math.round(e.la/60*1e5)/1e5,lng:Math.round(e.lo/60*1e5)/1e5,length:e.l,width:e.w,draught:e.draught,sog:e.sp,cog:e.co,hdg:e.h,rot:isNaN(e.rot)?0:e.rot,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(e.eta)?g.utc(e.eta).format():void 0,destination:e.destination,vesselType:e.type,dwt:e.dwt,build:e.buildyear,flag:e.fn,positionTime:d.unix(),utc:d.utc().format(),status:r,labelCn:u,labelEn:l,method:"position",vendor:"hifleet"}}async search(t,a={}){let i="https://www.hifleet.com/hifleetapi/searchVesselOL.do";const n={searchParams:{keyword:t},headers:{Referer:"https://www.hifleet.com",Origin:"https://www.hifleet.com",Host:"www.hifleet.com"}};let o=await A.post(i,n).json();m==null||m.info("[%s] fetch vessel props from: %s - %j",a.requestId,i,n),o instanceof Array&&(o=o[0]);for(const r in o)!isNaN(o[r])&&Number(o[r])!==1/0&&(o[r]=Number(o[r]));const e={mmsi:o.m,name:o.n,imo:o.i,callSign:o.c,length:o.l,breadth:o.b,draught:o.dr,type:o.t};return i="https://www.hifleet.com/hifleetapi/sameShipSearch.do",o=await A.post(i,n).json(),m==null||m.info("[%s] search vessel dead weight from: %s - %j",a.requestId,i,n),o instanceof Array&&(o=o[0]),o&&(e.deadweight=Number(o.dwt)),e}async suggest(t,a={}){const i="https://www.hifleet.com/hifleetapi/getShipSuggest.do",n={searchParams:{q:t},headers:{Referer:"https://www.hifleet.com",Origin:"https://www.hifleet.com",Host:"www.hifleet.com"}},o=await A.post(i,n).json();m==null||m.info("[%s] suggest vessel props from: %s - %j",a.requestId,i,n);const e=[];for(const r of o)e.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 e.sort((r,u)=>u.score-r.score),e}async trajectory(t,a,i,n,o=!0,e={}){var c,p,f;const r=await this.realTimePosition(t,e);let u=g(a);const l=g(i),d=g();if(o){let h=l.diff(u,"d",!0);h<0?u=l.clone().subtract(40,"d"):h<30?u.subtract(10,"d"):h<60?u.subtract(5,"d"):u=l.clone().subtract(80,"d"),h=d.diff(l,"d",!0),l.add(h>10?240:h*24,"h")}const y={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}},v="https://api.hifleet.com/position/trajectory/nocompressed/withstatic/token",M=await A.get(v,y).json();m==null||m.info("[%s] fetch trajectory from: %s - %j",e.requestId,v,y);let C;M&&(C=((p=(c=M.ships)==null?void 0:c.offors)==null?void 0:p.ship)||[],C.length||m==null||m.warn("[%s] fetch trajectory failed: %j",e.requestId,M));const S=[];let w=-1;const b=g(`${(f=C==null?void 0:C[0])==null?void 0:f.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");for(const h of C){for(const L in h)!isNaN(h[L])&&Number(h[L])!==1/0&&(h[L]=Number(h[L]));const k=g(`${h.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");h.status=h.sp>4?0:1;const{labelEn:j,labelCn:x}=this.parseStatus(h.status),Y={mmsi:h.m,name:h.n,imo:r==null?void 0:r.imo,lat:h.la,lng:h.lo,draught:h.draught,sog:h.sp,cog:h.co,hdg:h.hdg,positionTime:k.unix(),utc:k.utc().format(),status:h.status,labelCn:x,labelEn:j,method:"trajectory",vendor:"hifleet"},F=Math.floor(k.diff(b,"minute",!0)/(n||1));F!==w&&(w=F,S.push(Y))}return S}}class Mt extends G{constructor(t){super();K(this,"token");this.token=t}async realTimePosition(t,a={}){const i={searchParams:{id:t,k:this.token,enc:1}},n="https://api.shipxy.com/apicall/GetSingleShip",o=await A.get(n,i).json();if(m==null||m.info("[%s] fetch realtime position from: %s - %j",a.requestId,n,i),(o==null?void 0:o.status)!==0)return o;const e=o.data[0];for(const y in e)!isNaN(e[y])&&Number(e[y])!==1/0&&(e[y]=Number(e[y]));const{labelCn:r,labelEn:u}=await this.parseStatus(e.navistat),l=g.unix(e.lasttime);return{mmsi:e.ShipID,name:e.name,imo:e.imo,callSign:e.callsign,lat:Math.round(e.lat/1e6*1e5)/1e5,lng:Math.round(e.lon/1e6*1e5)/1e5,length:Math.round(e.length/10*100)/100,width:Math.round(e.width/10*100)/100,draught:Math.round(e.draught/1e3*100)/100,sog:Math.round(e.sog*3600/1e3/1852*100)/100,cog:Math.round(e.cog/100*100)/100,hdg:Math.round(e.hdg/100*100)/100,rot:Math.round(e.rot/100*100)/100,positionTime:e.lasttime,utc:l.utc().format(),status:e.navistat,labelEn:u,labelCn:r,method:"position",vendor:"shipxy"}}async trajectory(t,a,i,n,o=!0,e={}){var b;const r=await this.realTimePosition(t,e),u=g(a),l=g(i),d="https://api.shipxy.com/apicall/GetShipTrack",y={searchParams:{id:t,k:this.token,enc:1,cut:0,btm:u.unix(),etm:l.unix()}},v=await A.get(d,y).json();if(m==null||m.info("[%s] fetch trajectory from: %s - %j",e.requestId,d,y),(v==null?void 0:v.status)!==0)return v;const M=v==null?void 0:v.points,C=[],S=g.unix((b=M[0])==null?void 0:b.utc);let w=-1;for(const c of M){const p=g.unix(c.utc),f={imo:r==null?void 0:r.imo,mmsi:t,sog:Math.round(c.sog*3600/1e3/1852*100)/100,cog:Math.round(c.cog/100*100)/100,lat:Math.round(c.lat/1e6*1e5)/1e5,lng:Math.round(c.lon/1e6*1e5)/1e5,positionTime:p.unix(),utc:p.utc().format(),method:"trajectory",vendor:"shipxy"},h=Math.floor(p.diff(S,"minute",!0)/(n||1));h!==w&&(w=h,C.push(f))}return C}}class pt extends G{constructor(t){super();K(this,"token");this.token=t}async getShipId(t,a={}){const i={headers:{appKey:this.token},json:{mmsiList:t}},n="https://api3.myships.com/sp/ships/getShipIdByMMSI",o=await A.post(n,i).json();return m==null||m.info("[%s] fetch ship id from: %s - %j",a.requestId,n,i),o.code!=="0"?o:o.data[0].shipId}async getShipInfo(t,a={}){const i={headers:{appKey:this.token},json:{shipId:t}},n="https://api3.myships.com/sp/ships/aissta",o=await A.post(n,i).json();if(m==null||m.info("[%s] fetch ship info from: %s - %j",a.requestId,n,i),o.code!=="0")return o;const e=o.data;let r=e.imo;return t==="407170"&&(r="9198379",m==null||m.warn("[%s] ship(%s) imo error: %s, should be %s",a.requestId,t,e.imo,r)),{mmsi:e.mmsi,name:e.shipnameEn,imo:r,callSign:e.callSign,length:e.length,width:e.breadth,draught:(e.draught||100)/10}}async realTimePosition(t,a={}){const i=await this.getShipId(t,a),n=await this.getShipInfo(i,a),o={headers:{appKey:this.token},json:{shipId:i}},e="https://api3.myships.com/sp/ships/position/latest",r=await A.post(e,o).json();m==null||m.info("[%s] fetch realtime position from: %s - %j",a.requestId,e,o);const u=r.data[0];for(const M in u)!isNaN(u[M])&&Number(u[M])!==1/0&&(u[M]=Number(u[M]));const{labelCn:l,labelEn:d}=await this.parseStatus(u.aisNavStatus),y=g.unix(u.posTime);return{...n,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:y.utc().format(),status:u.aisNavStatus,labelEn:d,labelCn:l,method:"position",vendor:"myship"}}async trajectory(t,a,i,n,o=!0,e={}){const r=g(a),u=g(i),l=await this.getShipId(t),d=await this.getShipInfo(l),y=[];for(;u.diff(r,"day",!0)>30;)await this.trajectoryIn30Day(l,r.unix(),r.add(30,"day").unix(),d,t,n,y);return await this.trajectoryIn30Day(l,r.unix(),u.unix(),d,t,n,y),y}async trajectoryIn30Day(t,a,i,n,o,e,r,u={}){var S;const l={headers:{appKey:this.token},json:{shipId:t,startTime:a,endTime:i}},d="https://api3.myships.com/sp/ships/position/history",y=await A.post(d,l).json();if(m==null||m.info("[%s] fetch trajectory from: %s - %j",u.requestId,d,l),y.code!=="0")return m==null||m.warn("[%s] invoke myship trajectory failed: %j",u.requestId,y),y;const v=y.data;for(const w in v)!isNaN(v[w])&&Number(v[w])!==1/0&&(v[w]=Number(v[w]));const M=g.unix((S=v[0])==null?void 0:S.posTime);let C=-1;for(const w of v){const b=g.unix(w.posTime),c={imo:n==null?void 0:n.imo,mmsi:o,lat:Math.round(w.lat/1e4/60*1e5)/1e5,lng:Math.round(w.lon/1e4/60*1e5)/1e5,sog:Math.round(w.sog/10*100)/100,cog:Math.round(w.cog/10*100)/100,hdg:Math.round(w.heading*100)/100,rot:Math.round(w.rot*100)/100,positionTime:b.unix(),utc:b.utc().format(),method:"trajectory",vendor:"myship"},p=Math.floor(b.diff(M,"minute",!0)/(e||1));p!==C&&(C=p,r.push(c))}return r}}let _;try{_=U.getLogger("vessel")}catch{}finally{}var ct=(D=>(D.NOTICE="NOTICE",D.WARN="WARN",D.HEAVY="HEAVY",D.SEVERE="SEVERE",D.ERROR="ERROR",D.FATAL="FATAL",D))(ct||{});class dt{parsePrinciple(s,t={}){var e,r,u;_==null||_.debug("[%s] parse rule: %s",t.requestId,s);const a=new RegExp("(?<=\\[)(.+)(?=])","g"),i=s.match(a)?(e=s.match(a))==null?void 0:e[0]:void 0,n=i==null?void 0:i.split(";");if(!n)return;const o={};for(let l=0;l<(n==null?void 0:n.length);l++){const d=(u=(r=n[l].match(a))==null?void 0:r[0])==null?void 0:u.split("],");if(l===0&&!d)o.scope=n[0];else if(d)for(let y=0,v=d.length;y<v;y++){const M=this.parseRule(d[y]);M&&(o[M.level]?M.key?o[M.level][M==null?void 0:M.key]=M:o[M.level]=M:M.key?o[M.level]={[M==null?void 0:M.key]:M}:o[M.level]=M)}}return o}parseRule(s,t={}){var o;_==null||_.debug("[%s] parse rule: %s",t.requestId,s),s=s.startsWith("[")?s:`[${s}`,s=s.endsWith("]")?s:`${s}]`;const a=new RegExp("(?<=\\[)(.+?)(?=])","g"),i=(o=s==null?void 0:s.match(a))==null?void 0:o[0],n=i==null?void 0:i.split(",");if(n){let e=n[3]==="Number.MAX_VALUE"?100:Number(n[3]);return e=isNaN(e)?1:e,{operator:n[0],number:Number.isNaN(Number(n[1]))?n[1]:Number(n[1]),level:n[2],time:e,key:n[4]}}}checkWeather(s,t,a={}){var M,C,S,w,b,c,p,f,h,k,j,x,Y,F,L;let i=0,n=0,o=0,e=0;const r=Math.round(((C=(M=t==null?void 0:t.SEVERE)==null?void 0:M.sigWave)==null?void 0:C.number)*1.6*100)/100,u=(w=(S=t==null?void 0:t.SEVERE)==null?void 0:S.sigWave)==null?void 0:w.number,l=(c=(b=t==null?void 0:t.HEAVY)==null?void 0:b.sigWave)==null?void 0:c.number,d=Math.round((((f=(p=t==null?void 0:t.SEVERE)==null?void 0:p.wind)==null?void 0:f.number)+2)*100)/100,y=(k=(h=t==null?void 0:t.SEVERE)==null?void 0:h.wind)==null?void 0:k.number,v=(x=(j=t==null?void 0:t.HEAVY)==null?void 0:j.wind)==null?void 0:x.number;for(let H=0;H<(s==null?void 0:s.length);H++){const E=s[H],P=(F=(Y=E==null?void 0:E.meteo)==null?void 0:Y.wave)==null?void 0:F.sig,V=(L=E==null?void 0:E.meteo)==null?void 0:L.wind,J=H?g(E.eta).diff(g(s[H-1].eta),"hour",!0):0;e=J>e?J:e,_==null||_.debug("[%s] check sig.wave: %j",a.requestId,{...P,dgThd4Wv:r,svThd4Wv:u,hvThd4Wv:l}),(P==null?void 0:P.height)>=r?E.isDangerous=!0:(P==null?void 0:P.height)>=u?E.isSevere=!0:(P==null?void 0:P.height)>=l&&(E.isHeavy=!0),_==null||_.debug("[%s] check wind: %j",a.requestId,{...V,dgThd4Wd:d,svThd4Wd:y,hvThd4Wd:v}),(V==null?void 0:V.scale)>=d?(E.isDangerous=!0,delete E.isSevere,delete E.isHeavy):(V==null?void 0:V.scale)>y?(E.isDangerous||(E.isSevere=!0),delete E.isHeavy):(V==null?void 0:V.scale)===v&&!E.isDangerous&&!E.isSevere&&(E.isHeavy=!0),i+=E.isDangerous?J:0,n+=E.isSevere?J:0,o+=E.isHeavy?J:0}return i=Math.round(i*100)/100,n=Math.round(n*100)/100,o=Math.round(o*100)/100,e=Math.round(e),{sample:s,dangerous:i,severe:n,heavy:o,step:e<3?3:e,wind:{dgThd4Wd:d,svThd4Wd:y,hvThd4Wd:v},sig:{dgThd4Wv:r,svThd4Wv:u,hvThd4Wv:l}}}}const bt=new dt;let I;try{I=U.getLogger("vessel")}catch{}finally{}const vt=new ft.MeteoHelper2("",!0);var ut=(D=>(D.common="common",D.container="container",D.tugs="tugs",D))(ut||{}),lt=(D=>(D.Ballast="Ballast",D.Laden="Laden",D))(lt||{}),ht=(D=>(D.Cp="CP",D.Perf="Basis",D.Instruct="Other",D))(ht||{});class W{static blockCoefficient(s,t,a,i){let n=Math.round(s/(t*a*i)*100)/100;n=n<.55?.55:n>.85?.85:n;const o=[.55,.6,.65,.7,.75,.8,.85],e=o.map(r=>Math.abs(r-n));return o[e.indexOf(Math.min(...e))]}static froudeNumber(s,t,a=9.8){let i=Math.round(Math.sqrt(s*s/(a*t))*100)/100;return i=i<.05?.05:i>.3?.3:i,i}static amendFactor(s,t,a){const i={.55:[1.7,-1.4,-7.4],.6:[2.2,-2.5,-9.7],.65:[2.6,-3.7,-11.6],.7:[3.1,-5.3,-12.4],.75:[2.4,-10.6,-9.5],.8:[2.6,-13.1,-15.1],.85:[3.1,-18.7,28]};let 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.6,-12.5,-13.5],.8:[3,-16.3,-21.6],.85:[3.4,-20.9,31.8]}[s];return a==="Laden"&&(o=i[s]),o[0]+o[1]*t+o[2]*Math.pow(t,2)}static directionFactor(s,t=0){let a;return s>30&&s<=60?a=(1.7-.03*Math.pow(t-4,2))/2:s>60&&s<=150?a=(.9-.06*Math.pow(t-6,2))/2:s>150&&s<=180?a=(.4-.03*Math.pow(t-8,2))/2:a=1,Math.round(a*1e5)/1e5}static vesselTagFactor(s,t,a,i){let n;return a==="container"?n=.7*i/2+Math.pow(i,3)/(22*Math.pow(s,2/3)):t==="Ballast"?n=.7*i/2+Math.pow(i,3)/(2.7*Math.pow(s,2/3)):n=.5*i/2+Math.pow(i,3)/(2.7*Math.pow(s,2/3)),n}static waveHeightFactor(s,t){s=s<3?s*.7:s,s=s<0?.2:s,s=s>6?s-.9*(s-6):s,s=s>9?9:s;let a;return t>30&&t<=60?a=-.6:t>60&&t<=90?a=-.4:t>90&&t<=120?a=s<3?.4:-.3:t>120&&t<=150?a=s<3?.6:-.5:t>150&&t<=180?a=s<3?.7:-.6:a=-.7,Math.round(a*(.144*Math.pow(s,2)+.278*s)*1e4)/1e4}static assembleProperties(s,t,a,i){var y;const n=s.lbp??s.length??s.lengthOverall??198.9642,o=s.draught??8,e=s.breadthMoulded??s.breadth??s.breadthExtreme??32.4572,r=s.deadweight??67035.7773,u=((y=s==null?void 0:s.type)==null?void 0:y.toLowerCase())||"common";return{tag:u.indexOf("container")>-1?"container":u.indexOf("tugs")>-1?"tugs":"common",lbp:n,loadCondition:t,draught:o,breadthMoulded:e,displacement:Math.round((r/1.025+o*e*n*.7)*1e4)/1e4,speed:Math.round((a??14.1382)*1852/3600*1e4)/1e4,bearing:i||90}}static async speedLoseAt(s,t,a,i="",n=2,o=!0,e=!1,r={}){let u;if(t.velocity&&e&&(s.speed=N.LngLatHelper.roundPrecision(t.velocity*1852/3600,6)),o){let l;try{i=(i==null?void 0:i.toUpperCase())==="CMEMS"?"ECMWF":i,i=(i==null?void 0:i.toUpperCase())==="METEO2"?"best_match":i;const{weatherModels:M,marineModels:C}=await nt.Meteo2Assist.autoPickMeteoModel(i),S=await vt.spotForecast(t.lat,t.lng,a.utc().format(),!1,!1,!0,{...r,pastDays:1,forecastDays:1,weatherModels:M,marineModels:C}),[w]=nt.Meteo2Assist.pickHourly(S,a);l=nt.Meteo2Assist.toLegacy(w)}catch(M){I.warn("[%s] meteo2 spot(%j) forecast failed: %s",r.requestId,{...t,eta:a.utc().format(),source:i},M)}const d=W.currentFactor(s.bearing,l==null?void 0:l.current,n),y=W.weatherFactor(s,l,d),v=Math.round((s.speed*1.943844+y+d)*100)/100;u={meteo:{...l},wxFactor:y,cFactor:d,speed:t.velocity&&e?t.velocity:v<0?1:v,eta:a.utc().format(),etd:a.utc().format()}}else u={wxFactor:0,cFactor:0,speed:t.velocity&&e?t.velocity:Math.round(s.speed*1.943844*100)/100,eta:a.utc().format(),etd:a.utc().format()};return delete t.meteo,delete t.wxFactor,delete t.cFactor,delete t.speed,delete t.etd,{...u,...t}}static async speedLoseInHoursStep(s,t,a,i,n,o,e="",r=!0,u=!1,l={}){t.utc();const d=t.clone().add(14,"days"),y=[],v=[];let M=0,C=0,S,w;for(let b=0;b<o.length-1;b++){let c=o[b];c.distanceFromStart=Math.round((n+C)*1e3)/1e3;const p=o[b+1];if(s.bearing=N.LaneHelper.calculateBearing(c,p,!p.gcToPrevious),c.bearing=s.bearing,c.suspend&&u){c.eta=c.eta||t.utc().format(),c.elapsed=c.elapsed??0;const k=c.suspend-c.elapsed;if(i-M>k)i=i-M-k,t.add(k,"hour"),c.elapsed=c.suspend;else{const j=i-M;c.elapsed+=j,t.add(j,"hour"),i=0}if(I==null||I.info(`[%s] suspend ${c.elapsed} hours at %j, and remain ${i} hours need to go...`,l.requestId,c),i===0)return c.distanceFromPrevious=C,{etd:t,from:w||c,to:c,next:o.filter(j=>j),wps:y,days:v}}else c.suspend=0;r=t.isAfter(d)?!1:r,c=await W.speedLoseAt(s,c,t,e,0,r,u,l),w=w||c,c.important&&y.push(c),t.isSameOrAfter(a)&&(v.push(c),a.add(24,"hour"));const f=N.LaneHelper.calculateDistance(c,p,!p.gcToPrevious);let h=Math.round(f/w.speed*1e5)/1e5;if(M+h<i){if(M+=h,t.add(h,"hour"),delete o[b],I==null||I.debug(`[%s] go to %j from %j with ${f}nm, and cost ${h} hours`,l.requestId,{lat:p.lat,lng:p.lng},{lat:w.lat,lng:w.lng,etd:w.etd}),C+=f,o.filter(k=>k).length<=1){S=p,S.eta=t.utc().format(),S.distanceFromPrevious=f,S.distanceFromStart=Math.round((n+C)*1e4)/1e4,y.push(S),delete o[b+1];break}}else{h=i-M,t.add(h,"hour");const k=N.LngLatHelper.roundPrecision(w.speed*h,5);S=N.LaneHelper.calculateCoordinate(c,s.bearing,k,"nauticalmiles",!p.gcToPrevious),S.eta=t.utc().format(),o[b]=S,I==null||I.debug(`[%s] go to %j from %j with ${k}nm, and cost ${h} hours`,l.requestId,{lat:S.lat,lng:S.lng},{lat:c.lat,lng:c.lng,etd:c.etd}),C+=k,S.distanceFromPrevious=Math.round(C*1e4)/1e4,S.distanceFromStart=Math.round((n+C)*1e4)/1e4;break}}return{etd:t,from:w,to:S,next:o.filter(b=>b),wps:y,days:v}}static currentFactor(s,t,a=0){const i=(s-(t==null?void 0:t.degree)||0)/180*Math.PI;if(Math.abs(i)===Math.PI/2)return 0;let n=((t==null?void 0:t.kts)||0)*Math.cos(i);return a&2?n=Math.ceil(n*100)/100:a&1?n=Math.floor(n*100)/100:n=Math.round(n*100)/100,Math.abs(n)>5?0:n}static weatherFactor(s,t,a=0){var v,M,C,S,w,b,c;I==null||I.debug("calculate weather factor via: %j",{...s,...t});const i=W.blockCoefficient(s.displacement,s.lbp,s.breadthMoulded,s.draught),n=N.LngLatHelper.roundPrecision(a*1852/3600,6),o=W.froudeNumber(s.speed-n,s.lbp),e=W.amendFactor(i,o,s.loadCondition);let r=Math.abs(s.bearing%360-(((v=t==null?void 0:t.wind)==null?void 0:v.degree)%360||0));r=r>180?360-r:r;const u=W.directionFactor(r,(M=t==null?void 0:t.wind)==null?void 0:M.scale),l=W.vesselTagFactor(s.displacement,s.loadCondition,s.tag,(C=t==null?void 0:t.wind)==null?void 0:C.kts);let d=u*e*l/100*(s.speed-n);d=Math.round(d*1.943844*1e4)/1e4*-1,s.tag==="tugs"&&Math.abs(d)>1&&(d=d/(Math.abs(Math.round(d))+1)),I==null||I.debug("wind wx factor = %d",d),r=Math.abs(s.bearing%360-(((w=(S=t==null?void 0:t.wave)==null?void 0:S.sig)==null?void 0:w.degree)%360||0)),r=r>180?360-r:r;const y=W.waveHeightFactor(((c=(b=t==null?void 0:t.wave)==null?void 0:b.sig)==null?void 0:c.height)??1,r);return I==null||I.debug("wave wx factor = %d",y),d=Math.abs(d)>Math.abs(y)?d:d*.3+y*.7,I==null||I.debug("weather factor = %d",d),d=Math.abs(d)>3?3*(Math.abs(d)/d)+Math.abs(d)/d*(Math.abs(d)-2)*.1:d,Math.round((d||0)*100)/100}static async analyseInstant(s,t,a,i,n,o="",e=0,r=!0,u=!1,l={}){var X,Q,Z,$,tt,et;const d=g().valueOf();s.lng=N.LngLatHelper.convertToStdLng(s.lng);const{route:y,waypoints:v}=n.points,M=N.LaneHelper.calculateSubRoute(s,y);if(((X=M[0])==null?void 0:X.length)<=1)return;const{v0:C,label:S}=s.sog?{v0:s.sog,label:s.label||"Other"}:{v0:i.speed,label:"CP"},w=W.assembleProperties(a,i.loadCondition,C,0),b=v.length?N.LaneHelper.calculateSubWaypoints(s,v):[];b.forEach(O=>O.important=!0);const c={from:{...s},route:M,waypoints:b,v0:C,label:S},p={hours:[],days:[],wps:[]};e||(N.LaneHelper.calculateRouteDistance(M)/i.speed<=72?e=3:e=6);let f=N.LaneHelper.simplifyRouteToCoordinates(M,b,0),h=0,k=0,j=0,x=0;t=g(t).utc();const Y=t.clone();for(;f.length>0;){const O=e-t.hour()%e,z=Math.ceil(t.clone().add(O,"h").set({minute:0,second:0,millisecond:0}).diff(t,"h",!0)*1e4)/1e4,T=await W.speedLoseInHoursStep(w,t,Y,z,h,f,o,r,u,l);if((Q=T.from)!=null&&Q.speed&&(p.hours.push(T.from),p.wps.push(...T.wps),p.days.push(...T.days)),f=T==null?void 0:T.next,!f.length){const B=await W.speedLoseAt(w,T.to,g(T.to.eta),o,0,r,u,l);p.hours.push(B)}h+=Math.round((((Z=T==null?void 0:T.to)==null?void 0:Z.distanceFromPrevious)??0)*1e4)/1e4}const F=p.hours;for(let O=0;O<F.length-1;O++){const z=g(F[O+1].eta).diff(F[O].etd,"hour",!0)||1;k+=(F[O].wxFactor||0)*z,j+=(F[O].cFactor||0)*z,x+=z}($=p.wps)==null||$.forEach((O,z)=>{O.positionTime=g.utc(O.etd||O.eta).unix();const T=p.wps[z-1];if(T){const B=O.distanceFromStart-T.distanceFromStart,R=g(O.eta||O.etd).diff(g(T.etd||T.eta),"h",!0);O.avgSpd=Math.round(B/R*100)/100,T.bearing=N.LaneHelper.calculateBearing(T,O)}}),p.wps=(tt=p.wps)==null?void 0:tt.reduce((O,z)=>(O.some(T=>Math.round(T.positionTime/60)===Math.round(z.positionTime/60))||O.push(z),O),[]),c.sample=p;const L=p.hours.at(0),H=p.hours.at(-1);c.distance=Math.round(H.distanceFromStart*1e3)/1e3,c.etd=g(L.eta).utc().format(),c.eta=g(H.eta).utc().format(),c.wxFactor=Math.round(k/x*1e3)/1e3,c.cFactor=Math.round(j/x*1e3)/1e3,c.avgSpeed=Math.round(H.distanceFromStart/x*1e3)/1e3,c.totalHrs=Math.round(x*1e3)/1e3;const{distanceInECA:E,hoursInECA:P,totalDgoConsInECA:V,eca:J}=await this.calculateECA(c,i,l),st=N.LngLatHelper.roundPrecision(i.fo/24*(x-P),3),ot=N.LngLatHelper.roundPrecision(i.dgo/24*x,3);c.extend={eca:J,distanceInECA:E,hoursInECA:P,totalDgoConsInECA:V},c.totalFoCons=st<0?0:st,c.totalDgoCons=ot;const at=g().valueOf()-d,rt=((et=p==null?void 0:p.hours)==null?void 0:et.length)||1;return I==null||I.info("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms",l==null?void 0:l.requestId,at,rt,Math.round(at/rt*1e3)/1e3),c}static async analyseInstantWithThreshed(s,t,a,i,n,o,e,r="",u=3,l=!0,d=!1,y={}){var Z,$,tt,et,O,z;const v=g().valueOf();s.lng=N.LngLatHelper.convertToStdLng(s.lng);const{v0:M,label:C}=s.sog?{v0:s.sog,label:s.label||"Other"}:{v0:n.speed,label:"CP"},S=W.assembleProperties(i,n.loadCondition,M,0),w=N.LaneHelper.calculateSubRoute(s,o);if(((Z=w[0])==null?void 0:Z.length)<=1)return;const b=e.length?N.LaneHelper.calculateSubWaypoints(s,e):[];b.forEach(T=>T.important=!0);let c=N.LaneHelper.simplifyRouteToCoordinates(w,b,0),p=0,f=0,h=0,k=0;const j={hours:[],wps:[],days:[]};t=g(t).utc();const x=t.clone();for(;c.length>0;){const T=u-t.hour()%u;let B=Math.ceil(t.clone().add(T,"h").set({minute:0,second:0,millisecond:0}).diff(t,"h",!0)*1e4)/1e4;B=t.clone().add(B,"h").isSameOrAfter(a)?a.diff(t,"h",!0)*1e4/1e4:B;const R=await W.speedLoseInHoursStep(S,t,x,B,p,c,r,l,d,y);if(($=R.from)!=null&&$.speed&&(j.hours.push(R.from),R!=null&&R.wps&&j.wps.push(...R.wps),j.days.push(...R.days)),c=R==null?void 0:R.next,c.length||j.hours.push(R==null?void 0:R.to),p+=Math.round((((tt=R==null?void 0:R.to)==null?void 0:tt.distanceFromPrevious)??0)*1e4)/1e4,!B)break}j.wps=(et=j.wps)==null?void 0:et.reduce((T,B)=>(T.some(R=>Math.round(g(R.etd).unix()/60)===Math.round(g(B.etd).unix()/60))||T.push(B),T),[]),(O=j.wps)==null||O.forEach((T,B)=>{const R=j.wps[B-1];if(R){const gt=T.distanceFromStart-R.distanceFromStart,wt=g(T.eta||T.etd).diff(g(R.etd||R.eta),"h",!0);T.avgSpd=Math.round(gt/wt*100)/100;const kt=N.LaneHelper.calculateBearing(R,T);R.bearing=kt}});const Y=j.hours;for(let T=0;T<Y.length-1;T++){const B=g(Y[T+1].eta).diff(Y[T].etd,"hour",!0);f+=Y[T].wxFactor*B,h+=Y[T].cFactor*B,k+=B}const F=j.hours.at(0),L=j.hours.at(-1),H=await N.LaneHelper.calculateRangeRoute(F,L,w),E=await N.LaneHelper.calculateRangeWaypoints(F,L,w,b),P={sample:j,distance:Math.round(((L==null?void 0:L.distanceFromStart)||0)*1e4)/1e4,etd:g(F.eta).utc().format(),eta:g(L==null?void 0:L.eta).utc().format(),wxFactor:Math.round(f/k*1e3)/1e3,cFactor:Math.round(h/k*1e3)/1e3,avgSpeed:Math.round(((L==null?void 0:L.distanceFromStart)||0)/k*1e3)/1e3,totalHrs:Math.round(k*1e3)/1e3,from:F,to:L,route:H,waypoints:E,v0:M,label:C},{distanceInECA:V,hoursInECA:J,totalDgoConsInECA:st,eca:ot}=await this.calculateECA(P,n,y),it=N.LngLatHelper.roundPrecision(n.fo/24*(k-J),3),at=N.LngLatHelper.roundPrecision(n.dgo/24*k,3);P.extend={eca:ot,distanceInECA:V,hoursInECA:J,totalDgoConsInECA:st},P.totalDgoCons=at,P.totalFoCons=it<0?0:it;const X=g().valueOf()-v,Q=((z=j==null?void 0:j.hours)==null?void 0:z.length)||1;return I==null||I.debug("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms",y==null?void 0:y.requestId,X,Q,Math.round(X/Q*1e3)/1e3),P}static async analyseCost(s,t,a,i,n={}){var w,b;const o=g().valueOf(),e=[];s.speedStep=s.speedStep||3,s.alterStep=s.alterStep??1;const r=N.LaneHelper.calculateRouteDistance(i.route);let u=0;a.forEach(c=>{const p=Math.ceil(r/c.speed/24);u=u<p?p:u}),u=u*1.3;const l=g.utc(s.etd).add(u??14,"day");let d=1;for(const c of a){const p=JSON.parse(JSON.stringify(i.route)),f=JSON.parse(JSON.stringify(i.waypoints)),h=await W.analyseInstantWithThreshed({lat:s.lat,lng:s.lng},s.etd,l,t,c,p,f,s.meteoVendor,s.speedStep,s.useMeteo,s.useRouteParam,n);h&&(await W.calculateCost(h,c,s,n),e.push(h),I==null||I.info("[%s][L%d-%d] analyse from %s to %s cost: %j",n.requestId,1,d,s.etd,l.format(),{cost:h.cost.total,hire:h.cost.hire,bunker:h.cost.bunker,distance:h.distance,hours:h.totalHrs,cp:`${c.speed}/${c.fo}/${c.dgo}`})),d++}e.sort((c,p)=>c.cost.total-p.cost.total);const y=e.at(0),v=e.at(1),M=[];if(M.push({combined:!1,speeds:[y],cost:(w=y.cost)==null?void 0:w.total}),v){const c=y.cost.cp,p=v.cost.cp,f=g(y.eta),h=g(y.etd),k=f.diff(h,"days",!0);let j=Math.ceil(k/2);j=j>7?7:j<s.alterStep?s.alterStep:j;let x=2,Y={combined:!1,speeds:[v],cost:(b=v.cost)==null?void 0:b.total},F;for(;j>=s.alterStep;){const L=await W.combinedAnalyse(s,t,l,[c,p],i,j,{...n,level:x});if(Y.cost>L.cost?F?(F==null?void 0:F.cost)>L.cost&&(F=L):(F=Y,Y=L):(!F||(F==null?void 0:F.cost)>L.cost)&&(F=L),j<=s.alterStep)break;j=Math.ceil(j/2),x+=1}M.push(Y),F&&M.push(F)}const S=g().valueOf()-o;return I==null||I.info("[%s] analyse elapsed: %d ms",n==null?void 0:n.requestId,S),M.sort((c,p)=>c.cost-p.cost)}static async combinedAnalyse(s,t,a,i,n,o,e={}){e.counter=1,I==null||I.info("[%s][L%d] analyse with alternate cp in every %d days",e.requestId,e.level,o);const r=await W.alternateAnalyse(s,t,a,i,0,n,o,e),u=r.reduce((p,f)=>p+f.cost.total,0),l=r.reduce((p,f)=>p+f.cost.hire,0),d=r.reduce((p,f)=>p+f.cost.bunker,0),y=r.reduce((p,f)=>p+f.distance,0),v=r.reduce((p,f)=>p+f.totalHrs,0);I==null||I.info("[%s][L%d] cost with cpa/cpb turn: %j",e.requestId,e.level,{cost:u,hire:l,bunker:d,distance:y,hours:v});const M=await W.alternateAnalyse(s,t,a,i,1,n,o,e),C=M.reduce((p,f)=>p+f.cost.total,0),S=M.reduce((p,f)=>p+f.cost.hire,0),w=M.reduce((p,f)=>p+f.cost.bunker,0),b=M.reduce((p,f)=>p+f.distance,0),c=M.reduce((p,f)=>p+f.totalHrs,0);return I==null||I.info("[%s][L%d] cost with cpb/cpa turn: %j",e.requestId,e.level,{cost:C,hire:S,bunker:w,distance:b,hours:c}),u<C?{combined:!0,cost:Math.round(u*1e3)/1e3,speeds:r,step:o}:{combined:!0,cost:Math.round(C*1e3)/1e3,speeds:M,step:o}}static async alternateAnalyse(s,t,a,i,n,o,e,r={}){var y,v;let u=g.utc(s.etd);const l={lat:s.lat,lng:s.lng},d=[];for(;u.isBefore(a);){const M=u.clone().utc().add(e,"day"),C=JSON.parse(JSON.stringify(o.route)),S=JSON.parse(JSON.stringify(o.waypoints)),w=i[n],b=await W.analyseInstantWithThreshed(l,u.utc().format(),M,t,w,C,S,s.meteoVendor,s.speedStep,s.useMeteo,s.useRouteParam,r);b&&(await W.calculateCost(b,w,s,r),I==null||I.info("[%s][L%d-%d] analyse from %s to %s cost: %j",r.requestId,r.level,r.counter,u.utc().format(),M.utc().format(),{cost:b.cost.total,hire:b.cost.hire,bunker:b.cost.bunker,distance:b.distance,hours:b.totalHrs,cp:`${w.speed}/${w.fo}/${w.dgo}`})),r.counter=r.counter+1;const c=(v=(y=b==null?void 0:b.sample)==null?void 0:y.hours)==null?void 0:v.at(-1);if(c)l.lat=c.lat,l.lng=c.lng,u=g(c.eta),d.push(b),n=n?0:1;else break}return d}static async calculateCost(s,t,a,i={}){var n;if(s){const o=(a.addComm||0)>=1?(a.addComm||0)/100:a.addComm||0,e=Math.round(s.totalHrs/24*(a.dailyHire||0)*(1-o)*1e3)/1e3,r=Math.round(s.totalFoCons*(a.priceFO||0)*1e3)/1e3,u=Math.round((s.totalDgoCons+(((n=s.extend)==null?void 0:n.totalDgoConsInECA)||0))*(a.priceDGO||0)*1e3)/1e3;s.cost={total:Math.round((e+r+u)*1e3)/1e3,hire:e,bunker:Math.round((r+u)*1e3)/1e3,cp:t}}return s}static async calculateECA(s,t,a={}){var r,u,l,d;const i=await N.LaneHelper.intersectInECA((s==null?void 0:s.route)||[]);let n=0,o=0,e=0;(u=(r=s==null?void 0:s.sample)==null?void 0:r.wps)==null||u.forEach(y=>{y.positionTime=g.utc(y.etd||y.eta).unix()});for(const y of i){n+=y.distance;const v=await N.LaneHelper.deadReckoningTime((l=y.waypoints)==null?void 0:l.at(0),s.sample.wps),M=await N.LaneHelper.deadReckoningTime((d=y.waypoints)==null?void 0:d.at(-1),s.sample.wps);y.in=v,y.out=M,y.totalHrs=N.LngLatHelper.roundPrecision((M.positionTime-v.positionTime)/3600,3),y.totalDgoCons=N.LngLatHelper.roundPrecision(t.fo/24*y.totalHrs,3),o+=y.totalHrs,e+=y.totalDgoCons}return n=N.LngLatHelper.roundPrecision(n,3),o=N.LngLatHelper.roundPrecision(o,3),e=N.LngLatHelper.roundPrecision(e,3),{distanceInECA:n,hoursInECA:o,totalDgoConsInECA:e,eca:i}}static async mergeSpeeds(s,t={}){var c,p;const a={hours:[],wps:[],days:[]},i=s.reduce((f,h)=>f+h.distance,0),n=s.reduce((f,h)=>{var k;return f+(((k=h.extend)==null?void 0:k.distanceInECA)||0)},0),o=s.reduce((f,h)=>f+h.totalHrs,0),e=s.reduce((f,h)=>{var k;return f+(((k=h.extend)==null?void 0:k.hoursInECA)||0)},0),r=s.reduce((f,h)=>{var k;return f+(((k=h.extend)==null?void 0:k.totalDgoConsInECA)||0)},0),u=s.reduce((f,h)=>f+h.wxFactor*h.totalHrs/o,0),l=s.reduce((f,h)=>f+h.cFactor*h.totalHrs/o,0),d=s.reduce((f,h)=>f+h.totalFoCons,0),y=s.reduce((f,h)=>f+h.totalDgoCons,0),v=s.reduce((f,h)=>f+h.cost.total,0),M=s.reduce((f,h)=>f+h.cost.hire,0),C=s.reduce((f,h)=>f+h.cost.bunker,0),S=[],w=[];let b;for(const f of s){w.push(...((c=f.extend)==null?void 0:c.eca)||[]);const h=f.sample.hours,k=f.sample.wps,j=f.sample.days,x=h.at(0);b&&(x.distanceFromPrevious=b.distanceFromPrevious,x.distanceFromStart=b.distanceFromStart,h.forEach((H,E)=>{E&&(H.distanceFromStart=H.distanceFromStart+b.distanceFromStart)}),k.at(0).distanceFromPrevious=b.distanceFromPrevious,k.at(0).distanceFromStart=b.distanceFromStart,k.forEach((H,E)=>{E&&(H.distanceFromStart=H.distanceFromStart+b.distanceFromStart)}),j.at(0).distanceFromPrevious=b.distanceFromPrevious,j.at(0).distanceFromStart=b.distanceFromStart,j.forEach((H,E)=>{E&&(H.distanceFromStart=H.distanceFromStart+b.distanceFromStart)})),x.cp=f.cost.cp;const Y=[f.etd,f.eta],F=S.findIndex(H=>H.id===x.cp.id);F===-1?(x.cp.segment=[Y],S.push(x.cp)):S[F].segment.push(Y),h.forEach(H=>{var P;((P=a.hours)==null?void 0:P.findIndex(V=>V.eta===H.eta))===-1&&a.hours.push(H)}),k.forEach(H=>{var P;((P=a.wps)==null?void 0:P.findIndex(V=>V.eta===H.eta))===-1&&a.wps.push(H)}),j.forEach(H=>{var P;((P=a==null?void 0:a.days)==null?void 0:P.findIndex(V=>V.eta===H.eta))===-1&&a.days.push(H)});const L=(p=a.wps)==null?void 0:p.findIndex(H=>H.eta===x.eta);L===-1?a.wps.push(x):a.wps[L]=x,b=h.at(-1)}return a.wps.sort((f,h)=>{g(f.etd).unix()-g(h.etd).unix()}),a.wps.forEach((f,h)=>{const k=a.wps[h-1];if(k){const j=f.distanceFromStart-(k.distanceFromStart||0),x=g(f.eta||f.etd).diff(g(k.etd||k.eta),"hour",!0),Y=Math.round(j/x*100)/100;f.avgSpd=Y;const F=N.LaneHelper.calculateBearing(k,f);k.bearing=F}}),{sample:a,etd:s.at(0).etd,eta:s.at(-1).eta,from:s.at(0).from,to:s.at(-1).to,v0:s.at(0).v0,label:"Combined",distance:Math.round(i*1e3)/1e3,totalHrs:Math.round(o*1e3)/1e3,avgSpeed:Math.round(i/o*1e3)/1e3,wxFactor:Math.round(u*1e3)/1e3,cFactor:Math.round(l*1e3)/1e3,totalFoCons:Math.round(d*1e3)/1e3,totalDgoCons:Math.round(y*1e3)/1e3,cost:{total:Math.round(v*1e3)/1e3,hire:Math.round(M*1e3)/1e3,bunker:Math.round(C*1e3)/1e3},extend:{cps:S,eca:w,distanceInECA:Math.round(n*1e3)/1e3,hoursInECA:Math.round(e*1e3)/1e3,totalDgoConsInECA:Math.round(r*1e3)/1e3,speeds:s}}}}q.AISImpl=G,q.AlertHelper=dt,q.AlertLevel=ct,q.HifleetImpl=yt,q.LoadCondition=lt,q.MyShipImpl=pt,q.MyVesselImpl=mt,q.ShipxyImpl=Mt,q.SpeedHelper=W,q.SpeedLabel=ht,q.VesselTag=ut,q.alertHelper=bt,Object.defineProperty(q,Symbol.toStringTag,{value:"Module"})});
|