@idm-plugin/vessel 1.2.2 → 1.2.4
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 +366 -327
- package/dist/index.umd.cjs +1 -1
- package/dist/speed/src/index.d.ts +8 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var
|
|
4
|
-
import
|
|
1
|
+
var tt = Object.defineProperty;
|
|
2
|
+
var et = (w, s, t) => s in w ? tt(w, s, { enumerable: !0, configurable: !0, writable: !0, value: t }) : w[s] = t;
|
|
3
|
+
var Z = (w, s, t) => (et(w, typeof s != "symbol" ? s + "" : s, t), t);
|
|
4
|
+
import A from "got";
|
|
5
5
|
import z from "@log4js-node/log4js-api";
|
|
6
6
|
import b from "moment";
|
|
7
|
-
import { LngLatHelper as
|
|
8
|
-
import { MeteoHelper as
|
|
9
|
-
let
|
|
7
|
+
import { LngLatHelper as B, LaneHelper as L } from "@idm-plugin/geo";
|
|
8
|
+
import { MeteoHelper as st } from "@idm-plugin/meteo";
|
|
9
|
+
let f;
|
|
10
10
|
try {
|
|
11
|
-
|
|
11
|
+
f = z.getLogger("vessel");
|
|
12
12
|
} catch {
|
|
13
13
|
} finally {
|
|
14
14
|
}
|
|
@@ -53,12 +53,12 @@ class K {
|
|
|
53
53
|
return { labelCn: t, labelEn: i };
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
|
-
class
|
|
56
|
+
class mt extends K {
|
|
57
57
|
constructor(t, i) {
|
|
58
58
|
super();
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
59
|
+
Z(this, "clientId");
|
|
60
|
+
Z(this, "clientSecret");
|
|
61
|
+
Z(this, "token");
|
|
62
62
|
this.clientId = t, this.clientSecret = i;
|
|
63
63
|
}
|
|
64
64
|
async authToken(t = {}) {
|
|
@@ -68,8 +68,8 @@ class lt extends K {
|
|
|
68
68
|
client_secret: this.clientSecret,
|
|
69
69
|
grant_type: "client_credentials"
|
|
70
70
|
}
|
|
71
|
-
}, n = await
|
|
72
|
-
|
|
71
|
+
}, n = await A.post(i, o).json();
|
|
72
|
+
f == null || f.info("[%s] fetch access token from: %s - %j", t.requestId, i, n), n.error || (this.token = {
|
|
73
73
|
accessToken: n.access_token,
|
|
74
74
|
tokenType: n.token_type,
|
|
75
75
|
expiresIn: n.expires_in,
|
|
@@ -79,21 +79,21 @@ class lt extends K {
|
|
|
79
79
|
});
|
|
80
80
|
}
|
|
81
81
|
async realTimePosition(t, i = {}) {
|
|
82
|
-
var
|
|
83
|
-
(!this.token || b().diff(b(this.token.issuedAt), "seconds") > ((
|
|
82
|
+
var u, l, M;
|
|
83
|
+
(!this.token || b().diff(b(this.token.issuedAt), "seconds") > ((u = this.token) == null ? void 0 : u.expiresIn) - 300) && await this.authToken(i);
|
|
84
84
|
const o = "https://svc.data.myvessel.cn/sdc/v1/vessels/status/location/unit", n = {
|
|
85
85
|
headers: {
|
|
86
|
-
Authorization: `${(
|
|
86
|
+
Authorization: `${(l = this.token) == null ? void 0 : l.tokenType} ${(M = this.token) == null ? void 0 : M.accessToken}`
|
|
87
87
|
},
|
|
88
88
|
searchParams: { mmsi: t }
|
|
89
89
|
};
|
|
90
|
-
|
|
91
|
-
const a = await
|
|
90
|
+
f == null || f.info("[%s] fetch realtime position from: %s - %j", i.requestId, o, n);
|
|
91
|
+
const a = await A.get(o, n).json();
|
|
92
92
|
if (a.code)
|
|
93
|
-
return
|
|
93
|
+
return f == null || f.warn("[%s] fetch realtime position failed: %j", i.requestId, o, { message: a.message, status: a.status, code: a.code }), a;
|
|
94
94
|
const e = a.data;
|
|
95
|
-
for (const
|
|
96
|
-
!isNaN(e[
|
|
95
|
+
for (const m in e)
|
|
96
|
+
!isNaN(e[m]) && Number(e[m]) !== 1 / 0 && (e[m] = Number(e[m]));
|
|
97
97
|
const d = b(`${e.postime} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
98
98
|
return {
|
|
99
99
|
mmsi: e.mmsi,
|
|
@@ -122,16 +122,16 @@ class lt extends K {
|
|
|
122
122
|
}
|
|
123
123
|
async trajectory(t, i, o, n, a = !0, e = {}) {
|
|
124
124
|
(!this.token || b().diff(b(this.token.issuedAt), "seconds") > this.token.expiresIn - 300) && await this.authToken(e);
|
|
125
|
-
const d = await this.realTimePosition(t, e),
|
|
126
|
-
for (;
|
|
127
|
-
await this.trajectoryIn30Day(t,
|
|
128
|
-
return await this.trajectoryIn30Day(t,
|
|
125
|
+
const d = await this.realTimePosition(t, e), c = b(i), u = b(o), l = [];
|
|
126
|
+
for (; u.diff(c, "day", !0) > 30; )
|
|
127
|
+
await this.trajectoryIn30Day(t, c, c.clone().add(30, "day"), d, n, l, e), c.add(30, "day");
|
|
128
|
+
return await this.trajectoryIn30Day(t, c, u, d, n, l, e), l;
|
|
129
129
|
}
|
|
130
130
|
async trajectoryIn30Day(t, i, o, n, a, e, d = {}) {
|
|
131
|
-
var
|
|
132
|
-
const
|
|
131
|
+
var h, v, I, Y, p;
|
|
132
|
+
const c = "https://svc.data.myvessel.cn/sdc/v1/vessels/status/track", u = {
|
|
133
133
|
headers: {
|
|
134
|
-
Authorization: `${(
|
|
134
|
+
Authorization: `${(h = this.token) == null ? void 0 : h.tokenType} ${(v = this.token) == null ? void 0 : v.accessToken}`
|
|
135
135
|
},
|
|
136
136
|
json: {
|
|
137
137
|
mmsi: t,
|
|
@@ -139,42 +139,42 @@ class lt extends K {
|
|
|
139
139
|
endTime: o.utcOffset(8).format("YYYY-MM-DD HH:mm:ss")
|
|
140
140
|
}
|
|
141
141
|
};
|
|
142
|
-
|
|
143
|
-
const
|
|
144
|
-
if (
|
|
145
|
-
return
|
|
146
|
-
let
|
|
147
|
-
const
|
|
148
|
-
return (
|
|
149
|
-
for (const S in
|
|
150
|
-
!isNaN(
|
|
151
|
-
const
|
|
152
|
-
mmsi:
|
|
142
|
+
f == null || f.info("[%s] fetch trajectory from: %s - %j", d.requestId, c, u);
|
|
143
|
+
const l = await A.post(c, u).json();
|
|
144
|
+
if (l.code)
|
|
145
|
+
return f == null || f.warn("[%s] fetch trajectory failed: %j", d.requestId, c, { message: l.message, status: l.status, code: l.code }), l;
|
|
146
|
+
let M = -1;
|
|
147
|
+
const m = b(`${(Y = (I = l.data) == null ? void 0 : I[0]) == null ? void 0 : Y.postime} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
148
|
+
return (p = l.data) == null || p.forEach((r) => {
|
|
149
|
+
for (const S in r)
|
|
150
|
+
!isNaN(r[S]) && Number(r[S]) !== 1 / 0 && (r[S] = Number(r[S]));
|
|
151
|
+
const y = b(`${r.postime} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00"), k = r.eta ? b(`${r.eta} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00") : void 0, g = r.status, { labelCn: j, labelEn: W } = this.parseStatus(g), F = {
|
|
152
|
+
mmsi: r.mmsi,
|
|
153
153
|
imo: n == null ? void 0 : n.imo,
|
|
154
|
-
lat:
|
|
155
|
-
lng:
|
|
156
|
-
sog:
|
|
157
|
-
cog:
|
|
158
|
-
hdg:
|
|
159
|
-
draught:
|
|
154
|
+
lat: r.lat,
|
|
155
|
+
lng: r.lon,
|
|
156
|
+
sog: r.sog,
|
|
157
|
+
cog: r.cog,
|
|
158
|
+
hdg: r.hdg,
|
|
159
|
+
draught: r.draught,
|
|
160
160
|
status: g,
|
|
161
|
-
eta:
|
|
162
|
-
destination:
|
|
163
|
-
positionTime:
|
|
164
|
-
labelCn:
|
|
165
|
-
labelEn:
|
|
161
|
+
eta: k == null ? void 0 : k.unix(),
|
|
162
|
+
destination: r.dest,
|
|
163
|
+
positionTime: y.unix(),
|
|
164
|
+
labelCn: j,
|
|
165
|
+
labelEn: W,
|
|
166
166
|
method: "trajectory",
|
|
167
167
|
vendor: "myVessel",
|
|
168
|
-
utc:
|
|
169
|
-
},
|
|
170
|
-
|
|
168
|
+
utc: y.utc().format()
|
|
169
|
+
}, O = Math.floor(y.diff(m, "minute", !0) / (a || 1));
|
|
170
|
+
O !== M && (M = O, e.push(F));
|
|
171
171
|
}), e;
|
|
172
172
|
}
|
|
173
173
|
}
|
|
174
|
-
class
|
|
174
|
+
class pt extends K {
|
|
175
175
|
constructor(t) {
|
|
176
176
|
super();
|
|
177
|
-
|
|
177
|
+
Z(this, "token");
|
|
178
178
|
this.token = t;
|
|
179
179
|
}
|
|
180
180
|
async realTimePosition(t, i = {}) {
|
|
@@ -183,15 +183,15 @@ class ft extends K {
|
|
|
183
183
|
mmsi: t,
|
|
184
184
|
usertoken: this.token
|
|
185
185
|
}
|
|
186
|
-
}, a = await
|
|
187
|
-
|
|
186
|
+
}, a = await A.post(o, n).json();
|
|
187
|
+
f == null || f.info("[%s] fetch realtime position from: %s - %j", i.requestId, o, n);
|
|
188
188
|
const e = a == null ? void 0 : a.list;
|
|
189
189
|
if (!e)
|
|
190
|
-
return
|
|
191
|
-
for (const
|
|
192
|
-
!isNaN(e[
|
|
190
|
+
return f == null || f.warn("[%s] fetch realtime position failed: %j", i.requestId, o, a), a;
|
|
191
|
+
for (const m in e)
|
|
192
|
+
!isNaN(e[m]) && Number(e[m]) !== 1 / 0 && (e[m] = Number(e[m]));
|
|
193
193
|
e.status = e.sp > 3 ? 0 : 1;
|
|
194
|
-
const d = e.status, { labelCn:
|
|
194
|
+
const d = e.status, { labelCn: c, labelEn: u } = this.parseStatus(d), l = b(`${e.ti} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
195
195
|
return {
|
|
196
196
|
mmsi: e.m,
|
|
197
197
|
name: e.n,
|
|
@@ -208,11 +208,11 @@ class ft extends K {
|
|
|
208
208
|
rot: isNaN(e.rot) ? 0 : e.rot,
|
|
209
209
|
eta: /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(e.eta) ? b(`${e.eta} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00").unix() : void 0,
|
|
210
210
|
destination: e.destination,
|
|
211
|
-
positionTime:
|
|
212
|
-
utc:
|
|
211
|
+
positionTime: l.unix(),
|
|
212
|
+
utc: l.utc().format(),
|
|
213
213
|
status: d,
|
|
214
|
-
labelCn:
|
|
215
|
-
labelEn:
|
|
214
|
+
labelCn: c,
|
|
215
|
+
labelEn: u,
|
|
216
216
|
method: "position",
|
|
217
217
|
vendor: "hifleet"
|
|
218
218
|
};
|
|
@@ -229,8 +229,8 @@ class ft extends K {
|
|
|
229
229
|
Host: "www.hifleet.com"
|
|
230
230
|
}
|
|
231
231
|
};
|
|
232
|
-
let a = await
|
|
233
|
-
|
|
232
|
+
let a = await A.post(o, n).json();
|
|
233
|
+
f == null || f.info("[%s] fetch vessel props from: %s - %j", i.requestId, o, n), a instanceof Array && (a = a[0]);
|
|
234
234
|
for (const d in a)
|
|
235
235
|
!isNaN(a[d]) && Number(a[d]) !== 1 / 0 && (a[d] = Number(a[d]));
|
|
236
236
|
const e = {
|
|
@@ -242,37 +242,37 @@ class ft extends K {
|
|
|
242
242
|
breadth: a.b,
|
|
243
243
|
draught: a.dr
|
|
244
244
|
};
|
|
245
|
-
return o = "https://www.hifleet.com/hifleetapi/sameShipSearch.do", a = await
|
|
245
|
+
return o = "https://www.hifleet.com/hifleetapi/sameShipSearch.do", a = await A.post(o, n).json(), f == null || f.info("[%s] fetch vessel dead weight from: %s - %j", i.requestId, o, n), a instanceof Array && (a = a[0]), a && (e.deadweight = Number(a.dwt)), e;
|
|
246
246
|
}
|
|
247
247
|
async trajectory(t, i, o, n, a = !0, e = {}) {
|
|
248
|
-
var
|
|
248
|
+
var r, y, k;
|
|
249
249
|
const d = await this.realTimePosition(t, e);
|
|
250
|
-
let
|
|
251
|
-
const
|
|
250
|
+
let c = b(i);
|
|
251
|
+
const u = b(o), l = b();
|
|
252
252
|
if (a) {
|
|
253
|
-
let g =
|
|
254
|
-
g < 0 ?
|
|
253
|
+
let g = u.diff(c, "d", !0);
|
|
254
|
+
g < 0 ? c = u.clone().subtract(40, "d") : g < 30 ? c.subtract(10, "d") : g < 60 ? c.subtract(5, "d") : c = u.clone().subtract(80, "d"), g = l.diff(u, "d", !0), u.add(g > 10 ? 240 : g * 24, "h");
|
|
255
255
|
}
|
|
256
|
-
const
|
|
256
|
+
const M = {
|
|
257
257
|
searchParams: {
|
|
258
|
-
endtime:
|
|
259
|
-
starttime:
|
|
258
|
+
endtime: u.utcOffset("+8:00").format("YYYY-MM-DD HH:mm:ss"),
|
|
259
|
+
starttime: c.utcOffset("+8:00").format("YYYY-MM-DD HH:mm:ss"),
|
|
260
260
|
mmsi: t,
|
|
261
261
|
usertoken: this.token
|
|
262
262
|
}
|
|
263
|
-
},
|
|
264
|
-
|
|
263
|
+
}, m = "https://api.hifleet.com/position/trajectory/nocompressed/withstatic/token", h = await A.get(m, M).json();
|
|
264
|
+
f == null || f.info("[%s] fetch trajectory from: %s - %j", e.requestId, m, M);
|
|
265
265
|
let v;
|
|
266
|
-
|
|
267
|
-
const
|
|
268
|
-
let
|
|
269
|
-
const
|
|
266
|
+
h && (v = ((y = (r = h.ships) == null ? void 0 : r.offors) == null ? void 0 : y.ship) || [], v.length || f == null || f.warn("[%s] fetch trajectory failed: %j", e.requestId, h));
|
|
267
|
+
const I = [];
|
|
268
|
+
let Y = -1;
|
|
269
|
+
const p = b(`${(k = v == null ? void 0 : v[0]) == null ? void 0 : k.ti} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
270
270
|
for (const g of v) {
|
|
271
|
-
for (const
|
|
272
|
-
!isNaN(g[
|
|
273
|
-
const
|
|
271
|
+
for (const D in g)
|
|
272
|
+
!isNaN(g[D]) && Number(g[D]) !== 1 / 0 && (g[D] = Number(g[D]));
|
|
273
|
+
const j = b(`${g.ti} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
274
274
|
g.status = g.sp > 4 ? 0 : 1;
|
|
275
|
-
const { labelEn:
|
|
275
|
+
const { labelEn: W, labelCn: F } = this.parseStatus(g.status), O = {
|
|
276
276
|
mmsi: g.m,
|
|
277
277
|
name: g.n,
|
|
278
278
|
imo: d == null ? void 0 : d.imo,
|
|
@@ -282,23 +282,23 @@ class ft extends K {
|
|
|
282
282
|
sog: g.sp,
|
|
283
283
|
cog: g.co,
|
|
284
284
|
hdg: g.hdg,
|
|
285
|
-
positionTime:
|
|
286
|
-
utc:
|
|
285
|
+
positionTime: j.unix(),
|
|
286
|
+
utc: j.utc().format(),
|
|
287
287
|
status: g.status,
|
|
288
|
-
labelCn:
|
|
289
|
-
labelEn:
|
|
288
|
+
labelCn: F,
|
|
289
|
+
labelEn: W,
|
|
290
290
|
method: "trajectory",
|
|
291
291
|
vendor: "hifleet"
|
|
292
|
-
}, S = Math.floor(
|
|
293
|
-
S !==
|
|
292
|
+
}, S = Math.floor(j.diff(p, "minute", !0) / (n || 1));
|
|
293
|
+
S !== Y && (Y = S, I.push(O));
|
|
294
294
|
}
|
|
295
|
-
return
|
|
295
|
+
return I;
|
|
296
296
|
}
|
|
297
297
|
}
|
|
298
|
-
class
|
|
298
|
+
class Mt extends K {
|
|
299
299
|
constructor(t) {
|
|
300
300
|
super();
|
|
301
|
-
|
|
301
|
+
Z(this, "token");
|
|
302
302
|
this.token = t;
|
|
303
303
|
}
|
|
304
304
|
async realTimePosition(t, i = {}) {
|
|
@@ -308,13 +308,13 @@ class mt extends K {
|
|
|
308
308
|
k: this.token,
|
|
309
309
|
enc: 1
|
|
310
310
|
}
|
|
311
|
-
}, n = "https://api.shipxy.com/apicall/GetSingleShip", a = await
|
|
312
|
-
if (
|
|
311
|
+
}, n = "https://api.shipxy.com/apicall/GetSingleShip", a = await A.get(n, o).json();
|
|
312
|
+
if (f == null || f.info("[%s] fetch realtime position from: %s - %j", i.requestId, n, o), (a == null ? void 0 : a.status) !== 0)
|
|
313
313
|
return a;
|
|
314
314
|
const e = a.data[0];
|
|
315
|
-
for (const
|
|
316
|
-
!isNaN(e[
|
|
317
|
-
const { labelCn: d, labelEn:
|
|
315
|
+
for (const M in e)
|
|
316
|
+
!isNaN(e[M]) && Number(e[M]) !== 1 / 0 && (e[M] = Number(e[M]));
|
|
317
|
+
const { labelCn: d, labelEn: c } = await this.parseStatus(e.navistat), u = b.unix(e.lasttime);
|
|
318
318
|
return {
|
|
319
319
|
mmsi: e.ShipID,
|
|
320
320
|
name: e.name,
|
|
@@ -330,52 +330,52 @@ class mt extends K {
|
|
|
330
330
|
hdg: Math.round(e.hdg / 100 * 100) / 100,
|
|
331
331
|
rot: Math.round(e.rot / 100 * 100) / 100,
|
|
332
332
|
positionTime: e.lasttime,
|
|
333
|
-
utc:
|
|
333
|
+
utc: u.utc().format(),
|
|
334
334
|
status: e.navistat,
|
|
335
|
-
labelEn:
|
|
335
|
+
labelEn: c,
|
|
336
336
|
labelCn: d,
|
|
337
337
|
method: "position",
|
|
338
338
|
vendor: "shipxy"
|
|
339
339
|
};
|
|
340
340
|
}
|
|
341
341
|
async trajectory(t, i, o, n, a = !0, e = {}) {
|
|
342
|
-
var
|
|
343
|
-
const d = await this.realTimePosition(t, e),
|
|
342
|
+
var p;
|
|
343
|
+
const d = await this.realTimePosition(t, e), c = b(i), u = b(o), l = "https://api.shipxy.com/apicall/GetShipTrack", M = {
|
|
344
344
|
searchParams: {
|
|
345
345
|
id: t,
|
|
346
346
|
k: this.token,
|
|
347
347
|
enc: 1,
|
|
348
348
|
cut: 0,
|
|
349
|
-
btm:
|
|
350
|
-
etm:
|
|
349
|
+
btm: c.unix(),
|
|
350
|
+
etm: u.unix()
|
|
351
351
|
}
|
|
352
|
-
},
|
|
353
|
-
if (
|
|
354
|
-
return
|
|
355
|
-
const
|
|
356
|
-
let
|
|
357
|
-
for (const
|
|
358
|
-
const
|
|
352
|
+
}, m = await A.get(l, M).json();
|
|
353
|
+
if (f == null || f.info("[%s] fetch trajectory from: %s - %j", e.requestId, l, M), (m == null ? void 0 : m.status) !== 0)
|
|
354
|
+
return m;
|
|
355
|
+
const h = m == null ? void 0 : m.points, v = [], I = b.unix((p = h[0]) == null ? void 0 : p.utc);
|
|
356
|
+
let Y = -1;
|
|
357
|
+
for (const r of h) {
|
|
358
|
+
const y = b.unix(r.utc), k = {
|
|
359
359
|
imo: d == null ? void 0 : d.imo,
|
|
360
360
|
mmsi: t,
|
|
361
|
-
sog: Math.round(
|
|
362
|
-
cog: Math.round(
|
|
363
|
-
lat: Math.round(
|
|
364
|
-
lng: Math.round(
|
|
365
|
-
positionTime:
|
|
366
|
-
utc:
|
|
361
|
+
sog: Math.round(r.sog * 3600 / 1e3 / 1852 * 100) / 100,
|
|
362
|
+
cog: Math.round(r.cog / 100 * 100) / 100,
|
|
363
|
+
lat: Math.round(r.lat / 1e6 * 1e5) / 1e5,
|
|
364
|
+
lng: Math.round(r.lon / 1e6 * 1e5) / 1e5,
|
|
365
|
+
positionTime: y.unix(),
|
|
366
|
+
utc: y.utc().format(),
|
|
367
367
|
method: "trajectory",
|
|
368
368
|
vendor: "shipxy"
|
|
369
|
-
}, g = Math.floor(
|
|
370
|
-
g !==
|
|
369
|
+
}, g = Math.floor(y.diff(I, "minute", !0) / (n || 1));
|
|
370
|
+
g !== Y && (Y = g, v.push(k));
|
|
371
371
|
}
|
|
372
372
|
return v;
|
|
373
373
|
}
|
|
374
374
|
}
|
|
375
|
-
class
|
|
375
|
+
class yt extends K {
|
|
376
376
|
constructor(t) {
|
|
377
377
|
super();
|
|
378
|
-
|
|
378
|
+
Z(this, "token");
|
|
379
379
|
this.token = t;
|
|
380
380
|
}
|
|
381
381
|
async getShipId(t, i = {}) {
|
|
@@ -386,8 +386,8 @@ class pt extends K {
|
|
|
386
386
|
json: {
|
|
387
387
|
mmsiList: t
|
|
388
388
|
}
|
|
389
|
-
}, n = "https://api3.myships.com/sp/ships/getShipIdByMMSI", a = await
|
|
390
|
-
return
|
|
389
|
+
}, n = "https://api3.myships.com/sp/ships/getShipIdByMMSI", a = await A.post(n, o).json();
|
|
390
|
+
return f == null || f.info("[%s] fetch ship id from: %s - %j", i.requestId, n, o), a.code !== "0" ? a : a.data[0].shipId;
|
|
391
391
|
}
|
|
392
392
|
async getShipInfo(t, i = {}) {
|
|
393
393
|
const o = {
|
|
@@ -397,12 +397,12 @@ class pt extends K {
|
|
|
397
397
|
json: {
|
|
398
398
|
shipId: t
|
|
399
399
|
}
|
|
400
|
-
}, n = "https://api3.myships.com/sp/ships/aissta", a = await
|
|
401
|
-
if (
|
|
400
|
+
}, n = "https://api3.myships.com/sp/ships/aissta", a = await A.post(n, o).json();
|
|
401
|
+
if (f == null || f.info("[%s] fetch ship info from: %s - %j", i.requestId, n, o), a.code !== "0")
|
|
402
402
|
return a;
|
|
403
403
|
const e = a.data;
|
|
404
404
|
let d = e.imo;
|
|
405
|
-
return t === "407170" && (d = "9198379",
|
|
405
|
+
return t === "407170" && (d = "9198379", f == null || f.warn("[%s] ship(%s) imo error: %s, should be %s", i.requestId, t, e.imo, d)), {
|
|
406
406
|
mmsi: e.mmsi,
|
|
407
407
|
name: e.shipnameEn,
|
|
408
408
|
imo: d,
|
|
@@ -420,39 +420,39 @@ class pt extends K {
|
|
|
420
420
|
json: {
|
|
421
421
|
shipId: o
|
|
422
422
|
}
|
|
423
|
-
}, e = "https://api3.myships.com/sp/ships/position/latest", d = await
|
|
424
|
-
|
|
425
|
-
const
|
|
426
|
-
for (const
|
|
427
|
-
!isNaN(
|
|
428
|
-
const { labelCn:
|
|
423
|
+
}, e = "https://api3.myships.com/sp/ships/position/latest", d = await A.post(e, a).json();
|
|
424
|
+
f == null || f.info("[%s] fetch realtime position from: %s - %j", i.requestId, e, a);
|
|
425
|
+
const c = d.data[0];
|
|
426
|
+
for (const h in c)
|
|
427
|
+
!isNaN(c[h]) && Number(c[h]) !== 1 / 0 && (c[h] = Number(c[h]));
|
|
428
|
+
const { labelCn: u, labelEn: l } = await this.parseStatus(c.aisNavStatus), M = b.unix(c.posTime);
|
|
429
429
|
return {
|
|
430
430
|
...n,
|
|
431
431
|
mmsi: t,
|
|
432
|
-
lat: Math.round(
|
|
433
|
-
lng: Math.round(
|
|
434
|
-
sog: Math.round(
|
|
435
|
-
cog: Math.round(
|
|
436
|
-
hdg: Math.round(
|
|
437
|
-
rot: Math.round(
|
|
438
|
-
positionTime:
|
|
439
|
-
utc:
|
|
440
|
-
status:
|
|
441
|
-
labelEn:
|
|
442
|
-
labelCn:
|
|
432
|
+
lat: Math.round(c.lat / 1e4 / 60 * 1e5) / 1e5,
|
|
433
|
+
lng: Math.round(c.lon / 1e4 / 60 * 1e5) / 1e5,
|
|
434
|
+
sog: Math.round(c.sog / 10 * 100) / 100,
|
|
435
|
+
cog: Math.round(c.cog / 10 * 100) / 100,
|
|
436
|
+
hdg: Math.round(c.heading * 100) / 100,
|
|
437
|
+
rot: Math.round(c.rot * 100) / 100,
|
|
438
|
+
positionTime: c.posTime,
|
|
439
|
+
utc: M.utc().format(),
|
|
440
|
+
status: c.aisNavStatus,
|
|
441
|
+
labelEn: l,
|
|
442
|
+
labelCn: u,
|
|
443
443
|
method: "position",
|
|
444
444
|
vendor: "myship"
|
|
445
445
|
};
|
|
446
446
|
}
|
|
447
447
|
async trajectory(t, i, o, n, a = !0, e = {}) {
|
|
448
|
-
const d = b(i),
|
|
449
|
-
for (;
|
|
450
|
-
await this.trajectoryIn30Day(
|
|
451
|
-
return await this.trajectoryIn30Day(
|
|
452
|
-
}
|
|
453
|
-
async trajectoryIn30Day(t, i, o, n, a, e, d,
|
|
454
|
-
var
|
|
455
|
-
const
|
|
448
|
+
const d = b(i), c = b(o), u = await this.getShipId(t), l = await this.getShipInfo(u), M = [];
|
|
449
|
+
for (; c.diff(d, "day", !0) > 30; )
|
|
450
|
+
await this.trajectoryIn30Day(u, d.unix(), d.add(30, "day").unix(), l, t, n, M);
|
|
451
|
+
return await this.trajectoryIn30Day(u, d.unix(), c.unix(), l, t, n, M), M;
|
|
452
|
+
}
|
|
453
|
+
async trajectoryIn30Day(t, i, o, n, a, e, d, c = {}) {
|
|
454
|
+
var I;
|
|
455
|
+
const u = {
|
|
456
456
|
headers: {
|
|
457
457
|
appKey: this.token
|
|
458
458
|
},
|
|
@@ -461,42 +461,42 @@ class pt extends K {
|
|
|
461
461
|
startTime: i,
|
|
462
462
|
endTime: o
|
|
463
463
|
}
|
|
464
|
-
},
|
|
465
|
-
if (
|
|
466
|
-
return
|
|
467
|
-
const
|
|
468
|
-
for (const
|
|
469
|
-
!isNaN(
|
|
470
|
-
const
|
|
464
|
+
}, l = "https://api3.myships.com/sp/ships/position/history", M = await A.post(l, u).json();
|
|
465
|
+
if (f == null || f.info("[%s] fetch trajectory from: %s - %j", c.requestId, l, u), M.code !== "0")
|
|
466
|
+
return f == null || f.warn("[%s] invoke myship trajectory failed: %j", c.requestId, M), M;
|
|
467
|
+
const m = M.data;
|
|
468
|
+
for (const Y in m)
|
|
469
|
+
!isNaN(m[Y]) && Number(m[Y]) !== 1 / 0 && (m[Y] = Number(m[Y]));
|
|
470
|
+
const h = b.unix((I = m[0]) == null ? void 0 : I.posTime);
|
|
471
471
|
let v = -1;
|
|
472
|
-
for (const
|
|
473
|
-
const
|
|
472
|
+
for (const Y of m) {
|
|
473
|
+
const p = b.unix(Y.posTime), r = {
|
|
474
474
|
imo: n == null ? void 0 : n.imo,
|
|
475
475
|
mmsi: a,
|
|
476
|
-
lat: Math.round(
|
|
477
|
-
lng: Math.round(
|
|
478
|
-
sog: Math.round(
|
|
479
|
-
cog: Math.round(
|
|
480
|
-
hdg: Math.round(
|
|
481
|
-
rot: Math.round(
|
|
482
|
-
positionTime:
|
|
483
|
-
utc:
|
|
476
|
+
lat: Math.round(Y.lat / 1e4 / 60 * 1e5) / 1e5,
|
|
477
|
+
lng: Math.round(Y.lon / 1e4 / 60 * 1e5) / 1e5,
|
|
478
|
+
sog: Math.round(Y.sog / 10 * 100) / 100,
|
|
479
|
+
cog: Math.round(Y.cog / 10 * 100) / 100,
|
|
480
|
+
hdg: Math.round(Y.heading * 100) / 100,
|
|
481
|
+
rot: Math.round(Y.rot * 100) / 100,
|
|
482
|
+
positionTime: p.unix(),
|
|
483
|
+
utc: p.utc().format(),
|
|
484
484
|
method: "trajectory",
|
|
485
485
|
vendor: "myship"
|
|
486
|
-
},
|
|
487
|
-
|
|
486
|
+
}, y = Math.floor(p.diff(h, "minute", !0) / (e || 1));
|
|
487
|
+
y !== v && (v = y, d.push(r));
|
|
488
488
|
}
|
|
489
489
|
return d;
|
|
490
490
|
}
|
|
491
491
|
}
|
|
492
|
-
let
|
|
492
|
+
let R;
|
|
493
493
|
try {
|
|
494
|
-
|
|
494
|
+
R = z.getLogger("vessel");
|
|
495
495
|
} catch {
|
|
496
496
|
} finally {
|
|
497
497
|
}
|
|
498
|
-
var
|
|
499
|
-
class
|
|
498
|
+
var at = /* @__PURE__ */ ((w) => (w.NOTICE = "NOTICE", w.WARN = "WARN", w.HEAVY = "HEAVY", w.SEVERE = "SEVERE", w.ERROR = "ERROR", w.FATAL = "FATAL", w))(at || {});
|
|
499
|
+
class ot {
|
|
500
500
|
/**
|
|
501
501
|
* 解析告警规则, 多规则场景
|
|
502
502
|
* @param rule
|
|
@@ -506,20 +506,20 @@ class st {
|
|
|
506
506
|
* @param options
|
|
507
507
|
*/
|
|
508
508
|
parsePrinciple(s, t = {}) {
|
|
509
|
-
var e, d,
|
|
510
|
-
|
|
509
|
+
var e, d, c;
|
|
510
|
+
R == null || R.info("[%s] parse rule: %s", t.requestId, s);
|
|
511
511
|
const i = new RegExp("(?<=\\[)(.+)(?=])", "g"), o = s.match(i) ? (e = s.match(i)) == null ? void 0 : e[0] : void 0, n = o == null ? void 0 : o.split(";");
|
|
512
512
|
if (!n)
|
|
513
513
|
return;
|
|
514
514
|
const a = {};
|
|
515
|
-
for (let
|
|
516
|
-
const
|
|
517
|
-
if (
|
|
515
|
+
for (let u = 0; u < (n == null ? void 0 : n.length); u++) {
|
|
516
|
+
const l = (c = (d = n[u].match(i)) == null ? void 0 : d[0]) == null ? void 0 : c.split("],");
|
|
517
|
+
if (u === 0 && !l)
|
|
518
518
|
a.scope = n[0];
|
|
519
|
-
else if (
|
|
520
|
-
for (let
|
|
521
|
-
const
|
|
522
|
-
|
|
519
|
+
else if (l)
|
|
520
|
+
for (let M = 0, m = l.length; M < m; M++) {
|
|
521
|
+
const h = this.parseRule(l[M]);
|
|
522
|
+
h && (a[h.level] ? h.key ? a[h.level][h == null ? void 0 : h.key] = h : a[h.level] = h : h.key ? a[h.level] = { [h == null ? void 0 : h.key]: h } : a[h.level] = h);
|
|
523
523
|
}
|
|
524
524
|
}
|
|
525
525
|
return a;
|
|
@@ -532,7 +532,7 @@ class st {
|
|
|
532
532
|
*/
|
|
533
533
|
parseRule(s, t = {}) {
|
|
534
534
|
var a;
|
|
535
|
-
|
|
535
|
+
R == null || R.info("[%s] parse rule: %s", t.requestId, s), s = s.startsWith("[") ? s : `[${s}`, s = s.endsWith("]") ? s : `${s}]`;
|
|
536
536
|
const i = new RegExp("(?<=\\[)(.+?)(?=])", "g"), o = (a = s == null ? void 0 : s.match(i)) == null ? void 0 : a[0], n = o == null ? void 0 : o.split(",");
|
|
537
537
|
if (n)
|
|
538
538
|
return {
|
|
@@ -550,25 +550,25 @@ class st {
|
|
|
550
550
|
* @param options
|
|
551
551
|
*/
|
|
552
552
|
checkWeather(s, t, i = {}) {
|
|
553
|
-
var
|
|
553
|
+
var h, v, I, Y, p, r, y, k, g, j, W, F, O, S, D;
|
|
554
554
|
let o = 0, n = 0, a = 0, e = 0;
|
|
555
|
-
const d = Math.round(((v = (
|
|
556
|
-
for (let
|
|
557
|
-
const
|
|
558
|
-
e = _ > e ? _ : e,
|
|
555
|
+
const d = Math.round(((v = (h = t == null ? void 0 : t.SEVERE) == null ? void 0 : h.sigWave) == null ? void 0 : v.number) * 1.6 * 100) / 100, c = (Y = (I = t == null ? void 0 : t.SEVERE) == null ? void 0 : I.sigWave) == null ? void 0 : Y.number, u = (r = (p = t == null ? void 0 : t.HEAVY) == null ? void 0 : p.sigWave) == null ? void 0 : r.number, l = Math.round((((k = (y = t == null ? void 0 : t.SEVERE) == null ? void 0 : y.wind) == null ? void 0 : k.number) + 2) * 100) / 100, M = (j = (g = t == null ? void 0 : t.SEVERE) == null ? void 0 : g.wind) == null ? void 0 : j.number, m = (F = (W = t == null ? void 0 : t.HEAVY) == null ? void 0 : W.wind) == null ? void 0 : F.number;
|
|
556
|
+
for (let N = 0; N < (s == null ? void 0 : s.length); N++) {
|
|
557
|
+
const T = s[N], P = (S = (O = T == null ? void 0 : T.meteo) == null ? void 0 : O.wave) == null ? void 0 : S.sig, C = (D = T == null ? void 0 : T.meteo) == null ? void 0 : D.wind, _ = N ? b(T.eta).diff(b(s[N - 1].eta), "hour", !0) : 0;
|
|
558
|
+
e = _ > e ? _ : e, R == null || R.info("[%s] check sig.wave: %j", i.requestId, { ...P, dgThd4Wv: d, svThd4Wv: c, hvThd4Wv: u }), (P == null ? void 0 : P.height) >= d ? T.isDangerous = !0 : (P == null ? void 0 : P.height) >= c ? T.isSevere = !0 : (P == null ? void 0 : P.height) >= u && (T.isHeavy = !0), R == null || R.info("[%s] check wind: %j", i.requestId, { ...C, dgThd4Wd: l, svThd4Wd: M, hvThd4Wd: m }), (C == null ? void 0 : C.scale) >= l ? (T.isDangerous = !0, delete T.isSevere, delete T.isHeavy) : (C == null ? void 0 : C.scale) > M ? (T.isDangerous || (T.isSevere = !0), delete T.isHeavy) : (C == null ? void 0 : C.scale) === m && !T.isDangerous && !T.isSevere && (T.isHeavy = !0), o += T.isDangerous ? _ : 0, n += T.isSevere ? _ : 0, a += T.isHeavy ? _ : 0;
|
|
559
559
|
}
|
|
560
|
-
return o = Math.round(o * 100) / 100, n = Math.round(n * 100) / 100, a = Math.round(a * 100) / 100, e = Math.round(e), { sample: s, dangerous: o, severe: n, heavy: a, step: e < 3 ? 3 : e, wind: { dgThd4Wd:
|
|
560
|
+
return o = Math.round(o * 100) / 100, n = Math.round(n * 100) / 100, a = Math.round(a * 100) / 100, e = Math.round(e), { sample: s, dangerous: o, severe: n, heavy: a, step: e < 3 ? 3 : e, wind: { dgThd4Wd: l, svThd4Wd: M, hvThd4Wd: m }, sig: { dgThd4Wv: d, svThd4Wv: c, hvThd4Wv: u } };
|
|
561
561
|
}
|
|
562
562
|
}
|
|
563
|
-
const
|
|
564
|
-
let
|
|
563
|
+
const gt = new ot();
|
|
564
|
+
let H;
|
|
565
565
|
try {
|
|
566
|
-
|
|
566
|
+
H = z.getLogger("vessel");
|
|
567
567
|
} catch {
|
|
568
568
|
} finally {
|
|
569
569
|
}
|
|
570
|
-
var
|
|
571
|
-
class
|
|
570
|
+
var nt = /* @__PURE__ */ ((w) => (w.common = "common", w.container = "container", w))(nt || {}), it = /* @__PURE__ */ ((w) => (w.Ballast = "Ballast", w.Laden = "Laden", w))(it || {}), rt = /* @__PURE__ */ ((w) => (w.Cp = "CP", w.Perf = "Basis", w.Instruct = "Other", w))(rt || {});
|
|
571
|
+
class q {
|
|
572
572
|
/**
|
|
573
573
|
* @see https://baike.baidu.com/item/%E6%96%B9%E5%BD%A2%E7%B3%BB%E6%95%B0/4965568?fr=aladdin
|
|
574
574
|
* 方形系数(block coefficient)
|
|
@@ -678,11 +678,11 @@ class E {
|
|
|
678
678
|
* @private
|
|
679
679
|
*/
|
|
680
680
|
static assembleProperties(s, t, i, o) {
|
|
681
|
-
var
|
|
681
|
+
var u, l;
|
|
682
682
|
const n = s.lbp ?? s.length ?? s.lengthOverall ?? 198.9642, a = s.draught ?? 8, e = s.breadthMoulded ?? s.breadth ?? s.breadthExtreme ?? 32.4572, d = s.deadweight ?? 67035.7773;
|
|
683
683
|
return {
|
|
684
684
|
// @ts-ignore
|
|
685
|
-
tag: ((
|
|
685
|
+
tag: ((l = (u = s == null ? void 0 : s.type) == null ? void 0 : u.toLowerCase()) == null ? void 0 : l.indexOf("container")) > -1 ? "container" : "common",
|
|
686
686
|
lbp: n,
|
|
687
687
|
loadCondition: t,
|
|
688
688
|
draught: a,
|
|
@@ -702,19 +702,30 @@ class E {
|
|
|
702
702
|
* @param eta 位置时间
|
|
703
703
|
* @param source [CMEMS, GFS, Other]
|
|
704
704
|
* @param role 1: 船东, 2: 租家, 0: 未知
|
|
705
|
+
* @param useMeteo true 启用气象分析
|
|
705
706
|
* @param useRouteParam true 启用设置速度
|
|
706
707
|
*/
|
|
707
|
-
static async speedLoseAt(s, t, i, o = "", n = 2, a = !
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
708
|
+
static async speedLoseAt(s, t, i, o = "", n = 2, a = !0, e = !1, d = {}) {
|
|
709
|
+
let c;
|
|
710
|
+
if (t.velocity && e && (s.speed = B.roundPrecision(t.velocity * 1852 / 3600, 6)), a) {
|
|
711
|
+
const u = await st.queryPointFactor(t.lng, t.lat, i.valueOf(), "wind,wave,current,watertemp", o, d), l = q.weatherFactor(s, u), M = q.currentFactor(s.bearing, u == null ? void 0 : u.current, n);
|
|
712
|
+
c = {
|
|
713
|
+
meteo: { ...u },
|
|
714
|
+
wxFactor: l,
|
|
715
|
+
cFactor: M,
|
|
716
|
+
speed: t.velocity && e ? t.velocity : Math.round((s.speed * 1.943844 + l + M) * 100) / 100,
|
|
717
|
+
eta: i.utc().format("YYYY-MM-DDTHH:mm[Z]"),
|
|
718
|
+
etd: i.utc().format("YYYY-MM-DDTHH:mm[Z]")
|
|
719
|
+
};
|
|
720
|
+
} else
|
|
721
|
+
c = {
|
|
722
|
+
wxFactor: 0,
|
|
723
|
+
cFactor: 0,
|
|
724
|
+
speed: t.velocity && e ? t.velocity : Math.round((s.speed * 1.943844 + 0 + 0) * 100) / 100,
|
|
725
|
+
eta: i.utc().format("YYYY-MM-DDTHH:mm[Z]"),
|
|
726
|
+
etd: i.utc().format("YYYY-MM-DDTHH:mm[Z]")
|
|
727
|
+
};
|
|
728
|
+
return delete t.meteo, delete t.wxFactor, delete t.cFactor, delete t.speed, delete t.etd, { ...c, ...t };
|
|
718
729
|
}
|
|
719
730
|
/**
|
|
720
731
|
* 基于步长计算失速样本
|
|
@@ -725,55 +736,56 @@ class E {
|
|
|
725
736
|
* @param distanceFromStart 与最开始起点的距离
|
|
726
737
|
* @param keypoints 剩下的航路点
|
|
727
738
|
* @param source 气象数据源: CMEMS / GFS
|
|
739
|
+
* @param useMeteo true 启用气象分析
|
|
728
740
|
* @param useRouteParam true 启用航线上设置的参数 { suspend: 停留时长(小时), velocity: 速度(kts)}
|
|
729
741
|
* @private
|
|
730
742
|
*/
|
|
731
|
-
static async speedLoseInHoursStep(s, t, i, o, n, a, e = "", d = !1,
|
|
743
|
+
static async speedLoseInHoursStep(s, t, i, o, n, a, e = "", d = !0, c = !1, u = {}) {
|
|
732
744
|
t.utc();
|
|
733
|
-
const
|
|
734
|
-
let
|
|
745
|
+
const l = [], M = [];
|
|
746
|
+
let m = 0, h = 0, v, I;
|
|
735
747
|
for (let Y = 0; Y < a.length - 1; Y++) {
|
|
736
|
-
let
|
|
737
|
-
|
|
738
|
-
const
|
|
739
|
-
if (s.bearing =
|
|
740
|
-
|
|
741
|
-
const
|
|
742
|
-
if (o -
|
|
743
|
-
o = o -
|
|
748
|
+
let p = a[Y];
|
|
749
|
+
p.distanceFromStart = n + h;
|
|
750
|
+
const r = a[Y + 1];
|
|
751
|
+
if (s.bearing = L.calculateBearing(p, r, !r.gcToPrevious), p.bearing = s.bearing, p.suspend && c) {
|
|
752
|
+
p.eta = p.eta || t.format("YYYY-MM-DDTHH:mm[Z]"), p.elapsed = p.elapsed ?? 0;
|
|
753
|
+
const g = p.suspend - p.elapsed;
|
|
754
|
+
if (o - m > g)
|
|
755
|
+
o = o - m - g, t.add(g, "hour"), p.elapsed = p.suspend;
|
|
744
756
|
else {
|
|
745
|
-
const
|
|
746
|
-
|
|
757
|
+
const j = o - m;
|
|
758
|
+
p.elapsed += j, t.add(j, "hour"), o = 0;
|
|
747
759
|
}
|
|
748
|
-
if (
|
|
749
|
-
return
|
|
760
|
+
if (H == null || H.info(`[%s] suspend ${p.elapsed} hours at %j, and remain ${o} hours need to go...`, u.requestId, p), o === 0)
|
|
761
|
+
return p.distanceFromPrevious = h, { etd: t, from: I || p, to: p, next: a.filter((j) => j), wps: l, days: M };
|
|
750
762
|
}
|
|
751
|
-
|
|
752
|
-
const
|
|
753
|
-
let
|
|
754
|
-
if (
|
|
755
|
-
if (
|
|
756
|
-
`[%s] go to %j from %j with ${
|
|
757
|
-
|
|
758
|
-
{ lat:
|
|
759
|
-
{ lat:
|
|
760
|
-
),
|
|
761
|
-
|
|
763
|
+
p = await q.speedLoseAt(s, p, t, e, 0, d, c, u), I = I || p, p.important && l.push(p), t.isSameOrAfter(i) && (M.push(p), i.add(24, "hour"));
|
|
764
|
+
const y = L.calculateDistance(p, r, !r.gcToPrevious);
|
|
765
|
+
let k = Math.ceil(y / I.speed * 1e4) / 1e4;
|
|
766
|
+
if (m + k < o) {
|
|
767
|
+
if (m += k, t.add(k, "hour"), delete a[Y], H == null || H.info(
|
|
768
|
+
`[%s] go to %j from %j with ${y}nm, and cost ${k} hours`,
|
|
769
|
+
u.requestId,
|
|
770
|
+
{ lat: r.lat, lng: r.lng },
|
|
771
|
+
{ lat: I.lat, lng: I.lng, etd: I.etd }
|
|
772
|
+
), h += y, a.filter((g) => g).length <= 1) {
|
|
773
|
+
v = r, v.eta = t.format("YYYY-MM-DDTHH:mm[Z]"), v.distanceFromPrevious = y, v.distanceFromStart = n + h, l.push(v), delete a[Y + 1];
|
|
762
774
|
break;
|
|
763
775
|
}
|
|
764
776
|
} else {
|
|
765
|
-
|
|
766
|
-
const
|
|
767
|
-
|
|
768
|
-
`[%s] go to %j from %j with ${
|
|
769
|
-
|
|
770
|
-
{ lat:
|
|
771
|
-
{ lat:
|
|
772
|
-
),
|
|
777
|
+
k = o - m, t.add(k, "hour");
|
|
778
|
+
const g = B.roundPrecision(I.speed * k, 4);
|
|
779
|
+
v = L.calculateCoordinate(p, s.bearing, g, "nauticalmiles", !r.gcToPrevious), v.eta = t.format("YYYY-MM-DDTHH:mm[Z]"), a[Y] = v, H == null || H.info(
|
|
780
|
+
`[%s] go to %j from %j with ${g}nm, and cost ${k} hours`,
|
|
781
|
+
u.requestId,
|
|
782
|
+
{ lat: v.lat, lng: v.lng },
|
|
783
|
+
{ lat: p.lat, lng: p.lng, etd: p.etd }
|
|
784
|
+
), h += g, v.distanceFromPrevious = h, v.distanceFromStart = n + h;
|
|
773
785
|
break;
|
|
774
786
|
}
|
|
775
787
|
}
|
|
776
|
-
return { etd: t, from:
|
|
788
|
+
return { etd: t, from: I, to: v, next: a.filter((Y) => Y), wps: l, days: M };
|
|
777
789
|
}
|
|
778
790
|
/**
|
|
779
791
|
* 洋流影响因子
|
|
@@ -794,16 +806,16 @@ class E {
|
|
|
794
806
|
* @param wwc 气象要素
|
|
795
807
|
*/
|
|
796
808
|
static weatherFactor(s, t) {
|
|
797
|
-
var
|
|
798
|
-
|
|
799
|
-
const i =
|
|
800
|
-
let a = Math.abs(s.bearing % 360 - (((
|
|
809
|
+
var l, M, m, h, v;
|
|
810
|
+
H == null || H.debug("calculate weather factor via: %j", { ...s, ...t });
|
|
811
|
+
const i = q.blockCoefficient(s.displacement, s.lbp, s.breadthMoulded, s.draught), o = q.froudeNumber(s.speed, s.lbp), n = q.amendFactor(i, o, s.loadCondition);
|
|
812
|
+
let a = Math.abs(s.bearing % 360 - (((l = t == null ? void 0 : t.wind) == null ? void 0 : l.degree) % 360 || 0));
|
|
801
813
|
a = a > 180 ? 360 - a : a;
|
|
802
|
-
const e =
|
|
803
|
-
let
|
|
804
|
-
|
|
805
|
-
const
|
|
806
|
-
return
|
|
814
|
+
const e = q.directionFactor(a, (M = t == null ? void 0 : t.wind) == null ? void 0 : M.scale), d = q.vesselTagFactor(s.displacement, s.loadCondition, s.tag, (m = t == null ? void 0 : t.wind) == null ? void 0 : m.scale);
|
|
815
|
+
let c = e * n * d / 100 * s.speed;
|
|
816
|
+
c = Math.round(c * 1.943844 * 1e4) / 1e4 * -1;
|
|
817
|
+
const u = q.waveHeightFactor(((v = (h = t == null ? void 0 : t.wave) == null ? void 0 : h.sig) == null ? void 0 : v.height) ?? 1);
|
|
818
|
+
return c = c * 0.24 + u * 0.76, H == null || H.debug("weather factor = %s", c), Math.round(c * 100) / 100;
|
|
807
819
|
}
|
|
808
820
|
/**
|
|
809
821
|
* 全程失速分析(走完航程)
|
|
@@ -814,16 +826,17 @@ class E {
|
|
|
814
826
|
* @param lane 航线 { points: { route, waypoints }}
|
|
815
827
|
* @param source 气象数据源,GFS or CMEMES, 默认CMEMS
|
|
816
828
|
* @param stepHrs 样本步长, 0表示动态计算(6 or 3 hrs)
|
|
829
|
+
* @param useMeteo true 启用气象分析
|
|
817
830
|
* @param useRouteParam
|
|
818
831
|
*/
|
|
819
|
-
static async analyseInstant(s, t, i, o, n, a = "", e = 0, d = !1,
|
|
820
|
-
var
|
|
821
|
-
const
|
|
822
|
-
s.lng =
|
|
823
|
-
const { route: M, waypoints:
|
|
824
|
-
if (((
|
|
832
|
+
static async analyseInstant(s, t, i, o, n, a = "", e = 0, d = !0, c = !1, u = {}) {
|
|
833
|
+
var _, G, U, J, Q;
|
|
834
|
+
const l = b().valueOf();
|
|
835
|
+
s.lng = B.convertToStdLng(s.lng);
|
|
836
|
+
const { route: M, waypoints: m } = n.points, h = L.calculateSubRoute(s, M);
|
|
837
|
+
if (((_ = h[0]) == null ? void 0 : _.length) <= 1)
|
|
825
838
|
return;
|
|
826
|
-
const { v0:
|
|
839
|
+
const { v0: v, label: I } = s.sog ? {
|
|
827
840
|
v0: s.sog,
|
|
828
841
|
label: "Other"
|
|
829
842
|
/* Instruct */
|
|
@@ -831,40 +844,51 @@ class E {
|
|
|
831
844
|
v0: o.speed,
|
|
832
845
|
label: "CP"
|
|
833
846
|
/* Cp */
|
|
834
|
-
}, Y =
|
|
847
|
+
}, Y = q.assembleProperties(i, o.loadCondition, v, 0), p = m.length ? L.calculateSubWaypoints(s, m) : [], r = {
|
|
835
848
|
from: { ...s },
|
|
836
|
-
route:
|
|
837
|
-
waypoints:
|
|
838
|
-
v0:
|
|
839
|
-
label:
|
|
840
|
-
},
|
|
849
|
+
route: h,
|
|
850
|
+
waypoints: p,
|
|
851
|
+
v0: v,
|
|
852
|
+
label: I
|
|
853
|
+
}, y = {
|
|
841
854
|
hours: [],
|
|
842
855
|
days: [],
|
|
843
856
|
wps: []
|
|
844
857
|
};
|
|
845
|
-
e || (
|
|
846
|
-
let
|
|
858
|
+
e || (L.calculateRouteDistance(h) / o.speed <= 72 ? e = 3 : e = 6);
|
|
859
|
+
let k = L.simplifyRouteToCoordinates(h, p, 0), g = 0, j = 0, W = 0, F = 0;
|
|
847
860
|
t = b(t).utc();
|
|
848
|
-
const
|
|
849
|
-
for (;
|
|
850
|
-
const
|
|
851
|
-
|
|
861
|
+
const O = t.clone();
|
|
862
|
+
for (; k.length > 0; ) {
|
|
863
|
+
const E = e - t.hour() % e, V = Math.ceil(t.clone().add(E, "h").set({ minute: 0, second: 0, millisecond: 0 }).diff(t, "h", !0) * 1e4) / 1e4, x = await q.speedLoseInHoursStep(
|
|
864
|
+
Y,
|
|
865
|
+
t,
|
|
866
|
+
O,
|
|
867
|
+
V,
|
|
868
|
+
g,
|
|
869
|
+
k,
|
|
870
|
+
a,
|
|
871
|
+
d,
|
|
872
|
+
c,
|
|
873
|
+
u
|
|
874
|
+
);
|
|
875
|
+
(G = x.from) != null && G.speed && (y.hours.push(x.from), y.wps.push(...x.wps), y.days.push(...x.days)), k = x == null ? void 0 : x.next, k.length || y.hours.push(x == null ? void 0 : x.to), g += ((U = x == null ? void 0 : x.to) == null ? void 0 : U.distanceFromPrevious) ?? 0;
|
|
852
876
|
}
|
|
853
|
-
const
|
|
854
|
-
for (let
|
|
855
|
-
const
|
|
856
|
-
|
|
877
|
+
const S = y.hours;
|
|
878
|
+
for (let E = 0; E < S.length - 1; E++) {
|
|
879
|
+
const V = b(S[E + 1].eta).diff(S[E].etd, "hour", !0) || 1;
|
|
880
|
+
j += S[E].wxFactor || 0 * V, W += S[E].cFactor || 0 * V, F += V;
|
|
857
881
|
}
|
|
858
|
-
(
|
|
859
|
-
if (
|
|
860
|
-
const
|
|
861
|
-
|
|
882
|
+
(J = y.wps) == null || J.forEach((E, V) => {
|
|
883
|
+
if (V) {
|
|
884
|
+
const x = y.wps[V - 1], $ = E.distanceFromStart - x.distanceFromStart, X = b(E.eta).diff(b(x.etd), "h", !0);
|
|
885
|
+
X < 1 ? E.avgSpd = x.speed : E.avgSpd = Math.round($ / X * 100) / 100;
|
|
862
886
|
}
|
|
863
|
-
}),
|
|
864
|
-
const
|
|
865
|
-
|
|
866
|
-
const
|
|
867
|
-
return
|
|
887
|
+
}), r.sample = y;
|
|
888
|
+
const D = y.hours.at(0), N = y.hours.at(-1);
|
|
889
|
+
r.distance = Math.round(N.distanceFromStart * 1e4) / 1e4, r.etd = b(D.eta).utc().format(), r.eta = b(N.eta).utc().format(), r.wxFactor = Math.round(j / F * 1e4) / 1e4, r.cFactor = Math.round(W / F * 1e4) / 1e4, r.avgSpeed = Math.round(N.distanceFromStart / F * 1e4) / 1e4, r.totalHrs = Math.round(F * 1e4) / 1e4, r.totalFoCons = Math.round((o == null ? void 0 : o.fo) / 24 * r.totalHrs * 1e3) / 1e3, r.totalDgoCons = Math.round((o == null ? void 0 : o.dgo) / 24 * r.totalHrs * 1e3) / 1e3;
|
|
890
|
+
const P = b().valueOf() - l, C = ((Q = y == null ? void 0 : y.hours) == null ? void 0 : Q.length) || 1;
|
|
891
|
+
return H == null || H.info("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms", u == null ? void 0 : u.requestId, P, C, Math.round(P / C * 1e3) / 1e3), r;
|
|
868
892
|
}
|
|
869
893
|
/**
|
|
870
894
|
* 分段失速分析(最多走hours 小时)
|
|
@@ -876,61 +900,76 @@ class E {
|
|
|
876
900
|
* @param route 航路[[[lng, lat]]]
|
|
877
901
|
* @param source 气象数据源,GFS or CMEMES, 默认CMEMS
|
|
878
902
|
* @param stepHrs
|
|
903
|
+
* @param useMeteo true 启用气象分析
|
|
904
|
+
* @param useRouteParam
|
|
879
905
|
*/
|
|
880
|
-
static async analyseInstantWithThreshed(s, t, i, o, n, a, e = "", d = 3,
|
|
881
|
-
var F,
|
|
882
|
-
s.lng =
|
|
883
|
-
const M =
|
|
884
|
-
if (((F =
|
|
906
|
+
static async analyseInstantWithThreshed(s, t, i, o, n, a, e = "", d = 3, c = !0, u = !1, l = {}) {
|
|
907
|
+
var F, O, S;
|
|
908
|
+
s.lng = B.convertToStdLng(s.lng);
|
|
909
|
+
const M = q.assembleProperties(o, n.loadCondition, n.speed, 0), m = L.calculateSubRoute(s, a);
|
|
910
|
+
if (((F = m[0]) == null ? void 0 : F.length) <= 1)
|
|
885
911
|
return;
|
|
886
|
-
let
|
|
887
|
-
|
|
888
|
-
let
|
|
889
|
-
const
|
|
912
|
+
let h = L.simplifyRouteToCoordinates(m, [], 0);
|
|
913
|
+
h.forEach((D) => D.important = !0);
|
|
914
|
+
let v = 0, I = 0, Y = 0, p = 0, r;
|
|
915
|
+
const y = {
|
|
890
916
|
hours: [],
|
|
891
917
|
wps: [],
|
|
892
918
|
days: []
|
|
893
919
|
};
|
|
894
|
-
for (t = b(t).utc();
|
|
895
|
-
const
|
|
896
|
-
let
|
|
897
|
-
if (
|
|
898
|
-
|
|
920
|
+
for (t = b(t).utc(); h.length > 0; ) {
|
|
921
|
+
const D = d - t.hour() % d;
|
|
922
|
+
let N = Math.ceil(t.clone().add(D, "h").set({ minute: 0, second: 0, millisecond: 0 }).diff(t, "h", !0) * 1e4) / 1e4;
|
|
923
|
+
if (N = t.clone().add(N, "h").isAfter(i) ? i.diff(t, "h", !0) * 1e4 / 1e4 : N, N)
|
|
924
|
+
r = await q.speedLoseInHoursStep(
|
|
925
|
+
M,
|
|
926
|
+
t,
|
|
927
|
+
i.clone(),
|
|
928
|
+
N,
|
|
929
|
+
v,
|
|
930
|
+
h,
|
|
931
|
+
e,
|
|
932
|
+
c,
|
|
933
|
+
u,
|
|
934
|
+
l
|
|
935
|
+
), (O = r.from) != null && O.speed && (y.hours.push(r.from), r != null && r.wps && y.wps.push(...r.wps), y.days.push(...r.days)), h = r == null ? void 0 : r.next, h.length || (y.hours.push(r == null ? void 0 : r.to), r != null && r.wps && y.wps.push(...r.wps), y.days.push(r == null ? void 0 : r.to)), v += ((S = r == null ? void 0 : r.to) == null ? void 0 : S.distanceFromPrevious) ?? 0;
|
|
899
936
|
else {
|
|
900
|
-
|
|
937
|
+
r && (y.hours.push(r.to), r != null && r.wps && y.wps.push(...r.wps), y.days.push(r.to));
|
|
901
938
|
break;
|
|
902
939
|
}
|
|
903
940
|
}
|
|
904
|
-
const
|
|
905
|
-
for (let
|
|
906
|
-
const
|
|
907
|
-
|
|
941
|
+
const k = y.hours;
|
|
942
|
+
for (let D = 0; D < k.length - 1; D++) {
|
|
943
|
+
const N = b(k[D + 1].eta).diff(k[D].etd, "hour", !0);
|
|
944
|
+
I += k[D].wxFactor * N, Y += k[D].cFactor * N, p += N;
|
|
908
945
|
}
|
|
909
|
-
const
|
|
946
|
+
const g = y.hours.at(0), j = y.hours.at(-1);
|
|
910
947
|
return {
|
|
911
|
-
sample:
|
|
912
|
-
distance: Math.round(((
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
948
|
+
sample: y,
|
|
949
|
+
distance: Math.round(((j == null ? void 0 : j.distanceFromStart) || 0) * 1e4) / 1e4,
|
|
950
|
+
// 注意,可能会在first节点Drift,所有采用eta做为初始出发时间
|
|
951
|
+
etd: b(g.eta).utc().format(),
|
|
952
|
+
eta: b(j == null ? void 0 : j.eta).utc().format(),
|
|
953
|
+
wxFactor: Math.round(I / p * 1e4) / 1e4,
|
|
954
|
+
cFactor: Math.round(Y / p * 1e4) / 1e4,
|
|
955
|
+
avgSpeed: Math.round(((j == null ? void 0 : j.distanceFromStart) || 0) / p * 1e4) / 1e4,
|
|
956
|
+
totalHrs: Math.round(p * 1e4) / 1e4,
|
|
957
|
+
to: j,
|
|
958
|
+
route: L.generateRouteAccordingToWaypoints(h)
|
|
920
959
|
};
|
|
921
960
|
}
|
|
922
961
|
}
|
|
923
962
|
export {
|
|
924
963
|
K as AISImpl,
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
964
|
+
ot as AlertHelper,
|
|
965
|
+
at as AlertLevel,
|
|
966
|
+
pt as HifleetImpl,
|
|
967
|
+
it as LoadCondition,
|
|
968
|
+
yt as MyShipImpl,
|
|
969
|
+
mt as MyVesselImpl,
|
|
970
|
+
Mt as ShipxyImpl,
|
|
971
|
+
q as SpeedHelper,
|
|
972
|
+
rt as SpeedLabel,
|
|
973
|
+
nt as VesselTag,
|
|
974
|
+
gt as alertHelper
|
|
936
975
|
};
|
package/dist/index.umd.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(k,T){typeof exports=="object"&&typeof module<"u"?T(exports,require("got"),require("@log4js-node/log4js-api"),require("moment"),require("@idm-plugin/geo"),require("@idm-plugin/meteo")):typeof define=="function"&&define.amd?define(["exports","got","@log4js-node/log4js-api","moment","@idm-plugin/geo","@idm-plugin/meteo"],T):(k=typeof globalThis<"u"?globalThis:k||self,T(k["idm-plugin-rabbitmq"]={},k.got,k["@log4js-node/log4js-api"],k.moment,k["@idm-plugin/geo"],k["@idm-plugin/meteo"]))})(this,function(k,T,W,g,E,st){"use strict";var dt=Object.defineProperty;var ut=(k,T,W)=>T in k?dt(k,T,{enumerable:!0,configurable:!0,writable:!0,value:W}):k[T]=W;var K=(k,T,W)=>(ut(k,typeof T!="symbol"?T+"":T,W),W);let m;try{m=W.getLogger("vessel")}catch{}finally{}class z{parseStatus(a){let t,i;switch(a){case 0:t="在航(主机推动)",i="The engine is in use";break;case 1:t="锚泊",i="Anchored";break;case 2:t="失控",i="Not operated";break;case 3:t="操纵受限",i="Limited airworthiness";break;case 4:t="吃水受限",i="Limited by ship's draft";break;case 5:t="靠泊",i="Mooring";break;case 6:t="搁浅",i="Stranded";break;case 7:t="捕捞作业",i="Engaged in fishing";break;case 8:t="靠帆船提供动力",i="Sailing";break;default:t="未定义",i="Undefined"}return{labelCn:t,labelEn:i}}}class at extends z{constructor(t,i){super();K(this,"clientId");K(this,"clientSecret");K(this,"token");this.clientId=t,this.clientSecret=i}async authToken(t={}){const i="https://svc.data.myvessel.cn/ada/oauth/token",n={searchParams:{client_id:this.clientId,client_secret:this.clientSecret,grant_type:"client_credentials"}},o=await T.post(i,n).json();m==null||m.info("[%s] fetch access token from: %s - %j",t.requestId,i,o),o.error||(this.token={accessToken:o.access_token,tokenType:o.token_type,expiresIn:o.expires_in,scope:o.scope,jti:o.jti,issuedAt:g().utc().format()})}async realTimePosition(t,i={}){var p,y,M;(!this.token||g().diff(g(this.token.issuedAt),"seconds")>((p=this.token)==null?void 0:p.expiresIn)-300)&&await this.authToken(i);const n="https://svc.data.myvessel.cn/sdc/v1/vessels/status/location/unit",o={headers:{Authorization:`${(y=this.token)==null?void 0:y.tokenType} ${(M=this.token)==null?void 0:M.accessToken}`},searchParams:{mmsi:t}};m==null||m.info("[%s] fetch realtime position from: %s - %j",i.requestId,n,o);const s=await T.get(n,o).json();if(s.code)return m==null||m.warn("[%s] fetch realtime position failed: %j",i.requestId,n,{message:s.message,status:s.status,code:s.code}),s;const e=s.data;for(const f in e)!isNaN(e[f])&&Number(e[f])!==1/0&&(e[f]=Number(e[f]));const d=g(`${e.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return{mmsi:e.mmsi,name:e.vesselName,imo:e.imo,callSign:e.callsign,lat:e.lat,lng:e.lon,length:e.length,width:e.width,draught:e.currDraught,sog:e.sog,cog:e.cog,hdg:e.hdg,rot:e.rot,eta:e.eta,destination:e.dest,positionTime:d.unix(),status:e.status,labelCn:e.statusNameCn,labelEn:e.statusNameEn,method:"position",vendor:"myVessel",utc:d.utc().format()}}async trajectory(t,i,n,o,s=!0,e={}){(!this.token||g().diff(g(this.token.issuedAt),"seconds")>this.token.expiresIn-300)&&await this.authToken(e);const d=await this.realTimePosition(t,e),r=g(i),p=g(n),y=[];for(;p.diff(r,"day",!0)>30;)await this.trajectoryIn30Day(t,r,r.clone().add(30,"day"),d,o,y,e),r.add(30,"day");return await this.trajectoryIn30Day(t,r,p,d,o,y,e),y}async trajectoryIn30Day(t,i,n,o,s,e,d={}){var l,v,Y,u,c;const r="https://svc.data.myvessel.cn/sdc/v1/vessels/status/track",p={headers:{Authorization:`${(l=this.token)==null?void 0:l.tokenType} ${(v=this.token)==null?void 0:v.accessToken}`},json:{mmsi:t,startTime:i.utcOffset(8).format("YYYY-MM-DD HH:mm:ss"),endTime:n.utcOffset(8).format("YYYY-MM-DD HH:mm:ss")}};m==null||m.info("[%s] fetch trajectory from: %s - %j",d.requestId,r,p);const y=await T.post(r,p).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 M=-1;const f=g(`${(u=(Y=y.data)==null?void 0:Y[0])==null?void 0:u.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return(c=y.data)==null||c.forEach(h=>{for(const D in h)!isNaN(h[D])&&Number(h[D])!==1/0&&(h[D]=Number(h[D]));const I=g(`${h.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00"),j=h.eta?g(`${h.eta} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00"):void 0,b=h.status,{labelCn:P,labelEn:x}=this.parseStatus(b),O={mmsi:h.mmsi,imo:o==null?void 0:o.imo,lat:h.lat,lng:h.lon,sog:h.sog,cog:h.cog,hdg:h.hdg,draught:h.draught,status:b,eta:j==null?void 0:j.unix(),destination:h.dest,positionTime:I.unix(),labelCn:P,labelEn:x,method:"trajectory",vendor:"myVessel",utc:I.utc().format()},S=Math.floor(I.diff(f,"minute",!0)/(s||1));S!==M&&(M=S,e.push(O))}),e}}class nt extends z{constructor(t){super();K(this,"token");this.token=t}async realTimePosition(t,i={}){const n="https://api.hifleet.com/position/position/get/token",o={searchParams:{mmsi:t,usertoken:this.token}},s=await T.post(n,o).json();m==null||m.info("[%s] fetch realtime position from: %s - %j",i.requestId,n,o);const e=s==null?void 0:s.list;if(!e)return m==null||m.warn("[%s] fetch realtime position failed: %j",i.requestId,n,s),s;for(const f in e)!isNaN(e[f])&&Number(e[f])!==1/0&&(e[f]=Number(e[f]));e.status=e.sp>3?0:1;const d=e.status,{labelCn:r,labelEn:p}=this.parseStatus(d),y=g(`${e.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return{mmsi:e.m,name:e.n,imo:e.imonumber,callSign:e.callsign,lat:Math.round(e.la/60*1e5)/1e5,lng:Math.round(e.lo/60*1e5)/1e5,length:e.l,width:e.w,draught:e.draught,sog:e.sp,cog:e.co,hdg:e.h,rot:isNaN(e.rot)?0:e.rot,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(e.eta)?g(`${e.eta} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00").unix():void 0,destination:e.destination,positionTime:y.unix(),utc:y.utc().format(),status:d,labelCn:r,labelEn:p,method:"position",vendor:"hifleet"}}async search(t,i={}){let n="https://www.hifleet.com/hifleetapi/searchVesselOL.do";const o={searchParams:{keyword:t},headers:{Referer:"https://www.hifleet.com",Origin:"https://www.hifleet.com",Host:"www.hifleet.com"}};let s=await T.post(n,o).json();m==null||m.info("[%s] fetch vessel props from: %s - %j",i.requestId,n,o),s instanceof Array&&(s=s[0]);for(const d in s)!isNaN(s[d])&&Number(s[d])!==1/0&&(s[d]=Number(s[d]));const e={mmsi:s.m,name:s.n,imo:s.i,callSign:s.c,length:s.l,breadth:s.b,draught:s.dr};return n="https://www.hifleet.com/hifleetapi/sameShipSearch.do",s=await T.post(n,o).json(),m==null||m.info("[%s] fetch vessel dead weight from: %s - %j",i.requestId,n,o),s instanceof Array&&(s=s[0]),s&&(e.deadweight=Number(s.dwt)),e}async trajectory(t,i,n,o,s=!0,e={}){var h,I,j;const d=await this.realTimePosition(t,e);let r=g(i);const p=g(n),y=g();if(s){let b=p.diff(r,"d",!0);b<0?r=p.clone().subtract(40,"d"):b<30?r.subtract(10,"d"):b<60?r.subtract(5,"d"):r=p.clone().subtract(80,"d"),b=y.diff(p,"d",!0),p.add(b>10?240:b*24,"h")}const M={searchParams:{endtime:p.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}},f="https://api.hifleet.com/position/trajectory/nocompressed/withstatic/token",l=await T.get(f,M).json();m==null||m.info("[%s] fetch trajectory from: %s - %j",e.requestId,f,M);let v;l&&(v=((I=(h=l.ships)==null?void 0:h.offors)==null?void 0:I.ship)||[],v.length||m==null||m.warn("[%s] fetch trajectory failed: %j",e.requestId,l));const Y=[];let u=-1;const c=g(`${(j=v==null?void 0:v[0])==null?void 0:j.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");for(const b of v){for(const _ in b)!isNaN(b[_])&&Number(b[_])!==1/0&&(b[_]=Number(b[_]));const P=g(`${b.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");b.status=b.sp>4?0:1;const{labelEn:x,labelCn:O}=this.parseStatus(b.status),S={mmsi:b.m,name:b.n,imo:d==null?void 0:d.imo,lat:b.la,lng:b.lo,draught:b.draught,sog:b.sp,cog:b.co,hdg:b.hdg,positionTime:P.unix(),utc:P.utc().format(),status:b.status,labelCn:O,labelEn:x,method:"trajectory",vendor:"hifleet"},D=Math.floor(P.diff(c,"minute",!0)/(o||1));D!==u&&(u=D,Y.push(S))}return Y}}class ot extends z{constructor(t){super();K(this,"token");this.token=t}async realTimePosition(t,i={}){const n={searchParams:{id:t,k:this.token,enc:1}},o="https://api.shipxy.com/apicall/GetSingleShip",s=await T.get(o,n).json();if(m==null||m.info("[%s] fetch realtime position from: %s - %j",i.requestId,o,n),(s==null?void 0:s.status)!==0)return s;const e=s.data[0];for(const M in e)!isNaN(e[M])&&Number(e[M])!==1/0&&(e[M]=Number(e[M]));const{labelCn:d,labelEn:r}=await this.parseStatus(e.navistat),p=g.unix(e.lasttime);return{mmsi:e.ShipID,name:e.name,imo:e.imo,callSign:e.callsign,lat:Math.round(e.lat/1e6*1e5)/1e5,lng:Math.round(e.lon/1e6*1e5)/1e5,length:Math.round(e.length/10*100)/100,width:Math.round(e.width/10*100)/100,draught:Math.round(e.draught/1e3*100)/100,sog:Math.round(e.sog*3600/1e3/1852*100)/100,cog:Math.round(e.cog/100*100)/100,hdg:Math.round(e.hdg/100*100)/100,rot:Math.round(e.rot/100*100)/100,positionTime:e.lasttime,utc:p.utc().format(),status:e.navistat,labelEn:r,labelCn:d,method:"position",vendor:"shipxy"}}async trajectory(t,i,n,o,s=!0,e={}){var c;const d=await this.realTimePosition(t,e),r=g(i),p=g(n),y="https://api.shipxy.com/apicall/GetShipTrack",M={searchParams:{id:t,k:this.token,enc:1,cut:0,btm:r.unix(),etm:p.unix()}},f=await T.get(y,M).json();if(m==null||m.info("[%s] fetch trajectory from: %s - %j",e.requestId,y,M),(f==null?void 0:f.status)!==0)return f;const l=f==null?void 0:f.points,v=[],Y=g.unix((c=l[0])==null?void 0:c.utc);let u=-1;for(const h of l){const I=g.unix(h.utc),j={imo:d==null?void 0:d.imo,mmsi:t,sog:Math.round(h.sog*3600/1e3/1852*100)/100,cog:Math.round(h.cog/100*100)/100,lat:Math.round(h.lat/1e6*1e5)/1e5,lng:Math.round(h.lon/1e6*1e5)/1e5,positionTime:I.unix(),utc:I.utc().format(),method:"trajectory",vendor:"shipxy"},b=Math.floor(I.diff(Y,"minute",!0)/(o||1));b!==u&&(u=b,v.push(j))}return v}}class it extends z{constructor(t){super();K(this,"token");this.token=t}async getShipId(t,i={}){const n={headers:{appKey:this.token},json:{mmsiList:t}},o="https://api3.myships.com/sp/ships/getShipIdByMMSI",s=await T.post(o,n).json();return m==null||m.info("[%s] fetch ship id from: %s - %j",i.requestId,o,n),s.code!=="0"?s:s.data[0].shipId}async getShipInfo(t,i={}){const n={headers:{appKey:this.token},json:{shipId:t}},o="https://api3.myships.com/sp/ships/aissta",s=await T.post(o,n).json();if(m==null||m.info("[%s] fetch ship info from: %s - %j",i.requestId,o,n),s.code!=="0")return s;const e=s.data;let d=e.imo;return t==="407170"&&(d="9198379",m==null||m.warn("[%s] ship(%s) imo error: %s, should be %s",i.requestId,t,e.imo,d)),{mmsi:e.mmsi,name:e.shipnameEn,imo:d,callSign:e.callSign,length:e.length,width:e.breadth,draught:(e.draught||100)/10}}async realTimePosition(t,i={}){const n=await this.getShipId(t,i),o=await this.getShipInfo(n,i),s={headers:{appKey:this.token},json:{shipId:n}},e="https://api3.myships.com/sp/ships/position/latest",d=await T.post(e,s).json();m==null||m.info("[%s] fetch realtime position from: %s - %j",i.requestId,e,s);const r=d.data[0];for(const l in r)!isNaN(r[l])&&Number(r[l])!==1/0&&(r[l]=Number(r[l]));const{labelCn:p,labelEn:y}=await this.parseStatus(r.aisNavStatus),M=g.unix(r.posTime);return{...o,mmsi:t,lat:Math.round(r.lat/1e4/60*1e5)/1e5,lng:Math.round(r.lon/1e4/60*1e5)/1e5,sog:Math.round(r.sog/10*100)/100,cog:Math.round(r.cog/10*100)/100,hdg:Math.round(r.heading*100)/100,rot:Math.round(r.rot*100)/100,positionTime:r.posTime,utc:M.utc().format(),status:r.aisNavStatus,labelEn:y,labelCn:p,method:"position",vendor:"myship"}}async trajectory(t,i,n,o,s=!0,e={}){const d=g(i),r=g(n),p=await this.getShipId(t),y=await this.getShipInfo(p),M=[];for(;r.diff(d,"day",!0)>30;)await this.trajectoryIn30Day(p,d.unix(),d.add(30,"day").unix(),y,t,o,M);return await this.trajectoryIn30Day(p,d.unix(),r.unix(),y,t,o,M),M}async trajectoryIn30Day(t,i,n,o,s,e,d,r={}){var Y;const p={headers:{appKey:this.token},json:{shipId:t,startTime:i,endTime:n}},y="https://api3.myships.com/sp/ships/position/history",M=await T.post(y,p).json();if(m==null||m.info("[%s] fetch trajectory from: %s - %j",r.requestId,y,p),M.code!=="0")return m==null||m.warn("[%s] invoke myship trajectory failed: %j",r.requestId,M),M;const f=M.data;for(const u in f)!isNaN(f[u])&&Number(f[u])!==1/0&&(f[u]=Number(f[u]));const l=g.unix((Y=f[0])==null?void 0:Y.posTime);let v=-1;for(const u of f){const c=g.unix(u.posTime),h={imo:o==null?void 0:o.imo,mmsi:s,lat:Math.round(u.lat/1e4/60*1e5)/1e5,lng:Math.round(u.lon/1e4/60*1e5)/1e5,sog:Math.round(u.sog/10*100)/100,cog:Math.round(u.cog/10*100)/100,hdg:Math.round(u.heading*100)/100,rot:Math.round(u.rot*100)/100,positionTime:c.unix(),utc:c.utc().format(),method:"trajectory",vendor:"myship"},I=Math.floor(c.diff(l,"minute",!0)/(e||1));I!==v&&(v=I,d.push(h))}return d}}let C;try{C=W.getLogger("vessel")}catch{}finally{}var G=(w=>(w.NOTICE="NOTICE",w.WARN="WARN",w.HEAVY="HEAVY",w.SEVERE="SEVERE",w.ERROR="ERROR",w.FATAL="FATAL",w))(G||{});class U{parsePrinciple(a,t={}){var e,d,r;C==null||C.info("[%s] parse rule: %s",t.requestId,a);const i=new RegExp("(?<=\\[)(.+)(?=])","g"),n=a.match(i)?(e=a.match(i))==null?void 0:e[0]:void 0,o=n==null?void 0:n.split(";");if(!o)return;const s={};for(let p=0;p<(o==null?void 0:o.length);p++){const y=(r=(d=o[p].match(i))==null?void 0:d[0])==null?void 0:r.split("],");if(p===0&&!y)s.scope=o[0];else if(y)for(let M=0,f=y.length;M<f;M++){const l=this.parseRule(y[M]);l&&(s[l.level]?l.key?s[l.level][l==null?void 0:l.key]=l:s[l.level]=l:l.key?s[l.level]={[l==null?void 0:l.key]:l}:s[l.level]=l)}}return s}parseRule(a,t={}){var s;C==null||C.info("[%s] parse rule: %s",t.requestId,a),a=a.startsWith("[")?a:`[${a}`,a=a.endsWith("]")?a:`${a}]`;const i=new RegExp("(?<=\\[)(.+?)(?=])","g"),n=(s=a==null?void 0:a.match(i))==null?void 0:s[0],o=n==null?void 0:n.split(",");if(o)return{operator:o[0],number:Number.isNaN(Number(o[1]))?o[1]:Number(o[1]),level:o[2],time:Number(o[3]),key:o[4]}}checkWeather(a,t,i={}){var l,v,Y,u,c,h,I,j,b,P,x,O,S,D,_;let n=0,o=0,s=0,e=0;const d=Math.round(((v=(l=t==null?void 0:t.SEVERE)==null?void 0:l.sigWave)==null?void 0:v.number)*1.6*100)/100,r=(u=(Y=t==null?void 0:t.SEVERE)==null?void 0:Y.sigWave)==null?void 0:u.number,p=(h=(c=t==null?void 0:t.HEAVY)==null?void 0:c.sigWave)==null?void 0:h.number,y=Math.round((((j=(I=t==null?void 0:t.SEVERE)==null?void 0:I.wind)==null?void 0:j.number)+2)*100)/100,M=(P=(b=t==null?void 0:t.SEVERE)==null?void 0:b.wind)==null?void 0:P.number,f=(O=(x=t==null?void 0:t.HEAVY)==null?void 0:x.wind)==null?void 0:O.number;for(let B=0;B<(a==null?void 0:a.length);B++){const H=a[B],A=(D=(S=H==null?void 0:H.meteo)==null?void 0:S.wave)==null?void 0:D.sig,R=(_=H==null?void 0:H.meteo)==null?void 0:_.wind,Z=B?g(H.eta).diff(g(a[B-1].eta),"hour",!0):0;e=Z>e?Z:e,C==null||C.info("[%s] check sig.wave: %j",i.requestId,{...A,dgThd4Wv:d,svThd4Wv:r,hvThd4Wv:p}),(A==null?void 0:A.height)>=d?H.isDangerous=!0:(A==null?void 0:A.height)>=r?H.isSevere=!0:(A==null?void 0:A.height)>=p&&(H.isHeavy=!0),C==null||C.info("[%s] check wind: %j",i.requestId,{...R,dgThd4Wd:y,svThd4Wd:M,hvThd4Wd:f}),(R==null?void 0:R.scale)>=y?(H.isDangerous=!0,delete H.isSevere,delete H.isHeavy):(R==null?void 0:R.scale)>M?(H.isDangerous||(H.isSevere=!0),delete H.isHeavy):(R==null?void 0:R.scale)===f&&!H.isDangerous&&!H.isSevere&&(H.isHeavy=!0),n+=H.isDangerous?Z:0,o+=H.isSevere?Z:0,s+=H.isHeavy?Z:0}return n=Math.round(n*100)/100,o=Math.round(o*100)/100,s=Math.round(s*100)/100,e=Math.round(e),{sample:a,dangerous:n,severe:o,heavy:s,step:e<3?3:e,wind:{dgThd4Wd:y,svThd4Wd:M,hvThd4Wd:f},sig:{dgThd4Wv:d,svThd4Wv:r,hvThd4Wv:p}}}}const rt=new U;let N;try{N=W.getLogger("vessel")}catch{}finally{}var J=(w=>(w.common="common",w.container="container",w))(J||{}),Q=(w=>(w.Ballast="Ballast",w.Laden="Laden",w))(Q||{}),X=(w=>(w.Cp="CP",w.Perf="Basis",w.Instruct="Other",w))(X||{});class q{static blockCoefficient(a,t,i,n){let o=Math.round(a/(t*i*n)*100)/100;o=o<.55?.55:o>.85?.85:o;const s=[.55,.6,.65,.7,.75,.8,.85],e=s.map(d=>Math.abs(d-o));return s[e.indexOf(Math.min(...e))]}static froudeNumber(a,t,i=9.8){let n=Math.round(Math.sqrt(a*a/(i*t))*100)/100;return n=n<.05?.05:n>.3?.3:n,n}static amendFactor(a,t,i){const 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.4,-10.6,-9.5],.8:[2.6,-13.1,-15.1],.85:[3.1,-18.7,28]};let s={.55:[1.7,-1.4,-7.4],.6:[2.2,-2.5,-9.7],.65:[2.6,-3.7,-11.6],.7:[3.1,-5.3,-12.4],.75:[2.6,-12.5,-13.5],.8:[3,-16.3,-21.6],.85:[3.4,-20.9,31.8]}[a];return i==="Laden"&&(s=n[a]),s[0]+s[1]*t+s[2]*Math.pow(t,2)}static directionFactor(a,t=0){let i;return a>30&&a<=60?i=(1.7-.03*Math.pow(t-4,2))/2:a>60&&a<=150?i=(.9-.06*Math.pow(t-6,2))/2:i=(.4-.03*Math.pow(t-8,2))/2,Math.round(i*1e5)/1e5}static vesselTagFactor(a,t,i,n=0){n=n>5?n-.9*(n-5):n;let o;return i==="container"?o=.7*n+Math.pow(n,6.5)/(22*Math.pow(a,2/3)):t==="Ballast"?o=.7*n+Math.pow(n,6.5)/(2.7*Math.pow(a,2/3)):o=.5*n+Math.pow(n,6.5)/(2.7*Math.pow(a,2/3)),o}static waveHeightFactor(a){return a=a<1.25?1.25:a,a=a>6?a-.9*(a-6):a,Math.round((-.144*Math.pow(a,2)+.178*a)*1e4)/1e4}static assembleProperties(a,t,i,n){var p,y;const o=a.lbp??a.length??a.lengthOverall??198.9642,s=a.draught??8,e=a.breadthMoulded??a.breadth??a.breadthExtreme??32.4572,d=a.deadweight??67035.7773;return{tag:((y=(p=a==null?void 0:a.type)==null?void 0:p.toLowerCase())==null?void 0:y.indexOf("container"))>-1?"container":"common",lbp:o,loadCondition:t,draught:s,breadthMoulded:e,displacement:Math.round((d/1.025+s*e*o*.7)*1e4)/1e4,speed:Math.round((i??14.1382)*1852/3600*1e4)/1e4,bearing:n||90}}static async speedLoseAt(a,t,i,n="",o=2,s=!1,e={}){t.velocity&&!t.noFactor&&s&&(a.speed=E.LngLatHelper.roundPrecision(t.velocity*1852/3600,6));const d=await st.MeteoHelper.queryPointFactor(t.lng,t.lat,i.valueOf(),"wind,wave,current,watertemp",n,e),r=q.weatherFactor(a,d),p=q.currentFactor(a.bearing,d==null?void 0:d.current,o),y={meteo:{...d},wxFactor:r,cFactor:p,speed:t.velocity&&s?t.velocity:Math.round((a.speed*1.943844+r+p)*100)/100,eta:i.utc().format("YYYY-MM-DDTHH:mm[Z]"),etd:i.utc().format("YYYY-MM-DDTHH:mm[Z]")};return delete t.meteo,delete t.wxFactor,delete t.cFactor,delete t.speed,delete t.etd,{...y,...t}}static async speedLoseInHoursStep(a,t,i,n,o,s,e="",d=!1,r={}){t.utc();const p=[],y=[];let M=0,f=0,l,v;for(let Y=0;Y<s.length-1;Y++){let u=s[Y];u.distanceFromStart=o+f;const c=s[Y+1];if(a.bearing=E.LaneHelper.calculateBearing(u,c,!c.gcToPrevious),u.bearing=a.bearing,u.suspend&&d){u.eta=u.eta||t.format("YYYY-MM-DDTHH:mm[Z]"),u.elapsed=u.elapsed??0;const j=u.suspend-u.elapsed;if(n-M>j)n=n-M-j,t.add(j,"hour"),u.elapsed=u.suspend;else{const b=n-M;u.elapsed+=b,t.add(b,"hour"),n=0}if(N==null||N.info(`[%s] suspend ${u.elapsed} hours at %j, and remain ${n} hours need to go...`,r.requestId,u),n===0)return u.distanceFromPrevious=f,{etd:t,from:v||u,to:u,next:s.filter(b=>b),wps:p,days:y}}u=await q.speedLoseAt(a,u,t,e,0,d,r),v=v||u,u.important&&p.push(u),t.isSameOrAfter(i)&&(y.push(u),i.add(24,"hour"));const h=E.LaneHelper.calculateDistance(u,c,!c.gcToPrevious);let I=Math.ceil(h/v.speed*1e4)/1e4;if(M+I<n){if(M+=I,t.add(I,"hour"),delete s[Y],N==null||N.info(`[%s] go to %j from %j with ${h}nm, and cost ${I} hours`,r.requestId,{lat:c.lat,lng:c.lng},{lat:v.lat,lng:v.lng,etd:v.etd}),f+=h,s.filter(j=>j).length<=1){l=c,l.eta=t.format("YYYY-MM-DDTHH:mm[Z]"),l.distanceFromPrevious=h,l.distanceFromStart=o+f,p.push(l),delete s[Y+1];break}}else{I=n-M,t.add(I,"hour");const j=E.LngLatHelper.roundPrecision(v.speed*I,4);l=E.LaneHelper.calculateCoordinate(u,a.bearing,j,"nauticalmiles",!c.gcToPrevious),l.eta=t.format("YYYY-MM-DDTHH:mm[Z]"),s[Y]=l,N==null||N.info(`[%s] go to %j from %j with ${j}nm, and cost ${I} hours`,r.requestId,{lat:l.lat,lng:l.lng},{lat:u.lat,lng:u.lng,etd:u.etd}),f+=j,l.distanceFromPrevious=f,l.distanceFromStart=o+f;break}}return{etd:t,from:v,to:l,next:s.filter(Y=>Y),wps:p,days:y}}static currentFactor(a,t,i=0){const n=(a-(t==null?void 0:t.degree)||0)/180*Math.PI;if(Math.abs(n)===Math.PI/2)return 0;let o=((t==null?void 0:t.kts)||0)*Math.cos(n);return i&2?o=Math.ceil(o*100)/100:i&1?o=Math.floor(o*100)/100:o=Math.round(o*100)/100,Math.abs(o)>5?0:o}static weatherFactor(a,t){var y,M,f,l,v;N==null||N.debug("calculate weather factor via: %j",{...a,...t});const i=q.blockCoefficient(a.displacement,a.lbp,a.breadthMoulded,a.draught),n=q.froudeNumber(a.speed,a.lbp),o=q.amendFactor(i,n,a.loadCondition);let s=Math.abs(a.bearing%360-(((y=t==null?void 0:t.wind)==null?void 0:y.degree)%360||0));s=s>180?360-s:s;const e=q.directionFactor(s,(M=t==null?void 0:t.wind)==null?void 0:M.scale),d=q.vesselTagFactor(a.displacement,a.loadCondition,a.tag,(f=t==null?void 0:t.wind)==null?void 0:f.scale);let r=e*o*d/100*a.speed;r=Math.round(r*1.943844*1e4)/1e4*-1;const p=q.waveHeightFactor(((v=(l=t==null?void 0:t.wave)==null?void 0:l.sig)==null?void 0:v.height)??1);return r=r*.24+p*.76,N==null||N.debug("weather factor = %s",r),Math.round(r*100)/100}static async analyseInstant(a,t,i,n,o,s="",e=0,d=!1,r={}){var A,R,Z,$,tt;const p=g().valueOf();a.lng=E.LngLatHelper.convertToStdLng(a.lng);const{route:y,waypoints:M}=o.points,f=E.LaneHelper.calculateSubRoute(a,y);if(((A=f[0])==null?void 0:A.length)<=1)return;const{v0:l,label:v}=a.sog?{v0:a.sog,label:"Other"}:{v0:n.speed,label:"CP"},Y=q.assembleProperties(i,n.loadCondition,l,0),u=M.length?E.LaneHelper.calculateSubWaypoints(a,M):[],c={from:{...a},route:f,waypoints:u,v0:l,label:v},h={hours:[],days:[],wps:[]};e||(E.LaneHelper.calculateRouteDistance(f)/n.speed<=72?e=3:e=6);let I=E.LaneHelper.simplifyRouteToCoordinates(f,u,0),j=0,b=0,P=0,x=0;t=g(t).utc();const O=t.clone();for(;I.length>0;){const L=e-t.hour()%e,V=Math.ceil(t.clone().add(L,"h").set({minute:0,second:0,millisecond:0}).diff(t,"h",!0)*1e4)/1e4,F=await q.speedLoseInHoursStep(Y,t,O,V,j,I,s,d,r);(R=F.from)!=null&&R.speed&&(h.hours.push(F.from),h.wps.push(...F.wps),h.days.push(...F.days)),I=F==null?void 0:F.next,I.length||h.hours.push(F==null?void 0:F.to),j+=((Z=F==null?void 0:F.to)==null?void 0:Z.distanceFromPrevious)??0}const S=h.hours;for(let L=0;L<S.length-1;L++){const V=g(S[L+1].eta).diff(S[L].etd,"hour",!0)||1;b+=S[L].wxFactor*V,P+=S[L].cFactor*V,x+=V}($=h.wps)==null||$.forEach((L,V)=>{if(V){const F=h.wps[V-1],ct=L.distanceFromStart-F.distanceFromStart,et=g(L.eta).diff(g(F.etd),"h",!0);et<1?L.avgSpd=F.speed:L.avgSpd=Math.round(ct/et*100)/100}}),c.sample=h;const D=h.hours.at(-1);c.distance=Math.round(D.distanceFromStart*1e4)/1e4,c.eta=g(D.eta).toDate(),c.wxFactor=Math.round(b/x*1e4)/1e4,c.cFactor=Math.round(P/x*1e4)/1e4,c.avgSpeed=Math.round(D.distanceFromStart/x*1e4)/1e4,c.totalHrs=Math.round(x*1e4)/1e4,c.totalFoCons=Math.round((n==null?void 0:n.fo)/24*c.totalHrs*1e3)/1e3,c.totalDgoCons=Math.round((n==null?void 0:n.dgo)/24*c.totalHrs*1e3)/1e3;const B=g().valueOf()-p,H=((tt=h==null?void 0:h.hours)==null?void 0:tt.length)||1;return N==null||N.info("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms",r==null?void 0:r.requestId,B,H,Math.round(B/H*1e3)/1e3),c}static async analyseInstantWithThreshed(a,t,i,n,o,s,e="",d=3,r=!1,p={}){var P,x,O;a.lng=E.LngLatHelper.convertToStdLng(a.lng);const y=q.assembleProperties(n,o.loadCondition,o.speed,0),M=E.LaneHelper.calculateSubRoute(a,s);if(((P=M[0])==null?void 0:P.length)<=1)return;let f=E.LaneHelper.simplifyRouteToCoordinates(M,[],0);f.forEach(S=>S.important=!0);let l=0,v=0,Y=0,u=0,c;const h={hours:[],wps:[],days:[]};for(t=g(t).utc();f.length>0;){const S=d-t.hour()%d;let D=Math.ceil(t.clone().add(S,"h").set({minute:0,second:0,millisecond:0}).diff(t,"h",!0)*1e4)/1e4;if(D=t.clone().add(D,"h").isAfter(i)?i.diff(t,"h",!0)*1e4/1e4:D,D)c=await q.speedLoseInHoursStep(y,t,i.clone(),D,l,f,e,r,p),(x=c.from)!=null&&x.speed&&(h.hours.push(c.from),c!=null&&c.wps&&h.wps.push(...c.wps),h.days.push(...c.days)),f=c==null?void 0:c.next,f.length||(h.hours.push(c==null?void 0:c.to),c!=null&&c.wps&&h.wps.push(...c.wps),h.days.push(c==null?void 0:c.to)),l+=((O=c==null?void 0:c.to)==null?void 0:O.distanceFromPrevious)??0;else{c&&(h.hours.push(c.to),c!=null&&c.wps&&h.wps.push(...c.wps),h.days.push(c.to));break}}const I=h.hours;for(let S=0;S<I.length-1;S++){const D=g(I[S+1].eta).diff(I[S].etd,"hour",!0);v+=I[S].wxFactor*D,Y+=I[S].cFactor*D,u+=D}const j=h.hours.at(-1);return{sample:h,distance:Math.round(((j==null?void 0:j.distanceFromStart)||0)*1e4)/1e4,eta:g(j==null?void 0:j.eta).utc().format(),wxFactor:Math.round(v/u*1e4)/1e4,cFactor:Math.round(Y/u*1e4)/1e4,avgSpeed:Math.round(((j==null?void 0:j.distanceFromStart)||0)/u*1e4)/1e4,totalHrs:Math.round(u*1e4)/1e4,to:j,route:E.LaneHelper.generateRouteAccordingToWaypoints(f)}}}k.AISImpl=z,k.AlertHelper=U,k.AlertLevel=G,k.HifleetImpl=nt,k.LoadCondition=Q,k.MyShipImpl=it,k.MyVesselImpl=at,k.ShipxyImpl=ot,k.SpeedHelper=q,k.SpeedLabel=X,k.VesselTag=J,k.alertHelper=rt,Object.defineProperty(k,Symbol.toStringTag,{value:"Module"})});
|
|
1
|
+
(function(j,T){typeof exports=="object"&&typeof module<"u"?T(exports,require("got"),require("@log4js-node/log4js-api"),require("moment"),require("@idm-plugin/geo"),require("@idm-plugin/meteo")):typeof define=="function"&&define.amd?define(["exports","got","@log4js-node/log4js-api","moment","@idm-plugin/geo","@idm-plugin/meteo"],T):(j=typeof globalThis<"u"?globalThis:j||self,T(j["idm-plugin-rabbitmq"]={},j.got,j["@log4js-node/log4js-api"],j.moment,j["@idm-plugin/geo"],j["@idm-plugin/meteo"]))})(this,function(j,T,_,v,P,nt){"use strict";var ht=Object.defineProperty;var lt=(j,T,_)=>T in j?ht(j,T,{enumerable:!0,configurable:!0,writable:!0,value:_}):j[T]=_;var K=(j,T,_)=>(lt(j,typeof T!="symbol"?T+"":T,_),_);let l;try{l=_.getLogger("vessel")}catch{}finally{}class z{parseStatus(a){let t,i;switch(a){case 0:t="在航(主机推动)",i="The engine is in use";break;case 1:t="锚泊",i="Anchored";break;case 2:t="失控",i="Not operated";break;case 3:t="操纵受限",i="Limited airworthiness";break;case 4:t="吃水受限",i="Limited by ship's draft";break;case 5:t="靠泊",i="Mooring";break;case 6:t="搁浅",i="Stranded";break;case 7:t="捕捞作业",i="Engaged in fishing";break;case 8:t="靠帆船提供动力",i="Sailing";break;default:t="未定义",i="Undefined"}return{labelCn:t,labelEn:i}}}class ot extends z{constructor(t,i){super();K(this,"clientId");K(this,"clientSecret");K(this,"token");this.clientId=t,this.clientSecret=i}async authToken(t={}){const i="https://svc.data.myvessel.cn/ada/oauth/token",n={searchParams:{client_id:this.clientId,client_secret:this.clientSecret,grant_type:"client_credentials"}},o=await T.post(i,n).json();l==null||l.info("[%s] fetch access token from: %s - %j",t.requestId,i,o),o.error||(this.token={accessToken:o.access_token,tokenType:o.token_type,expiresIn:o.expires_in,scope:o.scope,jti:o.jti,issuedAt:v().utc().format()})}async realTimePosition(t,i={}){var u,f,y;(!this.token||v().diff(v(this.token.issuedAt),"seconds")>((u=this.token)==null?void 0:u.expiresIn)-300)&&await this.authToken(i);const n="https://svc.data.myvessel.cn/sdc/v1/vessels/status/location/unit",o={headers:{Authorization:`${(f=this.token)==null?void 0:f.tokenType} ${(y=this.token)==null?void 0:y.accessToken}`},searchParams:{mmsi:t}};l==null||l.info("[%s] fetch realtime position from: %s - %j",i.requestId,n,o);const s=await T.get(n,o).json();if(s.code)return l==null||l.warn("[%s] fetch realtime position failed: %j",i.requestId,n,{message:s.message,status:s.status,code:s.code}),s;const e=s.data;for(const m in e)!isNaN(e[m])&&Number(e[m])!==1/0&&(e[m]=Number(e[m]));const d=v(`${e.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return{mmsi:e.mmsi,name:e.vesselName,imo:e.imo,callSign:e.callsign,lat:e.lat,lng:e.lon,length:e.length,width:e.width,draught:e.currDraught,sog:e.sog,cog:e.cog,hdg:e.hdg,rot:e.rot,eta:e.eta,destination:e.dest,positionTime:d.unix(),status:e.status,labelCn:e.statusNameCn,labelEn:e.statusNameEn,method:"position",vendor:"myVessel",utc:d.utc().format()}}async trajectory(t,i,n,o,s=!0,e={}){(!this.token||v().diff(v(this.token.issuedAt),"seconds")>this.token.expiresIn-300)&&await this.authToken(e);const d=await this.realTimePosition(t,e),c=v(i),u=v(n),f=[];for(;u.diff(c,"day",!0)>30;)await this.trajectoryIn30Day(t,c,c.clone().add(30,"day"),d,o,f,e),c.add(30,"day");return await this.trajectoryIn30Day(t,c,u,d,o,f,e),f}async trajectoryIn30Day(t,i,n,o,s,e,d={}){var h,g,k,Y,p;const c="https://svc.data.myvessel.cn/sdc/v1/vessels/status/track",u={headers:{Authorization:`${(h=this.token)==null?void 0:h.tokenType} ${(g=this.token)==null?void 0:g.accessToken}`},json:{mmsi:t,startTime:i.utcOffset(8).format("YYYY-MM-DD HH:mm:ss"),endTime:n.utcOffset(8).format("YYYY-MM-DD HH:mm:ss")}};l==null||l.info("[%s] fetch trajectory from: %s - %j",d.requestId,c,u);const f=await T.post(c,u).json();if(f.code)return l==null||l.warn("[%s] fetch trajectory failed: %j",d.requestId,c,{message:f.message,status:f.status,code:f.code}),f;let y=-1;const m=v(`${(Y=(k=f.data)==null?void 0:k[0])==null?void 0:Y.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return(p=f.data)==null||p.forEach(r=>{for(const F in r)!isNaN(r[F])&&Number(r[F])!==1/0&&(r[F]=Number(r[F]));const M=v(`${r.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00"),I=r.eta?v(`${r.eta} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00"):void 0,b=r.status,{labelCn:H,labelEn:V}=this.parseStatus(b),L={mmsi:r.mmsi,imo:o==null?void 0:o.imo,lat:r.lat,lng:r.lon,sog:r.sog,cog:r.cog,hdg:r.hdg,draught:r.draught,status:b,eta:I==null?void 0:I.unix(),destination:r.dest,positionTime:M.unix(),labelCn:H,labelEn:V,method:"trajectory",vendor:"myVessel",utc:M.utc().format()},W=Math.floor(M.diff(m,"minute",!0)/(s||1));W!==y&&(y=W,e.push(L))}),e}}class it extends z{constructor(t){super();K(this,"token");this.token=t}async realTimePosition(t,i={}){const n="https://api.hifleet.com/position/position/get/token",o={searchParams:{mmsi:t,usertoken:this.token}},s=await T.post(n,o).json();l==null||l.info("[%s] fetch realtime position from: %s - %j",i.requestId,n,o);const e=s==null?void 0:s.list;if(!e)return l==null||l.warn("[%s] fetch realtime position failed: %j",i.requestId,n,s),s;for(const m in e)!isNaN(e[m])&&Number(e[m])!==1/0&&(e[m]=Number(e[m]));e.status=e.sp>3?0:1;const d=e.status,{labelCn:c,labelEn:u}=this.parseStatus(d),f=v(`${e.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return{mmsi:e.m,name:e.n,imo:e.imonumber,callSign:e.callsign,lat:Math.round(e.la/60*1e5)/1e5,lng:Math.round(e.lo/60*1e5)/1e5,length:e.l,width:e.w,draught:e.draught,sog:e.sp,cog:e.co,hdg:e.h,rot:isNaN(e.rot)?0:e.rot,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(e.eta)?v(`${e.eta} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00").unix():void 0,destination:e.destination,positionTime:f.unix(),utc:f.utc().format(),status:d,labelCn:c,labelEn:u,method:"position",vendor:"hifleet"}}async search(t,i={}){let n="https://www.hifleet.com/hifleetapi/searchVesselOL.do";const o={searchParams:{keyword:t},headers:{Referer:"https://www.hifleet.com",Origin:"https://www.hifleet.com",Host:"www.hifleet.com"}};let s=await T.post(n,o).json();l==null||l.info("[%s] fetch vessel props from: %s - %j",i.requestId,n,o),s instanceof Array&&(s=s[0]);for(const d in s)!isNaN(s[d])&&Number(s[d])!==1/0&&(s[d]=Number(s[d]));const e={mmsi:s.m,name:s.n,imo:s.i,callSign:s.c,length:s.l,breadth:s.b,draught:s.dr};return n="https://www.hifleet.com/hifleetapi/sameShipSearch.do",s=await T.post(n,o).json(),l==null||l.info("[%s] fetch vessel dead weight from: %s - %j",i.requestId,n,o),s instanceof Array&&(s=s[0]),s&&(e.deadweight=Number(s.dwt)),e}async trajectory(t,i,n,o,s=!0,e={}){var r,M,I;const d=await this.realTimePosition(t,e);let c=v(i);const u=v(n),f=v();if(s){let b=u.diff(c,"d",!0);b<0?c=u.clone().subtract(40,"d"):b<30?c.subtract(10,"d"):b<60?c.subtract(5,"d"):c=u.clone().subtract(80,"d"),b=f.diff(u,"d",!0),u.add(b>10?240:b*24,"h")}const y={searchParams:{endtime:u.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}},m="https://api.hifleet.com/position/trajectory/nocompressed/withstatic/token",h=await T.get(m,y).json();l==null||l.info("[%s] fetch trajectory from: %s - %j",e.requestId,m,y);let g;h&&(g=((M=(r=h.ships)==null?void 0:r.offors)==null?void 0:M.ship)||[],g.length||l==null||l.warn("[%s] fetch trajectory failed: %j",e.requestId,h));const k=[];let Y=-1;const p=v(`${(I=g==null?void 0:g[0])==null?void 0:I.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");for(const b of g){for(const D in b)!isNaN(b[D])&&Number(b[D])!==1/0&&(b[D]=Number(b[D]));const H=v(`${b.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");b.status=b.sp>4?0:1;const{labelEn:V,labelCn:L}=this.parseStatus(b.status),W={mmsi:b.m,name:b.n,imo:d==null?void 0:d.imo,lat:b.la,lng:b.lo,draught:b.draught,sog:b.sp,cog:b.co,hdg:b.hdg,positionTime:H.unix(),utc:H.utc().format(),status:b.status,labelCn:L,labelEn:V,method:"trajectory",vendor:"hifleet"},F=Math.floor(H.diff(p,"minute",!0)/(o||1));F!==Y&&(Y=F,k.push(W))}return k}}class rt extends z{constructor(t){super();K(this,"token");this.token=t}async realTimePosition(t,i={}){const n={searchParams:{id:t,k:this.token,enc:1}},o="https://api.shipxy.com/apicall/GetSingleShip",s=await T.get(o,n).json();if(l==null||l.info("[%s] fetch realtime position from: %s - %j",i.requestId,o,n),(s==null?void 0:s.status)!==0)return s;const e=s.data[0];for(const y in e)!isNaN(e[y])&&Number(e[y])!==1/0&&(e[y]=Number(e[y]));const{labelCn:d,labelEn:c}=await this.parseStatus(e.navistat),u=v.unix(e.lasttime);return{mmsi:e.ShipID,name:e.name,imo:e.imo,callSign:e.callsign,lat:Math.round(e.lat/1e6*1e5)/1e5,lng:Math.round(e.lon/1e6*1e5)/1e5,length:Math.round(e.length/10*100)/100,width:Math.round(e.width/10*100)/100,draught:Math.round(e.draught/1e3*100)/100,sog:Math.round(e.sog*3600/1e3/1852*100)/100,cog:Math.round(e.cog/100*100)/100,hdg:Math.round(e.hdg/100*100)/100,rot:Math.round(e.rot/100*100)/100,positionTime:e.lasttime,utc:u.utc().format(),status:e.navistat,labelEn:c,labelCn:d,method:"position",vendor:"shipxy"}}async trajectory(t,i,n,o,s=!0,e={}){var p;const d=await this.realTimePosition(t,e),c=v(i),u=v(n),f="https://api.shipxy.com/apicall/GetShipTrack",y={searchParams:{id:t,k:this.token,enc:1,cut:0,btm:c.unix(),etm:u.unix()}},m=await T.get(f,y).json();if(l==null||l.info("[%s] fetch trajectory from: %s - %j",e.requestId,f,y),(m==null?void 0:m.status)!==0)return m;const h=m==null?void 0:m.points,g=[],k=v.unix((p=h[0])==null?void 0:p.utc);let Y=-1;for(const r of h){const M=v.unix(r.utc),I={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:M.unix(),utc:M.utc().format(),method:"trajectory",vendor:"shipxy"},b=Math.floor(M.diff(k,"minute",!0)/(o||1));b!==Y&&(Y=b,g.push(I))}return g}}class ct extends z{constructor(t){super();K(this,"token");this.token=t}async getShipId(t,i={}){const n={headers:{appKey:this.token},json:{mmsiList:t}},o="https://api3.myships.com/sp/ships/getShipIdByMMSI",s=await T.post(o,n).json();return l==null||l.info("[%s] fetch ship id from: %s - %j",i.requestId,o,n),s.code!=="0"?s:s.data[0].shipId}async getShipInfo(t,i={}){const n={headers:{appKey:this.token},json:{shipId:t}},o="https://api3.myships.com/sp/ships/aissta",s=await T.post(o,n).json();if(l==null||l.info("[%s] fetch ship info from: %s - %j",i.requestId,o,n),s.code!=="0")return s;const e=s.data;let d=e.imo;return t==="407170"&&(d="9198379",l==null||l.warn("[%s] ship(%s) imo error: %s, should be %s",i.requestId,t,e.imo,d)),{mmsi:e.mmsi,name:e.shipnameEn,imo:d,callSign:e.callSign,length:e.length,width:e.breadth,draught:(e.draught||100)/10}}async realTimePosition(t,i={}){const n=await this.getShipId(t,i),o=await this.getShipInfo(n,i),s={headers:{appKey:this.token},json:{shipId:n}},e="https://api3.myships.com/sp/ships/position/latest",d=await T.post(e,s).json();l==null||l.info("[%s] fetch realtime position from: %s - %j",i.requestId,e,s);const c=d.data[0];for(const h in c)!isNaN(c[h])&&Number(c[h])!==1/0&&(c[h]=Number(c[h]));const{labelCn:u,labelEn:f}=await this.parseStatus(c.aisNavStatus),y=v.unix(c.posTime);return{...o,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:y.utc().format(),status:c.aisNavStatus,labelEn:f,labelCn:u,method:"position",vendor:"myship"}}async trajectory(t,i,n,o,s=!0,e={}){const d=v(i),c=v(n),u=await this.getShipId(t),f=await this.getShipInfo(u),y=[];for(;c.diff(d,"day",!0)>30;)await this.trajectoryIn30Day(u,d.unix(),d.add(30,"day").unix(),f,t,o,y);return await this.trajectoryIn30Day(u,d.unix(),c.unix(),f,t,o,y),y}async trajectoryIn30Day(t,i,n,o,s,e,d,c={}){var k;const u={headers:{appKey:this.token},json:{shipId:t,startTime:i,endTime:n}},f="https://api3.myships.com/sp/ships/position/history",y=await T.post(f,u).json();if(l==null||l.info("[%s] fetch trajectory from: %s - %j",c.requestId,f,u),y.code!=="0")return l==null||l.warn("[%s] invoke myship trajectory failed: %j",c.requestId,y),y;const m=y.data;for(const Y in m)!isNaN(m[Y])&&Number(m[Y])!==1/0&&(m[Y]=Number(m[Y]));const h=v.unix((k=m[0])==null?void 0:k.posTime);let g=-1;for(const Y of m){const p=v.unix(Y.posTime),r={imo:o==null?void 0:o.imo,mmsi:s,lat:Math.round(Y.lat/1e4/60*1e5)/1e5,lng:Math.round(Y.lon/1e4/60*1e5)/1e5,sog:Math.round(Y.sog/10*100)/100,cog:Math.round(Y.cog/10*100)/100,hdg:Math.round(Y.heading*100)/100,rot:Math.round(Y.rot*100)/100,positionTime:p.unix(),utc:p.utc().format(),method:"trajectory",vendor:"myship"},M=Math.floor(p.diff(h,"minute",!0)/(e||1));M!==g&&(g=M,d.push(r))}return d}}let A;try{A=_.getLogger("vessel")}catch{}finally{}var G=(w=>(w.NOTICE="NOTICE",w.WARN="WARN",w.HEAVY="HEAVY",w.SEVERE="SEVERE",w.ERROR="ERROR",w.FATAL="FATAL",w))(G||{});class U{parsePrinciple(a,t={}){var e,d,c;A==null||A.info("[%s] parse rule: %s",t.requestId,a);const i=new RegExp("(?<=\\[)(.+)(?=])","g"),n=a.match(i)?(e=a.match(i))==null?void 0:e[0]:void 0,o=n==null?void 0:n.split(";");if(!o)return;const s={};for(let u=0;u<(o==null?void 0:o.length);u++){const f=(c=(d=o[u].match(i))==null?void 0:d[0])==null?void 0:c.split("],");if(u===0&&!f)s.scope=o[0];else if(f)for(let y=0,m=f.length;y<m;y++){const h=this.parseRule(f[y]);h&&(s[h.level]?h.key?s[h.level][h==null?void 0:h.key]=h:s[h.level]=h:h.key?s[h.level]={[h==null?void 0:h.key]:h}:s[h.level]=h)}}return s}parseRule(a,t={}){var s;A==null||A.info("[%s] parse rule: %s",t.requestId,a),a=a.startsWith("[")?a:`[${a}`,a=a.endsWith("]")?a:`${a}]`;const i=new RegExp("(?<=\\[)(.+?)(?=])","g"),n=(s=a==null?void 0:a.match(i))==null?void 0:s[0],o=n==null?void 0:n.split(",");if(o)return{operator:o[0],number:Number.isNaN(Number(o[1]))?o[1]:Number(o[1]),level:o[2],time:Number(o[3]),key:o[4]}}checkWeather(a,t,i={}){var h,g,k,Y,p,r,M,I,b,H,V,L,W,F,D;let n=0,o=0,s=0,e=0;const d=Math.round(((g=(h=t==null?void 0:t.SEVERE)==null?void 0:h.sigWave)==null?void 0:g.number)*1.6*100)/100,c=(Y=(k=t==null?void 0:t.SEVERE)==null?void 0:k.sigWave)==null?void 0:Y.number,u=(r=(p=t==null?void 0:t.HEAVY)==null?void 0:p.sigWave)==null?void 0:r.number,f=Math.round((((I=(M=t==null?void 0:t.SEVERE)==null?void 0:M.wind)==null?void 0:I.number)+2)*100)/100,y=(H=(b=t==null?void 0:t.SEVERE)==null?void 0:b.wind)==null?void 0:H.number,m=(L=(V=t==null?void 0:t.HEAVY)==null?void 0:V.wind)==null?void 0:L.number;for(let q=0;q<(a==null?void 0:a.length);q++){const S=a[q],R=(F=(W=S==null?void 0:S.meteo)==null?void 0:W.wave)==null?void 0:F.sig,O=(D=S==null?void 0:S.meteo)==null?void 0:D.wind,B=q?v(S.eta).diff(v(a[q-1].eta),"hour",!0):0;e=B>e?B:e,A==null||A.info("[%s] check sig.wave: %j",i.requestId,{...R,dgThd4Wv:d,svThd4Wv:c,hvThd4Wv:u}),(R==null?void 0:R.height)>=d?S.isDangerous=!0:(R==null?void 0:R.height)>=c?S.isSevere=!0:(R==null?void 0:R.height)>=u&&(S.isHeavy=!0),A==null||A.info("[%s] check wind: %j",i.requestId,{...O,dgThd4Wd:f,svThd4Wd:y,hvThd4Wd:m}),(O==null?void 0:O.scale)>=f?(S.isDangerous=!0,delete S.isSevere,delete S.isHeavy):(O==null?void 0:O.scale)>y?(S.isDangerous||(S.isSevere=!0),delete S.isHeavy):(O==null?void 0:O.scale)===m&&!S.isDangerous&&!S.isSevere&&(S.isHeavy=!0),n+=S.isDangerous?B:0,o+=S.isSevere?B:0,s+=S.isHeavy?B:0}return n=Math.round(n*100)/100,o=Math.round(o*100)/100,s=Math.round(s*100)/100,e=Math.round(e),{sample:a,dangerous:n,severe:o,heavy:s,step:e<3?3:e,wind:{dgThd4Wd:f,svThd4Wd:y,hvThd4Wd:m},sig:{dgThd4Wv:d,svThd4Wv:c,hvThd4Wv:u}}}}const dt=new U;let N;try{N=_.getLogger("vessel")}catch{}finally{}var J=(w=>(w.common="common",w.container="container",w))(J||{}),Q=(w=>(w.Ballast="Ballast",w.Laden="Laden",w))(Q||{}),X=(w=>(w.Cp="CP",w.Perf="Basis",w.Instruct="Other",w))(X||{});class E{static blockCoefficient(a,t,i,n){let o=Math.round(a/(t*i*n)*100)/100;o=o<.55?.55:o>.85?.85:o;const s=[.55,.6,.65,.7,.75,.8,.85],e=s.map(d=>Math.abs(d-o));return s[e.indexOf(Math.min(...e))]}static froudeNumber(a,t,i=9.8){let n=Math.round(Math.sqrt(a*a/(i*t))*100)/100;return n=n<.05?.05:n>.3?.3:n,n}static amendFactor(a,t,i){const 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.4,-10.6,-9.5],.8:[2.6,-13.1,-15.1],.85:[3.1,-18.7,28]};let s={.55:[1.7,-1.4,-7.4],.6:[2.2,-2.5,-9.7],.65:[2.6,-3.7,-11.6],.7:[3.1,-5.3,-12.4],.75:[2.6,-12.5,-13.5],.8:[3,-16.3,-21.6],.85:[3.4,-20.9,31.8]}[a];return i==="Laden"&&(s=n[a]),s[0]+s[1]*t+s[2]*Math.pow(t,2)}static directionFactor(a,t=0){let i;return a>30&&a<=60?i=(1.7-.03*Math.pow(t-4,2))/2:a>60&&a<=150?i=(.9-.06*Math.pow(t-6,2))/2:i=(.4-.03*Math.pow(t-8,2))/2,Math.round(i*1e5)/1e5}static vesselTagFactor(a,t,i,n=0){n=n>5?n-.9*(n-5):n;let o;return i==="container"?o=.7*n+Math.pow(n,6.5)/(22*Math.pow(a,2/3)):t==="Ballast"?o=.7*n+Math.pow(n,6.5)/(2.7*Math.pow(a,2/3)):o=.5*n+Math.pow(n,6.5)/(2.7*Math.pow(a,2/3)),o}static waveHeightFactor(a){return a=a<1.25?1.25:a,a=a>6?a-.9*(a-6):a,Math.round((-.144*Math.pow(a,2)+.178*a)*1e4)/1e4}static assembleProperties(a,t,i,n){var u,f;const o=a.lbp??a.length??a.lengthOverall??198.9642,s=a.draught??8,e=a.breadthMoulded??a.breadth??a.breadthExtreme??32.4572,d=a.deadweight??67035.7773;return{tag:((f=(u=a==null?void 0:a.type)==null?void 0:u.toLowerCase())==null?void 0:f.indexOf("container"))>-1?"container":"common",lbp:o,loadCondition:t,draught:s,breadthMoulded:e,displacement:Math.round((d/1.025+s*e*o*.7)*1e4)/1e4,speed:Math.round((i??14.1382)*1852/3600*1e4)/1e4,bearing:n||90}}static async speedLoseAt(a,t,i,n="",o=2,s=!0,e=!1,d={}){let c;if(t.velocity&&e&&(a.speed=P.LngLatHelper.roundPrecision(t.velocity*1852/3600,6)),s){const u=await nt.MeteoHelper.queryPointFactor(t.lng,t.lat,i.valueOf(),"wind,wave,current,watertemp",n,d),f=E.weatherFactor(a,u),y=E.currentFactor(a.bearing,u==null?void 0:u.current,o);c={meteo:{...u},wxFactor:f,cFactor:y,speed:t.velocity&&e?t.velocity:Math.round((a.speed*1.943844+f+y)*100)/100,eta:i.utc().format("YYYY-MM-DDTHH:mm[Z]"),etd:i.utc().format("YYYY-MM-DDTHH:mm[Z]")}}else c={wxFactor:0,cFactor:0,speed:t.velocity&&e?t.velocity:Math.round((a.speed*1.943844+0+0)*100)/100,eta:i.utc().format("YYYY-MM-DDTHH:mm[Z]"),etd:i.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(a,t,i,n,o,s,e="",d=!0,c=!1,u={}){t.utc();const f=[],y=[];let m=0,h=0,g,k;for(let Y=0;Y<s.length-1;Y++){let p=s[Y];p.distanceFromStart=o+h;const r=s[Y+1];if(a.bearing=P.LaneHelper.calculateBearing(p,r,!r.gcToPrevious),p.bearing=a.bearing,p.suspend&&c){p.eta=p.eta||t.format("YYYY-MM-DDTHH:mm[Z]"),p.elapsed=p.elapsed??0;const b=p.suspend-p.elapsed;if(n-m>b)n=n-m-b,t.add(b,"hour"),p.elapsed=p.suspend;else{const H=n-m;p.elapsed+=H,t.add(H,"hour"),n=0}if(N==null||N.info(`[%s] suspend ${p.elapsed} hours at %j, and remain ${n} hours need to go...`,u.requestId,p),n===0)return p.distanceFromPrevious=h,{etd:t,from:k||p,to:p,next:s.filter(H=>H),wps:f,days:y}}p=await E.speedLoseAt(a,p,t,e,0,d,c,u),k=k||p,p.important&&f.push(p),t.isSameOrAfter(i)&&(y.push(p),i.add(24,"hour"));const M=P.LaneHelper.calculateDistance(p,r,!r.gcToPrevious);let I=Math.ceil(M/k.speed*1e4)/1e4;if(m+I<n){if(m+=I,t.add(I,"hour"),delete s[Y],N==null||N.info(`[%s] go to %j from %j with ${M}nm, and cost ${I} hours`,u.requestId,{lat:r.lat,lng:r.lng},{lat:k.lat,lng:k.lng,etd:k.etd}),h+=M,s.filter(b=>b).length<=1){g=r,g.eta=t.format("YYYY-MM-DDTHH:mm[Z]"),g.distanceFromPrevious=M,g.distanceFromStart=o+h,f.push(g),delete s[Y+1];break}}else{I=n-m,t.add(I,"hour");const b=P.LngLatHelper.roundPrecision(k.speed*I,4);g=P.LaneHelper.calculateCoordinate(p,a.bearing,b,"nauticalmiles",!r.gcToPrevious),g.eta=t.format("YYYY-MM-DDTHH:mm[Z]"),s[Y]=g,N==null||N.info(`[%s] go to %j from %j with ${b}nm, and cost ${I} hours`,u.requestId,{lat:g.lat,lng:g.lng},{lat:p.lat,lng:p.lng,etd:p.etd}),h+=b,g.distanceFromPrevious=h,g.distanceFromStart=o+h;break}}return{etd:t,from:k,to:g,next:s.filter(Y=>Y),wps:f,days:y}}static currentFactor(a,t,i=0){const n=(a-(t==null?void 0:t.degree)||0)/180*Math.PI;if(Math.abs(n)===Math.PI/2)return 0;let o=((t==null?void 0:t.kts)||0)*Math.cos(n);return i&2?o=Math.ceil(o*100)/100:i&1?o=Math.floor(o*100)/100:o=Math.round(o*100)/100,Math.abs(o)>5?0:o}static weatherFactor(a,t){var f,y,m,h,g;N==null||N.debug("calculate weather factor via: %j",{...a,...t});const i=E.blockCoefficient(a.displacement,a.lbp,a.breadthMoulded,a.draught),n=E.froudeNumber(a.speed,a.lbp),o=E.amendFactor(i,n,a.loadCondition);let s=Math.abs(a.bearing%360-(((f=t==null?void 0:t.wind)==null?void 0:f.degree)%360||0));s=s>180?360-s:s;const e=E.directionFactor(s,(y=t==null?void 0:t.wind)==null?void 0:y.scale),d=E.vesselTagFactor(a.displacement,a.loadCondition,a.tag,(m=t==null?void 0:t.wind)==null?void 0:m.scale);let c=e*o*d/100*a.speed;c=Math.round(c*1.943844*1e4)/1e4*-1;const u=E.waveHeightFactor(((g=(h=t==null?void 0:t.wave)==null?void 0:h.sig)==null?void 0:g.height)??1);return c=c*.24+u*.76,N==null||N.debug("weather factor = %s",c),Math.round(c*100)/100}static async analyseInstant(a,t,i,n,o,s="",e=0,d=!0,c=!1,u={}){var B,$,tt,et,st;const f=v().valueOf();a.lng=P.LngLatHelper.convertToStdLng(a.lng);const{route:y,waypoints:m}=o.points,h=P.LaneHelper.calculateSubRoute(a,y);if(((B=h[0])==null?void 0:B.length)<=1)return;const{v0:g,label:k}=a.sog?{v0:a.sog,label:"Other"}:{v0:n.speed,label:"CP"},Y=E.assembleProperties(i,n.loadCondition,g,0),p=m.length?P.LaneHelper.calculateSubWaypoints(a,m):[],r={from:{...a},route:h,waypoints:p,v0:g,label:k},M={hours:[],days:[],wps:[]};e||(P.LaneHelper.calculateRouteDistance(h)/n.speed<=72?e=3:e=6);let I=P.LaneHelper.simplifyRouteToCoordinates(h,p,0),b=0,H=0,V=0,L=0;t=v(t).utc();const W=t.clone();for(;I.length>0;){const C=e-t.hour()%e,Z=Math.ceil(t.clone().add(C,"h").set({minute:0,second:0,millisecond:0}).diff(t,"h",!0)*1e4)/1e4,x=await E.speedLoseInHoursStep(Y,t,W,Z,b,I,s,d,c,u);($=x.from)!=null&&$.speed&&(M.hours.push(x.from),M.wps.push(...x.wps),M.days.push(...x.days)),I=x==null?void 0:x.next,I.length||M.hours.push(x==null?void 0:x.to),b+=((tt=x==null?void 0:x.to)==null?void 0:tt.distanceFromPrevious)??0}const F=M.hours;for(let C=0;C<F.length-1;C++){const Z=v(F[C+1].eta).diff(F[C].etd,"hour",!0)||1;H+=F[C].wxFactor||0*Z,V+=F[C].cFactor||0*Z,L+=Z}(et=M.wps)==null||et.forEach((C,Z)=>{if(Z){const x=M.wps[Z-1],ut=C.distanceFromStart-x.distanceFromStart,at=v(C.eta).diff(v(x.etd),"h",!0);at<1?C.avgSpd=x.speed:C.avgSpd=Math.round(ut/at*100)/100}}),r.sample=M;const D=M.hours.at(0),q=M.hours.at(-1);r.distance=Math.round(q.distanceFromStart*1e4)/1e4,r.etd=v(D.eta).utc().format(),r.eta=v(q.eta).utc().format(),r.wxFactor=Math.round(H/L*1e4)/1e4,r.cFactor=Math.round(V/L*1e4)/1e4,r.avgSpeed=Math.round(q.distanceFromStart/L*1e4)/1e4,r.totalHrs=Math.round(L*1e4)/1e4,r.totalFoCons=Math.round((n==null?void 0:n.fo)/24*r.totalHrs*1e3)/1e3,r.totalDgoCons=Math.round((n==null?void 0:n.dgo)/24*r.totalHrs*1e3)/1e3;const R=v().valueOf()-f,O=((st=M==null?void 0:M.hours)==null?void 0:st.length)||1;return N==null||N.info("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms",u==null?void 0:u.requestId,R,O,Math.round(R/O*1e3)/1e3),r}static async analyseInstantWithThreshed(a,t,i,n,o,s,e="",d=3,c=!0,u=!1,f={}){var L,W,F;a.lng=P.LngLatHelper.convertToStdLng(a.lng);const y=E.assembleProperties(n,o.loadCondition,o.speed,0),m=P.LaneHelper.calculateSubRoute(a,s);if(((L=m[0])==null?void 0:L.length)<=1)return;let h=P.LaneHelper.simplifyRouteToCoordinates(m,[],0);h.forEach(D=>D.important=!0);let g=0,k=0,Y=0,p=0,r;const M={hours:[],wps:[],days:[]};for(t=v(t).utc();h.length>0;){const D=d-t.hour()%d;let q=Math.ceil(t.clone().add(D,"h").set({minute:0,second:0,millisecond:0}).diff(t,"h",!0)*1e4)/1e4;if(q=t.clone().add(q,"h").isAfter(i)?i.diff(t,"h",!0)*1e4/1e4:q,q)r=await E.speedLoseInHoursStep(y,t,i.clone(),q,g,h,e,c,u,f),(W=r.from)!=null&&W.speed&&(M.hours.push(r.from),r!=null&&r.wps&&M.wps.push(...r.wps),M.days.push(...r.days)),h=r==null?void 0:r.next,h.length||(M.hours.push(r==null?void 0:r.to),r!=null&&r.wps&&M.wps.push(...r.wps),M.days.push(r==null?void 0:r.to)),g+=((F=r==null?void 0:r.to)==null?void 0:F.distanceFromPrevious)??0;else{r&&(M.hours.push(r.to),r!=null&&r.wps&&M.wps.push(...r.wps),M.days.push(r.to));break}}const I=M.hours;for(let D=0;D<I.length-1;D++){const q=v(I[D+1].eta).diff(I[D].etd,"hour",!0);k+=I[D].wxFactor*q,Y+=I[D].cFactor*q,p+=q}const b=M.hours.at(0),H=M.hours.at(-1);return{sample:M,distance:Math.round(((H==null?void 0:H.distanceFromStart)||0)*1e4)/1e4,etd:v(b.eta).utc().format(),eta:v(H==null?void 0:H.eta).utc().format(),wxFactor:Math.round(k/p*1e4)/1e4,cFactor:Math.round(Y/p*1e4)/1e4,avgSpeed:Math.round(((H==null?void 0:H.distanceFromStart)||0)/p*1e4)/1e4,totalHrs:Math.round(p*1e4)/1e4,to:H,route:P.LaneHelper.generateRouteAccordingToWaypoints(h)}}}j.AISImpl=z,j.AlertHelper=U,j.AlertLevel=G,j.HifleetImpl=it,j.LoadCondition=Q,j.MyShipImpl=ct,j.MyVesselImpl=ot,j.ShipxyImpl=rt,j.SpeedHelper=E,j.SpeedLabel=X,j.VesselTag=J,j.alertHelper=dt,Object.defineProperty(j,Symbol.toStringTag,{value:"Module"})});
|
|
@@ -130,6 +130,7 @@ export declare class SpeedHelper {
|
|
|
130
130
|
* @param eta 位置时间
|
|
131
131
|
* @param source [CMEMS, GFS, Other]
|
|
132
132
|
* @param role 1: 船东, 2: 租家, 0: 未知
|
|
133
|
+
* @param useMeteo true 启用气象分析
|
|
133
134
|
* @param useRouteParam true 启用设置速度
|
|
134
135
|
*/
|
|
135
136
|
private static speedLoseAt;
|
|
@@ -142,6 +143,7 @@ export declare class SpeedHelper {
|
|
|
142
143
|
* @param distanceFromStart 与最开始起点的距离
|
|
143
144
|
* @param keypoints 剩下的航路点
|
|
144
145
|
* @param source 气象数据源: CMEMS / GFS
|
|
146
|
+
* @param useMeteo true 启用气象分析
|
|
145
147
|
* @param useRouteParam true 启用航线上设置的参数 { suspend: 停留时长(小时), velocity: 速度(kts)}
|
|
146
148
|
* @private
|
|
147
149
|
*/
|
|
@@ -168,6 +170,7 @@ export declare class SpeedHelper {
|
|
|
168
170
|
* @param lane 航线 { points: { route, waypoints }}
|
|
169
171
|
* @param source 气象数据源,GFS or CMEMES, 默认CMEMS
|
|
170
172
|
* @param stepHrs 样本步长, 0表示动态计算(6 or 3 hrs)
|
|
173
|
+
* @param useMeteo true 启用气象分析
|
|
171
174
|
* @param useRouteParam
|
|
172
175
|
*/
|
|
173
176
|
static analyseInstant(from: any, etd: any, vessel: VesselAssemble, cp: {
|
|
@@ -181,7 +184,7 @@ export declare class SpeedHelper {
|
|
|
181
184
|
waypoints: any[];
|
|
182
185
|
};
|
|
183
186
|
voyage: any;
|
|
184
|
-
}, source?: string, stepHrs?: number, useRouteParam?: boolean, options?: {
|
|
187
|
+
}, source?: string, stepHrs?: number, useMeteo?: boolean, useRouteParam?: boolean, options?: {
|
|
185
188
|
requestId?: string;
|
|
186
189
|
}): Promise<any>;
|
|
187
190
|
/**
|
|
@@ -194,17 +197,20 @@ export declare class SpeedHelper {
|
|
|
194
197
|
* @param route 航路[[[lng, lat]]]
|
|
195
198
|
* @param source 气象数据源,GFS or CMEMES, 默认CMEMS
|
|
196
199
|
* @param stepHrs
|
|
200
|
+
* @param useMeteo true 启用气象分析
|
|
201
|
+
* @param useRouteParam
|
|
197
202
|
*/
|
|
198
203
|
static analyseInstantWithThreshed(from: any, etd: any, threshed: moment.Moment, vessel: VesselAssemble, cp: {
|
|
199
204
|
loadCondition: string;
|
|
200
205
|
speed: number;
|
|
201
206
|
fo: number;
|
|
202
207
|
dgo: number;
|
|
203
|
-
}, route: number[][][], source?: string, stepHrs?: number, useRouteParam?: boolean, options?: {
|
|
208
|
+
}, route: number[][][], source?: string, stepHrs?: number, useMeteo?: boolean, useRouteParam?: boolean, options?: {
|
|
204
209
|
requestId?: string;
|
|
205
210
|
}): Promise<{
|
|
206
211
|
sample: any;
|
|
207
212
|
distance: number;
|
|
213
|
+
etd: string;
|
|
208
214
|
eta: string;
|
|
209
215
|
wxFactor: number;
|
|
210
216
|
cFactor: number;
|