@idm-plugin/vessel 3.7.4 → 3.7.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +521 -521
- package/dist/index.umd.cjs +1 -1
- package/dist/speed/src/index.d.ts +8 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -63,19 +63,19 @@ class Tt extends nt {
|
|
|
63
63
|
this.clientId = t, this.clientSecret = a;
|
|
64
64
|
}
|
|
65
65
|
async authToken(t = {}) {
|
|
66
|
-
const a = "https://svc.data.myvessel.cn/ada/oauth/token",
|
|
66
|
+
const a = "https://svc.data.myvessel.cn/ada/oauth/token", o = {
|
|
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
|
-
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
|
|
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,
|
|
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
|
|
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
|
|
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,
|
|
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
|
|
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,
|
|
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,
|
|
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
|
-
}),
|
|
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,45 +326,45 @@ 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,
|
|
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,
|
|
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,
|
|
352
352
|
startTime: a.utcOffset(8).format("YYYY-MM-DD HH:mm:ss"),
|
|
353
|
-
endTime:
|
|
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,14 +374,14 @@ 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
|
}
|
|
@@ -392,20 +392,20 @@ class jt extends nt {
|
|
|
392
392
|
this.token = t;
|
|
393
393
|
}
|
|
394
394
|
async realTimePosition(t, a = {}) {
|
|
395
|
-
const
|
|
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,
|
|
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,
|
|
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
|
-
let
|
|
440
|
-
const
|
|
439
|
+
let o = "https://www.hifleet.com/hifleetapi/searchVesselOL.do";
|
|
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,
|
|
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
|
|
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
|
|
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,
|
|
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,
|
|
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,17 +524,17 @@ 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 {
|
|
@@ -544,19 +544,19 @@ class xt extends nt {
|
|
|
544
544
|
this.token = t;
|
|
545
545
|
}
|
|
546
546
|
async realTimePosition(t, a = {}) {
|
|
547
|
-
const
|
|
547
|
+
const o = {
|
|
548
548
|
searchParams: {
|
|
549
549
|
id: t,
|
|
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,46 +572,46 @@ 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,
|
|
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 {
|
|
@@ -621,28 +621,28 @@ class Nt extends nt {
|
|
|
621
621
|
this.token = t;
|
|
622
622
|
}
|
|
623
623
|
async getShipId(t, a = {}) {
|
|
624
|
-
const
|
|
624
|
+
const o = {
|
|
625
625
|
headers: {
|
|
626
626
|
appKey: this.token
|
|
627
627
|
},
|
|
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
|
-
const
|
|
635
|
+
const o = {
|
|
636
636
|
headers: {
|
|
637
637
|
appKey: this.token
|
|
638
638
|
},
|
|
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,66 +655,66 @@ class Nt extends nt {
|
|
|
655
655
|
};
|
|
656
656
|
}
|
|
657
657
|
async realTimePosition(t, a = {}) {
|
|
658
|
-
const
|
|
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
|
-
shipId:
|
|
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,
|
|
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,
|
|
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
|
},
|
|
701
701
|
json: {
|
|
702
702
|
shipId: t,
|
|
703
703
|
startTime: a,
|
|
704
|
-
endTime:
|
|
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,8 +725,8 @@ 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
|
}
|
|
@@ -748,23 +748,23 @@ class Mt {
|
|
|
748
748
|
* @param options
|
|
749
749
|
*/
|
|
750
750
|
parsePrinciple(e, t = {}) {
|
|
751
|
-
var s, r,
|
|
751
|
+
var s, r, u;
|
|
752
752
|
_ == null || _.debug("[%s] parse rule: %s", t.requestId, e);
|
|
753
|
-
const a = new RegExp("(?<=\\[)(.+)(?=])", "g"),
|
|
754
|
-
if (!
|
|
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
|
|
776
|
+
var n;
|
|
777
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"),
|
|
779
|
-
if (
|
|
780
|
-
let s =
|
|
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
|
|
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, _ == null || _.debug("[%s] check sig.wave: %j", a.requestId, { ...Y, dgThd4Wv: r, svThd4Wv:
|
|
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
|
|
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
|
}
|
|
@@ -826,11 +826,11 @@ class H {
|
|
|
826
826
|
* @param draught 吃水 m
|
|
827
827
|
* @return [0.55, 0.85]
|
|
828
828
|
*/
|
|
829
|
-
static blockCoefficient(e, t, a,
|
|
830
|
-
let
|
|
831
|
-
|
|
832
|
-
const
|
|
833
|
-
return
|
|
829
|
+
static blockCoefficient(e, t, a, o) {
|
|
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
|
|
@@ -844,8 +844,8 @@ class H {
|
|
|
844
844
|
* @return [0.05, 0.30]
|
|
845
845
|
*/
|
|
846
846
|
static froudeNumber(e, t, a = 9.8) {
|
|
847
|
-
let
|
|
848
|
-
return
|
|
847
|
+
let o = Math.round(Math.sqrt(e * e / (a * t)) * 100) / 100;
|
|
848
|
+
return o = o < 0.05 ? 0.05 : o > 0.3 ? 0.3 : o, o;
|
|
849
849
|
}
|
|
850
850
|
/**
|
|
851
851
|
* 失速修正系數
|
|
@@ -855,7 +855,7 @@ class H {
|
|
|
855
855
|
* @private
|
|
856
856
|
*/
|
|
857
857
|
static amendFactor(e, t, a) {
|
|
858
|
-
const
|
|
858
|
+
const o = {
|
|
859
859
|
0.55: [1.7, -1.4, -7.4],
|
|
860
860
|
0.6: [2.2, -2.5, -9.7],
|
|
861
861
|
0.65: [2.6, -3.7, -11.6],
|
|
@@ -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
|
* 失速方向因子
|
|
@@ -902,9 +902,9 @@ class H {
|
|
|
902
902
|
* @param kts
|
|
903
903
|
* @private
|
|
904
904
|
*/
|
|
905
|
-
static vesselTagFactor(e, t, a,
|
|
906
|
-
let
|
|
907
|
-
return a === "container" ?
|
|
905
|
+
static vesselTagFactor(e, t, a, o) {
|
|
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
|
* 浪高影响因子
|
|
@@ -915,8 +915,8 @@ class H {
|
|
|
915
915
|
*/
|
|
916
916
|
static waveHeightFactor(e, t, a = 10) {
|
|
917
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;
|
|
918
|
-
let
|
|
919
|
-
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.4 : t > 120 && t <= 150 ? o = e < 4 ? 0.5 : -0.5 : t > 150 && t <= 180 ? o = e < 4 ? 0.6 : -0.6 : o = -0.7, Math.round(o * (0.144 * Math.pow(e, 2) + 0.378 * e) * 1e4) / 1e4;
|
|
920
920
|
}
|
|
921
921
|
/**
|
|
922
922
|
* 组装船舶运行参数
|
|
@@ -926,21 +926,21 @@ class H {
|
|
|
926
926
|
* @param bearing 方位角
|
|
927
927
|
* @private
|
|
928
928
|
*/
|
|
929
|
-
static assembleProperties(e, t, a,
|
|
930
|
-
var
|
|
931
|
-
const
|
|
929
|
+
static assembleProperties(e, t, a, o) {
|
|
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";
|
|
932
932
|
return {
|
|
933
|
-
tag:
|
|
934
|
-
lbp:
|
|
933
|
+
tag: u.indexOf("container") > -1 ? "container" : u.indexOf("tugs") > -1 ? "tugs" : "common",
|
|
934
|
+
lbp: i,
|
|
935
935
|
loadCondition: t,
|
|
936
|
-
draught:
|
|
936
|
+
draught: n,
|
|
937
937
|
breadthMoulded: s,
|
|
938
938
|
// 排水量(吨)= 载重量(吨)/ 1.025 + 吃水(米)× 船舶型宽(米)× 船舶型长(米)× 0.7
|
|
939
939
|
// 其中,1.025是指海水的密度,吨是指公吨,吃水是指船舶的最大吃水深度。船舶型宽是指船舶的最大型宽,船舶型长是指船舶的设计型长。上述公式是针对常规船舶适用的,不同类型的船舶可能会有一些差异。
|
|
940
|
-
displacement: Math.round((r / 1.025 +
|
|
940
|
+
displacement: Math.round((r / 1.025 + n * s * i * 0.7) * 1e4) / 1e4,
|
|
941
941
|
// 换算为m/s
|
|
942
942
|
speed: Math.round((a ?? 14.1382) * 1852 / 3600 * 1e4) / 1e4,
|
|
943
|
-
bearing:
|
|
943
|
+
bearing: o || 90
|
|
944
944
|
};
|
|
945
945
|
}
|
|
946
946
|
/**
|
|
@@ -954,47 +954,47 @@ class H {
|
|
|
954
954
|
* @param useRouteParam true 启用设置速度
|
|
955
955
|
* @param options
|
|
956
956
|
*/
|
|
957
|
-
static async speedLoseAt(e, t, a,
|
|
958
|
-
let
|
|
959
|
-
if (t.velocity && s && (e.speed = J.roundPrecision(t.velocity * 1852 / 3600, 6)),
|
|
960
|
-
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;
|
|
961
961
|
try {
|
|
962
|
-
|
|
963
|
-
const { weatherModels:
|
|
962
|
+
o = (o == null ? void 0 : o.toUpperCase()) === "CMEMS" ? "ECMWF" : o, o = (o == null ? void 0 : o.toUpperCase()) === "METEO2" ? "best_match" : o;
|
|
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, {
|
|
964
964
|
...r,
|
|
965
965
|
pastDays: 1,
|
|
966
966
|
forecastDays: 2,
|
|
967
|
-
weatherModels:
|
|
967
|
+
weatherModels: k,
|
|
968
968
|
marineModels: p
|
|
969
|
-
}), [
|
|
970
|
-
|
|
971
|
-
} catch (
|
|
972
|
-
|
|
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);
|
|
973
973
|
}
|
|
974
|
-
let
|
|
975
|
-
const
|
|
976
|
-
|
|
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(
|
|
977
977
|
"[%s] v0(%d) is less then factor(%d) = wxFactor(%d) + cFactor(%d), scale factor with 0.6",
|
|
978
978
|
r.requestId,
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
),
|
|
984
|
-
const b =
|
|
985
|
-
h += b;
|
|
986
|
-
let
|
|
987
|
-
|
|
988
|
-
meteo: { ...
|
|
989
|
-
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,
|
|
990
990
|
v0Factor: b,
|
|
991
|
-
cFactor:
|
|
992
|
-
speed: t.velocity && s ? t.velocity :
|
|
991
|
+
cFactor: h,
|
|
992
|
+
speed: t.velocity && s ? t.velocity : E,
|
|
993
993
|
eta: a.utc().format(),
|
|
994
994
|
etd: a.utc().format()
|
|
995
995
|
};
|
|
996
996
|
} else
|
|
997
|
-
|
|
997
|
+
u = {
|
|
998
998
|
wxFactor: 0,
|
|
999
999
|
v0Factor: 0,
|
|
1000
1000
|
cFactor: 0,
|
|
@@ -1002,7 +1002,7 @@ class H {
|
|
|
1002
1002
|
eta: a.utc().format(),
|
|
1003
1003
|
etd: a.utc().format()
|
|
1004
1004
|
};
|
|
1005
|
-
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 };
|
|
1006
1006
|
}
|
|
1007
1007
|
/**
|
|
1008
1008
|
* 基于步长计算失速样本
|
|
@@ -1018,83 +1018,83 @@ class H {
|
|
|
1018
1018
|
* @param options
|
|
1019
1019
|
* @private
|
|
1020
1020
|
*/
|
|
1021
|
-
static async speedLoseInHoursStep(e, t, a,
|
|
1021
|
+
static async speedLoseInHoursStep(e, t, a, o, i, n, s = "", r = !0, u = !1, l = {}) {
|
|
1022
1022
|
t.utc();
|
|
1023
|
-
const
|
|
1024
|
-
let
|
|
1025
|
-
for (let m = 0; m <
|
|
1026
|
-
let
|
|
1027
|
-
|
|
1028
|
-
const f =
|
|
1029
|
-
if (e.bearing = R.calculateBearing(
|
|
1030
|
-
|
|
1031
|
-
const M =
|
|
1032
|
-
if (
|
|
1033
|
-
|
|
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;
|
|
1034
1034
|
else {
|
|
1035
|
-
const j =
|
|
1036
|
-
|
|
1035
|
+
const j = o - E;
|
|
1036
|
+
c.elapsed += j, t.add(j, "hour"), o = 0;
|
|
1037
1037
|
}
|
|
1038
|
-
if (
|
|
1039
|
-
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 };
|
|
1040
1040
|
} else
|
|
1041
|
-
|
|
1042
|
-
r = t.isAfter(
|
|
1043
|
-
const y = R.calculateDistance(
|
|
1044
|
-
let
|
|
1045
|
-
if (
|
|
1046
|
-
if (
|
|
1047
|
-
`[%s] go to %j from %j with ${y}nm, and cost ${
|
|
1048
|
-
|
|
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,
|
|
1049
1049
|
{ lat: f.lat, lng: f.lng },
|
|
1050
1050
|
{ lat: v.lat, lng: v.lng, etd: v.etd }
|
|
1051
|
-
),
|
|
1052
|
-
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];
|
|
1053
1053
|
break;
|
|
1054
1054
|
}
|
|
1055
1055
|
} else {
|
|
1056
|
-
|
|
1057
|
-
const M = J.roundPrecision(v.speed *
|
|
1058
|
-
p = R.calculateCoordinate(
|
|
1059
|
-
`[%s] go to %j from %j with ${M}nm, and cost ${
|
|
1060
|
-
|
|
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,
|
|
1061
1061
|
{ lat: p.lat, lng: p.lng },
|
|
1062
|
-
{ lat:
|
|
1063
|
-
),
|
|
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;
|
|
1064
1064
|
break;
|
|
1065
1065
|
}
|
|
1066
1066
|
}
|
|
1067
|
-
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 };
|
|
1068
1068
|
}
|
|
1069
1069
|
/**
|
|
1070
1070
|
* 洋流影响因子
|
|
1071
1071
|
* @param bearing 船舶航行方位角
|
|
1072
1072
|
* @param current 洋流要素
|
|
1073
1073
|
* @param role 1: 船东, 2: 租家, 0: 未知
|
|
1074
|
+
* @param options
|
|
1074
1075
|
*/
|
|
1075
|
-
static currentFactor(e, t, a = 0) {
|
|
1076
|
-
const
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
let o = ((t == null ? void 0 : t.kts) || 0) * Math.cos(n);
|
|
1080
|
-
return a & 2 ? o = Math.ceil(o * 100) / 100 : a & 1 ? o = Math.floor(o * 100) / 100 : o = Math.round(o * 100) / 100, Math.abs(o) > 5 ? 0 : o;
|
|
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;
|
|
1081
1080
|
}
|
|
1082
1081
|
/**
|
|
1083
1082
|
* 风浪影响因子
|
|
1084
1083
|
* @param props 船舶档案
|
|
1085
1084
|
* @param wwc 气象要素
|
|
1086
1085
|
* @param cFactor 洋流因子
|
|
1086
|
+
* @param options
|
|
1087
1087
|
*/
|
|
1088
|
-
static weatherFactor(e, t, a = 0) {
|
|
1089
|
-
var
|
|
1090
|
-
|
|
1091
|
-
const
|
|
1092
|
-
let
|
|
1093
|
-
const l = H.directionFactor(
|
|
1094
|
-
let
|
|
1095
|
-
|
|
1096
|
-
const
|
|
1097
|
-
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", o.requestId, 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;
|
|
1098
1098
|
}
|
|
1099
1099
|
/**
|
|
1100
1100
|
* 以12小时级别去掉重复的days
|
|
@@ -1102,7 +1102,7 @@ class H {
|
|
|
1102
1102
|
* @param interval 12 hours
|
|
1103
1103
|
*/
|
|
1104
1104
|
static async reduceDays(e, t = 12 * 60 * 60) {
|
|
1105
|
-
return e = e == null ? void 0 : e.reduce((a,
|
|
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;
|
|
1106
1106
|
}
|
|
1107
1107
|
/**
|
|
1108
1108
|
* 以分钟级别去掉重复的wps
|
|
@@ -1110,7 +1110,7 @@ class H {
|
|
|
1110
1110
|
* @param interval 1 minute
|
|
1111
1111
|
*/
|
|
1112
1112
|
static async reduceWPS(e, t = 60) {
|
|
1113
|
-
return e = e == null ? void 0 : e.reduce((a,
|
|
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;
|
|
1114
1114
|
}
|
|
1115
1115
|
/**
|
|
1116
1116
|
* 全程失速分析(走完航程)
|
|
@@ -1125,37 +1125,37 @@ class H {
|
|
|
1125
1125
|
* @param useRouteParam
|
|
1126
1126
|
* @param options
|
|
1127
1127
|
*/
|
|
1128
|
-
static async analyseInstant(e, t, a,
|
|
1128
|
+
static async analyseInstant(e, t, a, o, i, n = "", s = 0, r = !0, u = !1, l = {}) {
|
|
1129
1129
|
var U, G, X, Q, Z, $;
|
|
1130
|
-
const
|
|
1130
|
+
const h = w().valueOf();
|
|
1131
1131
|
e.lng = J.convertToStdLng(e.lng);
|
|
1132
|
-
const { route:
|
|
1132
|
+
const { route: d, waypoints: I } = i.points, b = R.calculateSubRoute(e, d);
|
|
1133
1133
|
if (((U = b[0]) == null ? void 0 : U.length) <= 1)
|
|
1134
1134
|
return;
|
|
1135
|
-
const { v0:
|
|
1135
|
+
const { v0: E, label: k } = e.sog ? {
|
|
1136
1136
|
v0: e.sog,
|
|
1137
1137
|
label: e.label || "Other"
|
|
1138
1138
|
/* Instruct */
|
|
1139
1139
|
} : {
|
|
1140
|
-
v0:
|
|
1140
|
+
v0: o.speed,
|
|
1141
1141
|
label: "CP"
|
|
1142
1142
|
/* Cp */
|
|
1143
|
-
}, p = H.assembleProperties(a,
|
|
1143
|
+
}, p = H.assembleProperties(a, o.loadCondition, E, 0), v = I.length ? R.calculateSubWaypoints(e, I) : [];
|
|
1144
1144
|
v.forEach((P) => P.important = !0);
|
|
1145
1145
|
const m = {
|
|
1146
1146
|
from: { ...e },
|
|
1147
1147
|
route: b,
|
|
1148
1148
|
waypoints: v,
|
|
1149
|
-
v0:
|
|
1150
|
-
label:
|
|
1151
|
-
},
|
|
1149
|
+
v0: E,
|
|
1150
|
+
label: k
|
|
1151
|
+
}, c = {
|
|
1152
1152
|
hours: [],
|
|
1153
1153
|
days: [],
|
|
1154
1154
|
wps: [],
|
|
1155
1155
|
all: []
|
|
1156
1156
|
};
|
|
1157
|
-
s || (R.calculateRouteDistance(b) /
|
|
1158
|
-
let f = R.simplifyRouteToCoordinates(b, v, 0), y = 0,
|
|
1157
|
+
s || (R.calculateRouteDistance(b) / o.speed <= 72 ? s = 3 : s = 6);
|
|
1158
|
+
let f = R.simplifyRouteToCoordinates(b, v, 0), y = 0, F = 0, M = 0, j = 0;
|
|
1159
1159
|
t = w(t).utc();
|
|
1160
1160
|
const N = t.clone();
|
|
1161
1161
|
for (; f.length > 0; ) {
|
|
@@ -1166,36 +1166,36 @@ class H {
|
|
|
1166
1166
|
B,
|
|
1167
1167
|
y,
|
|
1168
1168
|
f,
|
|
1169
|
-
|
|
1169
|
+
n,
|
|
1170
1170
|
r,
|
|
1171
|
-
|
|
1172
|
-
|
|
1171
|
+
u,
|
|
1172
|
+
l
|
|
1173
1173
|
);
|
|
1174
|
-
if (
|
|
1175
|
-
const O = await H.speedLoseAt(p, T.to, w(T.to.eta),
|
|
1176
|
-
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);
|
|
1177
1177
|
}
|
|
1178
1178
|
y += Math.round((((X = T == null ? void 0 : T.to) == null ? void 0 : X.distanceFromPrevious) ?? 0) * 1e4) / 1e4;
|
|
1179
1179
|
}
|
|
1180
|
-
const D =
|
|
1180
|
+
const D = c.hours;
|
|
1181
1181
|
for (let P = 0; P < D.length - 1; P++) {
|
|
1182
1182
|
const B = w(D[P + 1].eta).diff(D[P].etd, "hour", !0) || 1;
|
|
1183
|
-
|
|
1183
|
+
F += (D[P].wxFactor || 0) * B, M += (D[P].cFactor || 0) * B, j += B;
|
|
1184
1184
|
}
|
|
1185
1185
|
const L = D.reduce((P, B) => P + (B.suspend || 0), 0);
|
|
1186
|
-
(Q =
|
|
1186
|
+
(Q = c.wps) == null || Q.forEach((P, B) => {
|
|
1187
1187
|
P.positionTime = w.utc(P.etd || P.eta).unix();
|
|
1188
|
-
const T =
|
|
1188
|
+
const T = c.wps[B - 1];
|
|
1189
1189
|
if (T) {
|
|
1190
1190
|
const O = P.distanceFromStart - T.distanceFromStart, q = w(P.eta || P.etd).diff(w(T.etd || T.eta), "h", !0);
|
|
1191
1191
|
P.avgSpd = Math.round(O / q * 100) / 100;
|
|
1192
1192
|
const at = R.calculateBearing(T, P);
|
|
1193
1193
|
P.avgBearing = at, T.bearing = at;
|
|
1194
1194
|
}
|
|
1195
|
-
}),
|
|
1196
|
-
const W =
|
|
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(
|
|
1198
|
-
const Y = J.roundPrecision(
|
|
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);
|
|
1199
1199
|
m.extend = {
|
|
1200
1200
|
eca: tt,
|
|
1201
1201
|
distanceInECA: A,
|
|
@@ -1203,8 +1203,8 @@ class H {
|
|
|
1203
1203
|
totalDgoConsInECA: ot,
|
|
1204
1204
|
totalDgoConsInSuspend: Y
|
|
1205
1205
|
}, m.totalFoCons = et < 0 ? 0 : et, m.totalDgoCons = it;
|
|
1206
|
-
const st = w().valueOf() -
|
|
1207
|
-
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;
|
|
1208
1208
|
}
|
|
1209
1209
|
/**
|
|
1210
1210
|
* 分段失速分析(最多走hours 小时)
|
|
@@ -1221,24 +1221,24 @@ class H {
|
|
|
1221
1221
|
* @param useRouteParam
|
|
1222
1222
|
* @param options
|
|
1223
1223
|
*/
|
|
1224
|
-
static async analyseInstantWithThreshed(e, t, a,
|
|
1224
|
+
static async analyseInstantWithThreshed(e, t, a, o, i, n, s, r = "", u = 3, l = !0, h = !1, d = {}) {
|
|
1225
1225
|
var X, Q, Z, $, P, B;
|
|
1226
|
-
const
|
|
1226
|
+
const I = w().valueOf();
|
|
1227
1227
|
e.lng = J.convertToStdLng(e.lng);
|
|
1228
|
-
const { v0: b, label:
|
|
1228
|
+
const { v0: b, label: E } = e.sog ? {
|
|
1229
1229
|
v0: e.sog,
|
|
1230
1230
|
label: e.label || "Other"
|
|
1231
1231
|
/* Instruct */
|
|
1232
1232
|
} : {
|
|
1233
|
-
v0:
|
|
1233
|
+
v0: i.speed,
|
|
1234
1234
|
label: "CP"
|
|
1235
1235
|
/* Cp */
|
|
1236
|
-
},
|
|
1236
|
+
}, k = H.assembleProperties(o, i.loadCondition, b, 0), p = R.calculateSubRoute(e, n);
|
|
1237
1237
|
if (((X = p[0]) == null ? void 0 : X.length) <= 1)
|
|
1238
1238
|
return;
|
|
1239
1239
|
const v = s.length ? R.calculateSubWaypoints(e, s) : [];
|
|
1240
1240
|
v.forEach((T) => T.important = !0);
|
|
1241
|
-
let m = R.simplifyRouteToCoordinates(p, v, 0),
|
|
1241
|
+
let m = R.simplifyRouteToCoordinates(p, v, 0), c = 0, f = 0, y = 0, F = 0;
|
|
1242
1242
|
const M = {
|
|
1243
1243
|
hours: [],
|
|
1244
1244
|
wps: [],
|
|
@@ -1248,11 +1248,11 @@ class H {
|
|
|
1248
1248
|
t = w(t).utc();
|
|
1249
1249
|
const j = t.clone();
|
|
1250
1250
|
for (; m.length > 0; ) {
|
|
1251
|
-
const T =
|
|
1251
|
+
const T = u - t.hour() % u;
|
|
1252
1252
|
let O = Math.ceil(t.clone().add(T, "h").set({ minute: 0, second: 0, millisecond: 0 }).diff(t, "h", !0) * 1e4) / 1e4;
|
|
1253
1253
|
O = t.clone().add(O, "h").isSameOrAfter(a) ? a.diff(t, "h", !0) * 1e4 / 1e4 : O;
|
|
1254
|
-
const q = await H.speedLoseInHoursStep(
|
|
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),
|
|
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)
|
|
1256
1256
|
break;
|
|
1257
1257
|
}
|
|
1258
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) => {
|
|
@@ -1265,7 +1265,7 @@ class H {
|
|
|
1265
1265
|
const N = M.hours;
|
|
1266
1266
|
for (let T = 0; T < N.length - 1; T++) {
|
|
1267
1267
|
const O = w(N[T + 1].eta).diff(N[T].etd, "hour", !0);
|
|
1268
|
-
f += N[T].wxFactor * O, y += N[T].cFactor * O,
|
|
1268
|
+
f += N[T].wxFactor * O, y += N[T].cFactor * O, F += O;
|
|
1269
1269
|
}
|
|
1270
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 = {
|
|
1271
1271
|
sample: M,
|
|
@@ -1273,18 +1273,18 @@ class H {
|
|
|
1273
1273
|
// 注意,可能会在first节点Drift,所有采用eta做为初始出发时间
|
|
1274
1274
|
etd: w(L.eta).utc().format(),
|
|
1275
1275
|
eta: w(W == null ? void 0 : W.eta).utc().format(),
|
|
1276
|
-
wxFactor: Math.round(f /
|
|
1277
|
-
cFactor: Math.round(y /
|
|
1278
|
-
avgSpeed: Math.round(((W == null ? void 0 : W.distanceFromStart) || 0) /
|
|
1279
|
-
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,
|
|
1280
1280
|
suspend: Math.round(D * 1e3) / 1e3,
|
|
1281
1281
|
from: L,
|
|
1282
1282
|
to: W,
|
|
1283
1283
|
route: C,
|
|
1284
1284
|
waypoints: Y,
|
|
1285
1285
|
v0: b,
|
|
1286
|
-
label:
|
|
1287
|
-
}, 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);
|
|
1288
1288
|
A.extend = {
|
|
1289
1289
|
eca: it,
|
|
1290
1290
|
distanceInECA: ot,
|
|
@@ -1292,8 +1292,8 @@ class H {
|
|
|
1292
1292
|
totalDgoConsInECA: et,
|
|
1293
1293
|
totalDgoConsInSuspend: V
|
|
1294
1294
|
}, A.totalDgoCons = st, A.totalFoCons = rt < 0 ? 0 : rt;
|
|
1295
|
-
const U = w().valueOf() -
|
|
1296
|
-
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;
|
|
1297
1297
|
}
|
|
1298
1298
|
/**
|
|
1299
1299
|
* 在指定航线条件下,基于多CP,动态计算最优成本(租金+油费)方案
|
|
@@ -1310,59 +1310,59 @@ class H {
|
|
|
1310
1310
|
* @param lane 基础航线(重要转向点)
|
|
1311
1311
|
* @param options
|
|
1312
1312
|
*/
|
|
1313
|
-
static async analyseCost(e, t, a,
|
|
1313
|
+
static async analyseCost(e, t, a, o, i = {}) {
|
|
1314
1314
|
var p, v;
|
|
1315
|
-
const
|
|
1315
|
+
const n = w().valueOf(), s = [];
|
|
1316
1316
|
e.speedStep = e.speedStep || 3, e.alterStep = e.alterStep ?? 1;
|
|
1317
|
-
const r = R.calculateRouteDistance(
|
|
1318
|
-
let
|
|
1317
|
+
const r = R.calculateRouteDistance(o.route);
|
|
1318
|
+
let u = 0;
|
|
1319
1319
|
a.forEach((m) => {
|
|
1320
|
-
const
|
|
1321
|
-
|
|
1322
|
-
}),
|
|
1323
|
-
const
|
|
1324
|
-
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;
|
|
1325
1325
|
for (const m of a) {
|
|
1326
|
-
const
|
|
1326
|
+
const c = JSON.parse(JSON.stringify(o.route)), f = JSON.parse(JSON.stringify(o.waypoints)), y = await H.analyseInstantWithThreshed(
|
|
1327
1327
|
{ lat: e.lat, lng: e.lng },
|
|
1328
1328
|
e.etd,
|
|
1329
|
-
|
|
1329
|
+
l,
|
|
1330
1330
|
t,
|
|
1331
1331
|
m,
|
|
1332
|
-
|
|
1332
|
+
c,
|
|
1333
1333
|
f,
|
|
1334
1334
|
e.meteoVendor,
|
|
1335
1335
|
e.speedStep,
|
|
1336
1336
|
e.useMeteo,
|
|
1337
1337
|
e.useRouteParam,
|
|
1338
|
-
|
|
1338
|
+
i
|
|
1339
1339
|
);
|
|
1340
|
-
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(), {
|
|
1341
1341
|
cost: y.cost.total,
|
|
1342
1342
|
hire: y.cost.hire,
|
|
1343
1343
|
bunker: y.cost.bunker,
|
|
1344
1344
|
distance: y.distance,
|
|
1345
1345
|
hours: y.totalHrs,
|
|
1346
1346
|
cp: `${m.speed}/${m.fo}/${m.dgo}`
|
|
1347
|
-
})),
|
|
1347
|
+
})), h++;
|
|
1348
1348
|
}
|
|
1349
|
-
s.sort((m,
|
|
1350
|
-
const
|
|
1351
|
-
if (b.push({ combined: !1, speeds: [
|
|
1352
|
-
const m =
|
|
1353
|
-
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);
|
|
1354
1354
|
M = M > 7 ? 7 : M < e.alterStep ? e.alterStep : M;
|
|
1355
|
-
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;
|
|
1356
1356
|
for (; M >= e.alterStep; ) {
|
|
1357
|
-
const L = await H.combinedAnalyse(e, t,
|
|
1357
|
+
const L = await H.combinedAnalyse(e, t, l, [m, c], o, M, { ...i, level: j });
|
|
1358
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)
|
|
1359
1359
|
break;
|
|
1360
1360
|
M = Math.ceil(M / 2), j += 1;
|
|
1361
1361
|
}
|
|
1362
1362
|
b.push(N), D && b.push(D);
|
|
1363
1363
|
}
|
|
1364
|
-
const
|
|
1365
|
-
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);
|
|
1366
1366
|
}
|
|
1367
1367
|
/**
|
|
1368
1368
|
* 按步长多次减半,分别用7,4,2,1天步长及cpa,cpb交替计算各种组合下的成本
|
|
@@ -1374,24 +1374,24 @@ class H {
|
|
|
1374
1374
|
* @param step 步长,7,4,2,1
|
|
1375
1375
|
* @param options
|
|
1376
1376
|
*/
|
|
1377
|
-
static async combinedAnalyse(e, t, a,
|
|
1378
|
-
s.counter = 1,
|
|
1379
|
-
const r = await H.alternateAnalyse(e, t, a,
|
|
1380
|
-
|
|
1381
|
-
cost:
|
|
1382
|
-
hire:
|
|
1383
|
-
bunker:
|
|
1384
|
-
distance:
|
|
1385
|
-
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
|
|
1386
1386
|
});
|
|
1387
|
-
const b = await H.alternateAnalyse(e, t, a,
|
|
1388
|
-
return
|
|
1389
|
-
cost:
|
|
1390
|
-
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,
|
|
1391
1391
|
bunker: p,
|
|
1392
1392
|
distance: v,
|
|
1393
1393
|
hours: m
|
|
1394
|
-
}),
|
|
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 };
|
|
1395
1395
|
}
|
|
1396
1396
|
/**
|
|
1397
1397
|
* 基于cp索引,交替计算指定步长下的成本
|
|
@@ -1404,31 +1404,31 @@ class H {
|
|
|
1404
1404
|
* @param step 步长,7,4,2,1
|
|
1405
1405
|
* @param options
|
|
1406
1406
|
*/
|
|
1407
|
-
static async alternateAnalyse(e, t, a,
|
|
1408
|
-
var
|
|
1409
|
-
let
|
|
1410
|
-
const
|
|
1411
|
-
for (;
|
|
1412
|
-
const b =
|
|
1413
|
-
|
|
1414
|
-
|
|
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(),
|
|
1415
1415
|
b,
|
|
1416
1416
|
t,
|
|
1417
1417
|
p,
|
|
1418
|
-
|
|
1419
|
-
|
|
1418
|
+
E,
|
|
1419
|
+
k,
|
|
1420
1420
|
e.meteoVendor,
|
|
1421
1421
|
e.speedStep,
|
|
1422
1422
|
e.useMeteo,
|
|
1423
1423
|
e.useRouteParam,
|
|
1424
1424
|
r
|
|
1425
1425
|
);
|
|
1426
|
-
v && (await H.calculateCost(v, p, e, r),
|
|
1426
|
+
v && (await H.calculateCost(v, p, e, r), S == null || S.info(
|
|
1427
1427
|
"[%s][L%d-%d] analyse from %s to %s cost: %j",
|
|
1428
1428
|
r.requestId,
|
|
1429
1429
|
r.level,
|
|
1430
1430
|
r.counter,
|
|
1431
|
-
|
|
1431
|
+
u.utc().format(),
|
|
1432
1432
|
b.utc().format(),
|
|
1433
1433
|
{
|
|
1434
1434
|
cost: v.cost.total,
|
|
@@ -1439,13 +1439,13 @@ class H {
|
|
|
1439
1439
|
cp: `${p.speed}/${p.fo}/${p.dgo}`
|
|
1440
1440
|
}
|
|
1441
1441
|
)), r.counter = r.counter + 1;
|
|
1442
|
-
const m = (
|
|
1442
|
+
const m = (I = (d = v == null ? void 0 : v.sample) == null ? void 0 : d.hours) == null ? void 0 : I.at(-1);
|
|
1443
1443
|
if (m)
|
|
1444
|
-
|
|
1444
|
+
l.lat = m.lat, l.lng = m.lng, u = w(m.eta), h.push(v), i = i ? 0 : 1;
|
|
1445
1445
|
else
|
|
1446
1446
|
break;
|
|
1447
1447
|
}
|
|
1448
|
-
return
|
|
1448
|
+
return h;
|
|
1449
1449
|
}
|
|
1450
1450
|
/**
|
|
1451
1451
|
* 计算Speed的cost
|
|
@@ -1454,15 +1454,15 @@ class H {
|
|
|
1454
1454
|
* @param props
|
|
1455
1455
|
* @param options
|
|
1456
1456
|
*/
|
|
1457
|
-
static async calculateCost(e, t, a,
|
|
1458
|
-
var
|
|
1457
|
+
static async calculateCost(e, t, a, o = {}) {
|
|
1458
|
+
var i;
|
|
1459
1459
|
if (e) {
|
|
1460
|
-
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;
|
|
1461
1461
|
e.cost = {
|
|
1462
|
-
total: Math.round((r +
|
|
1462
|
+
total: Math.round((r + u + l) * 1e3) / 1e3,
|
|
1463
1463
|
hire: Math.round(r * 1e3) / 1e3,
|
|
1464
1464
|
suspendHire: s,
|
|
1465
|
-
bunker: Math.round((
|
|
1465
|
+
bunker: Math.round((u + l) * 1e3) / 1e3,
|
|
1466
1466
|
cp: t
|
|
1467
1467
|
};
|
|
1468
1468
|
}
|
|
@@ -1473,22 +1473,22 @@ class H {
|
|
|
1473
1473
|
*
|
|
1474
1474
|
*/
|
|
1475
1475
|
static async calculateECA(e, t, a = {}) {
|
|
1476
|
-
var r,
|
|
1477
|
-
const
|
|
1478
|
-
let
|
|
1479
|
-
(
|
|
1480
|
-
|
|
1476
|
+
var r, u, l, h;
|
|
1477
|
+
const o = await R.intersectInECA((e == null ? void 0 : e.route) || []);
|
|
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();
|
|
1481
1481
|
});
|
|
1482
|
-
for (const
|
|
1483
|
-
|
|
1484
|
-
const
|
|
1485
|
-
|
|
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;
|
|
1486
1486
|
}
|
|
1487
|
-
return
|
|
1488
|
-
distanceInECA:
|
|
1489
|
-
hoursInECA:
|
|
1487
|
+
return i = J.roundPrecision(i, 3), n = J.roundPrecision(n, 3), s = J.roundPrecision(s, 3), {
|
|
1488
|
+
distanceInECA: i,
|
|
1489
|
+
hoursInECA: n,
|
|
1490
1490
|
totalDgoConsInECA: s,
|
|
1491
|
-
eca:
|
|
1491
|
+
eca: o
|
|
1492
1492
|
};
|
|
1493
1493
|
}
|
|
1494
1494
|
/**
|
|
@@ -1497,40 +1497,40 @@ class H {
|
|
|
1497
1497
|
* @param options
|
|
1498
1498
|
*/
|
|
1499
1499
|
static async mergeSpeeds(e, t = {}) {
|
|
1500
|
-
var m,
|
|
1500
|
+
var m, c;
|
|
1501
1501
|
const a = {
|
|
1502
1502
|
hours: [],
|
|
1503
1503
|
wps: [],
|
|
1504
1504
|
days: [],
|
|
1505
1505
|
all: []
|
|
1506
|
-
},
|
|
1507
|
-
var
|
|
1508
|
-
return f + (((
|
|
1509
|
-
}, 0),
|
|
1510
|
-
var
|
|
1511
|
-
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);
|
|
1512
1512
|
}, 0), r = e.reduce((f, y) => {
|
|
1513
|
-
var
|
|
1514
|
-
return f + (((
|
|
1515
|
-
}, 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 = [];
|
|
1516
1516
|
let v;
|
|
1517
1517
|
for (const f of e) {
|
|
1518
1518
|
p.push(...((m = f.extend) == null ? void 0 : m.eca) || []);
|
|
1519
|
-
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);
|
|
1520
1520
|
v && (N.distanceFromPrevious = v.distanceFromPrevious, N.distanceFromStart = v.distanceFromStart, y.forEach((C, Y) => {
|
|
1521
1521
|
Y && (C.distanceFromStart = C.distanceFromStart + v.distanceFromStart);
|
|
1522
|
-
}),
|
|
1522
|
+
}), F.at(0).distanceFromPrevious = v.distanceFromPrevious, F.at(0).distanceFromStart = v.distanceFromStart, F.forEach((C, Y) => {
|
|
1523
1523
|
Y && (C.distanceFromStart = C.distanceFromStart + v.distanceFromStart);
|
|
1524
1524
|
}), M.at(0).distanceFromPrevious = v.distanceFromPrevious, M.at(0).distanceFromStart = v.distanceFromStart, M.forEach((C, Y) => {
|
|
1525
1525
|
Y && (C.distanceFromStart = C.distanceFromStart + v.distanceFromStart);
|
|
1526
1526
|
}), j.at(0).distanceFromPrevious = v.distanceFromPrevious, j.at(0).distanceFromStart = v.distanceFromStart, j.forEach((C, Y) => {
|
|
1527
1527
|
Y && (C.distanceFromStart = C.distanceFromStart + v.distanceFromStart);
|
|
1528
1528
|
})), N.cp = f.cost.cp;
|
|
1529
|
-
const D = [f.etd, f.eta], L =
|
|
1530
|
-
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) => {
|
|
1531
1531
|
var A;
|
|
1532
1532
|
((A = a.hours) == null ? void 0 : A.findIndex((V) => V.eta === C.eta)) === -1 && a.hours.push(C);
|
|
1533
|
-
}),
|
|
1533
|
+
}), F.forEach((C) => {
|
|
1534
1534
|
var A;
|
|
1535
1535
|
((A = a.all) == null ? void 0 : A.findIndex((V) => V.eta === C.eta)) === -1 && a.all.push(C);
|
|
1536
1536
|
}), M.forEach((C) => {
|
|
@@ -1540,16 +1540,16 @@ class H {
|
|
|
1540
1540
|
var A;
|
|
1541
1541
|
((A = a == null ? void 0 : a.days) == null ? void 0 : A.findIndex((V) => V.eta === C.eta)) === -1 && a.days.push(C);
|
|
1542
1542
|
});
|
|
1543
|
-
const W = (
|
|
1543
|
+
const W = (c = a.wps) == null ? void 0 : c.findIndex((C) => C.eta === N.eta);
|
|
1544
1544
|
W === -1 ? a.wps.push(N) : a.wps[W] = N, v = y.at(-1);
|
|
1545
1545
|
}
|
|
1546
1546
|
return a.wps.sort((f, y) => w(f.etd).unix() - w(y.etd).unix()), a.wps.forEach((f, y) => {
|
|
1547
|
-
const
|
|
1548
|
-
if (
|
|
1549
|
-
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;
|
|
1550
1550
|
f.avgSpd = N;
|
|
1551
|
-
const D = R.calculateBearing(
|
|
1552
|
-
|
|
1551
|
+
const D = R.calculateBearing(F, f);
|
|
1552
|
+
F.bearing = D;
|
|
1553
1553
|
}
|
|
1554
1554
|
}), {
|
|
1555
1555
|
sample: a,
|
|
@@ -1559,22 +1559,22 @@ class H {
|
|
|
1559
1559
|
to: e.at(-1).to,
|
|
1560
1560
|
v0: e.at(0).v0,
|
|
1561
1561
|
label: "Combined",
|
|
1562
|
-
distance: Math.round(
|
|
1563
|
-
totalHrs: Math.round(
|
|
1564
|
-
avgSpeed: Math.round(
|
|
1565
|
-
wxFactor: Math.round(
|
|
1566
|
-
cFactor: Math.round(
|
|
1567
|
-
totalFoCons: Math.round(
|
|
1568
|
-
totalDgoCons: Math.round(
|
|
1562
|
+
distance: Math.round(o * 1e3) / 1e3,
|
|
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,
|
|
1569
1569
|
cost: {
|
|
1570
|
-
total: Math.round(
|
|
1570
|
+
total: Math.round(I * 1e3) / 1e3,
|
|
1571
1571
|
hire: Math.round(b * 1e3) / 1e3,
|
|
1572
|
-
bunker: Math.round(
|
|
1572
|
+
bunker: Math.round(E * 1e3) / 1e3
|
|
1573
1573
|
},
|
|
1574
1574
|
extend: {
|
|
1575
|
-
cps:
|
|
1575
|
+
cps: k,
|
|
1576
1576
|
eca: p,
|
|
1577
|
-
distanceInECA: Math.round(
|
|
1577
|
+
distanceInECA: Math.round(i * 1e3) / 1e3,
|
|
1578
1578
|
hoursInECA: Math.round(s * 1e3) / 1e3,
|
|
1579
1579
|
totalDgoConsInECA: Math.round(r * 1e3) / 1e3,
|
|
1580
1580
|
speeds: e
|