@idm-plugin/vessel 3.7.3 → 3.7.5
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 +513 -512
- package/dist/index.umd.cjs +1 -1
- package/dist/speed/src/index.d.ts +9 -2
- package/package.json +3 -8
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
var ht = Object.defineProperty;
|
|
2
2
|
var mt = (x, e, t) => e in x ? ht(x, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : x[e] = t;
|
|
3
|
-
var
|
|
3
|
+
var K = (x, e, t) => (mt(x, typeof e != "symbol" ? e + "" : e, t), t);
|
|
4
4
|
import z from "got";
|
|
5
5
|
import ut from "@log4js-node/log4js-api";
|
|
6
6
|
import w from "moment";
|
|
@@ -57,9 +57,9 @@ class nt {
|
|
|
57
57
|
class Tt extends nt {
|
|
58
58
|
constructor(t, a) {
|
|
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 = a;
|
|
64
64
|
}
|
|
65
65
|
async authToken(t = {}) {
|
|
@@ -69,13 +69,13 @@ class Tt extends nt {
|
|
|
69
69
|
client_secret: this.clientSecret,
|
|
70
70
|
grant_type: "client_credentials"
|
|
71
71
|
}
|
|
72
|
-
},
|
|
73
|
-
g == null || g.info("[%s] fetch access token from: %s - %j", t.requestId, a,
|
|
74
|
-
accessToken:
|
|
75
|
-
tokenType:
|
|
76
|
-
expiresIn:
|
|
77
|
-
scope:
|
|
78
|
-
jti:
|
|
72
|
+
}, i = await z.post(a, o).json();
|
|
73
|
+
g == null || g.info("[%s] fetch access token from: %s - %j", t.requestId, a, i), i.error || (this.token = {
|
|
74
|
+
accessToken: i.access_token,
|
|
75
|
+
tokenType: i.token_type,
|
|
76
|
+
expiresIn: i.expires_in,
|
|
77
|
+
scope: i.scope,
|
|
78
|
+
jti: i.jti,
|
|
79
79
|
issuedAt: w().utc().format()
|
|
80
80
|
});
|
|
81
81
|
}
|
|
@@ -91,7 +91,7 @@ class Tt extends nt {
|
|
|
91
91
|
async suggest(t, a = {}) {
|
|
92
92
|
var s, r;
|
|
93
93
|
await this.checkToken(a);
|
|
94
|
-
const o = "https://market.myvessel.cn/sdc/v1/mkt/vessels/fuzzy",
|
|
94
|
+
const o = "https://market.myvessel.cn/sdc/v1/mkt/vessels/fuzzy", i = {
|
|
95
95
|
headers: {
|
|
96
96
|
Authorization: `${(s = this.token) == null ? void 0 : s.tokenType} ${(r = this.token) == null ? void 0 : r.accessToken}`
|
|
97
97
|
},
|
|
@@ -100,18 +100,18 @@ class Tt extends nt {
|
|
|
100
100
|
recordNum: a.ps || 10
|
|
101
101
|
}
|
|
102
102
|
};
|
|
103
|
-
g == null || g.info("[%s] fetch suggest vessels from: %s - %j", a.requestId, o,
|
|
104
|
-
const
|
|
105
|
-
return
|
|
106
|
-
mmsi:
|
|
107
|
-
name:
|
|
108
|
-
nameCn:
|
|
109
|
-
imo: Number.isNaN(
|
|
110
|
-
callSign:
|
|
111
|
-
type:
|
|
112
|
-
flagName:
|
|
103
|
+
g == null || g.info("[%s] fetch suggest vessels from: %s - %j", a.requestId, o, i);
|
|
104
|
+
const n = await z.post(o, i).json();
|
|
105
|
+
return n.status !== 200 ? (g == null || g.warn("[%s] fetch suggest vessels failed: %j", a.requestId, { message: n.message, status: n.status, code: n.code }), []) : (n.data || []).map((l) => ({
|
|
106
|
+
mmsi: l.mmsi,
|
|
107
|
+
name: l.nameEn,
|
|
108
|
+
nameCn: l.nameCn,
|
|
109
|
+
imo: Number.isNaN(l.imo) ? null : Number(l.imo),
|
|
110
|
+
callSign: l.callsign,
|
|
111
|
+
type: l.vesselTypeNameEn,
|
|
112
|
+
flagName: l.flagCtry,
|
|
113
113
|
vendor: "myvessel",
|
|
114
|
-
raw:
|
|
114
|
+
raw: l
|
|
115
115
|
}));
|
|
116
116
|
}
|
|
117
117
|
/**
|
|
@@ -120,43 +120,43 @@ class Tt extends nt {
|
|
|
120
120
|
* @param options
|
|
121
121
|
*/
|
|
122
122
|
async search(t, a = {}) {
|
|
123
|
-
var
|
|
123
|
+
var u, l;
|
|
124
124
|
await this.checkToken(a);
|
|
125
|
-
const o = /^\d{7}$/.test(t.toString()),
|
|
125
|
+
const o = /^\d{7}$/.test(t.toString()), i = o ? "https://market.myvessel.cn/sdc/v1/mkt/vessels/detail/imo" : "https://market.myvessel.cn/sdc/v1/mkt/vessels/detail/mmsi", n = o ? { imo: t } : { mmsi: t }, s = {
|
|
126
126
|
headers: {
|
|
127
|
-
Authorization: `${(
|
|
127
|
+
Authorization: `${(u = this.token) == null ? void 0 : u.tokenType} ${(l = this.token) == null ? void 0 : l.accessToken}`
|
|
128
128
|
},
|
|
129
|
-
searchParams:
|
|
129
|
+
searchParams: n
|
|
130
130
|
};
|
|
131
|
-
g == null || g.info("[%s] fetch vessel from: %s - %j", a.requestId,
|
|
132
|
-
const r = await z.get(
|
|
131
|
+
g == null || g.info("[%s] fetch vessel from: %s - %j", a.requestId, i, s);
|
|
132
|
+
const r = await z.get(i, s).json();
|
|
133
133
|
if (r.status !== 200)
|
|
134
134
|
return g == null || g.warn("[%s] fetch suggest vessels failed: %j", a.requestId, { message: r.message, status: r.status, code: r.code }), {};
|
|
135
135
|
{
|
|
136
|
-
const
|
|
137
|
-
if (
|
|
136
|
+
const h = r.data;
|
|
137
|
+
if (h)
|
|
138
138
|
return {
|
|
139
|
-
mmsi:
|
|
140
|
-
imo: Number.isNaN(
|
|
141
|
-
callSign:
|
|
142
|
-
name:
|
|
143
|
-
nameCn:
|
|
144
|
-
type:
|
|
145
|
-
flagName:
|
|
146
|
-
clasz:
|
|
147
|
-
dateOfBuild:
|
|
148
|
-
deadweight:
|
|
149
|
-
grossTonnage:
|
|
150
|
-
netTonnage:
|
|
151
|
-
teu:
|
|
152
|
-
length:
|
|
153
|
-
breadth:
|
|
154
|
-
height:
|
|
155
|
-
draught:
|
|
156
|
-
speed:
|
|
157
|
-
passengerCapacity:
|
|
139
|
+
mmsi: h.mmsi,
|
|
140
|
+
imo: Number.isNaN(h.imo) ? null : Number(h.imo),
|
|
141
|
+
callSign: h.callsign,
|
|
142
|
+
name: h.nameEn,
|
|
143
|
+
nameCn: h.nameCn,
|
|
144
|
+
type: h.vesselTypeNameEn,
|
|
145
|
+
flagName: h.flagCtry,
|
|
146
|
+
clasz: h.classSociety,
|
|
147
|
+
dateOfBuild: h.buildYearMonth,
|
|
148
|
+
deadweight: h.dwt,
|
|
149
|
+
grossTonnage: h.grt,
|
|
150
|
+
netTonnage: h.net,
|
|
151
|
+
teu: h.teu,
|
|
152
|
+
length: h.length,
|
|
153
|
+
breadth: h.width,
|
|
154
|
+
height: h.height,
|
|
155
|
+
draught: h.draught,
|
|
156
|
+
speed: h.speed,
|
|
157
|
+
passengerCapacity: h.passengercapacity,
|
|
158
158
|
vendor: "myvessel",
|
|
159
|
-
raw:
|
|
159
|
+
raw: h
|
|
160
160
|
};
|
|
161
161
|
}
|
|
162
162
|
return {};
|
|
@@ -164,7 +164,7 @@ class Tt extends nt {
|
|
|
164
164
|
async archives(t, a = {}) {
|
|
165
165
|
var s, r;
|
|
166
166
|
await this.checkToken(a);
|
|
167
|
-
const o = "https://svc.data.myvessel.cn/sdc/v1/ship/info/batch",
|
|
167
|
+
const o = "https://svc.data.myvessel.cn/sdc/v1/ship/info/batch", i = {
|
|
168
168
|
headers: {
|
|
169
169
|
Authorization: `${(s = this.token) == null ? void 0 : s.tokenType} ${(r = this.token) == null ? void 0 : r.accessToken}`
|
|
170
170
|
},
|
|
@@ -172,28 +172,28 @@ class Tt extends nt {
|
|
|
172
172
|
mmsiList: typeof t == "number" ? [t] : t
|
|
173
173
|
}
|
|
174
174
|
};
|
|
175
|
-
g == null || g.info("[%s] fetch vessel archive from: %s - %j", a.requestId, o,
|
|
176
|
-
const
|
|
177
|
-
return
|
|
175
|
+
g == null || g.info("[%s] fetch vessel archive from: %s - %j", a.requestId, o, i);
|
|
176
|
+
const n = await z.post(o, i).json();
|
|
177
|
+
return n.status !== 200 ? (g == null || g.warn("[%s] fetch vessel archive failed: %j", a.requestId, { message: n.message, status: n.status, code: n.code }), {}) : n.data;
|
|
178
178
|
}
|
|
179
179
|
async realTimePosition(t, a = {}) {
|
|
180
|
-
var r,
|
|
180
|
+
var r, u;
|
|
181
181
|
await this.checkToken(a);
|
|
182
|
-
const o = "https://svc.data.myvessel.cn/sdc/v1/vessels/status/location/unit",
|
|
182
|
+
const o = "https://svc.data.myvessel.cn/sdc/v1/vessels/status/location/unit", i = {
|
|
183
183
|
headers: {
|
|
184
|
-
Authorization: `${(r = this.token) == null ? void 0 : r.tokenType} ${(
|
|
184
|
+
Authorization: `${(r = this.token) == null ? void 0 : r.tokenType} ${(u = this.token) == null ? void 0 : u.accessToken}`
|
|
185
185
|
},
|
|
186
186
|
searchParams: { mmsi: t }
|
|
187
187
|
};
|
|
188
|
-
g == null || g.info("[%s] fetch realtime position from: %s - %j", a.requestId, o,
|
|
189
|
-
const
|
|
190
|
-
if (
|
|
191
|
-
return g == null || g.warn("[%s] fetch realtime position failed: %j", a.requestId, { message:
|
|
192
|
-
const s =
|
|
193
|
-
for (const
|
|
194
|
-
!isNaN(s[
|
|
188
|
+
g == null || g.info("[%s] fetch realtime position from: %s - %j", a.requestId, o, i);
|
|
189
|
+
const n = await z.get(o, i).json();
|
|
190
|
+
if (n.code)
|
|
191
|
+
return g == null || g.warn("[%s] fetch realtime position failed: %j", a.requestId, { message: n.message, status: n.status, code: n.code }), n;
|
|
192
|
+
const s = n.data;
|
|
193
|
+
for (const l in s)
|
|
194
|
+
!isNaN(s[l]) && Number(s[l]) !== 1 / 0 && (s[l] = Number(s[l]));
|
|
195
195
|
if (s) {
|
|
196
|
-
const
|
|
196
|
+
const l = w(`${s.postime} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
197
197
|
return {
|
|
198
198
|
mmsi: s.mmsi,
|
|
199
199
|
name: s.vesselName || s.aisVesselName,
|
|
@@ -210,7 +210,7 @@ class Tt extends nt {
|
|
|
210
210
|
rot: s.rot,
|
|
211
211
|
eta: /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(s.eta) ? w.utc(s.eta).format() : void 0,
|
|
212
212
|
destination: s.dest,
|
|
213
|
-
positionTime:
|
|
213
|
+
positionTime: l.unix(),
|
|
214
214
|
status: s.status,
|
|
215
215
|
labelCn: s.statusNameCn,
|
|
216
216
|
labelEn: s.statusNameEn,
|
|
@@ -223,7 +223,7 @@ class Tt extends nt {
|
|
|
223
223
|
net: s.net,
|
|
224
224
|
method: "position",
|
|
225
225
|
vendor: "myVessel",
|
|
226
|
-
utc:
|
|
226
|
+
utc: l.utc().format()
|
|
227
227
|
};
|
|
228
228
|
} else
|
|
229
229
|
return {};
|
|
@@ -236,35 +236,35 @@ class Tt extends nt {
|
|
|
236
236
|
* @param excludeSeas 排除水域, [sea.code]
|
|
237
237
|
* @param options { requiretId: '请求ID', useAIModel: '启用AI算法', withECA: '是否计算低硫区航行距离', withSpecial: '是否计算穿越的特战区列表和海盗区列表', draught: '最大吃水' }
|
|
238
238
|
*/
|
|
239
|
-
async calculateRoute(t, a, o,
|
|
240
|
-
var
|
|
239
|
+
async calculateRoute(t, a, o, i, n, s = {}) {
|
|
240
|
+
var I, b, E;
|
|
241
241
|
const r = w();
|
|
242
242
|
await this.checkToken(s);
|
|
243
|
-
const
|
|
243
|
+
const u = "https://market.myvessel.cn/sdc/v1/mkt/routes/plan", l = {
|
|
244
244
|
maxDraught: s.draught || 10,
|
|
245
245
|
useAIModel: s.useAIModel ?? !0,
|
|
246
246
|
withECA: s.withECA || !1,
|
|
247
247
|
withSpecialRegion: s.withSpecial || !1
|
|
248
248
|
};
|
|
249
|
-
t.code && (
|
|
249
|
+
t.code && (l.startPortCode = t.code), t.lng !== void 0 && t.lat !== void 0 && (l.startPoint = {
|
|
250
250
|
lon: t.lng,
|
|
251
251
|
lat: t.lat
|
|
252
|
-
}), a.code && (
|
|
252
|
+
}), a.code && (l.endPortCode = a.code), a.lng !== void 0 && a.lat !== void 0 && (l.endPoint = {
|
|
253
253
|
lon: a.lng,
|
|
254
254
|
lat: a.lat
|
|
255
|
-
}), o != null && o.length && (
|
|
256
|
-
const
|
|
255
|
+
}), o != null && o.length && (l.crossMonthList = o), i != null && i.length && (l.excludeNodes = i), n != null && n.length && (l.excludeSeaAreas = n);
|
|
256
|
+
const h = {
|
|
257
257
|
headers: {
|
|
258
|
-
Authorization: `${(
|
|
258
|
+
Authorization: `${(I = this.token) == null ? void 0 : I.tokenType} ${(b = this.token) == null ? void 0 : b.accessToken}`
|
|
259
259
|
},
|
|
260
|
-
json:
|
|
260
|
+
json: l
|
|
261
261
|
};
|
|
262
|
-
g == null || g.info("[%s] fetch route from: %s - %j", s.requestId,
|
|
263
|
-
const
|
|
264
|
-
if (
|
|
265
|
-
return g == null || g.warn("[%s] fetch route failed: %j", s.requestId, { message:
|
|
262
|
+
g == null || g.info("[%s] fetch route from: %s - %j", s.requestId, u, h);
|
|
263
|
+
const d = await z.post(u, h).json();
|
|
264
|
+
if (d.status !== 200)
|
|
265
|
+
return g == null || g.warn("[%s] fetch route failed: %j", s.requestId, { message: d.message, status: d.status, code: d.code }), {};
|
|
266
266
|
{
|
|
267
|
-
const
|
|
267
|
+
const k = {
|
|
268
268
|
status: "Success",
|
|
269
269
|
nodes: [],
|
|
270
270
|
seas: [],
|
|
@@ -273,8 +273,8 @@ class Tt extends nt {
|
|
|
273
273
|
route: [],
|
|
274
274
|
distance: 0,
|
|
275
275
|
memo: ""
|
|
276
|
-
}, { nodes: p, seas: v, tracks: m, specialRegions:
|
|
277
|
-
|
|
276
|
+
}, { nodes: p, seas: v, tracks: m, specialRegions: c, ecaLength: f } = d.data;
|
|
277
|
+
k.nodes = p == null ? void 0 : p.map((M) => ({
|
|
278
278
|
code: M.nodeCode,
|
|
279
279
|
nameEn: M.nameEn,
|
|
280
280
|
nameCn: M.nameCn,
|
|
@@ -297,7 +297,7 @@ class Tt extends nt {
|
|
|
297
297
|
isKey: M.isKeyNode,
|
|
298
298
|
// 重要枢纽节点
|
|
299
299
|
isHub: M.isHubNode
|
|
300
|
-
})),
|
|
300
|
+
})), k.seas = v == null ? void 0 : v.map((M) => ({
|
|
301
301
|
code: M.mrgidSea,
|
|
302
302
|
nameEn: M.nameEn,
|
|
303
303
|
nameCn: M.nameCn,
|
|
@@ -314,8 +314,8 @@ class Tt extends nt {
|
|
|
314
314
|
lng: Math.round(M.maxLon * 1e6) / 1e6
|
|
315
315
|
},
|
|
316
316
|
level: M.mapLevel
|
|
317
|
-
})),
|
|
318
|
-
M.regionLength &&
|
|
317
|
+
})), c == null || c.map((M) => {
|
|
318
|
+
M.regionLength && k.regions.push({
|
|
319
319
|
type: M.regionType,
|
|
320
320
|
distance: M.regionLength,
|
|
321
321
|
rows: M.regions.map((j) => ({
|
|
@@ -326,26 +326,26 @@ class Tt extends nt {
|
|
|
326
326
|
distance: j.length
|
|
327
327
|
}))
|
|
328
328
|
});
|
|
329
|
-
}),
|
|
329
|
+
}), k.waypoints = m == null ? void 0 : m.map((M) => ({
|
|
330
330
|
lat: Math.round(M.lat * 1e5) / 1e5,
|
|
331
331
|
lng: Math.round(M.lon * 1e5) / 1e5
|
|
332
|
-
})), (
|
|
333
|
-
const
|
|
334
|
-
return
|
|
332
|
+
})), (E = k.waypoints) != null && E.length && (k.waypoints = R.simplifyCoordinates(k.waypoints), k.route = R.divideAccordingToLng(k.waypoints), k.distance = R.calculateRouteDistance(k.route), k.distanceInECA = f);
|
|
333
|
+
const F = w().diff(r, "second");
|
|
334
|
+
return k.memo = `time cost: ${F}s`, g.info("[%s] calculate route cost: %d seconds", s.requestId, F), k;
|
|
335
335
|
}
|
|
336
336
|
}
|
|
337
|
-
async trajectory(t, a, o,
|
|
337
|
+
async trajectory(t, a, o, i, n = !0, s = {}) {
|
|
338
338
|
await this.checkToken(s);
|
|
339
|
-
const r = await this.realTimePosition(t, s),
|
|
340
|
-
for (;
|
|
341
|
-
await this.trajectoryIn30Day(t,
|
|
342
|
-
return await this.trajectoryIn30Day(t,
|
|
339
|
+
const r = await this.realTimePosition(t, s), u = w(a), l = w(o), h = [];
|
|
340
|
+
for (; l.diff(u, "day", !0) > 30; )
|
|
341
|
+
await this.trajectoryIn30Day(t, u, u.clone().add(30, "day"), r, i, h, s), u.add(30, "day");
|
|
342
|
+
return await this.trajectoryIn30Day(t, u, l, r, i, h, s), h;
|
|
343
343
|
}
|
|
344
|
-
async trajectoryIn30Day(t, a, o,
|
|
345
|
-
var b,
|
|
346
|
-
const
|
|
344
|
+
async trajectoryIn30Day(t, a, o, i, n, s, r = {}) {
|
|
345
|
+
var b, E, k, p, v;
|
|
346
|
+
const u = "https://svc.data.myvessel.cn/sdc/v1/vessels/status/track", l = {
|
|
347
347
|
headers: {
|
|
348
|
-
Authorization: `${(b = this.token) == null ? void 0 : b.tokenType} ${(
|
|
348
|
+
Authorization: `${(b = this.token) == null ? void 0 : b.tokenType} ${(E = this.token) == null ? void 0 : E.accessToken}`
|
|
349
349
|
},
|
|
350
350
|
json: {
|
|
351
351
|
mmsi: t,
|
|
@@ -353,18 +353,18 @@ class Tt extends nt {
|
|
|
353
353
|
endTime: o.utcOffset(8).format("YYYY-MM-DD HH:mm:ss")
|
|
354
354
|
}
|
|
355
355
|
};
|
|
356
|
-
g == null || g.info("[%s] fetch trajectory from: %s - %j", r.requestId,
|
|
357
|
-
const
|
|
358
|
-
if (
|
|
359
|
-
return g == null || g.warn("[%s] fetch trajectory failed: %j", r.requestId,
|
|
360
|
-
let
|
|
361
|
-
const
|
|
362
|
-
return (v =
|
|
356
|
+
g == null || g.info("[%s] fetch trajectory from: %s - %j", r.requestId, u, l);
|
|
357
|
+
const h = await z.post(u, l).json();
|
|
358
|
+
if (h.code)
|
|
359
|
+
return g == null || g.warn("[%s] fetch trajectory failed: %j", r.requestId, u, { message: h.message, status: h.status, code: h.code }), h;
|
|
360
|
+
let d = -1;
|
|
361
|
+
const I = w(`${(p = (k = h.data) == null ? void 0 : k[0]) == null ? void 0 : p.postime} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
362
|
+
return (v = h.data) == null || v.forEach((m) => {
|
|
363
363
|
for (const N in m)
|
|
364
364
|
!isNaN(m[N]) && Number(m[N]) !== 1 / 0 && (m[N] = Number(m[N]));
|
|
365
|
-
const
|
|
365
|
+
const c = w(`${m.postime} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00"), f = m.status, { labelCn: y, labelEn: F } = this.parseStatus(f), M = {
|
|
366
366
|
mmsi: m.mmsi,
|
|
367
|
-
imo:
|
|
367
|
+
imo: i == null ? void 0 : i.imo,
|
|
368
368
|
lat: m.lat,
|
|
369
369
|
lng: m.lon,
|
|
370
370
|
sog: m.sog,
|
|
@@ -374,38 +374,38 @@ class Tt extends nt {
|
|
|
374
374
|
status: f,
|
|
375
375
|
eta: /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(m.eta) ? w(`${m.eta} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00").utc().format() : void 0,
|
|
376
376
|
destination: m.dest,
|
|
377
|
-
positionTime:
|
|
377
|
+
positionTime: c.unix(),
|
|
378
378
|
labelCn: y,
|
|
379
|
-
labelEn:
|
|
379
|
+
labelEn: F,
|
|
380
380
|
method: "trajectory",
|
|
381
381
|
vendor: "myVessel",
|
|
382
|
-
utc:
|
|
383
|
-
}, j = Math.floor(
|
|
384
|
-
j !==
|
|
382
|
+
utc: c.utc().format()
|
|
383
|
+
}, j = Math.floor(c.diff(I, "minute", !0) / (n || 1));
|
|
384
|
+
j !== d && (d = j, s.push(M));
|
|
385
385
|
}), s;
|
|
386
386
|
}
|
|
387
387
|
}
|
|
388
388
|
class jt extends nt {
|
|
389
389
|
constructor(t) {
|
|
390
390
|
super();
|
|
391
|
-
|
|
391
|
+
K(this, "token");
|
|
392
392
|
this.token = t;
|
|
393
393
|
}
|
|
394
394
|
async realTimePosition(t, a = {}) {
|
|
395
|
-
const o = "https://api.hifleet.com/position/position/get/token",
|
|
395
|
+
const o = "https://api.hifleet.com/position/position/get/token", i = {
|
|
396
396
|
searchParams: {
|
|
397
397
|
mmsi: t,
|
|
398
398
|
usertoken: this.token
|
|
399
399
|
}
|
|
400
|
-
},
|
|
401
|
-
g == null || g.info("[%s] fetch realtime position from: %s - %j", a.requestId, o,
|
|
402
|
-
const s =
|
|
400
|
+
}, n = await z.post(o, i).json();
|
|
401
|
+
g == null || g.info("[%s] fetch realtime position from: %s - %j", a.requestId, o, i);
|
|
402
|
+
const s = n == null ? void 0 : n.list;
|
|
403
403
|
if (!s)
|
|
404
|
-
return g == null || g.warn("[%s] fetch realtime position failed: %j", a.requestId, o,
|
|
405
|
-
for (const
|
|
406
|
-
!isNaN(s[
|
|
404
|
+
return g == null || g.warn("[%s] fetch realtime position failed: %j", a.requestId, o, n), n;
|
|
405
|
+
for (const I in s)
|
|
406
|
+
!isNaN(s[I]) && Number(s[I]) !== 1 / 0 && (s[I] = Number(s[I]));
|
|
407
407
|
s.status = s.sp > 3 ? 0 : 1;
|
|
408
|
-
const r = s.status, { labelCn:
|
|
408
|
+
const r = s.status, { labelCn: u, labelEn: l } = this.parseStatus(r), h = w(`${s.ti} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
409
409
|
return {
|
|
410
410
|
mmsi: s.m,
|
|
411
411
|
name: s.n,
|
|
@@ -426,18 +426,18 @@ class jt extends nt {
|
|
|
426
426
|
dwt: s.dwt,
|
|
427
427
|
build: s.buildyear,
|
|
428
428
|
flag: s.fn,
|
|
429
|
-
positionTime:
|
|
430
|
-
utc:
|
|
429
|
+
positionTime: h.unix(),
|
|
430
|
+
utc: h.utc().format(),
|
|
431
431
|
status: r,
|
|
432
|
-
labelCn:
|
|
433
|
-
labelEn:
|
|
432
|
+
labelCn: u,
|
|
433
|
+
labelEn: l,
|
|
434
434
|
method: "position",
|
|
435
435
|
vendor: "hifleet"
|
|
436
436
|
};
|
|
437
437
|
}
|
|
438
438
|
async search(t, a = {}) {
|
|
439
439
|
let o = "https://www.hifleet.com/hifleetapi/searchVesselOL.do";
|
|
440
|
-
const
|
|
440
|
+
const i = {
|
|
441
441
|
searchParams: {
|
|
442
442
|
keyword: t
|
|
443
443
|
},
|
|
@@ -447,24 +447,24 @@ class jt extends nt {
|
|
|
447
447
|
Host: "www.hifleet.com"
|
|
448
448
|
}
|
|
449
449
|
};
|
|
450
|
-
let
|
|
451
|
-
g == null || g.info("[%s] fetch vessel props from: %s - %j", a.requestId, o,
|
|
452
|
-
for (const r in
|
|
453
|
-
!isNaN(
|
|
450
|
+
let n = await z.post(o, i).json();
|
|
451
|
+
g == null || g.info("[%s] fetch vessel props from: %s - %j", a.requestId, o, i), n instanceof Array && (n = n[0]);
|
|
452
|
+
for (const r in n)
|
|
453
|
+
!isNaN(n[r]) && Number(n[r]) !== 1 / 0 && (n[r] = Number(n[r]));
|
|
454
454
|
const s = {
|
|
455
|
-
mmsi:
|
|
456
|
-
name:
|
|
457
|
-
imo:
|
|
458
|
-
callSign:
|
|
459
|
-
length:
|
|
460
|
-
breadth:
|
|
461
|
-
draught:
|
|
462
|
-
type:
|
|
455
|
+
mmsi: n.m,
|
|
456
|
+
name: n.n,
|
|
457
|
+
imo: n.i,
|
|
458
|
+
callSign: n.c,
|
|
459
|
+
length: n.l,
|
|
460
|
+
breadth: n.b,
|
|
461
|
+
draught: n.dr,
|
|
462
|
+
type: n.t
|
|
463
463
|
};
|
|
464
|
-
return o = "https://www.hifleet.com/hifleetapi/sameShipSearch.do",
|
|
464
|
+
return o = "https://www.hifleet.com/hifleetapi/sameShipSearch.do", n = await z.post(o, i).json(), g == null || g.info("[%s] search vessel dead weight from: %s - %j", a.requestId, o, i), n instanceof Array && (n = n[0]), n && (s.deadweight = Number(n.dwt)), s;
|
|
465
465
|
}
|
|
466
466
|
async suggest(t, a = {}) {
|
|
467
|
-
const o = "https://www.hifleet.com/hifleetapi/getShipSuggest.do",
|
|
467
|
+
const o = "https://www.hifleet.com/hifleetapi/getShipSuggest.do", i = {
|
|
468
468
|
searchParams: {
|
|
469
469
|
q: t
|
|
470
470
|
},
|
|
@@ -473,10 +473,10 @@ class jt extends nt {
|
|
|
473
473
|
Origin: "https://www.hifleet.com",
|
|
474
474
|
Host: "www.hifleet.com"
|
|
475
475
|
}
|
|
476
|
-
},
|
|
477
|
-
g == null || g.info("[%s] suggest vessel props from: %s - %j", a.requestId, o,
|
|
476
|
+
}, n = await z.post(o, i).json();
|
|
477
|
+
g == null || g.info("[%s] suggest vessel props from: %s - %j", a.requestId, o, i);
|
|
478
478
|
const s = [];
|
|
479
|
-
for (const r of
|
|
479
|
+
for (const r of n)
|
|
480
480
|
s.push({
|
|
481
481
|
mmsi: !r.mmsi || isNaN(r.mmsi) ? null : Number(r.mmsi),
|
|
482
482
|
name: r.name,
|
|
@@ -484,35 +484,35 @@ class jt extends nt {
|
|
|
484
484
|
imo: !r.imo || isNaN(r.imo) ? null : Number(r.imo),
|
|
485
485
|
score: r._score
|
|
486
486
|
});
|
|
487
|
-
return s.sort((r,
|
|
487
|
+
return s.sort((r, u) => u.score - r.score), s;
|
|
488
488
|
}
|
|
489
|
-
async trajectory(t, a, o,
|
|
490
|
-
var m,
|
|
489
|
+
async trajectory(t, a, o, i, n = !0, s = {}) {
|
|
490
|
+
var m, c, f;
|
|
491
491
|
const r = await this.realTimePosition(t, s);
|
|
492
|
-
let
|
|
493
|
-
const
|
|
494
|
-
if (
|
|
495
|
-
let y =
|
|
496
|
-
y < 0 ?
|
|
492
|
+
let u = w(a);
|
|
493
|
+
const l = w(o), h = w();
|
|
494
|
+
if (n) {
|
|
495
|
+
let y = l.diff(u, "d", !0);
|
|
496
|
+
y < 0 ? u = l.clone().subtract(40, "d") : y < 30 ? u.subtract(10, "d") : y < 60 ? u.subtract(5, "d") : u = l.clone().subtract(80, "d"), y = h.diff(l, "d", !0), l.add(y > 10 ? 240 : y * 24, "h");
|
|
497
497
|
}
|
|
498
|
-
const
|
|
498
|
+
const d = {
|
|
499
499
|
searchParams: {
|
|
500
|
-
endtime:
|
|
501
|
-
starttime:
|
|
500
|
+
endtime: l.utcOffset("+8:00").format("YYYY-MM-DD HH:mm:ss"),
|
|
501
|
+
starttime: u.utcOffset("+8:00").format("YYYY-MM-DD HH:mm:ss"),
|
|
502
502
|
mmsi: t,
|
|
503
503
|
usertoken: this.token
|
|
504
504
|
}
|
|
505
|
-
},
|
|
506
|
-
g == null || g.info("[%s] fetch trajectory from: %s - %j", s.requestId,
|
|
507
|
-
let
|
|
508
|
-
b && (
|
|
509
|
-
const
|
|
505
|
+
}, I = "https://api.hifleet.com/position/trajectory/nocompressed/withstatic/token", b = await z.get(I, d).json();
|
|
506
|
+
g == null || g.info("[%s] fetch trajectory from: %s - %j", s.requestId, I, d);
|
|
507
|
+
let E;
|
|
508
|
+
b && (E = ((c = (m = b.ships) == null ? void 0 : m.offors) == null ? void 0 : c.ship) || [], E.length || g == null || g.warn("[%s] fetch trajectory failed: %j", s.requestId, b));
|
|
509
|
+
const k = [];
|
|
510
510
|
let p = -1;
|
|
511
|
-
const v = w(`${(f =
|
|
512
|
-
for (const y of
|
|
511
|
+
const v = w(`${(f = E == null ? void 0 : E[0]) == null ? void 0 : f.ti} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
512
|
+
for (const y of E) {
|
|
513
513
|
for (const L in y)
|
|
514
514
|
!isNaN(y[L]) && Number(y[L]) !== 1 / 0 && (y[L] = Number(y[L]));
|
|
515
|
-
const
|
|
515
|
+
const F = w(`${y.ti} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
516
516
|
y.status = y.sp > 4 ? 0 : 1;
|
|
517
517
|
const { labelEn: M, labelCn: j } = this.parseStatus(y.status), N = {
|
|
518
518
|
mmsi: y.m,
|
|
@@ -524,23 +524,23 @@ class jt extends nt {
|
|
|
524
524
|
sog: y.sp,
|
|
525
525
|
cog: y.co,
|
|
526
526
|
hdg: y.hdg,
|
|
527
|
-
positionTime:
|
|
528
|
-
utc:
|
|
527
|
+
positionTime: F.unix(),
|
|
528
|
+
utc: F.utc().format(),
|
|
529
529
|
status: y.status,
|
|
530
530
|
labelCn: j,
|
|
531
531
|
labelEn: M,
|
|
532
532
|
method: "trajectory",
|
|
533
533
|
vendor: "hifleet"
|
|
534
|
-
}, D = Math.floor(
|
|
535
|
-
D !== p && (p = D,
|
|
534
|
+
}, D = Math.floor(F.diff(v, "minute", !0) / (i || 1));
|
|
535
|
+
D !== p && (p = D, k.push(N));
|
|
536
536
|
}
|
|
537
|
-
return
|
|
537
|
+
return k;
|
|
538
538
|
}
|
|
539
539
|
}
|
|
540
540
|
class xt extends nt {
|
|
541
541
|
constructor(t) {
|
|
542
542
|
super();
|
|
543
|
-
|
|
543
|
+
K(this, "token");
|
|
544
544
|
this.token = t;
|
|
545
545
|
}
|
|
546
546
|
async realTimePosition(t, a = {}) {
|
|
@@ -550,13 +550,13 @@ class xt extends nt {
|
|
|
550
550
|
k: this.token,
|
|
551
551
|
enc: 1
|
|
552
552
|
}
|
|
553
|
-
},
|
|
554
|
-
if (g == null || g.info("[%s] fetch realtime position from: %s - %j", a.requestId,
|
|
555
|
-
return
|
|
556
|
-
const s =
|
|
557
|
-
for (const
|
|
558
|
-
!isNaN(s[
|
|
559
|
-
const { labelCn: r, labelEn:
|
|
553
|
+
}, i = "https://api.shipxy.com/apicall/GetSingleShip", n = await z.get(i, o).json();
|
|
554
|
+
if (g == null || g.info("[%s] fetch realtime position from: %s - %j", a.requestId, i, o), (n == null ? void 0 : n.status) !== 0)
|
|
555
|
+
return n;
|
|
556
|
+
const s = n.data[0];
|
|
557
|
+
for (const d in s)
|
|
558
|
+
!isNaN(s[d]) && Number(s[d]) !== 1 / 0 && (s[d] = Number(s[d]));
|
|
559
|
+
const { labelCn: r, labelEn: u } = await this.parseStatus(s.navistat), l = w.unix(s.lasttime);
|
|
560
560
|
return {
|
|
561
561
|
mmsi: s.ShipID,
|
|
562
562
|
name: s.name,
|
|
@@ -572,52 +572,52 @@ class xt extends nt {
|
|
|
572
572
|
hdg: Math.round(s.hdg / 100 * 100) / 100,
|
|
573
573
|
rot: Math.round(s.rot / 100 * 100) / 100,
|
|
574
574
|
positionTime: s.lasttime,
|
|
575
|
-
utc:
|
|
575
|
+
utc: l.utc().format(),
|
|
576
576
|
status: s.navistat,
|
|
577
|
-
labelEn:
|
|
577
|
+
labelEn: u,
|
|
578
578
|
labelCn: r,
|
|
579
579
|
method: "position",
|
|
580
580
|
vendor: "shipxy"
|
|
581
581
|
};
|
|
582
582
|
}
|
|
583
|
-
async trajectory(t, a, o,
|
|
583
|
+
async trajectory(t, a, o, i, n = !0, s = {}) {
|
|
584
584
|
var v;
|
|
585
|
-
const r = await this.realTimePosition(t, s),
|
|
585
|
+
const r = await this.realTimePosition(t, s), u = w(a), l = w(o), h = "https://api.shipxy.com/apicall/GetShipTrack", d = {
|
|
586
586
|
searchParams: {
|
|
587
587
|
id: t,
|
|
588
588
|
k: this.token,
|
|
589
589
|
enc: 1,
|
|
590
590
|
cut: 0,
|
|
591
|
-
btm:
|
|
592
|
-
etm:
|
|
591
|
+
btm: u.unix(),
|
|
592
|
+
etm: l.unix()
|
|
593
593
|
}
|
|
594
|
-
},
|
|
595
|
-
if (g == null || g.info("[%s] fetch trajectory from: %s - %j", s.requestId,
|
|
596
|
-
return
|
|
597
|
-
const b =
|
|
594
|
+
}, I = await z.get(h, d).json();
|
|
595
|
+
if (g == null || g.info("[%s] fetch trajectory from: %s - %j", s.requestId, h, d), (I == null ? void 0 : I.status) !== 0)
|
|
596
|
+
return I;
|
|
597
|
+
const b = I == null ? void 0 : I.points, E = [], k = w.unix((v = b[0]) == null ? void 0 : v.utc);
|
|
598
598
|
let p = -1;
|
|
599
599
|
for (const m of b) {
|
|
600
|
-
const
|
|
600
|
+
const c = w.unix(m.utc), f = {
|
|
601
601
|
imo: r == null ? void 0 : r.imo,
|
|
602
602
|
mmsi: t,
|
|
603
603
|
sog: Math.round(m.sog * 3600 / 1e3 / 1852 * 100) / 100,
|
|
604
604
|
cog: Math.round(m.cog / 100 * 100) / 100,
|
|
605
605
|
lat: Math.round(m.lat / 1e6 * 1e5) / 1e5,
|
|
606
606
|
lng: Math.round(m.lon / 1e6 * 1e5) / 1e5,
|
|
607
|
-
positionTime:
|
|
608
|
-
utc:
|
|
607
|
+
positionTime: c.unix(),
|
|
608
|
+
utc: c.utc().format(),
|
|
609
609
|
method: "trajectory",
|
|
610
610
|
vendor: "shipxy"
|
|
611
|
-
}, y = Math.floor(
|
|
612
|
-
y !== p && (p = y,
|
|
611
|
+
}, y = Math.floor(c.diff(k, "minute", !0) / (i || 1));
|
|
612
|
+
y !== p && (p = y, E.push(f));
|
|
613
613
|
}
|
|
614
|
-
return
|
|
614
|
+
return E;
|
|
615
615
|
}
|
|
616
616
|
}
|
|
617
617
|
class Nt extends nt {
|
|
618
618
|
constructor(t) {
|
|
619
619
|
super();
|
|
620
|
-
|
|
620
|
+
K(this, "token");
|
|
621
621
|
this.token = t;
|
|
622
622
|
}
|
|
623
623
|
async getShipId(t, a = {}) {
|
|
@@ -628,8 +628,8 @@ class Nt extends nt {
|
|
|
628
628
|
json: {
|
|
629
629
|
mmsiList: t
|
|
630
630
|
}
|
|
631
|
-
},
|
|
632
|
-
return g == null || g.info("[%s] fetch ship id from: %s - %j", a.requestId,
|
|
631
|
+
}, i = "https://api3.myships.com/sp/ships/getShipIdByMMSI", n = await z.post(i, o).json();
|
|
632
|
+
return g == null || g.info("[%s] fetch ship id from: %s - %j", a.requestId, i, o), n.code !== "0" ? n : n.data[0].shipId;
|
|
633
633
|
}
|
|
634
634
|
async getShipInfo(t, a = {}) {
|
|
635
635
|
const o = {
|
|
@@ -639,10 +639,10 @@ class Nt extends nt {
|
|
|
639
639
|
json: {
|
|
640
640
|
shipId: t
|
|
641
641
|
}
|
|
642
|
-
},
|
|
643
|
-
if (g == null || g.info("[%s] fetch ship info from: %s - %j", a.requestId,
|
|
644
|
-
return
|
|
645
|
-
const s =
|
|
642
|
+
}, i = "https://api3.myships.com/sp/ships/aissta", n = await z.post(i, o).json();
|
|
643
|
+
if (g == null || g.info("[%s] fetch ship info from: %s - %j", a.requestId, i, o), n.code !== "0")
|
|
644
|
+
return n;
|
|
645
|
+
const s = n.data;
|
|
646
646
|
let r = s.imo;
|
|
647
647
|
return t === "407170" && (r = "9198379", g == null || g.warn("[%s] ship(%s) imo error: %s, should be %s", a.requestId, t, s.imo, r)), {
|
|
648
648
|
mmsi: s.mmsi,
|
|
@@ -655,46 +655,46 @@ class Nt extends nt {
|
|
|
655
655
|
};
|
|
656
656
|
}
|
|
657
657
|
async realTimePosition(t, a = {}) {
|
|
658
|
-
const o = await this.getShipId(t, a),
|
|
658
|
+
const o = await this.getShipId(t, a), i = await this.getShipInfo(o, a), n = {
|
|
659
659
|
headers: {
|
|
660
660
|
appKey: this.token
|
|
661
661
|
},
|
|
662
662
|
json: {
|
|
663
663
|
shipId: o
|
|
664
664
|
}
|
|
665
|
-
}, s = "https://api3.myships.com/sp/ships/position/latest", r = await z.post(s,
|
|
666
|
-
g == null || g.info("[%s] fetch realtime position from: %s - %j", a.requestId, s,
|
|
667
|
-
const
|
|
668
|
-
for (const b in
|
|
669
|
-
!isNaN(
|
|
670
|
-
const { labelCn:
|
|
665
|
+
}, s = "https://api3.myships.com/sp/ships/position/latest", r = await z.post(s, n).json();
|
|
666
|
+
g == null || g.info("[%s] fetch realtime position from: %s - %j", a.requestId, s, n);
|
|
667
|
+
const u = r.data[0];
|
|
668
|
+
for (const b in u)
|
|
669
|
+
!isNaN(u[b]) && Number(u[b]) !== 1 / 0 && (u[b] = Number(u[b]));
|
|
670
|
+
const { labelCn: l, labelEn: h } = await this.parseStatus(u.aisNavStatus), d = w.unix(u.posTime);
|
|
671
671
|
return {
|
|
672
|
-
...
|
|
672
|
+
...i,
|
|
673
673
|
mmsi: t,
|
|
674
|
-
lat: Math.round(
|
|
675
|
-
lng: Math.round(
|
|
676
|
-
sog: Math.round(
|
|
677
|
-
cog: Math.round(
|
|
678
|
-
hdg: Math.round(
|
|
679
|
-
rot: Math.round(
|
|
680
|
-
positionTime:
|
|
681
|
-
utc:
|
|
682
|
-
status:
|
|
683
|
-
labelEn:
|
|
684
|
-
labelCn:
|
|
674
|
+
lat: Math.round(u.lat / 1e4 / 60 * 1e5) / 1e5,
|
|
675
|
+
lng: Math.round(u.lon / 1e4 / 60 * 1e5) / 1e5,
|
|
676
|
+
sog: Math.round(u.sog / 10 * 100) / 100,
|
|
677
|
+
cog: Math.round(u.cog / 10 * 100) / 100,
|
|
678
|
+
hdg: Math.round(u.heading * 100) / 100,
|
|
679
|
+
rot: Math.round(u.rot * 100) / 100,
|
|
680
|
+
positionTime: u.posTime,
|
|
681
|
+
utc: d.utc().format(),
|
|
682
|
+
status: u.aisNavStatus,
|
|
683
|
+
labelEn: h,
|
|
684
|
+
labelCn: l,
|
|
685
685
|
method: "position",
|
|
686
686
|
vendor: "myship"
|
|
687
687
|
};
|
|
688
688
|
}
|
|
689
|
-
async trajectory(t, a, o,
|
|
690
|
-
const r = w(a),
|
|
691
|
-
for (;
|
|
692
|
-
await this.trajectoryIn30Day(
|
|
693
|
-
return await this.trajectoryIn30Day(
|
|
689
|
+
async trajectory(t, a, o, i, n = !0, s = {}) {
|
|
690
|
+
const r = w(a), u = w(o), l = await this.getShipId(t), h = await this.getShipInfo(l), d = [];
|
|
691
|
+
for (; u.diff(r, "day", !0) > 30; )
|
|
692
|
+
await this.trajectoryIn30Day(l, r.unix(), r.add(30, "day").unix(), h, t, i, d);
|
|
693
|
+
return await this.trajectoryIn30Day(l, r.unix(), u.unix(), h, t, i, d), d;
|
|
694
694
|
}
|
|
695
|
-
async trajectoryIn30Day(t, a, o,
|
|
696
|
-
var
|
|
697
|
-
const
|
|
695
|
+
async trajectoryIn30Day(t, a, o, i, n, s, r, u = {}) {
|
|
696
|
+
var k;
|
|
697
|
+
const l = {
|
|
698
698
|
headers: {
|
|
699
699
|
appKey: this.token
|
|
700
700
|
},
|
|
@@ -703,18 +703,18 @@ class Nt extends nt {
|
|
|
703
703
|
startTime: a,
|
|
704
704
|
endTime: o
|
|
705
705
|
}
|
|
706
|
-
},
|
|
707
|
-
if (g == null || g.info("[%s] fetch trajectory from: %s - %j",
|
|
708
|
-
return g == null || g.warn("[%s] invoke myship trajectory failed: %j",
|
|
709
|
-
const
|
|
710
|
-
for (const p in
|
|
711
|
-
!isNaN(
|
|
712
|
-
const b = w.unix((
|
|
713
|
-
let
|
|
714
|
-
for (const p of
|
|
706
|
+
}, h = "https://api3.myships.com/sp/ships/position/history", d = await z.post(h, l).json();
|
|
707
|
+
if (g == null || g.info("[%s] fetch trajectory from: %s - %j", u.requestId, h, l), d.code !== "0")
|
|
708
|
+
return g == null || g.warn("[%s] invoke myship trajectory failed: %j", u.requestId, d), d;
|
|
709
|
+
const I = d.data;
|
|
710
|
+
for (const p in I)
|
|
711
|
+
!isNaN(I[p]) && Number(I[p]) !== 1 / 0 && (I[p] = Number(I[p]));
|
|
712
|
+
const b = w.unix((k = I[0]) == null ? void 0 : k.posTime);
|
|
713
|
+
let E = -1;
|
|
714
|
+
for (const p of I) {
|
|
715
715
|
const v = w.unix(p.posTime), m = {
|
|
716
|
-
imo:
|
|
717
|
-
mmsi:
|
|
716
|
+
imo: i == null ? void 0 : i.imo,
|
|
717
|
+
mmsi: n,
|
|
718
718
|
lat: Math.round(p.lat / 1e4 / 60 * 1e5) / 1e5,
|
|
719
719
|
lng: Math.round(p.lon / 1e4 / 60 * 1e5) / 1e5,
|
|
720
720
|
sog: Math.round(p.sog / 10 * 100) / 100,
|
|
@@ -725,15 +725,15 @@ class Nt extends nt {
|
|
|
725
725
|
utc: v.utc().format(),
|
|
726
726
|
method: "trajectory",
|
|
727
727
|
vendor: "myship"
|
|
728
|
-
},
|
|
729
|
-
|
|
728
|
+
}, c = Math.floor(v.diff(b, "minute", !0) / (s || 1));
|
|
729
|
+
c !== E && (E = c, r.push(m));
|
|
730
730
|
}
|
|
731
731
|
return r;
|
|
732
732
|
}
|
|
733
733
|
}
|
|
734
|
-
let
|
|
734
|
+
let _;
|
|
735
735
|
try {
|
|
736
|
-
|
|
736
|
+
_ = ut.getLogger("vessel");
|
|
737
737
|
} catch {
|
|
738
738
|
} finally {
|
|
739
739
|
}
|
|
@@ -748,23 +748,23 @@ class Mt {
|
|
|
748
748
|
* @param options
|
|
749
749
|
*/
|
|
750
750
|
parsePrinciple(e, t = {}) {
|
|
751
|
-
var s, r,
|
|
752
|
-
|
|
753
|
-
const a = new RegExp("(?<=\\[)(.+)(?=])", "g"), o = e.match(a) ? (s = e.match(a)) == null ? void 0 : s[0] : void 0,
|
|
754
|
-
if (!
|
|
751
|
+
var s, r, u;
|
|
752
|
+
_ == null || _.debug("[%s] parse rule: %s", t.requestId, e);
|
|
753
|
+
const a = new RegExp("(?<=\\[)(.+)(?=])", "g"), o = e.match(a) ? (s = e.match(a)) == null ? void 0 : s[0] : void 0, i = o == null ? void 0 : o.split(";");
|
|
754
|
+
if (!i)
|
|
755
755
|
return;
|
|
756
|
-
const
|
|
757
|
-
for (let
|
|
758
|
-
const
|
|
759
|
-
if (
|
|
760
|
-
|
|
761
|
-
else if (
|
|
762
|
-
for (let
|
|
763
|
-
const b = this.parseRule(
|
|
764
|
-
b && (
|
|
756
|
+
const n = {};
|
|
757
|
+
for (let l = 0; l < (i == null ? void 0 : i.length); l++) {
|
|
758
|
+
const h = (u = (r = i[l].match(a)) == null ? void 0 : r[0]) == null ? void 0 : u.split("],");
|
|
759
|
+
if (l === 0 && !h)
|
|
760
|
+
n.scope = i[0];
|
|
761
|
+
else if (h)
|
|
762
|
+
for (let d = 0, I = h.length; d < I; d++) {
|
|
763
|
+
const b = this.parseRule(h[d]);
|
|
764
|
+
b && (n[b.level] ? b.key ? n[b.level][b == null ? void 0 : b.key] = b : n[b.level] = b : b.key ? n[b.level] = { [b == null ? void 0 : b.key]: b } : n[b.level] = b);
|
|
765
765
|
}
|
|
766
766
|
}
|
|
767
|
-
return
|
|
767
|
+
return n;
|
|
768
768
|
}
|
|
769
769
|
/**
|
|
770
770
|
* 解析单一告警规则
|
|
@@ -773,17 +773,17 @@ class Mt {
|
|
|
773
773
|
* @param options
|
|
774
774
|
*/
|
|
775
775
|
parseRule(e, t = {}) {
|
|
776
|
-
var
|
|
777
|
-
|
|
778
|
-
const a = new RegExp("(?<=\\[)(.+?)(?=])", "g"), o = (
|
|
779
|
-
if (
|
|
780
|
-
let s =
|
|
776
|
+
var n;
|
|
777
|
+
_ == null || _.debug("[%s] parse rule: %s", t.requestId, e), e = e.startsWith("[") ? e : `[${e}`, e = e.endsWith("]") ? e : `${e}]`;
|
|
778
|
+
const a = new RegExp("(?<=\\[)(.+?)(?=])", "g"), o = (n = e == null ? void 0 : e.match(a)) == null ? void 0 : n[0], i = o == null ? void 0 : o.split(",");
|
|
779
|
+
if (i) {
|
|
780
|
+
let s = i[3] === "Number.MAX_VALUE" ? 100 : Number(i[3]);
|
|
781
781
|
return s = isNaN(s) ? 1 : s, {
|
|
782
|
-
operator:
|
|
783
|
-
number: Number.isNaN(Number(
|
|
784
|
-
level:
|
|
782
|
+
operator: i[0],
|
|
783
|
+
number: Number.isNaN(Number(i[1])) ? i[1] : Number(i[1]),
|
|
784
|
+
level: i[2],
|
|
785
785
|
time: s,
|
|
786
|
-
key:
|
|
786
|
+
key: i[4]
|
|
787
787
|
};
|
|
788
788
|
}
|
|
789
789
|
}
|
|
@@ -794,20 +794,20 @@ class Mt {
|
|
|
794
794
|
* @param options
|
|
795
795
|
*/
|
|
796
796
|
checkWeather(e, t, a = {}) {
|
|
797
|
-
var b,
|
|
798
|
-
let o = 0,
|
|
799
|
-
const r = Math.round(((
|
|
797
|
+
var b, E, k, p, v, m, c, f, y, F, M, j, N, D, L;
|
|
798
|
+
let o = 0, i = 0, n = 0, s = 0;
|
|
799
|
+
const r = Math.round(((E = (b = t == null ? void 0 : t.SEVERE) == null ? void 0 : b.sigWave) == null ? void 0 : E.number) * 1.6 * 100) / 100, u = (p = (k = t == null ? void 0 : t.SEVERE) == null ? void 0 : k.sigWave) == null ? void 0 : p.number, l = (m = (v = t == null ? void 0 : t.HEAVY) == null ? void 0 : v.sigWave) == null ? void 0 : m.number, h = Math.round((((f = (c = t == null ? void 0 : t.SEVERE) == null ? void 0 : c.wind) == null ? void 0 : f.number) + 2) * 100) / 100, d = (F = (y = t == null ? void 0 : t.SEVERE) == null ? void 0 : y.wind) == null ? void 0 : F.number, I = (j = (M = t == null ? void 0 : t.HEAVY) == null ? void 0 : M.wind) == null ? void 0 : j.number;
|
|
800
800
|
for (let W = 0; W < (e == null ? void 0 : e.length); W++) {
|
|
801
801
|
const C = e[W], Y = (D = (N = C == null ? void 0 : C.meteo) == null ? void 0 : N.wave) == null ? void 0 : D.sig, A = (L = C == null ? void 0 : C.meteo) == null ? void 0 : L.wind, V = W ? w(C.eta).diff(w(e[W - 1].eta), "hour", !0) : 0;
|
|
802
|
-
s = V > s ? V : s,
|
|
802
|
+
s = V > s ? V : s, _ == null || _.debug("[%s] check sig.wave: %j", a.requestId, { ...Y, dgThd4Wv: r, svThd4Wv: u, hvThd4Wv: l }), (Y == null ? void 0 : Y.height) >= r ? C.isDangerous = !0 : (Y == null ? void 0 : Y.height) >= u ? C.isSevere = !0 : (Y == null ? void 0 : Y.height) >= l && (C.isHeavy = !0), _ == null || _.debug("[%s] check wind: %j", a.requestId, { ...A, dgThd4Wd: h, svThd4Wd: d, hvThd4Wd: I }), (A == null ? void 0 : A.scale) >= h ? (C.isDangerous = !0, delete C.isSevere, delete C.isHeavy) : (A == null ? void 0 : A.scale) > d ? (C.isDangerous || (C.isSevere = !0), delete C.isHeavy) : (A == null ? void 0 : A.scale) === I && !C.isDangerous && !C.isSevere && (C.isHeavy = !0), o += C.isDangerous ? V : 0, i += C.isSevere ? V : 0, n += C.isHeavy ? V : 0;
|
|
803
803
|
}
|
|
804
|
-
return o = Math.round(o * 100) / 100,
|
|
804
|
+
return o = Math.round(o * 100) / 100, i = Math.round(i * 100) / 100, n = Math.round(n * 100) / 100, s = Math.round(s), { sample: e, dangerous: o, severe: i, heavy: n, step: s < 3 ? 3 : s, wind: { dgThd4Wd: h, svThd4Wd: d, hvThd4Wd: I }, sig: { dgThd4Wv: r, svThd4Wv: u, hvThd4Wv: l } };
|
|
805
805
|
}
|
|
806
806
|
}
|
|
807
807
|
const Dt = new Mt();
|
|
808
|
-
let
|
|
808
|
+
let S;
|
|
809
809
|
try {
|
|
810
|
-
|
|
810
|
+
S = ut.getLogger("vessel");
|
|
811
811
|
} catch {
|
|
812
812
|
} finally {
|
|
813
813
|
}
|
|
@@ -827,10 +827,10 @@ class H {
|
|
|
827
827
|
* @return [0.55, 0.85]
|
|
828
828
|
*/
|
|
829
829
|
static blockCoefficient(e, t, a, o) {
|
|
830
|
-
let
|
|
831
|
-
|
|
832
|
-
const
|
|
833
|
-
return
|
|
830
|
+
let i = Math.round(e / (t * a * o) * 100) / 100;
|
|
831
|
+
i = i < 0.55 ? 0.55 : i > 0.85 ? 0.85 : i;
|
|
832
|
+
const n = [0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85], s = n.map((r) => Math.abs(r - i));
|
|
833
|
+
return n[s.indexOf(Math.min(...s))];
|
|
834
834
|
}
|
|
835
835
|
/**
|
|
836
836
|
* @see https://baike.baidu.com/item/%E5%BC%97%E5%8A%B3%E5%BE%B7%E6%95%B0/228891?fromModule=search-result_lemma-recommend
|
|
@@ -864,7 +864,7 @@ class H {
|
|
|
864
864
|
0.8: [2.6, -13.1, -15.1],
|
|
865
865
|
0.85: [3.1, -18.7, 28]
|
|
866
866
|
};
|
|
867
|
-
let
|
|
867
|
+
let n = {
|
|
868
868
|
0.55: [1.7, -1.4, -7.4],
|
|
869
869
|
0.6: [2.2, -2.5, -9.7],
|
|
870
870
|
0.65: [2.6, -3.7, -11.6],
|
|
@@ -873,7 +873,7 @@ class H {
|
|
|
873
873
|
0.8: [3, -16.3, -21.6],
|
|
874
874
|
0.85: [3.4, -20.9, 31.8]
|
|
875
875
|
}[e];
|
|
876
|
-
return a === "Laden" && (
|
|
876
|
+
return a === "Laden" && (n = o[e]), n[0] + n[1] * t + n[2] * Math.pow(t, 2);
|
|
877
877
|
}
|
|
878
878
|
/**
|
|
879
879
|
* 失速方向因子
|
|
@@ -903,19 +903,20 @@ class H {
|
|
|
903
903
|
* @private
|
|
904
904
|
*/
|
|
905
905
|
static vesselTagFactor(e, t, a, o) {
|
|
906
|
-
let
|
|
907
|
-
return a === "container" ?
|
|
906
|
+
let i;
|
|
907
|
+
return a === "container" ? i = 0.7 * o / 2 + Math.pow(o, 3) / (22 * Math.pow(e, 2 / 3)) : t === "Ballast" ? i = 0.7 * o / 2 + Math.pow(o, 3) / (2.7 * Math.pow(e, 2 / 3)) : i = 0.5 * o / 2 + Math.pow(o, 3) / (2.7 * Math.pow(e, 2 / 3)), i;
|
|
908
908
|
}
|
|
909
909
|
/**
|
|
910
910
|
* 浪高影响因子
|
|
911
911
|
* @param ht 浪高,单位m
|
|
912
912
|
* @param beta 夹角
|
|
913
|
+
* @param _draught 吃水
|
|
913
914
|
* @private
|
|
914
915
|
*/
|
|
915
|
-
static waveHeightFactor(e, t) {
|
|
916
|
+
static waveHeightFactor(e, t, a = 10) {
|
|
916
917
|
e = e < 3 ? e * 0.7 : e, e = e < 0 ? 0.2 : e, e = e > 6 ? e - 0.9 * (e - 6) : e, e = e > 9 ? 9 : e;
|
|
917
|
-
let
|
|
918
|
-
return t > 30 && t <= 60 ?
|
|
918
|
+
let o;
|
|
919
|
+
return t > 30 && t <= 60 ? o = -0.6 : t > 60 && t <= 90 ? o = -0.5 : t > 90 && t <= 120 ? o = e < 4 ? 0.4 : -0.15 : t > 120 && t <= 150 ? o = e < 4 ? 0.5 : -0.12 : t > 150 && t <= 180 ? o = e < 4 ? 0.6 : -0.1 : o = -0.7, Math.round(o * (0.144 * Math.pow(e, 2) + 0.378 * e) * 1e4) / 1e4;
|
|
919
920
|
}
|
|
920
921
|
/**
|
|
921
922
|
* 组装船舶运行参数
|
|
@@ -926,17 +927,17 @@ class H {
|
|
|
926
927
|
* @private
|
|
927
928
|
*/
|
|
928
929
|
static assembleProperties(e, t, a, o) {
|
|
929
|
-
var
|
|
930
|
-
const
|
|
930
|
+
var d;
|
|
931
|
+
const i = e.lbp ?? e.length ?? e.lengthOverall ?? 198.9642, n = e.draught ?? 8, s = e.breadthMoulded ?? e.breadth ?? e.breadthExtreme ?? 32.4572, r = e.deadweight ?? 67035.7773, u = ((d = e == null ? void 0 : e.type) == null ? void 0 : d.toLowerCase()) || "common";
|
|
931
932
|
return {
|
|
932
|
-
tag:
|
|
933
|
-
lbp:
|
|
933
|
+
tag: u.indexOf("container") > -1 ? "container" : u.indexOf("tugs") > -1 ? "tugs" : "common",
|
|
934
|
+
lbp: i,
|
|
934
935
|
loadCondition: t,
|
|
935
|
-
draught:
|
|
936
|
+
draught: n,
|
|
936
937
|
breadthMoulded: s,
|
|
937
938
|
// 排水量(吨)= 载重量(吨)/ 1.025 + 吃水(米)× 船舶型宽(米)× 船舶型长(米)× 0.7
|
|
938
939
|
// 其中,1.025是指海水的密度,吨是指公吨,吃水是指船舶的最大吃水深度。船舶型宽是指船舶的最大型宽,船舶型长是指船舶的设计型长。上述公式是针对常规船舶适用的,不同类型的船舶可能会有一些差异。
|
|
939
|
-
displacement: Math.round((r / 1.025 +
|
|
940
|
+
displacement: Math.round((r / 1.025 + n * s * i * 0.7) * 1e4) / 1e4,
|
|
940
941
|
// 换算为m/s
|
|
941
942
|
speed: Math.round((a ?? 14.1382) * 1852 / 3600 * 1e4) / 1e4,
|
|
942
943
|
bearing: o || 90
|
|
@@ -953,47 +954,47 @@ class H {
|
|
|
953
954
|
* @param useRouteParam true 启用设置速度
|
|
954
955
|
* @param options
|
|
955
956
|
*/
|
|
956
|
-
static async speedLoseAt(e, t, a, o = "",
|
|
957
|
-
let
|
|
958
|
-
if (t.velocity && s && (e.speed = J.roundPrecision(t.velocity * 1852 / 3600, 6)),
|
|
959
|
-
let
|
|
957
|
+
static async speedLoseAt(e, t, a, o = "", i = 2, n = !0, s = !1, r = {}) {
|
|
958
|
+
let u;
|
|
959
|
+
if (t.velocity && s && (e.speed = J.roundPrecision(t.velocity * 1852 / 3600, 6)), n) {
|
|
960
|
+
let l;
|
|
960
961
|
try {
|
|
961
962
|
o = (o == null ? void 0 : o.toUpperCase()) === "CMEMS" ? "ECMWF" : o, o = (o == null ? void 0 : o.toUpperCase()) === "METEO2" ? "best_match" : o;
|
|
962
|
-
const { weatherModels:
|
|
963
|
+
const { weatherModels: k, marineModels: p } = await dt.autoPickMeteoModel(o), v = a.utc().format(), m = await gt.spotForecast(t.lat, t.lng, v, !1, !1, !0, {
|
|
963
964
|
...r,
|
|
964
965
|
pastDays: 1,
|
|
965
966
|
forecastDays: 2,
|
|
966
|
-
weatherModels:
|
|
967
|
+
weatherModels: k,
|
|
967
968
|
marineModels: p
|
|
968
|
-
}), [
|
|
969
|
-
|
|
970
|
-
} catch (
|
|
971
|
-
|
|
969
|
+
}), [c] = dt.pickHourly(m, a);
|
|
970
|
+
l = dt.toLegacy(c);
|
|
971
|
+
} catch (k) {
|
|
972
|
+
S.warn("[%s] meteo2 spot(%j) forecast failed: %s", r.requestId, { ...t, eta: a.utc().format(), source: o }, k);
|
|
972
973
|
}
|
|
973
|
-
let
|
|
974
|
-
const
|
|
975
|
-
|
|
974
|
+
let h = H.currentFactor(e.bearing, l == null ? void 0 : l.current, i, r), d = H.weatherFactor(e, l, h, r);
|
|
975
|
+
const I = e.speed * 1.943844;
|
|
976
|
+
I + h + d <= 0 && (S.warn(
|
|
976
977
|
"[%s] v0(%d) is less then factor(%d) = wxFactor(%d) + cFactor(%d), scale factor with 0.6",
|
|
977
978
|
r.requestId,
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
),
|
|
983
|
-
const b =
|
|
984
|
-
h += b;
|
|
985
|
-
let
|
|
986
|
-
|
|
987
|
-
meteo: { ...
|
|
988
|
-
wxFactor:
|
|
979
|
+
I,
|
|
980
|
+
d + h,
|
|
981
|
+
d,
|
|
982
|
+
h
|
|
983
|
+
), h = Math.round(h * 0.6 * 1e3) / 1e3, d = Math.round(d * 0.6 * 1e3) / 1e3);
|
|
984
|
+
const b = d <= (r.minV0Factor || -1) ? Math.max(r.maxV0Factor || -3, -1 * d * (d / 1.2)) : 0;
|
|
985
|
+
S == null || S.info("[%s] calculate speed lose with v0Factor(%d), cFactor(%d) and wxFactor(%d)", r.requestId, b, h, d), d += b;
|
|
986
|
+
let E = Math.round((I + h + d) * 100) / 100;
|
|
987
|
+
E = E <= 0 ? 1 : E, u = {
|
|
988
|
+
meteo: { ...l },
|
|
989
|
+
wxFactor: d,
|
|
989
990
|
v0Factor: b,
|
|
990
|
-
cFactor:
|
|
991
|
-
speed: t.velocity && s ? t.velocity :
|
|
991
|
+
cFactor: h,
|
|
992
|
+
speed: t.velocity && s ? t.velocity : E,
|
|
992
993
|
eta: a.utc().format(),
|
|
993
994
|
etd: a.utc().format()
|
|
994
995
|
};
|
|
995
996
|
} else
|
|
996
|
-
|
|
997
|
+
u = {
|
|
997
998
|
wxFactor: 0,
|
|
998
999
|
v0Factor: 0,
|
|
999
1000
|
cFactor: 0,
|
|
@@ -1001,7 +1002,7 @@ class H {
|
|
|
1001
1002
|
eta: a.utc().format(),
|
|
1002
1003
|
etd: a.utc().format()
|
|
1003
1004
|
};
|
|
1004
|
-
return delete t.meteo, delete t.wxFactor, delete t.cFactor, delete t.speed, delete t.etd, { ...
|
|
1005
|
+
return delete t.meteo, delete t.wxFactor, delete t.cFactor, delete t.speed, delete t.etd, { ...u, ...t };
|
|
1005
1006
|
}
|
|
1006
1007
|
/**
|
|
1007
1008
|
* 基于步长计算失速样本
|
|
@@ -1017,83 +1018,83 @@ class H {
|
|
|
1017
1018
|
* @param options
|
|
1018
1019
|
* @private
|
|
1019
1020
|
*/
|
|
1020
|
-
static async speedLoseInHoursStep(e, t, a, o,
|
|
1021
|
+
static async speedLoseInHoursStep(e, t, a, o, i, n, s = "", r = !0, u = !1, l = {}) {
|
|
1021
1022
|
t.utc();
|
|
1022
|
-
const
|
|
1023
|
-
let
|
|
1024
|
-
for (let m = 0; m <
|
|
1025
|
-
let
|
|
1026
|
-
|
|
1027
|
-
const f =
|
|
1028
|
-
if (e.bearing = R.calculateBearing(
|
|
1029
|
-
|
|
1030
|
-
const M =
|
|
1031
|
-
if (o -
|
|
1032
|
-
o = o -
|
|
1023
|
+
const h = t.clone().add(14, "days"), d = [], I = [], b = [];
|
|
1024
|
+
let E = 0, k = 0, p, v;
|
|
1025
|
+
for (let m = 0; m < n.length - 1; m++) {
|
|
1026
|
+
let c = n[m];
|
|
1027
|
+
c.distanceFromStart = Math.round((i + k) * 1e3) / 1e3;
|
|
1028
|
+
const f = n[m + 1];
|
|
1029
|
+
if (e.bearing = R.calculateBearing(c, f, !f.gcToPrevious), c.bearing = e.bearing, c.suspend && u) {
|
|
1030
|
+
c.eta = c.eta || t.utc().format(), c.elapsed = c.elapsed ?? 0;
|
|
1031
|
+
const M = c.suspend - c.elapsed;
|
|
1032
|
+
if (o - E > M)
|
|
1033
|
+
o = o - E - M, t.add(M, "hour"), c.elapsed = c.suspend;
|
|
1033
1034
|
else {
|
|
1034
|
-
const j = o -
|
|
1035
|
-
|
|
1035
|
+
const j = o - E;
|
|
1036
|
+
c.elapsed += j, t.add(j, "hour"), o = 0;
|
|
1036
1037
|
}
|
|
1037
|
-
if (
|
|
1038
|
-
return
|
|
1038
|
+
if (S == null || S.info(`[%s] suspend ${c.elapsed} hours at %j, and remain ${o} hours need to go...`, l.requestId, c), o === 0)
|
|
1039
|
+
return c.distanceFromPrevious = k, { etd: t, from: v || c, to: c, next: n.filter((j) => j), wps: d, days: I, all: b };
|
|
1039
1040
|
} else
|
|
1040
|
-
|
|
1041
|
-
r = t.isAfter(
|
|
1042
|
-
const y = R.calculateDistance(
|
|
1043
|
-
let
|
|
1044
|
-
if (
|
|
1045
|
-
if (
|
|
1046
|
-
`[%s] go to %j from %j with ${y}nm, and cost ${
|
|
1047
|
-
|
|
1041
|
+
c.suspend = 0;
|
|
1042
|
+
r = t.isAfter(h) ? !1 : r, c = await H.speedLoseAt(e, c, t, s, 0, r, u, l), b.push(c), v = v || c, c.important && d.push(c), t.isSameOrAfter(a) && (I.push(c), a.add(24, "hour"));
|
|
1043
|
+
const y = R.calculateDistance(c, f, !f.gcToPrevious);
|
|
1044
|
+
let F = Math.round(y / v.speed * 1e5) / 1e5;
|
|
1045
|
+
if (E + F < o) {
|
|
1046
|
+
if (E += F, t.add(F, "hour"), delete n[m], S == null || S.debug(
|
|
1047
|
+
`[%s] go to %j from %j with ${y}nm, and cost ${F} hours`,
|
|
1048
|
+
l.requestId,
|
|
1048
1049
|
{ lat: f.lat, lng: f.lng },
|
|
1049
1050
|
{ lat: v.lat, lng: v.lng, etd: v.etd }
|
|
1050
|
-
),
|
|
1051
|
-
p = f, p.eta = t.utc().format(), p.distanceFromPrevious = y, p.distanceFromStart = Math.round((
|
|
1051
|
+
), k += y, n.filter((M) => M).length <= 1) {
|
|
1052
|
+
p = f, p.eta = t.utc().format(), p.distanceFromPrevious = y, p.distanceFromStart = Math.round((i + k) * 1e4) / 1e4, d.push(p), b.push(p), delete n[m + 1];
|
|
1052
1053
|
break;
|
|
1053
1054
|
}
|
|
1054
1055
|
} else {
|
|
1055
|
-
|
|
1056
|
-
const M = J.roundPrecision(v.speed *
|
|
1057
|
-
p = R.calculateCoordinate(
|
|
1058
|
-
`[%s] go to %j from %j with ${M}nm, and cost ${
|
|
1059
|
-
|
|
1056
|
+
F = o - E, t.add(F, "hour");
|
|
1057
|
+
const M = J.roundPrecision(v.speed * F, 5);
|
|
1058
|
+
p = R.calculateCoordinate(c, e.bearing, M, "nauticalmiles", !f.gcToPrevious), p.eta = t.utc().format(), n[m] = p, S == null || S.debug(
|
|
1059
|
+
`[%s] go to %j from %j with ${M}nm, and cost ${F} hours`,
|
|
1060
|
+
l.requestId,
|
|
1060
1061
|
{ lat: p.lat, lng: p.lng },
|
|
1061
|
-
{ lat:
|
|
1062
|
-
),
|
|
1062
|
+
{ lat: c.lat, lng: c.lng, etd: c.etd }
|
|
1063
|
+
), k += M, p.distanceFromPrevious = Math.round(k * 1e4) / 1e4, p.distanceFromStart = Math.round((i + k) * 1e4) / 1e4;
|
|
1063
1064
|
break;
|
|
1064
1065
|
}
|
|
1065
1066
|
}
|
|
1066
|
-
return { etd: t, from: v, to: p, next:
|
|
1067
|
+
return { etd: t, from: v, to: p, next: n.filter((m) => m), wps: d, days: I, all: b };
|
|
1067
1068
|
}
|
|
1068
1069
|
/**
|
|
1069
1070
|
* 洋流影响因子
|
|
1070
1071
|
* @param bearing 船舶航行方位角
|
|
1071
1072
|
* @param current 洋流要素
|
|
1072
1073
|
* @param role 1: 船东, 2: 租家, 0: 未知
|
|
1074
|
+
* @param options
|
|
1073
1075
|
*/
|
|
1074
|
-
static currentFactor(e, t, a = 0) {
|
|
1075
|
-
const
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
let n = ((t == null ? void 0 : t.kts) || 0) * Math.cos(o);
|
|
1079
|
-
return a & 2 ? n = Math.ceil(n * 100) / 100 : a & 1 ? n = Math.floor(n * 100) / 100 : n = Math.round(n * 100) / 100, Math.abs(n) > 5 ? 0 : n;
|
|
1076
|
+
static currentFactor(e, t, a = 0, o = {}) {
|
|
1077
|
+
const i = R.includedAngle(e, (t == null ? void 0 : t.degree) || 0) / 180 * Math.PI;
|
|
1078
|
+
let n;
|
|
1079
|
+
return Math.abs(i) === Math.PI / 2 && (n = 0), n = ((t == null ? void 0 : t.kts) || 0) * Math.cos(i), a & 2 ? n = Math.ceil(n * 100) / 100 : a & 1 ? n = Math.floor(n * 100) / 100 : n = Math.round(n * 100) / 100, S == null || S.info("[%s] calculate current factor with %j", o.requestId, { beta: i, current: t, factor: n, role: a }), Math.abs(n) > 5 ? 0 : n;
|
|
1080
1080
|
}
|
|
1081
1081
|
/**
|
|
1082
1082
|
* 风浪影响因子
|
|
1083
1083
|
* @param props 船舶档案
|
|
1084
1084
|
* @param wwc 气象要素
|
|
1085
1085
|
* @param cFactor 洋流因子
|
|
1086
|
+
* @param options
|
|
1086
1087
|
*/
|
|
1087
|
-
static weatherFactor(e, t, a = 0) {
|
|
1088
|
-
var
|
|
1089
|
-
|
|
1090
|
-
const
|
|
1091
|
-
let
|
|
1092
|
-
const l = H.directionFactor(
|
|
1093
|
-
let
|
|
1094
|
-
|
|
1095
|
-
const
|
|
1096
|
-
return
|
|
1088
|
+
static weatherFactor(e, t, a = 0, o = {}) {
|
|
1089
|
+
var b, E, k, p, v, m, c;
|
|
1090
|
+
S == null || S.info("[%s] calculate weather factor via: %j", o.requestId, { ...e, ...t });
|
|
1091
|
+
const i = H.blockCoefficient(e.displacement, e.lbp, e.breadthMoulded, e.draught), n = J.roundPrecision(a * 1852 / 3600, 6), s = H.froudeNumber(e.speed - n, e.lbp), r = H.amendFactor(i, s, e.loadCondition);
|
|
1092
|
+
let u = R.includedAngle(e.bearing, (b = t == null ? void 0 : t.wind) == null ? void 0 : b.degree);
|
|
1093
|
+
const l = H.directionFactor(u, (E = t == null ? void 0 : t.wind) == null ? void 0 : E.scale), h = H.vesselTagFactor(e.displacement, e.loadCondition, e.tag, (k = t == null ? void 0 : t.wind) == null ? void 0 : k.kts);
|
|
1094
|
+
let d = l * r * h / 100 * (e.speed - n);
|
|
1095
|
+
d = Math.round(d * 1.943844 * 1e4) / 1e4 * -1, e.tag === "tugs" && Math.abs(d) > 1 && (d = d / (Math.abs(Math.round(d)) + 1)), S == null || S.info("[%s] calculate wind wx factor: %d", o.requestId, d), u = R.includedAngle(e.bearing, (v = (p = t == null ? void 0 : t.wave) == null ? void 0 : p.sig) == null ? void 0 : v.degree);
|
|
1096
|
+
const I = H.waveHeightFactor(((c = (m = t == null ? void 0 : t.wave) == null ? void 0 : m.sig) == null ? void 0 : c.height) ?? 1, u, e.draught);
|
|
1097
|
+
return S == null || S.info("[%s] calculate wave wx factor: %d", I), d = Math.abs(d) > Math.abs(I) ? d : 0.7 * d + 0.9 * I, S == null || S.info("[%s] calculate finial weather factor: %d (0.7 * wf) + (0.9 * hf)", o.requestId, d), Math.round((d || 0) * 100) / 100;
|
|
1097
1098
|
}
|
|
1098
1099
|
/**
|
|
1099
1100
|
* 以12小时级别去掉重复的days
|
|
@@ -1101,7 +1102,7 @@ class H {
|
|
|
1101
1102
|
* @param interval 12 hours
|
|
1102
1103
|
*/
|
|
1103
1104
|
static async reduceDays(e, t = 12 * 60 * 60) {
|
|
1104
|
-
return e = e == null ? void 0 : e.reduce((a, o) => (o.positionTime || (o.positionTime = w.utc(o.etd || o.eta).unix()), a.some((
|
|
1105
|
+
return e = e == null ? void 0 : e.reduce((a, o) => (o.positionTime || (o.positionTime = w.utc(o.etd || o.eta).unix()), a.some((i) => Math.floor(i.positionTime / t) === Math.floor(o.positionTime / t)) || a.push(o), a), []), e;
|
|
1105
1106
|
}
|
|
1106
1107
|
/**
|
|
1107
1108
|
* 以分钟级别去掉重复的wps
|
|
@@ -1109,7 +1110,7 @@ class H {
|
|
|
1109
1110
|
* @param interval 1 minute
|
|
1110
1111
|
*/
|
|
1111
1112
|
static async reduceWPS(e, t = 60) {
|
|
1112
|
-
return e = e == null ? void 0 : e.reduce((a, o) => (a.some((
|
|
1113
|
+
return e = e == null ? void 0 : e.reduce((a, o) => (a.some((i) => Math.floor(w(i.etd).unix() / t) === Math.floor(w(o.etd).unix() / t)) || a.push(o), a), []), e;
|
|
1113
1114
|
}
|
|
1114
1115
|
/**
|
|
1115
1116
|
* 全程失速分析(走完航程)
|
|
@@ -1124,14 +1125,14 @@ class H {
|
|
|
1124
1125
|
* @param useRouteParam
|
|
1125
1126
|
* @param options
|
|
1126
1127
|
*/
|
|
1127
|
-
static async analyseInstant(e, t, a, o,
|
|
1128
|
-
var
|
|
1129
|
-
const
|
|
1128
|
+
static async analyseInstant(e, t, a, o, i, n = "", s = 0, r = !0, u = !1, l = {}) {
|
|
1129
|
+
var U, G, X, Q, Z, $;
|
|
1130
|
+
const h = w().valueOf();
|
|
1130
1131
|
e.lng = J.convertToStdLng(e.lng);
|
|
1131
|
-
const { route:
|
|
1132
|
-
if (((
|
|
1132
|
+
const { route: d, waypoints: I } = i.points, b = R.calculateSubRoute(e, d);
|
|
1133
|
+
if (((U = b[0]) == null ? void 0 : U.length) <= 1)
|
|
1133
1134
|
return;
|
|
1134
|
-
const { v0:
|
|
1135
|
+
const { v0: E, label: k } = e.sog ? {
|
|
1135
1136
|
v0: e.sog,
|
|
1136
1137
|
label: e.label || "Other"
|
|
1137
1138
|
/* Instruct */
|
|
@@ -1139,22 +1140,22 @@ class H {
|
|
|
1139
1140
|
v0: o.speed,
|
|
1140
1141
|
label: "CP"
|
|
1141
1142
|
/* Cp */
|
|
1142
|
-
}, p = H.assembleProperties(a, o.loadCondition,
|
|
1143
|
+
}, p = H.assembleProperties(a, o.loadCondition, E, 0), v = I.length ? R.calculateSubWaypoints(e, I) : [];
|
|
1143
1144
|
v.forEach((P) => P.important = !0);
|
|
1144
1145
|
const m = {
|
|
1145
1146
|
from: { ...e },
|
|
1146
1147
|
route: b,
|
|
1147
1148
|
waypoints: v,
|
|
1148
|
-
v0:
|
|
1149
|
-
label:
|
|
1150
|
-
},
|
|
1149
|
+
v0: E,
|
|
1150
|
+
label: k
|
|
1151
|
+
}, c = {
|
|
1151
1152
|
hours: [],
|
|
1152
1153
|
days: [],
|
|
1153
1154
|
wps: [],
|
|
1154
1155
|
all: []
|
|
1155
1156
|
};
|
|
1156
1157
|
s || (R.calculateRouteDistance(b) / o.speed <= 72 ? s = 3 : s = 6);
|
|
1157
|
-
let f = R.simplifyRouteToCoordinates(b, v, 0), y = 0,
|
|
1158
|
+
let f = R.simplifyRouteToCoordinates(b, v, 0), y = 0, F = 0, M = 0, j = 0;
|
|
1158
1159
|
t = w(t).utc();
|
|
1159
1160
|
const N = t.clone();
|
|
1160
1161
|
for (; f.length > 0; ) {
|
|
@@ -1165,36 +1166,36 @@ class H {
|
|
|
1165
1166
|
B,
|
|
1166
1167
|
y,
|
|
1167
1168
|
f,
|
|
1168
|
-
|
|
1169
|
+
n,
|
|
1169
1170
|
r,
|
|
1170
|
-
|
|
1171
|
-
|
|
1171
|
+
u,
|
|
1172
|
+
l
|
|
1172
1173
|
);
|
|
1173
|
-
if (
|
|
1174
|
-
const O = await H.speedLoseAt(p, T.to, w(T.to.eta),
|
|
1175
|
-
O.bearing = p.bearing,
|
|
1174
|
+
if (c.all.push(...T.all), (G = T.from) != null && G.speed && (c.hours.push(T.from), c.wps.push(...T.wps), c.days.push(...T.days)), f = T == null ? void 0 : T.next, !f.length) {
|
|
1175
|
+
const O = await H.speedLoseAt(p, T.to, w(T.to.eta), n, 0, r, u, l);
|
|
1176
|
+
O.bearing = p.bearing, c.hours.push(O), c.all.push(O);
|
|
1176
1177
|
}
|
|
1177
1178
|
y += Math.round((((X = T == null ? void 0 : T.to) == null ? void 0 : X.distanceFromPrevious) ?? 0) * 1e4) / 1e4;
|
|
1178
1179
|
}
|
|
1179
|
-
const D =
|
|
1180
|
+
const D = c.hours;
|
|
1180
1181
|
for (let P = 0; P < D.length - 1; P++) {
|
|
1181
1182
|
const B = w(D[P + 1].eta).diff(D[P].etd, "hour", !0) || 1;
|
|
1182
|
-
|
|
1183
|
+
F += (D[P].wxFactor || 0) * B, M += (D[P].cFactor || 0) * B, j += B;
|
|
1183
1184
|
}
|
|
1184
1185
|
const L = D.reduce((P, B) => P + (B.suspend || 0), 0);
|
|
1185
|
-
(Q =
|
|
1186
|
+
(Q = c.wps) == null || Q.forEach((P, B) => {
|
|
1186
1187
|
P.positionTime = w.utc(P.etd || P.eta).unix();
|
|
1187
|
-
const T =
|
|
1188
|
+
const T = c.wps[B - 1];
|
|
1188
1189
|
if (T) {
|
|
1189
1190
|
const O = P.distanceFromStart - T.distanceFromStart, q = w(P.eta || P.etd).diff(w(T.etd || T.eta), "h", !0);
|
|
1190
1191
|
P.avgSpd = Math.round(O / q * 100) / 100;
|
|
1191
1192
|
const at = R.calculateBearing(T, P);
|
|
1192
1193
|
P.avgBearing = at, T.bearing = at;
|
|
1193
1194
|
}
|
|
1194
|
-
}),
|
|
1195
|
-
const W =
|
|
1196
|
-
m.distance = Math.round(C.distanceFromStart * 1e3) / 1e3, m.etd = w(W.eta).utc().format(), m.eta = w(C.eta).utc().format(), m.wxFactor = Math.round(
|
|
1197
|
-
const Y = J.roundPrecision(o.dgo / 24 * L, 3), { distanceInECA: A, hoursInECA: V, totalDgoConsInECA: ot, eca: tt } = await this.calculateECA(m, o,
|
|
1195
|
+
}), c.wps = await H.reduceWPS(c.wps), c.days = await H.reduceDays(c.days), c.all = (Z = c.all) == null ? void 0 : Z.reduce((P, B) => (B.positionTime = w.utc(B.etd || B.eta).unix(), P.some((T) => Math.round(T.positionTime / 60) === Math.round(B.positionTime / 60)) || P.push(B), P), []), m.sample = c;
|
|
1196
|
+
const W = c.hours.at(0), C = c.hours.at(-1);
|
|
1197
|
+
m.distance = Math.round(C.distanceFromStart * 1e3) / 1e3, m.etd = w(W.eta).utc().format(), m.eta = w(C.eta).utc().format(), m.wxFactor = Math.round(F / j * 1e3) / 1e3, m.cFactor = Math.round(M / j * 1e3) / 1e3, m.avgSpeed = Math.round(C.distanceFromStart / j * 1e3) / 1e3, m.totalHrs = Math.round(j * 1e3) / 1e3, m.suspend = Math.round(L * 1e3) / 1e3;
|
|
1198
|
+
const Y = J.roundPrecision(o.dgo / 24 * L, 3), { distanceInECA: A, hoursInECA: V, totalDgoConsInECA: ot, eca: tt } = await this.calculateECA(m, o, l), et = J.roundPrecision(o.fo / 24 * (j - V), 3), it = J.roundPrecision(o.dgo / 24 * j + Y, 3);
|
|
1198
1199
|
m.extend = {
|
|
1199
1200
|
eca: tt,
|
|
1200
1201
|
distanceInECA: A,
|
|
@@ -1202,8 +1203,8 @@ class H {
|
|
|
1202
1203
|
totalDgoConsInECA: ot,
|
|
1203
1204
|
totalDgoConsInSuspend: Y
|
|
1204
1205
|
}, m.totalFoCons = et < 0 ? 0 : et, m.totalDgoCons = it;
|
|
1205
|
-
const st = w().valueOf() -
|
|
1206
|
-
return
|
|
1206
|
+
const st = w().valueOf() - h, ct = (($ = c == null ? void 0 : c.hours) == null ? void 0 : $.length) || 1;
|
|
1207
|
+
return S == null || S.info("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms", l == null ? void 0 : l.requestId, st, ct, Math.round(st / ct * 1e3) / 1e3), m;
|
|
1207
1208
|
}
|
|
1208
1209
|
/**
|
|
1209
1210
|
* 分段失速分析(最多走hours 小时)
|
|
@@ -1220,24 +1221,24 @@ class H {
|
|
|
1220
1221
|
* @param useRouteParam
|
|
1221
1222
|
* @param options
|
|
1222
1223
|
*/
|
|
1223
|
-
static async analyseInstantWithThreshed(e, t, a, o,
|
|
1224
|
+
static async analyseInstantWithThreshed(e, t, a, o, i, n, s, r = "", u = 3, l = !0, h = !1, d = {}) {
|
|
1224
1225
|
var X, Q, Z, $, P, B;
|
|
1225
|
-
const
|
|
1226
|
+
const I = w().valueOf();
|
|
1226
1227
|
e.lng = J.convertToStdLng(e.lng);
|
|
1227
|
-
const { v0: b, label:
|
|
1228
|
+
const { v0: b, label: E } = e.sog ? {
|
|
1228
1229
|
v0: e.sog,
|
|
1229
1230
|
label: e.label || "Other"
|
|
1230
1231
|
/* Instruct */
|
|
1231
1232
|
} : {
|
|
1232
|
-
v0:
|
|
1233
|
+
v0: i.speed,
|
|
1233
1234
|
label: "CP"
|
|
1234
1235
|
/* Cp */
|
|
1235
|
-
},
|
|
1236
|
+
}, k = H.assembleProperties(o, i.loadCondition, b, 0), p = R.calculateSubRoute(e, n);
|
|
1236
1237
|
if (((X = p[0]) == null ? void 0 : X.length) <= 1)
|
|
1237
1238
|
return;
|
|
1238
1239
|
const v = s.length ? R.calculateSubWaypoints(e, s) : [];
|
|
1239
1240
|
v.forEach((T) => T.important = !0);
|
|
1240
|
-
let m = R.simplifyRouteToCoordinates(p, v, 0),
|
|
1241
|
+
let m = R.simplifyRouteToCoordinates(p, v, 0), c = 0, f = 0, y = 0, F = 0;
|
|
1241
1242
|
const M = {
|
|
1242
1243
|
hours: [],
|
|
1243
1244
|
wps: [],
|
|
@@ -1247,11 +1248,11 @@ class H {
|
|
|
1247
1248
|
t = w(t).utc();
|
|
1248
1249
|
const j = t.clone();
|
|
1249
1250
|
for (; m.length > 0; ) {
|
|
1250
|
-
const T =
|
|
1251
|
+
const T = u - t.hour() % u;
|
|
1251
1252
|
let O = Math.ceil(t.clone().add(T, "h").set({ minute: 0, second: 0, millisecond: 0 }).diff(t, "h", !0) * 1e4) / 1e4;
|
|
1252
1253
|
O = t.clone().add(O, "h").isSameOrAfter(a) ? a.diff(t, "h", !0) * 1e4 / 1e4 : O;
|
|
1253
|
-
const q = await H.speedLoseInHoursStep(
|
|
1254
|
-
if (M.all.push(...q.all), (Q = q.from) != null && Q.speed && (M.hours.push(q.from), q != null && q.wps && M.wps.push(...q.wps), M.days.push(...q.days)), m = q == null ? void 0 : q.next, m.length || M.hours.push(q == null ? void 0 : q.to),
|
|
1254
|
+
const q = await H.speedLoseInHoursStep(k, t, j, O, c, m, r, l, h, d);
|
|
1255
|
+
if (M.all.push(...q.all), (Q = q.from) != null && Q.speed && (M.hours.push(q.from), q != null && q.wps && M.wps.push(...q.wps), M.days.push(...q.days)), m = q == null ? void 0 : q.next, m.length || M.hours.push(q == null ? void 0 : q.to), c += Math.round((((Z = q == null ? void 0 : q.to) == null ? void 0 : Z.distanceFromPrevious) ?? 0) * 1e4) / 1e4, !O)
|
|
1255
1256
|
break;
|
|
1256
1257
|
}
|
|
1257
1258
|
M.wps = await H.reduceWPS(M.wps), M.days = await H.reduceDays(M.days), M.all = ($ = M.all) == null ? void 0 : $.reduce((T, O) => (O.positionTime = w.utc(O.etd || O.eta).unix(), T.some((q) => Math.round(w(q.etd).unix() / 60) === Math.round(w(O.etd).unix() / 60)) || T.push(O), T), []), (P = M.wps) == null || P.forEach((T, O) => {
|
|
@@ -1264,7 +1265,7 @@ class H {
|
|
|
1264
1265
|
const N = M.hours;
|
|
1265
1266
|
for (let T = 0; T < N.length - 1; T++) {
|
|
1266
1267
|
const O = w(N[T + 1].eta).diff(N[T].etd, "hour", !0);
|
|
1267
|
-
f += N[T].wxFactor * O, y += N[T].cFactor * O,
|
|
1268
|
+
f += N[T].wxFactor * O, y += N[T].cFactor * O, F += O;
|
|
1268
1269
|
}
|
|
1269
1270
|
const D = N.reduce((T, O) => T + (O.suspend || 0), 0), L = M.hours.at(0), W = M.hours.at(-1), C = await R.calculateRangeRoute(L, W, p), Y = await R.calculateRangeWaypoints(L, W, p, v), A = {
|
|
1270
1271
|
sample: M,
|
|
@@ -1272,18 +1273,18 @@ class H {
|
|
|
1272
1273
|
// 注意,可能会在first节点Drift,所有采用eta做为初始出发时间
|
|
1273
1274
|
etd: w(L.eta).utc().format(),
|
|
1274
1275
|
eta: w(W == null ? void 0 : W.eta).utc().format(),
|
|
1275
|
-
wxFactor: Math.round(f /
|
|
1276
|
-
cFactor: Math.round(y /
|
|
1277
|
-
avgSpeed: Math.round(((W == null ? void 0 : W.distanceFromStart) || 0) /
|
|
1278
|
-
totalHrs: Math.round(
|
|
1276
|
+
wxFactor: Math.round(f / F * 1e3) / 1e3,
|
|
1277
|
+
cFactor: Math.round(y / F * 1e3) / 1e3,
|
|
1278
|
+
avgSpeed: Math.round(((W == null ? void 0 : W.distanceFromStart) || 0) / F * 1e3) / 1e3,
|
|
1279
|
+
totalHrs: Math.round(F * 1e3) / 1e3,
|
|
1279
1280
|
suspend: Math.round(D * 1e3) / 1e3,
|
|
1280
1281
|
from: L,
|
|
1281
1282
|
to: W,
|
|
1282
1283
|
route: C,
|
|
1283
1284
|
waypoints: Y,
|
|
1284
1285
|
v0: b,
|
|
1285
|
-
label:
|
|
1286
|
-
}, V = J.roundPrecision(
|
|
1286
|
+
label: E
|
|
1287
|
+
}, V = J.roundPrecision(i.dgo / 24 * D, 3), { distanceInECA: ot, hoursInECA: tt, totalDgoConsInECA: et, eca: it } = await this.calculateECA(A, i, d), rt = J.roundPrecision(i.fo / 24 * (F - tt), 3), st = J.roundPrecision(i.dgo / 24 * F + V, 3);
|
|
1287
1288
|
A.extend = {
|
|
1288
1289
|
eca: it,
|
|
1289
1290
|
distanceInECA: ot,
|
|
@@ -1291,8 +1292,8 @@ class H {
|
|
|
1291
1292
|
totalDgoConsInECA: et,
|
|
1292
1293
|
totalDgoConsInSuspend: V
|
|
1293
1294
|
}, A.totalDgoCons = st, A.totalFoCons = rt < 0 ? 0 : rt;
|
|
1294
|
-
const
|
|
1295
|
-
return
|
|
1295
|
+
const U = w().valueOf() - I, G = ((B = M == null ? void 0 : M.hours) == null ? void 0 : B.length) || 1;
|
|
1296
|
+
return S == null || S.debug("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms", d == null ? void 0 : d.requestId, U, G, Math.round(U / G * 1e3) / 1e3), A;
|
|
1296
1297
|
}
|
|
1297
1298
|
/**
|
|
1298
1299
|
* 在指定航线条件下,基于多CP,动态计算最优成本(租金+油费)方案
|
|
@@ -1309,59 +1310,59 @@ class H {
|
|
|
1309
1310
|
* @param lane 基础航线(重要转向点)
|
|
1310
1311
|
* @param options
|
|
1311
1312
|
*/
|
|
1312
|
-
static async analyseCost(e, t, a, o,
|
|
1313
|
+
static async analyseCost(e, t, a, o, i = {}) {
|
|
1313
1314
|
var p, v;
|
|
1314
|
-
const
|
|
1315
|
+
const n = w().valueOf(), s = [];
|
|
1315
1316
|
e.speedStep = e.speedStep || 3, e.alterStep = e.alterStep ?? 1;
|
|
1316
1317
|
const r = R.calculateRouteDistance(o.route);
|
|
1317
|
-
let
|
|
1318
|
+
let u = 0;
|
|
1318
1319
|
a.forEach((m) => {
|
|
1319
|
-
const
|
|
1320
|
-
|
|
1321
|
-
}),
|
|
1322
|
-
const
|
|
1323
|
-
let
|
|
1320
|
+
const c = Math.ceil(r / m.speed / 24);
|
|
1321
|
+
u = u < c ? c : u;
|
|
1322
|
+
}), u = u * 1.3;
|
|
1323
|
+
const l = w.utc(e.etd).add(u ?? 14, "day");
|
|
1324
|
+
let h = 1;
|
|
1324
1325
|
for (const m of a) {
|
|
1325
|
-
const
|
|
1326
|
+
const c = JSON.parse(JSON.stringify(o.route)), f = JSON.parse(JSON.stringify(o.waypoints)), y = await H.analyseInstantWithThreshed(
|
|
1326
1327
|
{ lat: e.lat, lng: e.lng },
|
|
1327
1328
|
e.etd,
|
|
1328
|
-
|
|
1329
|
+
l,
|
|
1329
1330
|
t,
|
|
1330
1331
|
m,
|
|
1331
|
-
|
|
1332
|
+
c,
|
|
1332
1333
|
f,
|
|
1333
1334
|
e.meteoVendor,
|
|
1334
1335
|
e.speedStep,
|
|
1335
1336
|
e.useMeteo,
|
|
1336
1337
|
e.useRouteParam,
|
|
1337
|
-
|
|
1338
|
+
i
|
|
1338
1339
|
);
|
|
1339
|
-
y && (await H.calculateCost(y, m, e,
|
|
1340
|
+
y && (await H.calculateCost(y, m, e, i), s.push(y), S == null || S.info("[%s][L%d-%d] analyse from %s to %s cost: %j", i.requestId, 1, h, e.etd, l.format(), {
|
|
1340
1341
|
cost: y.cost.total,
|
|
1341
1342
|
hire: y.cost.hire,
|
|
1342
1343
|
bunker: y.cost.bunker,
|
|
1343
1344
|
distance: y.distance,
|
|
1344
1345
|
hours: y.totalHrs,
|
|
1345
1346
|
cp: `${m.speed}/${m.fo}/${m.dgo}`
|
|
1346
|
-
})),
|
|
1347
|
+
})), h++;
|
|
1347
1348
|
}
|
|
1348
|
-
s.sort((m,
|
|
1349
|
-
const
|
|
1350
|
-
if (b.push({ combined: !1, speeds: [
|
|
1351
|
-
const m =
|
|
1352
|
-
let M = Math.ceil(
|
|
1349
|
+
s.sort((m, c) => m.cost.total - c.cost.total);
|
|
1350
|
+
const d = s.at(0), I = s.at(1), b = [];
|
|
1351
|
+
if (b.push({ combined: !1, speeds: [d], cost: (p = d.cost) == null ? void 0 : p.total }), I) {
|
|
1352
|
+
const m = d.cost.cp, c = I.cost.cp, f = w(d.eta), y = w(d.etd), F = f.diff(y, "days", !0);
|
|
1353
|
+
let M = Math.ceil(F / 2);
|
|
1353
1354
|
M = M > 7 ? 7 : M < e.alterStep ? e.alterStep : M;
|
|
1354
|
-
let j = 2, N = { combined: !1, speeds: [
|
|
1355
|
+
let j = 2, N = { combined: !1, speeds: [I], cost: (v = I.cost) == null ? void 0 : v.total }, D;
|
|
1355
1356
|
for (; M >= e.alterStep; ) {
|
|
1356
|
-
const L = await H.combinedAnalyse(e, t,
|
|
1357
|
+
const L = await H.combinedAnalyse(e, t, l, [m, c], o, M, { ...i, level: j });
|
|
1357
1358
|
if (N.cost > L.cost ? D ? (D == null ? void 0 : D.cost) > L.cost && (D = L) : (D = N, N = L) : (!D || (D == null ? void 0 : D.cost) > L.cost) && (D = L), M <= e.alterStep)
|
|
1358
1359
|
break;
|
|
1359
1360
|
M = Math.ceil(M / 2), j += 1;
|
|
1360
1361
|
}
|
|
1361
1362
|
b.push(N), D && b.push(D);
|
|
1362
1363
|
}
|
|
1363
|
-
const
|
|
1364
|
-
return
|
|
1364
|
+
const k = w().valueOf() - n;
|
|
1365
|
+
return S == null || S.info("[%s] analyse elapsed: %d ms", i == null ? void 0 : i.requestId, k), b.sort((m, c) => m.cost - c.cost);
|
|
1365
1366
|
}
|
|
1366
1367
|
/**
|
|
1367
1368
|
* 按步长多次减半,分别用7,4,2,1天步长及cpa,cpb交替计算各种组合下的成本
|
|
@@ -1373,24 +1374,24 @@ class H {
|
|
|
1373
1374
|
* @param step 步长,7,4,2,1
|
|
1374
1375
|
* @param options
|
|
1375
1376
|
*/
|
|
1376
|
-
static async combinedAnalyse(e, t, a, o,
|
|
1377
|
-
s.counter = 1,
|
|
1378
|
-
const r = await H.alternateAnalyse(e, t, a, o, 0,
|
|
1379
|
-
|
|
1380
|
-
cost:
|
|
1381
|
-
hire:
|
|
1382
|
-
bunker:
|
|
1383
|
-
distance:
|
|
1384
|
-
hours:
|
|
1377
|
+
static async combinedAnalyse(e, t, a, o, i, n, s = {}) {
|
|
1378
|
+
s.counter = 1, S == null || S.info("[%s][L%d] analyse with alternate cp in every %d days", s.requestId, s.level, n);
|
|
1379
|
+
const r = await H.alternateAnalyse(e, t, a, o, 0, i, n, s), u = r.reduce((c, f) => c + f.cost.total, 0), l = r.reduce((c, f) => c + f.cost.hire, 0), h = r.reduce((c, f) => c + f.cost.bunker, 0), d = r.reduce((c, f) => c + f.distance, 0), I = r.reduce((c, f) => c + f.totalHrs, 0);
|
|
1380
|
+
S == null || S.info("[%s][L%d] cost with cpa/cpb turn: %j", s.requestId, s.level, {
|
|
1381
|
+
cost: u,
|
|
1382
|
+
hire: l,
|
|
1383
|
+
bunker: h,
|
|
1384
|
+
distance: d,
|
|
1385
|
+
hours: I
|
|
1385
1386
|
});
|
|
1386
|
-
const b = await H.alternateAnalyse(e, t, a, o, 1,
|
|
1387
|
-
return
|
|
1388
|
-
cost:
|
|
1389
|
-
hire:
|
|
1387
|
+
const b = await H.alternateAnalyse(e, t, a, o, 1, i, n, s), E = b.reduce((c, f) => c + f.cost.total, 0), k = b.reduce((c, f) => c + f.cost.hire, 0), p = b.reduce((c, f) => c + f.cost.bunker, 0), v = b.reduce((c, f) => c + f.distance, 0), m = b.reduce((c, f) => c + f.totalHrs, 0);
|
|
1388
|
+
return S == null || S.info("[%s][L%d] cost with cpb/cpa turn: %j", s.requestId, s.level, {
|
|
1389
|
+
cost: E,
|
|
1390
|
+
hire: k,
|
|
1390
1391
|
bunker: p,
|
|
1391
1392
|
distance: v,
|
|
1392
1393
|
hours: m
|
|
1393
|
-
}),
|
|
1394
|
+
}), u < E ? { combined: !0, cost: Math.round(u * 1e3) / 1e3, speeds: r, step: n } : { combined: !0, cost: Math.round(E * 1e3) / 1e3, speeds: b, step: n };
|
|
1394
1395
|
}
|
|
1395
1396
|
/**
|
|
1396
1397
|
* 基于cp索引,交替计算指定步长下的成本
|
|
@@ -1403,31 +1404,31 @@ class H {
|
|
|
1403
1404
|
* @param step 步长,7,4,2,1
|
|
1404
1405
|
* @param options
|
|
1405
1406
|
*/
|
|
1406
|
-
static async alternateAnalyse(e, t, a, o,
|
|
1407
|
-
var
|
|
1408
|
-
let
|
|
1409
|
-
const
|
|
1410
|
-
for (;
|
|
1411
|
-
const b =
|
|
1412
|
-
|
|
1413
|
-
|
|
1407
|
+
static async alternateAnalyse(e, t, a, o, i, n, s, r = {}) {
|
|
1408
|
+
var d, I;
|
|
1409
|
+
let u = w.utc(e.etd);
|
|
1410
|
+
const l = { lat: e.lat, lng: e.lng }, h = [];
|
|
1411
|
+
for (; u.isBefore(a); ) {
|
|
1412
|
+
const b = u.clone().utc().add(s, "day"), E = JSON.parse(JSON.stringify(n.route)), k = JSON.parse(JSON.stringify(n.waypoints)), p = o[i], v = await H.analyseInstantWithThreshed(
|
|
1413
|
+
l,
|
|
1414
|
+
u.utc().format(),
|
|
1414
1415
|
b,
|
|
1415
1416
|
t,
|
|
1416
1417
|
p,
|
|
1417
|
-
|
|
1418
|
-
|
|
1418
|
+
E,
|
|
1419
|
+
k,
|
|
1419
1420
|
e.meteoVendor,
|
|
1420
1421
|
e.speedStep,
|
|
1421
1422
|
e.useMeteo,
|
|
1422
1423
|
e.useRouteParam,
|
|
1423
1424
|
r
|
|
1424
1425
|
);
|
|
1425
|
-
v && (await H.calculateCost(v, p, e, r),
|
|
1426
|
+
v && (await H.calculateCost(v, p, e, r), S == null || S.info(
|
|
1426
1427
|
"[%s][L%d-%d] analyse from %s to %s cost: %j",
|
|
1427
1428
|
r.requestId,
|
|
1428
1429
|
r.level,
|
|
1429
1430
|
r.counter,
|
|
1430
|
-
|
|
1431
|
+
u.utc().format(),
|
|
1431
1432
|
b.utc().format(),
|
|
1432
1433
|
{
|
|
1433
1434
|
cost: v.cost.total,
|
|
@@ -1438,13 +1439,13 @@ class H {
|
|
|
1438
1439
|
cp: `${p.speed}/${p.fo}/${p.dgo}`
|
|
1439
1440
|
}
|
|
1440
1441
|
)), r.counter = r.counter + 1;
|
|
1441
|
-
const m = (
|
|
1442
|
+
const m = (I = (d = v == null ? void 0 : v.sample) == null ? void 0 : d.hours) == null ? void 0 : I.at(-1);
|
|
1442
1443
|
if (m)
|
|
1443
|
-
|
|
1444
|
+
l.lat = m.lat, l.lng = m.lng, u = w(m.eta), h.push(v), i = i ? 0 : 1;
|
|
1444
1445
|
else
|
|
1445
1446
|
break;
|
|
1446
1447
|
}
|
|
1447
|
-
return
|
|
1448
|
+
return h;
|
|
1448
1449
|
}
|
|
1449
1450
|
/**
|
|
1450
1451
|
* 计算Speed的cost
|
|
@@ -1454,14 +1455,14 @@ class H {
|
|
|
1454
1455
|
* @param options
|
|
1455
1456
|
*/
|
|
1456
1457
|
static async calculateCost(e, t, a, o = {}) {
|
|
1457
|
-
var
|
|
1458
|
+
var i;
|
|
1458
1459
|
if (e) {
|
|
1459
|
-
const
|
|
1460
|
+
const n = (a.addComm || 0) >= 1 ? (a.addComm || 0) / 100 : a.addComm || 0, s = Math.round((a.dailyHire || 0) * (e.suspend || 0) / 24 * 1e3) / 1e3, r = Math.round(e.totalHrs / 24 * (a.dailyHire || 0) * (1 - n) * 1e3) / 1e3 + s, u = Math.round(e.totalFoCons * (a.priceFO || 0) * 1e3) / 1e3, l = Math.round((e.totalDgoCons + (((i = e.extend) == null ? void 0 : i.totalDgoConsInECA) || 0)) * (a.priceDGO || 0) * 1e3) / 1e3;
|
|
1460
1461
|
e.cost = {
|
|
1461
|
-
total: Math.round((r +
|
|
1462
|
+
total: Math.round((r + u + l) * 1e3) / 1e3,
|
|
1462
1463
|
hire: Math.round(r * 1e3) / 1e3,
|
|
1463
1464
|
suspendHire: s,
|
|
1464
|
-
bunker: Math.round((
|
|
1465
|
+
bunker: Math.round((u + l) * 1e3) / 1e3,
|
|
1465
1466
|
cp: t
|
|
1466
1467
|
};
|
|
1467
1468
|
}
|
|
@@ -1472,20 +1473,20 @@ class H {
|
|
|
1472
1473
|
*
|
|
1473
1474
|
*/
|
|
1474
1475
|
static async calculateECA(e, t, a = {}) {
|
|
1475
|
-
var r,
|
|
1476
|
+
var r, u, l, h;
|
|
1476
1477
|
const o = await R.intersectInECA((e == null ? void 0 : e.route) || []);
|
|
1477
|
-
let
|
|
1478
|
-
(
|
|
1479
|
-
|
|
1478
|
+
let i = 0, n = 0, s = 0;
|
|
1479
|
+
(u = (r = e == null ? void 0 : e.sample) == null ? void 0 : r.wps) == null || u.forEach((d) => {
|
|
1480
|
+
d.positionTime = w.utc(d.etd || d.eta).unix();
|
|
1480
1481
|
});
|
|
1481
|
-
for (const
|
|
1482
|
-
|
|
1483
|
-
const
|
|
1484
|
-
|
|
1482
|
+
for (const d of o) {
|
|
1483
|
+
i += d.distance;
|
|
1484
|
+
const I = await R.deadReckoningTime((l = d.waypoints) == null ? void 0 : l.at(0), e.sample.all || e.sample.wps), b = await R.deadReckoningTime((h = d.waypoints) == null ? void 0 : h.at(-1), e.sample.all || e.sample.wps);
|
|
1485
|
+
d.in = I, d.out = b, d.totalHrs = J.roundPrecision((b.positionTime - I.positionTime) / 3600, 3), d.totalDgoCons = J.roundPrecision(t.fo / 24 * d.totalHrs, 3), n += d.totalHrs, s += d.totalDgoCons;
|
|
1485
1486
|
}
|
|
1486
|
-
return
|
|
1487
|
-
distanceInECA:
|
|
1488
|
-
hoursInECA:
|
|
1487
|
+
return i = J.roundPrecision(i, 3), n = J.roundPrecision(n, 3), s = J.roundPrecision(s, 3), {
|
|
1488
|
+
distanceInECA: i,
|
|
1489
|
+
hoursInECA: n,
|
|
1489
1490
|
totalDgoConsInECA: s,
|
|
1490
1491
|
eca: o
|
|
1491
1492
|
};
|
|
@@ -1496,40 +1497,40 @@ class H {
|
|
|
1496
1497
|
* @param options
|
|
1497
1498
|
*/
|
|
1498
1499
|
static async mergeSpeeds(e, t = {}) {
|
|
1499
|
-
var m,
|
|
1500
|
+
var m, c;
|
|
1500
1501
|
const a = {
|
|
1501
1502
|
hours: [],
|
|
1502
1503
|
wps: [],
|
|
1503
1504
|
days: [],
|
|
1504
1505
|
all: []
|
|
1505
|
-
}, o = e.reduce((f, y) => f + y.distance, 0),
|
|
1506
|
-
var
|
|
1507
|
-
return f + (((
|
|
1508
|
-
}, 0),
|
|
1509
|
-
var
|
|
1510
|
-
return f + (((
|
|
1506
|
+
}, o = e.reduce((f, y) => f + y.distance, 0), i = e.reduce((f, y) => {
|
|
1507
|
+
var F;
|
|
1508
|
+
return f + (((F = y.extend) == null ? void 0 : F.distanceInECA) || 0);
|
|
1509
|
+
}, 0), n = e.reduce((f, y) => f + y.totalHrs, 0), s = e.reduce((f, y) => {
|
|
1510
|
+
var F;
|
|
1511
|
+
return f + (((F = y.extend) == null ? void 0 : F.hoursInECA) || 0);
|
|
1511
1512
|
}, 0), r = e.reduce((f, y) => {
|
|
1512
|
-
var
|
|
1513
|
-
return f + (((
|
|
1514
|
-
}, 0),
|
|
1513
|
+
var F;
|
|
1514
|
+
return f + (((F = y.extend) == null ? void 0 : F.totalDgoConsInECA) || 0);
|
|
1515
|
+
}, 0), u = e.reduce((f, y) => f + y.wxFactor * y.totalHrs / n, 0), l = e.reduce((f, y) => f + y.cFactor * y.totalHrs / n, 0), h = e.reduce((f, y) => f + y.totalFoCons, 0), d = e.reduce((f, y) => f + y.totalDgoCons, 0), I = e.reduce((f, y) => f + y.cost.total, 0), b = e.reduce((f, y) => f + y.cost.hire, 0), E = e.reduce((f, y) => f + y.cost.bunker, 0), k = [], p = [];
|
|
1515
1516
|
let v;
|
|
1516
1517
|
for (const f of e) {
|
|
1517
1518
|
p.push(...((m = f.extend) == null ? void 0 : m.eca) || []);
|
|
1518
|
-
const y = f.sample.hours,
|
|
1519
|
+
const y = f.sample.hours, F = f.sample.all, M = f.sample.wps, j = f.sample.days, N = y.at(0);
|
|
1519
1520
|
v && (N.distanceFromPrevious = v.distanceFromPrevious, N.distanceFromStart = v.distanceFromStart, y.forEach((C, Y) => {
|
|
1520
1521
|
Y && (C.distanceFromStart = C.distanceFromStart + v.distanceFromStart);
|
|
1521
|
-
}),
|
|
1522
|
+
}), F.at(0).distanceFromPrevious = v.distanceFromPrevious, F.at(0).distanceFromStart = v.distanceFromStart, F.forEach((C, Y) => {
|
|
1522
1523
|
Y && (C.distanceFromStart = C.distanceFromStart + v.distanceFromStart);
|
|
1523
1524
|
}), M.at(0).distanceFromPrevious = v.distanceFromPrevious, M.at(0).distanceFromStart = v.distanceFromStart, M.forEach((C, Y) => {
|
|
1524
1525
|
Y && (C.distanceFromStart = C.distanceFromStart + v.distanceFromStart);
|
|
1525
1526
|
}), j.at(0).distanceFromPrevious = v.distanceFromPrevious, j.at(0).distanceFromStart = v.distanceFromStart, j.forEach((C, Y) => {
|
|
1526
1527
|
Y && (C.distanceFromStart = C.distanceFromStart + v.distanceFromStart);
|
|
1527
1528
|
})), N.cp = f.cost.cp;
|
|
1528
|
-
const D = [f.etd, f.eta], L =
|
|
1529
|
-
L === -1 ? (N.cp.segment = [D],
|
|
1529
|
+
const D = [f.etd, f.eta], L = k.findIndex((C) => C.id === N.cp.id);
|
|
1530
|
+
L === -1 ? (N.cp.segment = [D], k.push(N.cp)) : k[L].segment.push(D), y.forEach((C) => {
|
|
1530
1531
|
var A;
|
|
1531
1532
|
((A = a.hours) == null ? void 0 : A.findIndex((V) => V.eta === C.eta)) === -1 && a.hours.push(C);
|
|
1532
|
-
}),
|
|
1533
|
+
}), F.forEach((C) => {
|
|
1533
1534
|
var A;
|
|
1534
1535
|
((A = a.all) == null ? void 0 : A.findIndex((V) => V.eta === C.eta)) === -1 && a.all.push(C);
|
|
1535
1536
|
}), M.forEach((C) => {
|
|
@@ -1539,16 +1540,16 @@ class H {
|
|
|
1539
1540
|
var A;
|
|
1540
1541
|
((A = a == null ? void 0 : a.days) == null ? void 0 : A.findIndex((V) => V.eta === C.eta)) === -1 && a.days.push(C);
|
|
1541
1542
|
});
|
|
1542
|
-
const W = (
|
|
1543
|
+
const W = (c = a.wps) == null ? void 0 : c.findIndex((C) => C.eta === N.eta);
|
|
1543
1544
|
W === -1 ? a.wps.push(N) : a.wps[W] = N, v = y.at(-1);
|
|
1544
1545
|
}
|
|
1545
1546
|
return a.wps.sort((f, y) => w(f.etd).unix() - w(y.etd).unix()), a.wps.forEach((f, y) => {
|
|
1546
|
-
const
|
|
1547
|
-
if (
|
|
1548
|
-
const M = f.distanceFromStart - (
|
|
1547
|
+
const F = a.wps[y - 1];
|
|
1548
|
+
if (F) {
|
|
1549
|
+
const M = f.distanceFromStart - (F.distanceFromStart || 0), j = w(f.eta || f.etd).diff(w(F.etd || F.eta), "hour", !0), N = Math.round(M / j * 100) / 100;
|
|
1549
1550
|
f.avgSpd = N;
|
|
1550
|
-
const D = R.calculateBearing(
|
|
1551
|
-
|
|
1551
|
+
const D = R.calculateBearing(F, f);
|
|
1552
|
+
F.bearing = D;
|
|
1552
1553
|
}
|
|
1553
1554
|
}), {
|
|
1554
1555
|
sample: a,
|
|
@@ -1559,21 +1560,21 @@ class H {
|
|
|
1559
1560
|
v0: e.at(0).v0,
|
|
1560
1561
|
label: "Combined",
|
|
1561
1562
|
distance: Math.round(o * 1e3) / 1e3,
|
|
1562
|
-
totalHrs: Math.round(
|
|
1563
|
-
avgSpeed: Math.round(o /
|
|
1564
|
-
wxFactor: Math.round(
|
|
1565
|
-
cFactor: Math.round(
|
|
1566
|
-
totalFoCons: Math.round(
|
|
1567
|
-
totalDgoCons: Math.round(
|
|
1563
|
+
totalHrs: Math.round(n * 1e3) / 1e3,
|
|
1564
|
+
avgSpeed: Math.round(o / n * 1e3) / 1e3,
|
|
1565
|
+
wxFactor: Math.round(u * 1e3) / 1e3,
|
|
1566
|
+
cFactor: Math.round(l * 1e3) / 1e3,
|
|
1567
|
+
totalFoCons: Math.round(h * 1e3) / 1e3,
|
|
1568
|
+
totalDgoCons: Math.round(d * 1e3) / 1e3,
|
|
1568
1569
|
cost: {
|
|
1569
|
-
total: Math.round(
|
|
1570
|
+
total: Math.round(I * 1e3) / 1e3,
|
|
1570
1571
|
hire: Math.round(b * 1e3) / 1e3,
|
|
1571
|
-
bunker: Math.round(
|
|
1572
|
+
bunker: Math.round(E * 1e3) / 1e3
|
|
1572
1573
|
},
|
|
1573
1574
|
extend: {
|
|
1574
|
-
cps:
|
|
1575
|
+
cps: k,
|
|
1575
1576
|
eca: p,
|
|
1576
|
-
distanceInECA: Math.round(
|
|
1577
|
+
distanceInECA: Math.round(i * 1e3) / 1e3,
|
|
1577
1578
|
hoursInECA: Math.round(s * 1e3) / 1e3,
|
|
1578
1579
|
totalDgoConsInECA: Math.round(r * 1e3) / 1e3,
|
|
1579
1580
|
speeds: e
|