@idm-plugin/vessel 1.9.6 → 1.9.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 +438 -436
- package/dist/index.umd.cjs +1 -1
- package/dist/speed/src/index.d.ts +0 -6
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
var ht = Object.defineProperty;
|
|
2
|
-
var lt = (
|
|
3
|
-
var
|
|
2
|
+
var lt = (E, e, t) => e in E ? ht(E, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : E[e] = t;
|
|
3
|
+
var K = (E, e, t) => (lt(E, typeof e != "symbol" ? e + "" : e, t), t);
|
|
4
4
|
import B from "got";
|
|
5
5
|
import rt from "@log4js-node/log4js-api";
|
|
6
6
|
import g from "moment";
|
|
7
7
|
import { LngLatHelper as J, LaneHelper as W } from "@idm-plugin/geo2";
|
|
8
|
-
import { MeteoHelper2 as ft
|
|
9
|
-
import { Meteo2Assist as
|
|
8
|
+
import { MeteoHelper2 as ft } from "@idm-plugin/meteo2";
|
|
9
|
+
import { Meteo2Assist as it } from "@idm-plugin/meteo";
|
|
10
10
|
let p;
|
|
11
11
|
try {
|
|
12
12
|
p = rt.getLogger("vessel");
|
|
@@ -54,45 +54,45 @@ class et {
|
|
|
54
54
|
return { labelCn: t, labelEn: n };
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
|
-
class
|
|
57
|
+
class xt extends et {
|
|
58
58
|
constructor(t, n) {
|
|
59
59
|
super();
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
60
|
+
K(this, "clientId");
|
|
61
|
+
K(this, "clientSecret");
|
|
62
|
+
K(this, "token");
|
|
63
63
|
this.clientId = t, this.clientSecret = n;
|
|
64
64
|
}
|
|
65
65
|
async authToken(t = {}) {
|
|
66
|
-
const n = "https://svc.data.myvessel.cn/ada/oauth/token",
|
|
66
|
+
const n = "https://svc.data.myvessel.cn/ada/oauth/token", i = {
|
|
67
67
|
searchParams: {
|
|
68
68
|
client_id: this.clientId,
|
|
69
69
|
client_secret: this.clientSecret,
|
|
70
70
|
grant_type: "client_credentials"
|
|
71
71
|
}
|
|
72
|
-
},
|
|
73
|
-
p == null || p.info("[%s] fetch access token from: %s - %j", t.requestId, n,
|
|
74
|
-
accessToken:
|
|
75
|
-
tokenType:
|
|
76
|
-
expiresIn:
|
|
77
|
-
scope:
|
|
78
|
-
jti:
|
|
72
|
+
}, o = await B.post(n, i).json();
|
|
73
|
+
p == null || p.info("[%s] fetch access token from: %s - %j", t.requestId, n, o), o.error || (this.token = {
|
|
74
|
+
accessToken: o.access_token,
|
|
75
|
+
tokenType: o.token_type,
|
|
76
|
+
expiresIn: o.expires_in,
|
|
77
|
+
scope: o.scope,
|
|
78
|
+
jti: o.jti,
|
|
79
79
|
issuedAt: g().utc().format()
|
|
80
80
|
});
|
|
81
81
|
}
|
|
82
82
|
async realTimePosition(t, n = {}) {
|
|
83
|
-
var d,
|
|
83
|
+
var d, r, h;
|
|
84
84
|
(!this.token || g().diff(g(this.token.issuedAt), "seconds") > ((d = this.token) == null ? void 0 : d.expiresIn) - 300) && await this.authToken(n);
|
|
85
|
-
const
|
|
85
|
+
const i = "https://svc.data.myvessel.cn/sdc/v1/vessels/status/location/unit", o = {
|
|
86
86
|
headers: {
|
|
87
|
-
Authorization: `${(
|
|
87
|
+
Authorization: `${(r = this.token) == null ? void 0 : r.tokenType} ${(h = this.token) == null ? void 0 : h.accessToken}`
|
|
88
88
|
},
|
|
89
89
|
searchParams: { mmsi: t }
|
|
90
90
|
};
|
|
91
|
-
p == null || p.info("[%s] fetch realtime position from: %s - %j", n.requestId,
|
|
92
|
-
const
|
|
93
|
-
if (
|
|
94
|
-
return p == null || p.warn("[%s] fetch realtime position failed: %j", n.requestId,
|
|
95
|
-
const s =
|
|
91
|
+
p == null || p.info("[%s] fetch realtime position from: %s - %j", n.requestId, i, o);
|
|
92
|
+
const a = await B.get(i, o).json();
|
|
93
|
+
if (a.code)
|
|
94
|
+
return p == null || p.warn("[%s] fetch realtime position failed: %j", n.requestId, i, { message: a.message, status: a.status, code: a.code }), a;
|
|
95
|
+
const s = a.data;
|
|
96
96
|
for (const M in s)
|
|
97
97
|
!isNaN(s[M]) && Number(s[M]) !== 1 / 0 && (s[M] = Number(s[M]));
|
|
98
98
|
if (s) {
|
|
@@ -131,37 +131,37 @@ class jt extends et {
|
|
|
131
131
|
} else
|
|
132
132
|
return {};
|
|
133
133
|
}
|
|
134
|
-
async trajectory(t, n,
|
|
134
|
+
async trajectory(t, n, i, o, a = !0, s = {}) {
|
|
135
135
|
(!this.token || g().diff(g(this.token.issuedAt), "seconds") > this.token.expiresIn - 300) && await this.authToken(s);
|
|
136
|
-
const d = await this.realTimePosition(t, s),
|
|
137
|
-
for (; h.diff(
|
|
138
|
-
await this.trajectoryIn30Day(t,
|
|
139
|
-
return await this.trajectoryIn30Day(t,
|
|
136
|
+
const d = await this.realTimePosition(t, s), r = g(n), h = g(i), M = [];
|
|
137
|
+
for (; h.diff(r, "day", !0) > 30; )
|
|
138
|
+
await this.trajectoryIn30Day(t, r, r.clone().add(30, "day"), d, o, M, s), r.add(30, "day");
|
|
139
|
+
return await this.trajectoryIn30Day(t, r, h, d, o, M, s), M;
|
|
140
140
|
}
|
|
141
|
-
async trajectoryIn30Day(t, n,
|
|
142
|
-
var m,
|
|
143
|
-
const
|
|
141
|
+
async trajectoryIn30Day(t, n, i, o, a, s, d = {}) {
|
|
142
|
+
var m, C, S, w, b;
|
|
143
|
+
const r = "https://svc.data.myvessel.cn/sdc/v1/vessels/status/track", h = {
|
|
144
144
|
headers: {
|
|
145
|
-
Authorization: `${(m = this.token) == null ? void 0 : m.tokenType} ${(
|
|
145
|
+
Authorization: `${(m = this.token) == null ? void 0 : m.tokenType} ${(C = this.token) == null ? void 0 : C.accessToken}`
|
|
146
146
|
},
|
|
147
147
|
json: {
|
|
148
148
|
mmsi: t,
|
|
149
149
|
startTime: n.utcOffset(8).format("YYYY-MM-DD HH:mm:ss"),
|
|
150
|
-
endTime:
|
|
150
|
+
endTime: i.utcOffset(8).format("YYYY-MM-DD HH:mm:ss")
|
|
151
151
|
}
|
|
152
152
|
};
|
|
153
|
-
p == null || p.info("[%s] fetch trajectory from: %s - %j", d.requestId,
|
|
154
|
-
const M = await B.post(
|
|
153
|
+
p == null || p.info("[%s] fetch trajectory from: %s - %j", d.requestId, r, h);
|
|
154
|
+
const M = await B.post(r, h).json();
|
|
155
155
|
if (M.code)
|
|
156
|
-
return p == null || p.warn("[%s] fetch trajectory failed: %j", d.requestId,
|
|
156
|
+
return p == null || p.warn("[%s] fetch trajectory failed: %j", d.requestId, r, { message: M.message, status: M.status, code: M.code }), M;
|
|
157
157
|
let y = -1;
|
|
158
|
-
const
|
|
158
|
+
const v = g(`${(w = (S = M.data) == null ? void 0 : S[0]) == null ? void 0 : w.postime} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
159
159
|
return (b = M.data) == null || b.forEach((c) => {
|
|
160
160
|
for (const Y in c)
|
|
161
161
|
!isNaN(c[Y]) && Number(c[Y]) !== 1 / 0 && (c[Y] = Number(c[Y]));
|
|
162
|
-
const f = g(`${c.postime} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00"), l = c.status, { labelCn: u, labelEn: I } = this.parseStatus(l),
|
|
162
|
+
const f = g(`${c.postime} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00"), l = c.status, { labelCn: u, labelEn: I } = this.parseStatus(l), k = {
|
|
163
163
|
mmsi: c.mmsi,
|
|
164
|
-
imo:
|
|
164
|
+
imo: o == null ? void 0 : o.imo,
|
|
165
165
|
lat: c.lat,
|
|
166
166
|
lng: c.lon,
|
|
167
167
|
sog: c.sog,
|
|
@@ -177,32 +177,32 @@ class jt extends et {
|
|
|
177
177
|
method: "trajectory",
|
|
178
178
|
vendor: "myVessel",
|
|
179
179
|
utc: f.utc().format()
|
|
180
|
-
}, D = Math.floor(f.diff(
|
|
181
|
-
D !== y && (y = D, s.push(
|
|
180
|
+
}, D = Math.floor(f.diff(v, "minute", !0) / (a || 1));
|
|
181
|
+
D !== y && (y = D, s.push(k));
|
|
182
182
|
}), s;
|
|
183
183
|
}
|
|
184
184
|
}
|
|
185
185
|
class Et extends et {
|
|
186
186
|
constructor(t) {
|
|
187
187
|
super();
|
|
188
|
-
|
|
188
|
+
K(this, "token");
|
|
189
189
|
this.token = t;
|
|
190
190
|
}
|
|
191
191
|
async realTimePosition(t, n = {}) {
|
|
192
|
-
const
|
|
192
|
+
const i = "https://api.hifleet.com/position/position/get/token", o = {
|
|
193
193
|
searchParams: {
|
|
194
194
|
mmsi: t,
|
|
195
195
|
usertoken: this.token
|
|
196
196
|
}
|
|
197
|
-
},
|
|
198
|
-
p == null || p.info("[%s] fetch realtime position from: %s - %j", n.requestId,
|
|
199
|
-
const s =
|
|
197
|
+
}, a = await B.post(i, o).json();
|
|
198
|
+
p == null || p.info("[%s] fetch realtime position from: %s - %j", n.requestId, i, o);
|
|
199
|
+
const s = a == null ? void 0 : a.list;
|
|
200
200
|
if (!s)
|
|
201
|
-
return p == null || p.warn("[%s] fetch realtime position failed: %j", n.requestId,
|
|
202
|
-
for (const
|
|
203
|
-
!isNaN(s[
|
|
201
|
+
return p == null || p.warn("[%s] fetch realtime position failed: %j", n.requestId, i, a), a;
|
|
202
|
+
for (const v in s)
|
|
203
|
+
!isNaN(s[v]) && Number(s[v]) !== 1 / 0 && (s[v] = Number(s[v]));
|
|
204
204
|
s.status = s.sp > 3 ? 0 : 1;
|
|
205
|
-
const d = s.status, { labelCn:
|
|
205
|
+
const d = s.status, { labelCn: r, labelEn: h } = this.parseStatus(d), M = g(`${s.ti} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
206
206
|
return {
|
|
207
207
|
mmsi: s.m,
|
|
208
208
|
name: s.n,
|
|
@@ -226,15 +226,15 @@ class Et extends et {
|
|
|
226
226
|
positionTime: M.unix(),
|
|
227
227
|
utc: M.utc().format(),
|
|
228
228
|
status: d,
|
|
229
|
-
labelCn:
|
|
229
|
+
labelCn: r,
|
|
230
230
|
labelEn: h,
|
|
231
231
|
method: "position",
|
|
232
232
|
vendor: "hifleet"
|
|
233
233
|
};
|
|
234
234
|
}
|
|
235
235
|
async search(t, n = {}) {
|
|
236
|
-
let
|
|
237
|
-
const
|
|
236
|
+
let i = "https://www.hifleet.com/hifleetapi/searchVesselOL.do";
|
|
237
|
+
const o = {
|
|
238
238
|
searchParams: {
|
|
239
239
|
keyword: t
|
|
240
240
|
},
|
|
@@ -244,24 +244,24 @@ class Et extends et {
|
|
|
244
244
|
Host: "www.hifleet.com"
|
|
245
245
|
}
|
|
246
246
|
};
|
|
247
|
-
let
|
|
248
|
-
p == null || p.info("[%s] fetch vessel props from: %s - %j", n.requestId,
|
|
249
|
-
for (const d in
|
|
250
|
-
!isNaN(
|
|
247
|
+
let a = await B.post(i, o).json();
|
|
248
|
+
p == null || p.info("[%s] fetch vessel props from: %s - %j", n.requestId, i, o), a instanceof Array && (a = a[0]);
|
|
249
|
+
for (const d in a)
|
|
250
|
+
!isNaN(a[d]) && Number(a[d]) !== 1 / 0 && (a[d] = Number(a[d]));
|
|
251
251
|
const s = {
|
|
252
|
-
mmsi:
|
|
253
|
-
name:
|
|
254
|
-
imo:
|
|
255
|
-
callSign:
|
|
256
|
-
length:
|
|
257
|
-
breadth:
|
|
258
|
-
draught:
|
|
259
|
-
type:
|
|
252
|
+
mmsi: a.m,
|
|
253
|
+
name: a.n,
|
|
254
|
+
imo: a.i,
|
|
255
|
+
callSign: a.c,
|
|
256
|
+
length: a.l,
|
|
257
|
+
breadth: a.b,
|
|
258
|
+
draught: a.dr,
|
|
259
|
+
type: a.t
|
|
260
260
|
};
|
|
261
|
-
return
|
|
261
|
+
return i = "https://www.hifleet.com/hifleetapi/sameShipSearch.do", a = await B.post(i, o).json(), p == null || p.info("[%s] search vessel dead weight from: %s - %j", n.requestId, i, o), a instanceof Array && (a = a[0]), a && (s.deadweight = Number(a.dwt)), s;
|
|
262
262
|
}
|
|
263
263
|
async suggest(t, n = {}) {
|
|
264
|
-
const
|
|
264
|
+
const i = "https://www.hifleet.com/hifleetapi/getShipSuggest.do", o = {
|
|
265
265
|
searchParams: {
|
|
266
266
|
q: t
|
|
267
267
|
},
|
|
@@ -270,10 +270,10 @@ class Et extends et {
|
|
|
270
270
|
Origin: "https://www.hifleet.com",
|
|
271
271
|
Host: "www.hifleet.com"
|
|
272
272
|
}
|
|
273
|
-
},
|
|
274
|
-
p == null || p.info("[%s] suggest vessel props from: %s - %j", n.requestId,
|
|
273
|
+
}, a = await B.post(i, o).json();
|
|
274
|
+
p == null || p.info("[%s] suggest vessel props from: %s - %j", n.requestId, i, o);
|
|
275
275
|
const s = [];
|
|
276
|
-
for (const d of
|
|
276
|
+
for (const d of a)
|
|
277
277
|
s.push({
|
|
278
278
|
mmsi: !d.mmsi || isNaN(d.mmsi) ? null : Number(d.mmsi),
|
|
279
279
|
name: d.name,
|
|
@@ -281,37 +281,37 @@ class Et extends et {
|
|
|
281
281
|
imo: !d.imo || isNaN(d.imo) ? null : Number(d.imo),
|
|
282
282
|
score: d._score
|
|
283
283
|
});
|
|
284
|
-
return s.sort((d,
|
|
284
|
+
return s.sort((d, r) => r.score - d.score), s;
|
|
285
285
|
}
|
|
286
|
-
async trajectory(t, n,
|
|
286
|
+
async trajectory(t, n, i, o, a = !0, s = {}) {
|
|
287
287
|
var c, f, l;
|
|
288
288
|
const d = await this.realTimePosition(t, s);
|
|
289
|
-
let
|
|
290
|
-
const h = g(
|
|
291
|
-
if (
|
|
292
|
-
let u = h.diff(
|
|
293
|
-
u < 0 ?
|
|
289
|
+
let r = g(n);
|
|
290
|
+
const h = g(i), M = g();
|
|
291
|
+
if (a) {
|
|
292
|
+
let u = h.diff(r, "d", !0);
|
|
293
|
+
u < 0 ? r = h.clone().subtract(40, "d") : u < 30 ? r.subtract(10, "d") : u < 60 ? r.subtract(5, "d") : r = h.clone().subtract(80, "d"), u = M.diff(h, "d", !0), h.add(u > 10 ? 240 : u * 24, "h");
|
|
294
294
|
}
|
|
295
295
|
const y = {
|
|
296
296
|
searchParams: {
|
|
297
297
|
endtime: h.utcOffset("+8:00").format("YYYY-MM-DD HH:mm:ss"),
|
|
298
|
-
starttime:
|
|
298
|
+
starttime: r.utcOffset("+8:00").format("YYYY-MM-DD HH:mm:ss"),
|
|
299
299
|
mmsi: t,
|
|
300
300
|
usertoken: this.token
|
|
301
301
|
}
|
|
302
|
-
},
|
|
303
|
-
p == null || p.info("[%s] fetch trajectory from: %s - %j", s.requestId,
|
|
304
|
-
let
|
|
305
|
-
m && (
|
|
306
|
-
const
|
|
307
|
-
let
|
|
308
|
-
const b = g(`${(l =
|
|
309
|
-
for (const u of
|
|
302
|
+
}, v = "https://api.hifleet.com/position/trajectory/nocompressed/withstatic/token", m = await B.get(v, y).json();
|
|
303
|
+
p == null || p.info("[%s] fetch trajectory from: %s - %j", s.requestId, v, y);
|
|
304
|
+
let C;
|
|
305
|
+
m && (C = ((f = (c = m.ships) == null ? void 0 : c.offors) == null ? void 0 : f.ship) || [], C.length || p == null || p.warn("[%s] fetch trajectory failed: %j", s.requestId, m));
|
|
306
|
+
const S = [];
|
|
307
|
+
let w = -1;
|
|
308
|
+
const b = g(`${(l = C == null ? void 0 : C[0]) == null ? void 0 : l.ti} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
309
|
+
for (const u of C) {
|
|
310
310
|
for (const P in u)
|
|
311
311
|
!isNaN(u[P]) && Number(u[P]) !== 1 / 0 && (u[P] = Number(u[P]));
|
|
312
312
|
const I = g(`${u.ti} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
313
313
|
u.status = u.sp > 4 ? 0 : 1;
|
|
314
|
-
const { labelEn:
|
|
314
|
+
const { labelEn: k, labelCn: D } = this.parseStatus(u.status), Y = {
|
|
315
315
|
mmsi: u.m,
|
|
316
316
|
name: u.n,
|
|
317
317
|
imo: d == null ? void 0 : d.imo,
|
|
@@ -325,35 +325,35 @@ class Et extends et {
|
|
|
325
325
|
utc: I.utc().format(),
|
|
326
326
|
status: u.status,
|
|
327
327
|
labelCn: D,
|
|
328
|
-
labelEn:
|
|
328
|
+
labelEn: k,
|
|
329
329
|
method: "trajectory",
|
|
330
330
|
vendor: "hifleet"
|
|
331
|
-
},
|
|
332
|
-
|
|
331
|
+
}, j = Math.floor(I.diff(b, "minute", !0) / (o || 1));
|
|
332
|
+
j !== w && (w = j, S.push(Y));
|
|
333
333
|
}
|
|
334
|
-
return
|
|
334
|
+
return S;
|
|
335
335
|
}
|
|
336
336
|
}
|
|
337
|
-
class
|
|
337
|
+
class jt extends et {
|
|
338
338
|
constructor(t) {
|
|
339
339
|
super();
|
|
340
|
-
|
|
340
|
+
K(this, "token");
|
|
341
341
|
this.token = t;
|
|
342
342
|
}
|
|
343
343
|
async realTimePosition(t, n = {}) {
|
|
344
|
-
const
|
|
344
|
+
const i = {
|
|
345
345
|
searchParams: {
|
|
346
346
|
id: t,
|
|
347
347
|
k: this.token,
|
|
348
348
|
enc: 1
|
|
349
349
|
}
|
|
350
|
-
},
|
|
351
|
-
if (p == null || p.info("[%s] fetch realtime position from: %s - %j", n.requestId,
|
|
352
|
-
return
|
|
353
|
-
const s =
|
|
350
|
+
}, o = "https://api.shipxy.com/apicall/GetSingleShip", a = await B.get(o, i).json();
|
|
351
|
+
if (p == null || p.info("[%s] fetch realtime position from: %s - %j", n.requestId, o, i), (a == null ? void 0 : a.status) !== 0)
|
|
352
|
+
return a;
|
|
353
|
+
const s = a.data[0];
|
|
354
354
|
for (const y in s)
|
|
355
355
|
!isNaN(s[y]) && Number(s[y]) !== 1 / 0 && (s[y] = Number(s[y]));
|
|
356
|
-
const { labelCn: d, labelEn:
|
|
356
|
+
const { labelCn: d, labelEn: r } = await this.parseStatus(s.navistat), h = g.unix(s.lasttime);
|
|
357
357
|
return {
|
|
358
358
|
mmsi: s.ShipID,
|
|
359
359
|
name: s.name,
|
|
@@ -371,28 +371,28 @@ class Nt extends et {
|
|
|
371
371
|
positionTime: s.lasttime,
|
|
372
372
|
utc: h.utc().format(),
|
|
373
373
|
status: s.navistat,
|
|
374
|
-
labelEn:
|
|
374
|
+
labelEn: r,
|
|
375
375
|
labelCn: d,
|
|
376
376
|
method: "position",
|
|
377
377
|
vendor: "shipxy"
|
|
378
378
|
};
|
|
379
379
|
}
|
|
380
|
-
async trajectory(t, n,
|
|
380
|
+
async trajectory(t, n, i, o, a = !0, s = {}) {
|
|
381
381
|
var b;
|
|
382
|
-
const d = await this.realTimePosition(t, s),
|
|
382
|
+
const d = await this.realTimePosition(t, s), r = g(n), h = g(i), M = "https://api.shipxy.com/apicall/GetShipTrack", y = {
|
|
383
383
|
searchParams: {
|
|
384
384
|
id: t,
|
|
385
385
|
k: this.token,
|
|
386
386
|
enc: 1,
|
|
387
387
|
cut: 0,
|
|
388
|
-
btm:
|
|
388
|
+
btm: r.unix(),
|
|
389
389
|
etm: h.unix()
|
|
390
390
|
}
|
|
391
|
-
},
|
|
392
|
-
if (p == null || p.info("[%s] fetch trajectory from: %s - %j", s.requestId, M, y), (
|
|
393
|
-
return
|
|
394
|
-
const m =
|
|
395
|
-
let
|
|
391
|
+
}, v = await B.get(M, y).json();
|
|
392
|
+
if (p == null || p.info("[%s] fetch trajectory from: %s - %j", s.requestId, M, y), (v == null ? void 0 : v.status) !== 0)
|
|
393
|
+
return v;
|
|
394
|
+
const m = v == null ? void 0 : v.points, C = [], S = g.unix((b = m[0]) == null ? void 0 : b.utc);
|
|
395
|
+
let w = -1;
|
|
396
396
|
for (const c of m) {
|
|
397
397
|
const f = g.unix(c.utc), l = {
|
|
398
398
|
imo: d == null ? void 0 : d.imo,
|
|
@@ -405,41 +405,41 @@ class Nt extends et {
|
|
|
405
405
|
utc: f.utc().format(),
|
|
406
406
|
method: "trajectory",
|
|
407
407
|
vendor: "shipxy"
|
|
408
|
-
}, u = Math.floor(f.diff(
|
|
409
|
-
u !==
|
|
408
|
+
}, u = Math.floor(f.diff(S, "minute", !0) / (o || 1));
|
|
409
|
+
u !== w && (w = u, C.push(l));
|
|
410
410
|
}
|
|
411
|
-
return
|
|
411
|
+
return C;
|
|
412
412
|
}
|
|
413
413
|
}
|
|
414
|
-
class
|
|
414
|
+
class Nt extends et {
|
|
415
415
|
constructor(t) {
|
|
416
416
|
super();
|
|
417
|
-
|
|
417
|
+
K(this, "token");
|
|
418
418
|
this.token = t;
|
|
419
419
|
}
|
|
420
420
|
async getShipId(t, n = {}) {
|
|
421
|
-
const
|
|
421
|
+
const i = {
|
|
422
422
|
headers: {
|
|
423
423
|
appKey: this.token
|
|
424
424
|
},
|
|
425
425
|
json: {
|
|
426
426
|
mmsiList: t
|
|
427
427
|
}
|
|
428
|
-
},
|
|
429
|
-
return p == null || p.info("[%s] fetch ship id from: %s - %j", n.requestId,
|
|
428
|
+
}, o = "https://api3.myships.com/sp/ships/getShipIdByMMSI", a = await B.post(o, i).json();
|
|
429
|
+
return p == null || p.info("[%s] fetch ship id from: %s - %j", n.requestId, o, i), a.code !== "0" ? a : a.data[0].shipId;
|
|
430
430
|
}
|
|
431
431
|
async getShipInfo(t, n = {}) {
|
|
432
|
-
const
|
|
432
|
+
const i = {
|
|
433
433
|
headers: {
|
|
434
434
|
appKey: this.token
|
|
435
435
|
},
|
|
436
436
|
json: {
|
|
437
437
|
shipId: t
|
|
438
438
|
}
|
|
439
|
-
},
|
|
440
|
-
if (p == null || p.info("[%s] fetch ship info from: %s - %j", n.requestId,
|
|
441
|
-
return
|
|
442
|
-
const s =
|
|
439
|
+
}, o = "https://api3.myships.com/sp/ships/aissta", a = await B.post(o, i).json();
|
|
440
|
+
if (p == null || p.info("[%s] fetch ship info from: %s - %j", n.requestId, o, i), a.code !== "0")
|
|
441
|
+
return a;
|
|
442
|
+
const s = a.data;
|
|
443
443
|
let d = s.imo;
|
|
444
444
|
return t === "407170" && (d = "9198379", p == null || p.warn("[%s] ship(%s) imo error: %s, should be %s", n.requestId, t, s.imo, d)), {
|
|
445
445
|
mmsi: s.mmsi,
|
|
@@ -452,45 +452,45 @@ class Tt extends et {
|
|
|
452
452
|
};
|
|
453
453
|
}
|
|
454
454
|
async realTimePosition(t, n = {}) {
|
|
455
|
-
const
|
|
455
|
+
const i = await this.getShipId(t, n), o = await this.getShipInfo(i, n), a = {
|
|
456
456
|
headers: {
|
|
457
457
|
appKey: this.token
|
|
458
458
|
},
|
|
459
459
|
json: {
|
|
460
|
-
shipId:
|
|
460
|
+
shipId: i
|
|
461
461
|
}
|
|
462
|
-
}, s = "https://api3.myships.com/sp/ships/position/latest", d = await B.post(s,
|
|
463
|
-
p == null || p.info("[%s] fetch realtime position from: %s - %j", n.requestId, s,
|
|
464
|
-
const
|
|
465
|
-
for (const m in
|
|
466
|
-
!isNaN(
|
|
467
|
-
const { labelCn: h, labelEn: M } = await this.parseStatus(
|
|
462
|
+
}, s = "https://api3.myships.com/sp/ships/position/latest", d = await B.post(s, a).json();
|
|
463
|
+
p == null || p.info("[%s] fetch realtime position from: %s - %j", n.requestId, s, a);
|
|
464
|
+
const r = d.data[0];
|
|
465
|
+
for (const m in r)
|
|
466
|
+
!isNaN(r[m]) && Number(r[m]) !== 1 / 0 && (r[m] = Number(r[m]));
|
|
467
|
+
const { labelCn: h, labelEn: M } = await this.parseStatus(r.aisNavStatus), y = g.unix(r.posTime);
|
|
468
468
|
return {
|
|
469
|
-
...
|
|
469
|
+
...o,
|
|
470
470
|
mmsi: t,
|
|
471
|
-
lat: Math.round(
|
|
472
|
-
lng: Math.round(
|
|
473
|
-
sog: Math.round(
|
|
474
|
-
cog: Math.round(
|
|
475
|
-
hdg: Math.round(
|
|
476
|
-
rot: Math.round(
|
|
477
|
-
positionTime:
|
|
471
|
+
lat: Math.round(r.lat / 1e4 / 60 * 1e5) / 1e5,
|
|
472
|
+
lng: Math.round(r.lon / 1e4 / 60 * 1e5) / 1e5,
|
|
473
|
+
sog: Math.round(r.sog / 10 * 100) / 100,
|
|
474
|
+
cog: Math.round(r.cog / 10 * 100) / 100,
|
|
475
|
+
hdg: Math.round(r.heading * 100) / 100,
|
|
476
|
+
rot: Math.round(r.rot * 100) / 100,
|
|
477
|
+
positionTime: r.posTime,
|
|
478
478
|
utc: y.utc().format(),
|
|
479
|
-
status:
|
|
479
|
+
status: r.aisNavStatus,
|
|
480
480
|
labelEn: M,
|
|
481
481
|
labelCn: h,
|
|
482
482
|
method: "position",
|
|
483
483
|
vendor: "myship"
|
|
484
484
|
};
|
|
485
485
|
}
|
|
486
|
-
async trajectory(t, n,
|
|
487
|
-
const d = g(n),
|
|
488
|
-
for (;
|
|
489
|
-
await this.trajectoryIn30Day(h, d.unix(), d.add(30, "day").unix(), M, t,
|
|
490
|
-
return await this.trajectoryIn30Day(h, d.unix(),
|
|
486
|
+
async trajectory(t, n, i, o, a = !0, s = {}) {
|
|
487
|
+
const d = g(n), r = g(i), h = await this.getShipId(t), M = await this.getShipInfo(h), y = [];
|
|
488
|
+
for (; r.diff(d, "day", !0) > 30; )
|
|
489
|
+
await this.trajectoryIn30Day(h, d.unix(), d.add(30, "day").unix(), M, t, o, y);
|
|
490
|
+
return await this.trajectoryIn30Day(h, d.unix(), r.unix(), M, t, o, y), y;
|
|
491
491
|
}
|
|
492
|
-
async trajectoryIn30Day(t, n,
|
|
493
|
-
var
|
|
492
|
+
async trajectoryIn30Day(t, n, i, o, a, s, d, r = {}) {
|
|
493
|
+
var S;
|
|
494
494
|
const h = {
|
|
495
495
|
headers: {
|
|
496
496
|
appKey: this.token
|
|
@@ -498,32 +498,32 @@ class Tt extends et {
|
|
|
498
498
|
json: {
|
|
499
499
|
shipId: t,
|
|
500
500
|
startTime: n,
|
|
501
|
-
endTime:
|
|
501
|
+
endTime: i
|
|
502
502
|
}
|
|
503
503
|
}, M = "https://api3.myships.com/sp/ships/position/history", y = await B.post(M, h).json();
|
|
504
|
-
if (p == null || p.info("[%s] fetch trajectory from: %s - %j",
|
|
505
|
-
return p == null || p.warn("[%s] invoke myship trajectory failed: %j",
|
|
506
|
-
const
|
|
507
|
-
for (const
|
|
508
|
-
!isNaN(w
|
|
509
|
-
const m = g.unix((
|
|
510
|
-
let
|
|
511
|
-
for (const
|
|
512
|
-
const b = g.unix(
|
|
513
|
-
imo:
|
|
514
|
-
mmsi:
|
|
515
|
-
lat: Math.round(
|
|
516
|
-
lng: Math.round(
|
|
517
|
-
sog: Math.round(
|
|
518
|
-
cog: Math.round(
|
|
519
|
-
hdg: Math.round(
|
|
520
|
-
rot: Math.round(
|
|
504
|
+
if (p == null || p.info("[%s] fetch trajectory from: %s - %j", r.requestId, M, h), y.code !== "0")
|
|
505
|
+
return p == null || p.warn("[%s] invoke myship trajectory failed: %j", r.requestId, y), y;
|
|
506
|
+
const v = y.data;
|
|
507
|
+
for (const w in v)
|
|
508
|
+
!isNaN(v[w]) && Number(v[w]) !== 1 / 0 && (v[w] = Number(v[w]));
|
|
509
|
+
const m = g.unix((S = v[0]) == null ? void 0 : S.posTime);
|
|
510
|
+
let C = -1;
|
|
511
|
+
for (const w of v) {
|
|
512
|
+
const b = g.unix(w.posTime), c = {
|
|
513
|
+
imo: o == null ? void 0 : o.imo,
|
|
514
|
+
mmsi: a,
|
|
515
|
+
lat: Math.round(w.lat / 1e4 / 60 * 1e5) / 1e5,
|
|
516
|
+
lng: Math.round(w.lon / 1e4 / 60 * 1e5) / 1e5,
|
|
517
|
+
sog: Math.round(w.sog / 10 * 100) / 100,
|
|
518
|
+
cog: Math.round(w.cog / 10 * 100) / 100,
|
|
519
|
+
hdg: Math.round(w.heading * 100) / 100,
|
|
520
|
+
rot: Math.round(w.rot * 100) / 100,
|
|
521
521
|
positionTime: b.unix(),
|
|
522
522
|
utc: b.utc().format(),
|
|
523
523
|
method: "trajectory",
|
|
524
524
|
vendor: "myship"
|
|
525
525
|
}, f = Math.floor(b.diff(m, "minute", !0) / (s || 1));
|
|
526
|
-
f !==
|
|
526
|
+
f !== C && (C = f, d.push(c));
|
|
527
527
|
}
|
|
528
528
|
return d;
|
|
529
529
|
}
|
|
@@ -534,8 +534,8 @@ try {
|
|
|
534
534
|
} catch {
|
|
535
535
|
} finally {
|
|
536
536
|
}
|
|
537
|
-
var
|
|
538
|
-
class
|
|
537
|
+
var mt = /* @__PURE__ */ ((E) => (E.NOTICE = "NOTICE", E.WARN = "WARN", E.HEAVY = "HEAVY", E.SEVERE = "SEVERE", E.ERROR = "ERROR", E.FATAL = "FATAL", E))(mt || {});
|
|
538
|
+
class yt {
|
|
539
539
|
/**
|
|
540
540
|
* 解析告警规则, 多规则场景
|
|
541
541
|
* @param rule
|
|
@@ -545,23 +545,23 @@ class Mt {
|
|
|
545
545
|
* @param options
|
|
546
546
|
*/
|
|
547
547
|
parsePrinciple(e, t = {}) {
|
|
548
|
-
var s, d,
|
|
548
|
+
var s, d, r;
|
|
549
549
|
_ == null || _.info("[%s] parse rule: %s", t.requestId, e);
|
|
550
|
-
const n = new RegExp("(?<=\\[)(.+)(?=])", "g"),
|
|
551
|
-
if (!
|
|
550
|
+
const n = new RegExp("(?<=\\[)(.+)(?=])", "g"), i = e.match(n) ? (s = e.match(n)) == null ? void 0 : s[0] : void 0, o = i == null ? void 0 : i.split(";");
|
|
551
|
+
if (!o)
|
|
552
552
|
return;
|
|
553
|
-
const
|
|
554
|
-
for (let h = 0; h < (
|
|
555
|
-
const M = (
|
|
553
|
+
const a = {};
|
|
554
|
+
for (let h = 0; h < (o == null ? void 0 : o.length); h++) {
|
|
555
|
+
const M = (r = (d = o[h].match(n)) == null ? void 0 : d[0]) == null ? void 0 : r.split("],");
|
|
556
556
|
if (h === 0 && !M)
|
|
557
|
-
|
|
557
|
+
a.scope = o[0];
|
|
558
558
|
else if (M)
|
|
559
|
-
for (let y = 0,
|
|
559
|
+
for (let y = 0, v = M.length; y < v; y++) {
|
|
560
560
|
const m = this.parseRule(M[y]);
|
|
561
|
-
m && (
|
|
561
|
+
m && (a[m.level] ? m.key ? a[m.level][m == null ? void 0 : m.key] = m : a[m.level] = m : m.key ? a[m.level] = { [m == null ? void 0 : m.key]: m } : a[m.level] = m);
|
|
562
562
|
}
|
|
563
563
|
}
|
|
564
|
-
return
|
|
564
|
+
return a;
|
|
565
565
|
}
|
|
566
566
|
/**
|
|
567
567
|
* 解析单一告警规则
|
|
@@ -570,16 +570,16 @@ class Mt {
|
|
|
570
570
|
* @param options
|
|
571
571
|
*/
|
|
572
572
|
parseRule(e, t = {}) {
|
|
573
|
-
var
|
|
573
|
+
var a;
|
|
574
574
|
_ == null || _.info("[%s] parse rule: %s", t.requestId, e), e = e.startsWith("[") ? e : `[${e}`, e = e.endsWith("]") ? e : `${e}]`;
|
|
575
|
-
const n = new RegExp("(?<=\\[)(.+?)(?=])", "g"),
|
|
576
|
-
if (
|
|
575
|
+
const n = new RegExp("(?<=\\[)(.+?)(?=])", "g"), i = (a = e == null ? void 0 : e.match(n)) == null ? void 0 : a[0], o = i == null ? void 0 : i.split(",");
|
|
576
|
+
if (o)
|
|
577
577
|
return {
|
|
578
|
-
operator:
|
|
579
|
-
number: Number.isNaN(Number(
|
|
580
|
-
level:
|
|
581
|
-
time: Number(
|
|
582
|
-
key:
|
|
578
|
+
operator: o[0],
|
|
579
|
+
number: Number.isNaN(Number(o[1])) ? o[1] : Number(o[1]),
|
|
580
|
+
level: o[2],
|
|
581
|
+
time: Number(o[3]),
|
|
582
|
+
key: o[4]
|
|
583
583
|
};
|
|
584
584
|
}
|
|
585
585
|
/**
|
|
@@ -589,25 +589,25 @@ class Mt {
|
|
|
589
589
|
* @param options
|
|
590
590
|
*/
|
|
591
591
|
checkWeather(e, t, n = {}) {
|
|
592
|
-
var m,
|
|
593
|
-
let
|
|
594
|
-
const d = Math.round(((
|
|
592
|
+
var m, C, S, w, b, c, f, l, u, I, k, D, Y, j, P;
|
|
593
|
+
let i = 0, o = 0, a = 0, s = 0;
|
|
594
|
+
const d = Math.round(((C = (m = t == null ? void 0 : t.SEVERE) == null ? void 0 : m.sigWave) == null ? void 0 : C.number) * 1.6 * 100) / 100, r = (w = (S = t == null ? void 0 : t.SEVERE) == null ? void 0 : S.sigWave) == null ? void 0 : w.number, h = (c = (b = t == null ? void 0 : t.HEAVY) == null ? void 0 : b.sigWave) == null ? void 0 : c.number, M = Math.round((((l = (f = t == null ? void 0 : t.SEVERE) == null ? void 0 : f.wind) == null ? void 0 : l.number) + 2) * 100) / 100, y = (I = (u = t == null ? void 0 : t.SEVERE) == null ? void 0 : u.wind) == null ? void 0 : I.number, v = (D = (k = t == null ? void 0 : t.HEAVY) == null ? void 0 : k.wind) == null ? void 0 : D.number;
|
|
595
595
|
for (let T = 0; T < (e == null ? void 0 : e.length); T++) {
|
|
596
|
-
const N = e[T], A = (
|
|
597
|
-
s =
|
|
596
|
+
const N = e[T], A = (j = (Y = N == null ? void 0 : N.meteo) == null ? void 0 : Y.wave) == null ? void 0 : j.sig, R = (P = N == null ? void 0 : N.meteo) == null ? void 0 : P.wind, U = T ? g(N.eta).diff(g(e[T - 1].eta), "hour", !0) : 0;
|
|
597
|
+
s = U > s ? U : s, _ == null || _.info("[%s] check sig.wave: %j", n.requestId, { ...A, dgThd4Wv: d, svThd4Wv: r, hvThd4Wv: h }), (A == null ? void 0 : A.height) >= d ? N.isDangerous = !0 : (A == null ? void 0 : A.height) >= r ? N.isSevere = !0 : (A == null ? void 0 : A.height) >= h && (N.isHeavy = !0), _ == null || _.info("[%s] check wind: %j", n.requestId, { ...R, dgThd4Wd: M, svThd4Wd: y, hvThd4Wd: v }), (R == null ? void 0 : R.scale) >= M ? (N.isDangerous = !0, delete N.isSevere, delete N.isHeavy) : (R == null ? void 0 : R.scale) > y ? (N.isDangerous || (N.isSevere = !0), delete N.isHeavy) : (R == null ? void 0 : R.scale) === v && !N.isDangerous && !N.isSevere && (N.isHeavy = !0), i += N.isDangerous ? U : 0, o += N.isSevere ? U : 0, a += N.isHeavy ? U : 0;
|
|
598
598
|
}
|
|
599
|
-
return
|
|
599
|
+
return i = Math.round(i * 100) / 100, o = Math.round(o * 100) / 100, a = Math.round(a * 100) / 100, s = Math.round(s), { sample: e, dangerous: i, severe: o, heavy: a, step: s < 3 ? 3 : s, wind: { dgThd4Wd: M, svThd4Wd: y, hvThd4Wd: v }, sig: { dgThd4Wv: d, svThd4Wv: r, hvThd4Wv: h } };
|
|
600
600
|
}
|
|
601
601
|
}
|
|
602
|
-
const
|
|
603
|
-
let
|
|
602
|
+
const Tt = new yt();
|
|
603
|
+
let F;
|
|
604
604
|
try {
|
|
605
|
-
|
|
605
|
+
F = rt.getLogger("vessel");
|
|
606
606
|
} catch {
|
|
607
607
|
} finally {
|
|
608
608
|
}
|
|
609
|
-
const
|
|
610
|
-
var
|
|
609
|
+
const Mt = new ft("", !0);
|
|
610
|
+
var gt = /* @__PURE__ */ ((E) => (E.common = "common", E.container = "container", E.tugs = "tugs", E))(gt || {}), bt = /* @__PURE__ */ ((E) => (E.Ballast = "Ballast", E.Laden = "Laden", E))(bt || {}), pt = /* @__PURE__ */ ((E) => (E.Cp = "CP", E.Perf = "Basis", E.Instruct = "Other", E))(pt || {});
|
|
611
611
|
class O {
|
|
612
612
|
/**
|
|
613
613
|
* @see https://baike.baidu.com/item/%E6%96%B9%E5%BD%A2%E7%B3%BB%E6%95%B0/4965568?fr=aladdin
|
|
@@ -621,11 +621,11 @@ class O {
|
|
|
621
621
|
* @param draught 吃水 m
|
|
622
622
|
* @return [0.55, 0.85]
|
|
623
623
|
*/
|
|
624
|
-
static blockCoefficient(e, t, n,
|
|
625
|
-
let
|
|
626
|
-
|
|
627
|
-
const
|
|
628
|
-
return
|
|
624
|
+
static blockCoefficient(e, t, n, i) {
|
|
625
|
+
let o = Math.round(e / (t * n * i) * 100) / 100;
|
|
626
|
+
o = o < 0.55 ? 0.55 : o > 0.85 ? 0.85 : o;
|
|
627
|
+
const a = [0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85], s = a.map((d) => Math.abs(d - o));
|
|
628
|
+
return a[s.indexOf(Math.min(...s))];
|
|
629
629
|
}
|
|
630
630
|
/**
|
|
631
631
|
* @see https://baike.baidu.com/item/%E5%BC%97%E5%8A%B3%E5%BE%B7%E6%95%B0/228891?fromModule=search-result_lemma-recommend
|
|
@@ -639,8 +639,8 @@ class O {
|
|
|
639
639
|
* @return [0.05, 0.30]
|
|
640
640
|
*/
|
|
641
641
|
static froudeNumber(e, t, n = 9.8) {
|
|
642
|
-
let
|
|
643
|
-
return
|
|
642
|
+
let i = Math.round(Math.sqrt(e * e / (n * t)) * 100) / 100;
|
|
643
|
+
return i = i < 0.05 ? 0.05 : i > 0.3 ? 0.3 : i, i;
|
|
644
644
|
}
|
|
645
645
|
/**
|
|
646
646
|
* 失速修正系數
|
|
@@ -650,7 +650,7 @@ class O {
|
|
|
650
650
|
* @private
|
|
651
651
|
*/
|
|
652
652
|
static amendFactor(e, t, n) {
|
|
653
|
-
const
|
|
653
|
+
const i = {
|
|
654
654
|
0.55: [1.7, -1.4, -7.4],
|
|
655
655
|
0.6: [2.2, -2.5, -9.7],
|
|
656
656
|
0.65: [2.6, -3.7, -11.6],
|
|
@@ -659,7 +659,7 @@ class O {
|
|
|
659
659
|
0.8: [2.6, -13.1, -15.1],
|
|
660
660
|
0.85: [3.1, -18.7, 28]
|
|
661
661
|
};
|
|
662
|
-
let
|
|
662
|
+
let a = {
|
|
663
663
|
0.55: [1.7, -1.4, -7.4],
|
|
664
664
|
0.6: [2.2, -2.5, -9.7],
|
|
665
665
|
0.65: [2.6, -3.7, -11.6],
|
|
@@ -668,7 +668,7 @@ class O {
|
|
|
668
668
|
0.8: [3, -16.3, -21.6],
|
|
669
669
|
0.85: [3.4, -20.9, 31.8]
|
|
670
670
|
}[e];
|
|
671
|
-
return n === "Laden" && (
|
|
671
|
+
return n === "Laden" && (a = i[e]), a[0] + a[1] * t + a[2] * Math.pow(t, 2);
|
|
672
672
|
}
|
|
673
673
|
/**
|
|
674
674
|
* 失速方向因子
|
|
@@ -696,10 +696,10 @@ class O {
|
|
|
696
696
|
* @param bn
|
|
697
697
|
* @private
|
|
698
698
|
*/
|
|
699
|
-
static vesselTagFactor(e, t, n,
|
|
700
|
-
|
|
701
|
-
let
|
|
702
|
-
return n === "container" ?
|
|
699
|
+
static vesselTagFactor(e, t, n, i = 0) {
|
|
700
|
+
i = i > 6 ? i - 0.9 * (i - 6) : i;
|
|
701
|
+
let o;
|
|
702
|
+
return n === "container" ? o = 0.7 * i + Math.pow(i, 6.5) / (22 * Math.pow(e, 2 / 3)) : t === "Ballast" ? o = 0.7 * i + Math.pow(i, 6.5) / (2.7 * Math.pow(e, 2 / 3)) : o = 0.5 * i + Math.pow(i, 6.5) / (2.7 * Math.pow(e, 2 / 3)), o;
|
|
703
703
|
}
|
|
704
704
|
/**
|
|
705
705
|
* 浪高影响因子
|
|
@@ -719,21 +719,21 @@ class O {
|
|
|
719
719
|
* @param bearing 方位角
|
|
720
720
|
* @private
|
|
721
721
|
*/
|
|
722
|
-
static assembleProperties(e, t, n,
|
|
722
|
+
static assembleProperties(e, t, n, i) {
|
|
723
723
|
var y;
|
|
724
|
-
const
|
|
724
|
+
const o = e.lbp ?? e.length ?? e.lengthOverall ?? 198.9642, a = e.draught ?? 8, s = e.breadthMoulded ?? e.breadth ?? e.breadthExtreme ?? 32.4572, d = e.deadweight ?? 67035.7773, r = ((y = e == null ? void 0 : e.type) == null ? void 0 : y.toLowerCase()) || "common";
|
|
725
725
|
return {
|
|
726
|
-
tag:
|
|
727
|
-
lbp:
|
|
726
|
+
tag: r.indexOf("container") > -1 ? "container" : r.indexOf("tugs") > -1 ? "tugs" : "common",
|
|
727
|
+
lbp: o,
|
|
728
728
|
loadCondition: t,
|
|
729
|
-
draught:
|
|
729
|
+
draught: a,
|
|
730
730
|
breadthMoulded: s,
|
|
731
731
|
// 排水量(吨)= 载重量(吨)/ 1.025 + 吃水(米)× 船舶型宽(米)× 船舶型长(米)× 0.7
|
|
732
732
|
// 其中,1.025是指海水的密度,吨是指公吨,吃水是指船舶的最大吃水深度。船舶型宽是指船舶的最大型宽,船舶型长是指船舶的设计型长。上述公式是针对常规船舶适用的,不同类型的船舶可能会有一些差异。
|
|
733
|
-
displacement: Math.round((d / 1.025 +
|
|
733
|
+
displacement: Math.round((d / 1.025 + a * s * o * 0.7) * 1e4) / 1e4,
|
|
734
734
|
// 换算为m/s
|
|
735
735
|
speed: Math.round((n ?? 14.1382) * 1852 / 3600 * 1e4) / 1e4,
|
|
736
|
-
bearing:
|
|
736
|
+
bearing: i || 90
|
|
737
737
|
};
|
|
738
738
|
}
|
|
739
739
|
/**
|
|
@@ -746,37 +746,39 @@ class O {
|
|
|
746
746
|
* @param useMeteo true 启用气象分析
|
|
747
747
|
* @param useRouteParam true 启用设置速度
|
|
748
748
|
*/
|
|
749
|
-
static async speedLoseAt(e, t, n,
|
|
750
|
-
let
|
|
751
|
-
if (t.velocity && s && (e.speed = J.roundPrecision(t.velocity * 1852 / 3600, 6)),
|
|
749
|
+
static async speedLoseAt(e, t, n, i = "", o = 2, a = !0, s = !1, d = {}) {
|
|
750
|
+
let r;
|
|
751
|
+
if (t.velocity && s && (e.speed = J.roundPrecision(t.velocity * 1852 / 3600, 6)), a) {
|
|
752
752
|
let h;
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
}
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
753
|
+
try {
|
|
754
|
+
i = (i == null ? void 0 : i.toUpperCase()) === "CMEMS" ? "ECMWF" : i, i = (i == null ? void 0 : i.toUpperCase()) === "METEO2" ? "best_match" : i;
|
|
755
|
+
const { weatherModels: m, marineModels: C } = await it.autoPickMeteoModel(i), S = await Mt.spotForecast(t.lat, t.lng, n.utc().format(), !1, !1, !0, {
|
|
756
|
+
...d,
|
|
757
|
+
weatherModels: m,
|
|
758
|
+
marineModels: C
|
|
759
|
+
}), [w] = it.pickHourly(S, n);
|
|
760
|
+
h = it.toLegacy(w);
|
|
761
|
+
} catch (m) {
|
|
762
|
+
F.warn("[%s] meteo2 spot(%j) forecast failed: %s", d.requestId, { ...t, eta: n.utc().format(), source: i }, m);
|
|
763
|
+
}
|
|
764
|
+
const M = O.weatherFactor(e, h), y = O.currentFactor(e.bearing, h == null ? void 0 : h.current, o), v = Math.round((e.speed * 1.943844 + M + y) * 100) / 100;
|
|
765
|
+
r = {
|
|
764
766
|
meteo: { ...h },
|
|
765
767
|
wxFactor: M,
|
|
766
768
|
cFactor: y,
|
|
767
|
-
speed: t.velocity && s ? t.velocity :
|
|
769
|
+
speed: t.velocity && s ? t.velocity : v < 0 ? 1 : v,
|
|
768
770
|
eta: n.utc().format(),
|
|
769
771
|
etd: n.utc().format()
|
|
770
772
|
};
|
|
771
773
|
} else
|
|
772
|
-
|
|
774
|
+
r = {
|
|
773
775
|
wxFactor: 0,
|
|
774
776
|
cFactor: 0,
|
|
775
777
|
speed: t.velocity && s ? t.velocity : Math.round((e.speed * 1.943844 + 0 + 0) * 100) / 100,
|
|
776
778
|
eta: n.utc().format(),
|
|
777
779
|
etd: n.utc().format()
|
|
778
780
|
};
|
|
779
|
-
return delete t.meteo, delete t.wxFactor, delete t.cFactor, delete t.speed, delete t.etd, { ...
|
|
781
|
+
return delete t.meteo, delete t.wxFactor, delete t.cFactor, delete t.speed, delete t.etd, { ...r, ...t };
|
|
780
782
|
}
|
|
781
783
|
/**
|
|
782
784
|
* 基于步长计算失速样本
|
|
@@ -791,53 +793,53 @@ class O {
|
|
|
791
793
|
* @param useRouteParam true 启用航线上设置的参数 { suspend: 停留时长(小时), velocity: 速度(kts)}
|
|
792
794
|
* @private
|
|
793
795
|
*/
|
|
794
|
-
static async speedLoseInHoursStep(e, t, n,
|
|
796
|
+
static async speedLoseInHoursStep(e, t, n, i, o, a, s = "", d = !0, r = !1, h = {}) {
|
|
795
797
|
t.utc();
|
|
796
|
-
const M = t.clone().add(14, "days"), y = [],
|
|
797
|
-
let m = 0,
|
|
798
|
-
for (let b = 0; b <
|
|
799
|
-
let c =
|
|
800
|
-
c.distanceFromStart = Math.round((
|
|
801
|
-
const f =
|
|
802
|
-
if (e.bearing = W.calculateBearing(c, f, !f.gcToPrevious), c.bearing = e.bearing, c.suspend &&
|
|
798
|
+
const M = t.clone().add(14, "days"), y = [], v = [];
|
|
799
|
+
let m = 0, C = 0, S, w;
|
|
800
|
+
for (let b = 0; b < a.length - 1; b++) {
|
|
801
|
+
let c = a[b];
|
|
802
|
+
c.distanceFromStart = Math.round((o + C) * 1e4) / 1e4;
|
|
803
|
+
const f = a[b + 1];
|
|
804
|
+
if (e.bearing = W.calculateBearing(c, f, !f.gcToPrevious), c.bearing = e.bearing, c.suspend && r) {
|
|
803
805
|
c.eta = c.eta || t.utc().format(), c.elapsed = c.elapsed ?? 0;
|
|
804
806
|
const I = c.suspend - c.elapsed;
|
|
805
|
-
if (
|
|
806
|
-
|
|
807
|
+
if (i - m > I)
|
|
808
|
+
i = i - m - I, t.add(I, "hour"), c.elapsed = c.suspend;
|
|
807
809
|
else {
|
|
808
|
-
const
|
|
809
|
-
c.elapsed +=
|
|
810
|
+
const k = i - m;
|
|
811
|
+
c.elapsed += k, t.add(k, "hour"), i = 0;
|
|
810
812
|
}
|
|
811
|
-
if (
|
|
812
|
-
return c.distanceFromPrevious =
|
|
813
|
+
if (F == null || F.info(`[%s] suspend ${c.elapsed} hours at %j, and remain ${i} hours need to go...`, h.requestId, c), i === 0)
|
|
814
|
+
return c.distanceFromPrevious = C, { etd: t, from: w || c, to: c, next: a.filter((k) => k), wps: y, days: v };
|
|
813
815
|
} else
|
|
814
816
|
c.suspend = 0;
|
|
815
|
-
d = t.isAfter(M) ? !1 : d, c = await O.speedLoseAt(e, c, t, s, 0, d,
|
|
817
|
+
d = t.isAfter(M) ? !1 : d, c = await O.speedLoseAt(e, c, t, s, 0, d, r, h), w = w || c, c.important && y.push(c), t.isSameOrAfter(n) && (v.push(c), n.add(24, "hour"));
|
|
816
818
|
const l = W.calculateDistance(c, f, !f.gcToPrevious);
|
|
817
|
-
let u = Math.round(l /
|
|
818
|
-
if (m + u <
|
|
819
|
-
if (m += u, t.add(u, "hour"), delete
|
|
819
|
+
let u = Math.round(l / w.speed * 1e5) / 1e5;
|
|
820
|
+
if (m + u < i) {
|
|
821
|
+
if (m += u, t.add(u, "hour"), delete a[b], F == null || F.debug(
|
|
820
822
|
`[%s] go to %j from %j with ${l}nm, and cost ${u} hours`,
|
|
821
823
|
h.requestId,
|
|
822
824
|
{ lat: f.lat, lng: f.lng },
|
|
823
|
-
{ lat:
|
|
824
|
-
),
|
|
825
|
-
|
|
825
|
+
{ lat: w.lat, lng: w.lng, etd: w.etd }
|
|
826
|
+
), C += l, a.filter((I) => I).length <= 1) {
|
|
827
|
+
S = f, S.eta = t.utc().format(), S.distanceFromPrevious = l, S.distanceFromStart = Math.round((o + C) * 1e4) / 1e4, y.push(S), delete a[b + 1];
|
|
826
828
|
break;
|
|
827
829
|
}
|
|
828
830
|
} else {
|
|
829
|
-
u =
|
|
830
|
-
const I = J.roundPrecision(
|
|
831
|
-
|
|
831
|
+
u = i - m, t.add(u, "hour");
|
|
832
|
+
const I = J.roundPrecision(w.speed * u, 5);
|
|
833
|
+
S = W.calculateCoordinate(c, e.bearing, I, "nauticalmiles", !f.gcToPrevious), S.eta = t.utc().format(), a[b] = S, F == null || F.debug(
|
|
832
834
|
`[%s] go to %j from %j with ${I}nm, and cost ${u} hours`,
|
|
833
835
|
h.requestId,
|
|
834
|
-
{ lat:
|
|
836
|
+
{ lat: S.lat, lng: S.lng },
|
|
835
837
|
{ lat: c.lat, lng: c.lng, etd: c.etd }
|
|
836
|
-
),
|
|
838
|
+
), C += I, S.distanceFromPrevious = Math.round(C * 1e4) / 1e4, S.distanceFromStart = Math.round((o + C) * 1e4) / 1e4;
|
|
837
839
|
break;
|
|
838
840
|
}
|
|
839
841
|
}
|
|
840
|
-
return { etd: t, from:
|
|
842
|
+
return { etd: t, from: w, to: S, next: a.filter((b) => b), wps: y, days: v };
|
|
841
843
|
}
|
|
842
844
|
/**
|
|
843
845
|
* 洋流影响因子
|
|
@@ -846,11 +848,11 @@ class O {
|
|
|
846
848
|
* @param role 1: 船东, 2: 租家, 0: 未知
|
|
847
849
|
*/
|
|
848
850
|
static currentFactor(e, t, n = 0) {
|
|
849
|
-
const
|
|
850
|
-
if (Math.abs(
|
|
851
|
+
const i = (e - (t == null ? void 0 : t.degree) || 0) / 180 * Math.PI;
|
|
852
|
+
if (Math.abs(i) === Math.PI / 2)
|
|
851
853
|
return 0;
|
|
852
|
-
let
|
|
853
|
-
return n & 2 ?
|
|
854
|
+
let o = ((t == null ? void 0 : t.kts) || 0) * Math.cos(i);
|
|
855
|
+
return n & 2 ? o = Math.ceil(o * 100) / 100 : n & 1 ? o = Math.floor(o * 100) / 100 : o = Math.round(o * 100) / 100, Math.abs(o) > 5 ? 0 : o;
|
|
854
856
|
}
|
|
855
857
|
/**
|
|
856
858
|
* 风浪影响因子
|
|
@@ -858,16 +860,16 @@ class O {
|
|
|
858
860
|
* @param wwc 气象要素
|
|
859
861
|
*/
|
|
860
862
|
static weatherFactor(e, t) {
|
|
861
|
-
var M, y,
|
|
862
|
-
|
|
863
|
-
const n = O.blockCoefficient(e.displacement, e.lbp, e.breadthMoulded, e.draught),
|
|
864
|
-
let
|
|
865
|
-
|
|
866
|
-
const s = O.directionFactor(
|
|
867
|
-
let
|
|
868
|
-
|
|
869
|
-
const h = O.waveHeightFactor(((
|
|
870
|
-
return
|
|
863
|
+
var M, y, v, m, C, S, w;
|
|
864
|
+
F == null || F.debug("calculate weather factor via: %j", { ...e, ...t });
|
|
865
|
+
const n = O.blockCoefficient(e.displacement, e.lbp, e.breadthMoulded, e.draught), i = O.froudeNumber(e.speed, e.lbp), o = O.amendFactor(n, i, e.loadCondition);
|
|
866
|
+
let a = Math.abs(e.bearing % 360 - (((M = t == null ? void 0 : t.wind) == null ? void 0 : M.degree) % 360 || 0));
|
|
867
|
+
a = a > 180 ? 360 - a : a;
|
|
868
|
+
const s = O.directionFactor(a, (y = t == null ? void 0 : t.wind) == null ? void 0 : y.scale), d = O.vesselTagFactor(e.displacement, e.loadCondition, e.tag, (v = t == null ? void 0 : t.wind) == null ? void 0 : v.scale);
|
|
869
|
+
let r = s * o * d / 100 * e.speed;
|
|
870
|
+
r = Math.round(r * 1.943844 * 1e4) / 1e4 * -1, e.tag === "tugs" && Math.abs(r) > 1 && (r = r / (Math.abs(Math.round(r)) + 1)), F == null || F.debug("wind wx factor = %d", r), a = Math.abs(e.bearing % 360 - (((C = (m = t == null ? void 0 : t.wave) == null ? void 0 : m.sig) == null ? void 0 : C.degree) % 360 || 0));
|
|
871
|
+
const h = O.waveHeightFactor(((w = (S = t == null ? void 0 : t.wave) == null ? void 0 : S.sig) == null ? void 0 : w.height) ?? 1, a);
|
|
872
|
+
return F == null || F.debug("wave wx factor = %d", h), r = r * 0.4 + h, F == null || F.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;
|
|
871
873
|
}
|
|
872
874
|
/**
|
|
873
875
|
* 全程失速分析(走完航程)
|
|
@@ -881,79 +883,79 @@ class O {
|
|
|
881
883
|
* @param useMeteo true 启用气象分析
|
|
882
884
|
* @param useRouteParam
|
|
883
885
|
*/
|
|
884
|
-
static async analyseInstant(e, t, n,
|
|
885
|
-
var
|
|
886
|
+
static async analyseInstant(e, t, n, i, o, a = "", s = 0, d = !0, r = !1, h = {}) {
|
|
887
|
+
var z, G, Q, X, Z, $;
|
|
886
888
|
const M = g().valueOf();
|
|
887
889
|
e.lng = J.convertToStdLng(e.lng);
|
|
888
|
-
const { route: y, waypoints:
|
|
889
|
-
if (((
|
|
890
|
+
const { route: y, waypoints: v } = o.points, m = W.calculateSubRoute(e, y);
|
|
891
|
+
if (((z = m[0]) == null ? void 0 : z.length) <= 1)
|
|
890
892
|
return;
|
|
891
|
-
const { v0:
|
|
893
|
+
const { v0: C, label: S } = e.sog ? {
|
|
892
894
|
v0: e.sog,
|
|
893
|
-
label: "Other"
|
|
895
|
+
label: e.label || "Other"
|
|
894
896
|
/* Instruct */
|
|
895
897
|
} : {
|
|
896
|
-
v0:
|
|
898
|
+
v0: i.speed,
|
|
897
899
|
label: "CP"
|
|
898
900
|
/* Cp */
|
|
899
|
-
},
|
|
901
|
+
}, w = O.assembleProperties(n, i.loadCondition, C, 0), b = v.length ? W.calculateSubWaypoints(e, v) : [];
|
|
900
902
|
b.forEach((q) => q.important = !0);
|
|
901
903
|
const c = {
|
|
902
904
|
from: { ...e },
|
|
903
905
|
route: m,
|
|
904
906
|
waypoints: b,
|
|
905
|
-
v0:
|
|
906
|
-
label:
|
|
907
|
+
v0: C,
|
|
908
|
+
label: S
|
|
907
909
|
}, f = {
|
|
908
910
|
hours: [],
|
|
909
911
|
days: [],
|
|
910
912
|
wps: []
|
|
911
913
|
};
|
|
912
|
-
s || (W.calculateRouteDistance(m) /
|
|
913
|
-
let l = W.simplifyRouteToCoordinates(m, b, 0), u = 0, I = 0,
|
|
914
|
+
s || (W.calculateRouteDistance(m) / i.speed <= 72 ? s = 3 : s = 6);
|
|
915
|
+
let l = W.simplifyRouteToCoordinates(m, b, 0), u = 0, I = 0, k = 0, D = 0;
|
|
914
916
|
t = g(t).utc();
|
|
915
917
|
const Y = t.clone();
|
|
916
918
|
for (; l.length > 0; ) {
|
|
917
|
-
const q = s - t.hour() % s, V = Math.ceil(t.clone().add(q, "h").set({ minute: 0, second: 0, millisecond: 0 }).diff(t, "h", !0) * 1e4) / 1e4,
|
|
918
|
-
|
|
919
|
+
const q = s - t.hour() % s, V = Math.ceil(t.clone().add(q, "h").set({ minute: 0, second: 0, millisecond: 0 }).diff(t, "h", !0) * 1e4) / 1e4, x = await O.speedLoseInHoursStep(
|
|
920
|
+
w,
|
|
919
921
|
t,
|
|
920
922
|
Y,
|
|
921
923
|
V,
|
|
922
924
|
u,
|
|
923
925
|
l,
|
|
924
|
-
|
|
926
|
+
a,
|
|
925
927
|
d,
|
|
926
|
-
|
|
928
|
+
r,
|
|
927
929
|
h
|
|
928
930
|
);
|
|
929
|
-
(
|
|
931
|
+
(G = x.from) != null && G.speed && (f.hours.push(x.from), f.wps.push(...x.wps), f.days.push(...x.days)), l = x == null ? void 0 : x.next, l.length || f.hours.push(x == null ? void 0 : x.to), u += Math.round((((Q = x == null ? void 0 : x.to) == null ? void 0 : Q.distanceFromPrevious) ?? 0) * 1e4) / 1e4;
|
|
930
932
|
}
|
|
931
|
-
const
|
|
932
|
-
for (let q = 0; q <
|
|
933
|
-
const V = g(
|
|
934
|
-
I += (
|
|
933
|
+
const j = f.hours;
|
|
934
|
+
for (let q = 0; q < j.length - 1; q++) {
|
|
935
|
+
const V = g(j[q + 1].eta).diff(j[q].etd, "hour", !0) || 1;
|
|
936
|
+
I += (j[q].wxFactor || 0) * V, k += (j[q].cFactor || 0) * V, D += V;
|
|
935
937
|
}
|
|
936
938
|
(X = f.wps) == null || X.forEach((q, V) => {
|
|
937
939
|
q.positionTime = g.utc(q.etd || q.eta).unix();
|
|
938
|
-
const
|
|
939
|
-
if (
|
|
940
|
-
const L = q.distanceFromStart -
|
|
940
|
+
const x = f.wps[V - 1];
|
|
941
|
+
if (x) {
|
|
942
|
+
const L = q.distanceFromStart - x.distanceFromStart, H = g(q.eta || q.etd).diff(g(x.etd || x.eta), "h", !0);
|
|
941
943
|
q.avgSpd = Math.round(L / H * 100) / 100;
|
|
942
|
-
const nt = W.calculateBearing(
|
|
943
|
-
|
|
944
|
+
const nt = W.calculateBearing(x, q);
|
|
945
|
+
x.bearing = nt;
|
|
944
946
|
}
|
|
945
|
-
}), f.wps = (Z = f.wps) == null ? void 0 : Z.reduce((q, V) => (q.some((
|
|
947
|
+
}), f.wps = (Z = f.wps) == null ? void 0 : Z.reduce((q, V) => (q.some((x) => Math.round(x.positionTime / 60) === Math.round(V.positionTime / 60)) || q.push(V), q), []), c.sample = f;
|
|
946
948
|
const P = f.hours.at(0), T = f.hours.at(-1);
|
|
947
|
-
c.distance = Math.round(T.distanceFromStart * 1e4) / 1e4, c.etd = g(P.eta).utc().format(), c.eta = g(T.eta).utc().format(), c.wxFactor = Math.round(I / D * 1e4) / 1e4, c.cFactor = Math.round(
|
|
948
|
-
const { distanceInECA: N, hoursInECA: A, totalDgoConsInECA: R, eca:
|
|
949
|
+
c.distance = Math.round(T.distanceFromStart * 1e4) / 1e4, c.etd = g(P.eta).utc().format(), c.eta = g(T.eta).utc().format(), c.wxFactor = Math.round(I / D * 1e4) / 1e4, c.cFactor = Math.round(k / D * 1e4) / 1e4, c.avgSpeed = Math.round(T.distanceFromStart / D * 1e4) / 1e4, c.totalHrs = Math.round(D * 1e4) / 1e4;
|
|
950
|
+
const { distanceInECA: N, hoursInECA: A, totalDgoConsInECA: R, eca: U } = await this.calculateECA(c, i, h), st = J.roundPrecision(i.fo / 24 * (D - A), 3), at = J.roundPrecision(i.dgo / 24 * D, 3);
|
|
949
951
|
c.extend = {
|
|
950
|
-
eca:
|
|
952
|
+
eca: U,
|
|
951
953
|
distanceInECA: N,
|
|
952
954
|
hoursInECA: A,
|
|
953
955
|
totalDgoConsInECA: R
|
|
954
956
|
}, c.totalFoCons = st, c.totalDgoCons = at;
|
|
955
957
|
const tt = g().valueOf() - M, ot = (($ = f == null ? void 0 : f.hours) == null ? void 0 : $.length) || 1;
|
|
956
|
-
return
|
|
958
|
+
return F == null || F.info("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms", h == null ? void 0 : h.requestId, tt, ot, Math.round(tt / ot * 1e3) / 1e3), c;
|
|
957
959
|
}
|
|
958
960
|
/**
|
|
959
961
|
* 分段失速分析(最多走hours 小时)
|
|
@@ -968,25 +970,25 @@ class O {
|
|
|
968
970
|
* @param useMeteo true 启用气象分析
|
|
969
971
|
* @param useRouteParam
|
|
970
972
|
*/
|
|
971
|
-
static async analyseInstantWithThreshed(e, t, n,
|
|
973
|
+
static async analyseInstantWithThreshed(e, t, n, i, o, a, s, d = "", r = 3, h = !0, M = !1, y = {}) {
|
|
972
974
|
var Q, X, Z, $, q, V;
|
|
973
|
-
const
|
|
975
|
+
const v = g().valueOf();
|
|
974
976
|
e.lng = J.convertToStdLng(e.lng);
|
|
975
|
-
const { v0: m, label:
|
|
977
|
+
const { v0: m, label: C } = e.sog ? {
|
|
976
978
|
v0: e.sog,
|
|
977
|
-
label: "Other"
|
|
979
|
+
label: e.label || "Other"
|
|
978
980
|
/* Instruct */
|
|
979
981
|
} : {
|
|
980
|
-
v0:
|
|
982
|
+
v0: o.speed,
|
|
981
983
|
label: "CP"
|
|
982
984
|
/* Cp */
|
|
983
|
-
},
|
|
984
|
-
if (((Q =
|
|
985
|
+
}, S = O.assembleProperties(i, o.loadCondition, m, 0), w = W.calculateSubRoute(e, a);
|
|
986
|
+
if (((Q = w[0]) == null ? void 0 : Q.length) <= 1)
|
|
985
987
|
return;
|
|
986
988
|
const b = s.length ? W.calculateSubWaypoints(e, s) : [];
|
|
987
|
-
b.forEach((
|
|
988
|
-
let c = W.simplifyRouteToCoordinates(
|
|
989
|
-
const
|
|
989
|
+
b.forEach((x) => x.important = !0);
|
|
990
|
+
let c = W.simplifyRouteToCoordinates(w, b, 0), f = 0, l = 0, u = 0, I = 0;
|
|
991
|
+
const k = {
|
|
990
992
|
hours: [],
|
|
991
993
|
wps: [],
|
|
992
994
|
days: []
|
|
@@ -994,52 +996,52 @@ class O {
|
|
|
994
996
|
t = g(t).utc();
|
|
995
997
|
const D = t.clone();
|
|
996
998
|
for (; c.length > 0; ) {
|
|
997
|
-
const
|
|
998
|
-
let L = Math.ceil(t.clone().add(
|
|
999
|
+
const x = r - t.hour() % r;
|
|
1000
|
+
let L = Math.ceil(t.clone().add(x, "h").set({ minute: 0, second: 0, millisecond: 0 }).diff(t, "h", !0) * 1e4) / 1e4;
|
|
999
1001
|
L = t.clone().add(L, "h").isSameOrAfter(n) ? n.diff(t, "h", !0) * 1e4 / 1e4 : L;
|
|
1000
|
-
const H = await O.speedLoseInHoursStep(
|
|
1001
|
-
if ((X = H.from) != null && X.speed && (
|
|
1002
|
+
const H = await O.speedLoseInHoursStep(S, t, D, L, f, c, d, h, M, y);
|
|
1003
|
+
if ((X = H.from) != null && X.speed && (k.hours.push(H.from), H != null && H.wps && k.wps.push(...H.wps), k.days.push(...H.days)), c = H == null ? void 0 : H.next, c.length || k.hours.push(H == null ? void 0 : H.to), f += Math.round((((Z = H == null ? void 0 : H.to) == null ? void 0 : Z.distanceFromPrevious) ?? 0) * 1e4) / 1e4, !L)
|
|
1002
1004
|
break;
|
|
1003
1005
|
}
|
|
1004
|
-
|
|
1005
|
-
const H =
|
|
1006
|
+
k.wps = ($ = k.wps) == null ? void 0 : $.reduce((x, L) => (x.some((H) => Math.round(g(H.etd).unix() / 60) === Math.round(g(L.etd).unix() / 60)) || x.push(L), x), []), (q = k.wps) == null || q.forEach((x, L) => {
|
|
1007
|
+
const H = k.wps[L - 1];
|
|
1006
1008
|
if (H) {
|
|
1007
|
-
const nt =
|
|
1008
|
-
|
|
1009
|
-
const ut = W.calculateBearing(H,
|
|
1009
|
+
const nt = x.distanceFromStart - H.distanceFromStart, dt = g(x.eta || x.etd).diff(g(H.etd || H.eta), "h", !0);
|
|
1010
|
+
x.avgSpd = Math.round(nt / dt * 100) / 100;
|
|
1011
|
+
const ut = W.calculateBearing(H, x);
|
|
1010
1012
|
H.bearing = ut;
|
|
1011
1013
|
}
|
|
1012
1014
|
});
|
|
1013
|
-
const Y =
|
|
1014
|
-
for (let
|
|
1015
|
-
const L = g(Y[
|
|
1016
|
-
l += Y[
|
|
1015
|
+
const Y = k.hours;
|
|
1016
|
+
for (let x = 0; x < Y.length - 1; x++) {
|
|
1017
|
+
const L = g(Y[x + 1].eta).diff(Y[x].etd, "hour", !0);
|
|
1018
|
+
l += Y[x].wxFactor * L, u += Y[x].cFactor * L, I += L;
|
|
1017
1019
|
}
|
|
1018
|
-
const
|
|
1019
|
-
sample:
|
|
1020
|
+
const j = k.hours.at(0), P = k.hours.at(-1), T = await W.calculateRangeRoute(j, P, w), N = await W.calculateRangeWaypoints(j, P, w, b), A = {
|
|
1021
|
+
sample: k,
|
|
1020
1022
|
distance: Math.round(((P == null ? void 0 : P.distanceFromStart) || 0) * 1e4) / 1e4,
|
|
1021
1023
|
// 注意,可能会在first节点Drift,所有采用eta做为初始出发时间
|
|
1022
|
-
etd: g(
|
|
1024
|
+
etd: g(j.eta).utc().format(),
|
|
1023
1025
|
eta: g(P == null ? void 0 : P.eta).utc().format(),
|
|
1024
1026
|
wxFactor: Math.round(l / I * 1e4) / 1e4,
|
|
1025
1027
|
cFactor: Math.round(u / I * 1e4) / 1e4,
|
|
1026
1028
|
avgSpeed: Math.round(((P == null ? void 0 : P.distanceFromStart) || 0) / I * 1e4) / 1e4,
|
|
1027
1029
|
totalHrs: Math.round(I * 1e4) / 1e4,
|
|
1028
|
-
from:
|
|
1030
|
+
from: j,
|
|
1029
1031
|
to: P,
|
|
1030
1032
|
route: T,
|
|
1031
1033
|
waypoints: N,
|
|
1032
1034
|
v0: m,
|
|
1033
|
-
label:
|
|
1034
|
-
}, { distanceInECA: R, hoursInECA:
|
|
1035
|
+
label: C
|
|
1036
|
+
}, { distanceInECA: R, hoursInECA: U, totalDgoConsInECA: st, eca: at } = await this.calculateECA(A, o, y), ct = J.roundPrecision(o.fo / 24 * (I - U), 3), tt = J.roundPrecision(o.dgo / 24 * I, 3);
|
|
1035
1037
|
A.extend = {
|
|
1036
1038
|
eca: at,
|
|
1037
1039
|
distanceInECA: R,
|
|
1038
|
-
hoursInECA:
|
|
1040
|
+
hoursInECA: U,
|
|
1039
1041
|
totalDgoConsInECA: st
|
|
1040
|
-
}, A.totalDgoCons = tt, A.totalFoCons =
|
|
1041
|
-
const
|
|
1042
|
-
return
|
|
1042
|
+
}, A.totalDgoCons = tt, A.totalFoCons = ct;
|
|
1043
|
+
const z = g().valueOf() - v, G = ((V = k == null ? void 0 : k.hours) == null ? void 0 : V.length) || 1;
|
|
1044
|
+
return F == null || F.debug("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms", y == null ? void 0 : y.requestId, z, G, Math.round(z / G * 1e3) / 1e3), A;
|
|
1043
1045
|
}
|
|
1044
1046
|
/**
|
|
1045
1047
|
* 在指定航线条件下,基于多CP,动态计算最优成本(租金+油费)方案
|
|
@@ -1056,20 +1058,20 @@ class O {
|
|
|
1056
1058
|
* @param lane 基础航线(重要转向点)
|
|
1057
1059
|
* @param options
|
|
1058
1060
|
*/
|
|
1059
|
-
static async analyseCost(e, t, n,
|
|
1060
|
-
var
|
|
1061
|
-
const
|
|
1062
|
-
|
|
1063
|
-
const d = W.calculateRouteDistance(
|
|
1064
|
-
let
|
|
1061
|
+
static async analyseCost(e, t, n, i, o = {}) {
|
|
1062
|
+
var w, b;
|
|
1063
|
+
const a = g().valueOf(), s = [];
|
|
1064
|
+
e.speedStep = e.speedStep || 3, e.alterStep = e.alterStep ?? 1;
|
|
1065
|
+
const d = W.calculateRouteDistance(i.route);
|
|
1066
|
+
let r = 0;
|
|
1065
1067
|
n.forEach((c) => {
|
|
1066
1068
|
const f = Math.ceil(d / c.speed / 24);
|
|
1067
|
-
|
|
1068
|
-
}),
|
|
1069
|
-
const h = g.utc(e.etd).add(
|
|
1069
|
+
r = r < f ? f : r;
|
|
1070
|
+
}), r = r * 1.3;
|
|
1071
|
+
const h = g.utc(e.etd).add(r ?? 14, "day");
|
|
1070
1072
|
let M = 1;
|
|
1071
1073
|
for (const c of n) {
|
|
1072
|
-
const f = JSON.parse(JSON.stringify(
|
|
1074
|
+
const f = JSON.parse(JSON.stringify(i.route)), l = JSON.parse(JSON.stringify(i.waypoints)), u = await O.analyseInstantWithThreshed(
|
|
1073
1075
|
{ lat: e.lat, lng: e.lng },
|
|
1074
1076
|
e.etd,
|
|
1075
1077
|
h,
|
|
@@ -1081,9 +1083,9 @@ class O {
|
|
|
1081
1083
|
e.speedStep,
|
|
1082
1084
|
e.useMeteo,
|
|
1083
1085
|
e.useRouteParam,
|
|
1084
|
-
|
|
1086
|
+
o
|
|
1085
1087
|
);
|
|
1086
|
-
u && (await O.calculateCost(u, c, e,
|
|
1088
|
+
u && (await O.calculateCost(u, c, e, o), s.push(u), F == null || F.info("[%s][L%d-%d] analyse from %s to %s cost: %j", o.requestId, 1, M, e.etd, h.format(), {
|
|
1087
1089
|
cost: u.cost.total,
|
|
1088
1090
|
hire: u.cost.hire,
|
|
1089
1091
|
bunker: u.cost.bunker,
|
|
@@ -1093,22 +1095,22 @@ class O {
|
|
|
1093
1095
|
})), M++;
|
|
1094
1096
|
}
|
|
1095
1097
|
s.sort((c, f) => c.cost.total - f.cost.total);
|
|
1096
|
-
const y = s.at(0),
|
|
1097
|
-
if (m.push({ combined: !1, speeds: [y], cost: (
|
|
1098
|
-
const c = y.cost.cp, f =
|
|
1099
|
-
let
|
|
1100
|
-
|
|
1101
|
-
let D = 2, Y = { combined: !1, speeds: [
|
|
1102
|
-
for (;
|
|
1103
|
-
const P = await O.combinedAnalyse(e, t, h, [c, f],
|
|
1104
|
-
if (Y.cost > P.cost ?
|
|
1098
|
+
const y = s.at(0), v = s.at(1), m = [];
|
|
1099
|
+
if (m.push({ combined: !1, speeds: [y], cost: (w = y.cost) == null ? void 0 : w.total }), v) {
|
|
1100
|
+
const c = y.cost.cp, f = v.cost.cp, l = g(y.eta), u = g(y.etd), I = l.diff(u, "days", !0);
|
|
1101
|
+
let k = Math.ceil(I / 2);
|
|
1102
|
+
k = k > 7 ? 7 : k < e.alterStep ? e.alterStep : k;
|
|
1103
|
+
let D = 2, Y = { combined: !1, speeds: [v], cost: (b = v.cost) == null ? void 0 : b.total }, j;
|
|
1104
|
+
for (; k >= e.alterStep; ) {
|
|
1105
|
+
const P = await O.combinedAnalyse(e, t, h, [c, f], i, k, { ...o, level: D });
|
|
1106
|
+
if (Y.cost > P.cost ? j ? (j == null ? void 0 : j.cost) > P.cost && (j = P) : (j = Y, Y = P) : (!j || (j == null ? void 0 : j.cost) > P.cost) && (j = P), k <= e.alterStep)
|
|
1105
1107
|
break;
|
|
1106
|
-
|
|
1108
|
+
k = Math.ceil(k / 2), D += 1;
|
|
1107
1109
|
}
|
|
1108
|
-
m.push(Y),
|
|
1110
|
+
m.push(Y), j && m.push(j);
|
|
1109
1111
|
}
|
|
1110
|
-
const
|
|
1111
|
-
return
|
|
1112
|
+
const S = g().valueOf() - a;
|
|
1113
|
+
return F == null || F.info("[%s] analyse elapsed: %d ms", o == null ? void 0 : o.requestId, S), m.sort((c, f) => c.cost - f.cost);
|
|
1112
1114
|
}
|
|
1113
1115
|
/**
|
|
1114
1116
|
* 按步长多次减半,分别用7,4,2,1天步长及cpa,cpb交替计算各种组合下的成本
|
|
@@ -1120,24 +1122,24 @@ class O {
|
|
|
1120
1122
|
* @param step 步长,7,4,2,1
|
|
1121
1123
|
* @param options
|
|
1122
1124
|
*/
|
|
1123
|
-
static async combinedAnalyse(e, t, n,
|
|
1124
|
-
s.counter = 1,
|
|
1125
|
-
const d = await O.alternateAnalyse(e, t, n,
|
|
1126
|
-
|
|
1127
|
-
cost:
|
|
1125
|
+
static async combinedAnalyse(e, t, n, i, o, a, s = {}) {
|
|
1126
|
+
s.counter = 1, F == null || F.info("[%s][L%d] analyse with alternate cp in every %d days", s.requestId, s.level, a);
|
|
1127
|
+
const d = await O.alternateAnalyse(e, t, n, i, 0, o, a, s), r = d.reduce((f, l) => f + l.cost.total, 0), h = d.reduce((f, l) => f + l.cost.hire, 0), M = d.reduce((f, l) => f + l.cost.bunker, 0), y = d.reduce((f, l) => f + l.distance, 0), v = d.reduce((f, l) => f + l.totalHrs, 0);
|
|
1128
|
+
F == null || F.info("[%s][L%d] cost with cpa/cpb turn: %j", s.requestId, s.level, {
|
|
1129
|
+
cost: r,
|
|
1128
1130
|
hire: h,
|
|
1129
1131
|
bunker: M,
|
|
1130
1132
|
distance: y,
|
|
1131
|
-
hours:
|
|
1133
|
+
hours: v
|
|
1132
1134
|
});
|
|
1133
|
-
const m = await O.alternateAnalyse(e, t, n,
|
|
1134
|
-
return
|
|
1135
|
-
cost:
|
|
1136
|
-
hire:
|
|
1137
|
-
bunker:
|
|
1135
|
+
const m = await O.alternateAnalyse(e, t, n, i, 1, o, a, s), C = m.reduce((f, l) => f + l.cost.total, 0), S = m.reduce((f, l) => f + l.cost.hire, 0), w = m.reduce((f, l) => f + l.cost.bunker, 0), b = m.reduce((f, l) => f + l.distance, 0), c = m.reduce((f, l) => f + l.totalHrs, 0);
|
|
1136
|
+
return F == null || F.info("[%s][L%d] cost with cpb/cpa turn: %j", s.requestId, s.level, {
|
|
1137
|
+
cost: C,
|
|
1138
|
+
hire: S,
|
|
1139
|
+
bunker: w,
|
|
1138
1140
|
distance: b,
|
|
1139
1141
|
hours: c
|
|
1140
|
-
}),
|
|
1142
|
+
}), r < C ? { combined: !0, cost: Math.round(r * 1e3) / 1e3, speeds: d, step: a } : { combined: !0, cost: Math.round(C * 1e3) / 1e3, speeds: m, step: a };
|
|
1141
1143
|
}
|
|
1142
1144
|
/**
|
|
1143
1145
|
* 基于cp索引,交替计算指定步长下的成本
|
|
@@ -1150,31 +1152,31 @@ class O {
|
|
|
1150
1152
|
* @param step 步长,7,4,2,1
|
|
1151
1153
|
* @param options
|
|
1152
1154
|
*/
|
|
1153
|
-
static async alternateAnalyse(e, t, n,
|
|
1154
|
-
var y,
|
|
1155
|
-
let
|
|
1155
|
+
static async alternateAnalyse(e, t, n, i, o, a, s, d = {}) {
|
|
1156
|
+
var y, v;
|
|
1157
|
+
let r = g.utc(e.etd);
|
|
1156
1158
|
const h = { lat: e.lat, lng: e.lng }, M = [];
|
|
1157
|
-
for (;
|
|
1158
|
-
const m =
|
|
1159
|
+
for (; r.isBefore(n); ) {
|
|
1160
|
+
const m = r.clone().utc().add(s, "day"), C = JSON.parse(JSON.stringify(a.route)), S = JSON.parse(JSON.stringify(a.waypoints)), w = i[o], b = await O.analyseInstantWithThreshed(
|
|
1159
1161
|
h,
|
|
1160
|
-
|
|
1162
|
+
r.utc().format(),
|
|
1161
1163
|
m,
|
|
1162
1164
|
t,
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1165
|
+
w,
|
|
1166
|
+
C,
|
|
1167
|
+
S,
|
|
1166
1168
|
e.meteoVendor,
|
|
1167
1169
|
e.speedStep,
|
|
1168
1170
|
e.useMeteo,
|
|
1169
1171
|
e.useRouteParam,
|
|
1170
1172
|
d
|
|
1171
1173
|
);
|
|
1172
|
-
b && (await O.calculateCost(b,
|
|
1174
|
+
b && (await O.calculateCost(b, w, e, d), F == null || F.info(
|
|
1173
1175
|
"[%s][L%d-%d] analyse from %s to %s cost: %j",
|
|
1174
1176
|
d.requestId,
|
|
1175
1177
|
d.level,
|
|
1176
1178
|
d.counter,
|
|
1177
|
-
|
|
1179
|
+
r.utc().format(),
|
|
1178
1180
|
m.utc().format(),
|
|
1179
1181
|
{
|
|
1180
1182
|
cost: b.cost.total,
|
|
@@ -1182,12 +1184,12 @@ class O {
|
|
|
1182
1184
|
bunker: b.cost.bunker,
|
|
1183
1185
|
distance: b.distance,
|
|
1184
1186
|
hours: b.totalHrs,
|
|
1185
|
-
cp: `${
|
|
1187
|
+
cp: `${w.speed}/${w.fo}/${w.dgo}`
|
|
1186
1188
|
}
|
|
1187
1189
|
)), d.counter = d.counter + 1;
|
|
1188
|
-
const c = (
|
|
1190
|
+
const c = (v = (y = b == null ? void 0 : b.sample) == null ? void 0 : y.hours) == null ? void 0 : v.at(-1);
|
|
1189
1191
|
if (c)
|
|
1190
|
-
h.lat = c.lat, h.lng = c.lng,
|
|
1192
|
+
h.lat = c.lat, h.lng = c.lng, r = g(c.eta), M.push(b), o = o ? 0 : 1;
|
|
1191
1193
|
else
|
|
1192
1194
|
break;
|
|
1193
1195
|
}
|
|
@@ -1200,13 +1202,13 @@ class O {
|
|
|
1200
1202
|
* @param props
|
|
1201
1203
|
* @param options
|
|
1202
1204
|
*/
|
|
1203
|
-
static async calculateCost(e, t, n,
|
|
1204
|
-
var
|
|
1205
|
+
static async calculateCost(e, t, n, i = {}) {
|
|
1206
|
+
var o;
|
|
1205
1207
|
if (e) {
|
|
1206
|
-
const
|
|
1208
|
+
const a = Math.round(e.totalHrs / 24 * (n.dailyHire || 0) * (1 - (n.addComm || 0)) * 1e3) / 1e3, s = Math.round(e.totalFoCons * (n.priceFO || 0) * 1e3) / 1e3, d = Math.round((e.totalDgoCons + (((o = e.extend) == null ? void 0 : o.totalDgoConsInECA) || 0)) * (n.priceDGO || 0) * 1e3) / 1e3;
|
|
1207
1209
|
e.cost = {
|
|
1208
|
-
total: Math.round((
|
|
1209
|
-
hire:
|
|
1210
|
+
total: Math.round((a + s + d) * 1e3) / 1e3,
|
|
1211
|
+
hire: a,
|
|
1210
1212
|
bunker: Math.round((s + d) * 1e3) / 1e3,
|
|
1211
1213
|
cp: t
|
|
1212
1214
|
};
|
|
@@ -1217,22 +1219,22 @@ class O {
|
|
|
1217
1219
|
* 计算单cp模式下的ECA属性
|
|
1218
1220
|
*/
|
|
1219
1221
|
static async calculateECA(e, t, n = {}) {
|
|
1220
|
-
var d,
|
|
1221
|
-
const
|
|
1222
|
-
let
|
|
1222
|
+
var d, r;
|
|
1223
|
+
const i = await W.intersectInECA(e.route);
|
|
1224
|
+
let o = 0, a = 0, s = 0;
|
|
1223
1225
|
e.sample.wps.forEach((h) => {
|
|
1224
1226
|
h.positionTime = g.utc(h.etd || h.eta).unix();
|
|
1225
1227
|
});
|
|
1226
|
-
for (const h of
|
|
1227
|
-
|
|
1228
|
-
const M = await W.deadReckoningTime((d = h.waypoints) == null ? void 0 : d.at(0), e.sample.wps), y = await W.deadReckoningTime((
|
|
1229
|
-
h.in = M, h.out = y, h.totalHrs = J.roundPrecision((y.positionTime - M.positionTime) / 3600, 2), h.totalDgoCons = J.roundPrecision(t.fo / 24 * h.totalHrs, 3),
|
|
1228
|
+
for (const h of i) {
|
|
1229
|
+
o += h.distance;
|
|
1230
|
+
const M = await W.deadReckoningTime((d = h.waypoints) == null ? void 0 : d.at(0), e.sample.wps), y = await W.deadReckoningTime((r = h.waypoints) == null ? void 0 : r.at(-1), e.sample.wps);
|
|
1231
|
+
h.in = M, h.out = y, h.totalHrs = J.roundPrecision((y.positionTime - M.positionTime) / 3600, 2), h.totalDgoCons = J.roundPrecision(t.fo / 24 * h.totalHrs, 3), a += h.totalHrs, s += h.totalDgoCons;
|
|
1230
1232
|
}
|
|
1231
|
-
return
|
|
1232
|
-
distanceInECA:
|
|
1233
|
-
hoursInECA:
|
|
1233
|
+
return o = J.roundPrecision(o, 3), a = J.roundPrecision(a, 3), s = J.roundPrecision(s, 3), {
|
|
1234
|
+
distanceInECA: o,
|
|
1235
|
+
hoursInECA: a,
|
|
1234
1236
|
totalDgoConsInECA: s,
|
|
1235
|
-
eca:
|
|
1237
|
+
eca: i
|
|
1236
1238
|
};
|
|
1237
1239
|
}
|
|
1238
1240
|
/**
|
|
@@ -1246,35 +1248,35 @@ class O {
|
|
|
1246
1248
|
hours: [],
|
|
1247
1249
|
wps: [],
|
|
1248
1250
|
days: []
|
|
1249
|
-
},
|
|
1251
|
+
}, i = e.reduce((l, u) => l + u.distance, 0), o = e.reduce((l, u) => {
|
|
1250
1252
|
var I;
|
|
1251
1253
|
return l + (((I = u.extend) == null ? void 0 : I.distanceInECA) || 0);
|
|
1252
|
-
}, 0),
|
|
1254
|
+
}, 0), a = e.reduce((l, u) => l + u.totalHrs, 0), s = e.reduce((l, u) => {
|
|
1253
1255
|
var I;
|
|
1254
1256
|
return l + (((I = u.extend) == null ? void 0 : I.hoursInECA) || 0);
|
|
1255
1257
|
}, 0), d = e.reduce((l, u) => {
|
|
1256
1258
|
var I;
|
|
1257
1259
|
return l + (((I = u.extend) == null ? void 0 : I.totalDgoConsInECA) || 0);
|
|
1258
|
-
}, 0),
|
|
1260
|
+
}, 0), r = e.reduce((l, u) => l + u.wxFactor * u.totalHrs / a, 0), h = e.reduce((l, u) => l + u.cFactor * u.totalHrs / a, 0), M = e.reduce((l, u) => l + u.totalFoCons, 0), y = e.reduce((l, u) => l + u.totalDgoCons, 0), v = e.reduce((l, u) => l + u.cost.total, 0), m = e.reduce((l, u) => l + u.cost.hire, 0), C = e.reduce((l, u) => l + u.cost.bunker, 0), S = [], w = [];
|
|
1259
1261
|
let b;
|
|
1260
1262
|
for (const l of e) {
|
|
1261
|
-
|
|
1262
|
-
const u = l.sample.hours, I = l.sample.wps,
|
|
1263
|
+
w.push(...((c = l.extend) == null ? void 0 : c.eca) || []);
|
|
1264
|
+
const u = l.sample.hours, I = l.sample.wps, k = l.sample.days, D = u.at(0);
|
|
1263
1265
|
b && (D.distanceFromPrevious = b.distanceFromPrevious, D.distanceFromStart = b.distanceFromStart, u.forEach((T, N) => {
|
|
1264
1266
|
N && (T.distanceFromStart = T.distanceFromStart + b.distanceFromStart);
|
|
1265
1267
|
}), I.at(0).distanceFromPrevious = b.distanceFromPrevious, I.at(0).distanceFromStart = b.distanceFromStart, I.forEach((T, N) => {
|
|
1266
1268
|
N && (T.distanceFromStart = T.distanceFromStart + b.distanceFromStart);
|
|
1267
|
-
}),
|
|
1269
|
+
}), k.at(0).distanceFromPrevious = b.distanceFromPrevious, k.at(0).distanceFromStart = b.distanceFromStart, k.forEach((T, N) => {
|
|
1268
1270
|
N && (T.distanceFromStart = T.distanceFromStart + b.distanceFromStart);
|
|
1269
1271
|
})), D.cp = l.cost.cp;
|
|
1270
|
-
const Y = [l.etd, l.eta],
|
|
1271
|
-
|
|
1272
|
+
const Y = [l.etd, l.eta], j = S.findIndex((T) => T.id === D.cp.id);
|
|
1273
|
+
j === -1 ? (D.cp.segment = [Y], S.push(D.cp)) : S[j].segment.push(Y), u.forEach((T) => {
|
|
1272
1274
|
var A;
|
|
1273
1275
|
((A = n.hours) == null ? void 0 : A.findIndex((R) => R.eta === T.eta)) === -1 && n.hours.push(T);
|
|
1274
1276
|
}), I.forEach((T) => {
|
|
1275
1277
|
var A;
|
|
1276
1278
|
((A = n.wps) == null ? void 0 : A.findIndex((R) => R.eta === T.eta)) === -1 && n.wps.push(T);
|
|
1277
|
-
}),
|
|
1279
|
+
}), k.forEach((T) => {
|
|
1278
1280
|
var A;
|
|
1279
1281
|
((A = n == null ? void 0 : n.days) == null ? void 0 : A.findIndex((R) => R.eta === T.eta)) === -1 && n.days.push(T);
|
|
1280
1282
|
});
|
|
@@ -1286,10 +1288,10 @@ class O {
|
|
|
1286
1288
|
}), n.wps.forEach((l, u) => {
|
|
1287
1289
|
const I = n.wps[u - 1];
|
|
1288
1290
|
if (I) {
|
|
1289
|
-
const
|
|
1291
|
+
const k = l.distanceFromStart - (I.distanceFromStart || 0), D = g(l.eta || l.etd).diff(g(I.etd || I.eta), "hour", !0), Y = Math.round(k / D * 100) / 100;
|
|
1290
1292
|
l.avgSpd = Y;
|
|
1291
|
-
const
|
|
1292
|
-
I.bearing =
|
|
1293
|
+
const j = W.calculateBearing(I, l);
|
|
1294
|
+
I.bearing = j;
|
|
1293
1295
|
}
|
|
1294
1296
|
}), {
|
|
1295
1297
|
sample: n,
|
|
@@ -1299,22 +1301,22 @@ class O {
|
|
|
1299
1301
|
to: e.at(-1).to,
|
|
1300
1302
|
v0: e.at(0).v0,
|
|
1301
1303
|
label: "Combined",
|
|
1302
|
-
distance: Math.round(
|
|
1303
|
-
totalHrs: Math.round(
|
|
1304
|
-
avgSpeed: Math.round(
|
|
1305
|
-
wxFactor: Math.round(
|
|
1304
|
+
distance: Math.round(i * 1e4) / 1e4,
|
|
1305
|
+
totalHrs: Math.round(a * 1e3) / 1e3,
|
|
1306
|
+
avgSpeed: Math.round(i / a * 1e3) / 1e3,
|
|
1307
|
+
wxFactor: Math.round(r * 1e3) / 1e3,
|
|
1306
1308
|
cFactor: Math.round(h * 1e3) / 1e3,
|
|
1307
1309
|
totalFoCons: Math.round(M * 1e3) / 1e3,
|
|
1308
1310
|
totalDgoCons: Math.round(y * 1e3) / 1e3,
|
|
1309
1311
|
cost: {
|
|
1310
|
-
total: Math.round(
|
|
1312
|
+
total: Math.round(v * 1e3) / 1e3,
|
|
1311
1313
|
hire: Math.round(m * 1e3) / 1e3,
|
|
1312
|
-
bunker: Math.round(
|
|
1314
|
+
bunker: Math.round(C * 1e3) / 1e3
|
|
1313
1315
|
},
|
|
1314
1316
|
extend: {
|
|
1315
|
-
cps:
|
|
1316
|
-
eca:
|
|
1317
|
-
distanceInECA: Math.round(
|
|
1317
|
+
cps: S,
|
|
1318
|
+
eca: w,
|
|
1319
|
+
distanceInECA: Math.round(o * 1e4) / 1e4,
|
|
1318
1320
|
hoursInECA: Math.round(s * 1e3) / 1e3,
|
|
1319
1321
|
totalDgoConsInECA: Math.round(d * 1e3) / 1e3,
|
|
1320
1322
|
speeds: e
|
|
@@ -1324,15 +1326,15 @@ class O {
|
|
|
1324
1326
|
}
|
|
1325
1327
|
export {
|
|
1326
1328
|
et as AISImpl,
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
+
yt as AlertHelper,
|
|
1330
|
+
mt as AlertLevel,
|
|
1329
1331
|
Et as HifleetImpl,
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1332
|
+
bt as LoadCondition,
|
|
1333
|
+
Nt as MyShipImpl,
|
|
1334
|
+
xt as MyVesselImpl,
|
|
1335
|
+
jt as ShipxyImpl,
|
|
1334
1336
|
O as SpeedHelper,
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1337
|
+
pt as SpeedLabel,
|
|
1338
|
+
gt as VesselTag,
|
|
1339
|
+
Tt as alertHelper
|
|
1338
1340
|
};
|