@idm-plugin/vessel 1.5.6 → 1.5.7
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 +295 -293
- package/dist/index.umd.cjs +1 -1
- package/dist/speed/src/index.d.ts +30 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
var st = Object.defineProperty;
|
|
2
|
-
var at = (
|
|
3
|
-
var Z = (
|
|
2
|
+
var at = (w, s, t) => s in w ? st(w, s, { enumerable: !0, configurable: !0, writable: !0, value: t }) : w[s] = t;
|
|
3
|
+
var Z = (w, s, t) => (at(w, typeof s != "symbol" ? s + "" : s, t), t);
|
|
4
4
|
import O from "got";
|
|
5
5
|
import z from "@log4js-node/log4js-api";
|
|
6
|
-
import
|
|
6
|
+
import g from "moment";
|
|
7
7
|
import { LngLatHelper as B, LaneHelper as V } from "@idm-plugin/geo";
|
|
8
8
|
import { MeteoHelper2 as ot, MeteoHelper as nt } from "@idm-plugin/meteo2";
|
|
9
9
|
import { Meteo2Assist as tt } from "@idm-plugin/meteo";
|
|
10
|
-
let
|
|
10
|
+
let h;
|
|
11
11
|
try {
|
|
12
|
-
|
|
12
|
+
h = z.getLogger("vessel");
|
|
13
13
|
} catch {
|
|
14
14
|
} finally {
|
|
15
15
|
}
|
|
@@ -70,32 +70,32 @@ class bt extends K {
|
|
|
70
70
|
grant_type: "client_credentials"
|
|
71
71
|
}
|
|
72
72
|
}, n = await O.post(i, o).json();
|
|
73
|
-
|
|
73
|
+
h == null || h.info("[%s] fetch access token from: %s - %j", t.requestId, i, n), n.error || (this.token = {
|
|
74
74
|
accessToken: n.access_token,
|
|
75
75
|
tokenType: n.token_type,
|
|
76
76
|
expiresIn: n.expires_in,
|
|
77
77
|
scope: n.scope,
|
|
78
78
|
jti: n.jti,
|
|
79
|
-
issuedAt:
|
|
79
|
+
issuedAt: g().utc().format()
|
|
80
80
|
});
|
|
81
81
|
}
|
|
82
82
|
async realTimePosition(t, i = {}) {
|
|
83
|
-
var
|
|
84
|
-
(!this.token ||
|
|
83
|
+
var u, m, f;
|
|
84
|
+
(!this.token || g().diff(g(this.token.issuedAt), "seconds") > ((u = this.token) == null ? void 0 : u.expiresIn) - 300) && await this.authToken(i);
|
|
85
85
|
const o = "https://svc.data.myvessel.cn/sdc/v1/vessels/status/location/unit", n = {
|
|
86
86
|
headers: {
|
|
87
|
-
Authorization: `${(
|
|
87
|
+
Authorization: `${(m = this.token) == null ? void 0 : m.tokenType} ${(f = this.token) == null ? void 0 : f.accessToken}`
|
|
88
88
|
},
|
|
89
89
|
searchParams: { mmsi: t }
|
|
90
90
|
};
|
|
91
|
-
|
|
91
|
+
h == null || h.info("[%s] fetch realtime position from: %s - %j", i.requestId, o, n);
|
|
92
92
|
const a = await O.get(o, n).json();
|
|
93
93
|
if (a.code)
|
|
94
|
-
return
|
|
94
|
+
return h == null || h.warn("[%s] fetch realtime position failed: %j", i.requestId, o, { message: a.message, status: a.status, code: a.code }), a;
|
|
95
95
|
const e = a.data;
|
|
96
|
-
for (const
|
|
97
|
-
!isNaN(e[
|
|
98
|
-
const
|
|
96
|
+
for (const p in e)
|
|
97
|
+
!isNaN(e[p]) && Number(e[p]) !== 1 / 0 && (e[p] = Number(e[p]));
|
|
98
|
+
const d = g(`${e.postime} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
99
99
|
return {
|
|
100
100
|
mmsi: e.mmsi,
|
|
101
101
|
name: e.vesselName,
|
|
@@ -110,29 +110,29 @@ class bt extends K {
|
|
|
110
110
|
cog: e.cog,
|
|
111
111
|
hdg: e.hdg,
|
|
112
112
|
rot: e.rot,
|
|
113
|
-
eta: /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(e.eta) ?
|
|
113
|
+
eta: /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(e.eta) ? g.utc(e.eta).format() : void 0,
|
|
114
114
|
destination: e.dest,
|
|
115
|
-
positionTime:
|
|
115
|
+
positionTime: d.unix(),
|
|
116
116
|
status: e.status,
|
|
117
117
|
labelCn: e.statusNameCn,
|
|
118
118
|
labelEn: e.statusNameEn,
|
|
119
119
|
method: "position",
|
|
120
120
|
vendor: "myVessel",
|
|
121
|
-
utc:
|
|
121
|
+
utc: d.utc().format()
|
|
122
122
|
};
|
|
123
123
|
}
|
|
124
124
|
async trajectory(t, i, o, n, a = !0, e = {}) {
|
|
125
|
-
(!this.token ||
|
|
126
|
-
const
|
|
127
|
-
for (;
|
|
128
|
-
await this.trajectoryIn30Day(t, r, r.clone().add(30, "day"),
|
|
129
|
-
return await this.trajectoryIn30Day(t, r,
|
|
125
|
+
(!this.token || g().diff(g(this.token.issuedAt), "seconds") > this.token.expiresIn - 300) && await this.authToken(e);
|
|
126
|
+
const d = await this.realTimePosition(t, e), r = g(i), u = g(o), m = [];
|
|
127
|
+
for (; u.diff(r, "day", !0) > 30; )
|
|
128
|
+
await this.trajectoryIn30Day(t, r, r.clone().add(30, "day"), d, n, m, e), r.add(30, "day");
|
|
129
|
+
return await this.trajectoryIn30Day(t, r, u, d, n, m, e), m;
|
|
130
130
|
}
|
|
131
|
-
async trajectoryIn30Day(t, i, o, n, a, e,
|
|
132
|
-
var
|
|
133
|
-
const r = "https://svc.data.myvessel.cn/sdc/v1/vessels/status/track",
|
|
131
|
+
async trajectoryIn30Day(t, i, o, n, a, e, d = {}) {
|
|
132
|
+
var l, Y, k, b, I;
|
|
133
|
+
const r = "https://svc.data.myvessel.cn/sdc/v1/vessels/status/track", u = {
|
|
134
134
|
headers: {
|
|
135
|
-
Authorization: `${(
|
|
135
|
+
Authorization: `${(l = this.token) == null ? void 0 : l.tokenType} ${(Y = this.token) == null ? void 0 : Y.accessToken}`
|
|
136
136
|
},
|
|
137
137
|
json: {
|
|
138
138
|
mmsi: t,
|
|
@@ -140,35 +140,35 @@ class bt extends K {
|
|
|
140
140
|
endTime: o.utcOffset(8).format("YYYY-MM-DD HH:mm:ss")
|
|
141
141
|
}
|
|
142
142
|
};
|
|
143
|
-
|
|
144
|
-
const
|
|
145
|
-
if (
|
|
146
|
-
return
|
|
147
|
-
let
|
|
148
|
-
const
|
|
149
|
-
return (
|
|
150
|
-
for (const R in
|
|
151
|
-
!isNaN(
|
|
152
|
-
const
|
|
153
|
-
mmsi:
|
|
143
|
+
h == null || h.info("[%s] fetch trajectory from: %s - %j", d.requestId, r, u);
|
|
144
|
+
const m = await O.post(r, u).json();
|
|
145
|
+
if (m.code)
|
|
146
|
+
return h == null || h.warn("[%s] fetch trajectory failed: %j", d.requestId, r, { message: m.message, status: m.status, code: m.code }), m;
|
|
147
|
+
let f = -1;
|
|
148
|
+
const p = g(`${(b = (k = m.data) == null ? void 0 : k[0]) == null ? void 0 : b.postime} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
149
|
+
return (I = m.data) == null || I.forEach((c) => {
|
|
150
|
+
for (const R in c)
|
|
151
|
+
!isNaN(c[R]) && Number(c[R]) !== 1 / 0 && (c[R] = Number(c[R]));
|
|
152
|
+
const v = g(`${c.postime} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00"), D = c.status, { labelCn: y, labelEn: M } = this.parseStatus(D), j = {
|
|
153
|
+
mmsi: c.mmsi,
|
|
154
154
|
imo: n == null ? void 0 : n.imo,
|
|
155
|
-
lat:
|
|
156
|
-
lng:
|
|
157
|
-
sog:
|
|
158
|
-
cog:
|
|
159
|
-
hdg:
|
|
160
|
-
draught:
|
|
161
|
-
status:
|
|
162
|
-
eta: /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(
|
|
163
|
-
destination:
|
|
164
|
-
positionTime:
|
|
155
|
+
lat: c.lat,
|
|
156
|
+
lng: c.lon,
|
|
157
|
+
sog: c.sog,
|
|
158
|
+
cog: c.cog,
|
|
159
|
+
hdg: c.hdg,
|
|
160
|
+
draught: c.draught,
|
|
161
|
+
status: D,
|
|
162
|
+
eta: /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(c.eta) ? g(`${c.eta} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00").utc().format() : void 0,
|
|
163
|
+
destination: c.dest,
|
|
164
|
+
positionTime: v.unix(),
|
|
165
165
|
labelCn: y,
|
|
166
|
-
labelEn:
|
|
166
|
+
labelEn: M,
|
|
167
167
|
method: "trajectory",
|
|
168
168
|
vendor: "myVessel",
|
|
169
|
-
utc:
|
|
170
|
-
}, F = Math.floor(
|
|
171
|
-
F !==
|
|
169
|
+
utc: v.utc().format()
|
|
170
|
+
}, F = Math.floor(v.diff(p, "minute", !0) / (a || 1));
|
|
171
|
+
F !== f && (f = F, e.push(j));
|
|
172
172
|
}), e;
|
|
173
173
|
}
|
|
174
174
|
}
|
|
@@ -185,14 +185,14 @@ class vt extends K {
|
|
|
185
185
|
usertoken: this.token
|
|
186
186
|
}
|
|
187
187
|
}, a = await O.post(o, n).json();
|
|
188
|
-
|
|
188
|
+
h == null || h.info("[%s] fetch realtime position from: %s - %j", i.requestId, o, n);
|
|
189
189
|
const e = a == null ? void 0 : a.list;
|
|
190
190
|
if (!e)
|
|
191
|
-
return
|
|
192
|
-
for (const
|
|
193
|
-
!isNaN(e[
|
|
191
|
+
return h == null || h.warn("[%s] fetch realtime position failed: %j", i.requestId, o, a), a;
|
|
192
|
+
for (const p in e)
|
|
193
|
+
!isNaN(e[p]) && Number(e[p]) !== 1 / 0 && (e[p] = Number(e[p]));
|
|
194
194
|
e.status = e.sp > 3 ? 0 : 1;
|
|
195
|
-
const
|
|
195
|
+
const d = e.status, { labelCn: r, labelEn: u } = this.parseStatus(d), m = g(`${e.ti} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
196
196
|
return {
|
|
197
197
|
mmsi: e.m,
|
|
198
198
|
name: e.n,
|
|
@@ -207,13 +207,13 @@ class vt extends K {
|
|
|
207
207
|
cog: e.co,
|
|
208
208
|
hdg: e.h,
|
|
209
209
|
rot: isNaN(e.rot) ? 0 : e.rot,
|
|
210
|
-
eta: /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(e.eta) ?
|
|
210
|
+
eta: /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(e.eta) ? g.utc(e.eta).format() : void 0,
|
|
211
211
|
destination: e.destination,
|
|
212
|
-
positionTime:
|
|
213
|
-
utc:
|
|
214
|
-
status:
|
|
212
|
+
positionTime: m.unix(),
|
|
213
|
+
utc: m.utc().format(),
|
|
214
|
+
status: d,
|
|
215
215
|
labelCn: r,
|
|
216
|
-
labelEn:
|
|
216
|
+
labelEn: u,
|
|
217
217
|
method: "position",
|
|
218
218
|
vendor: "hifleet"
|
|
219
219
|
};
|
|
@@ -231,9 +231,9 @@ class vt extends K {
|
|
|
231
231
|
}
|
|
232
232
|
};
|
|
233
233
|
let a = await O.post(o, n).json();
|
|
234
|
-
|
|
235
|
-
for (const
|
|
236
|
-
!isNaN(a[
|
|
234
|
+
h == null || h.info("[%s] fetch vessel props from: %s - %j", i.requestId, o, n), a instanceof Array && (a = a[0]);
|
|
235
|
+
for (const d in a)
|
|
236
|
+
!isNaN(a[d]) && Number(a[d]) !== 1 / 0 && (a[d] = Number(a[d]));
|
|
237
237
|
const e = {
|
|
238
238
|
mmsi: a.m,
|
|
239
239
|
name: a.n,
|
|
@@ -244,7 +244,7 @@ class vt extends K {
|
|
|
244
244
|
draught: a.dr,
|
|
245
245
|
type: a.t
|
|
246
246
|
};
|
|
247
|
-
return o = "https://www.hifleet.com/hifleetapi/sameShipSearch.do", a = await O.post(o, n).json(),
|
|
247
|
+
return o = "https://www.hifleet.com/hifleetapi/sameShipSearch.do", a = await O.post(o, n).json(), h == null || h.info("[%s] search vessel dead weight from: %s - %j", i.requestId, o, n), a instanceof Array && (a = a[0]), a && (e.deadweight = Number(a.dwt)), e;
|
|
248
248
|
}
|
|
249
249
|
async suggest(t, i = {}) {
|
|
250
250
|
const o = "https://www.hifleet.com/hifleetapi/getShipSuggest.do", n = {
|
|
@@ -257,67 +257,67 @@ class vt extends K {
|
|
|
257
257
|
Host: "www.hifleet.com"
|
|
258
258
|
}
|
|
259
259
|
}, a = await O.post(o, n).json();
|
|
260
|
-
|
|
260
|
+
h == null || h.info("[%s] suggest vessel props from: %s - %j", i.requestId, o, n);
|
|
261
261
|
const e = [];
|
|
262
|
-
for (const
|
|
262
|
+
for (const d of a)
|
|
263
263
|
e.push({
|
|
264
|
-
mmsi: !
|
|
265
|
-
name:
|
|
266
|
-
callSign:
|
|
267
|
-
imo: !
|
|
268
|
-
score:
|
|
264
|
+
mmsi: !d.mmsi || isNaN(d.mmsi) ? null : Number(d.mmsi),
|
|
265
|
+
name: d.name,
|
|
266
|
+
callSign: d.callsign,
|
|
267
|
+
imo: !d.imo || isNaN(d.imo) ? null : Number(d.imo),
|
|
268
|
+
score: d._score
|
|
269
269
|
});
|
|
270
|
-
return e.sort((
|
|
270
|
+
return e.sort((d, r) => r.score - d.score), e;
|
|
271
271
|
}
|
|
272
272
|
async trajectory(t, i, o, n, a = !0, e = {}) {
|
|
273
|
-
var
|
|
274
|
-
const
|
|
275
|
-
let r =
|
|
276
|
-
const
|
|
273
|
+
var c, v, D;
|
|
274
|
+
const d = await this.realTimePosition(t, e);
|
|
275
|
+
let r = g(i);
|
|
276
|
+
const u = g(o), m = g();
|
|
277
277
|
if (a) {
|
|
278
|
-
let y =
|
|
279
|
-
y < 0 ? r =
|
|
278
|
+
let y = u.diff(r, "d", !0);
|
|
279
|
+
y < 0 ? r = u.clone().subtract(40, "d") : y < 30 ? r.subtract(10, "d") : y < 60 ? r.subtract(5, "d") : r = u.clone().subtract(80, "d"), y = m.diff(u, "d", !0), u.add(y > 10 ? 240 : y * 24, "h");
|
|
280
280
|
}
|
|
281
|
-
const
|
|
281
|
+
const f = {
|
|
282
282
|
searchParams: {
|
|
283
|
-
endtime:
|
|
283
|
+
endtime: u.utcOffset("+8:00").format("YYYY-MM-DD HH:mm:ss"),
|
|
284
284
|
starttime: r.utcOffset("+8:00").format("YYYY-MM-DD HH:mm:ss"),
|
|
285
285
|
mmsi: t,
|
|
286
286
|
usertoken: this.token
|
|
287
287
|
}
|
|
288
|
-
},
|
|
289
|
-
|
|
290
|
-
let
|
|
291
|
-
|
|
292
|
-
const
|
|
288
|
+
}, p = "https://api.hifleet.com/position/trajectory/nocompressed/withstatic/token", l = await O.get(p, f).json();
|
|
289
|
+
h == null || h.info("[%s] fetch trajectory from: %s - %j", e.requestId, p, f);
|
|
290
|
+
let Y;
|
|
291
|
+
l && (Y = ((v = (c = l.ships) == null ? void 0 : c.offors) == null ? void 0 : v.ship) || [], Y.length || h == null || h.warn("[%s] fetch trajectory failed: %j", e.requestId, l));
|
|
292
|
+
const k = [];
|
|
293
293
|
let b = -1;
|
|
294
|
-
const
|
|
295
|
-
for (const y of
|
|
294
|
+
const I = g(`${(D = Y == null ? void 0 : Y[0]) == null ? void 0 : D.ti} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
295
|
+
for (const y of Y) {
|
|
296
296
|
for (const L in y)
|
|
297
297
|
!isNaN(y[L]) && Number(y[L]) !== 1 / 0 && (y[L] = Number(y[L]));
|
|
298
|
-
const
|
|
298
|
+
const M = g(`${y.ti} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
299
299
|
y.status = y.sp > 4 ? 0 : 1;
|
|
300
|
-
const { labelEn:
|
|
300
|
+
const { labelEn: j, labelCn: F } = this.parseStatus(y.status), R = {
|
|
301
301
|
mmsi: y.m,
|
|
302
302
|
name: y.n,
|
|
303
|
-
imo:
|
|
303
|
+
imo: d == null ? void 0 : d.imo,
|
|
304
304
|
lat: y.la,
|
|
305
305
|
lng: y.lo,
|
|
306
306
|
draught: y.draught,
|
|
307
307
|
sog: y.sp,
|
|
308
308
|
cog: y.co,
|
|
309
309
|
hdg: y.hdg,
|
|
310
|
-
positionTime:
|
|
311
|
-
utc:
|
|
310
|
+
positionTime: M.unix(),
|
|
311
|
+
utc: M.utc().format(),
|
|
312
312
|
status: y.status,
|
|
313
313
|
labelCn: F,
|
|
314
|
-
labelEn:
|
|
314
|
+
labelEn: j,
|
|
315
315
|
method: "trajectory",
|
|
316
316
|
vendor: "hifleet"
|
|
317
|
-
}, H = Math.floor(
|
|
318
|
-
H !== b && (b = H,
|
|
317
|
+
}, H = Math.floor(M.diff(I, "minute", !0) / (n || 1));
|
|
318
|
+
H !== b && (b = H, k.push(R));
|
|
319
319
|
}
|
|
320
|
-
return
|
|
320
|
+
return k;
|
|
321
321
|
}
|
|
322
322
|
}
|
|
323
323
|
class wt extends K {
|
|
@@ -334,12 +334,12 @@ class wt extends K {
|
|
|
334
334
|
enc: 1
|
|
335
335
|
}
|
|
336
336
|
}, n = "https://api.shipxy.com/apicall/GetSingleShip", a = await O.get(n, o).json();
|
|
337
|
-
if (
|
|
337
|
+
if (h == null || h.info("[%s] fetch realtime position from: %s - %j", i.requestId, n, o), (a == null ? void 0 : a.status) !== 0)
|
|
338
338
|
return a;
|
|
339
339
|
const e = a.data[0];
|
|
340
|
-
for (const
|
|
341
|
-
!isNaN(e[
|
|
342
|
-
const { labelCn:
|
|
340
|
+
for (const f in e)
|
|
341
|
+
!isNaN(e[f]) && Number(e[f]) !== 1 / 0 && (e[f] = Number(e[f]));
|
|
342
|
+
const { labelCn: d, labelEn: r } = await this.parseStatus(e.navistat), u = g.unix(e.lasttime);
|
|
343
343
|
return {
|
|
344
344
|
mmsi: e.ShipID,
|
|
345
345
|
name: e.name,
|
|
@@ -355,46 +355,46 @@ class wt extends K {
|
|
|
355
355
|
hdg: Math.round(e.hdg / 100 * 100) / 100,
|
|
356
356
|
rot: Math.round(e.rot / 100 * 100) / 100,
|
|
357
357
|
positionTime: e.lasttime,
|
|
358
|
-
utc:
|
|
358
|
+
utc: u.utc().format(),
|
|
359
359
|
status: e.navistat,
|
|
360
360
|
labelEn: r,
|
|
361
|
-
labelCn:
|
|
361
|
+
labelCn: d,
|
|
362
362
|
method: "position",
|
|
363
363
|
vendor: "shipxy"
|
|
364
364
|
};
|
|
365
365
|
}
|
|
366
366
|
async trajectory(t, i, o, n, a = !0, e = {}) {
|
|
367
|
-
var
|
|
368
|
-
const
|
|
367
|
+
var I;
|
|
368
|
+
const d = await this.realTimePosition(t, e), r = g(i), u = g(o), m = "https://api.shipxy.com/apicall/GetShipTrack", f = {
|
|
369
369
|
searchParams: {
|
|
370
370
|
id: t,
|
|
371
371
|
k: this.token,
|
|
372
372
|
enc: 1,
|
|
373
373
|
cut: 0,
|
|
374
374
|
btm: r.unix(),
|
|
375
|
-
etm:
|
|
375
|
+
etm: u.unix()
|
|
376
376
|
}
|
|
377
|
-
},
|
|
378
|
-
if (
|
|
379
|
-
return
|
|
380
|
-
const
|
|
377
|
+
}, p = await O.get(m, f).json();
|
|
378
|
+
if (h == null || h.info("[%s] fetch trajectory from: %s - %j", e.requestId, m, f), (p == null ? void 0 : p.status) !== 0)
|
|
379
|
+
return p;
|
|
380
|
+
const l = p == null ? void 0 : p.points, Y = [], k = g.unix((I = l[0]) == null ? void 0 : I.utc);
|
|
381
381
|
let b = -1;
|
|
382
|
-
for (const
|
|
383
|
-
const
|
|
384
|
-
imo:
|
|
382
|
+
for (const c of l) {
|
|
383
|
+
const v = g.unix(c.utc), D = {
|
|
384
|
+
imo: d == null ? void 0 : d.imo,
|
|
385
385
|
mmsi: t,
|
|
386
|
-
sog: Math.round(
|
|
387
|
-
cog: Math.round(
|
|
388
|
-
lat: Math.round(
|
|
389
|
-
lng: Math.round(
|
|
390
|
-
positionTime:
|
|
391
|
-
utc:
|
|
386
|
+
sog: Math.round(c.sog * 3600 / 1e3 / 1852 * 100) / 100,
|
|
387
|
+
cog: Math.round(c.cog / 100 * 100) / 100,
|
|
388
|
+
lat: Math.round(c.lat / 1e6 * 1e5) / 1e5,
|
|
389
|
+
lng: Math.round(c.lon / 1e6 * 1e5) / 1e5,
|
|
390
|
+
positionTime: v.unix(),
|
|
391
|
+
utc: v.utc().format(),
|
|
392
392
|
method: "trajectory",
|
|
393
393
|
vendor: "shipxy"
|
|
394
|
-
}, y = Math.floor(
|
|
395
|
-
y !== b && (b = y,
|
|
394
|
+
}, y = Math.floor(v.diff(k, "minute", !0) / (n || 1));
|
|
395
|
+
y !== b && (b = y, Y.push(D));
|
|
396
396
|
}
|
|
397
|
-
return
|
|
397
|
+
return Y;
|
|
398
398
|
}
|
|
399
399
|
}
|
|
400
400
|
class Yt extends K {
|
|
@@ -412,7 +412,7 @@ class Yt extends K {
|
|
|
412
412
|
mmsiList: t
|
|
413
413
|
}
|
|
414
414
|
}, n = "https://api3.myships.com/sp/ships/getShipIdByMMSI", a = await O.post(n, o).json();
|
|
415
|
-
return
|
|
415
|
+
return h == null || h.info("[%s] fetch ship id from: %s - %j", i.requestId, n, o), a.code !== "0" ? a : a.data[0].shipId;
|
|
416
416
|
}
|
|
417
417
|
async getShipInfo(t, i = {}) {
|
|
418
418
|
const o = {
|
|
@@ -423,14 +423,14 @@ class Yt extends K {
|
|
|
423
423
|
shipId: t
|
|
424
424
|
}
|
|
425
425
|
}, n = "https://api3.myships.com/sp/ships/aissta", a = await O.post(n, o).json();
|
|
426
|
-
if (
|
|
426
|
+
if (h == null || h.info("[%s] fetch ship info from: %s - %j", i.requestId, n, o), a.code !== "0")
|
|
427
427
|
return a;
|
|
428
428
|
const e = a.data;
|
|
429
|
-
let
|
|
430
|
-
return t === "407170" && (
|
|
429
|
+
let d = e.imo;
|
|
430
|
+
return t === "407170" && (d = "9198379", h == null || h.warn("[%s] ship(%s) imo error: %s, should be %s", i.requestId, t, e.imo, d)), {
|
|
431
431
|
mmsi: e.mmsi,
|
|
432
432
|
name: e.shipnameEn,
|
|
433
|
-
imo:
|
|
433
|
+
imo: d,
|
|
434
434
|
callSign: e.callSign,
|
|
435
435
|
length: e.length,
|
|
436
436
|
width: e.breadth,
|
|
@@ -445,12 +445,12 @@ class Yt extends K {
|
|
|
445
445
|
json: {
|
|
446
446
|
shipId: o
|
|
447
447
|
}
|
|
448
|
-
}, e = "https://api3.myships.com/sp/ships/position/latest",
|
|
449
|
-
|
|
450
|
-
const r =
|
|
451
|
-
for (const
|
|
452
|
-
!isNaN(r[
|
|
453
|
-
const { labelCn:
|
|
448
|
+
}, e = "https://api3.myships.com/sp/ships/position/latest", d = await O.post(e, a).json();
|
|
449
|
+
h == null || h.info("[%s] fetch realtime position from: %s - %j", i.requestId, e, a);
|
|
450
|
+
const r = d.data[0];
|
|
451
|
+
for (const l in r)
|
|
452
|
+
!isNaN(r[l]) && Number(r[l]) !== 1 / 0 && (r[l] = Number(r[l]));
|
|
453
|
+
const { labelCn: u, labelEn: m } = await this.parseStatus(r.aisNavStatus), f = g.unix(r.posTime);
|
|
454
454
|
return {
|
|
455
455
|
...n,
|
|
456
456
|
mmsi: t,
|
|
@@ -461,23 +461,23 @@ class Yt extends K {
|
|
|
461
461
|
hdg: Math.round(r.heading * 100) / 100,
|
|
462
462
|
rot: Math.round(r.rot * 100) / 100,
|
|
463
463
|
positionTime: r.posTime,
|
|
464
|
-
utc:
|
|
464
|
+
utc: f.utc().format(),
|
|
465
465
|
status: r.aisNavStatus,
|
|
466
|
-
labelEn:
|
|
467
|
-
labelCn:
|
|
466
|
+
labelEn: m,
|
|
467
|
+
labelCn: u,
|
|
468
468
|
method: "position",
|
|
469
469
|
vendor: "myship"
|
|
470
470
|
};
|
|
471
471
|
}
|
|
472
472
|
async trajectory(t, i, o, n, a = !0, e = {}) {
|
|
473
|
-
const
|
|
474
|
-
for (; r.diff(
|
|
475
|
-
await this.trajectoryIn30Day(
|
|
476
|
-
return await this.trajectoryIn30Day(
|
|
473
|
+
const d = g(i), r = g(o), u = await this.getShipId(t), m = await this.getShipInfo(u), f = [];
|
|
474
|
+
for (; r.diff(d, "day", !0) > 30; )
|
|
475
|
+
await this.trajectoryIn30Day(u, d.unix(), d.add(30, "day").unix(), m, t, n, f);
|
|
476
|
+
return await this.trajectoryIn30Day(u, d.unix(), r.unix(), m, t, n, f), f;
|
|
477
477
|
}
|
|
478
|
-
async trajectoryIn30Day(t, i, o, n, a, e,
|
|
479
|
-
var
|
|
480
|
-
const
|
|
478
|
+
async trajectoryIn30Day(t, i, o, n, a, e, d, r = {}) {
|
|
479
|
+
var k;
|
|
480
|
+
const u = {
|
|
481
481
|
headers: {
|
|
482
482
|
appKey: this.token
|
|
483
483
|
},
|
|
@@ -486,16 +486,16 @@ class Yt extends K {
|
|
|
486
486
|
startTime: i,
|
|
487
487
|
endTime: o
|
|
488
488
|
}
|
|
489
|
-
},
|
|
490
|
-
if (
|
|
491
|
-
return
|
|
492
|
-
const
|
|
493
|
-
for (const b in
|
|
494
|
-
!isNaN(
|
|
495
|
-
const
|
|
496
|
-
let
|
|
497
|
-
for (const b of
|
|
498
|
-
const
|
|
489
|
+
}, m = "https://api3.myships.com/sp/ships/position/history", f = await O.post(m, u).json();
|
|
490
|
+
if (h == null || h.info("[%s] fetch trajectory from: %s - %j", r.requestId, m, u), f.code !== "0")
|
|
491
|
+
return h == null || h.warn("[%s] invoke myship trajectory failed: %j", r.requestId, f), f;
|
|
492
|
+
const p = f.data;
|
|
493
|
+
for (const b in p)
|
|
494
|
+
!isNaN(p[b]) && Number(p[b]) !== 1 / 0 && (p[b] = Number(p[b]));
|
|
495
|
+
const l = g.unix((k = p[0]) == null ? void 0 : k.posTime);
|
|
496
|
+
let Y = -1;
|
|
497
|
+
for (const b of p) {
|
|
498
|
+
const I = g.unix(b.posTime), c = {
|
|
499
499
|
imo: n == null ? void 0 : n.imo,
|
|
500
500
|
mmsi: a,
|
|
501
501
|
lat: Math.round(b.lat / 1e4 / 60 * 1e5) / 1e5,
|
|
@@ -504,14 +504,14 @@ class Yt extends K {
|
|
|
504
504
|
cog: Math.round(b.cog / 10 * 100) / 100,
|
|
505
505
|
hdg: Math.round(b.heading * 100) / 100,
|
|
506
506
|
rot: Math.round(b.rot * 100) / 100,
|
|
507
|
-
positionTime:
|
|
508
|
-
utc:
|
|
507
|
+
positionTime: I.unix(),
|
|
508
|
+
utc: I.utc().format(),
|
|
509
509
|
method: "trajectory",
|
|
510
510
|
vendor: "myship"
|
|
511
|
-
},
|
|
512
|
-
|
|
511
|
+
}, v = Math.floor(I.diff(l, "minute", !0) / (e || 1));
|
|
512
|
+
v !== Y && (Y = v, d.push(c));
|
|
513
513
|
}
|
|
514
|
-
return
|
|
514
|
+
return d;
|
|
515
515
|
}
|
|
516
516
|
}
|
|
517
517
|
let A;
|
|
@@ -520,7 +520,7 @@ try {
|
|
|
520
520
|
} catch {
|
|
521
521
|
} finally {
|
|
522
522
|
}
|
|
523
|
-
var it = /* @__PURE__ */ ((
|
|
523
|
+
var it = /* @__PURE__ */ ((w) => (w.NOTICE = "NOTICE", w.WARN = "WARN", w.HEAVY = "HEAVY", w.SEVERE = "SEVERE", w.ERROR = "ERROR", w.FATAL = "FATAL", w))(it || {});
|
|
524
524
|
class rt {
|
|
525
525
|
/**
|
|
526
526
|
* 解析告警规则, 多规则场景
|
|
@@ -531,20 +531,20 @@ class rt {
|
|
|
531
531
|
* @param options
|
|
532
532
|
*/
|
|
533
533
|
parsePrinciple(s, t = {}) {
|
|
534
|
-
var e,
|
|
534
|
+
var e, d, r;
|
|
535
535
|
A == null || A.info("[%s] parse rule: %s", t.requestId, s);
|
|
536
536
|
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(";");
|
|
537
537
|
if (!n)
|
|
538
538
|
return;
|
|
539
539
|
const a = {};
|
|
540
|
-
for (let
|
|
541
|
-
const
|
|
542
|
-
if (
|
|
540
|
+
for (let u = 0; u < (n == null ? void 0 : n.length); u++) {
|
|
541
|
+
const m = (r = (d = n[u].match(i)) == null ? void 0 : d[0]) == null ? void 0 : r.split("],");
|
|
542
|
+
if (u === 0 && !m)
|
|
543
543
|
a.scope = n[0];
|
|
544
|
-
else if (
|
|
545
|
-
for (let
|
|
546
|
-
const
|
|
547
|
-
|
|
544
|
+
else if (m)
|
|
545
|
+
for (let f = 0, p = m.length; f < p; f++) {
|
|
546
|
+
const l = this.parseRule(m[f]);
|
|
547
|
+
l && (a[l.level] ? l.key ? a[l.level][l == null ? void 0 : l.key] = l : a[l.level] = l : l.key ? a[l.level] = { [l == null ? void 0 : l.key]: l } : a[l.level] = l);
|
|
548
548
|
}
|
|
549
549
|
}
|
|
550
550
|
return a;
|
|
@@ -575,14 +575,14 @@ class rt {
|
|
|
575
575
|
* @param options
|
|
576
576
|
*/
|
|
577
577
|
checkWeather(s, t, i = {}) {
|
|
578
|
-
var
|
|
578
|
+
var l, Y, k, b, I, c, v, D, y, M, j, F, R, H, L;
|
|
579
579
|
let o = 0, n = 0, a = 0, e = 0;
|
|
580
|
-
const
|
|
580
|
+
const d = Math.round(((Y = (l = t == null ? void 0 : t.SEVERE) == null ? void 0 : l.sigWave) == null ? void 0 : Y.number) * 1.6 * 100) / 100, r = (b = (k = t == null ? void 0 : t.SEVERE) == null ? void 0 : k.sigWave) == null ? void 0 : b.number, u = (c = (I = t == null ? void 0 : t.HEAVY) == null ? void 0 : I.sigWave) == null ? void 0 : c.number, m = Math.round((((D = (v = t == null ? void 0 : t.SEVERE) == null ? void 0 : v.wind) == null ? void 0 : D.number) + 2) * 100) / 100, f = (M = (y = t == null ? void 0 : t.SEVERE) == null ? void 0 : y.wind) == null ? void 0 : M.number, p = (F = (j = t == null ? void 0 : t.HEAVY) == null ? void 0 : j.wind) == null ? void 0 : F.number;
|
|
581
581
|
for (let W = 0; W < (s == null ? void 0 : s.length); W++) {
|
|
582
|
-
const S = s[W], P = (H = (R = S == null ? void 0 : S.meteo) == null ? void 0 : R.wave) == null ? void 0 : H.sig, N = (L = S == null ? void 0 : S.meteo) == null ? void 0 : L.wind, E = W ?
|
|
583
|
-
e = E > e ? E : e, A == null || A.info("[%s] check sig.wave: %j", i.requestId, { ...P, dgThd4Wv:
|
|
582
|
+
const S = s[W], P = (H = (R = S == null ? void 0 : S.meteo) == null ? void 0 : R.wave) == null ? void 0 : H.sig, N = (L = S == null ? void 0 : S.meteo) == null ? void 0 : L.wind, E = W ? g(S.eta).diff(g(s[W - 1].eta), "hour", !0) : 0;
|
|
583
|
+
e = E > e ? E : e, A == null || A.info("[%s] check sig.wave: %j", i.requestId, { ...P, dgThd4Wv: d, svThd4Wv: r, hvThd4Wv: u }), (P == null ? void 0 : P.height) >= d ? S.isDangerous = !0 : (P == null ? void 0 : P.height) >= r ? S.isSevere = !0 : (P == null ? void 0 : P.height) >= u && (S.isHeavy = !0), A == null || A.info("[%s] check wind: %j", i.requestId, { ...N, dgThd4Wd: m, svThd4Wd: f, hvThd4Wd: p }), (N == null ? void 0 : N.scale) >= m ? (S.isDangerous = !0, delete S.isSevere, delete S.isHeavy) : (N == null ? void 0 : N.scale) > f ? (S.isDangerous || (S.isSevere = !0), delete S.isHeavy) : (N == null ? void 0 : N.scale) === p && !S.isDangerous && !S.isSevere && (S.isHeavy = !0), o += S.isDangerous ? E : 0, n += S.isSevere ? E : 0, a += S.isHeavy ? E : 0;
|
|
584
584
|
}
|
|
585
|
-
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:
|
|
585
|
+
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: m, svThd4Wd: f, hvThd4Wd: p }, sig: { dgThd4Wv: d, svThd4Wv: r, hvThd4Wv: u } };
|
|
586
586
|
}
|
|
587
587
|
}
|
|
588
588
|
const kt = new rt();
|
|
@@ -593,7 +593,7 @@ try {
|
|
|
593
593
|
} finally {
|
|
594
594
|
}
|
|
595
595
|
const ct = new ot("", !0);
|
|
596
|
-
var dt = /* @__PURE__ */ ((
|
|
596
|
+
var dt = /* @__PURE__ */ ((w) => (w.common = "common", w.container = "container", w.tugs = "tugs", w))(dt || {}), ut = /* @__PURE__ */ ((w) => (w.Ballast = "Ballast", w.Laden = "Laden", w))(ut || {}), ht = /* @__PURE__ */ ((w) => (w.Cp = "CP", w.Perf = "Basis", w.Instruct = "Other", w))(ht || {});
|
|
597
597
|
class C {
|
|
598
598
|
/**
|
|
599
599
|
* @see https://baike.baidu.com/item/%E6%96%B9%E5%BD%A2%E7%B3%BB%E6%95%B0/4965568?fr=aladdin
|
|
@@ -610,7 +610,7 @@ class C {
|
|
|
610
610
|
static blockCoefficient(s, t, i, o) {
|
|
611
611
|
let n = Math.round(s / (t * i * o) * 100) / 100;
|
|
612
612
|
n = n < 0.55 ? 0.55 : n > 0.85 ? 0.85 : n;
|
|
613
|
-
const a = [0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85], e = a.map((
|
|
613
|
+
const a = [0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85], e = a.map((d) => Math.abs(d - n));
|
|
614
614
|
return a[e.indexOf(Math.min(...e))];
|
|
615
615
|
}
|
|
616
616
|
/**
|
|
@@ -706,8 +706,8 @@ class C {
|
|
|
706
706
|
* @private
|
|
707
707
|
*/
|
|
708
708
|
static assembleProperties(s, t, i, o) {
|
|
709
|
-
var
|
|
710
|
-
const n = s.lbp ?? s.length ?? s.lengthOverall ?? 198.9642, a = s.draught ?? 8, e = s.breadthMoulded ?? s.breadth ?? s.breadthExtreme ?? 32.4572,
|
|
709
|
+
var f;
|
|
710
|
+
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, r = ((f = s == null ? void 0 : s.type) == null ? void 0 : f.toLowerCase()) || "common";
|
|
711
711
|
return {
|
|
712
712
|
tag: r.indexOf("container") > -1 ? "container" : r.indexOf("tugs") > -1 ? "tugs" : "common",
|
|
713
713
|
lbp: n,
|
|
@@ -716,7 +716,7 @@ class C {
|
|
|
716
716
|
breadthMoulded: e,
|
|
717
717
|
// 排水量(吨)= 载重量(吨)/ 1.025 + 吃水(米)× 船舶型宽(米)× 船舶型长(米)× 0.7
|
|
718
718
|
// 其中,1.025是指海水的密度,吨是指公吨,吃水是指船舶的最大吃水深度。船舶型宽是指船舶的最大型宽,船舶型长是指船舶的设计型长。上述公式是针对常规船舶适用的,不同类型的船舶可能会有一些差异。
|
|
719
|
-
displacement: Math.round((
|
|
719
|
+
displacement: Math.round((d / 1.025 + a * e * n * 0.7) * 1e4) / 1e4,
|
|
720
720
|
// 换算为m/s
|
|
721
721
|
speed: Math.round((i ?? 14.1382) * 1852 / 3600 * 1e4) / 1e4,
|
|
722
722
|
bearing: o || 90
|
|
@@ -732,25 +732,25 @@ class C {
|
|
|
732
732
|
* @param useMeteo true 启用气象分析
|
|
733
733
|
* @param useRouteParam true 启用设置速度
|
|
734
734
|
*/
|
|
735
|
-
static async speedLoseAt(s, t, i, o = "", n = 2, a = !0, e = !1,
|
|
735
|
+
static async speedLoseAt(s, t, i, o = "", n = 2, a = !0, e = !1, d = {}) {
|
|
736
736
|
let r;
|
|
737
737
|
if (t.velocity && e && (s.speed = B.roundPrecision(t.velocity * 1852 / 3600, 6)), a) {
|
|
738
|
-
let
|
|
739
|
-
if (
|
|
738
|
+
let u;
|
|
739
|
+
if (d.meteo2)
|
|
740
740
|
try {
|
|
741
|
-
const
|
|
742
|
-
|
|
743
|
-
} catch (
|
|
744
|
-
T.warn("[%s] meteo2 spot(%j) forecast failed: %s",
|
|
741
|
+
const l = await ct.spotForecast(t.lat, t.lng, i.utc().format(), !1, !1, !0, d), [Y] = tt.pickHourly(l, i);
|
|
742
|
+
u = tt.toLegacy(Y);
|
|
743
|
+
} catch (l) {
|
|
744
|
+
T.warn("[%s] meteo2 spot(%j) forecast failed: %s", d.requestId, { ...t, eta: i.utc().format() }, l);
|
|
745
745
|
}
|
|
746
746
|
else
|
|
747
|
-
|
|
748
|
-
const
|
|
747
|
+
u = await nt.queryPointFactor(t.lng, t.lat, i.valueOf(), "wind,wave,current,watertemp", o, d);
|
|
748
|
+
const m = C.weatherFactor(s, u), f = C.currentFactor(s.bearing, u == null ? void 0 : u.current, n), p = Math.round((s.speed * 1.943844 + m + f) * 100) / 100;
|
|
749
749
|
r = {
|
|
750
|
-
meteo: { ...
|
|
751
|
-
wxFactor:
|
|
752
|
-
cFactor:
|
|
753
|
-
speed: t.velocity && e ? t.velocity :
|
|
750
|
+
meteo: { ...u },
|
|
751
|
+
wxFactor: m,
|
|
752
|
+
cFactor: f,
|
|
753
|
+
speed: t.velocity && e ? t.velocity : p < 0 ? 1 : p,
|
|
754
754
|
eta: i.utc().format("YYYY-MM-DDTHH:mm[Z]"),
|
|
755
755
|
etd: i.utc().format("YYYY-MM-DDTHH:mm[Z]")
|
|
756
756
|
};
|
|
@@ -777,53 +777,53 @@ class C {
|
|
|
777
777
|
* @param useRouteParam true 启用航线上设置的参数 { suspend: 停留时长(小时), velocity: 速度(kts)}
|
|
778
778
|
* @private
|
|
779
779
|
*/
|
|
780
|
-
static async speedLoseInHoursStep(s, t, i, o, n, a, e = "",
|
|
780
|
+
static async speedLoseInHoursStep(s, t, i, o, n, a, e = "", d = !0, r = !1, u = {}) {
|
|
781
781
|
t.utc();
|
|
782
|
-
const f = [],
|
|
783
|
-
let
|
|
784
|
-
for (let
|
|
785
|
-
let
|
|
786
|
-
|
|
787
|
-
const
|
|
788
|
-
if (s.bearing = V.calculateBearing(
|
|
789
|
-
|
|
790
|
-
const
|
|
791
|
-
if (o -
|
|
792
|
-
o = o -
|
|
782
|
+
const m = g().add(14, "days"), f = [], p = [];
|
|
783
|
+
let l = 0, Y = 0, k, b;
|
|
784
|
+
for (let I = 0; I < a.length - 1; I++) {
|
|
785
|
+
let c = a[I];
|
|
786
|
+
c.distanceFromStart = n + Y;
|
|
787
|
+
const v = a[I + 1];
|
|
788
|
+
if (s.bearing = V.calculateBearing(c, v, !v.gcToPrevious), c.bearing = s.bearing, c.suspend && r) {
|
|
789
|
+
c.eta = c.eta || t.format("YYYY-MM-DDTHH:mm[Z]"), c.elapsed = c.elapsed ?? 0;
|
|
790
|
+
const M = c.suspend - c.elapsed;
|
|
791
|
+
if (o - l > M)
|
|
792
|
+
o = o - l - M, t.add(M, "hour"), c.elapsed = c.suspend;
|
|
793
793
|
else {
|
|
794
|
-
const
|
|
795
|
-
|
|
794
|
+
const j = o - l;
|
|
795
|
+
c.elapsed += j, t.add(j, "hour"), o = 0;
|
|
796
796
|
}
|
|
797
|
-
if (T == null || T.info(`[%s] suspend ${
|
|
798
|
-
return
|
|
797
|
+
if (T == null || T.info(`[%s] suspend ${c.elapsed} hours at %j, and remain ${o} hours need to go...`, u.requestId, c), o === 0)
|
|
798
|
+
return c.distanceFromPrevious = Y, { etd: t, from: b || c, to: c, next: a.filter((j) => j), wps: f, days: p };
|
|
799
799
|
} else
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
const
|
|
803
|
-
let
|
|
804
|
-
if (
|
|
805
|
-
if (
|
|
806
|
-
`[%s] go to %j from %j with ${
|
|
807
|
-
|
|
808
|
-
{ lat:
|
|
809
|
-
{ lat:
|
|
810
|
-
),
|
|
811
|
-
|
|
800
|
+
c.suspend = 0;
|
|
801
|
+
d = t.isAfter(m) ? !1 : d, c = await C.speedLoseAt(s, c, t, e, 0, d, r, u), b = b || c, c.important && f.push(c), t.isSameOrAfter(i) && (p.push(c), i.add(24, "hour"));
|
|
802
|
+
const D = V.calculateDistance(c, v, !v.gcToPrevious);
|
|
803
|
+
let y = Math.ceil(D / b.speed * 1e4) / 1e4;
|
|
804
|
+
if (l + y < o) {
|
|
805
|
+
if (l += y, t.add(y, "hour"), delete a[I], T == null || T.info(
|
|
806
|
+
`[%s] go to %j from %j with ${D}nm, and cost ${y} hours`,
|
|
807
|
+
u.requestId,
|
|
808
|
+
{ lat: v.lat, lng: v.lng },
|
|
809
|
+
{ lat: b.lat, lng: b.lng, etd: b.etd }
|
|
810
|
+
), Y += D, a.filter((M) => M).length <= 1) {
|
|
811
|
+
k = v, k.eta = t.format("YYYY-MM-DDTHH:mm[Z]"), k.distanceFromPrevious = D, k.distanceFromStart = n + Y, f.push(k), delete a[I + 1];
|
|
812
812
|
break;
|
|
813
813
|
}
|
|
814
814
|
} else {
|
|
815
|
-
|
|
816
|
-
const
|
|
817
|
-
|
|
818
|
-
`[%s] go to %j from %j with ${
|
|
819
|
-
|
|
820
|
-
{ lat:
|
|
821
|
-
{ lat:
|
|
822
|
-
),
|
|
815
|
+
y = o - l, t.add(y, "hour");
|
|
816
|
+
const M = B.roundPrecision(b.speed * y, 4);
|
|
817
|
+
k = V.calculateCoordinate(c, s.bearing, M, "nauticalmiles", !v.gcToPrevious), k.eta = t.format("YYYY-MM-DDTHH:mm[Z]"), a[I] = k, T == null || T.info(
|
|
818
|
+
`[%s] go to %j from %j with ${M}nm, and cost ${y} hours`,
|
|
819
|
+
u.requestId,
|
|
820
|
+
{ lat: k.lat, lng: k.lng },
|
|
821
|
+
{ lat: c.lat, lng: c.lng, etd: c.etd }
|
|
822
|
+
), Y += M, k.distanceFromPrevious = Y, k.distanceFromStart = n + Y;
|
|
823
823
|
break;
|
|
824
824
|
}
|
|
825
825
|
}
|
|
826
|
-
return { etd: t, from:
|
|
826
|
+
return { etd: t, from: b, to: k, next: a.filter((I) => I), wps: f, days: p };
|
|
827
827
|
}
|
|
828
828
|
/**
|
|
829
829
|
* 洋流影响因子
|
|
@@ -844,16 +844,16 @@ class C {
|
|
|
844
844
|
* @param wwc 气象要素
|
|
845
845
|
*/
|
|
846
846
|
static weatherFactor(s, t) {
|
|
847
|
-
var
|
|
847
|
+
var m, f, p, l, Y, k, b;
|
|
848
848
|
T == null || T.debug("calculate weather factor via: %j", { ...s, ...t });
|
|
849
849
|
const i = C.blockCoefficient(s.displacement, s.lbp, s.breadthMoulded, s.draught), o = C.froudeNumber(s.speed, s.lbp), n = C.amendFactor(i, o, s.loadCondition);
|
|
850
|
-
let a = Math.abs(s.bearing % 360 - (((
|
|
850
|
+
let a = Math.abs(s.bearing % 360 - (((m = t == null ? void 0 : t.wind) == null ? void 0 : m.degree) % 360 || 0));
|
|
851
851
|
a = a > 180 ? 360 - a : a;
|
|
852
|
-
const e = C.directionFactor(a, (
|
|
853
|
-
let r = e * n *
|
|
854
|
-
r = Math.round(r * 1.943844 * 1e4) / 1e4 * -1, s.tag === "tugs" && Math.abs(r) > 1 && (r = r / (Math.abs(Math.round(r)) + 1)), T == null || T.debug("wind wx factor = %d", r), a = Math.abs(s.bearing % 360 - (((
|
|
855
|
-
const
|
|
856
|
-
return T == null || T.debug("wave wx factor = %d",
|
|
852
|
+
const e = C.directionFactor(a, (f = t == null ? void 0 : t.wind) == null ? void 0 : f.scale), d = C.vesselTagFactor(s.displacement, s.loadCondition, s.tag, (p = t == null ? void 0 : t.wind) == null ? void 0 : p.scale);
|
|
853
|
+
let r = e * n * d / 100 * s.speed;
|
|
854
|
+
r = Math.round(r * 1.943844 * 1e4) / 1e4 * -1, s.tag === "tugs" && Math.abs(r) > 1 && (r = r / (Math.abs(Math.round(r)) + 1)), T == null || T.debug("wind wx factor = %d", r), a = Math.abs(s.bearing % 360 - (((Y = (l = t == null ? void 0 : t.wave) == null ? void 0 : l.sig) == null ? void 0 : Y.degree) % 360 || 0));
|
|
855
|
+
const u = C.waveHeightFactor(((b = (k = t == null ? void 0 : t.wave) == null ? void 0 : k.sig) == null ? void 0 : b.height) ?? 1, a);
|
|
856
|
+
return T == null || T.debug("wave wx factor = %d", u), r = r * 0.4 + u, T == null || T.debug("weather factor = %d", r), r = Math.abs(r) > 4 ? 4 * (Math.abs(r) / r) + Math.abs(r) / r * (Math.abs(r) - 4) * 0.1 : r, Math.round((r || 0) * 100) / 100;
|
|
857
857
|
}
|
|
858
858
|
/**
|
|
859
859
|
* 全程失速分析(走完航程)
|
|
@@ -867,14 +867,14 @@ class C {
|
|
|
867
867
|
* @param useMeteo true 启用气象分析
|
|
868
868
|
* @param useRouteParam
|
|
869
869
|
*/
|
|
870
|
-
static async analyseInstant(s, t, i, o, n, a = "", e = 0,
|
|
870
|
+
static async analyseInstant(s, t, i, o, n, a = "", e = 0, d = !0, r = !1, u = {}) {
|
|
871
871
|
var E, G, U, J, Q;
|
|
872
|
-
const
|
|
872
|
+
const m = g().valueOf();
|
|
873
873
|
s.lng = B.convertToStdLng(s.lng);
|
|
874
|
-
const { route:
|
|
875
|
-
if (((E =
|
|
874
|
+
const { route: f, waypoints: p } = n.points, l = V.calculateSubRoute(s, f);
|
|
875
|
+
if (((E = l[0]) == null ? void 0 : E.length) <= 1)
|
|
876
876
|
return;
|
|
877
|
-
const { v0:
|
|
877
|
+
const { v0: Y, label: k } = s.sog ? {
|
|
878
878
|
v0: s.sog,
|
|
879
879
|
label: "Other"
|
|
880
880
|
/* Instruct */
|
|
@@ -882,46 +882,46 @@ class C {
|
|
|
882
882
|
v0: o.speed,
|
|
883
883
|
label: "CP"
|
|
884
884
|
/* Cp */
|
|
885
|
-
}, b = C.assembleProperties(i, o.loadCondition,
|
|
886
|
-
|
|
887
|
-
const
|
|
885
|
+
}, b = C.assembleProperties(i, o.loadCondition, Y, 0), I = p.length ? V.calculateSubWaypoints(s, p) : [];
|
|
886
|
+
I.forEach((x) => x.important = !0);
|
|
887
|
+
const c = {
|
|
888
888
|
from: { ...s },
|
|
889
|
-
route:
|
|
890
|
-
waypoints:
|
|
891
|
-
v0:
|
|
892
|
-
label:
|
|
893
|
-
},
|
|
889
|
+
route: l,
|
|
890
|
+
waypoints: I,
|
|
891
|
+
v0: Y,
|
|
892
|
+
label: k
|
|
893
|
+
}, v = {
|
|
894
894
|
hours: [],
|
|
895
895
|
days: [],
|
|
896
896
|
wps: []
|
|
897
897
|
};
|
|
898
|
-
e || (V.calculateRouteDistance(
|
|
899
|
-
let
|
|
900
|
-
t =
|
|
898
|
+
e || (V.calculateRouteDistance(l) / o.speed <= 72 ? e = 3 : e = 6);
|
|
899
|
+
let D = V.simplifyRouteToCoordinates(l, I, 0), y = 0, M = 0, j = 0, F = 0;
|
|
900
|
+
t = g(t).utc();
|
|
901
901
|
const R = t.clone();
|
|
902
|
-
for (;
|
|
902
|
+
for (; D.length > 0; ) {
|
|
903
903
|
const x = e - t.hour() % e, _ = Math.ceil(t.clone().add(x, "h").set({ minute: 0, second: 0, millisecond: 0 }).diff(t, "h", !0) * 1e4) / 1e4, q = await C.speedLoseInHoursStep(
|
|
904
904
|
b,
|
|
905
905
|
t,
|
|
906
906
|
R,
|
|
907
907
|
_,
|
|
908
908
|
y,
|
|
909
|
-
|
|
909
|
+
D,
|
|
910
910
|
a,
|
|
911
|
-
|
|
911
|
+
d,
|
|
912
912
|
r,
|
|
913
|
-
|
|
913
|
+
u
|
|
914
914
|
);
|
|
915
|
-
(G = q.from) != null && G.speed && (
|
|
915
|
+
(G = q.from) != null && G.speed && (v.hours.push(q.from), v.wps.push(...q.wps), v.days.push(...q.days)), D = q == null ? void 0 : q.next, D.length || v.hours.push(q == null ? void 0 : q.to), y += ((U = q == null ? void 0 : q.to) == null ? void 0 : U.distanceFromPrevious) ?? 0;
|
|
916
916
|
}
|
|
917
|
-
const H =
|
|
917
|
+
const H = v.hours;
|
|
918
918
|
for (let x = 0; x < H.length - 1; x++) {
|
|
919
|
-
const _ =
|
|
920
|
-
|
|
919
|
+
const _ = g(H[x + 1].eta).diff(H[x].etd, "hour", !0) || 1;
|
|
920
|
+
M += (H[x].wxFactor || 0) * _, j += (H[x].cFactor || 0) * _, F += _;
|
|
921
921
|
}
|
|
922
|
-
(J =
|
|
922
|
+
(J = v.wps) == null || J.forEach((x, _) => {
|
|
923
923
|
if (_) {
|
|
924
|
-
const q =
|
|
924
|
+
const q = v.wps[_ - 1], et = x.distanceFromStart - q.distanceFromStart, X = g(x.eta).diff(g(q.etd), "h", !0);
|
|
925
925
|
if (X < 1)
|
|
926
926
|
x.avgSpd = q.speed;
|
|
927
927
|
else {
|
|
@@ -930,11 +930,11 @@ class C {
|
|
|
930
930
|
x.avgSpd = x.avgSpd > $ ? $ : x.avgSpd;
|
|
931
931
|
}
|
|
932
932
|
}
|
|
933
|
-
}),
|
|
934
|
-
const L =
|
|
935
|
-
|
|
936
|
-
const P =
|
|
937
|
-
return T == null || T.info("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms",
|
|
933
|
+
}), c.sample = v;
|
|
934
|
+
const L = v.hours.at(0), W = v.hours.at(-1);
|
|
935
|
+
c.distance = Math.round(W.distanceFromStart * 1e4) / 1e4, c.etd = g(L.eta).utc().format(), c.eta = g(W.eta).utc().format(), c.wxFactor = Math.round(M / F * 1e4) / 1e4, c.cFactor = Math.round(j / F * 1e4) / 1e4, c.avgSpeed = Math.round(W.distanceFromStart / F * 1e4) / 1e4, c.totalHrs = Math.round(F * 1e4) / 1e4, c.totalFoCons = Math.round((o == null ? void 0 : o.fo) / 24 * c.totalHrs * 1e3) / 1e3, c.totalDgoCons = Math.round((o == null ? void 0 : o.dgo) / 24 * c.totalHrs * 1e3) / 1e3;
|
|
936
|
+
const P = g().valueOf() - m, N = ((Q = v == null ? void 0 : v.hours) == null ? void 0 : Q.length) || 1;
|
|
937
|
+
return T == null || T.info("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms", u == null ? void 0 : u.requestId, P, N, Math.round(P / N * 1e3) / 1e3), c;
|
|
938
938
|
}
|
|
939
939
|
/**
|
|
940
940
|
* 分段失速分析(最多走hours 小时)
|
|
@@ -949,10 +949,10 @@ class C {
|
|
|
949
949
|
* @param useMeteo true 启用气象分析
|
|
950
950
|
* @param useRouteParam
|
|
951
951
|
*/
|
|
952
|
-
static async analyseInstantWithThreshed(s, t, i, o, n, a, e,
|
|
952
|
+
static async analyseInstantWithThreshed(s, t, i, o, n, a, e, d = "", r = 3, u = !0, m = !1, f = {}) {
|
|
953
953
|
var W, S, P;
|
|
954
954
|
s.lng = B.convertToStdLng(s.lng);
|
|
955
|
-
const { v0:
|
|
955
|
+
const { v0: p, label: l } = s.sog ? {
|
|
956
956
|
v0: s.sog,
|
|
957
957
|
label: "Other"
|
|
958
958
|
/* Instruct */
|
|
@@ -960,62 +960,64 @@ class C {
|
|
|
960
960
|
v0: n.speed,
|
|
961
961
|
label: "CP"
|
|
962
962
|
/* Cp */
|
|
963
|
-
},
|
|
964
|
-
if (((W =
|
|
963
|
+
}, Y = C.assembleProperties(o, n.loadCondition, p, 0), k = V.calculateSubRoute(s, a);
|
|
964
|
+
if (((W = k[0]) == null ? void 0 : W.length) <= 1)
|
|
965
965
|
return;
|
|
966
966
|
const b = e.length ? V.calculateSubWaypoints(s, e) : [];
|
|
967
967
|
b.forEach((N) => N.important = !0);
|
|
968
|
-
let
|
|
969
|
-
const
|
|
968
|
+
let I = V.simplifyRouteToCoordinates(k, b, 0), c = 0, v = 0, D = 0, y = 0, M;
|
|
969
|
+
const j = {
|
|
970
970
|
hours: [],
|
|
971
971
|
wps: [],
|
|
972
972
|
days: []
|
|
973
973
|
};
|
|
974
|
-
for (t =
|
|
974
|
+
for (t = g(t).utc(); I.length > 0; ) {
|
|
975
975
|
const N = r - t.hour() % r;
|
|
976
976
|
let E = Math.ceil(t.clone().add(N, "h").set({ minute: 0, second: 0, millisecond: 0 }).diff(t, "h", !0) * 1e4) / 1e4;
|
|
977
977
|
if (E = t.clone().add(E, "h").isAfter(i) ? i.diff(t, "h", !0) * 1e4 / 1e4 : E, E)
|
|
978
|
-
|
|
979
|
-
|
|
978
|
+
M = await C.speedLoseInHoursStep(
|
|
979
|
+
Y,
|
|
980
980
|
t,
|
|
981
981
|
i.clone(),
|
|
982
982
|
E,
|
|
983
|
-
l,
|
|
984
|
-
p,
|
|
985
983
|
c,
|
|
984
|
+
I,
|
|
986
985
|
d,
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
986
|
+
u,
|
|
987
|
+
m,
|
|
988
|
+
f
|
|
989
|
+
), (S = M.from) != null && S.speed && (j.hours.push(M.from), M != null && M.wps && j.wps.push(...M.wps), j.days.push(...M.days)), I = M == null ? void 0 : M.next, I.length || (j.hours.push(M == null ? void 0 : M.to), M != null && M.wps && j.wps.push(...M.wps), j.days.push(M == null ? void 0 : M.to)), c += ((P = M == null ? void 0 : M.to) == null ? void 0 : P.distanceFromPrevious) ?? 0;
|
|
990
990
|
else {
|
|
991
|
-
|
|
991
|
+
M && (j.hours.push(M.to), M != null && M.wps && j.wps.push(...M.wps), j.days.push(M.to));
|
|
992
992
|
break;
|
|
993
993
|
}
|
|
994
994
|
}
|
|
995
|
-
const F =
|
|
995
|
+
const F = j.hours;
|
|
996
996
|
for (let N = 0; N < F.length - 1; N++) {
|
|
997
|
-
const E =
|
|
998
|
-
|
|
997
|
+
const E = g(F[N + 1].eta).diff(F[N].etd, "hour", !0);
|
|
998
|
+
v += F[N].wxFactor * E, D += F[N].cFactor * E, y += E;
|
|
999
999
|
}
|
|
1000
|
-
const R =
|
|
1000
|
+
const R = j.hours.at(0), H = j.hours.at(-1);
|
|
1001
1001
|
return {
|
|
1002
|
-
sample:
|
|
1002
|
+
sample: j,
|
|
1003
1003
|
distance: Math.round(((H == null ? void 0 : H.distanceFromStart) || 0) * 1e4) / 1e4,
|
|
1004
1004
|
// 注意,可能会在first节点Drift,所有采用eta做为初始出发时间
|
|
1005
|
-
etd:
|
|
1006
|
-
eta:
|
|
1007
|
-
wxFactor: Math.round(
|
|
1008
|
-
cFactor: Math.round(
|
|
1005
|
+
etd: g(R.eta).utc().format(),
|
|
1006
|
+
eta: g(H == null ? void 0 : H.eta).utc().format(),
|
|
1007
|
+
wxFactor: Math.round(v / y * 1e4) / 1e4,
|
|
1008
|
+
cFactor: Math.round(D / y * 1e4) / 1e4,
|
|
1009
1009
|
avgSpeed: Math.round(((H == null ? void 0 : H.distanceFromStart) || 0) / y * 1e4) / 1e4,
|
|
1010
1010
|
totalHrs: Math.round(y * 1e4) / 1e4,
|
|
1011
1011
|
from: s,
|
|
1012
1012
|
to: H,
|
|
1013
|
-
route:
|
|
1013
|
+
route: k,
|
|
1014
1014
|
waypoints: b,
|
|
1015
|
-
v0:
|
|
1016
|
-
label:
|
|
1015
|
+
v0: p,
|
|
1016
|
+
label: l
|
|
1017
1017
|
};
|
|
1018
1018
|
}
|
|
1019
|
+
static async analyseCost(s, t, i, o, n = {}) {
|
|
1020
|
+
}
|
|
1019
1021
|
}
|
|
1020
1022
|
export {
|
|
1021
1023
|
K as AISImpl,
|
package/dist/index.umd.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(k,S){typeof exports=="object"&&typeof module<"u"?S(exports,require("got"),require("@log4js-node/log4js-api"),require("moment"),require("@idm-plugin/geo"),require("@idm-plugin/meteo2"),require("@idm-plugin/meteo")):typeof define=="function"&&define.amd?define(["exports","got","@log4js-node/log4js-api","moment","@idm-plugin/geo","@idm-plugin/meteo2","@idm-plugin/meteo"],S):(k=typeof globalThis<"u"?globalThis:k||self,S(k["idm-plugin-rabbitmq"]={},k.got,k["@log4js-node/log4js-api"],k.moment,k["@idm-plugin/geo"],k["@idm-plugin/meteo2"],k["@idm-plugin/meteo"]))})(this,function(k,S,Z,v,O,G,U){"use strict";var mt=Object.defineProperty;var pt=(k,S,Z)=>S in k?mt(k,S,{enumerable:!0,configurable:!0,writable:!0,value:Z}):k[S]=Z;var K=(k,S,Z)=>(pt(k,typeof S!="symbol"?S+"":S,Z),Z);let u;try{u=Z.getLogger("vessel")}catch{}finally{}class z{parseStatus(s){let t,i;switch(s){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 rt 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 S.post(i,n).json();u==null||u.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 d,f,M;(!this.token||v().diff(v(this.token.issuedAt),"seconds")>((d=this.token)==null?void 0:d.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} ${(M=this.token)==null?void 0:M.accessToken}`},searchParams:{mmsi:t}};u==null||u.info("[%s] fetch realtime position from: %s - %j",i.requestId,n,o);const a=await S.get(n,o).json();if(a.code)return u==null||u.warn("[%s] fetch realtime position failed: %j",i.requestId,n,{message:a.message,status:a.status,code:a.code}),a;const e=a.data;for(const m in e)!isNaN(e[m])&&Number(e[m])!==1/0&&(e[m]=Number(e[m]));const c=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:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(e.eta)?v.utc(e.eta).format():void 0,destination:e.dest,positionTime:c.unix(),status:e.status,labelCn:e.statusNameCn,labelEn:e.statusNameEn,method:"position",vendor:"myVessel",utc:c.utc().format()}}async trajectory(t,i,n,o,a=!0,e={}){(!this.token||v().diff(v(this.token.issuedAt),"seconds")>this.token.expiresIn-300)&&await this.authToken(e);const c=await this.realTimePosition(t,e),r=v(i),d=v(n),f=[];for(;d.diff(r,"day",!0)>30;)await this.trajectoryIn30Day(t,r,r.clone().add(30,"day"),c,o,f,e),r.add(30,"day");return await this.trajectoryIn30Day(t,r,d,c,o,f,e),f}async trajectoryIn30Day(t,i,n,o,a,e,c={}){var h,w,j,b,p;const r="https://svc.data.myvessel.cn/sdc/v1/vessels/status/track",d={headers:{Authorization:`${(h=this.token)==null?void 0:h.tokenType} ${(w=this.token)==null?void 0:w.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")}};u==null||u.info("[%s] fetch trajectory from: %s - %j",c.requestId,r,d);const f=await S.post(r,d).json();if(f.code)return u==null||u.warn("[%s] fetch trajectory failed: %j",c.requestId,r,{message:f.message,status:f.status,code:f.code}),f;let M=-1;const m=v(`${(b=(j=f.data)==null?void 0:j[0])==null?void 0:b.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return(p=f.data)==null||p.forEach(l=>{for(const W in l)!isNaN(l[W])&&Number(l[W])!==1/0&&(l[W]=Number(l[W]));const I=v(`${l.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00"),H=l.status,{labelCn:y,labelEn:g}=this.parseStatus(H),F={mmsi:l.mmsi,imo:o==null?void 0:o.imo,lat:l.lat,lng:l.lon,sog:l.sog,cog:l.cog,hdg:l.hdg,draught:l.draught,status:H,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(l.eta)?v(`${l.eta} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00").utc().format():void 0,destination:l.dest,positionTime:I.unix(),labelCn:y,labelEn:g,method:"trajectory",vendor:"myVessel",utc:I.utc().format()},E=Math.floor(I.diff(m,"minute",!0)/(a||1));E!==M&&(M=E,e.push(F))}),e}}class ct 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}},a=await S.post(n,o).json();u==null||u.info("[%s] fetch realtime position from: %s - %j",i.requestId,n,o);const e=a==null?void 0:a.list;if(!e)return u==null||u.warn("[%s] fetch realtime position failed: %j",i.requestId,n,a),a;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 c=e.status,{labelCn:r,labelEn:d}=this.parseStatus(c),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.utc(e.eta).format():void 0,destination:e.destination,positionTime:f.unix(),utc:f.utc().format(),status:c,labelCn:r,labelEn:d,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 a=await S.post(n,o).json();u==null||u.info("[%s] fetch vessel props from: %s - %j",i.requestId,n,o),a instanceof Array&&(a=a[0]);for(const c in a)!isNaN(a[c])&&Number(a[c])!==1/0&&(a[c]=Number(a[c]));const e={mmsi:a.m,name:a.n,imo:a.i,callSign:a.c,length:a.l,breadth:a.b,draught:a.dr,type:a.t};return n="https://www.hifleet.com/hifleetapi/sameShipSearch.do",a=await S.post(n,o).json(),u==null||u.info("[%s] search vessel dead weight from: %s - %j",i.requestId,n,o),a instanceof Array&&(a=a[0]),a&&(e.deadweight=Number(a.dwt)),e}async suggest(t,i={}){const n="https://www.hifleet.com/hifleetapi/getShipSuggest.do",o={searchParams:{q:t},headers:{Referer:"https://www.hifleet.com",Origin:"https://www.hifleet.com",Host:"www.hifleet.com"}},a=await S.post(n,o).json();u==null||u.info("[%s] suggest vessel props from: %s - %j",i.requestId,n,o);const e=[];for(const c of a)e.push({mmsi:!c.mmsi||isNaN(c.mmsi)?null:Number(c.mmsi),name:c.name,callSign:c.callsign,imo:!c.imo||isNaN(c.imo)?null:Number(c.imo),score:c._score});return e.sort((c,r)=>r.score-c.score),e}async trajectory(t,i,n,o,a=!0,e={}){var l,I,H;const c=await this.realTimePosition(t,e);let r=v(i);const d=v(n),f=v();if(a){let y=d.diff(r,"d",!0);y<0?r=d.clone().subtract(40,"d"):y<30?r.subtract(10,"d"):y<60?r.subtract(5,"d"):r=d.clone().subtract(80,"d"),y=f.diff(d,"d",!0),d.add(y>10?240:y*24,"h")}const M={searchParams:{endtime:d.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}},m="https://api.hifleet.com/position/trajectory/nocompressed/withstatic/token",h=await S.get(m,M).json();u==null||u.info("[%s] fetch trajectory from: %s - %j",e.requestId,m,M);let w;h&&(w=((I=(l=h.ships)==null?void 0:l.offors)==null?void 0:I.ship)||[],w.length||u==null||u.warn("[%s] fetch trajectory failed: %j",e.requestId,h));const j=[];let b=-1;const p=v(`${(H=w==null?void 0:w[0])==null?void 0:H.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");for(const y of w){for(const _ in y)!isNaN(y[_])&&Number(y[_])!==1/0&&(y[_]=Number(y[_]));const g=v(`${y.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");y.status=y.sp>4?0:1;const{labelEn:F,labelCn:E}=this.parseStatus(y.status),W={mmsi:y.m,name:y.n,imo:c==null?void 0:c.imo,lat:y.la,lng:y.lo,draught:y.draught,sog:y.sp,cog:y.co,hdg:y.hdg,positionTime:g.unix(),utc:g.utc().format(),status:y.status,labelCn:E,labelEn:F,method:"trajectory",vendor:"hifleet"},q=Math.floor(g.diff(p,"minute",!0)/(o||1));q!==b&&(b=q,j.push(W))}return j}}class dt 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",a=await S.get(o,n).json();if(u==null||u.info("[%s] fetch realtime position from: %s - %j",i.requestId,o,n),(a==null?void 0:a.status)!==0)return a;const e=a.data[0];for(const M in e)!isNaN(e[M])&&Number(e[M])!==1/0&&(e[M]=Number(e[M]));const{labelCn:c,labelEn:r}=await this.parseStatus(e.navistat),d=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:d.utc().format(),status:e.navistat,labelEn:r,labelCn:c,method:"position",vendor:"shipxy"}}async trajectory(t,i,n,o,a=!0,e={}){var p;const c=await this.realTimePosition(t,e),r=v(i),d=v(n),f="https://api.shipxy.com/apicall/GetShipTrack",M={searchParams:{id:t,k:this.token,enc:1,cut:0,btm:r.unix(),etm:d.unix()}},m=await S.get(f,M).json();if(u==null||u.info("[%s] fetch trajectory from: %s - %j",e.requestId,f,M),(m==null?void 0:m.status)!==0)return m;const h=m==null?void 0:m.points,w=[],j=v.unix((p=h[0])==null?void 0:p.utc);let b=-1;for(const l of h){const I=v.unix(l.utc),H={imo:c==null?void 0:c.imo,mmsi:t,sog:Math.round(l.sog*3600/1e3/1852*100)/100,cog:Math.round(l.cog/100*100)/100,lat:Math.round(l.lat/1e6*1e5)/1e5,lng:Math.round(l.lon/1e6*1e5)/1e5,positionTime:I.unix(),utc:I.utc().format(),method:"trajectory",vendor:"shipxy"},y=Math.floor(I.diff(j,"minute",!0)/(o||1));y!==b&&(b=y,w.push(H))}return w}}class ut 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",a=await S.post(o,n).json();return u==null||u.info("[%s] fetch ship id from: %s - %j",i.requestId,o,n),a.code!=="0"?a:a.data[0].shipId}async getShipInfo(t,i={}){const n={headers:{appKey:this.token},json:{shipId:t}},o="https://api3.myships.com/sp/ships/aissta",a=await S.post(o,n).json();if(u==null||u.info("[%s] fetch ship info from: %s - %j",i.requestId,o,n),a.code!=="0")return a;const e=a.data;let c=e.imo;return t==="407170"&&(c="9198379",u==null||u.warn("[%s] ship(%s) imo error: %s, should be %s",i.requestId,t,e.imo,c)),{mmsi:e.mmsi,name:e.shipnameEn,imo:c,callSign:e.callSign,length:e.length,width:e.breadth,draught:(e.draught||100)/10}}async realTimePosition(t,i={}){const n=await this.getShipId(t,i),o=await this.getShipInfo(n,i),a={headers:{appKey:this.token},json:{shipId:n}},e="https://api3.myships.com/sp/ships/position/latest",c=await S.post(e,a).json();u==null||u.info("[%s] fetch realtime position from: %s - %j",i.requestId,e,a);const r=c.data[0];for(const h in r)!isNaN(r[h])&&Number(r[h])!==1/0&&(r[h]=Number(r[h]));const{labelCn:d,labelEn:f}=await this.parseStatus(r.aisNavStatus),M=v.unix(r.posTime);return{...o,mmsi:t,lat:Math.round(r.lat/1e4/60*1e5)/1e5,lng:Math.round(r.lon/1e4/60*1e5)/1e5,sog:Math.round(r.sog/10*100)/100,cog:Math.round(r.cog/10*100)/100,hdg:Math.round(r.heading*100)/100,rot:Math.round(r.rot*100)/100,positionTime:r.posTime,utc:M.utc().format(),status:r.aisNavStatus,labelEn:f,labelCn:d,method:"position",vendor:"myship"}}async trajectory(t,i,n,o,a=!0,e={}){const c=v(i),r=v(n),d=await this.getShipId(t),f=await this.getShipInfo(d),M=[];for(;r.diff(c,"day",!0)>30;)await this.trajectoryIn30Day(d,c.unix(),c.add(30,"day").unix(),f,t,o,M);return await this.trajectoryIn30Day(d,c.unix(),r.unix(),f,t,o,M),M}async trajectoryIn30Day(t,i,n,o,a,e,c,r={}){var j;const d={headers:{appKey:this.token},json:{shipId:t,startTime:i,endTime:n}},f="https://api3.myships.com/sp/ships/position/history",M=await S.post(f,d).json();if(u==null||u.info("[%s] fetch trajectory from: %s - %j",r.requestId,f,d),M.code!=="0")return u==null||u.warn("[%s] invoke myship trajectory failed: %j",r.requestId,M),M;const m=M.data;for(const b in m)!isNaN(m[b])&&Number(m[b])!==1/0&&(m[b]=Number(m[b]));const h=v.unix((j=m[0])==null?void 0:j.posTime);let w=-1;for(const b of m){const p=v.unix(b.posTime),l={imo:o==null?void 0:o.imo,mmsi:a,lat:Math.round(b.lat/1e4/60*1e5)/1e5,lng:Math.round(b.lon/1e4/60*1e5)/1e5,sog:Math.round(b.sog/10*100)/100,cog:Math.round(b.cog/10*100)/100,hdg:Math.round(b.heading*100)/100,rot:Math.round(b.rot*100)/100,positionTime:p.unix(),utc:p.utc().format(),method:"trajectory",vendor:"myship"},I=Math.floor(p.diff(h,"minute",!0)/(e||1));I!==w&&(w=I,c.push(l))}return c}}let R;try{R=Z.getLogger("vessel")}catch{}finally{}var J=(Y=>(Y.NOTICE="NOTICE",Y.WARN="WARN",Y.HEAVY="HEAVY",Y.SEVERE="SEVERE",Y.ERROR="ERROR",Y.FATAL="FATAL",Y))(J||{});class Q{parsePrinciple(s,t={}){var e,c,r;R==null||R.info("[%s] parse rule: %s",t.requestId,s);const i=new RegExp("(?<=\\[)(.+)(?=])","g"),n=s.match(i)?(e=s.match(i))==null?void 0:e[0]:void 0,o=n==null?void 0:n.split(";");if(!o)return;const a={};for(let d=0;d<(o==null?void 0:o.length);d++){const f=(r=(c=o[d].match(i))==null?void 0:c[0])==null?void 0:r.split("],");if(d===0&&!f)a.scope=o[0];else if(f)for(let M=0,m=f.length;M<m;M++){const h=this.parseRule(f[M]);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)}}return a}parseRule(s,t={}){var a;R==null||R.info("[%s] parse rule: %s",t.requestId,s),s=s.startsWith("[")?s:`[${s}`,s=s.endsWith("]")?s:`${s}]`;const i=new RegExp("(?<=\\[)(.+?)(?=])","g"),n=(a=s==null?void 0:s.match(i))==null?void 0:a[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(s,t,i={}){var h,w,j,b,p,l,I,H,y,g,F,E,W,q,_;let n=0,o=0,a=0,e=0;const c=Math.round(((w=(h=t==null?void 0:t.SEVERE)==null?void 0:h.sigWave)==null?void 0:w.number)*1.6*100)/100,r=(b=(j=t==null?void 0:t.SEVERE)==null?void 0:j.sigWave)==null?void 0:b.number,d=(l=(p=t==null?void 0:t.HEAVY)==null?void 0:p.sigWave)==null?void 0:l.number,f=Math.round((((H=(I=t==null?void 0:t.SEVERE)==null?void 0:I.wind)==null?void 0:H.number)+2)*100)/100,M=(g=(y=t==null?void 0:t.SEVERE)==null?void 0:y.wind)==null?void 0:g.number,m=(E=(F=t==null?void 0:t.HEAVY)==null?void 0:F.wind)==null?void 0:E.number;for(let V=0;V<(s==null?void 0:s.length);V++){const N=s[V],C=(q=(W=N==null?void 0:N.meteo)==null?void 0:W.wave)==null?void 0:q.sig,D=(_=N==null?void 0:N.meteo)==null?void 0:_.wind,P=V?v(N.eta).diff(v(s[V-1].eta),"hour",!0):0;e=P>e?P:e,R==null||R.info("[%s] check sig.wave: %j",i.requestId,{...C,dgThd4Wv:c,svThd4Wv:r,hvThd4Wv:d}),(C==null?void 0:C.height)>=c?N.isDangerous=!0:(C==null?void 0:C.height)>=r?N.isSevere=!0:(C==null?void 0:C.height)>=d&&(N.isHeavy=!0),R==null||R.info("[%s] check wind: %j",i.requestId,{...D,dgThd4Wd:f,svThd4Wd:M,hvThd4Wd:m}),(D==null?void 0:D.scale)>=f?(N.isDangerous=!0,delete N.isSevere,delete N.isHeavy):(D==null?void 0:D.scale)>M?(N.isDangerous||(N.isSevere=!0),delete N.isHeavy):(D==null?void 0:D.scale)===m&&!N.isDangerous&&!N.isSevere&&(N.isHeavy=!0),n+=N.isDangerous?P:0,o+=N.isSevere?P:0,a+=N.isHeavy?P:0}return n=Math.round(n*100)/100,o=Math.round(o*100)/100,a=Math.round(a*100)/100,e=Math.round(e),{sample:s,dangerous:n,severe:o,heavy:a,step:e<3?3:e,wind:{dgThd4Wd:f,svThd4Wd:M,hvThd4Wd:m},sig:{dgThd4Wv:c,svThd4Wv:r,hvThd4Wv:d}}}}const ht=new Q;let T;try{T=Z.getLogger("vessel")}catch{}finally{}const lt=new G.MeteoHelper2("",!0);var X=(Y=>(Y.common="common",Y.container="container",Y.tugs="tugs",Y))(X||{}),$=(Y=>(Y.Ballast="Ballast",Y.Laden="Laden",Y))($||{}),tt=(Y=>(Y.Cp="CP",Y.Perf="Basis",Y.Instruct="Other",Y))(tt||{});class A{static blockCoefficient(s,t,i,n){let o=Math.round(s/(t*i*n)*100)/100;o=o<.55?.55:o>.85?.85:o;const a=[.55,.6,.65,.7,.75,.8,.85],e=a.map(c=>Math.abs(c-o));return a[e.indexOf(Math.min(...e))]}static froudeNumber(s,t,i=9.8){let n=Math.round(Math.sqrt(s*s/(i*t))*100)/100;return n=n<.05?.05:n>.3?.3:n,n}static amendFactor(s,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 a={.55:[1.7,-1.4,-7.4],.6:[2.2,-2.5,-9.7],.65:[2.6,-3.7,-11.6],.7:[3.1,-5.3,-12.4],.75:[2.6,-12.5,-13.5],.8:[3,-16.3,-21.6],.85:[3.4,-20.9,31.8]}[s];return i==="Laden"&&(a=n[s]),a[0]+a[1]*t+a[2]*Math.pow(t,2)}static directionFactor(s,t=0){let i;return s>30&&s<=60?i=(1.7-.03*Math.pow(t-4,2))/2:s>60&&s<=150?i=(.9-.06*Math.pow(t-6,2))/2:s>150&&s<=180?i=(.4-.03*Math.pow(t-8,2))/2:i=1,Math.round(i*1e5)/1e5}static vesselTagFactor(s,t,i,n=0){n=n>6?n-.9*(n-6):n;let o;return i==="container"?o=.7*n+Math.pow(n,6.5)/(22*Math.pow(s,2/3)):t==="Ballast"?o=.7*n+Math.pow(n,6.5)/(2.7*Math.pow(s,2/3)):o=.5*n+Math.pow(n,6.5)/(2.7*Math.pow(s,2/3)),o}static waveHeightFactor(s,t){s=s<0?.2:s,s=s>6?s-.9*(s-6):s,s=s>9?9:s;let i;return t>30&&t<=60?i=-.6:t>60&&t<=90?i=-.4:t>90&&t<=120?i=s<3?.4:-.3:t>120&&t<=150?i=s<3?.6:-.5:t>150&&t<=180?i=s<3?.7:-.6:i=-.7,Math.round(i*(.144*Math.pow(s,2)+.178*s)*1e4)/1e4}static assembleProperties(s,t,i,n){var M;const o=s.lbp??s.length??s.lengthOverall??198.9642,a=s.draught??8,e=s.breadthMoulded??s.breadth??s.breadthExtreme??32.4572,c=s.deadweight??67035.7773,r=((M=s==null?void 0:s.type)==null?void 0:M.toLowerCase())||"common";return{tag:r.indexOf("container")>-1?"container":r.indexOf("tugs")>-1?"tugs":"common",lbp:o,loadCondition:t,draught:a,breadthMoulded:e,displacement:Math.round((c/1.025+a*e*o*.7)*1e4)/1e4,speed:Math.round((i??14.1382)*1852/3600*1e4)/1e4,bearing:n||90}}static async speedLoseAt(s,t,i,n="",o=2,a=!0,e=!1,c={}){let r;if(t.velocity&&e&&(s.speed=O.LngLatHelper.roundPrecision(t.velocity*1852/3600,6)),a){let d;if(c.meteo2)try{const h=await lt.spotForecast(t.lat,t.lng,i.utc().format(),!1,!1,!0,c),[w]=U.Meteo2Assist.pickHourly(h,i);d=U.Meteo2Assist.toLegacy(w)}catch(h){T.warn("[%s] meteo2 spot(%j) forecast failed: %s",c.requestId,{...t,eta:i.utc().format()},h)}else d=await G.MeteoHelper.queryPointFactor(t.lng,t.lat,i.valueOf(),"wind,wave,current,watertemp",n,c);const f=A.weatherFactor(s,d),M=A.currentFactor(s.bearing,d==null?void 0:d.current,o),m=Math.round((s.speed*1.943844+f+M)*100)/100;r={meteo:{...d},wxFactor:f,cFactor:M,speed:t.velocity&&e?t.velocity:m<0?1:m,eta:i.utc().format("YYYY-MM-DDTHH:mm[Z]"),etd:i.utc().format("YYYY-MM-DDTHH:mm[Z]")}}else r={wxFactor:0,cFactor:0,speed:t.velocity&&e?t.velocity:Math.round((s.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,{...r,...t}}static async speedLoseInHoursStep(s,t,i,n,o,a,e="",c=!0,r=!1,d={}){t.utc();const f=[],M=[];let m=0,h=0,w,j;for(let b=0;b<a.length-1;b++){let p=a[b];p.distanceFromStart=o+h;const l=a[b+1];if(s.bearing=O.LaneHelper.calculateBearing(p,l,!l.gcToPrevious),p.bearing=s.bearing,p.suspend&&r){p.eta=p.eta||t.format("YYYY-MM-DDTHH:mm[Z]"),p.elapsed=p.elapsed??0;const y=p.suspend-p.elapsed;if(n-m>y)n=n-m-y,t.add(y,"hour"),p.elapsed=p.suspend;else{const g=n-m;p.elapsed+=g,t.add(g,"hour"),n=0}if(T==null||T.info(`[%s] suspend ${p.elapsed} hours at %j, and remain ${n} hours need to go...`,d.requestId,p),n===0)return p.distanceFromPrevious=h,{etd:t,from:j||p,to:p,next:a.filter(g=>g),wps:f,days:M}}else p.suspend=0;p=await A.speedLoseAt(s,p,t,e,0,c,r,d),j=j||p,p.important&&f.push(p),t.isSameOrAfter(i)&&(M.push(p),i.add(24,"hour"));const I=O.LaneHelper.calculateDistance(p,l,!l.gcToPrevious);let H=Math.ceil(I/j.speed*1e4)/1e4;if(m+H<n){if(m+=H,t.add(H,"hour"),delete a[b],T==null||T.info(`[%s] go to %j from %j with ${I}nm, and cost ${H} hours`,d.requestId,{lat:l.lat,lng:l.lng},{lat:j.lat,lng:j.lng,etd:j.etd}),h+=I,a.filter(y=>y).length<=1){w=l,w.eta=t.format("YYYY-MM-DDTHH:mm[Z]"),w.distanceFromPrevious=I,w.distanceFromStart=o+h,f.push(w),delete a[b+1];break}}else{H=n-m,t.add(H,"hour");const y=O.LngLatHelper.roundPrecision(j.speed*H,4);w=O.LaneHelper.calculateCoordinate(p,s.bearing,y,"nauticalmiles",!l.gcToPrevious),w.eta=t.format("YYYY-MM-DDTHH:mm[Z]"),a[b]=w,T==null||T.info(`[%s] go to %j from %j with ${y}nm, and cost ${H} hours`,d.requestId,{lat:w.lat,lng:w.lng},{lat:p.lat,lng:p.lng,etd:p.etd}),h+=y,w.distanceFromPrevious=h,w.distanceFromStart=o+h;break}}return{etd:t,from:j,to:w,next:a.filter(b=>b),wps:f,days:M}}static currentFactor(s,t,i=0){const n=(s-(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(s,t){var f,M,m,h,w,j,b;T==null||T.debug("calculate weather factor via: %j",{...s,...t});const i=A.blockCoefficient(s.displacement,s.lbp,s.breadthMoulded,s.draught),n=A.froudeNumber(s.speed,s.lbp),o=A.amendFactor(i,n,s.loadCondition);let a=Math.abs(s.bearing%360-(((f=t==null?void 0:t.wind)==null?void 0:f.degree)%360||0));a=a>180?360-a:a;const e=A.directionFactor(a,(M=t==null?void 0:t.wind)==null?void 0:M.scale),c=A.vesselTagFactor(s.displacement,s.loadCondition,s.tag,(m=t==null?void 0:t.wind)==null?void 0:m.scale);let r=e*o*c/100*s.speed;r=Math.round(r*1.943844*1e4)/1e4*-1,s.tag==="tugs"&&Math.abs(r)>1&&(r=r/(Math.abs(Math.round(r))+1)),T==null||T.debug("wind wx factor = %d",r),a=Math.abs(s.bearing%360-(((w=(h=t==null?void 0:t.wave)==null?void 0:h.sig)==null?void 0:w.degree)%360||0));const d=A.waveHeightFactor(((b=(j=t==null?void 0:t.wave)==null?void 0:j.sig)==null?void 0:b.height)??1,a);return T==null||T.debug("wave wx factor = %d",d),r=r*.4+d,T==null||T.debug("weather factor = %d",r),r=Math.abs(r)>4?4*(Math.abs(r)/r)+Math.abs(r)/r*(Math.abs(r)-4)*.1:r,Math.round((r||0)*100)/100}static async analyseInstant(s,t,i,n,o,a="",e=0,c=!0,r=!1,d={}){var P,et,st,at,nt;const f=v().valueOf();s.lng=O.LngLatHelper.convertToStdLng(s.lng);const{route:M,waypoints:m}=o.points,h=O.LaneHelper.calculateSubRoute(s,M);if(((P=h[0])==null?void 0:P.length)<=1)return;const{v0:w,label:j}=s.sog?{v0:s.sog,label:"Other"}:{v0:n.speed,label:"CP"},b=A.assembleProperties(i,n.loadCondition,w,0),p=m.length?O.LaneHelper.calculateSubWaypoints(s,m):[];p.forEach(x=>x.important=!0);const l={from:{...s},route:h,waypoints:p,v0:w,label:j},I={hours:[],days:[],wps:[]};e||(O.LaneHelper.calculateRouteDistance(h)/n.speed<=72?e=3:e=6);let H=O.LaneHelper.simplifyRouteToCoordinates(h,p,0),y=0,g=0,F=0,E=0;t=v(t).utc();const W=t.clone();for(;H.length>0;){const x=e-t.hour()%e,B=Math.ceil(t.clone().add(x,"h").set({minute:0,second:0,millisecond:0}).diff(t,"h",!0)*1e4)/1e4,L=await A.speedLoseInHoursStep(b,t,W,B,y,H,a,c,r,d);(et=L.from)!=null&&et.speed&&(I.hours.push(L.from),I.wps.push(...L.wps),I.days.push(...L.days)),H=L==null?void 0:L.next,H.length||I.hours.push(L==null?void 0:L.to),y+=((st=L==null?void 0:L.to)==null?void 0:st.distanceFromPrevious)??0}const q=I.hours;for(let x=0;x<q.length-1;x++){const B=v(q[x+1].eta).diff(q[x].etd,"hour",!0)||1;g+=(q[x].wxFactor||0)*B,F+=(q[x].cFactor||0)*B,E+=B}(at=I.wps)==null||at.forEach((x,B)=>{if(B){const L=I.wps[B-1],ft=x.distanceFromStart-L.distanceFromStart,ot=v(x.eta).diff(v(L.etd),"h",!0);if(ot<1)x.avgSpd=L.speed;else{x.avgSpd=Math.round(ft/ot*100)/100;const it=Math.round((L.speed+x.speed)/2*100)/100;x.avgSpd=x.avgSpd>it?it:x.avgSpd}}}),l.sample=I;const _=I.hours.at(0),V=I.hours.at(-1);l.distance=Math.round(V.distanceFromStart*1e4)/1e4,l.etd=v(_.eta).utc().format(),l.eta=v(V.eta).utc().format(),l.wxFactor=Math.round(g/E*1e4)/1e4,l.cFactor=Math.round(F/E*1e4)/1e4,l.avgSpeed=Math.round(V.distanceFromStart/E*1e4)/1e4,l.totalHrs=Math.round(E*1e4)/1e4,l.totalFoCons=Math.round((n==null?void 0:n.fo)/24*l.totalHrs*1e3)/1e3,l.totalDgoCons=Math.round((n==null?void 0:n.dgo)/24*l.totalHrs*1e3)/1e3;const C=v().valueOf()-f,D=((nt=I==null?void 0:I.hours)==null?void 0:nt.length)||1;return T==null||T.info("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms",d==null?void 0:d.requestId,C,D,Math.round(C/D*1e3)/1e3),l}static async analyseInstantWithThreshed(s,t,i,n,o,a,e,c="",r=3,d=!0,f=!1,M={}){var V,N,C;s.lng=O.LngLatHelper.convertToStdLng(s.lng);const{v0:m,label:h}=s.sog?{v0:s.sog,label:"Other"}:{v0:o.speed,label:"CP"},w=A.assembleProperties(n,o.loadCondition,m,0),j=O.LaneHelper.calculateSubRoute(s,a);if(((V=j[0])==null?void 0:V.length)<=1)return;const b=e.length?O.LaneHelper.calculateSubWaypoints(s,e):[];b.forEach(D=>D.important=!0);let p=O.LaneHelper.simplifyRouteToCoordinates(j,b,0),l=0,I=0,H=0,y=0,g;const F={hours:[],wps:[],days:[]};for(t=v(t).utc();p.length>0;){const D=r-t.hour()%r;let P=Math.ceil(t.clone().add(D,"h").set({minute:0,second:0,millisecond:0}).diff(t,"h",!0)*1e4)/1e4;if(P=t.clone().add(P,"h").isAfter(i)?i.diff(t,"h",!0)*1e4/1e4:P,P)g=await A.speedLoseInHoursStep(w,t,i.clone(),P,l,p,c,d,f,M),(N=g.from)!=null&&N.speed&&(F.hours.push(g.from),g!=null&&g.wps&&F.wps.push(...g.wps),F.days.push(...g.days)),p=g==null?void 0:g.next,p.length||(F.hours.push(g==null?void 0:g.to),g!=null&&g.wps&&F.wps.push(...g.wps),F.days.push(g==null?void 0:g.to)),l+=((C=g==null?void 0:g.to)==null?void 0:C.distanceFromPrevious)??0;else{g&&(F.hours.push(g.to),g!=null&&g.wps&&F.wps.push(...g.wps),F.days.push(g.to));break}}const E=F.hours;for(let D=0;D<E.length-1;D++){const P=v(E[D+1].eta).diff(E[D].etd,"hour",!0);I+=E[D].wxFactor*P,H+=E[D].cFactor*P,y+=P}const W=F.hours.at(0),q=F.hours.at(-1);return{sample:F,distance:Math.round(((q==null?void 0:q.distanceFromStart)||0)*1e4)/1e4,etd:v(W.eta).utc().format(),eta:v(q==null?void 0:q.eta).utc().format(),wxFactor:Math.round(I/y*1e4)/1e4,cFactor:Math.round(H/y*1e4)/1e4,avgSpeed:Math.round(((q==null?void 0:q.distanceFromStart)||0)/y*1e4)/1e4,totalHrs:Math.round(y*1e4)/1e4,from:s,to:q,route:j,waypoints:b,v0:m,label:h}}}k.AISImpl=z,k.AlertHelper=Q,k.AlertLevel=J,k.HifleetImpl=ct,k.LoadCondition=$,k.MyShipImpl=ut,k.MyVesselImpl=rt,k.ShipxyImpl=dt,k.SpeedHelper=A,k.SpeedLabel=tt,k.VesselTag=X,k.alertHelper=ht,Object.defineProperty(k,Symbol.toStringTag,{value:"Module"})});
|
|
1
|
+
(function(k,S){typeof exports=="object"&&typeof module<"u"?S(exports,require("got"),require("@log4js-node/log4js-api"),require("moment"),require("@idm-plugin/geo"),require("@idm-plugin/meteo2"),require("@idm-plugin/meteo")):typeof define=="function"&&define.amd?define(["exports","got","@log4js-node/log4js-api","moment","@idm-plugin/geo","@idm-plugin/meteo2","@idm-plugin/meteo"],S):(k=typeof globalThis<"u"?globalThis:k||self,S(k["idm-plugin-rabbitmq"]={},k.got,k["@log4js-node/log4js-api"],k.moment,k["@idm-plugin/geo"],k["@idm-plugin/meteo2"],k["@idm-plugin/meteo"]))})(this,function(k,S,Z,g,O,G,U){"use strict";var mt=Object.defineProperty;var pt=(k,S,Z)=>S in k?mt(k,S,{enumerable:!0,configurable:!0,writable:!0,value:Z}):k[S]=Z;var K=(k,S,Z)=>(pt(k,typeof S!="symbol"?S+"":S,Z),Z);let h;try{h=Z.getLogger("vessel")}catch{}finally{}class z{parseStatus(s){let t,i;switch(s){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 rt 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 S.post(i,n).json();h==null||h.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 u,m,f;(!this.token||g().diff(g(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:`${(m=this.token)==null?void 0:m.tokenType} ${(f=this.token)==null?void 0:f.accessToken}`},searchParams:{mmsi:t}};h==null||h.info("[%s] fetch realtime position from: %s - %j",i.requestId,n,o);const a=await S.get(n,o).json();if(a.code)return h==null||h.warn("[%s] fetch realtime position failed: %j",i.requestId,n,{message:a.message,status:a.status,code:a.code}),a;const e=a.data;for(const p in e)!isNaN(e[p])&&Number(e[p])!==1/0&&(e[p]=Number(e[p]));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:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(e.eta)?g.utc(e.eta).format():void 0,destination:e.dest,positionTime: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,a=!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),u=g(n),m=[];for(;u.diff(r,"day",!0)>30;)await this.trajectoryIn30Day(t,r,r.clone().add(30,"day"),d,o,m,e),r.add(30,"day");return await this.trajectoryIn30Day(t,r,u,d,o,m,e),m}async trajectoryIn30Day(t,i,n,o,a,e,d={}){var l,w,I,v,j;const r="https://svc.data.myvessel.cn/sdc/v1/vessels/status/track",u={headers:{Authorization:`${(l=this.token)==null?void 0:l.tokenType} ${(w=this.token)==null?void 0:w.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")}};h==null||h.info("[%s] fetch trajectory from: %s - %j",d.requestId,r,u);const m=await S.post(r,u).json();if(m.code)return h==null||h.warn("[%s] fetch trajectory failed: %j",d.requestId,r,{message:m.message,status:m.status,code:m.code}),m;let f=-1;const p=g(`${(v=(I=m.data)==null?void 0:I[0])==null?void 0:v.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return(j=m.data)==null||j.forEach(c=>{for(const W in c)!isNaN(c[W])&&Number(c[W])!==1/0&&(c[W]=Number(c[W]));const b=g(`${c.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00"),F=c.status,{labelCn:M,labelEn:y}=this.parseStatus(F),H={mmsi:c.mmsi,imo:o==null?void 0:o.imo,lat:c.lat,lng:c.lon,sog:c.sog,cog:c.cog,hdg:c.hdg,draught:c.draught,status:F,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(c.eta)?g(`${c.eta} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00").utc().format():void 0,destination:c.dest,positionTime:b.unix(),labelCn:M,labelEn:y,method:"trajectory",vendor:"myVessel",utc:b.utc().format()},E=Math.floor(b.diff(p,"minute",!0)/(a||1));E!==f&&(f=E,e.push(H))}),e}}class ct 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}},a=await S.post(n,o).json();h==null||h.info("[%s] fetch realtime position from: %s - %j",i.requestId,n,o);const e=a==null?void 0:a.list;if(!e)return h==null||h.warn("[%s] fetch realtime position failed: %j",i.requestId,n,a),a;for(const p in e)!isNaN(e[p])&&Number(e[p])!==1/0&&(e[p]=Number(e[p]));e.status=e.sp>3?0:1;const d=e.status,{labelCn:r,labelEn:u}=this.parseStatus(d),m=g(`${e.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return{mmsi:e.m,name:e.n,imo:e.imonumber,callSign:e.callsign,lat:Math.round(e.la/60*1e5)/1e5,lng:Math.round(e.lo/60*1e5)/1e5,length:e.l,width:e.w,draught:e.draught,sog:e.sp,cog:e.co,hdg:e.h,rot:isNaN(e.rot)?0:e.rot,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(e.eta)?g.utc(e.eta).format():void 0,destination:e.destination,positionTime:m.unix(),utc:m.utc().format(),status:d,labelCn:r,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 a=await S.post(n,o).json();h==null||h.info("[%s] fetch vessel props from: %s - %j",i.requestId,n,o),a instanceof Array&&(a=a[0]);for(const d in a)!isNaN(a[d])&&Number(a[d])!==1/0&&(a[d]=Number(a[d]));const e={mmsi:a.m,name:a.n,imo:a.i,callSign:a.c,length:a.l,breadth:a.b,draught:a.dr,type:a.t};return n="https://www.hifleet.com/hifleetapi/sameShipSearch.do",a=await S.post(n,o).json(),h==null||h.info("[%s] search vessel dead weight from: %s - %j",i.requestId,n,o),a instanceof Array&&(a=a[0]),a&&(e.deadweight=Number(a.dwt)),e}async suggest(t,i={}){const n="https://www.hifleet.com/hifleetapi/getShipSuggest.do",o={searchParams:{q:t},headers:{Referer:"https://www.hifleet.com",Origin:"https://www.hifleet.com",Host:"www.hifleet.com"}},a=await S.post(n,o).json();h==null||h.info("[%s] suggest vessel props from: %s - %j",i.requestId,n,o);const e=[];for(const d of a)e.push({mmsi:!d.mmsi||isNaN(d.mmsi)?null:Number(d.mmsi),name:d.name,callSign:d.callsign,imo:!d.imo||isNaN(d.imo)?null:Number(d.imo),score:d._score});return e.sort((d,r)=>r.score-d.score),e}async trajectory(t,i,n,o,a=!0,e={}){var c,b,F;const d=await this.realTimePosition(t,e);let r=g(i);const u=g(n),m=g();if(a){let M=u.diff(r,"d",!0);M<0?r=u.clone().subtract(40,"d"):M<30?r.subtract(10,"d"):M<60?r.subtract(5,"d"):r=u.clone().subtract(80,"d"),M=m.diff(u,"d",!0),u.add(M>10?240:M*24,"h")}const f={searchParams:{endtime:u.utcOffset("+8:00").format("YYYY-MM-DD HH:mm:ss"),starttime:r.utcOffset("+8:00").format("YYYY-MM-DD HH:mm:ss"),mmsi:t,usertoken:this.token}},p="https://api.hifleet.com/position/trajectory/nocompressed/withstatic/token",l=await S.get(p,f).json();h==null||h.info("[%s] fetch trajectory from: %s - %j",e.requestId,p,f);let w;l&&(w=((b=(c=l.ships)==null?void 0:c.offors)==null?void 0:b.ship)||[],w.length||h==null||h.warn("[%s] fetch trajectory failed: %j",e.requestId,l));const I=[];let v=-1;const j=g(`${(F=w==null?void 0:w[0])==null?void 0:F.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");for(const M of w){for(const _ in M)!isNaN(M[_])&&Number(M[_])!==1/0&&(M[_]=Number(M[_]));const y=g(`${M.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");M.status=M.sp>4?0:1;const{labelEn:H,labelCn:E}=this.parseStatus(M.status),W={mmsi:M.m,name:M.n,imo:d==null?void 0:d.imo,lat:M.la,lng:M.lo,draught:M.draught,sog:M.sp,cog:M.co,hdg:M.hdg,positionTime:y.unix(),utc:y.utc().format(),status:M.status,labelCn:E,labelEn:H,method:"trajectory",vendor:"hifleet"},q=Math.floor(y.diff(j,"minute",!0)/(o||1));q!==v&&(v=q,I.push(W))}return I}}class dt 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",a=await S.get(o,n).json();if(h==null||h.info("[%s] fetch realtime position from: %s - %j",i.requestId,o,n),(a==null?void 0:a.status)!==0)return a;const e=a.data[0];for(const f in e)!isNaN(e[f])&&Number(e[f])!==1/0&&(e[f]=Number(e[f]));const{labelCn:d,labelEn:r}=await this.parseStatus(e.navistat),u=g.unix(e.lasttime);return{mmsi:e.ShipID,name:e.name,imo:e.imo,callSign:e.callsign,lat:Math.round(e.lat/1e6*1e5)/1e5,lng:Math.round(e.lon/1e6*1e5)/1e5,length:Math.round(e.length/10*100)/100,width:Math.round(e.width/10*100)/100,draught:Math.round(e.draught/1e3*100)/100,sog:Math.round(e.sog*3600/1e3/1852*100)/100,cog:Math.round(e.cog/100*100)/100,hdg:Math.round(e.hdg/100*100)/100,rot:Math.round(e.rot/100*100)/100,positionTime:e.lasttime,utc:u.utc().format(),status:e.navistat,labelEn:r,labelCn:d,method:"position",vendor:"shipxy"}}async trajectory(t,i,n,o,a=!0,e={}){var j;const d=await this.realTimePosition(t,e),r=g(i),u=g(n),m="https://api.shipxy.com/apicall/GetShipTrack",f={searchParams:{id:t,k:this.token,enc:1,cut:0,btm:r.unix(),etm:u.unix()}},p=await S.get(m,f).json();if(h==null||h.info("[%s] fetch trajectory from: %s - %j",e.requestId,m,f),(p==null?void 0:p.status)!==0)return p;const l=p==null?void 0:p.points,w=[],I=g.unix((j=l[0])==null?void 0:j.utc);let v=-1;for(const c of l){const b=g.unix(c.utc),F={imo:d==null?void 0:d.imo,mmsi:t,sog:Math.round(c.sog*3600/1e3/1852*100)/100,cog:Math.round(c.cog/100*100)/100,lat:Math.round(c.lat/1e6*1e5)/1e5,lng:Math.round(c.lon/1e6*1e5)/1e5,positionTime:b.unix(),utc:b.utc().format(),method:"trajectory",vendor:"shipxy"},M=Math.floor(b.diff(I,"minute",!0)/(o||1));M!==v&&(v=M,w.push(F))}return w}}class ut 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",a=await S.post(o,n).json();return h==null||h.info("[%s] fetch ship id from: %s - %j",i.requestId,o,n),a.code!=="0"?a:a.data[0].shipId}async getShipInfo(t,i={}){const n={headers:{appKey:this.token},json:{shipId:t}},o="https://api3.myships.com/sp/ships/aissta",a=await S.post(o,n).json();if(h==null||h.info("[%s] fetch ship info from: %s - %j",i.requestId,o,n),a.code!=="0")return a;const e=a.data;let d=e.imo;return t==="407170"&&(d="9198379",h==null||h.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),a={headers:{appKey:this.token},json:{shipId:n}},e="https://api3.myships.com/sp/ships/position/latest",d=await S.post(e,a).json();h==null||h.info("[%s] fetch realtime position from: %s - %j",i.requestId,e,a);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:u,labelEn:m}=await this.parseStatus(r.aisNavStatus),f=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:f.utc().format(),status:r.aisNavStatus,labelEn:m,labelCn:u,method:"position",vendor:"myship"}}async trajectory(t,i,n,o,a=!0,e={}){const d=g(i),r=g(n),u=await this.getShipId(t),m=await this.getShipInfo(u),f=[];for(;r.diff(d,"day",!0)>30;)await this.trajectoryIn30Day(u,d.unix(),d.add(30,"day").unix(),m,t,o,f);return await this.trajectoryIn30Day(u,d.unix(),r.unix(),m,t,o,f),f}async trajectoryIn30Day(t,i,n,o,a,e,d,r={}){var I;const u={headers:{appKey:this.token},json:{shipId:t,startTime:i,endTime:n}},m="https://api3.myships.com/sp/ships/position/history",f=await S.post(m,u).json();if(h==null||h.info("[%s] fetch trajectory from: %s - %j",r.requestId,m,u),f.code!=="0")return h==null||h.warn("[%s] invoke myship trajectory failed: %j",r.requestId,f),f;const p=f.data;for(const v in p)!isNaN(p[v])&&Number(p[v])!==1/0&&(p[v]=Number(p[v]));const l=g.unix((I=p[0])==null?void 0:I.posTime);let w=-1;for(const v of p){const j=g.unix(v.posTime),c={imo:o==null?void 0:o.imo,mmsi:a,lat:Math.round(v.lat/1e4/60*1e5)/1e5,lng:Math.round(v.lon/1e4/60*1e5)/1e5,sog:Math.round(v.sog/10*100)/100,cog:Math.round(v.cog/10*100)/100,hdg:Math.round(v.heading*100)/100,rot:Math.round(v.rot*100)/100,positionTime:j.unix(),utc:j.utc().format(),method:"trajectory",vendor:"myship"},b=Math.floor(j.diff(l,"minute",!0)/(e||1));b!==w&&(w=b,d.push(c))}return d}}let R;try{R=Z.getLogger("vessel")}catch{}finally{}var J=(Y=>(Y.NOTICE="NOTICE",Y.WARN="WARN",Y.HEAVY="HEAVY",Y.SEVERE="SEVERE",Y.ERROR="ERROR",Y.FATAL="FATAL",Y))(J||{});class Q{parsePrinciple(s,t={}){var e,d,r;R==null||R.info("[%s] parse rule: %s",t.requestId,s);const i=new RegExp("(?<=\\[)(.+)(?=])","g"),n=s.match(i)?(e=s.match(i))==null?void 0:e[0]:void 0,o=n==null?void 0:n.split(";");if(!o)return;const a={};for(let u=0;u<(o==null?void 0:o.length);u++){const m=(r=(d=o[u].match(i))==null?void 0:d[0])==null?void 0:r.split("],");if(u===0&&!m)a.scope=o[0];else if(m)for(let f=0,p=m.length;f<p;f++){const l=this.parseRule(m[f]);l&&(a[l.level]?l.key?a[l.level][l==null?void 0:l.key]=l:a[l.level]=l:l.key?a[l.level]={[l==null?void 0:l.key]:l}:a[l.level]=l)}}return a}parseRule(s,t={}){var a;R==null||R.info("[%s] parse rule: %s",t.requestId,s),s=s.startsWith("[")?s:`[${s}`,s=s.endsWith("]")?s:`${s}]`;const i=new RegExp("(?<=\\[)(.+?)(?=])","g"),n=(a=s==null?void 0:s.match(i))==null?void 0:a[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(s,t,i={}){var l,w,I,v,j,c,b,F,M,y,H,E,W,q,_;let n=0,o=0,a=0,e=0;const d=Math.round(((w=(l=t==null?void 0:t.SEVERE)==null?void 0:l.sigWave)==null?void 0:w.number)*1.6*100)/100,r=(v=(I=t==null?void 0:t.SEVERE)==null?void 0:I.sigWave)==null?void 0:v.number,u=(c=(j=t==null?void 0:t.HEAVY)==null?void 0:j.sigWave)==null?void 0:c.number,m=Math.round((((F=(b=t==null?void 0:t.SEVERE)==null?void 0:b.wind)==null?void 0:F.number)+2)*100)/100,f=(y=(M=t==null?void 0:t.SEVERE)==null?void 0:M.wind)==null?void 0:y.number,p=(E=(H=t==null?void 0:t.HEAVY)==null?void 0:H.wind)==null?void 0:E.number;for(let V=0;V<(s==null?void 0:s.length);V++){const N=s[V],C=(q=(W=N==null?void 0:N.meteo)==null?void 0:W.wave)==null?void 0:q.sig,D=(_=N==null?void 0:N.meteo)==null?void 0:_.wind,P=V?g(N.eta).diff(g(s[V-1].eta),"hour",!0):0;e=P>e?P:e,R==null||R.info("[%s] check sig.wave: %j",i.requestId,{...C,dgThd4Wv:d,svThd4Wv:r,hvThd4Wv:u}),(C==null?void 0:C.height)>=d?N.isDangerous=!0:(C==null?void 0:C.height)>=r?N.isSevere=!0:(C==null?void 0:C.height)>=u&&(N.isHeavy=!0),R==null||R.info("[%s] check wind: %j",i.requestId,{...D,dgThd4Wd:m,svThd4Wd:f,hvThd4Wd:p}),(D==null?void 0:D.scale)>=m?(N.isDangerous=!0,delete N.isSevere,delete N.isHeavy):(D==null?void 0:D.scale)>f?(N.isDangerous||(N.isSevere=!0),delete N.isHeavy):(D==null?void 0:D.scale)===p&&!N.isDangerous&&!N.isSevere&&(N.isHeavy=!0),n+=N.isDangerous?P:0,o+=N.isSevere?P:0,a+=N.isHeavy?P:0}return n=Math.round(n*100)/100,o=Math.round(o*100)/100,a=Math.round(a*100)/100,e=Math.round(e),{sample:s,dangerous:n,severe:o,heavy:a,step:e<3?3:e,wind:{dgThd4Wd:m,svThd4Wd:f,hvThd4Wd:p},sig:{dgThd4Wv:d,svThd4Wv:r,hvThd4Wv:u}}}}const ht=new Q;let T;try{T=Z.getLogger("vessel")}catch{}finally{}const lt=new G.MeteoHelper2("",!0);var X=(Y=>(Y.common="common",Y.container="container",Y.tugs="tugs",Y))(X||{}),$=(Y=>(Y.Ballast="Ballast",Y.Laden="Laden",Y))($||{}),tt=(Y=>(Y.Cp="CP",Y.Perf="Basis",Y.Instruct="Other",Y))(tt||{});class A{static blockCoefficient(s,t,i,n){let o=Math.round(s/(t*i*n)*100)/100;o=o<.55?.55:o>.85?.85:o;const a=[.55,.6,.65,.7,.75,.8,.85],e=a.map(d=>Math.abs(d-o));return a[e.indexOf(Math.min(...e))]}static froudeNumber(s,t,i=9.8){let n=Math.round(Math.sqrt(s*s/(i*t))*100)/100;return n=n<.05?.05:n>.3?.3:n,n}static amendFactor(s,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 a={.55:[1.7,-1.4,-7.4],.6:[2.2,-2.5,-9.7],.65:[2.6,-3.7,-11.6],.7:[3.1,-5.3,-12.4],.75:[2.6,-12.5,-13.5],.8:[3,-16.3,-21.6],.85:[3.4,-20.9,31.8]}[s];return i==="Laden"&&(a=n[s]),a[0]+a[1]*t+a[2]*Math.pow(t,2)}static directionFactor(s,t=0){let i;return s>30&&s<=60?i=(1.7-.03*Math.pow(t-4,2))/2:s>60&&s<=150?i=(.9-.06*Math.pow(t-6,2))/2:s>150&&s<=180?i=(.4-.03*Math.pow(t-8,2))/2:i=1,Math.round(i*1e5)/1e5}static vesselTagFactor(s,t,i,n=0){n=n>6?n-.9*(n-6):n;let o;return i==="container"?o=.7*n+Math.pow(n,6.5)/(22*Math.pow(s,2/3)):t==="Ballast"?o=.7*n+Math.pow(n,6.5)/(2.7*Math.pow(s,2/3)):o=.5*n+Math.pow(n,6.5)/(2.7*Math.pow(s,2/3)),o}static waveHeightFactor(s,t){s=s<0?.2:s,s=s>6?s-.9*(s-6):s,s=s>9?9:s;let i;return t>30&&t<=60?i=-.6:t>60&&t<=90?i=-.4:t>90&&t<=120?i=s<3?.4:-.3:t>120&&t<=150?i=s<3?.6:-.5:t>150&&t<=180?i=s<3?.7:-.6:i=-.7,Math.round(i*(.144*Math.pow(s,2)+.178*s)*1e4)/1e4}static assembleProperties(s,t,i,n){var f;const o=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,r=((f=s==null?void 0:s.type)==null?void 0:f.toLowerCase())||"common";return{tag:r.indexOf("container")>-1?"container":r.indexOf("tugs")>-1?"tugs":"common",lbp:o,loadCondition:t,draught:a,breadthMoulded:e,displacement:Math.round((d/1.025+a*e*o*.7)*1e4)/1e4,speed:Math.round((i??14.1382)*1852/3600*1e4)/1e4,bearing:n||90}}static async speedLoseAt(s,t,i,n="",o=2,a=!0,e=!1,d={}){let r;if(t.velocity&&e&&(s.speed=O.LngLatHelper.roundPrecision(t.velocity*1852/3600,6)),a){let u;if(d.meteo2)try{const l=await lt.spotForecast(t.lat,t.lng,i.utc().format(),!1,!1,!0,d),[w]=U.Meteo2Assist.pickHourly(l,i);u=U.Meteo2Assist.toLegacy(w)}catch(l){T.warn("[%s] meteo2 spot(%j) forecast failed: %s",d.requestId,{...t,eta:i.utc().format()},l)}else u=await G.MeteoHelper.queryPointFactor(t.lng,t.lat,i.valueOf(),"wind,wave,current,watertemp",n,d);const m=A.weatherFactor(s,u),f=A.currentFactor(s.bearing,u==null?void 0:u.current,o),p=Math.round((s.speed*1.943844+m+f)*100)/100;r={meteo:{...u},wxFactor:m,cFactor:f,speed:t.velocity&&e?t.velocity:p<0?1:p,eta:i.utc().format("YYYY-MM-DDTHH:mm[Z]"),etd:i.utc().format("YYYY-MM-DDTHH:mm[Z]")}}else r={wxFactor:0,cFactor:0,speed:t.velocity&&e?t.velocity:Math.round((s.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,{...r,...t}}static async speedLoseInHoursStep(s,t,i,n,o,a,e="",d=!0,r=!1,u={}){t.utc();const m=g().add(14,"days"),f=[],p=[];let l=0,w=0,I,v;for(let j=0;j<a.length-1;j++){let c=a[j];c.distanceFromStart=o+w;const b=a[j+1];if(s.bearing=O.LaneHelper.calculateBearing(c,b,!b.gcToPrevious),c.bearing=s.bearing,c.suspend&&r){c.eta=c.eta||t.format("YYYY-MM-DDTHH:mm[Z]"),c.elapsed=c.elapsed??0;const y=c.suspend-c.elapsed;if(n-l>y)n=n-l-y,t.add(y,"hour"),c.elapsed=c.suspend;else{const H=n-l;c.elapsed+=H,t.add(H,"hour"),n=0}if(T==null||T.info(`[%s] suspend ${c.elapsed} hours at %j, and remain ${n} hours need to go...`,u.requestId,c),n===0)return c.distanceFromPrevious=w,{etd:t,from:v||c,to:c,next:a.filter(H=>H),wps:f,days:p}}else c.suspend=0;d=t.isAfter(m)?!1:d,c=await A.speedLoseAt(s,c,t,e,0,d,r,u),v=v||c,c.important&&f.push(c),t.isSameOrAfter(i)&&(p.push(c),i.add(24,"hour"));const F=O.LaneHelper.calculateDistance(c,b,!b.gcToPrevious);let M=Math.ceil(F/v.speed*1e4)/1e4;if(l+M<n){if(l+=M,t.add(M,"hour"),delete a[j],T==null||T.info(`[%s] go to %j from %j with ${F}nm, and cost ${M} hours`,u.requestId,{lat:b.lat,lng:b.lng},{lat:v.lat,lng:v.lng,etd:v.etd}),w+=F,a.filter(y=>y).length<=1){I=b,I.eta=t.format("YYYY-MM-DDTHH:mm[Z]"),I.distanceFromPrevious=F,I.distanceFromStart=o+w,f.push(I),delete a[j+1];break}}else{M=n-l,t.add(M,"hour");const y=O.LngLatHelper.roundPrecision(v.speed*M,4);I=O.LaneHelper.calculateCoordinate(c,s.bearing,y,"nauticalmiles",!b.gcToPrevious),I.eta=t.format("YYYY-MM-DDTHH:mm[Z]"),a[j]=I,T==null||T.info(`[%s] go to %j from %j with ${y}nm, and cost ${M} hours`,u.requestId,{lat:I.lat,lng:I.lng},{lat:c.lat,lng:c.lng,etd:c.etd}),w+=y,I.distanceFromPrevious=w,I.distanceFromStart=o+w;break}}return{etd:t,from:v,to:I,next:a.filter(j=>j),wps:f,days:p}}static currentFactor(s,t,i=0){const n=(s-(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(s,t){var m,f,p,l,w,I,v;T==null||T.debug("calculate weather factor via: %j",{...s,...t});const i=A.blockCoefficient(s.displacement,s.lbp,s.breadthMoulded,s.draught),n=A.froudeNumber(s.speed,s.lbp),o=A.amendFactor(i,n,s.loadCondition);let a=Math.abs(s.bearing%360-(((m=t==null?void 0:t.wind)==null?void 0:m.degree)%360||0));a=a>180?360-a:a;const e=A.directionFactor(a,(f=t==null?void 0:t.wind)==null?void 0:f.scale),d=A.vesselTagFactor(s.displacement,s.loadCondition,s.tag,(p=t==null?void 0:t.wind)==null?void 0:p.scale);let r=e*o*d/100*s.speed;r=Math.round(r*1.943844*1e4)/1e4*-1,s.tag==="tugs"&&Math.abs(r)>1&&(r=r/(Math.abs(Math.round(r))+1)),T==null||T.debug("wind wx factor = %d",r),a=Math.abs(s.bearing%360-(((w=(l=t==null?void 0:t.wave)==null?void 0:l.sig)==null?void 0:w.degree)%360||0));const u=A.waveHeightFactor(((v=(I=t==null?void 0:t.wave)==null?void 0:I.sig)==null?void 0:v.height)??1,a);return T==null||T.debug("wave wx factor = %d",u),r=r*.4+u,T==null||T.debug("weather factor = %d",r),r=Math.abs(r)>4?4*(Math.abs(r)/r)+Math.abs(r)/r*(Math.abs(r)-4)*.1:r,Math.round((r||0)*100)/100}static async analyseInstant(s,t,i,n,o,a="",e=0,d=!0,r=!1,u={}){var P,et,st,at,nt;const m=g().valueOf();s.lng=O.LngLatHelper.convertToStdLng(s.lng);const{route:f,waypoints:p}=o.points,l=O.LaneHelper.calculateSubRoute(s,f);if(((P=l[0])==null?void 0:P.length)<=1)return;const{v0:w,label:I}=s.sog?{v0:s.sog,label:"Other"}:{v0:n.speed,label:"CP"},v=A.assembleProperties(i,n.loadCondition,w,0),j=p.length?O.LaneHelper.calculateSubWaypoints(s,p):[];j.forEach(x=>x.important=!0);const c={from:{...s},route:l,waypoints:j,v0:w,label:I},b={hours:[],days:[],wps:[]};e||(O.LaneHelper.calculateRouteDistance(l)/n.speed<=72?e=3:e=6);let F=O.LaneHelper.simplifyRouteToCoordinates(l,j,0),M=0,y=0,H=0,E=0;t=g(t).utc();const W=t.clone();for(;F.length>0;){const x=e-t.hour()%e,B=Math.ceil(t.clone().add(x,"h").set({minute:0,second:0,millisecond:0}).diff(t,"h",!0)*1e4)/1e4,L=await A.speedLoseInHoursStep(v,t,W,B,M,F,a,d,r,u);(et=L.from)!=null&&et.speed&&(b.hours.push(L.from),b.wps.push(...L.wps),b.days.push(...L.days)),F=L==null?void 0:L.next,F.length||b.hours.push(L==null?void 0:L.to),M+=((st=L==null?void 0:L.to)==null?void 0:st.distanceFromPrevious)??0}const q=b.hours;for(let x=0;x<q.length-1;x++){const B=g(q[x+1].eta).diff(q[x].etd,"hour",!0)||1;y+=(q[x].wxFactor||0)*B,H+=(q[x].cFactor||0)*B,E+=B}(at=b.wps)==null||at.forEach((x,B)=>{if(B){const L=b.wps[B-1],ft=x.distanceFromStart-L.distanceFromStart,ot=g(x.eta).diff(g(L.etd),"h",!0);if(ot<1)x.avgSpd=L.speed;else{x.avgSpd=Math.round(ft/ot*100)/100;const it=Math.round((L.speed+x.speed)/2*100)/100;x.avgSpd=x.avgSpd>it?it:x.avgSpd}}}),c.sample=b;const _=b.hours.at(0),V=b.hours.at(-1);c.distance=Math.round(V.distanceFromStart*1e4)/1e4,c.etd=g(_.eta).utc().format(),c.eta=g(V.eta).utc().format(),c.wxFactor=Math.round(y/E*1e4)/1e4,c.cFactor=Math.round(H/E*1e4)/1e4,c.avgSpeed=Math.round(V.distanceFromStart/E*1e4)/1e4,c.totalHrs=Math.round(E*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 C=g().valueOf()-m,D=((nt=b==null?void 0:b.hours)==null?void 0:nt.length)||1;return T==null||T.info("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms",u==null?void 0:u.requestId,C,D,Math.round(C/D*1e3)/1e3),c}static async analyseInstantWithThreshed(s,t,i,n,o,a,e,d="",r=3,u=!0,m=!1,f={}){var V,N,C;s.lng=O.LngLatHelper.convertToStdLng(s.lng);const{v0:p,label:l}=s.sog?{v0:s.sog,label:"Other"}:{v0:o.speed,label:"CP"},w=A.assembleProperties(n,o.loadCondition,p,0),I=O.LaneHelper.calculateSubRoute(s,a);if(((V=I[0])==null?void 0:V.length)<=1)return;const v=e.length?O.LaneHelper.calculateSubWaypoints(s,e):[];v.forEach(D=>D.important=!0);let j=O.LaneHelper.simplifyRouteToCoordinates(I,v,0),c=0,b=0,F=0,M=0,y;const H={hours:[],wps:[],days:[]};for(t=g(t).utc();j.length>0;){const D=r-t.hour()%r;let P=Math.ceil(t.clone().add(D,"h").set({minute:0,second:0,millisecond:0}).diff(t,"h",!0)*1e4)/1e4;if(P=t.clone().add(P,"h").isAfter(i)?i.diff(t,"h",!0)*1e4/1e4:P,P)y=await A.speedLoseInHoursStep(w,t,i.clone(),P,c,j,d,u,m,f),(N=y.from)!=null&&N.speed&&(H.hours.push(y.from),y!=null&&y.wps&&H.wps.push(...y.wps),H.days.push(...y.days)),j=y==null?void 0:y.next,j.length||(H.hours.push(y==null?void 0:y.to),y!=null&&y.wps&&H.wps.push(...y.wps),H.days.push(y==null?void 0:y.to)),c+=((C=y==null?void 0:y.to)==null?void 0:C.distanceFromPrevious)??0;else{y&&(H.hours.push(y.to),y!=null&&y.wps&&H.wps.push(...y.wps),H.days.push(y.to));break}}const E=H.hours;for(let D=0;D<E.length-1;D++){const P=g(E[D+1].eta).diff(E[D].etd,"hour",!0);b+=E[D].wxFactor*P,F+=E[D].cFactor*P,M+=P}const W=H.hours.at(0),q=H.hours.at(-1);return{sample:H,distance:Math.round(((q==null?void 0:q.distanceFromStart)||0)*1e4)/1e4,etd:g(W.eta).utc().format(),eta:g(q==null?void 0:q.eta).utc().format(),wxFactor:Math.round(b/M*1e4)/1e4,cFactor:Math.round(F/M*1e4)/1e4,avgSpeed:Math.round(((q==null?void 0:q.distanceFromStart)||0)/M*1e4)/1e4,totalHrs:Math.round(M*1e4)/1e4,from:s,to:q,route:I,waypoints:v,v0:p,label:l}}static async analyseCost(s,t,i,n,o={}){}}k.AISImpl=z,k.AlertHelper=Q,k.AlertLevel=J,k.HifleetImpl=ct,k.LoadCondition=$,k.MyShipImpl=ut,k.MyVesselImpl=rt,k.ShipxyImpl=dt,k.SpeedHelper=A,k.SpeedLabel=tt,k.VesselTag=X,k.alertHelper=ht,Object.defineProperty(k,Symbol.toStringTag,{value:"Module"})});
|
|
@@ -51,6 +51,22 @@ export interface VesselProperties {
|
|
|
51
51
|
speed: number;
|
|
52
52
|
bearing: number;
|
|
53
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* 速度计算参数
|
|
56
|
+
*/
|
|
57
|
+
export interface SpeedProps {
|
|
58
|
+
useRouteParam?: boolean;
|
|
59
|
+
lat?: number;
|
|
60
|
+
lng?: number;
|
|
61
|
+
etd?: string;
|
|
62
|
+
speedStep?: true;
|
|
63
|
+
forecastDay?: true;
|
|
64
|
+
meteoVendor?: true;
|
|
65
|
+
addComm?: true;
|
|
66
|
+
dailyHire?: true;
|
|
67
|
+
priceFO?: true;
|
|
68
|
+
priceDGO?: true;
|
|
69
|
+
}
|
|
54
70
|
export declare class SpeedHelper {
|
|
55
71
|
/**
|
|
56
72
|
* @see https://baike.baidu.com/item/%E6%96%B9%E5%BD%A2%E7%B3%BB%E6%95%B0/4965568?fr=aladdin
|
|
@@ -229,4 +245,18 @@ export declare class SpeedHelper {
|
|
|
229
245
|
v0: any;
|
|
230
246
|
label: SpeedLabel;
|
|
231
247
|
} | undefined>;
|
|
248
|
+
static analyseCost(props: SpeedProps, vessel: VesselAssemble, cps: [{
|
|
249
|
+
loadCondition: string;
|
|
250
|
+
speed: number;
|
|
251
|
+
fo?: number;
|
|
252
|
+
dgo?: number;
|
|
253
|
+
}], lane: {
|
|
254
|
+
points: {
|
|
255
|
+
route: number[][][];
|
|
256
|
+
waypoints: any[];
|
|
257
|
+
};
|
|
258
|
+
voyage: any;
|
|
259
|
+
}, options?: {
|
|
260
|
+
requestId?: string;
|
|
261
|
+
}): Promise<void>;
|
|
232
262
|
}
|