@idm-plugin/vessel 1.6.5 → 1.6.6
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 +301 -307
- package/dist/index.umd.cjs +1 -1
- package/dist/speed/src/index.d.ts +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
var st = Object.defineProperty;
|
|
2
|
-
var at = (
|
|
3
|
-
var Z = (
|
|
2
|
+
var at = (S, e, t) => e in S ? st(S, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : S[e] = t;
|
|
3
|
+
var Z = (S, e, t) => (at(S, typeof e != "symbol" ? e + "" : e, t), t);
|
|
4
4
|
import R from "got";
|
|
5
5
|
import Q from "@log4js-node/log4js-api";
|
|
6
|
-
import
|
|
6
|
+
import v from "moment";
|
|
7
7
|
import { LngLatHelper as z, LaneHelper as B } from "@idm-plugin/geo";
|
|
8
8
|
import { MeteoHelper2 as ot, MeteoHelper as nt } from "@idm-plugin/meteo2";
|
|
9
9
|
import { Meteo2Assist as tt } from "@idm-plugin/meteo";
|
|
@@ -76,15 +76,15 @@ class vt extends U {
|
|
|
76
76
|
expiresIn: a.expires_in,
|
|
77
77
|
scope: a.scope,
|
|
78
78
|
jti: a.jti,
|
|
79
|
-
issuedAt:
|
|
79
|
+
issuedAt: v().utc().format()
|
|
80
80
|
});
|
|
81
81
|
}
|
|
82
82
|
async realTimePosition(t, o = {}) {
|
|
83
|
-
var l,
|
|
84
|
-
(!this.token ||
|
|
83
|
+
var l, m, f;
|
|
84
|
+
(!this.token || v().diff(v(this.token.issuedAt), "seconds") > ((l = this.token) == null ? void 0 : l.expiresIn) - 300) && await this.authToken(o);
|
|
85
85
|
const i = "https://svc.data.myvessel.cn/sdc/v1/vessels/status/location/unit", a = {
|
|
86
86
|
headers: {
|
|
87
|
-
Authorization: `${(
|
|
87
|
+
Authorization: `${(m = this.token) == null ? void 0 : m.tokenType} ${(f = this.token) == null ? void 0 : f.accessToken}`
|
|
88
88
|
},
|
|
89
89
|
searchParams: { mmsi: t }
|
|
90
90
|
};
|
|
@@ -95,7 +95,7 @@ class vt extends U {
|
|
|
95
95
|
const s = n.data;
|
|
96
96
|
for (const h in s)
|
|
97
97
|
!isNaN(s[h]) && Number(s[h]) !== 1 / 0 && (s[h] = Number(s[h]));
|
|
98
|
-
const d =
|
|
98
|
+
const d = v(`${s.postime} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
99
99
|
return {
|
|
100
100
|
mmsi: s.mmsi,
|
|
101
101
|
name: s.vesselName,
|
|
@@ -110,7 +110,7 @@ class vt extends U {
|
|
|
110
110
|
cog: s.cog,
|
|
111
111
|
hdg: s.hdg,
|
|
112
112
|
rot: s.rot,
|
|
113
|
-
eta: /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(s.eta) ?
|
|
113
|
+
eta: /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(s.eta) ? v.utc(s.eta).format() : void 0,
|
|
114
114
|
destination: s.dest,
|
|
115
115
|
positionTime: d.unix(),
|
|
116
116
|
status: s.status,
|
|
@@ -122,15 +122,15 @@ class vt extends U {
|
|
|
122
122
|
};
|
|
123
123
|
}
|
|
124
124
|
async trajectory(t, o, i, a, n = !0, s = {}) {
|
|
125
|
-
(!this.token ||
|
|
126
|
-
const d = await this.realTimePosition(t, s),
|
|
127
|
-
for (; l.diff(
|
|
128
|
-
await this.trajectoryIn30Day(t,
|
|
129
|
-
return await this.trajectoryIn30Day(t,
|
|
125
|
+
(!this.token || v().diff(v(this.token.issuedAt), "seconds") > this.token.expiresIn - 300) && await this.authToken(s);
|
|
126
|
+
const d = await this.realTimePosition(t, s), c = v(o), l = v(i), m = [];
|
|
127
|
+
for (; l.diff(c, "day", !0) > 30; )
|
|
128
|
+
await this.trajectoryIn30Day(t, c, c.clone().add(30, "day"), d, a, m, s), c.add(30, "day");
|
|
129
|
+
return await this.trajectoryIn30Day(t, c, l, d, a, m, s), m;
|
|
130
130
|
}
|
|
131
131
|
async trajectoryIn30Day(t, o, i, a, n, s, d = {}) {
|
|
132
|
-
var u, I, k,
|
|
133
|
-
const
|
|
132
|
+
var u, I, k, y, w;
|
|
133
|
+
const c = "https://svc.data.myvessel.cn/sdc/v1/vessels/status/track", l = {
|
|
134
134
|
headers: {
|
|
135
135
|
Authorization: `${(u = this.token) == null ? void 0 : u.tokenType} ${(I = this.token) == null ? void 0 : I.accessToken}`
|
|
136
136
|
},
|
|
@@ -140,35 +140,35 @@ class vt extends U {
|
|
|
140
140
|
endTime: i.utcOffset(8).format("YYYY-MM-DD HH:mm:ss")
|
|
141
141
|
}
|
|
142
142
|
};
|
|
143
|
-
M == null || M.info("[%s] fetch trajectory from: %s - %j", d.requestId,
|
|
144
|
-
const
|
|
145
|
-
if (
|
|
146
|
-
return M == null || M.warn("[%s] fetch trajectory failed: %j", d.requestId,
|
|
143
|
+
M == null || M.info("[%s] fetch trajectory from: %s - %j", d.requestId, c, l);
|
|
144
|
+
const m = await R.post(c, l).json();
|
|
145
|
+
if (m.code)
|
|
146
|
+
return M == null || M.warn("[%s] fetch trajectory failed: %j", d.requestId, c, { message: m.message, status: m.status, code: m.code }), m;
|
|
147
147
|
let f = -1;
|
|
148
|
-
const h =
|
|
149
|
-
return (
|
|
150
|
-
for (const
|
|
151
|
-
!isNaN(
|
|
152
|
-
const b =
|
|
153
|
-
mmsi:
|
|
148
|
+
const h = v(`${(y = (k = m.data) == null ? void 0 : k[0]) == null ? void 0 : y.postime} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
149
|
+
return (w = m.data) == null || w.forEach((r) => {
|
|
150
|
+
for (const q in r)
|
|
151
|
+
!isNaN(r[q]) && Number(r[q]) !== 1 / 0 && (r[q] = Number(r[q]));
|
|
152
|
+
const b = v(`${r.postime} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00"), x = r.status, { labelCn: g, labelEn: j } = this.parseStatus(x), Y = {
|
|
153
|
+
mmsi: r.mmsi,
|
|
154
154
|
imo: a == null ? void 0 : a.imo,
|
|
155
|
-
lat:
|
|
156
|
-
lng:
|
|
157
|
-
sog:
|
|
158
|
-
cog:
|
|
159
|
-
hdg:
|
|
160
|
-
draught:
|
|
161
|
-
status:
|
|
162
|
-
eta: /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(
|
|
163
|
-
destination:
|
|
155
|
+
lat: r.lat,
|
|
156
|
+
lng: r.lon,
|
|
157
|
+
sog: r.sog,
|
|
158
|
+
cog: r.cog,
|
|
159
|
+
hdg: r.hdg,
|
|
160
|
+
draught: r.draught,
|
|
161
|
+
status: x,
|
|
162
|
+
eta: /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(r.eta) ? v(`${r.eta} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00").utc().format() : void 0,
|
|
163
|
+
destination: r.dest,
|
|
164
164
|
positionTime: b.unix(),
|
|
165
165
|
labelCn: g,
|
|
166
166
|
labelEn: j,
|
|
167
167
|
method: "trajectory",
|
|
168
168
|
vendor: "myVessel",
|
|
169
169
|
utc: b.utc().format()
|
|
170
|
-
},
|
|
171
|
-
|
|
170
|
+
}, C = Math.floor(b.diff(h, "minute", !0) / (n || 1));
|
|
171
|
+
C !== f && (f = C, s.push(Y));
|
|
172
172
|
}), s;
|
|
173
173
|
}
|
|
174
174
|
}
|
|
@@ -192,7 +192,7 @@ class wt extends U {
|
|
|
192
192
|
for (const h in s)
|
|
193
193
|
!isNaN(s[h]) && Number(s[h]) !== 1 / 0 && (s[h] = Number(s[h]));
|
|
194
194
|
s.status = s.sp > 3 ? 0 : 1;
|
|
195
|
-
const d = s.status, { labelCn:
|
|
195
|
+
const d = s.status, { labelCn: c, labelEn: l } = this.parseStatus(d), m = v(`${s.ti} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
196
196
|
return {
|
|
197
197
|
mmsi: s.m,
|
|
198
198
|
name: s.n,
|
|
@@ -207,12 +207,12 @@ class wt extends U {
|
|
|
207
207
|
cog: s.co,
|
|
208
208
|
hdg: s.h,
|
|
209
209
|
rot: isNaN(s.rot) ? 0 : s.rot,
|
|
210
|
-
eta: /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(s.eta) ?
|
|
210
|
+
eta: /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(s.eta) ? v.utc(s.eta).format() : void 0,
|
|
211
211
|
destination: s.destination,
|
|
212
|
-
positionTime:
|
|
213
|
-
utc:
|
|
212
|
+
positionTime: m.unix(),
|
|
213
|
+
utc: m.utc().format(),
|
|
214
214
|
status: d,
|
|
215
|
-
labelCn:
|
|
215
|
+
labelCn: c,
|
|
216
216
|
labelEn: l,
|
|
217
217
|
method: "position",
|
|
218
218
|
vendor: "hifleet"
|
|
@@ -267,37 +267,37 @@ class wt extends U {
|
|
|
267
267
|
imo: !d.imo || isNaN(d.imo) ? null : Number(d.imo),
|
|
268
268
|
score: d._score
|
|
269
269
|
});
|
|
270
|
-
return s.sort((d,
|
|
270
|
+
return s.sort((d, c) => c.score - d.score), s;
|
|
271
271
|
}
|
|
272
272
|
async trajectory(t, o, i, a, n = !0, s = {}) {
|
|
273
|
-
var
|
|
273
|
+
var r, b, x;
|
|
274
274
|
const d = await this.realTimePosition(t, s);
|
|
275
|
-
let
|
|
276
|
-
const l =
|
|
275
|
+
let c = v(o);
|
|
276
|
+
const l = v(i), m = v();
|
|
277
277
|
if (n) {
|
|
278
|
-
let g = l.diff(
|
|
279
|
-
g < 0 ?
|
|
278
|
+
let g = l.diff(c, "d", !0);
|
|
279
|
+
g < 0 ? c = l.clone().subtract(40, "d") : g < 30 ? c.subtract(10, "d") : g < 60 ? c.subtract(5, "d") : c = l.clone().subtract(80, "d"), g = m.diff(l, "d", !0), l.add(g > 10 ? 240 : g * 24, "h");
|
|
280
280
|
}
|
|
281
281
|
const f = {
|
|
282
282
|
searchParams: {
|
|
283
283
|
endtime: l.utcOffset("+8:00").format("YYYY-MM-DD HH:mm:ss"),
|
|
284
|
-
starttime:
|
|
284
|
+
starttime: c.utcOffset("+8:00").format("YYYY-MM-DD HH:mm:ss"),
|
|
285
285
|
mmsi: t,
|
|
286
286
|
usertoken: this.token
|
|
287
287
|
}
|
|
288
288
|
}, h = "https://api.hifleet.com/position/trajectory/nocompressed/withstatic/token", u = await R.get(h, f).json();
|
|
289
289
|
M == null || M.info("[%s] fetch trajectory from: %s - %j", s.requestId, h, f);
|
|
290
290
|
let I;
|
|
291
|
-
u && (I = ((b = (
|
|
291
|
+
u && (I = ((b = (r = u.ships) == null ? void 0 : r.offors) == null ? void 0 : b.ship) || [], I.length || M == null || M.warn("[%s] fetch trajectory failed: %j", s.requestId, u));
|
|
292
292
|
const k = [];
|
|
293
|
-
let
|
|
294
|
-
const
|
|
293
|
+
let y = -1;
|
|
294
|
+
const w = v(`${(x = I == null ? void 0 : I[0]) == null ? void 0 : x.ti} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
295
295
|
for (const g of I) {
|
|
296
|
-
for (const
|
|
297
|
-
!isNaN(g[
|
|
298
|
-
const j =
|
|
296
|
+
for (const D in g)
|
|
297
|
+
!isNaN(g[D]) && Number(g[D]) !== 1 / 0 && (g[D] = Number(g[D]));
|
|
298
|
+
const j = v(`${g.ti} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
299
299
|
g.status = g.sp > 4 ? 0 : 1;
|
|
300
|
-
const { labelEn:
|
|
300
|
+
const { labelEn: Y, labelCn: C } = this.parseStatus(g.status), q = {
|
|
301
301
|
mmsi: g.m,
|
|
302
302
|
name: g.n,
|
|
303
303
|
imo: d == null ? void 0 : d.imo,
|
|
@@ -310,12 +310,12 @@ class wt extends U {
|
|
|
310
310
|
positionTime: j.unix(),
|
|
311
311
|
utc: j.utc().format(),
|
|
312
312
|
status: g.status,
|
|
313
|
-
labelCn:
|
|
314
|
-
labelEn:
|
|
313
|
+
labelCn: C,
|
|
314
|
+
labelEn: Y,
|
|
315
315
|
method: "trajectory",
|
|
316
316
|
vendor: "hifleet"
|
|
317
|
-
},
|
|
318
|
-
|
|
317
|
+
}, T = Math.floor(j.diff(w, "minute", !0) / (a || 1));
|
|
318
|
+
T !== y && (y = T, k.push(q));
|
|
319
319
|
}
|
|
320
320
|
return k;
|
|
321
321
|
}
|
|
@@ -339,7 +339,7 @@ class pt extends U {
|
|
|
339
339
|
const s = n.data[0];
|
|
340
340
|
for (const f in s)
|
|
341
341
|
!isNaN(s[f]) && Number(s[f]) !== 1 / 0 && (s[f] = Number(s[f]));
|
|
342
|
-
const { labelCn: d, labelEn:
|
|
342
|
+
const { labelCn: d, labelEn: c } = await this.parseStatus(s.navistat), l = v.unix(s.lasttime);
|
|
343
343
|
return {
|
|
344
344
|
mmsi: s.ShipID,
|
|
345
345
|
name: s.name,
|
|
@@ -357,42 +357,42 @@ class pt extends U {
|
|
|
357
357
|
positionTime: s.lasttime,
|
|
358
358
|
utc: l.utc().format(),
|
|
359
359
|
status: s.navistat,
|
|
360
|
-
labelEn:
|
|
360
|
+
labelEn: c,
|
|
361
361
|
labelCn: d,
|
|
362
362
|
method: "position",
|
|
363
363
|
vendor: "shipxy"
|
|
364
364
|
};
|
|
365
365
|
}
|
|
366
366
|
async trajectory(t, o, i, a, n = !0, s = {}) {
|
|
367
|
-
var
|
|
368
|
-
const d = await this.realTimePosition(t, s),
|
|
367
|
+
var w;
|
|
368
|
+
const d = await this.realTimePosition(t, s), c = v(o), l = v(i), m = "https://api.shipxy.com/apicall/GetShipTrack", f = {
|
|
369
369
|
searchParams: {
|
|
370
370
|
id: t,
|
|
371
371
|
k: this.token,
|
|
372
372
|
enc: 1,
|
|
373
373
|
cut: 0,
|
|
374
|
-
btm:
|
|
374
|
+
btm: c.unix(),
|
|
375
375
|
etm: l.unix()
|
|
376
376
|
}
|
|
377
|
-
}, h = await R.get(
|
|
378
|
-
if (M == null || M.info("[%s] fetch trajectory from: %s - %j", s.requestId,
|
|
377
|
+
}, h = await R.get(m, f).json();
|
|
378
|
+
if (M == null || M.info("[%s] fetch trajectory from: %s - %j", s.requestId, m, f), (h == null ? void 0 : h.status) !== 0)
|
|
379
379
|
return h;
|
|
380
|
-
const u = h == null ? void 0 : h.points, I = [], k =
|
|
381
|
-
let
|
|
382
|
-
for (const
|
|
383
|
-
const b =
|
|
380
|
+
const u = h == null ? void 0 : h.points, I = [], k = v.unix((w = u[0]) == null ? void 0 : w.utc);
|
|
381
|
+
let y = -1;
|
|
382
|
+
for (const r of u) {
|
|
383
|
+
const b = v.unix(r.utc), x = {
|
|
384
384
|
imo: d == null ? void 0 : d.imo,
|
|
385
385
|
mmsi: t,
|
|
386
|
-
sog: Math.round(
|
|
387
|
-
cog: Math.round(
|
|
388
|
-
lat: Math.round(
|
|
389
|
-
lng: Math.round(
|
|
386
|
+
sog: Math.round(r.sog * 3600 / 1e3 / 1852 * 100) / 100,
|
|
387
|
+
cog: Math.round(r.cog / 100 * 100) / 100,
|
|
388
|
+
lat: Math.round(r.lat / 1e6 * 1e5) / 1e5,
|
|
389
|
+
lng: Math.round(r.lon / 1e6 * 1e5) / 1e5,
|
|
390
390
|
positionTime: b.unix(),
|
|
391
391
|
utc: b.utc().format(),
|
|
392
392
|
method: "trajectory",
|
|
393
393
|
vendor: "shipxy"
|
|
394
394
|
}, g = Math.floor(b.diff(k, "minute", !0) / (a || 1));
|
|
395
|
-
g !==
|
|
395
|
+
g !== y && (y = g, I.push(x));
|
|
396
396
|
}
|
|
397
397
|
return I;
|
|
398
398
|
}
|
|
@@ -447,35 +447,35 @@ class It extends U {
|
|
|
447
447
|
}
|
|
448
448
|
}, s = "https://api3.myships.com/sp/ships/position/latest", d = await R.post(s, n).json();
|
|
449
449
|
M == null || M.info("[%s] fetch realtime position from: %s - %j", o.requestId, s, n);
|
|
450
|
-
const
|
|
451
|
-
for (const u in
|
|
452
|
-
!isNaN(
|
|
453
|
-
const { labelCn: l, labelEn:
|
|
450
|
+
const c = d.data[0];
|
|
451
|
+
for (const u in c)
|
|
452
|
+
!isNaN(c[u]) && Number(c[u]) !== 1 / 0 && (c[u] = Number(c[u]));
|
|
453
|
+
const { labelCn: l, labelEn: m } = await this.parseStatus(c.aisNavStatus), f = v.unix(c.posTime);
|
|
454
454
|
return {
|
|
455
455
|
...a,
|
|
456
456
|
mmsi: t,
|
|
457
|
-
lat: Math.round(
|
|
458
|
-
lng: Math.round(
|
|
459
|
-
sog: Math.round(
|
|
460
|
-
cog: Math.round(
|
|
461
|
-
hdg: Math.round(
|
|
462
|
-
rot: Math.round(
|
|
463
|
-
positionTime:
|
|
457
|
+
lat: Math.round(c.lat / 1e4 / 60 * 1e5) / 1e5,
|
|
458
|
+
lng: Math.round(c.lon / 1e4 / 60 * 1e5) / 1e5,
|
|
459
|
+
sog: Math.round(c.sog / 10 * 100) / 100,
|
|
460
|
+
cog: Math.round(c.cog / 10 * 100) / 100,
|
|
461
|
+
hdg: Math.round(c.heading * 100) / 100,
|
|
462
|
+
rot: Math.round(c.rot * 100) / 100,
|
|
463
|
+
positionTime: c.posTime,
|
|
464
464
|
utc: f.utc().format(),
|
|
465
|
-
status:
|
|
466
|
-
labelEn:
|
|
465
|
+
status: c.aisNavStatus,
|
|
466
|
+
labelEn: m,
|
|
467
467
|
labelCn: l,
|
|
468
468
|
method: "position",
|
|
469
469
|
vendor: "myship"
|
|
470
470
|
};
|
|
471
471
|
}
|
|
472
472
|
async trajectory(t, o, i, a, n = !0, s = {}) {
|
|
473
|
-
const d =
|
|
474
|
-
for (;
|
|
475
|
-
await this.trajectoryIn30Day(l, d.unix(), d.add(30, "day").unix(),
|
|
476
|
-
return await this.trajectoryIn30Day(l, d.unix(),
|
|
473
|
+
const d = v(o), c = v(i), l = await this.getShipId(t), m = await this.getShipInfo(l), f = [];
|
|
474
|
+
for (; c.diff(d, "day", !0) > 30; )
|
|
475
|
+
await this.trajectoryIn30Day(l, d.unix(), d.add(30, "day").unix(), m, t, a, f);
|
|
476
|
+
return await this.trajectoryIn30Day(l, d.unix(), c.unix(), m, t, a, f), f;
|
|
477
477
|
}
|
|
478
|
-
async trajectoryIn30Day(t, o, i, a, n, s, d,
|
|
478
|
+
async trajectoryIn30Day(t, o, i, a, n, s, d, c = {}) {
|
|
479
479
|
var k;
|
|
480
480
|
const l = {
|
|
481
481
|
headers: {
|
|
@@ -486,30 +486,30 @@ class It extends U {
|
|
|
486
486
|
startTime: o,
|
|
487
487
|
endTime: i
|
|
488
488
|
}
|
|
489
|
-
},
|
|
490
|
-
if (M == null || M.info("[%s] fetch trajectory from: %s - %j",
|
|
491
|
-
return M == null || M.warn("[%s] invoke myship trajectory failed: %j",
|
|
489
|
+
}, m = "https://api3.myships.com/sp/ships/position/history", f = await R.post(m, l).json();
|
|
490
|
+
if (M == null || M.info("[%s] fetch trajectory from: %s - %j", c.requestId, m, l), f.code !== "0")
|
|
491
|
+
return M == null || M.warn("[%s] invoke myship trajectory failed: %j", c.requestId, f), f;
|
|
492
492
|
const h = f.data;
|
|
493
|
-
for (const
|
|
494
|
-
!isNaN(h[
|
|
495
|
-
const u =
|
|
493
|
+
for (const y in h)
|
|
494
|
+
!isNaN(h[y]) && Number(h[y]) !== 1 / 0 && (h[y] = Number(h[y]));
|
|
495
|
+
const u = v.unix((k = h[0]) == null ? void 0 : k.posTime);
|
|
496
496
|
let I = -1;
|
|
497
|
-
for (const
|
|
498
|
-
const
|
|
497
|
+
for (const y of h) {
|
|
498
|
+
const w = v.unix(y.posTime), r = {
|
|
499
499
|
imo: a == null ? void 0 : a.imo,
|
|
500
500
|
mmsi: n,
|
|
501
|
-
lat: Math.round(
|
|
502
|
-
lng: Math.round(
|
|
503
|
-
sog: Math.round(
|
|
504
|
-
cog: Math.round(
|
|
505
|
-
hdg: Math.round(
|
|
506
|
-
rot: Math.round(
|
|
507
|
-
positionTime:
|
|
508
|
-
utc:
|
|
501
|
+
lat: Math.round(y.lat / 1e4 / 60 * 1e5) / 1e5,
|
|
502
|
+
lng: Math.round(y.lon / 1e4 / 60 * 1e5) / 1e5,
|
|
503
|
+
sog: Math.round(y.sog / 10 * 100) / 100,
|
|
504
|
+
cog: Math.round(y.cog / 10 * 100) / 100,
|
|
505
|
+
hdg: Math.round(y.heading * 100) / 100,
|
|
506
|
+
rot: Math.round(y.rot * 100) / 100,
|
|
507
|
+
positionTime: w.unix(),
|
|
508
|
+
utc: w.utc().format(),
|
|
509
509
|
method: "trajectory",
|
|
510
510
|
vendor: "myship"
|
|
511
|
-
}, b = Math.floor(
|
|
512
|
-
b !== I && (I = b, d.push(
|
|
511
|
+
}, b = Math.floor(w.diff(u, "minute", !0) / (s || 1));
|
|
512
|
+
b !== I && (I = b, d.push(r));
|
|
513
513
|
}
|
|
514
514
|
return d;
|
|
515
515
|
}
|
|
@@ -520,7 +520,7 @@ try {
|
|
|
520
520
|
} catch {
|
|
521
521
|
} finally {
|
|
522
522
|
}
|
|
523
|
-
var it = /* @__PURE__ */ ((
|
|
523
|
+
var it = /* @__PURE__ */ ((S) => (S.NOTICE = "NOTICE", S.WARN = "WARN", S.HEAVY = "HEAVY", S.SEVERE = "SEVERE", S.ERROR = "ERROR", S.FATAL = "FATAL", S))(it || {});
|
|
524
524
|
class rt {
|
|
525
525
|
/**
|
|
526
526
|
* 解析告警规则, 多规则场景
|
|
@@ -531,19 +531,19 @@ class rt {
|
|
|
531
531
|
* @param options
|
|
532
532
|
*/
|
|
533
533
|
parsePrinciple(e, t = {}) {
|
|
534
|
-
var s, d,
|
|
534
|
+
var s, d, c;
|
|
535
535
|
W == null || W.info("[%s] parse rule: %s", t.requestId, e);
|
|
536
536
|
const o = new RegExp("(?<=\\[)(.+)(?=])", "g"), i = e.match(o) ? (s = e.match(o)) == null ? void 0 : s[0] : void 0, a = i == null ? void 0 : i.split(";");
|
|
537
537
|
if (!a)
|
|
538
538
|
return;
|
|
539
539
|
const n = {};
|
|
540
540
|
for (let l = 0; l < (a == null ? void 0 : a.length); l++) {
|
|
541
|
-
const
|
|
542
|
-
if (l === 0 && !
|
|
541
|
+
const m = (c = (d = a[l].match(o)) == null ? void 0 : d[0]) == null ? void 0 : c.split("],");
|
|
542
|
+
if (l === 0 && !m)
|
|
543
543
|
n.scope = a[0];
|
|
544
|
-
else if (
|
|
545
|
-
for (let f = 0, h =
|
|
546
|
-
const u = this.parseRule(
|
|
544
|
+
else if (m)
|
|
545
|
+
for (let f = 0, h = m.length; f < h; f++) {
|
|
546
|
+
const u = this.parseRule(m[f]);
|
|
547
547
|
u && (n[u.level] ? u.key ? n[u.level][u == null ? void 0 : u.key] = u : n[u.level] = u : u.key ? n[u.level] = { [u == null ? void 0 : u.key]: u } : n[u.level] = u);
|
|
548
548
|
}
|
|
549
549
|
}
|
|
@@ -575,14 +575,14 @@ class rt {
|
|
|
575
575
|
* @param options
|
|
576
576
|
*/
|
|
577
577
|
checkWeather(e, t, o = {}) {
|
|
578
|
-
var u, I, k,
|
|
578
|
+
var u, I, k, y, w, r, b, x, g, j, Y, C, q, T, D;
|
|
579
579
|
let i = 0, a = 0, n = 0, s = 0;
|
|
580
|
-
const d = Math.round(((I = (u = t == null ? void 0 : t.SEVERE) == null ? void 0 : u.sigWave) == null ? void 0 : I.number) * 1.6 * 100) / 100,
|
|
580
|
+
const d = Math.round(((I = (u = t == null ? void 0 : t.SEVERE) == null ? void 0 : u.sigWave) == null ? void 0 : I.number) * 1.6 * 100) / 100, c = (y = (k = t == null ? void 0 : t.SEVERE) == null ? void 0 : k.sigWave) == null ? void 0 : y.number, l = (r = (w = t == null ? void 0 : t.HEAVY) == null ? void 0 : w.sigWave) == null ? void 0 : r.number, m = Math.round((((x = (b = t == null ? void 0 : t.SEVERE) == null ? void 0 : b.wind) == null ? void 0 : x.number) + 2) * 100) / 100, f = (j = (g = t == null ? void 0 : t.SEVERE) == null ? void 0 : g.wind) == null ? void 0 : j.number, h = (C = (Y = t == null ? void 0 : t.HEAVY) == null ? void 0 : Y.wind) == null ? void 0 : C.number;
|
|
581
581
|
for (let V = 0; V < (e == null ? void 0 : e.length); V++) {
|
|
582
|
-
const H = e[V],
|
|
583
|
-
s = J > s ? J : s, W == null || W.info("[%s] check sig.wave: %j", o.requestId, { ...
|
|
582
|
+
const H = e[V], P = (T = (q = H == null ? void 0 : H.meteo) == null ? void 0 : q.wave) == null ? void 0 : T.sig, A = (D = H == null ? void 0 : H.meteo) == null ? void 0 : D.wind, J = V ? v(H.eta).diff(v(e[V - 1].eta), "hour", !0) : 0;
|
|
583
|
+
s = J > s ? J : s, W == null || W.info("[%s] check sig.wave: %j", o.requestId, { ...P, dgThd4Wv: d, svThd4Wv: c, hvThd4Wv: l }), (P == null ? void 0 : P.height) >= d ? H.isDangerous = !0 : (P == null ? void 0 : P.height) >= c ? H.isSevere = !0 : (P == null ? void 0 : P.height) >= l && (H.isHeavy = !0), W == null || W.info("[%s] check wind: %j", o.requestId, { ...A, dgThd4Wd: m, svThd4Wd: f, hvThd4Wd: h }), (A == null ? void 0 : A.scale) >= m ? (H.isDangerous = !0, delete H.isSevere, delete H.isHeavy) : (A == null ? void 0 : A.scale) > f ? (H.isDangerous || (H.isSevere = !0), delete H.isHeavy) : (A == null ? void 0 : A.scale) === h && !H.isDangerous && !H.isSevere && (H.isHeavy = !0), i += H.isDangerous ? J : 0, a += H.isSevere ? J : 0, n += H.isHeavy ? J : 0;
|
|
584
584
|
}
|
|
585
|
-
return i = Math.round(i * 100) / 100, a = Math.round(a * 100) / 100, n = Math.round(n * 100) / 100, s = Math.round(s), { sample: e, dangerous: i, severe: a, heavy: n, step: s < 3 ? 3 : s, wind: { dgThd4Wd:
|
|
585
|
+
return i = Math.round(i * 100) / 100, a = Math.round(a * 100) / 100, n = Math.round(n * 100) / 100, s = Math.round(s), { sample: e, dangerous: i, severe: a, heavy: n, step: s < 3 ? 3 : s, wind: { dgThd4Wd: m, svThd4Wd: f, hvThd4Wd: h }, sig: { dgThd4Wv: d, svThd4Wv: c, hvThd4Wv: l } };
|
|
586
586
|
}
|
|
587
587
|
}
|
|
588
588
|
const kt = new rt();
|
|
@@ -593,8 +593,8 @@ try {
|
|
|
593
593
|
} finally {
|
|
594
594
|
}
|
|
595
595
|
const ct = new ot("", !0);
|
|
596
|
-
var dt = /* @__PURE__ */ ((
|
|
597
|
-
class
|
|
596
|
+
var dt = /* @__PURE__ */ ((S) => (S.common = "common", S.container = "container", S.tugs = "tugs", S))(dt || {}), ut = /* @__PURE__ */ ((S) => (S.Ballast = "Ballast", S.Laden = "Laden", S))(ut || {}), ht = /* @__PURE__ */ ((S) => (S.Cp = "CP", S.Perf = "Basis", S.Instruct = "Other", S))(ht || {});
|
|
597
|
+
class E {
|
|
598
598
|
/**
|
|
599
599
|
* @see https://baike.baidu.com/item/%E6%96%B9%E5%BD%A2%E7%B3%BB%E6%95%B0/4965568?fr=aladdin
|
|
600
600
|
* 方形系数(block coefficient)
|
|
@@ -707,9 +707,9 @@ class q {
|
|
|
707
707
|
*/
|
|
708
708
|
static assembleProperties(e, t, o, i) {
|
|
709
709
|
var f;
|
|
710
|
-
const a = e.lbp ?? e.length ?? e.lengthOverall ?? 198.9642, n = e.draught ?? 8, s = e.breadthMoulded ?? e.breadth ?? e.breadthExtreme ?? 32.4572, d = e.deadweight ?? 67035.7773,
|
|
710
|
+
const a = e.lbp ?? e.length ?? e.lengthOverall ?? 198.9642, n = e.draught ?? 8, s = e.breadthMoulded ?? e.breadth ?? e.breadthExtreme ?? 32.4572, d = e.deadweight ?? 67035.7773, c = ((f = e == null ? void 0 : e.type) == null ? void 0 : f.toLowerCase()) || "common";
|
|
711
711
|
return {
|
|
712
|
-
tag:
|
|
712
|
+
tag: c.indexOf("container") > -1 ? "container" : c.indexOf("tugs") > -1 ? "tugs" : "common",
|
|
713
713
|
lbp: a,
|
|
714
714
|
loadCondition: t,
|
|
715
715
|
draught: n,
|
|
@@ -733,7 +733,7 @@ class q {
|
|
|
733
733
|
* @param useRouteParam true 启用设置速度
|
|
734
734
|
*/
|
|
735
735
|
static async speedLoseAt(e, t, o, i = "", a = 2, n = !0, s = !1, d = {}) {
|
|
736
|
-
let
|
|
736
|
+
let c;
|
|
737
737
|
if (t.velocity && s && (e.speed = z.roundPrecision(t.velocity * 1852 / 3600, 6)), n) {
|
|
738
738
|
let l;
|
|
739
739
|
if (d.meteo2)
|
|
@@ -745,24 +745,24 @@ class q {
|
|
|
745
745
|
}
|
|
746
746
|
else
|
|
747
747
|
l = await nt.queryPointFactor(t.lng, t.lat, o.valueOf(), "wind,wave,current,watertemp", i, d);
|
|
748
|
-
const
|
|
749
|
-
|
|
748
|
+
const m = E.weatherFactor(e, l), f = E.currentFactor(e.bearing, l == null ? void 0 : l.current, a), h = Math.round((e.speed * 1.943844 + m + f) * 100) / 100;
|
|
749
|
+
c = {
|
|
750
750
|
meteo: { ...l },
|
|
751
|
-
wxFactor:
|
|
751
|
+
wxFactor: m,
|
|
752
752
|
cFactor: f,
|
|
753
753
|
speed: t.velocity && s ? t.velocity : h < 0 ? 1 : h,
|
|
754
754
|
eta: o.utc().format("YYYY-MM-DDTHH:mm[Z]"),
|
|
755
755
|
etd: o.utc().format("YYYY-MM-DDTHH:mm[Z]")
|
|
756
756
|
};
|
|
757
757
|
} else
|
|
758
|
-
|
|
758
|
+
c = {
|
|
759
759
|
wxFactor: 0,
|
|
760
760
|
cFactor: 0,
|
|
761
761
|
speed: t.velocity && s ? t.velocity : Math.round((e.speed * 1.943844 + 0 + 0) * 100) / 100,
|
|
762
762
|
eta: o.utc().format("YYYY-MM-DDTHH:mm[Z]"),
|
|
763
763
|
etd: o.utc().format("YYYY-MM-DDTHH:mm[Z]")
|
|
764
764
|
};
|
|
765
|
-
return delete t.meteo, delete t.wxFactor, delete t.cFactor, delete t.speed, delete t.etd, { ...
|
|
765
|
+
return delete t.meteo, delete t.wxFactor, delete t.cFactor, delete t.speed, delete t.etd, { ...c, ...t };
|
|
766
766
|
}
|
|
767
767
|
/**
|
|
768
768
|
* 基于步长计算失速样本
|
|
@@ -777,53 +777,53 @@ class q {
|
|
|
777
777
|
* @param useRouteParam true 启用航线上设置的参数 { suspend: 停留时长(小时), velocity: 速度(kts)}
|
|
778
778
|
* @private
|
|
779
779
|
*/
|
|
780
|
-
static async speedLoseInHoursStep(e, t, o, i, a, n, s = "", d = !0,
|
|
780
|
+
static async speedLoseInHoursStep(e, t, o, i, a, n, s = "", d = !0, c = !1, l = {}) {
|
|
781
781
|
t.utc();
|
|
782
|
-
const
|
|
783
|
-
let u = 0, I = 0, k,
|
|
784
|
-
for (let
|
|
785
|
-
let
|
|
786
|
-
|
|
787
|
-
const b = n[
|
|
788
|
-
if (e.bearing = B.calculateBearing(
|
|
789
|
-
|
|
790
|
-
const j =
|
|
782
|
+
const m = t.clone().add(14, "days"), f = [], h = [];
|
|
783
|
+
let u = 0, I = 0, k, y;
|
|
784
|
+
for (let w = 0; w < n.length - 1; w++) {
|
|
785
|
+
let r = n[w];
|
|
786
|
+
r.distanceFromStart = Math.round((a + I) * 1e4) / 1e4;
|
|
787
|
+
const b = n[w + 1];
|
|
788
|
+
if (e.bearing = B.calculateBearing(r, b, !b.gcToPrevious), r.bearing = e.bearing, r.suspend && c) {
|
|
789
|
+
r.eta = r.eta || t.format("YYYY-MM-DDTHH:mm[Z]"), r.elapsed = r.elapsed ?? 0;
|
|
790
|
+
const j = r.suspend - r.elapsed;
|
|
791
791
|
if (i - u > j)
|
|
792
|
-
i = i - u - j, t.add(j, "hour"),
|
|
792
|
+
i = i - u - j, t.add(j, "hour"), r.elapsed = r.suspend;
|
|
793
793
|
else {
|
|
794
|
-
const
|
|
795
|
-
|
|
794
|
+
const Y = i - u;
|
|
795
|
+
r.elapsed += Y, t.add(Y, "hour"), i = 0;
|
|
796
796
|
}
|
|
797
|
-
if (p == null || p.info(`[%s] suspend ${
|
|
798
|
-
return
|
|
797
|
+
if (p == null || p.info(`[%s] suspend ${r.elapsed} hours at %j, and remain ${i} hours need to go...`, l.requestId, r), i === 0)
|
|
798
|
+
return r.distanceFromPrevious = I, { etd: t, from: y || r, to: r, next: n.filter((Y) => Y), wps: f, days: h };
|
|
799
799
|
} else
|
|
800
|
-
|
|
801
|
-
d = t.isAfter(
|
|
802
|
-
const
|
|
803
|
-
let g = Math.ceil(
|
|
800
|
+
r.suspend = 0;
|
|
801
|
+
d = t.isAfter(m) ? !1 : d, r = await E.speedLoseAt(e, r, t, s, 0, d, c, l), y = y || r, r.important && f.push(r), t.isSameOrAfter(o) && (h.push(r), o.add(24, "hour"));
|
|
802
|
+
const x = B.calculateDistance(r, b, !b.gcToPrevious);
|
|
803
|
+
let g = Math.ceil(x / y.speed * 1e4) / 1e4;
|
|
804
804
|
if (u + g < i) {
|
|
805
|
-
if (u += g, t.add(g, "hour"), delete n[
|
|
806
|
-
`[%s] go to %j from %j with ${
|
|
805
|
+
if (u += g, t.add(g, "hour"), delete n[w], p == null || p.debug(
|
|
806
|
+
`[%s] go to %j from %j with ${x}nm, and cost ${g} hours`,
|
|
807
807
|
l.requestId,
|
|
808
808
|
{ lat: b.lat, lng: b.lng },
|
|
809
|
-
{ lat:
|
|
810
|
-
), I +=
|
|
811
|
-
k = b, k.eta = t.format("YYYY-MM-DDTHH:mm[Z]"), k.distanceFromPrevious =
|
|
809
|
+
{ lat: y.lat, lng: y.lng, etd: y.etd }
|
|
810
|
+
), I += x, n.filter((j) => j).length <= 1) {
|
|
811
|
+
k = b, k.eta = t.format("YYYY-MM-DDTHH:mm[Z]"), k.distanceFromPrevious = x, k.distanceFromStart = Math.round((a + I) * 1e4) / 1e4, f.push(k), delete n[w + 1];
|
|
812
812
|
break;
|
|
813
813
|
}
|
|
814
814
|
} else {
|
|
815
815
|
g = i - u, t.add(g, "hour");
|
|
816
|
-
const j = z.roundPrecision(
|
|
817
|
-
k = B.calculateCoordinate(
|
|
816
|
+
const j = z.roundPrecision(y.speed * g, 4);
|
|
817
|
+
k = B.calculateCoordinate(r, e.bearing, j, "nauticalmiles", !b.gcToPrevious), k.eta = t.format("YYYY-MM-DDTHH:mm[Z]"), n[w] = k, p == null || p.debug(
|
|
818
818
|
`[%s] go to %j from %j with ${j}nm, and cost ${g} hours`,
|
|
819
819
|
l.requestId,
|
|
820
820
|
{ lat: k.lat, lng: k.lng },
|
|
821
|
-
{ lat:
|
|
821
|
+
{ lat: r.lat, lng: r.lng, etd: r.etd }
|
|
822
822
|
), I += j, k.distanceFromPrevious = Math.round(I * 1e4) / 1e4, k.distanceFromStart = Math.round((a + I) * 1e4) / 1e4;
|
|
823
823
|
break;
|
|
824
824
|
}
|
|
825
825
|
}
|
|
826
|
-
return { etd: t, from:
|
|
826
|
+
return { etd: t, from: y, to: k, next: n.filter((w) => w), wps: f, days: h };
|
|
827
827
|
}
|
|
828
828
|
/**
|
|
829
829
|
* 洋流影响因子
|
|
@@ -844,16 +844,16 @@ class q {
|
|
|
844
844
|
* @param wwc 气象要素
|
|
845
845
|
*/
|
|
846
846
|
static weatherFactor(e, t) {
|
|
847
|
-
var
|
|
847
|
+
var m, f, h, u, I, k, y;
|
|
848
848
|
p == null || p.debug("calculate weather factor via: %j", { ...e, ...t });
|
|
849
|
-
const o =
|
|
850
|
-
let n = Math.abs(e.bearing % 360 - (((
|
|
849
|
+
const o = E.blockCoefficient(e.displacement, e.lbp, e.breadthMoulded, e.draught), i = E.froudeNumber(e.speed, e.lbp), a = E.amendFactor(o, i, e.loadCondition);
|
|
850
|
+
let n = Math.abs(e.bearing % 360 - (((m = t == null ? void 0 : t.wind) == null ? void 0 : m.degree) % 360 || 0));
|
|
851
851
|
n = n > 180 ? 360 - n : n;
|
|
852
|
-
const s =
|
|
853
|
-
let
|
|
854
|
-
|
|
855
|
-
const l =
|
|
856
|
-
return p == null || p.debug("wave wx factor = %d", l),
|
|
852
|
+
const s = E.directionFactor(n, (f = t == null ? void 0 : t.wind) == null ? void 0 : f.scale), d = E.vesselTagFactor(e.displacement, e.loadCondition, e.tag, (h = t == null ? void 0 : t.wind) == null ? void 0 : h.scale);
|
|
853
|
+
let c = s * a * d / 100 * e.speed;
|
|
854
|
+
c = Math.round(c * 1.943844 * 1e4) / 1e4 * -1, e.tag === "tugs" && Math.abs(c) > 1 && (c = c / (Math.abs(Math.round(c)) + 1)), p == null || p.debug("wind wx factor = %d", c), n = Math.abs(e.bearing % 360 - (((I = (u = t == null ? void 0 : t.wave) == null ? void 0 : u.sig) == null ? void 0 : I.degree) % 360 || 0));
|
|
855
|
+
const l = E.waveHeightFactor(((y = (k = t == null ? void 0 : t.wave) == null ? void 0 : k.sig) == null ? void 0 : y.height) ?? 1, n);
|
|
856
|
+
return p == null || p.debug("wave wx factor = %d", l), c = c * 0.4 + l, p == null || p.debug("weather factor = %d", c), c = Math.abs(c) > 4 ? 4 * (Math.abs(c) / c) + Math.abs(c) / c * (Math.abs(c) - 4) * 0.1 : c, Math.round((c || 0) * 100) / 100;
|
|
857
857
|
}
|
|
858
858
|
/**
|
|
859
859
|
* 全程失速分析(走完航程)
|
|
@@ -867,9 +867,9 @@ class q {
|
|
|
867
867
|
* @param useMeteo true 启用气象分析
|
|
868
868
|
* @param useRouteParam
|
|
869
869
|
*/
|
|
870
|
-
static async analyseInstant(e, t, o, i, a, n = "", s = 0, d = !0,
|
|
871
|
-
var J,
|
|
872
|
-
const
|
|
870
|
+
static async analyseInstant(e, t, o, i, a, n = "", s = 0, d = !0, c = !1, l = {}) {
|
|
871
|
+
var J, _, K, G, L;
|
|
872
|
+
const m = v().valueOf();
|
|
873
873
|
e.lng = z.convertToStdLng(e.lng);
|
|
874
874
|
const { route: f, waypoints: h } = a.points, u = B.calculateSubRoute(e, f);
|
|
875
875
|
if (((J = u[0]) == null ? void 0 : J.length) <= 1)
|
|
@@ -882,12 +882,12 @@ class q {
|
|
|
882
882
|
v0: i.speed,
|
|
883
883
|
label: "CP"
|
|
884
884
|
/* Cp */
|
|
885
|
-
},
|
|
886
|
-
|
|
887
|
-
const
|
|
885
|
+
}, y = E.assembleProperties(o, i.loadCondition, I, 0), w = h.length ? B.calculateSubWaypoints(e, h) : [];
|
|
886
|
+
w.forEach((N) => N.important = !0);
|
|
887
|
+
const r = {
|
|
888
888
|
from: { ...e },
|
|
889
889
|
route: u,
|
|
890
|
-
waypoints:
|
|
890
|
+
waypoints: w,
|
|
891
891
|
v0: I,
|
|
892
892
|
label: k
|
|
893
893
|
}, b = {
|
|
@@ -896,45 +896,45 @@ class q {
|
|
|
896
896
|
wps: []
|
|
897
897
|
};
|
|
898
898
|
s || (B.calculateRouteDistance(u) / i.speed <= 72 ? s = 3 : s = 6);
|
|
899
|
-
let
|
|
900
|
-
t =
|
|
901
|
-
const
|
|
902
|
-
for (;
|
|
903
|
-
const N = s - t.hour() % s,
|
|
904
|
-
|
|
899
|
+
let x = B.simplifyRouteToCoordinates(u, w, 0), g = 0, j = 0, Y = 0, C = 0;
|
|
900
|
+
t = v(t).utc();
|
|
901
|
+
const q = t.clone();
|
|
902
|
+
for (; x.length > 0; ) {
|
|
903
|
+
const N = s - t.hour() % s, F = Math.ceil(t.clone().add(N, "h").set({ minute: 0, second: 0, millisecond: 0 }).diff(t, "h", !0) * 1e4) / 1e4, O = await E.speedLoseInHoursStep(
|
|
904
|
+
y,
|
|
905
905
|
t,
|
|
906
|
+
q,
|
|
906
907
|
F,
|
|
907
|
-
x,
|
|
908
908
|
g,
|
|
909
|
-
|
|
909
|
+
x,
|
|
910
910
|
n,
|
|
911
911
|
d,
|
|
912
|
-
|
|
912
|
+
c,
|
|
913
913
|
l
|
|
914
914
|
);
|
|
915
|
-
(
|
|
915
|
+
(_ = O.from) != null && _.speed && (b.hours.push(O.from), b.wps.push(...O.wps), b.days.push(...O.days)), x = O == null ? void 0 : O.next, x.length || b.hours.push(O == null ? void 0 : O.to), g += Math.round((((K = O == null ? void 0 : O.to) == null ? void 0 : K.distanceFromPrevious) ?? 0) * 1e4) / 1e4;
|
|
916
916
|
}
|
|
917
|
-
const
|
|
918
|
-
for (let N = 0; N <
|
|
919
|
-
const
|
|
920
|
-
j += (
|
|
917
|
+
const T = b.hours;
|
|
918
|
+
for (let N = 0; N < T.length - 1; N++) {
|
|
919
|
+
const F = v(T[N + 1].eta).diff(T[N].etd, "hour", !0) || 1;
|
|
920
|
+
j += (T[N].wxFactor || 0) * F, Y += (T[N].cFactor || 0) * F, C += F;
|
|
921
921
|
}
|
|
922
|
-
(G = b.wps) == null || G.forEach((N,
|
|
923
|
-
if (
|
|
924
|
-
const
|
|
922
|
+
(G = b.wps) == null || G.forEach((N, F) => {
|
|
923
|
+
if (F) {
|
|
924
|
+
const O = b.wps[F - 1], et = N.distanceFromStart - O.distanceFromStart, X = v(N.eta).diff(v(O.etd), "h", !0);
|
|
925
925
|
if (X < 1)
|
|
926
|
-
N.avgSpd =
|
|
926
|
+
N.avgSpd = O.speed;
|
|
927
927
|
else {
|
|
928
928
|
N.avgSpd = Math.round(et / X * 100) / 100;
|
|
929
|
-
const $ = Math.round((
|
|
929
|
+
const $ = Math.round((O.speed + N.speed) / 2 * 100) / 100;
|
|
930
930
|
N.avgSpd = N.avgSpd > $ ? $ : N.avgSpd;
|
|
931
931
|
}
|
|
932
932
|
}
|
|
933
|
-
}),
|
|
934
|
-
const
|
|
935
|
-
|
|
936
|
-
const
|
|
937
|
-
return p == null || p.info("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms", l == null ? void 0 : l.requestId,
|
|
933
|
+
}), r.sample = b;
|
|
934
|
+
const D = b.hours.at(0), V = b.hours.at(-1);
|
|
935
|
+
r.distance = Math.round(V.distanceFromStart * 1e4) / 1e4, r.etd = v(D.eta).utc().format(), r.eta = v(V.eta).utc().format(), r.wxFactor = Math.round(j / C * 1e4) / 1e4, r.cFactor = Math.round(Y / C * 1e4) / 1e4, r.avgSpeed = Math.round(V.distanceFromStart / C * 1e4) / 1e4, r.totalHrs = Math.round(C * 1e4) / 1e4, r.totalFoCons = Math.round((i == null ? void 0 : i.fo) / 24 * r.totalHrs * 1e3) / 1e3, r.totalDgoCons = Math.round((i == null ? void 0 : i.dgo) / 24 * r.totalHrs * 1e3) / 1e3;
|
|
936
|
+
const P = v().valueOf() - m, A = ((L = b == null ? void 0 : b.hours) == null ? void 0 : L.length) || 1;
|
|
937
|
+
return p == null || p.info("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms", l == null ? void 0 : l.requestId, P, A, Math.round(P / A * 1e3) / 1e3), r;
|
|
938
938
|
}
|
|
939
939
|
/**
|
|
940
940
|
* 分段失速分析(最多走hours 小时)
|
|
@@ -949,9 +949,9 @@ class q {
|
|
|
949
949
|
* @param useMeteo true 启用气象分析
|
|
950
950
|
* @param useRouteParam
|
|
951
951
|
*/
|
|
952
|
-
static async analyseInstantWithThreshed(e, t, o, i, a, n, s, d = "",
|
|
953
|
-
var J,
|
|
954
|
-
const h =
|
|
952
|
+
static async analyseInstantWithThreshed(e, t, o, i, a, n, s, d = "", c = 3, l = !0, m = !1, f = {}) {
|
|
953
|
+
var J, _, K, G;
|
|
954
|
+
const h = v().valueOf();
|
|
955
955
|
e.lng = z.convertToStdLng(e.lng);
|
|
956
956
|
const { v0: u, label: I } = e.sog ? {
|
|
957
957
|
v0: e.sog,
|
|
@@ -961,64 +961,52 @@ class q {
|
|
|
961
961
|
v0: a.speed,
|
|
962
962
|
label: "CP"
|
|
963
963
|
/* Cp */
|
|
964
|
-
}, k =
|
|
965
|
-
if (((J =
|
|
964
|
+
}, k = E.assembleProperties(i, a.loadCondition, u, 0), y = B.calculateSubRoute(e, n);
|
|
965
|
+
if (((J = y[0]) == null ? void 0 : J.length) <= 1)
|
|
966
966
|
return;
|
|
967
|
-
const
|
|
968
|
-
|
|
969
|
-
let
|
|
970
|
-
const
|
|
967
|
+
const w = s.length ? B.calculateSubWaypoints(e, s) : [];
|
|
968
|
+
w.forEach((L) => L.important = !0);
|
|
969
|
+
let r = B.simplifyRouteToCoordinates(y, w, 0), b = 0, x = 0, g = 0, j = 0;
|
|
970
|
+
const Y = {
|
|
971
971
|
hours: [],
|
|
972
972
|
wps: [],
|
|
973
973
|
days: []
|
|
974
974
|
};
|
|
975
|
-
t =
|
|
976
|
-
const
|
|
977
|
-
for (;
|
|
978
|
-
const L =
|
|
975
|
+
t = v(t).utc();
|
|
976
|
+
const C = t.clone();
|
|
977
|
+
for (; r.length > 0; ) {
|
|
978
|
+
const L = c - t.hour() % c;
|
|
979
979
|
let N = Math.ceil(t.clone().add(L, "h").set({ minute: 0, second: 0, millisecond: 0 }).diff(t, "h", !0) * 1e4) / 1e4;
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
t,
|
|
984
|
-
T,
|
|
985
|
-
N,
|
|
986
|
-
b,
|
|
987
|
-
c,
|
|
988
|
-
d,
|
|
989
|
-
l,
|
|
990
|
-
y,
|
|
991
|
-
f
|
|
992
|
-
);
|
|
993
|
-
(K = x.from) != null && K.speed && (S.hours.push(x.from), x != null && x.wps && S.wps.push(...x.wps), S.days.push(...x.days)), c = x == null ? void 0 : x.next, c.length || S.hours.push(x == null ? void 0 : x.to), b += Math.round((((_ = x == null ? void 0 : x.to) == null ? void 0 : _.distanceFromPrevious) ?? 0) * 1e4) / 1e4;
|
|
994
|
-
} else
|
|
980
|
+
N = t.clone().add(N, "h").isSameOrAfter(o) ? o.diff(t, "h", !0) * 1e4 / 1e4 : N;
|
|
981
|
+
const F = await E.speedLoseInHoursStep(k, t, C, N, b, r, d, l, m, f);
|
|
982
|
+
if ((_ = F.from) != null && _.speed && (Y.hours.push(F.from), F != null && F.wps && Y.wps.push(...F.wps), Y.days.push(...F.days)), r = F == null ? void 0 : F.next, r.length || Y.hours.push(F == null ? void 0 : F.to), b += Math.round((((K = F == null ? void 0 : F.to) == null ? void 0 : K.distanceFromPrevious) ?? 0) * 1e4) / 1e4, !N)
|
|
995
983
|
break;
|
|
996
984
|
}
|
|
997
|
-
const
|
|
998
|
-
for (let L = 0; L <
|
|
999
|
-
const N =
|
|
1000
|
-
|
|
985
|
+
const q = Y.hours;
|
|
986
|
+
for (let L = 0; L < q.length - 1; L++) {
|
|
987
|
+
const N = v(q[L + 1].eta).diff(q[L].etd, "hour", !0);
|
|
988
|
+
x += q[L].wxFactor * N, g += q[L].cFactor * N, j += N;
|
|
1001
989
|
}
|
|
1002
|
-
const
|
|
1003
|
-
sample:
|
|
1004
|
-
distance: Math.round(((
|
|
990
|
+
const T = Y.hours.at(0), D = Y.hours.at(-1), V = {
|
|
991
|
+
sample: Y,
|
|
992
|
+
distance: Math.round(((D == null ? void 0 : D.distanceFromStart) || 0) * 1e4) / 1e4,
|
|
1005
993
|
// 注意,可能会在first节点Drift,所有采用eta做为初始出发时间
|
|
1006
|
-
etd:
|
|
1007
|
-
eta:
|
|
1008
|
-
wxFactor: Math.round(
|
|
994
|
+
etd: v(T.eta).utc().format(),
|
|
995
|
+
eta: v(D == null ? void 0 : D.eta).utc().format(),
|
|
996
|
+
wxFactor: Math.round(x / j * 1e4) / 1e4,
|
|
1009
997
|
cFactor: Math.round(g / j * 1e4) / 1e4,
|
|
1010
|
-
avgSpeed: Math.round(((
|
|
998
|
+
avgSpeed: Math.round(((D == null ? void 0 : D.distanceFromStart) || 0) / j * 1e4) / 1e4,
|
|
1011
999
|
totalHrs: Math.round(j * 1e4) / 1e4,
|
|
1012
1000
|
totalFoCons: Math.round((a == null ? void 0 : a.fo) / 24 * j * 1e3) / 1e3,
|
|
1013
1001
|
totalDgoCons: Math.round((a == null ? void 0 : a.dgo) / 24 * j * 1e3) / 1e3,
|
|
1014
|
-
from:
|
|
1015
|
-
to:
|
|
1016
|
-
route:
|
|
1017
|
-
waypoints:
|
|
1002
|
+
from: T,
|
|
1003
|
+
to: D,
|
|
1004
|
+
route: y,
|
|
1005
|
+
waypoints: w,
|
|
1018
1006
|
v0: u,
|
|
1019
1007
|
label: I
|
|
1020
|
-
},
|
|
1021
|
-
return p == null || p.debug("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms", f == null ? void 0 : f.requestId,
|
|
1008
|
+
}, P = v().valueOf() - h, A = ((G = Y == null ? void 0 : Y.hours) == null ? void 0 : G.length) || 1;
|
|
1009
|
+
return p == null || p.debug("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms", f == null ? void 0 : f.requestId, P, A, Math.round(P / A * 1e3) / 1e3), V;
|
|
1022
1010
|
}
|
|
1023
1011
|
/**
|
|
1024
1012
|
* 在指定航线条件下,基于多CP,动态计算最优成本(租金+油费)方案
|
|
@@ -1036,50 +1024,56 @@ class q {
|
|
|
1036
1024
|
* @param options
|
|
1037
1025
|
*/
|
|
1038
1026
|
static async analyseCost(e, t, o, i, a = {}) {
|
|
1039
|
-
var
|
|
1040
|
-
const n =
|
|
1041
|
-
a.meteo2 = !0, e.speedStep = e.speedStep || 3;
|
|
1042
|
-
const d =
|
|
1043
|
-
let
|
|
1044
|
-
|
|
1045
|
-
const
|
|
1027
|
+
var y, w;
|
|
1028
|
+
const n = v().valueOf(), s = [];
|
|
1029
|
+
a.meteo2 = !0, e.speedStep = e.speedStep || 3, e.alterStep = e.alterStep ?? 1;
|
|
1030
|
+
const d = B.calculateRouteDistance(i.route);
|
|
1031
|
+
let c = 0;
|
|
1032
|
+
o.forEach((r) => {
|
|
1033
|
+
const b = Math.ceil(d / r.speed / 24);
|
|
1034
|
+
c = c < b ? b : c;
|
|
1035
|
+
}), c = c * 1.3;
|
|
1036
|
+
const l = v.utc(e.etd).add(c ?? 14, "day");
|
|
1037
|
+
let m = 1;
|
|
1038
|
+
for (const r of o) {
|
|
1039
|
+
const b = JSON.parse(JSON.stringify(i.route)), x = JSON.parse(JSON.stringify(i.waypoints)), g = await E.analyseInstantWithThreshed(
|
|
1046
1040
|
{ lat: e.lat, lng: e.lng },
|
|
1047
1041
|
e.etd,
|
|
1048
|
-
|
|
1042
|
+
l,
|
|
1049
1043
|
t,
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1044
|
+
r,
|
|
1045
|
+
b,
|
|
1046
|
+
x,
|
|
1053
1047
|
e.meteoVendor,
|
|
1054
1048
|
e.speedStep,
|
|
1055
1049
|
e.useMeteo,
|
|
1056
1050
|
e.useRouteParam,
|
|
1057
1051
|
a
|
|
1058
1052
|
);
|
|
1059
|
-
|
|
1060
|
-
cost:
|
|
1061
|
-
distance:
|
|
1062
|
-
hours:
|
|
1063
|
-
cp: `${
|
|
1064
|
-
})),
|
|
1053
|
+
g && (await E.calculateCost(g, r, e, a), s.push(g), p == null || p.info("[%s][L%d-%d] analyse from %s to %s cost: %j", a.requestId, 1, m, e.etd, l.format(), {
|
|
1054
|
+
cost: g.cost.total,
|
|
1055
|
+
distance: g.distance,
|
|
1056
|
+
hours: g.totalHrs,
|
|
1057
|
+
cp: `${r.speed}/${r.fo}/${r.dgo}`
|
|
1058
|
+
})), m++;
|
|
1065
1059
|
}
|
|
1066
|
-
s.sort((
|
|
1067
|
-
const
|
|
1068
|
-
if (
|
|
1069
|
-
const
|
|
1070
|
-
let
|
|
1071
|
-
|
|
1072
|
-
let
|
|
1073
|
-
for (;
|
|
1074
|
-
const
|
|
1075
|
-
if (
|
|
1060
|
+
s.sort((r, b) => r.cost.total - b.cost.total);
|
|
1061
|
+
const f = s.at(0), h = s.at(1), u = [];
|
|
1062
|
+
if (u.push({ combined: !1, speeds: [f], cost: (y = f.cost) == null ? void 0 : y.total }), h) {
|
|
1063
|
+
const r = f.cost.cp, b = h.cost.cp, x = v(f.eta), g = v(f.etd), j = x.diff(g, "days", !0);
|
|
1064
|
+
let Y = Math.ceil(j / 2);
|
|
1065
|
+
Y = Y > 7 ? 7 : Y < e.alterStep ? e.alterStep : Y;
|
|
1066
|
+
let C = 2, q = { combined: !1, speeds: [h], cost: (w = h.cost) == null ? void 0 : w.total }, T;
|
|
1067
|
+
for (; Y >= e.alterStep; ) {
|
|
1068
|
+
const D = await E.combinedAnalyse(e, t, l, [r, b], i, Y, { ...a, level: C });
|
|
1069
|
+
if (q.cost > D.cost ? T ? (T == null ? void 0 : T.cost) > D.cost && (T = D) : (T = q, q = D) : (!T || (T == null ? void 0 : T.cost) > D.cost) && (T = D), Y <= e.alterStep)
|
|
1076
1070
|
break;
|
|
1077
|
-
|
|
1071
|
+
Y = Math.ceil(Y / 2), C += 1;
|
|
1078
1072
|
}
|
|
1079
|
-
|
|
1073
|
+
u.push(q), T && u.push(T);
|
|
1080
1074
|
}
|
|
1081
|
-
const
|
|
1082
|
-
return p == null || p.info("[%s] analyse elapsed: %d ms", a == null ? void 0 : a.requestId,
|
|
1075
|
+
const k = v().valueOf() - n;
|
|
1076
|
+
return p == null || p.info("[%s] analyse elapsed: %d ms", a == null ? void 0 : a.requestId, k), u.sort((r, b) => r.cost - b.cost);
|
|
1083
1077
|
}
|
|
1084
1078
|
/**
|
|
1085
1079
|
* 按步长多次减半,分别用7,4,2,1天步长及cpa,cpb交替计算各种组合下的成本
|
|
@@ -1093,10 +1087,10 @@ class q {
|
|
|
1093
1087
|
*/
|
|
1094
1088
|
static async combinedAnalyse(e, t, o, i, a, n, s = {}) {
|
|
1095
1089
|
s.counter = 1, p == null || p.info("[%s][L%d] analyse with alternate cp in every %d days", s.requestId, s.level, n);
|
|
1096
|
-
const d = await
|
|
1097
|
-
p == null || p.info("[%s][L%d] cost with cpa/cpb turn: %d", s.requestId, s.level,
|
|
1098
|
-
const l = await
|
|
1099
|
-
return p == null || p.info("[%s][L%d] cost with cpb/cpa turn: %d", s.requestId, s.level,
|
|
1090
|
+
const d = await E.alternateAnalyse(e, t, o, i, 0, a, n, s), c = d.reduce((f, h) => f + h.cost.total, 0);
|
|
1091
|
+
p == null || p.info("[%s][L%d] cost with cpa/cpb turn: %d", s.requestId, s.level, c);
|
|
1092
|
+
const l = await E.alternateAnalyse(e, t, o, i, 1, a, n, s), m = l.reduce((f, h) => f + h.cost.total, 0);
|
|
1093
|
+
return p == null || p.info("[%s][L%d] cost with cpb/cpa turn: %d", s.requestId, s.level, m), c < m ? { combined: !0, cost: Math.round(c * 1e3) / 1e3, speeds: d } : { combined: !0, cost: Math.round(m * 1e3) / 1e3, speeds: l };
|
|
1100
1094
|
}
|
|
1101
1095
|
/**
|
|
1102
1096
|
* 基于cp索引,交替计算指定步长下的成本
|
|
@@ -1111,15 +1105,15 @@ class q {
|
|
|
1111
1105
|
*/
|
|
1112
1106
|
static async alternateAnalyse(e, t, o, i, a, n, s, d = {}) {
|
|
1113
1107
|
var f, h;
|
|
1114
|
-
let
|
|
1115
|
-
const l = { lat: e.lat, lng: e.lng },
|
|
1116
|
-
for (;
|
|
1117
|
-
const u =
|
|
1108
|
+
let c = v.utc(e.etd);
|
|
1109
|
+
const l = { lat: e.lat, lng: e.lng }, m = [];
|
|
1110
|
+
for (; c.isBefore(o); ) {
|
|
1111
|
+
const u = c.clone().utc().add(s, "day"), I = JSON.parse(JSON.stringify(n.route)), k = JSON.parse(JSON.stringify(n.waypoints)), y = i[a], w = await E.analyseInstantWithThreshed(
|
|
1118
1112
|
l,
|
|
1119
|
-
|
|
1113
|
+
c.format(),
|
|
1120
1114
|
u,
|
|
1121
1115
|
t,
|
|
1122
|
-
|
|
1116
|
+
y,
|
|
1123
1117
|
I,
|
|
1124
1118
|
k,
|
|
1125
1119
|
e.meteoVendor,
|
|
@@ -1128,22 +1122,22 @@ class q {
|
|
|
1128
1122
|
e.useRouteParam,
|
|
1129
1123
|
d
|
|
1130
1124
|
);
|
|
1131
|
-
|
|
1125
|
+
w && (await E.calculateCost(w, y, e, d), p == null || p.info(
|
|
1132
1126
|
"[%s][L%d-%d] analyse from %s to %s cost: %j",
|
|
1133
1127
|
d.requestId,
|
|
1134
1128
|
d.level,
|
|
1135
1129
|
d.counter,
|
|
1136
|
-
|
|
1130
|
+
c.utc().format(),
|
|
1137
1131
|
u.utc().format(),
|
|
1138
|
-
{ cost:
|
|
1132
|
+
{ cost: w.cost.total, distance: w.distance, hours: w.totalHrs, cp: `${y.speed}/${y.fo}/${y.dgo}` }
|
|
1139
1133
|
)), d.counter = d.counter + 1;
|
|
1140
|
-
const
|
|
1141
|
-
if (
|
|
1142
|
-
l.lat =
|
|
1134
|
+
const r = (h = (f = w == null ? void 0 : w.sample) == null ? void 0 : f.hours) == null ? void 0 : h.at(-1);
|
|
1135
|
+
if (r)
|
|
1136
|
+
l.lat = r.lat, l.lng = r.lng, c = v(r.eta), m.push(w), a = a ? 0 : 1;
|
|
1143
1137
|
else
|
|
1144
1138
|
break;
|
|
1145
1139
|
}
|
|
1146
|
-
return
|
|
1140
|
+
return m;
|
|
1147
1141
|
}
|
|
1148
1142
|
/**
|
|
1149
1143
|
* 计算Speed的cost
|
|
@@ -1169,18 +1163,18 @@ class q {
|
|
|
1169
1163
|
hours: [],
|
|
1170
1164
|
wps: [],
|
|
1171
1165
|
days: []
|
|
1172
|
-
}, i = e.reduce((h, u) => h + u.distance, 0), a = e.reduce((h, u) => h + u.totalHrs, 0), n = e.reduce((h, u) => h + u.wxFactor * u.totalHrs / a, 0), s = e.reduce((h, u) => h + u.cFactor * u.totalHrs / a, 0), d = e.reduce((h, u) => h + u.totalFoCons, 0),
|
|
1166
|
+
}, i = e.reduce((h, u) => h + u.distance, 0), a = e.reduce((h, u) => h + u.totalHrs, 0), n = e.reduce((h, u) => h + u.wxFactor * u.totalHrs / a, 0), s = e.reduce((h, u) => h + u.cFactor * u.totalHrs / a, 0), d = e.reduce((h, u) => h + u.totalFoCons, 0), c = e.reduce((h, u) => h + u.totalDgoCons, 0), l = e.reduce((h, u) => h + u.cost.total, 0), m = e.reduce((h, u) => h + u.cost.hire, 0), f = e.reduce((h, u) => h + u.cost.bunker, 0);
|
|
1173
1167
|
for (const h of e) {
|
|
1174
1168
|
const u = h.sample.hours, I = h.sample.wps, k = h.sample.days;
|
|
1175
|
-
u.forEach((
|
|
1176
|
-
var
|
|
1177
|
-
((
|
|
1178
|
-
}), I.forEach((
|
|
1179
|
-
var
|
|
1180
|
-
((
|
|
1181
|
-
}), k.forEach((
|
|
1182
|
-
var
|
|
1183
|
-
((
|
|
1169
|
+
u.forEach((y) => {
|
|
1170
|
+
var r;
|
|
1171
|
+
((r = o.hours) == null ? void 0 : r.findIndex((b) => b.eta === y.eta)) === -1 && o.hours.push(y);
|
|
1172
|
+
}), I.forEach((y) => {
|
|
1173
|
+
var r;
|
|
1174
|
+
((r = o.wps) == null ? void 0 : r.findIndex((b) => b.eta === y.eta)) === -1 && o.wps.push(y);
|
|
1175
|
+
}), k.forEach((y) => {
|
|
1176
|
+
var r;
|
|
1177
|
+
((r = o == null ? void 0 : o.days) == null ? void 0 : r.findIndex((b) => b.eta === y.eta)) === -1 && o.days.push(y);
|
|
1184
1178
|
});
|
|
1185
1179
|
}
|
|
1186
1180
|
return {
|
|
@@ -1196,10 +1190,10 @@ class q {
|
|
|
1196
1190
|
wxFactor: Math.round(n / a * 1e3) / 1e3,
|
|
1197
1191
|
cFactor: Math.round(s / a * 1e3) / 1e3,
|
|
1198
1192
|
totalFoCons: Math.round(d * 1e3) / 1e3,
|
|
1199
|
-
totalDgoCons: Math.round(
|
|
1193
|
+
totalDgoCons: Math.round(c * 1e3) / 1e3,
|
|
1200
1194
|
cost: {
|
|
1201
1195
|
total: Math.round(l * 1e3) / 1e3,
|
|
1202
|
-
hire: Math.round(
|
|
1196
|
+
hire: Math.round(m * 1e3) / 1e3,
|
|
1203
1197
|
bunker: Math.round(f * 1e3) / 1e3
|
|
1204
1198
|
}
|
|
1205
1199
|
};
|
|
@@ -1214,7 +1208,7 @@ export {
|
|
|
1214
1208
|
It as MyShipImpl,
|
|
1215
1209
|
vt as MyVesselImpl,
|
|
1216
1210
|
pt as ShipxyImpl,
|
|
1217
|
-
|
|
1211
|
+
E as SpeedHelper,
|
|
1218
1212
|
ht as SpeedLabel,
|
|
1219
1213
|
dt as VesselTag,
|
|
1220
1214
|
kt as alertHelper
|
package/dist/index.umd.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(T,D){typeof exports=="object"&&typeof module<"u"?D(exports,require("got"),require("@log4js-node/log4js-api"),require("moment"),require("@idm-plugin/geo"),require("@idm-plugin/meteo2"),require("@idm-plugin/meteo")):typeof define=="function"&&define.amd?define(["exports","got","@log4js-node/log4js-api","moment","@idm-plugin/geo","@idm-plugin/meteo2","@idm-plugin/meteo"],D):(T=typeof globalThis<"u"?globalThis:T||self,D(T["idm-plugin-rabbitmq"]={},T.got,T["@log4js-node/log4js-api"],T.moment,T["@idm-plugin/geo"],T["@idm-plugin/meteo2"],T["@idm-plugin/meteo"]))})(this,function(T,D,K,g,R,X,$){"use strict";var mt=Object.defineProperty;var yt=(T,D,K)=>D in T?mt(T,D,{enumerable:!0,configurable:!0,writable:!0,value:K}):T[D]=K;var _=(T,D,K)=>(yt(T,typeof D!="symbol"?D+"":D,K),K);let M;try{M=K.getLogger("vessel")}catch{}finally{}class G{parseStatus(e){let t,o;switch(e){case 0:t="在航(主机推动)",o="The engine is in use";break;case 1:t="锚泊",o="Anchored";break;case 2:t="失控",o="Not operated";break;case 3:t="操纵受限",o="Limited airworthiness";break;case 4:t="吃水受限",o="Limited by ship's draft";break;case 5:t="靠泊",o="Mooring";break;case 6:t="搁浅",o="Stranded";break;case 7:t="捕捞作业",o="Engaged in fishing";break;case 8:t="靠帆船提供动力",o="Sailing";break;default:t="未定义",o="Undefined"}return{labelCn:t,labelEn:o}}}class rt extends G{constructor(t,o){super();_(this,"clientId");_(this,"clientSecret");_(this,"token");this.clientId=t,this.clientSecret=o}async authToken(t={}){const o="https://svc.data.myvessel.cn/ada/oauth/token",i={searchParams:{client_id:this.clientId,client_secret:this.clientSecret,grant_type:"client_credentials"}},a=await D.post(o,i).json();M==null||M.info("[%s] fetch access token from: %s - %j",t.requestId,o,a),a.error||(this.token={accessToken:a.access_token,tokenType:a.token_type,expiresIn:a.expires_in,scope:a.scope,jti:a.jti,issuedAt:g().utc().format()})}async realTimePosition(t,o={}){var l,y,f;(!this.token||g().diff(g(this.token.issuedAt),"seconds")>((l=this.token)==null?void 0:l.expiresIn)-300)&&await this.authToken(o);const i="https://svc.data.myvessel.cn/sdc/v1/vessels/status/location/unit",a={headers:{Authorization:`${(y=this.token)==null?void 0:y.tokenType} ${(f=this.token)==null?void 0:f.accessToken}`},searchParams:{mmsi:t}};M==null||M.info("[%s] fetch realtime position from: %s - %j",o.requestId,i,a);const n=await D.get(i,a).json();if(n.code)return M==null||M.warn("[%s] fetch realtime position failed: %j",o.requestId,i,{message:n.message,status:n.status,code:n.code}),n;const s=n.data;for(const h in s)!isNaN(s[h])&&Number(s[h])!==1/0&&(s[h]=Number(s[h]));const d=g(`${s.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return{mmsi:s.mmsi,name:s.vesselName,imo:s.imo,callSign:s.callsign,lat:s.lat,lng:s.lon,length:s.length,width:s.width,draught:s.currDraught,sog:s.sog,cog:s.cog,hdg:s.hdg,rot:s.rot,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(s.eta)?g.utc(s.eta).format():void 0,destination:s.dest,positionTime:d.unix(),status:s.status,labelCn:s.statusNameCn,labelEn:s.statusNameEn,method:"position",vendor:"myVessel",utc:d.utc().format()}}async trajectory(t,o,i,a,n=!0,s={}){(!this.token||g().diff(g(this.token.issuedAt),"seconds")>this.token.expiresIn-300)&&await this.authToken(s);const d=await this.realTimePosition(t,s),r=g(o),l=g(i),y=[];for(;l.diff(r,"day",!0)>30;)await this.trajectoryIn30Day(t,r,r.clone().add(30,"day"),d,a,y,s),r.add(30,"day");return await this.trajectoryIn30Day(t,r,l,d,a,y,s),y}async trajectoryIn30Day(t,o,i,a,n,s,d={}){var u,I,k,m,v;const r="https://svc.data.myvessel.cn/sdc/v1/vessels/status/track",l={headers:{Authorization:`${(u=this.token)==null?void 0:u.tokenType} ${(I=this.token)==null?void 0:I.accessToken}`},json:{mmsi:t,startTime:o.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",d.requestId,r,l);const y=await D.post(r,l).json();if(y.code)return M==null||M.warn("[%s] fetch trajectory failed: %j",d.requestId,r,{message:y.message,status:y.status,code:y.code}),y;let f=-1;const h=g(`${(m=(k=y.data)==null?void 0:k[0])==null?void 0:m.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return(v=y.data)==null||v.forEach(c=>{for(const x in c)!isNaN(c[x])&&Number(c[x])!==1/0&&(c[x]=Number(c[x]));const b=g(`${c.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00"),q=c.status,{labelCn:p,labelEn:j}=this.parseStatus(q),S={mmsi:c.mmsi,imo:a==null?void 0:a.imo,lat:c.lat,lng:c.lon,sog:c.sog,cog:c.cog,hdg:c.hdg,draught:c.draught,status:q,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:b.unix(),labelCn:p,labelEn:j,method:"trajectory",vendor:"myVessel",utc:b.utc().format()},N=Math.floor(b.diff(h,"minute",!0)/(n||1));N!==f&&(f=N,s.push(S))}),s}}class ct extends G{constructor(t){super();_(this,"token");this.token=t}async realTimePosition(t,o={}){const i="https://api.hifleet.com/position/position/get/token",a={searchParams:{mmsi:t,usertoken:this.token}},n=await D.post(i,a).json();M==null||M.info("[%s] fetch realtime position from: %s - %j",o.requestId,i,a);const s=n==null?void 0:n.list;if(!s)return M==null||M.warn("[%s] fetch realtime position failed: %j",o.requestId,i,n),n;for(const h in s)!isNaN(s[h])&&Number(s[h])!==1/0&&(s[h]=Number(s[h]));s.status=s.sp>3?0:1;const d=s.status,{labelCn:r,labelEn:l}=this.parseStatus(d),y=g(`${s.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return{mmsi:s.m,name:s.n,imo:s.imonumber,callSign:s.callsign,lat:Math.round(s.la/60*1e5)/1e5,lng:Math.round(s.lo/60*1e5)/1e5,length:s.l,width:s.w,draught:s.draught,sog:s.sp,cog:s.co,hdg:s.h,rot:isNaN(s.rot)?0:s.rot,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(s.eta)?g.utc(s.eta).format():void 0,destination:s.destination,positionTime:y.unix(),utc:y.utc().format(),status:d,labelCn:r,labelEn:l,method:"position",vendor:"hifleet"}}async search(t,o={}){let i="https://www.hifleet.com/hifleetapi/searchVesselOL.do";const a={searchParams:{keyword:t},headers:{Referer:"https://www.hifleet.com",Origin:"https://www.hifleet.com",Host:"www.hifleet.com"}};let n=await D.post(i,a).json();M==null||M.info("[%s] fetch vessel props from: %s - %j",o.requestId,i,a),n instanceof Array&&(n=n[0]);for(const d in n)!isNaN(n[d])&&Number(n[d])!==1/0&&(n[d]=Number(n[d]));const s={mmsi:n.m,name:n.n,imo:n.i,callSign:n.c,length:n.l,breadth:n.b,draught:n.dr,type:n.t};return i="https://www.hifleet.com/hifleetapi/sameShipSearch.do",n=await D.post(i,a).json(),M==null||M.info("[%s] search vessel dead weight from: %s - %j",o.requestId,i,a),n instanceof Array&&(n=n[0]),n&&(s.deadweight=Number(n.dwt)),s}async suggest(t,o={}){const i="https://www.hifleet.com/hifleetapi/getShipSuggest.do",a={searchParams:{q:t},headers:{Referer:"https://www.hifleet.com",Origin:"https://www.hifleet.com",Host:"www.hifleet.com"}},n=await D.post(i,a).json();M==null||M.info("[%s] suggest vessel props from: %s - %j",o.requestId,i,a);const s=[];for(const d of n)s.push({mmsi:!d.mmsi||isNaN(d.mmsi)?null:Number(d.mmsi),name:d.name,callSign:d.callsign,imo:!d.imo||isNaN(d.imo)?null:Number(d.imo),score:d._score});return s.sort((d,r)=>r.score-d.score),s}async trajectory(t,o,i,a,n=!0,s={}){var c,b,q;const d=await this.realTimePosition(t,s);let r=g(o);const l=g(i),y=g();if(n){let p=l.diff(r,"d",!0);p<0?r=l.clone().subtract(40,"d"):p<30?r.subtract(10,"d"):p<60?r.subtract(5,"d"):r=l.clone().subtract(80,"d"),p=y.diff(l,"d",!0),l.add(p>10?240:p*24,"h")}const f={searchParams:{endtime:l.utcOffset("+8:00").format("YYYY-MM-DD HH:mm:ss"),starttime:r.utcOffset("+8:00").format("YYYY-MM-DD HH:mm:ss"),mmsi:t,usertoken:this.token}},h="https://api.hifleet.com/position/trajectory/nocompressed/withstatic/token",u=await D.get(h,f).json();M==null||M.info("[%s] fetch trajectory from: %s - %j",s.requestId,h,f);let I;u&&(I=((b=(c=u.ships)==null?void 0:c.offors)==null?void 0:b.ship)||[],I.length||M==null||M.warn("[%s] fetch trajectory failed: %j",s.requestId,u));const k=[];let m=-1;const v=g(`${(q=I==null?void 0:I[0])==null?void 0:q.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");for(const p of I){for(const L in p)!isNaN(p[L])&&Number(p[L])!==1/0&&(p[L]=Number(p[L]));const j=g(`${p.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");p.status=p.sp>4?0:1;const{labelEn:S,labelCn:N}=this.parseStatus(p.status),x={mmsi:p.m,name:p.n,imo:d==null?void 0:d.imo,lat:p.la,lng:p.lo,draught:p.draught,sog:p.sp,cog:p.co,hdg:p.hdg,positionTime:j.unix(),utc:j.utc().format(),status:p.status,labelCn:N,labelEn:S,method:"trajectory",vendor:"hifleet"},W=Math.floor(j.diff(v,"minute",!0)/(a||1));W!==m&&(m=W,k.push(x))}return k}}class dt extends G{constructor(t){super();_(this,"token");this.token=t}async realTimePosition(t,o={}){const i={searchParams:{id:t,k:this.token,enc:1}},a="https://api.shipxy.com/apicall/GetSingleShip",n=await D.get(a,i).json();if(M==null||M.info("[%s] fetch realtime position from: %s - %j",o.requestId,a,i),(n==null?void 0:n.status)!==0)return n;const s=n.data[0];for(const f in s)!isNaN(s[f])&&Number(s[f])!==1/0&&(s[f]=Number(s[f]));const{labelCn:d,labelEn:r}=await this.parseStatus(s.navistat),l=g.unix(s.lasttime);return{mmsi:s.ShipID,name:s.name,imo:s.imo,callSign:s.callsign,lat:Math.round(s.lat/1e6*1e5)/1e5,lng:Math.round(s.lon/1e6*1e5)/1e5,length:Math.round(s.length/10*100)/100,width:Math.round(s.width/10*100)/100,draught:Math.round(s.draught/1e3*100)/100,sog:Math.round(s.sog*3600/1e3/1852*100)/100,cog:Math.round(s.cog/100*100)/100,hdg:Math.round(s.hdg/100*100)/100,rot:Math.round(s.rot/100*100)/100,positionTime:s.lasttime,utc:l.utc().format(),status:s.navistat,labelEn:r,labelCn:d,method:"position",vendor:"shipxy"}}async trajectory(t,o,i,a,n=!0,s={}){var v;const d=await this.realTimePosition(t,s),r=g(o),l=g(i),y="https://api.shipxy.com/apicall/GetShipTrack",f={searchParams:{id:t,k:this.token,enc:1,cut:0,btm:r.unix(),etm:l.unix()}},h=await D.get(y,f).json();if(M==null||M.info("[%s] fetch trajectory from: %s - %j",s.requestId,y,f),(h==null?void 0:h.status)!==0)return h;const u=h==null?void 0:h.points,I=[],k=g.unix((v=u[0])==null?void 0:v.utc);let m=-1;for(const c of u){const b=g.unix(c.utc),q={imo:d==null?void 0:d.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:b.unix(),utc:b.utc().format(),method:"trajectory",vendor:"shipxy"},p=Math.floor(b.diff(k,"minute",!0)/(a||1));p!==m&&(m=p,I.push(q))}return I}}class ut extends G{constructor(t){super();_(this,"token");this.token=t}async getShipId(t,o={}){const i={headers:{appKey:this.token},json:{mmsiList:t}},a="https://api3.myships.com/sp/ships/getShipIdByMMSI",n=await D.post(a,i).json();return M==null||M.info("[%s] fetch ship id from: %s - %j",o.requestId,a,i),n.code!=="0"?n:n.data[0].shipId}async getShipInfo(t,o={}){const i={headers:{appKey:this.token},json:{shipId:t}},a="https://api3.myships.com/sp/ships/aissta",n=await D.post(a,i).json();if(M==null||M.info("[%s] fetch ship info from: %s - %j",o.requestId,a,i),n.code!=="0")return n;const s=n.data;let d=s.imo;return t==="407170"&&(d="9198379",M==null||M.warn("[%s] ship(%s) imo error: %s, should be %s",o.requestId,t,s.imo,d)),{mmsi:s.mmsi,name:s.shipnameEn,imo:d,callSign:s.callSign,length:s.length,width:s.breadth,draught:(s.draught||100)/10}}async realTimePosition(t,o={}){const i=await this.getShipId(t,o),a=await this.getShipInfo(i,o),n={headers:{appKey:this.token},json:{shipId:i}},s="https://api3.myships.com/sp/ships/position/latest",d=await D.post(s,n).json();M==null||M.info("[%s] fetch realtime position from: %s - %j",o.requestId,s,n);const r=d.data[0];for(const u in r)!isNaN(r[u])&&Number(r[u])!==1/0&&(r[u]=Number(r[u]));const{labelCn:l,labelEn:y}=await this.parseStatus(r.aisNavStatus),f=g.unix(r.posTime);return{...a,mmsi:t,lat:Math.round(r.lat/1e4/60*1e5)/1e5,lng:Math.round(r.lon/1e4/60*1e5)/1e5,sog:Math.round(r.sog/10*100)/100,cog:Math.round(r.cog/10*100)/100,hdg:Math.round(r.heading*100)/100,rot:Math.round(r.rot*100)/100,positionTime:r.posTime,utc:f.utc().format(),status:r.aisNavStatus,labelEn:y,labelCn:l,method:"position",vendor:"myship"}}async trajectory(t,o,i,a,n=!0,s={}){const d=g(o),r=g(i),l=await this.getShipId(t),y=await this.getShipInfo(l),f=[];for(;r.diff(d,"day",!0)>30;)await this.trajectoryIn30Day(l,d.unix(),d.add(30,"day").unix(),y,t,a,f);return await this.trajectoryIn30Day(l,d.unix(),r.unix(),y,t,a,f),f}async trajectoryIn30Day(t,o,i,a,n,s,d,r={}){var k;const l={headers:{appKey:this.token},json:{shipId:t,startTime:o,endTime:i}},y="https://api3.myships.com/sp/ships/position/history",f=await D.post(y,l).json();if(M==null||M.info("[%s] fetch trajectory from: %s - %j",r.requestId,y,l),f.code!=="0")return M==null||M.warn("[%s] invoke myship trajectory failed: %j",r.requestId,f),f;const h=f.data;for(const m in h)!isNaN(h[m])&&Number(h[m])!==1/0&&(h[m]=Number(h[m]));const u=g.unix((k=h[0])==null?void 0:k.posTime);let I=-1;for(const m of h){const v=g.unix(m.posTime),c={imo:a==null?void 0:a.imo,mmsi:n,lat:Math.round(m.lat/1e4/60*1e5)/1e5,lng:Math.round(m.lon/1e4/60*1e5)/1e5,sog:Math.round(m.sog/10*100)/100,cog:Math.round(m.cog/10*100)/100,hdg:Math.round(m.heading*100)/100,rot:Math.round(m.rot*100)/100,positionTime:v.unix(),utc:v.utc().format(),method:"trajectory",vendor:"myship"},b=Math.floor(v.diff(u,"minute",!0)/(s||1));b!==I&&(I=b,d.push(c))}return d}}let V;try{V=K.getLogger("vessel")}catch{}finally{}var tt=(Y=>(Y.NOTICE="NOTICE",Y.WARN="WARN",Y.HEAVY="HEAVY",Y.SEVERE="SEVERE",Y.ERROR="ERROR",Y.FATAL="FATAL",Y))(tt||{});class et{parsePrinciple(e,t={}){var s,d,r;V==null||V.info("[%s] parse rule: %s",t.requestId,e);const o=new RegExp("(?<=\\[)(.+)(?=])","g"),i=e.match(o)?(s=e.match(o))==null?void 0:s[0]:void 0,a=i==null?void 0:i.split(";");if(!a)return;const n={};for(let l=0;l<(a==null?void 0:a.length);l++){const y=(r=(d=a[l].match(o))==null?void 0:d[0])==null?void 0:r.split("],");if(l===0&&!y)n.scope=a[0];else if(y)for(let f=0,h=y.length;f<h;f++){const u=this.parseRule(y[f]);u&&(n[u.level]?u.key?n[u.level][u==null?void 0:u.key]=u:n[u.level]=u:u.key?n[u.level]={[u==null?void 0:u.key]:u}:n[u.level]=u)}}return n}parseRule(e,t={}){var n;V==null||V.info("[%s] parse rule: %s",t.requestId,e),e=e.startsWith("[")?e:`[${e}`,e=e.endsWith("]")?e:`${e}]`;const o=new RegExp("(?<=\\[)(.+?)(?=])","g"),i=(n=e==null?void 0:e.match(o))==null?void 0:n[0],a=i==null?void 0:i.split(",");if(a)return{operator:a[0],number:Number.isNaN(Number(a[1]))?a[1]:Number(a[1]),level:a[2],time:Number(a[3]),key:a[4]}}checkWeather(e,t,o={}){var u,I,k,m,v,c,b,q,p,j,S,N,x,W,L;let i=0,a=0,n=0,s=0;const d=Math.round(((I=(u=t==null?void 0:t.SEVERE)==null?void 0:u.sigWave)==null?void 0:I.number)*1.6*100)/100,r=(m=(k=t==null?void 0:t.SEVERE)==null?void 0:k.sigWave)==null?void 0:m.number,l=(c=(v=t==null?void 0:t.HEAVY)==null?void 0:v.sigWave)==null?void 0:c.number,y=Math.round((((q=(b=t==null?void 0:t.SEVERE)==null?void 0:b.wind)==null?void 0:q.number)+2)*100)/100,f=(j=(p=t==null?void 0:t.SEVERE)==null?void 0:p.wind)==null?void 0:j.number,h=(N=(S=t==null?void 0:t.HEAVY)==null?void 0:S.wind)==null?void 0:N.number;for(let B=0;B<(e==null?void 0:e.length);B++){const E=e[B],P=(W=(x=E==null?void 0:E.meteo)==null?void 0:x.wave)==null?void 0:W.sig,A=(L=E==null?void 0:E.meteo)==null?void 0:L.wind,Z=B?g(E.eta).diff(g(e[B-1].eta),"hour",!0):0;s=Z>s?Z:s,V==null||V.info("[%s] check sig.wave: %j",o.requestId,{...P,dgThd4Wv:d,svThd4Wv:r,hvThd4Wv:l}),(P==null?void 0:P.height)>=d?E.isDangerous=!0:(P==null?void 0:P.height)>=r?E.isSevere=!0:(P==null?void 0:P.height)>=l&&(E.isHeavy=!0),V==null||V.info("[%s] check wind: %j",o.requestId,{...A,dgThd4Wd:y,svThd4Wd:f,hvThd4Wd:h}),(A==null?void 0:A.scale)>=y?(E.isDangerous=!0,delete E.isSevere,delete E.isHeavy):(A==null?void 0:A.scale)>f?(E.isDangerous||(E.isSevere=!0),delete E.isHeavy):(A==null?void 0:A.scale)===h&&!E.isDangerous&&!E.isSevere&&(E.isHeavy=!0),i+=E.isDangerous?Z:0,a+=E.isSevere?Z:0,n+=E.isHeavy?Z:0}return i=Math.round(i*100)/100,a=Math.round(a*100)/100,n=Math.round(n*100)/100,s=Math.round(s),{sample:e,dangerous:i,severe:a,heavy:n,step:s<3?3:s,wind:{dgThd4Wd:y,svThd4Wd:f,hvThd4Wd:h},sig:{dgThd4Wv:d,svThd4Wv:r,hvThd4Wv:l}}}}const ht=new et;let w;try{w=K.getLogger("vessel")}catch{}finally{}const lt=new X.MeteoHelper2("",!0);var st=(Y=>(Y.common="common",Y.container="container",Y.tugs="tugs",Y))(st||{}),at=(Y=>(Y.Ballast="Ballast",Y.Laden="Laden",Y))(at||{}),ot=(Y=>(Y.Cp="CP",Y.Perf="Basis",Y.Instruct="Other",Y))(ot||{});class C{static blockCoefficient(e,t,o,i){let a=Math.round(e/(t*o*i)*100)/100;a=a<.55?.55:a>.85?.85:a;const n=[.55,.6,.65,.7,.75,.8,.85],s=n.map(d=>Math.abs(d-a));return n[s.indexOf(Math.min(...s))]}static froudeNumber(e,t,o=9.8){let i=Math.round(Math.sqrt(e*e/(o*t))*100)/100;return i=i<.05?.05:i>.3?.3:i,i}static amendFactor(e,t,o){const i={.55:[1.7,-1.4,-7.4],.6:[2.2,-2.5,-9.7],.65:[2.6,-3.7,-11.6],.7:[3.1,-5.3,-12.4],.75:[2.4,-10.6,-9.5],.8:[2.6,-13.1,-15.1],.85:[3.1,-18.7,28]};let n={.55:[1.7,-1.4,-7.4],.6:[2.2,-2.5,-9.7],.65:[2.6,-3.7,-11.6],.7:[3.1,-5.3,-12.4],.75:[2.6,-12.5,-13.5],.8:[3,-16.3,-21.6],.85:[3.4,-20.9,31.8]}[e];return o==="Laden"&&(n=i[e]),n[0]+n[1]*t+n[2]*Math.pow(t,2)}static directionFactor(e,t=0){let o;return e>30&&e<=60?o=(1.7-.03*Math.pow(t-4,2))/2:e>60&&e<=150?o=(.9-.06*Math.pow(t-6,2))/2:e>150&&e<=180?o=(.4-.03*Math.pow(t-8,2))/2:o=1,Math.round(o*1e5)/1e5}static vesselTagFactor(e,t,o,i=0){i=i>6?i-.9*(i-6):i;let a;return o==="container"?a=.7*i+Math.pow(i,6.5)/(22*Math.pow(e,2/3)):t==="Ballast"?a=.7*i+Math.pow(i,6.5)/(2.7*Math.pow(e,2/3)):a=.5*i+Math.pow(i,6.5)/(2.7*Math.pow(e,2/3)),a}static waveHeightFactor(e,t){e=e<0?.2:e,e=e>6?e-.9*(e-6):e,e=e>9?9:e;let o;return t>30&&t<=60?o=-.6:t>60&&t<=90?o=-.4:t>90&&t<=120?o=e<3?.4:-.3:t>120&&t<=150?o=e<3?.6:-.5:t>150&&t<=180?o=e<3?.7:-.6:o=-.7,Math.round(o*(.144*Math.pow(e,2)+.178*e)*1e4)/1e4}static assembleProperties(e,t,o,i){var f;const a=e.lbp??e.length??e.lengthOverall??198.9642,n=e.draught??8,s=e.breadthMoulded??e.breadth??e.breadthExtreme??32.4572,d=e.deadweight??67035.7773,r=((f=e==null?void 0:e.type)==null?void 0:f.toLowerCase())||"common";return{tag:r.indexOf("container")>-1?"container":r.indexOf("tugs")>-1?"tugs":"common",lbp:a,loadCondition:t,draught:n,breadthMoulded:s,displacement:Math.round((d/1.025+n*s*a*.7)*1e4)/1e4,speed:Math.round((o??14.1382)*1852/3600*1e4)/1e4,bearing:i||90}}static async speedLoseAt(e,t,o,i="",a=2,n=!0,s=!1,d={}){let r;if(t.velocity&&s&&(e.speed=R.LngLatHelper.roundPrecision(t.velocity*1852/3600,6)),n){let l;if(d.meteo2)try{const u=await lt.spotForecast(t.lat,t.lng,o.utc().format(),!1,!1,!0,d),[I]=$.Meteo2Assist.pickHourly(u,o);l=$.Meteo2Assist.toLegacy(I)}catch(u){w.warn("[%s] meteo2 spot(%j) forecast failed: %s",d.requestId,{...t,eta:o.utc().format()},u)}else l=await X.MeteoHelper.queryPointFactor(t.lng,t.lat,o.valueOf(),"wind,wave,current,watertemp",i,d);const y=C.weatherFactor(e,l),f=C.currentFactor(e.bearing,l==null?void 0:l.current,a),h=Math.round((e.speed*1.943844+y+f)*100)/100;r={meteo:{...l},wxFactor:y,cFactor:f,speed:t.velocity&&s?t.velocity:h<0?1:h,eta:o.utc().format("YYYY-MM-DDTHH:mm[Z]"),etd:o.utc().format("YYYY-MM-DDTHH:mm[Z]")}}else r={wxFactor:0,cFactor:0,speed:t.velocity&&s?t.velocity:Math.round((e.speed*1.943844+0+0)*100)/100,eta:o.utc().format("YYYY-MM-DDTHH:mm[Z]"),etd:o.utc().format("YYYY-MM-DDTHH:mm[Z]")};return delete t.meteo,delete t.wxFactor,delete t.cFactor,delete t.speed,delete t.etd,{...r,...t}}static async speedLoseInHoursStep(e,t,o,i,a,n,s="",d=!0,r=!1,l={}){t.utc();const y=t.clone().add(14,"days"),f=[],h=[];let u=0,I=0,k,m;for(let v=0;v<n.length-1;v++){let c=n[v];c.distanceFromStart=Math.round((a+I)*1e4)/1e4;const b=n[v+1];if(e.bearing=R.LaneHelper.calculateBearing(c,b,!b.gcToPrevious),c.bearing=e.bearing,c.suspend&&r){c.eta=c.eta||t.format("YYYY-MM-DDTHH:mm[Z]"),c.elapsed=c.elapsed??0;const j=c.suspend-c.elapsed;if(i-u>j)i=i-u-j,t.add(j,"hour"),c.elapsed=c.suspend;else{const S=i-u;c.elapsed+=S,t.add(S,"hour"),i=0}if(w==null||w.info(`[%s] suspend ${c.elapsed} hours at %j, and remain ${i} hours need to go...`,l.requestId,c),i===0)return c.distanceFromPrevious=I,{etd:t,from:m||c,to:c,next:n.filter(S=>S),wps:f,days:h}}else c.suspend=0;d=t.isAfter(y)?!1:d,c=await C.speedLoseAt(e,c,t,s,0,d,r,l),m=m||c,c.important&&f.push(c),t.isSameOrAfter(o)&&(h.push(c),o.add(24,"hour"));const q=R.LaneHelper.calculateDistance(c,b,!b.gcToPrevious);let p=Math.ceil(q/m.speed*1e4)/1e4;if(u+p<i){if(u+=p,t.add(p,"hour"),delete n[v],w==null||w.debug(`[%s] go to %j from %j with ${q}nm, and cost ${p} hours`,l.requestId,{lat:b.lat,lng:b.lng},{lat:m.lat,lng:m.lng,etd:m.etd}),I+=q,n.filter(j=>j).length<=1){k=b,k.eta=t.format("YYYY-MM-DDTHH:mm[Z]"),k.distanceFromPrevious=q,k.distanceFromStart=Math.round((a+I)*1e4)/1e4,f.push(k),delete n[v+1];break}}else{p=i-u,t.add(p,"hour");const j=R.LngLatHelper.roundPrecision(m.speed*p,4);k=R.LaneHelper.calculateCoordinate(c,e.bearing,j,"nauticalmiles",!b.gcToPrevious),k.eta=t.format("YYYY-MM-DDTHH:mm[Z]"),n[v]=k,w==null||w.debug(`[%s] go to %j from %j with ${j}nm, and cost ${p} hours`,l.requestId,{lat:k.lat,lng:k.lng},{lat:c.lat,lng:c.lng,etd:c.etd}),I+=j,k.distanceFromPrevious=Math.round(I*1e4)/1e4,k.distanceFromStart=Math.round((a+I)*1e4)/1e4;break}}return{etd:t,from:m,to:k,next:n.filter(v=>v),wps:f,days:h}}static currentFactor(e,t,o=0){const i=(e-(t==null?void 0:t.degree)||0)/180*Math.PI;if(Math.abs(i)===Math.PI/2)return 0;let a=((t==null?void 0:t.kts)||0)*Math.cos(i);return o&2?a=Math.ceil(a*100)/100:o&1?a=Math.floor(a*100)/100:a=Math.round(a*100)/100,Math.abs(a)>5?0:a}static weatherFactor(e,t){var y,f,h,u,I,k,m;w==null||w.debug("calculate weather factor via: %j",{...e,...t});const o=C.blockCoefficient(e.displacement,e.lbp,e.breadthMoulded,e.draught),i=C.froudeNumber(e.speed,e.lbp),a=C.amendFactor(o,i,e.loadCondition);let n=Math.abs(e.bearing%360-(((y=t==null?void 0:t.wind)==null?void 0:y.degree)%360||0));n=n>180?360-n:n;const s=C.directionFactor(n,(f=t==null?void 0:t.wind)==null?void 0:f.scale),d=C.vesselTagFactor(e.displacement,e.loadCondition,e.tag,(h=t==null?void 0:t.wind)==null?void 0:h.scale);let r=s*a*d/100*e.speed;r=Math.round(r*1.943844*1e4)/1e4*-1,e.tag==="tugs"&&Math.abs(r)>1&&(r=r/(Math.abs(Math.round(r))+1)),w==null||w.debug("wind wx factor = %d",r),n=Math.abs(e.bearing%360-(((I=(u=t==null?void 0:t.wave)==null?void 0:u.sig)==null?void 0:I.degree)%360||0));const l=C.waveHeightFactor(((m=(k=t==null?void 0:t.wave)==null?void 0:k.sig)==null?void 0:m.height)??1,n);return w==null||w.debug("wave wx factor = %d",l),r=r*.4+l,w==null||w.debug("weather factor = %d",r),r=Math.abs(r)>4?4*(Math.abs(r)/r)+Math.abs(r)/r*(Math.abs(r)-4)*.1:r,Math.round((r||0)*100)/100}static async analyseInstant(e,t,o,i,a,n="",s=0,d=!0,r=!1,l={}){var Z,z,U,Q,J;const y=g().valueOf();e.lng=R.LngLatHelper.convertToStdLng(e.lng);const{route:f,waypoints:h}=a.points,u=R.LaneHelper.calculateSubRoute(e,f);if(((Z=u[0])==null?void 0:Z.length)<=1)return;const{v0:I,label:k}=e.sog?{v0:e.sog,label:"Other"}:{v0:i.speed,label:"CP"},m=C.assembleProperties(o,i.loadCondition,I,0),v=h.length?R.LaneHelper.calculateSubWaypoints(e,h):[];v.forEach(H=>H.important=!0);const c={from:{...e},route:u,waypoints:v,v0:I,label:k},b={hours:[],days:[],wps:[]};s||(R.LaneHelper.calculateRouteDistance(u)/i.speed<=72?s=3:s=6);let q=R.LaneHelper.simplifyRouteToCoordinates(u,v,0),p=0,j=0,S=0,N=0;t=g(t).utc();const x=t.clone();for(;q.length>0;){const H=s-t.hour()%s,F=Math.ceil(t.clone().add(H,"h").set({minute:0,second:0,millisecond:0}).diff(t,"h",!0)*1e4)/1e4,O=await C.speedLoseInHoursStep(m,t,x,F,p,q,n,d,r,l);(z=O.from)!=null&&z.speed&&(b.hours.push(O.from),b.wps.push(...O.wps),b.days.push(...O.days)),q=O==null?void 0:O.next,q.length||b.hours.push(O==null?void 0:O.to),p+=Math.round((((U=O==null?void 0:O.to)==null?void 0:U.distanceFromPrevious)??0)*1e4)/1e4}const W=b.hours;for(let H=0;H<W.length-1;H++){const F=g(W[H+1].eta).diff(W[H].etd,"hour",!0)||1;j+=(W[H].wxFactor||0)*F,S+=(W[H].cFactor||0)*F,N+=F}(Q=b.wps)==null||Q.forEach((H,F)=>{if(F){const O=b.wps[F-1],ft=H.distanceFromStart-O.distanceFromStart,nt=g(H.eta).diff(g(O.etd),"h",!0);if(nt<1)H.avgSpd=O.speed;else{H.avgSpd=Math.round(ft/nt*100)/100;const it=Math.round((O.speed+H.speed)/2*100)/100;H.avgSpd=H.avgSpd>it?it:H.avgSpd}}}),c.sample=b;const L=b.hours.at(0),B=b.hours.at(-1);c.distance=Math.round(B.distanceFromStart*1e4)/1e4,c.etd=g(L.eta).utc().format(),c.eta=g(B.eta).utc().format(),c.wxFactor=Math.round(j/N*1e4)/1e4,c.cFactor=Math.round(S/N*1e4)/1e4,c.avgSpeed=Math.round(B.distanceFromStart/N*1e4)/1e4,c.totalHrs=Math.round(N*1e4)/1e4,c.totalFoCons=Math.round((i==null?void 0:i.fo)/24*c.totalHrs*1e3)/1e3,c.totalDgoCons=Math.round((i==null?void 0:i.dgo)/24*c.totalHrs*1e3)/1e3;const P=g().valueOf()-y,A=((J=b==null?void 0:b.hours)==null?void 0:J.length)||1;return w==null||w.info("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms",l==null?void 0:l.requestId,P,A,Math.round(P/A*1e3)/1e3),c}static async analyseInstantWithThreshed(e,t,o,i,a,n,s,d="",r=3,l=!0,y=!1,f={}){var Z,z,U,Q;const h=g().valueOf();e.lng=R.LngLatHelper.convertToStdLng(e.lng);const{v0:u,label:I}=e.sog?{v0:e.sog,label:"Other"}:{v0:a.speed,label:"CP"},k=C.assembleProperties(i,a.loadCondition,u,0),m=R.LaneHelper.calculateSubRoute(e,n);if(((Z=m[0])==null?void 0:Z.length)<=1)return;const v=s.length?R.LaneHelper.calculateSubWaypoints(e,s):[];v.forEach(J=>J.important=!0);let c=R.LaneHelper.simplifyRouteToCoordinates(m,v,0),b=0,q=0,p=0,j=0;const S={hours:[],wps:[],days:[]};t=g(t).utc();const N=t.clone();for(;c.length>0;){const J=r-t.hour()%r;let H=Math.ceil(t.clone().add(J,"h").set({minute:0,second:0,millisecond:0}).diff(t,"h",!0)*1e4)/1e4;if(H=t.clone().add(H,"h").isAfter(o)?o.diff(t,"h",!0)*1e4/1e4:H,H){const F=await C.speedLoseInHoursStep(k,t,N,H,b,c,d,l,y,f);(z=F.from)!=null&&z.speed&&(S.hours.push(F.from),F!=null&&F.wps&&S.wps.push(...F.wps),S.days.push(...F.days)),c=F==null?void 0:F.next,c.length||S.hours.push(F==null?void 0:F.to),b+=Math.round((((U=F==null?void 0:F.to)==null?void 0:U.distanceFromPrevious)??0)*1e4)/1e4}else break}const x=S.hours;for(let J=0;J<x.length-1;J++){const H=g(x[J+1].eta).diff(x[J].etd,"hour",!0);q+=x[J].wxFactor*H,p+=x[J].cFactor*H,j+=H}const W=S.hours.at(0),L=S.hours.at(-1),B={sample:S,distance:Math.round(((L==null?void 0:L.distanceFromStart)||0)*1e4)/1e4,etd:g(W.eta).utc().format(),eta:g(L==null?void 0:L.eta).utc().format(),wxFactor:Math.round(q/j*1e4)/1e4,cFactor:Math.round(p/j*1e4)/1e4,avgSpeed:Math.round(((L==null?void 0:L.distanceFromStart)||0)/j*1e4)/1e4,totalHrs:Math.round(j*1e4)/1e4,totalFoCons:Math.round((a==null?void 0:a.fo)/24*j*1e3)/1e3,totalDgoCons:Math.round((a==null?void 0:a.dgo)/24*j*1e3)/1e3,from:W,to:L,route:m,waypoints:v,v0:u,label:I},P=g().valueOf()-h,A=((Q=S==null?void 0:S.hours)==null?void 0:Q.length)||1;return w==null||w.debug("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms",f==null?void 0:f.requestId,P,A,Math.round(P/A*1e3)/1e3),B}static async analyseCost(e,t,o,i,a={}){var I,k;const n=g().valueOf(),s=[];a.meteo2=!0,e.speedStep=e.speedStep||3;const d=g.utc(e.etd).add(a.maxDays??14,"day");let r=1;for(const m of o){const v=JSON.parse(JSON.stringify(i.route)),c=JSON.parse(JSON.stringify(i.waypoints)),b=await C.analyseInstantWithThreshed({lat:e.lat,lng:e.lng},e.etd,d,t,m,v,c,e.meteoVendor,e.speedStep,e.useMeteo,e.useRouteParam,a);b&&(await C.calculateCost(b,m,e,a),s.push(b),w==null||w.info("[%s][L%d-%d] analyse from %s to %s cost: %j",a.requestId,1,r,e.etd,d.format(),{cost:b.cost.total,distance:b.distance,hours:b.totalHrs,cp:`${m.speed}/${m.fo}/${m.dgo}`})),r++}s.sort((m,v)=>m.cost.total-v.cost.total);const l=s.at(0),y=s.at(1),f=[];if(f.push({combined:!1,speeds:[l],cost:(I=l.cost)==null?void 0:I.total}),y){const m=l.cost.cp,v=y.cost.cp,c=g(l.eta),b=g(l.etd),q=c.diff(b,"days",!0);let p=Math.ceil(q/2);p=p>7?7:p;let j=2,S={combined:!1,speeds:[y],cost:(k=y.cost)==null?void 0:k.total},N;for(;p>=1;){const x=await C.combinedAnalyse(e,t,d,[m,v],i,p,{...a,level:j});if(S.cost>x.cost?N?(N==null?void 0:N.cost)>x.cost&&(N=x):(N=S,S=x):(!N||(N==null?void 0:N.cost)>x.cost)&&(N=x),p===1)break;p=Math.ceil(p/2),j+=1}f.push(S),N&&f.push(N)}const u=g().valueOf()-n;return w==null||w.info("[%s] analyse elapsed: %d ms",a==null?void 0:a.requestId,u),f.sort((m,v)=>m.cost-v.cost)}static async combinedAnalyse(e,t,o,i,a,n,s={}){s.counter=1,w==null||w.info("[%s][L%d] analyse with alternate cp in every %d days",s.requestId,s.level,n);const d=await C.alternateAnalyse(e,t,o,i,0,a,n,s),r=d.reduce((f,h)=>f+h.cost.total,0);w==null||w.info("[%s][L%d] cost with cpa/cpb turn: %d",s.requestId,s.level,r);const l=await C.alternateAnalyse(e,t,o,i,1,a,n,s),y=l.reduce((f,h)=>f+h.cost.total,0);return w==null||w.info("[%s][L%d] cost with cpb/cpa turn: %d",s.requestId,s.level,y),r<y?{combined:!0,cost:Math.round(r*1e3)/1e3,speeds:d}:{combined:!0,cost:Math.round(y*1e3)/1e3,speeds:l}}static async alternateAnalyse(e,t,o,i,a,n,s,d={}){var f,h;let r=g.utc(e.etd);const l={lat:e.lat,lng:e.lng},y=[];for(;r.isBefore(o);){const u=r.clone().utc().add(s,"day"),I=JSON.parse(JSON.stringify(n.route)),k=JSON.parse(JSON.stringify(n.waypoints)),m=i[a],v=await C.analyseInstantWithThreshed(l,r.format(),u,t,m,I,k,e.meteoVendor,e.speedStep,e.useMeteo,e.useRouteParam,d);v&&(await C.calculateCost(v,m,e,d),w==null||w.info("[%s][L%d-%d] analyse from %s to %s cost: %j",d.requestId,d.level,d.counter,r.utc().format(),u.utc().format(),{cost:v.cost.total,distance:v.distance,hours:v.totalHrs,cp:`${m.speed}/${m.fo}/${m.dgo}`})),d.counter=d.counter+1;const c=(h=(f=v==null?void 0:v.sample)==null?void 0:f.hours)==null?void 0:h.at(-1);if(c)l.lat=c.lat,l.lng=c.lng,r=g(c.eta),y.push(v),a=a?0:1;else break}return y}static async calculateCost(e,t,o,i={}){if(e){const a=Math.round(e.totalHrs/24*(o.dailyHire||0)*(1-(o.addComm||0))*1e3)/1e3,n=Math.round(e.totalFoCons*(o.priceFO||0)*1e3)/1e3,s=Math.round(e.totalDgoCons*(o.priceDGO||0)*1e3)/1e3;e.cost={total:Math.round((a+n+s)*1e3)/1e3,hire:a,bunker:Math.round((n+s)*1e3)/1e3,cp:t}}return e}static async mergeSpeeds(e,t={}){const o={hours:[],wps:[],days:[]},i=e.reduce((h,u)=>h+u.distance,0),a=e.reduce((h,u)=>h+u.totalHrs,0),n=e.reduce((h,u)=>h+u.wxFactor*u.totalHrs/a,0),s=e.reduce((h,u)=>h+u.cFactor*u.totalHrs/a,0),d=e.reduce((h,u)=>h+u.totalFoCons,0),r=e.reduce((h,u)=>h+u.totalDgoCons,0),l=e.reduce((h,u)=>h+u.cost.total,0),y=e.reduce((h,u)=>h+u.cost.hire,0),f=e.reduce((h,u)=>h+u.cost.bunker,0);for(const h of e){const u=h.sample.hours,I=h.sample.wps,k=h.sample.days;u.forEach(m=>{var c;((c=o.hours)==null?void 0:c.findIndex(b=>b.eta===m.eta))===-1&&o.hours.push(m)}),I.forEach(m=>{var c;((c=o.wps)==null?void 0:c.findIndex(b=>b.eta===m.eta))===-1&&o.wps.push(m)}),k.forEach(m=>{var c;((c=o==null?void 0:o.days)==null?void 0:c.findIndex(b=>b.eta===m.eta))===-1&&o.days.push(m)})}return{sample:o,etd:e.at(0).etd,eta:e.at(-1).eta,from:e.at(0).from,to:e.at(-1).to,label:"combined",distance:Math.round(i*1e4)/1e4,totalHrs:Math.round(a*1e3)/1e3,avgSpeed:Math.round(i/a*1e3)/1e3,wxFactor:Math.round(n/a*1e3)/1e3,cFactor:Math.round(s/a*1e3)/1e3,totalFoCons:Math.round(d*1e3)/1e3,totalDgoCons:Math.round(r*1e3)/1e3,cost:{total:Math.round(l*1e3)/1e3,hire:Math.round(y*1e3)/1e3,bunker:Math.round(f*1e3)/1e3}}}}T.AISImpl=G,T.AlertHelper=et,T.AlertLevel=tt,T.HifleetImpl=ct,T.LoadCondition=at,T.MyShipImpl=ut,T.MyVesselImpl=rt,T.ShipxyImpl=dt,T.SpeedHelper=C,T.SpeedLabel=ot,T.VesselTag=st,T.alertHelper=ht,Object.defineProperty(T,Symbol.toStringTag,{value:"Module"})});
|
|
1
|
+
(function(T,q){typeof exports=="object"&&typeof module<"u"?q(exports,require("got"),require("@log4js-node/log4js-api"),require("moment"),require("@idm-plugin/geo"),require("@idm-plugin/meteo2"),require("@idm-plugin/meteo")):typeof define=="function"&&define.amd?define(["exports","got","@log4js-node/log4js-api","moment","@idm-plugin/geo","@idm-plugin/meteo2","@idm-plugin/meteo"],q):(T=typeof globalThis<"u"?globalThis:T||self,q(T["idm-plugin-rabbitmq"]={},T.got,T["@log4js-node/log4js-api"],T.moment,T["@idm-plugin/geo"],T["@idm-plugin/meteo2"],T["@idm-plugin/meteo"]))})(this,function(T,q,_,v,W,X,$){"use strict";var mt=Object.defineProperty;var yt=(T,q,_)=>q in T?mt(T,q,{enumerable:!0,configurable:!0,writable:!0,value:_}):T[q]=_;var K=(T,q,_)=>(yt(T,typeof q!="symbol"?q+"":q,_),_);let y;try{y=_.getLogger("vessel")}catch{}finally{}class G{parseStatus(e){let t,n;switch(e){case 0:t="在航(主机推动)",n="The engine is in use";break;case 1:t="锚泊",n="Anchored";break;case 2:t="失控",n="Not operated";break;case 3:t="操纵受限",n="Limited airworthiness";break;case 4:t="吃水受限",n="Limited by ship's draft";break;case 5:t="靠泊",n="Mooring";break;case 6:t="搁浅",n="Stranded";break;case 7:t="捕捞作业",n="Engaged in fishing";break;case 8:t="靠帆船提供动力",n="Sailing";break;default:t="未定义",n="Undefined"}return{labelCn:t,labelEn:n}}}class rt extends G{constructor(t,n){super();K(this,"clientId");K(this,"clientSecret");K(this,"token");this.clientId=t,this.clientSecret=n}async authToken(t={}){const n="https://svc.data.myvessel.cn/ada/oauth/token",i={searchParams:{client_id:this.clientId,client_secret:this.clientSecret,grant_type:"client_credentials"}},a=await q.post(n,i).json();y==null||y.info("[%s] fetch access token from: %s - %j",t.requestId,n,a),a.error||(this.token={accessToken:a.access_token,tokenType:a.token_type,expiresIn:a.expires_in,scope:a.scope,jti:a.jti,issuedAt:v().utc().format()})}async realTimePosition(t,n={}){var l,m,f;(!this.token||v().diff(v(this.token.issuedAt),"seconds")>((l=this.token)==null?void 0:l.expiresIn)-300)&&await this.authToken(n);const i="https://svc.data.myvessel.cn/sdc/v1/vessels/status/location/unit",a={headers:{Authorization:`${(m=this.token)==null?void 0:m.tokenType} ${(f=this.token)==null?void 0:f.accessToken}`},searchParams:{mmsi:t}};y==null||y.info("[%s] fetch realtime position from: %s - %j",n.requestId,i,a);const o=await q.get(i,a).json();if(o.code)return y==null||y.warn("[%s] fetch realtime position failed: %j",n.requestId,i,{message:o.message,status:o.status,code:o.code}),o;const s=o.data;for(const h in s)!isNaN(s[h])&&Number(s[h])!==1/0&&(s[h]=Number(s[h]));const d=v(`${s.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return{mmsi:s.mmsi,name:s.vesselName,imo:s.imo,callSign:s.callsign,lat:s.lat,lng:s.lon,length:s.length,width:s.width,draught:s.currDraught,sog:s.sog,cog:s.cog,hdg:s.hdg,rot:s.rot,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(s.eta)?v.utc(s.eta).format():void 0,destination:s.dest,positionTime:d.unix(),status:s.status,labelCn:s.statusNameCn,labelEn:s.statusNameEn,method:"position",vendor:"myVessel",utc:d.utc().format()}}async trajectory(t,n,i,a,o=!0,s={}){(!this.token||v().diff(v(this.token.issuedAt),"seconds")>this.token.expiresIn-300)&&await this.authToken(s);const d=await this.realTimePosition(t,s),c=v(n),l=v(i),m=[];for(;l.diff(c,"day",!0)>30;)await this.trajectoryIn30Day(t,c,c.clone().add(30,"day"),d,a,m,s),c.add(30,"day");return await this.trajectoryIn30Day(t,c,l,d,a,m,s),m}async trajectoryIn30Day(t,n,i,a,o,s,d={}){var u,I,S,M,g;const c="https://svc.data.myvessel.cn/sdc/v1/vessels/status/track",l={headers:{Authorization:`${(u=this.token)==null?void 0:u.tokenType} ${(I=this.token)==null?void 0:I.accessToken}`},json:{mmsi:t,startTime:n.utcOffset(8).format("YYYY-MM-DD HH:mm:ss"),endTime:i.utcOffset(8).format("YYYY-MM-DD HH:mm:ss")}};y==null||y.info("[%s] fetch trajectory from: %s - %j",d.requestId,c,l);const m=await q.post(c,l).json();if(m.code)return y==null||y.warn("[%s] fetch trajectory failed: %j",d.requestId,c,{message:m.message,status:m.status,code:m.code}),m;let f=-1;const h=v(`${(M=(S=m.data)==null?void 0:S[0])==null?void 0:M.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return(g=m.data)==null||g.forEach(r=>{for(const L in r)!isNaN(r[L])&&Number(r[L])!==1/0&&(r[L]=Number(r[L]));const b=v(`${r.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00"),D=r.status,{labelCn:p,labelEn:j}=this.parseStatus(D),k={mmsi:r.mmsi,imo:a==null?void 0:a.imo,lat:r.lat,lng:r.lon,sog:r.sog,cog:r.cog,hdg:r.hdg,draught:r.draught,status:D,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(r.eta)?v(`${r.eta} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00").utc().format():void 0,destination:r.dest,positionTime:b.unix(),labelCn:p,labelEn:j,method:"trajectory",vendor:"myVessel",utc:b.utc().format()},O=Math.floor(b.diff(h,"minute",!0)/(o||1));O!==f&&(f=O,s.push(k))}),s}}class ct extends G{constructor(t){super();K(this,"token");this.token=t}async realTimePosition(t,n={}){const i="https://api.hifleet.com/position/position/get/token",a={searchParams:{mmsi:t,usertoken:this.token}},o=await q.post(i,a).json();y==null||y.info("[%s] fetch realtime position from: %s - %j",n.requestId,i,a);const s=o==null?void 0:o.list;if(!s)return y==null||y.warn("[%s] fetch realtime position failed: %j",n.requestId,i,o),o;for(const h in s)!isNaN(s[h])&&Number(s[h])!==1/0&&(s[h]=Number(s[h]));s.status=s.sp>3?0:1;const d=s.status,{labelCn:c,labelEn:l}=this.parseStatus(d),m=v(`${s.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return{mmsi:s.m,name:s.n,imo:s.imonumber,callSign:s.callsign,lat:Math.round(s.la/60*1e5)/1e5,lng:Math.round(s.lo/60*1e5)/1e5,length:s.l,width:s.w,draught:s.draught,sog:s.sp,cog:s.co,hdg:s.h,rot:isNaN(s.rot)?0:s.rot,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(s.eta)?v.utc(s.eta).format():void 0,destination:s.destination,positionTime:m.unix(),utc:m.utc().format(),status:d,labelCn:c,labelEn:l,method:"position",vendor:"hifleet"}}async search(t,n={}){let i="https://www.hifleet.com/hifleetapi/searchVesselOL.do";const a={searchParams:{keyword:t},headers:{Referer:"https://www.hifleet.com",Origin:"https://www.hifleet.com",Host:"www.hifleet.com"}};let o=await q.post(i,a).json();y==null||y.info("[%s] fetch vessel props from: %s - %j",n.requestId,i,a),o instanceof Array&&(o=o[0]);for(const d in o)!isNaN(o[d])&&Number(o[d])!==1/0&&(o[d]=Number(o[d]));const s={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 q.post(i,a).json(),y==null||y.info("[%s] search vessel dead weight from: %s - %j",n.requestId,i,a),o instanceof Array&&(o=o[0]),o&&(s.deadweight=Number(o.dwt)),s}async suggest(t,n={}){const i="https://www.hifleet.com/hifleetapi/getShipSuggest.do",a={searchParams:{q:t},headers:{Referer:"https://www.hifleet.com",Origin:"https://www.hifleet.com",Host:"www.hifleet.com"}},o=await q.post(i,a).json();y==null||y.info("[%s] suggest vessel props from: %s - %j",n.requestId,i,a);const s=[];for(const d of o)s.push({mmsi:!d.mmsi||isNaN(d.mmsi)?null:Number(d.mmsi),name:d.name,callSign:d.callsign,imo:!d.imo||isNaN(d.imo)?null:Number(d.imo),score:d._score});return s.sort((d,c)=>c.score-d.score),s}async trajectory(t,n,i,a,o=!0,s={}){var r,b,D;const d=await this.realTimePosition(t,s);let c=v(n);const l=v(i),m=v();if(o){let p=l.diff(c,"d",!0);p<0?c=l.clone().subtract(40,"d"):p<30?c.subtract(10,"d"):p<60?c.subtract(5,"d"):c=l.clone().subtract(80,"d"),p=m.diff(l,"d",!0),l.add(p>10?240:p*24,"h")}const f={searchParams:{endtime:l.utcOffset("+8:00").format("YYYY-MM-DD HH:mm:ss"),starttime:c.utcOffset("+8:00").format("YYYY-MM-DD HH:mm:ss"),mmsi:t,usertoken:this.token}},h="https://api.hifleet.com/position/trajectory/nocompressed/withstatic/token",u=await q.get(h,f).json();y==null||y.info("[%s] fetch trajectory from: %s - %j",s.requestId,h,f);let I;u&&(I=((b=(r=u.ships)==null?void 0:r.offors)==null?void 0:b.ship)||[],I.length||y==null||y.warn("[%s] fetch trajectory failed: %j",s.requestId,u));const S=[];let M=-1;const g=v(`${(D=I==null?void 0:I[0])==null?void 0:D.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");for(const p of I){for(const F in p)!isNaN(p[F])&&Number(p[F])!==1/0&&(p[F]=Number(p[F]));const j=v(`${p.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");p.status=p.sp>4?0:1;const{labelEn:k,labelCn:O}=this.parseStatus(p.status),L={mmsi:p.m,name:p.n,imo:d==null?void 0:d.imo,lat:p.la,lng:p.lo,draught:p.draught,sog:p.sp,cog:p.co,hdg:p.hdg,positionTime:j.unix(),utc:j.utc().format(),status:p.status,labelCn:O,labelEn:k,method:"trajectory",vendor:"hifleet"},N=Math.floor(j.diff(g,"minute",!0)/(a||1));N!==M&&(M=N,S.push(L))}return S}}class dt extends G{constructor(t){super();K(this,"token");this.token=t}async realTimePosition(t,n={}){const i={searchParams:{id:t,k:this.token,enc:1}},a="https://api.shipxy.com/apicall/GetSingleShip",o=await q.get(a,i).json();if(y==null||y.info("[%s] fetch realtime position from: %s - %j",n.requestId,a,i),(o==null?void 0:o.status)!==0)return o;const s=o.data[0];for(const f in s)!isNaN(s[f])&&Number(s[f])!==1/0&&(s[f]=Number(s[f]));const{labelCn:d,labelEn:c}=await this.parseStatus(s.navistat),l=v.unix(s.lasttime);return{mmsi:s.ShipID,name:s.name,imo:s.imo,callSign:s.callsign,lat:Math.round(s.lat/1e6*1e5)/1e5,lng:Math.round(s.lon/1e6*1e5)/1e5,length:Math.round(s.length/10*100)/100,width:Math.round(s.width/10*100)/100,draught:Math.round(s.draught/1e3*100)/100,sog:Math.round(s.sog*3600/1e3/1852*100)/100,cog:Math.round(s.cog/100*100)/100,hdg:Math.round(s.hdg/100*100)/100,rot:Math.round(s.rot/100*100)/100,positionTime:s.lasttime,utc:l.utc().format(),status:s.navistat,labelEn:c,labelCn:d,method:"position",vendor:"shipxy"}}async trajectory(t,n,i,a,o=!0,s={}){var g;const d=await this.realTimePosition(t,s),c=v(n),l=v(i),m="https://api.shipxy.com/apicall/GetShipTrack",f={searchParams:{id:t,k:this.token,enc:1,cut:0,btm:c.unix(),etm:l.unix()}},h=await q.get(m,f).json();if(y==null||y.info("[%s] fetch trajectory from: %s - %j",s.requestId,m,f),(h==null?void 0:h.status)!==0)return h;const u=h==null?void 0:h.points,I=[],S=v.unix((g=u[0])==null?void 0:g.utc);let M=-1;for(const r of u){const b=v.unix(r.utc),D={imo:d==null?void 0:d.imo,mmsi:t,sog:Math.round(r.sog*3600/1e3/1852*100)/100,cog:Math.round(r.cog/100*100)/100,lat:Math.round(r.lat/1e6*1e5)/1e5,lng:Math.round(r.lon/1e6*1e5)/1e5,positionTime:b.unix(),utc:b.utc().format(),method:"trajectory",vendor:"shipxy"},p=Math.floor(b.diff(S,"minute",!0)/(a||1));p!==M&&(M=p,I.push(D))}return I}}class ut extends G{constructor(t){super();K(this,"token");this.token=t}async getShipId(t,n={}){const i={headers:{appKey:this.token},json:{mmsiList:t}},a="https://api3.myships.com/sp/ships/getShipIdByMMSI",o=await q.post(a,i).json();return y==null||y.info("[%s] fetch ship id from: %s - %j",n.requestId,a,i),o.code!=="0"?o:o.data[0].shipId}async getShipInfo(t,n={}){const i={headers:{appKey:this.token},json:{shipId:t}},a="https://api3.myships.com/sp/ships/aissta",o=await q.post(a,i).json();if(y==null||y.info("[%s] fetch ship info from: %s - %j",n.requestId,a,i),o.code!=="0")return o;const s=o.data;let d=s.imo;return t==="407170"&&(d="9198379",y==null||y.warn("[%s] ship(%s) imo error: %s, should be %s",n.requestId,t,s.imo,d)),{mmsi:s.mmsi,name:s.shipnameEn,imo:d,callSign:s.callSign,length:s.length,width:s.breadth,draught:(s.draught||100)/10}}async realTimePosition(t,n={}){const i=await this.getShipId(t,n),a=await this.getShipInfo(i,n),o={headers:{appKey:this.token},json:{shipId:i}},s="https://api3.myships.com/sp/ships/position/latest",d=await q.post(s,o).json();y==null||y.info("[%s] fetch realtime position from: %s - %j",n.requestId,s,o);const c=d.data[0];for(const u in c)!isNaN(c[u])&&Number(c[u])!==1/0&&(c[u]=Number(c[u]));const{labelCn:l,labelEn:m}=await this.parseStatus(c.aisNavStatus),f=v.unix(c.posTime);return{...a,mmsi:t,lat:Math.round(c.lat/1e4/60*1e5)/1e5,lng:Math.round(c.lon/1e4/60*1e5)/1e5,sog:Math.round(c.sog/10*100)/100,cog:Math.round(c.cog/10*100)/100,hdg:Math.round(c.heading*100)/100,rot:Math.round(c.rot*100)/100,positionTime:c.posTime,utc:f.utc().format(),status:c.aisNavStatus,labelEn:m,labelCn:l,method:"position",vendor:"myship"}}async trajectory(t,n,i,a,o=!0,s={}){const d=v(n),c=v(i),l=await this.getShipId(t),m=await this.getShipInfo(l),f=[];for(;c.diff(d,"day",!0)>30;)await this.trajectoryIn30Day(l,d.unix(),d.add(30,"day").unix(),m,t,a,f);return await this.trajectoryIn30Day(l,d.unix(),c.unix(),m,t,a,f),f}async trajectoryIn30Day(t,n,i,a,o,s,d,c={}){var S;const l={headers:{appKey:this.token},json:{shipId:t,startTime:n,endTime:i}},m="https://api3.myships.com/sp/ships/position/history",f=await q.post(m,l).json();if(y==null||y.info("[%s] fetch trajectory from: %s - %j",c.requestId,m,l),f.code!=="0")return y==null||y.warn("[%s] invoke myship trajectory failed: %j",c.requestId,f),f;const h=f.data;for(const M in h)!isNaN(h[M])&&Number(h[M])!==1/0&&(h[M]=Number(h[M]));const u=v.unix((S=h[0])==null?void 0:S.posTime);let I=-1;for(const M of h){const g=v.unix(M.posTime),r={imo:a==null?void 0:a.imo,mmsi:o,lat:Math.round(M.lat/1e4/60*1e5)/1e5,lng:Math.round(M.lon/1e4/60*1e5)/1e5,sog:Math.round(M.sog/10*100)/100,cog:Math.round(M.cog/10*100)/100,hdg:Math.round(M.heading*100)/100,rot:Math.round(M.rot*100)/100,positionTime:g.unix(),utc:g.utc().format(),method:"trajectory",vendor:"myship"},b=Math.floor(g.diff(u,"minute",!0)/(s||1));b!==I&&(I=b,d.push(r))}return d}}let V;try{V=_.getLogger("vessel")}catch{}finally{}var tt=(Y=>(Y.NOTICE="NOTICE",Y.WARN="WARN",Y.HEAVY="HEAVY",Y.SEVERE="SEVERE",Y.ERROR="ERROR",Y.FATAL="FATAL",Y))(tt||{});class et{parsePrinciple(e,t={}){var s,d,c;V==null||V.info("[%s] parse rule: %s",t.requestId,e);const n=new RegExp("(?<=\\[)(.+)(?=])","g"),i=e.match(n)?(s=e.match(n))==null?void 0:s[0]:void 0,a=i==null?void 0:i.split(";");if(!a)return;const o={};for(let l=0;l<(a==null?void 0:a.length);l++){const m=(c=(d=a[l].match(n))==null?void 0:d[0])==null?void 0:c.split("],");if(l===0&&!m)o.scope=a[0];else if(m)for(let f=0,h=m.length;f<h;f++){const u=this.parseRule(m[f]);u&&(o[u.level]?u.key?o[u.level][u==null?void 0:u.key]=u:o[u.level]=u:u.key?o[u.level]={[u==null?void 0:u.key]:u}:o[u.level]=u)}}return o}parseRule(e,t={}){var o;V==null||V.info("[%s] parse rule: %s",t.requestId,e),e=e.startsWith("[")?e:`[${e}`,e=e.endsWith("]")?e:`${e}]`;const n=new RegExp("(?<=\\[)(.+?)(?=])","g"),i=(o=e==null?void 0:e.match(n))==null?void 0:o[0],a=i==null?void 0:i.split(",");if(a)return{operator:a[0],number:Number.isNaN(Number(a[1]))?a[1]:Number(a[1]),level:a[2],time:Number(a[3]),key:a[4]}}checkWeather(e,t,n={}){var u,I,S,M,g,r,b,D,p,j,k,O,L,N,F;let i=0,a=0,o=0,s=0;const d=Math.round(((I=(u=t==null?void 0:t.SEVERE)==null?void 0:u.sigWave)==null?void 0:I.number)*1.6*100)/100,c=(M=(S=t==null?void 0:t.SEVERE)==null?void 0:S.sigWave)==null?void 0:M.number,l=(r=(g=t==null?void 0:t.HEAVY)==null?void 0:g.sigWave)==null?void 0:r.number,m=Math.round((((D=(b=t==null?void 0:t.SEVERE)==null?void 0:b.wind)==null?void 0:D.number)+2)*100)/100,f=(j=(p=t==null?void 0:t.SEVERE)==null?void 0:p.wind)==null?void 0:j.number,h=(O=(k=t==null?void 0:t.HEAVY)==null?void 0:k.wind)==null?void 0:O.number;for(let B=0;B<(e==null?void 0:e.length);B++){const E=e[B],A=(N=(L=E==null?void 0:E.meteo)==null?void 0:L.wave)==null?void 0:N.sig,R=(F=E==null?void 0:E.meteo)==null?void 0:F.wind,Z=B?v(E.eta).diff(v(e[B-1].eta),"hour",!0):0;s=Z>s?Z:s,V==null||V.info("[%s] check sig.wave: %j",n.requestId,{...A,dgThd4Wv:d,svThd4Wv:c,hvThd4Wv:l}),(A==null?void 0:A.height)>=d?E.isDangerous=!0:(A==null?void 0:A.height)>=c?E.isSevere=!0:(A==null?void 0:A.height)>=l&&(E.isHeavy=!0),V==null||V.info("[%s] check wind: %j",n.requestId,{...R,dgThd4Wd:m,svThd4Wd:f,hvThd4Wd:h}),(R==null?void 0:R.scale)>=m?(E.isDangerous=!0,delete E.isSevere,delete E.isHeavy):(R==null?void 0:R.scale)>f?(E.isDangerous||(E.isSevere=!0),delete E.isHeavy):(R==null?void 0:R.scale)===h&&!E.isDangerous&&!E.isSevere&&(E.isHeavy=!0),i+=E.isDangerous?Z:0,a+=E.isSevere?Z:0,o+=E.isHeavy?Z:0}return i=Math.round(i*100)/100,a=Math.round(a*100)/100,o=Math.round(o*100)/100,s=Math.round(s),{sample:e,dangerous:i,severe:a,heavy:o,step:s<3?3:s,wind:{dgThd4Wd:m,svThd4Wd:f,hvThd4Wd:h},sig:{dgThd4Wv:d,svThd4Wv:c,hvThd4Wv:l}}}}const ht=new et;let w;try{w=_.getLogger("vessel")}catch{}finally{}const lt=new X.MeteoHelper2("",!0);var st=(Y=>(Y.common="common",Y.container="container",Y.tugs="tugs",Y))(st||{}),at=(Y=>(Y.Ballast="Ballast",Y.Laden="Laden",Y))(at||{}),nt=(Y=>(Y.Cp="CP",Y.Perf="Basis",Y.Instruct="Other",Y))(nt||{});class C{static blockCoefficient(e,t,n,i){let a=Math.round(e/(t*n*i)*100)/100;a=a<.55?.55:a>.85?.85:a;const o=[.55,.6,.65,.7,.75,.8,.85],s=o.map(d=>Math.abs(d-a));return o[s.indexOf(Math.min(...s))]}static froudeNumber(e,t,n=9.8){let i=Math.round(Math.sqrt(e*e/(n*t))*100)/100;return i=i<.05?.05:i>.3?.3:i,i}static amendFactor(e,t,n){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]}[e];return n==="Laden"&&(o=i[e]),o[0]+o[1]*t+o[2]*Math.pow(t,2)}static directionFactor(e,t=0){let n;return e>30&&e<=60?n=(1.7-.03*Math.pow(t-4,2))/2:e>60&&e<=150?n=(.9-.06*Math.pow(t-6,2))/2:e>150&&e<=180?n=(.4-.03*Math.pow(t-8,2))/2:n=1,Math.round(n*1e5)/1e5}static vesselTagFactor(e,t,n,i=0){i=i>6?i-.9*(i-6):i;let a;return n==="container"?a=.7*i+Math.pow(i,6.5)/(22*Math.pow(e,2/3)):t==="Ballast"?a=.7*i+Math.pow(i,6.5)/(2.7*Math.pow(e,2/3)):a=.5*i+Math.pow(i,6.5)/(2.7*Math.pow(e,2/3)),a}static waveHeightFactor(e,t){e=e<0?.2:e,e=e>6?e-.9*(e-6):e,e=e>9?9:e;let n;return t>30&&t<=60?n=-.6:t>60&&t<=90?n=-.4:t>90&&t<=120?n=e<3?.4:-.3:t>120&&t<=150?n=e<3?.6:-.5:t>150&&t<=180?n=e<3?.7:-.6:n=-.7,Math.round(n*(.144*Math.pow(e,2)+.178*e)*1e4)/1e4}static assembleProperties(e,t,n,i){var f;const a=e.lbp??e.length??e.lengthOverall??198.9642,o=e.draught??8,s=e.breadthMoulded??e.breadth??e.breadthExtreme??32.4572,d=e.deadweight??67035.7773,c=((f=e==null?void 0:e.type)==null?void 0:f.toLowerCase())||"common";return{tag:c.indexOf("container")>-1?"container":c.indexOf("tugs")>-1?"tugs":"common",lbp:a,loadCondition:t,draught:o,breadthMoulded:s,displacement:Math.round((d/1.025+o*s*a*.7)*1e4)/1e4,speed:Math.round((n??14.1382)*1852/3600*1e4)/1e4,bearing:i||90}}static async speedLoseAt(e,t,n,i="",a=2,o=!0,s=!1,d={}){let c;if(t.velocity&&s&&(e.speed=W.LngLatHelper.roundPrecision(t.velocity*1852/3600,6)),o){let l;if(d.meteo2)try{const u=await lt.spotForecast(t.lat,t.lng,n.utc().format(),!1,!1,!0,d),[I]=$.Meteo2Assist.pickHourly(u,n);l=$.Meteo2Assist.toLegacy(I)}catch(u){w.warn("[%s] meteo2 spot(%j) forecast failed: %s",d.requestId,{...t,eta:n.utc().format()},u)}else l=await X.MeteoHelper.queryPointFactor(t.lng,t.lat,n.valueOf(),"wind,wave,current,watertemp",i,d);const m=C.weatherFactor(e,l),f=C.currentFactor(e.bearing,l==null?void 0:l.current,a),h=Math.round((e.speed*1.943844+m+f)*100)/100;c={meteo:{...l},wxFactor:m,cFactor:f,speed:t.velocity&&s?t.velocity:h<0?1:h,eta:n.utc().format("YYYY-MM-DDTHH:mm[Z]"),etd:n.utc().format("YYYY-MM-DDTHH:mm[Z]")}}else c={wxFactor:0,cFactor:0,speed:t.velocity&&s?t.velocity:Math.round((e.speed*1.943844+0+0)*100)/100,eta:n.utc().format("YYYY-MM-DDTHH:mm[Z]"),etd:n.utc().format("YYYY-MM-DDTHH:mm[Z]")};return delete t.meteo,delete t.wxFactor,delete t.cFactor,delete t.speed,delete t.etd,{...c,...t}}static async speedLoseInHoursStep(e,t,n,i,a,o,s="",d=!0,c=!1,l={}){t.utc();const m=t.clone().add(14,"days"),f=[],h=[];let u=0,I=0,S,M;for(let g=0;g<o.length-1;g++){let r=o[g];r.distanceFromStart=Math.round((a+I)*1e4)/1e4;const b=o[g+1];if(e.bearing=W.LaneHelper.calculateBearing(r,b,!b.gcToPrevious),r.bearing=e.bearing,r.suspend&&c){r.eta=r.eta||t.format("YYYY-MM-DDTHH:mm[Z]"),r.elapsed=r.elapsed??0;const j=r.suspend-r.elapsed;if(i-u>j)i=i-u-j,t.add(j,"hour"),r.elapsed=r.suspend;else{const k=i-u;r.elapsed+=k,t.add(k,"hour"),i=0}if(w==null||w.info(`[%s] suspend ${r.elapsed} hours at %j, and remain ${i} hours need to go...`,l.requestId,r),i===0)return r.distanceFromPrevious=I,{etd:t,from:M||r,to:r,next:o.filter(k=>k),wps:f,days:h}}else r.suspend=0;d=t.isAfter(m)?!1:d,r=await C.speedLoseAt(e,r,t,s,0,d,c,l),M=M||r,r.important&&f.push(r),t.isSameOrAfter(n)&&(h.push(r),n.add(24,"hour"));const D=W.LaneHelper.calculateDistance(r,b,!b.gcToPrevious);let p=Math.ceil(D/M.speed*1e4)/1e4;if(u+p<i){if(u+=p,t.add(p,"hour"),delete o[g],w==null||w.debug(`[%s] go to %j from %j with ${D}nm, and cost ${p} hours`,l.requestId,{lat:b.lat,lng:b.lng},{lat:M.lat,lng:M.lng,etd:M.etd}),I+=D,o.filter(j=>j).length<=1){S=b,S.eta=t.format("YYYY-MM-DDTHH:mm[Z]"),S.distanceFromPrevious=D,S.distanceFromStart=Math.round((a+I)*1e4)/1e4,f.push(S),delete o[g+1];break}}else{p=i-u,t.add(p,"hour");const j=W.LngLatHelper.roundPrecision(M.speed*p,4);S=W.LaneHelper.calculateCoordinate(r,e.bearing,j,"nauticalmiles",!b.gcToPrevious),S.eta=t.format("YYYY-MM-DDTHH:mm[Z]"),o[g]=S,w==null||w.debug(`[%s] go to %j from %j with ${j}nm, and cost ${p} hours`,l.requestId,{lat:S.lat,lng:S.lng},{lat:r.lat,lng:r.lng,etd:r.etd}),I+=j,S.distanceFromPrevious=Math.round(I*1e4)/1e4,S.distanceFromStart=Math.round((a+I)*1e4)/1e4;break}}return{etd:t,from:M,to:S,next:o.filter(g=>g),wps:f,days:h}}static currentFactor(e,t,n=0){const i=(e-(t==null?void 0:t.degree)||0)/180*Math.PI;if(Math.abs(i)===Math.PI/2)return 0;let a=((t==null?void 0:t.kts)||0)*Math.cos(i);return n&2?a=Math.ceil(a*100)/100:n&1?a=Math.floor(a*100)/100:a=Math.round(a*100)/100,Math.abs(a)>5?0:a}static weatherFactor(e,t){var m,f,h,u,I,S,M;w==null||w.debug("calculate weather factor via: %j",{...e,...t});const n=C.blockCoefficient(e.displacement,e.lbp,e.breadthMoulded,e.draught),i=C.froudeNumber(e.speed,e.lbp),a=C.amendFactor(n,i,e.loadCondition);let o=Math.abs(e.bearing%360-(((m=t==null?void 0:t.wind)==null?void 0:m.degree)%360||0));o=o>180?360-o:o;const s=C.directionFactor(o,(f=t==null?void 0:t.wind)==null?void 0:f.scale),d=C.vesselTagFactor(e.displacement,e.loadCondition,e.tag,(h=t==null?void 0:t.wind)==null?void 0:h.scale);let c=s*a*d/100*e.speed;c=Math.round(c*1.943844*1e4)/1e4*-1,e.tag==="tugs"&&Math.abs(c)>1&&(c=c/(Math.abs(Math.round(c))+1)),w==null||w.debug("wind wx factor = %d",c),o=Math.abs(e.bearing%360-(((I=(u=t==null?void 0:t.wave)==null?void 0:u.sig)==null?void 0:I.degree)%360||0));const l=C.waveHeightFactor(((M=(S=t==null?void 0:t.wave)==null?void 0:S.sig)==null?void 0:M.height)??1,o);return w==null||w.debug("wave wx factor = %d",l),c=c*.4+l,w==null||w.debug("weather factor = %d",c),c=Math.abs(c)>4?4*(Math.abs(c)/c)+Math.abs(c)/c*(Math.abs(c)-4)*.1:c,Math.round((c||0)*100)/100}static async analyseInstant(e,t,n,i,a,o="",s=0,d=!0,c=!1,l={}){var Z,z,U,Q,J;const m=v().valueOf();e.lng=W.LngLatHelper.convertToStdLng(e.lng);const{route:f,waypoints:h}=a.points,u=W.LaneHelper.calculateSubRoute(e,f);if(((Z=u[0])==null?void 0:Z.length)<=1)return;const{v0:I,label:S}=e.sog?{v0:e.sog,label:"Other"}:{v0:i.speed,label:"CP"},M=C.assembleProperties(n,i.loadCondition,I,0),g=h.length?W.LaneHelper.calculateSubWaypoints(e,h):[];g.forEach(H=>H.important=!0);const r={from:{...e},route:u,waypoints:g,v0:I,label:S},b={hours:[],days:[],wps:[]};s||(W.LaneHelper.calculateRouteDistance(u)/i.speed<=72?s=3:s=6);let D=W.LaneHelper.simplifyRouteToCoordinates(u,g,0),p=0,j=0,k=0,O=0;t=v(t).utc();const L=t.clone();for(;D.length>0;){const H=s-t.hour()%s,x=Math.ceil(t.clone().add(H,"h").set({minute:0,second:0,millisecond:0}).diff(t,"h",!0)*1e4)/1e4,P=await C.speedLoseInHoursStep(M,t,L,x,p,D,o,d,c,l);(z=P.from)!=null&&z.speed&&(b.hours.push(P.from),b.wps.push(...P.wps),b.days.push(...P.days)),D=P==null?void 0:P.next,D.length||b.hours.push(P==null?void 0:P.to),p+=Math.round((((U=P==null?void 0:P.to)==null?void 0:U.distanceFromPrevious)??0)*1e4)/1e4}const N=b.hours;for(let H=0;H<N.length-1;H++){const x=v(N[H+1].eta).diff(N[H].etd,"hour",!0)||1;j+=(N[H].wxFactor||0)*x,k+=(N[H].cFactor||0)*x,O+=x}(Q=b.wps)==null||Q.forEach((H,x)=>{if(x){const P=b.wps[x-1],ft=H.distanceFromStart-P.distanceFromStart,ot=v(H.eta).diff(v(P.etd),"h",!0);if(ot<1)H.avgSpd=P.speed;else{H.avgSpd=Math.round(ft/ot*100)/100;const it=Math.round((P.speed+H.speed)/2*100)/100;H.avgSpd=H.avgSpd>it?it:H.avgSpd}}}),r.sample=b;const F=b.hours.at(0),B=b.hours.at(-1);r.distance=Math.round(B.distanceFromStart*1e4)/1e4,r.etd=v(F.eta).utc().format(),r.eta=v(B.eta).utc().format(),r.wxFactor=Math.round(j/O*1e4)/1e4,r.cFactor=Math.round(k/O*1e4)/1e4,r.avgSpeed=Math.round(B.distanceFromStart/O*1e4)/1e4,r.totalHrs=Math.round(O*1e4)/1e4,r.totalFoCons=Math.round((i==null?void 0:i.fo)/24*r.totalHrs*1e3)/1e3,r.totalDgoCons=Math.round((i==null?void 0:i.dgo)/24*r.totalHrs*1e3)/1e3;const A=v().valueOf()-m,R=((J=b==null?void 0:b.hours)==null?void 0:J.length)||1;return w==null||w.info("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms",l==null?void 0:l.requestId,A,R,Math.round(A/R*1e3)/1e3),r}static async analyseInstantWithThreshed(e,t,n,i,a,o,s,d="",c=3,l=!0,m=!1,f={}){var Z,z,U,Q;const h=v().valueOf();e.lng=W.LngLatHelper.convertToStdLng(e.lng);const{v0:u,label:I}=e.sog?{v0:e.sog,label:"Other"}:{v0:a.speed,label:"CP"},S=C.assembleProperties(i,a.loadCondition,u,0),M=W.LaneHelper.calculateSubRoute(e,o);if(((Z=M[0])==null?void 0:Z.length)<=1)return;const g=s.length?W.LaneHelper.calculateSubWaypoints(e,s):[];g.forEach(J=>J.important=!0);let r=W.LaneHelper.simplifyRouteToCoordinates(M,g,0),b=0,D=0,p=0,j=0;const k={hours:[],wps:[],days:[]};t=v(t).utc();const O=t.clone();for(;r.length>0;){const J=c-t.hour()%c;let H=Math.ceil(t.clone().add(J,"h").set({minute:0,second:0,millisecond:0}).diff(t,"h",!0)*1e4)/1e4;H=t.clone().add(H,"h").isSameOrAfter(n)?n.diff(t,"h",!0)*1e4/1e4:H;const x=await C.speedLoseInHoursStep(S,t,O,H,b,r,d,l,m,f);if((z=x.from)!=null&&z.speed&&(k.hours.push(x.from),x!=null&&x.wps&&k.wps.push(...x.wps),k.days.push(...x.days)),r=x==null?void 0:x.next,r.length||k.hours.push(x==null?void 0:x.to),b+=Math.round((((U=x==null?void 0:x.to)==null?void 0:U.distanceFromPrevious)??0)*1e4)/1e4,!H)break}const L=k.hours;for(let J=0;J<L.length-1;J++){const H=v(L[J+1].eta).diff(L[J].etd,"hour",!0);D+=L[J].wxFactor*H,p+=L[J].cFactor*H,j+=H}const N=k.hours.at(0),F=k.hours.at(-1),B={sample:k,distance:Math.round(((F==null?void 0:F.distanceFromStart)||0)*1e4)/1e4,etd:v(N.eta).utc().format(),eta:v(F==null?void 0:F.eta).utc().format(),wxFactor:Math.round(D/j*1e4)/1e4,cFactor:Math.round(p/j*1e4)/1e4,avgSpeed:Math.round(((F==null?void 0:F.distanceFromStart)||0)/j*1e4)/1e4,totalHrs:Math.round(j*1e4)/1e4,totalFoCons:Math.round((a==null?void 0:a.fo)/24*j*1e3)/1e3,totalDgoCons:Math.round((a==null?void 0:a.dgo)/24*j*1e3)/1e3,from:N,to:F,route:M,waypoints:g,v0:u,label:I},A=v().valueOf()-h,R=((Q=k==null?void 0:k.hours)==null?void 0:Q.length)||1;return w==null||w.debug("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms",f==null?void 0:f.requestId,A,R,Math.round(A/R*1e3)/1e3),B}static async analyseCost(e,t,n,i,a={}){var M,g;const o=v().valueOf(),s=[];a.meteo2=!0,e.speedStep=e.speedStep||3,e.alterStep=e.alterStep??1;const d=W.LaneHelper.calculateRouteDistance(i.route);let c=0;n.forEach(r=>{const b=Math.ceil(d/r.speed/24);c=c<b?b:c}),c=c*1.3;const l=v.utc(e.etd).add(c??14,"day");let m=1;for(const r of n){const b=JSON.parse(JSON.stringify(i.route)),D=JSON.parse(JSON.stringify(i.waypoints)),p=await C.analyseInstantWithThreshed({lat:e.lat,lng:e.lng},e.etd,l,t,r,b,D,e.meteoVendor,e.speedStep,e.useMeteo,e.useRouteParam,a);p&&(await C.calculateCost(p,r,e,a),s.push(p),w==null||w.info("[%s][L%d-%d] analyse from %s to %s cost: %j",a.requestId,1,m,e.etd,l.format(),{cost:p.cost.total,distance:p.distance,hours:p.totalHrs,cp:`${r.speed}/${r.fo}/${r.dgo}`})),m++}s.sort((r,b)=>r.cost.total-b.cost.total);const f=s.at(0),h=s.at(1),u=[];if(u.push({combined:!1,speeds:[f],cost:(M=f.cost)==null?void 0:M.total}),h){const r=f.cost.cp,b=h.cost.cp,D=v(f.eta),p=v(f.etd),j=D.diff(p,"days",!0);let k=Math.ceil(j/2);k=k>7?7:k<e.alterStep?e.alterStep:k;let O=2,L={combined:!1,speeds:[h],cost:(g=h.cost)==null?void 0:g.total},N;for(;k>=e.alterStep;){const F=await C.combinedAnalyse(e,t,l,[r,b],i,k,{...a,level:O});if(L.cost>F.cost?N?(N==null?void 0:N.cost)>F.cost&&(N=F):(N=L,L=F):(!N||(N==null?void 0:N.cost)>F.cost)&&(N=F),k<=e.alterStep)break;k=Math.ceil(k/2),O+=1}u.push(L),N&&u.push(N)}const S=v().valueOf()-o;return w==null||w.info("[%s] analyse elapsed: %d ms",a==null?void 0:a.requestId,S),u.sort((r,b)=>r.cost-b.cost)}static async combinedAnalyse(e,t,n,i,a,o,s={}){s.counter=1,w==null||w.info("[%s][L%d] analyse with alternate cp in every %d days",s.requestId,s.level,o);const d=await C.alternateAnalyse(e,t,n,i,0,a,o,s),c=d.reduce((f,h)=>f+h.cost.total,0);w==null||w.info("[%s][L%d] cost with cpa/cpb turn: %d",s.requestId,s.level,c);const l=await C.alternateAnalyse(e,t,n,i,1,a,o,s),m=l.reduce((f,h)=>f+h.cost.total,0);return w==null||w.info("[%s][L%d] cost with cpb/cpa turn: %d",s.requestId,s.level,m),c<m?{combined:!0,cost:Math.round(c*1e3)/1e3,speeds:d}:{combined:!0,cost:Math.round(m*1e3)/1e3,speeds:l}}static async alternateAnalyse(e,t,n,i,a,o,s,d={}){var f,h;let c=v.utc(e.etd);const l={lat:e.lat,lng:e.lng},m=[];for(;c.isBefore(n);){const u=c.clone().utc().add(s,"day"),I=JSON.parse(JSON.stringify(o.route)),S=JSON.parse(JSON.stringify(o.waypoints)),M=i[a],g=await C.analyseInstantWithThreshed(l,c.format(),u,t,M,I,S,e.meteoVendor,e.speedStep,e.useMeteo,e.useRouteParam,d);g&&(await C.calculateCost(g,M,e,d),w==null||w.info("[%s][L%d-%d] analyse from %s to %s cost: %j",d.requestId,d.level,d.counter,c.utc().format(),u.utc().format(),{cost:g.cost.total,distance:g.distance,hours:g.totalHrs,cp:`${M.speed}/${M.fo}/${M.dgo}`})),d.counter=d.counter+1;const r=(h=(f=g==null?void 0:g.sample)==null?void 0:f.hours)==null?void 0:h.at(-1);if(r)l.lat=r.lat,l.lng=r.lng,c=v(r.eta),m.push(g),a=a?0:1;else break}return m}static async calculateCost(e,t,n,i={}){if(e){const a=Math.round(e.totalHrs/24*(n.dailyHire||0)*(1-(n.addComm||0))*1e3)/1e3,o=Math.round(e.totalFoCons*(n.priceFO||0)*1e3)/1e3,s=Math.round(e.totalDgoCons*(n.priceDGO||0)*1e3)/1e3;e.cost={total:Math.round((a+o+s)*1e3)/1e3,hire:a,bunker:Math.round((o+s)*1e3)/1e3,cp:t}}return e}static async mergeSpeeds(e,t={}){const n={hours:[],wps:[],days:[]},i=e.reduce((h,u)=>h+u.distance,0),a=e.reduce((h,u)=>h+u.totalHrs,0),o=e.reduce((h,u)=>h+u.wxFactor*u.totalHrs/a,0),s=e.reduce((h,u)=>h+u.cFactor*u.totalHrs/a,0),d=e.reduce((h,u)=>h+u.totalFoCons,0),c=e.reduce((h,u)=>h+u.totalDgoCons,0),l=e.reduce((h,u)=>h+u.cost.total,0),m=e.reduce((h,u)=>h+u.cost.hire,0),f=e.reduce((h,u)=>h+u.cost.bunker,0);for(const h of e){const u=h.sample.hours,I=h.sample.wps,S=h.sample.days;u.forEach(M=>{var r;((r=n.hours)==null?void 0:r.findIndex(b=>b.eta===M.eta))===-1&&n.hours.push(M)}),I.forEach(M=>{var r;((r=n.wps)==null?void 0:r.findIndex(b=>b.eta===M.eta))===-1&&n.wps.push(M)}),S.forEach(M=>{var r;((r=n==null?void 0:n.days)==null?void 0:r.findIndex(b=>b.eta===M.eta))===-1&&n.days.push(M)})}return{sample:n,etd:e.at(0).etd,eta:e.at(-1).eta,from:e.at(0).from,to:e.at(-1).to,label:"combined",distance:Math.round(i*1e4)/1e4,totalHrs:Math.round(a*1e3)/1e3,avgSpeed:Math.round(i/a*1e3)/1e3,wxFactor:Math.round(o/a*1e3)/1e3,cFactor:Math.round(s/a*1e3)/1e3,totalFoCons:Math.round(d*1e3)/1e3,totalDgoCons:Math.round(c*1e3)/1e3,cost:{total:Math.round(l*1e3)/1e3,hire:Math.round(m*1e3)/1e3,bunker:Math.round(f*1e3)/1e3}}}}T.AISImpl=G,T.AlertHelper=et,T.AlertLevel=tt,T.HifleetImpl=ct,T.LoadCondition=at,T.MyShipImpl=ut,T.MyVesselImpl=rt,T.ShipxyImpl=dt,T.SpeedHelper=C,T.SpeedLabel=nt,T.VesselTag=st,T.alertHelper=ht,Object.defineProperty(T,Symbol.toStringTag,{value:"Module"})});
|
|
@@ -67,6 +67,7 @@ export interface SpeedProps extends CostProps {
|
|
|
67
67
|
usePerfSpeed?: boolean;
|
|
68
68
|
useRouteParam?: boolean;
|
|
69
69
|
useMeteo?: boolean;
|
|
70
|
+
alterStep?: number;
|
|
70
71
|
lat?: number;
|
|
71
72
|
lng?: number;
|
|
72
73
|
etd?: string;
|
|
@@ -273,7 +274,6 @@ export declare class SpeedHelper {
|
|
|
273
274
|
}, options?: {
|
|
274
275
|
requestId?: string;
|
|
275
276
|
meteo2?: boolean;
|
|
276
|
-
maxDays?: number;
|
|
277
277
|
}): Promise<any[]>;
|
|
278
278
|
/**
|
|
279
279
|
* 按步长多次减半,分别用7,4,2,1天步长及cpa,cpb交替计算各种组合下的成本
|