@idm-plugin/vessel 2.2.9 → 2.3.0
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/ais/src/index.d.ts +68 -0
- package/dist/index.js +745 -650
- package/dist/index.umd.cjs +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
var ht = Object.defineProperty;
|
|
2
|
-
var lt = (
|
|
3
|
-
var
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import { LngLatHelper as
|
|
8
|
-
import { MeteoHelper2 as
|
|
2
|
+
var lt = (E, e, t) => e in E ? ht(E, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : E[e] = t;
|
|
3
|
+
var U = (E, e, t) => (lt(E, typeof e != "symbol" ? e + "" : e, t), t);
|
|
4
|
+
import L from "got";
|
|
5
|
+
import ct from "@log4js-node/log4js-api";
|
|
6
|
+
import w from "moment";
|
|
7
|
+
import { LngLatHelper as _, LaneHelper as W } from "@idm-plugin/geo2";
|
|
8
|
+
import { MeteoHelper2 as mt } from "@idm-plugin/meteo2";
|
|
9
9
|
import { Meteo2Assist as it } from "@idm-plugin/meteo";
|
|
10
|
-
let
|
|
10
|
+
let M;
|
|
11
11
|
try {
|
|
12
|
-
|
|
12
|
+
M = ct.getLogger("vessel");
|
|
13
13
|
} catch {
|
|
14
14
|
} finally {
|
|
15
15
|
}
|
|
@@ -18,85 +18,180 @@ class st {
|
|
|
18
18
|
* 解析AIS状态码
|
|
19
19
|
* @param status
|
|
20
20
|
*/
|
|
21
|
-
parseStatus(
|
|
22
|
-
let
|
|
23
|
-
switch (
|
|
21
|
+
parseStatus(e) {
|
|
22
|
+
let t, a;
|
|
23
|
+
switch (e) {
|
|
24
24
|
case 0:
|
|
25
|
-
|
|
25
|
+
t = "在航(主机推动)", a = "Underway Using Engine";
|
|
26
26
|
break;
|
|
27
27
|
case 1:
|
|
28
|
-
|
|
28
|
+
t = "锚泊", a = "Anchored";
|
|
29
29
|
break;
|
|
30
30
|
case 2:
|
|
31
|
-
|
|
31
|
+
t = "失控", a = "Not under command";
|
|
32
32
|
break;
|
|
33
33
|
case 3:
|
|
34
|
-
|
|
34
|
+
t = "操纵受限", a = "Limited airworthiness";
|
|
35
35
|
break;
|
|
36
36
|
case 4:
|
|
37
|
-
|
|
37
|
+
t = "吃水受限", a = "Limited by ship's draft";
|
|
38
38
|
break;
|
|
39
39
|
case 5:
|
|
40
|
-
|
|
40
|
+
t = "靠泊", a = "Mooring";
|
|
41
41
|
break;
|
|
42
42
|
case 6:
|
|
43
|
-
|
|
43
|
+
t = "搁浅", a = "Stranded";
|
|
44
44
|
break;
|
|
45
45
|
case 7:
|
|
46
|
-
|
|
46
|
+
t = "捕捞作业", a = "Engaged in fishing";
|
|
47
47
|
break;
|
|
48
48
|
case 8:
|
|
49
|
-
|
|
49
|
+
t = "靠帆船提供动力", a = "Sailing";
|
|
50
50
|
break;
|
|
51
51
|
default:
|
|
52
|
-
|
|
52
|
+
t = "未定义", a = "Undefined";
|
|
53
53
|
}
|
|
54
|
-
return { labelCn:
|
|
54
|
+
return { labelCn: t, labelEn: a };
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
|
-
class
|
|
58
|
-
constructor(
|
|
57
|
+
class jt extends st {
|
|
58
|
+
constructor(t, a) {
|
|
59
59
|
super();
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
this.clientId =
|
|
60
|
+
U(this, "clientId");
|
|
61
|
+
U(this, "clientSecret");
|
|
62
|
+
U(this, "token");
|
|
63
|
+
this.clientId = t, this.clientSecret = a;
|
|
64
64
|
}
|
|
65
|
-
async authToken(
|
|
65
|
+
async authToken(t = {}) {
|
|
66
66
|
const a = "https://svc.data.myvessel.cn/ada/oauth/token", i = {
|
|
67
67
|
searchParams: {
|
|
68
68
|
client_id: this.clientId,
|
|
69
69
|
client_secret: this.clientSecret,
|
|
70
70
|
grant_type: "client_credentials"
|
|
71
71
|
}
|
|
72
|
-
}, o = await
|
|
73
|
-
|
|
72
|
+
}, o = await L.post(a, i).json();
|
|
73
|
+
M == null || M.info("[%s] fetch access token from: %s - %j", t.requestId, a, o), o.error || (this.token = {
|
|
74
74
|
accessToken: o.access_token,
|
|
75
75
|
tokenType: o.token_type,
|
|
76
76
|
expiresIn: o.expires_in,
|
|
77
77
|
scope: o.scope,
|
|
78
78
|
jti: o.jti,
|
|
79
|
-
issuedAt:
|
|
79
|
+
issuedAt: w().utc().format()
|
|
80
80
|
});
|
|
81
81
|
}
|
|
82
|
-
async
|
|
83
|
-
var
|
|
84
|
-
(!this.token ||
|
|
82
|
+
async checkToken(t = {}) {
|
|
83
|
+
var a;
|
|
84
|
+
return (!this.token || w().diff(w(this.token.issuedAt), "seconds") > (((a = this.token) == null ? void 0 : a.expiresIn) || 0) - 300) && await this.authToken(t), this.token;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* 模糊查询
|
|
88
|
+
* @param kw
|
|
89
|
+
* @param options
|
|
90
|
+
*/
|
|
91
|
+
async suggest(t, a = {}) {
|
|
92
|
+
var s, r;
|
|
93
|
+
await this.checkToken(a);
|
|
94
|
+
const i = "https://market.myvessel.cn/sdc/v1/mkt/vessels/fuzzy", o = {
|
|
95
|
+
headers: {
|
|
96
|
+
Authorization: `${(s = this.token) == null ? void 0 : s.tokenType} ${(r = this.token) == null ? void 0 : r.accessToken}`
|
|
97
|
+
},
|
|
98
|
+
json: {
|
|
99
|
+
kw: t,
|
|
100
|
+
recordNum: a.ps || 10
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
M == null || M.info("[%s] fetch suggest vessels from: %s - %j", a.requestId, i, o);
|
|
104
|
+
const n = await L.post(i, o).json();
|
|
105
|
+
return n.code ? (M == null || M.warn("[%s] fetch suggest vessels failed: %j", a.requestId, { message: n.message, status: n.status, code: n.code }), []) : n.data.map((u) => ({
|
|
106
|
+
mmsi: u.mmsi,
|
|
107
|
+
name: u.nameEn,
|
|
108
|
+
nameCn: u.nameCn,
|
|
109
|
+
imo: Number.isNaN(u.imo) ? null : Number(u.imo),
|
|
110
|
+
callSign: u.callsign,
|
|
111
|
+
type: u.vesselTypeNameEn,
|
|
112
|
+
flagName: u.flagCtry,
|
|
113
|
+
vendor: "myvessel",
|
|
114
|
+
raw: u
|
|
115
|
+
}));
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* imo/mmsi 精确查询
|
|
119
|
+
* @param imo
|
|
120
|
+
* @param options
|
|
121
|
+
*/
|
|
122
|
+
async search(t, a = {}) {
|
|
123
|
+
var c, u;
|
|
124
|
+
await this.checkToken(a);
|
|
125
|
+
const i = /^\d{7}$/.test(t.toString()), o = i ? "https://market.myvessel.cn/sdc/v1/mkt/vessels/detail/imo" : "https://market.myvessel.cn/sdc/v1/mkt/vessels/detail/mmsi", n = i ? { imo: t } : { mmsi: t }, s = {
|
|
126
|
+
headers: {
|
|
127
|
+
Authorization: `${(c = this.token) == null ? void 0 : c.tokenType} ${(u = this.token) == null ? void 0 : u.accessToken}`
|
|
128
|
+
},
|
|
129
|
+
searchParams: n
|
|
130
|
+
};
|
|
131
|
+
M == null || M.info("[%s] fetch vessel from: %s - %j", a.requestId, o, s);
|
|
132
|
+
const r = await L.get(o, s).json();
|
|
133
|
+
if (r.status !== 200)
|
|
134
|
+
return M == null || M.warn("[%s] fetch suggest vessels failed: %j", a.requestId, { message: r.message, status: r.status, code: r.code }), {};
|
|
135
|
+
{
|
|
136
|
+
const m = r.data;
|
|
137
|
+
return {
|
|
138
|
+
mmsi: m.mmsi,
|
|
139
|
+
imo: Number.isNaN(m.imo) ? null : Number(m.imo),
|
|
140
|
+
callSign: m.callsign,
|
|
141
|
+
name: m.nameEn,
|
|
142
|
+
nameCn: m.nameCn,
|
|
143
|
+
type: m.vesselTypeNameEn,
|
|
144
|
+
flagName: m.flagCtry,
|
|
145
|
+
clasz: m.classSociety,
|
|
146
|
+
dateOfBuild: m.buildYearMonth,
|
|
147
|
+
deadweight: m.dwt,
|
|
148
|
+
grossTonnage: m.grt,
|
|
149
|
+
netTonnage: m.net,
|
|
150
|
+
teu: m.teu,
|
|
151
|
+
length: m.length,
|
|
152
|
+
breadth: m.width,
|
|
153
|
+
height: m.height,
|
|
154
|
+
draught: m.draught,
|
|
155
|
+
speed: m.speed,
|
|
156
|
+
passengerCapacity: m.passengercapacity,
|
|
157
|
+
vendor: "myvessel",
|
|
158
|
+
raw: m
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
async archives(t, a = {}) {
|
|
163
|
+
var s, r;
|
|
164
|
+
await this.checkToken(a);
|
|
165
|
+
const i = "https://svc.data.myvessel.cn/sdc/v1/ship/info/batch", o = {
|
|
166
|
+
headers: {
|
|
167
|
+
Authorization: `${(s = this.token) == null ? void 0 : s.tokenType} ${(r = this.token) == null ? void 0 : r.accessToken}`
|
|
168
|
+
},
|
|
169
|
+
json: {
|
|
170
|
+
mmsiList: typeof t == "number" ? [t] : t
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
M == null || M.info("[%s] fetch vessel archive from: %s - %j", a.requestId, i, o);
|
|
174
|
+
const n = await L.post(i, o).json();
|
|
175
|
+
return n.status !== 200 ? (M == null || M.warn("[%s] fetch vessel archive failed: %j", a.requestId, { message: n.message, status: n.status, code: n.code }), {}) : n.data;
|
|
176
|
+
}
|
|
177
|
+
async realTimePosition(t, a = {}) {
|
|
178
|
+
var r, c;
|
|
179
|
+
await this.checkToken(a);
|
|
85
180
|
const i = "https://svc.data.myvessel.cn/sdc/v1/vessels/status/location/unit", o = {
|
|
86
181
|
headers: {
|
|
87
|
-
Authorization: `${(r = this.token) == null ? void 0 : r.tokenType} ${(
|
|
182
|
+
Authorization: `${(r = this.token) == null ? void 0 : r.tokenType} ${(c = this.token) == null ? void 0 : c.accessToken}`
|
|
88
183
|
},
|
|
89
|
-
searchParams: { mmsi:
|
|
184
|
+
searchParams: { mmsi: t }
|
|
90
185
|
};
|
|
91
|
-
|
|
92
|
-
const n = await
|
|
186
|
+
M == null || M.info("[%s] fetch realtime position from: %s - %j", a.requestId, i, o);
|
|
187
|
+
const n = await L.get(i, o).json();
|
|
93
188
|
if (n.code)
|
|
94
|
-
return
|
|
189
|
+
return M == null || M.warn("[%s] fetch realtime position failed: %j", a.requestId, { message: n.message, status: n.status, code: n.code }), n;
|
|
95
190
|
const s = n.data;
|
|
96
|
-
for (const
|
|
97
|
-
!isNaN(s[
|
|
191
|
+
for (const u in s)
|
|
192
|
+
!isNaN(s[u]) && Number(s[u]) !== 1 / 0 && (s[u] = Number(s[u]));
|
|
98
193
|
if (s) {
|
|
99
|
-
const
|
|
194
|
+
const u = w(`${s.postime} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
100
195
|
return {
|
|
101
196
|
mmsi: s.mmsi,
|
|
102
197
|
name: s.vesselName || s.aisVesselName,
|
|
@@ -111,9 +206,9 @@ class Et extends st {
|
|
|
111
206
|
cog: s.cog,
|
|
112
207
|
hdg: s.hdg,
|
|
113
208
|
rot: s.rot,
|
|
114
|
-
eta: /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(s.eta) ?
|
|
209
|
+
eta: /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(s.eta) ? w.utc(s.eta).format() : void 0,
|
|
115
210
|
destination: s.dest,
|
|
116
|
-
positionTime:
|
|
211
|
+
positionTime: u.unix(),
|
|
117
212
|
status: s.status,
|
|
118
213
|
labelCn: s.statusNameCn,
|
|
119
214
|
labelEn: s.statusNameEn,
|
|
@@ -126,83 +221,83 @@ class Et extends st {
|
|
|
126
221
|
net: s.net,
|
|
127
222
|
method: "position",
|
|
128
223
|
vendor: "myVessel",
|
|
129
|
-
utc:
|
|
224
|
+
utc: u.utc().format()
|
|
130
225
|
};
|
|
131
226
|
} else
|
|
132
227
|
return {};
|
|
133
228
|
}
|
|
134
|
-
async trajectory(
|
|
135
|
-
|
|
136
|
-
const
|
|
137
|
-
for (;
|
|
138
|
-
await this.trajectoryIn30Day(
|
|
139
|
-
return await this.trajectoryIn30Day(
|
|
229
|
+
async trajectory(t, a, i, o, n = !0, s = {}) {
|
|
230
|
+
await this.checkToken(s);
|
|
231
|
+
const r = await this.realTimePosition(t, s), c = w(a), u = w(i), m = [];
|
|
232
|
+
for (; u.diff(c, "day", !0) > 30; )
|
|
233
|
+
await this.trajectoryIn30Day(t, c, c.clone().add(30, "day"), r, o, m, s), c.add(30, "day");
|
|
234
|
+
return await this.trajectoryIn30Day(t, c, u, r, o, m, s), m;
|
|
140
235
|
}
|
|
141
|
-
async trajectoryIn30Day(
|
|
142
|
-
var
|
|
143
|
-
const
|
|
236
|
+
async trajectoryIn30Day(t, a, i, o, n, s, r = {}) {
|
|
237
|
+
var y, F, I, p, v;
|
|
238
|
+
const c = "https://svc.data.myvessel.cn/sdc/v1/vessels/status/track", u = {
|
|
144
239
|
headers: {
|
|
145
|
-
Authorization: `${(
|
|
240
|
+
Authorization: `${(y = this.token) == null ? void 0 : y.tokenType} ${(F = this.token) == null ? void 0 : F.accessToken}`
|
|
146
241
|
},
|
|
147
242
|
json: {
|
|
148
|
-
mmsi:
|
|
243
|
+
mmsi: t,
|
|
149
244
|
startTime: a.utcOffset(8).format("YYYY-MM-DD HH:mm:ss"),
|
|
150
245
|
endTime: i.utcOffset(8).format("YYYY-MM-DD HH:mm:ss")
|
|
151
246
|
}
|
|
152
247
|
};
|
|
153
|
-
|
|
154
|
-
const
|
|
155
|
-
if (
|
|
156
|
-
return
|
|
157
|
-
let
|
|
158
|
-
const b =
|
|
159
|
-
return (
|
|
160
|
-
for (const
|
|
161
|
-
!isNaN(
|
|
162
|
-
const
|
|
163
|
-
mmsi:
|
|
248
|
+
M == null || M.info("[%s] fetch trajectory from: %s - %j", r.requestId, c, u);
|
|
249
|
+
const m = await L.post(c, u).json();
|
|
250
|
+
if (m.code)
|
|
251
|
+
return M == null || M.warn("[%s] fetch trajectory failed: %j", r.requestId, c, { message: m.message, status: m.status, code: m.code }), m;
|
|
252
|
+
let f = -1;
|
|
253
|
+
const b = w(`${(p = (I = m.data) == null ? void 0 : I[0]) == null ? void 0 : p.postime} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
254
|
+
return (v = m.data) == null || v.forEach((d) => {
|
|
255
|
+
for (const P in d)
|
|
256
|
+
!isNaN(d[P]) && Number(d[P]) !== 1 / 0 && (d[P] = Number(d[P]));
|
|
257
|
+
const g = w(`${d.postime} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00"), l = d.status, { labelCn: h, labelEn: k } = this.parseStatus(l), S = {
|
|
258
|
+
mmsi: d.mmsi,
|
|
164
259
|
imo: o == null ? void 0 : o.imo,
|
|
165
|
-
lat:
|
|
166
|
-
lng:
|
|
167
|
-
sog:
|
|
168
|
-
cog:
|
|
169
|
-
hdg:
|
|
170
|
-
draught:
|
|
171
|
-
status:
|
|
172
|
-
eta: /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(
|
|
173
|
-
destination:
|
|
174
|
-
positionTime:
|
|
175
|
-
labelCn:
|
|
176
|
-
labelEn:
|
|
260
|
+
lat: d.lat,
|
|
261
|
+
lng: d.lon,
|
|
262
|
+
sog: d.sog,
|
|
263
|
+
cog: d.cog,
|
|
264
|
+
hdg: d.hdg,
|
|
265
|
+
draught: d.draught,
|
|
266
|
+
status: l,
|
|
267
|
+
eta: /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(d.eta) ? w(`${d.eta} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00").utc().format() : void 0,
|
|
268
|
+
destination: d.dest,
|
|
269
|
+
positionTime: g.unix(),
|
|
270
|
+
labelCn: h,
|
|
271
|
+
labelEn: k,
|
|
177
272
|
method: "trajectory",
|
|
178
273
|
vendor: "myVessel",
|
|
179
|
-
utc:
|
|
180
|
-
}, D = Math.floor(
|
|
181
|
-
D !==
|
|
274
|
+
utc: g.utc().format()
|
|
275
|
+
}, D = Math.floor(g.diff(b, "minute", !0) / (n || 1));
|
|
276
|
+
D !== f && (f = D, s.push(S));
|
|
182
277
|
}), s;
|
|
183
278
|
}
|
|
184
279
|
}
|
|
185
|
-
class
|
|
186
|
-
constructor(
|
|
280
|
+
class Et extends st {
|
|
281
|
+
constructor(t) {
|
|
187
282
|
super();
|
|
188
|
-
|
|
189
|
-
this.token =
|
|
283
|
+
U(this, "token");
|
|
284
|
+
this.token = t;
|
|
190
285
|
}
|
|
191
|
-
async realTimePosition(
|
|
286
|
+
async realTimePosition(t, a = {}) {
|
|
192
287
|
const i = "https://api.hifleet.com/position/position/get/token", o = {
|
|
193
288
|
searchParams: {
|
|
194
|
-
mmsi:
|
|
289
|
+
mmsi: t,
|
|
195
290
|
usertoken: this.token
|
|
196
291
|
}
|
|
197
|
-
}, n = await
|
|
198
|
-
|
|
292
|
+
}, n = await L.post(i, o).json();
|
|
293
|
+
M == null || M.info("[%s] fetch realtime position from: %s - %j", a.requestId, i, o);
|
|
199
294
|
const s = n == null ? void 0 : n.list;
|
|
200
295
|
if (!s)
|
|
201
|
-
return
|
|
296
|
+
return M == null || M.warn("[%s] fetch realtime position failed: %j", a.requestId, i, n), n;
|
|
202
297
|
for (const b in s)
|
|
203
298
|
!isNaN(s[b]) && Number(s[b]) !== 1 / 0 && (s[b] = Number(s[b]));
|
|
204
299
|
s.status = s.sp > 3 ? 0 : 1;
|
|
205
|
-
const
|
|
300
|
+
const r = s.status, { labelCn: c, labelEn: u } = this.parseStatus(r), m = w(`${s.ti} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
206
301
|
return {
|
|
207
302
|
mmsi: s.m,
|
|
208
303
|
name: s.n,
|
|
@@ -217,26 +312,26 @@ class xt extends st {
|
|
|
217
312
|
cog: s.co,
|
|
218
313
|
hdg: s.h,
|
|
219
314
|
rot: isNaN(s.rot) ? 0 : s.rot,
|
|
220
|
-
eta: /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(s.eta) ?
|
|
315
|
+
eta: /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(s.eta) ? w.utc(s.eta).format() : void 0,
|
|
221
316
|
destination: s.destination,
|
|
222
317
|
vesselType: s.type,
|
|
223
318
|
dwt: s.dwt,
|
|
224
319
|
build: s.buildyear,
|
|
225
320
|
flag: s.fn,
|
|
226
|
-
positionTime:
|
|
227
|
-
utc:
|
|
228
|
-
status:
|
|
229
|
-
labelCn:
|
|
230
|
-
labelEn:
|
|
321
|
+
positionTime: m.unix(),
|
|
322
|
+
utc: m.utc().format(),
|
|
323
|
+
status: r,
|
|
324
|
+
labelCn: c,
|
|
325
|
+
labelEn: u,
|
|
231
326
|
method: "position",
|
|
232
327
|
vendor: "hifleet"
|
|
233
328
|
};
|
|
234
329
|
}
|
|
235
|
-
async search(
|
|
330
|
+
async search(t, a = {}) {
|
|
236
331
|
let i = "https://www.hifleet.com/hifleetapi/searchVesselOL.do";
|
|
237
332
|
const o = {
|
|
238
333
|
searchParams: {
|
|
239
|
-
keyword:
|
|
334
|
+
keyword: t
|
|
240
335
|
},
|
|
241
336
|
headers: {
|
|
242
337
|
Referer: "https://www.hifleet.com",
|
|
@@ -244,10 +339,10 @@ class xt extends st {
|
|
|
244
339
|
Host: "www.hifleet.com"
|
|
245
340
|
}
|
|
246
341
|
};
|
|
247
|
-
let n = await
|
|
248
|
-
|
|
249
|
-
for (const
|
|
250
|
-
!isNaN(n[
|
|
342
|
+
let n = await L.post(i, o).json();
|
|
343
|
+
M == null || M.info("[%s] fetch vessel props from: %s - %j", a.requestId, i, o), n instanceof Array && (n = n[0]);
|
|
344
|
+
for (const r in n)
|
|
345
|
+
!isNaN(n[r]) && Number(n[r]) !== 1 / 0 && (n[r] = Number(n[r]));
|
|
251
346
|
const s = {
|
|
252
347
|
mmsi: n.m,
|
|
253
348
|
name: n.n,
|
|
@@ -258,102 +353,102 @@ class xt extends st {
|
|
|
258
353
|
draught: n.dr,
|
|
259
354
|
type: n.t
|
|
260
355
|
};
|
|
261
|
-
return i = "https://www.hifleet.com/hifleetapi/sameShipSearch.do", n = await
|
|
356
|
+
return i = "https://www.hifleet.com/hifleetapi/sameShipSearch.do", n = await L.post(i, o).json(), M == null || M.info("[%s] search vessel dead weight from: %s - %j", a.requestId, i, o), n instanceof Array && (n = n[0]), n && (s.deadweight = Number(n.dwt)), s;
|
|
262
357
|
}
|
|
263
|
-
async suggest(
|
|
358
|
+
async suggest(t, a = {}) {
|
|
264
359
|
const i = "https://www.hifleet.com/hifleetapi/getShipSuggest.do", o = {
|
|
265
360
|
searchParams: {
|
|
266
|
-
q:
|
|
361
|
+
q: t
|
|
267
362
|
},
|
|
268
363
|
headers: {
|
|
269
364
|
Referer: "https://www.hifleet.com",
|
|
270
365
|
Origin: "https://www.hifleet.com",
|
|
271
366
|
Host: "www.hifleet.com"
|
|
272
367
|
}
|
|
273
|
-
}, n = await
|
|
274
|
-
|
|
368
|
+
}, n = await L.post(i, o).json();
|
|
369
|
+
M == null || M.info("[%s] suggest vessel props from: %s - %j", a.requestId, i, o);
|
|
275
370
|
const s = [];
|
|
276
|
-
for (const
|
|
371
|
+
for (const r of n)
|
|
277
372
|
s.push({
|
|
278
|
-
mmsi: !
|
|
279
|
-
name:
|
|
280
|
-
callSign:
|
|
281
|
-
imo: !
|
|
282
|
-
score:
|
|
373
|
+
mmsi: !r.mmsi || isNaN(r.mmsi) ? null : Number(r.mmsi),
|
|
374
|
+
name: r.name,
|
|
375
|
+
callSign: r.callsign,
|
|
376
|
+
imo: !r.imo || isNaN(r.imo) ? null : Number(r.imo),
|
|
377
|
+
score: r._score
|
|
283
378
|
});
|
|
284
|
-
return s.sort((
|
|
379
|
+
return s.sort((r, c) => c.score - r.score), s;
|
|
285
380
|
}
|
|
286
|
-
async trajectory(
|
|
287
|
-
var
|
|
288
|
-
const
|
|
289
|
-
let
|
|
290
|
-
const
|
|
381
|
+
async trajectory(t, a, i, o, n = !0, s = {}) {
|
|
382
|
+
var d, g, l;
|
|
383
|
+
const r = await this.realTimePosition(t, s);
|
|
384
|
+
let c = w(a);
|
|
385
|
+
const u = w(i), m = w();
|
|
291
386
|
if (n) {
|
|
292
|
-
let
|
|
293
|
-
|
|
387
|
+
let h = u.diff(c, "d", !0);
|
|
388
|
+
h < 0 ? c = u.clone().subtract(40, "d") : h < 30 ? c.subtract(10, "d") : h < 60 ? c.subtract(5, "d") : c = u.clone().subtract(80, "d"), h = m.diff(u, "d", !0), u.add(h > 10 ? 240 : h * 24, "h");
|
|
294
389
|
}
|
|
295
|
-
const
|
|
390
|
+
const f = {
|
|
296
391
|
searchParams: {
|
|
297
|
-
endtime:
|
|
298
|
-
starttime:
|
|
299
|
-
mmsi:
|
|
392
|
+
endtime: u.utcOffset("+8:00").format("YYYY-MM-DD HH:mm:ss"),
|
|
393
|
+
starttime: c.utcOffset("+8:00").format("YYYY-MM-DD HH:mm:ss"),
|
|
394
|
+
mmsi: t,
|
|
300
395
|
usertoken: this.token
|
|
301
396
|
}
|
|
302
|
-
}, b = "https://api.hifleet.com/position/trajectory/nocompressed/withstatic/token",
|
|
303
|
-
|
|
304
|
-
let
|
|
305
|
-
|
|
306
|
-
const
|
|
397
|
+
}, b = "https://api.hifleet.com/position/trajectory/nocompressed/withstatic/token", y = await L.get(b, f).json();
|
|
398
|
+
M == null || M.info("[%s] fetch trajectory from: %s - %j", s.requestId, b, f);
|
|
399
|
+
let F;
|
|
400
|
+
y && (F = ((g = (d = y.ships) == null ? void 0 : d.offors) == null ? void 0 : g.ship) || [], F.length || M == null || M.warn("[%s] fetch trajectory failed: %j", s.requestId, y));
|
|
401
|
+
const I = [];
|
|
307
402
|
let p = -1;
|
|
308
|
-
const
|
|
309
|
-
for (const
|
|
310
|
-
for (const A in
|
|
311
|
-
!isNaN(
|
|
312
|
-
const
|
|
313
|
-
|
|
314
|
-
const { labelEn:
|
|
315
|
-
mmsi:
|
|
316
|
-
name:
|
|
317
|
-
imo:
|
|
318
|
-
lat:
|
|
319
|
-
lng:
|
|
320
|
-
draught:
|
|
321
|
-
sog:
|
|
322
|
-
cog:
|
|
323
|
-
hdg:
|
|
324
|
-
positionTime:
|
|
325
|
-
utc:
|
|
326
|
-
status:
|
|
403
|
+
const v = w(`${(l = F == null ? void 0 : F[0]) == null ? void 0 : l.ti} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
404
|
+
for (const h of F) {
|
|
405
|
+
for (const A in h)
|
|
406
|
+
!isNaN(h[A]) && Number(h[A]) !== 1 / 0 && (h[A] = Number(h[A]));
|
|
407
|
+
const k = w(`${h.ti} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
408
|
+
h.status = h.sp > 4 ? 0 : 1;
|
|
409
|
+
const { labelEn: S, labelCn: D } = this.parseStatus(h.status), P = {
|
|
410
|
+
mmsi: h.m,
|
|
411
|
+
name: h.n,
|
|
412
|
+
imo: r == null ? void 0 : r.imo,
|
|
413
|
+
lat: h.la,
|
|
414
|
+
lng: h.lo,
|
|
415
|
+
draught: h.draught,
|
|
416
|
+
sog: h.sp,
|
|
417
|
+
cog: h.co,
|
|
418
|
+
hdg: h.hdg,
|
|
419
|
+
positionTime: k.unix(),
|
|
420
|
+
utc: k.utc().format(),
|
|
421
|
+
status: h.status,
|
|
327
422
|
labelCn: D,
|
|
328
|
-
labelEn:
|
|
423
|
+
labelEn: S,
|
|
329
424
|
method: "trajectory",
|
|
330
425
|
vendor: "hifleet"
|
|
331
|
-
},
|
|
332
|
-
|
|
426
|
+
}, N = Math.floor(k.diff(v, "minute", !0) / (o || 1));
|
|
427
|
+
N !== p && (p = N, I.push(P));
|
|
333
428
|
}
|
|
334
|
-
return
|
|
429
|
+
return I;
|
|
335
430
|
}
|
|
336
431
|
}
|
|
337
|
-
class
|
|
338
|
-
constructor(
|
|
432
|
+
class Nt extends st {
|
|
433
|
+
constructor(t) {
|
|
339
434
|
super();
|
|
340
|
-
|
|
341
|
-
this.token =
|
|
435
|
+
U(this, "token");
|
|
436
|
+
this.token = t;
|
|
342
437
|
}
|
|
343
|
-
async realTimePosition(
|
|
438
|
+
async realTimePosition(t, a = {}) {
|
|
344
439
|
const i = {
|
|
345
440
|
searchParams: {
|
|
346
|
-
id:
|
|
441
|
+
id: t,
|
|
347
442
|
k: this.token,
|
|
348
443
|
enc: 1
|
|
349
444
|
}
|
|
350
|
-
}, o = "https://api.shipxy.com/apicall/GetSingleShip", n = await
|
|
351
|
-
if (
|
|
445
|
+
}, o = "https://api.shipxy.com/apicall/GetSingleShip", n = await L.get(o, i).json();
|
|
446
|
+
if (M == null || M.info("[%s] fetch realtime position from: %s - %j", a.requestId, o, i), (n == null ? void 0 : n.status) !== 0)
|
|
352
447
|
return n;
|
|
353
448
|
const s = n.data[0];
|
|
354
|
-
for (const
|
|
355
|
-
!isNaN(s[
|
|
356
|
-
const { labelCn:
|
|
449
|
+
for (const f in s)
|
|
450
|
+
!isNaN(s[f]) && Number(s[f]) !== 1 / 0 && (s[f] = Number(s[f]));
|
|
451
|
+
const { labelCn: r, labelEn: c } = await this.parseStatus(s.navistat), u = w.unix(s.lasttime);
|
|
357
452
|
return {
|
|
358
453
|
mmsi: s.ShipID,
|
|
359
454
|
name: s.name,
|
|
@@ -369,147 +464,147 @@ class jt extends st {
|
|
|
369
464
|
hdg: Math.round(s.hdg / 100 * 100) / 100,
|
|
370
465
|
rot: Math.round(s.rot / 100 * 100) / 100,
|
|
371
466
|
positionTime: s.lasttime,
|
|
372
|
-
utc:
|
|
467
|
+
utc: u.utc().format(),
|
|
373
468
|
status: s.navistat,
|
|
374
|
-
labelEn:
|
|
375
|
-
labelCn:
|
|
469
|
+
labelEn: c,
|
|
470
|
+
labelCn: r,
|
|
376
471
|
method: "position",
|
|
377
472
|
vendor: "shipxy"
|
|
378
473
|
};
|
|
379
474
|
}
|
|
380
|
-
async trajectory(
|
|
381
|
-
var
|
|
382
|
-
const
|
|
475
|
+
async trajectory(t, a, i, o, n = !0, s = {}) {
|
|
476
|
+
var v;
|
|
477
|
+
const r = await this.realTimePosition(t, s), c = w(a), u = w(i), m = "https://api.shipxy.com/apicall/GetShipTrack", f = {
|
|
383
478
|
searchParams: {
|
|
384
|
-
id:
|
|
479
|
+
id: t,
|
|
385
480
|
k: this.token,
|
|
386
481
|
enc: 1,
|
|
387
482
|
cut: 0,
|
|
388
|
-
btm:
|
|
389
|
-
etm:
|
|
483
|
+
btm: c.unix(),
|
|
484
|
+
etm: u.unix()
|
|
390
485
|
}
|
|
391
|
-
}, b = await
|
|
392
|
-
if (
|
|
486
|
+
}, b = await L.get(m, f).json();
|
|
487
|
+
if (M == null || M.info("[%s] fetch trajectory from: %s - %j", s.requestId, m, f), (b == null ? void 0 : b.status) !== 0)
|
|
393
488
|
return b;
|
|
394
|
-
const
|
|
489
|
+
const y = b == null ? void 0 : b.points, F = [], I = w.unix((v = y[0]) == null ? void 0 : v.utc);
|
|
395
490
|
let p = -1;
|
|
396
|
-
for (const
|
|
397
|
-
const
|
|
398
|
-
imo:
|
|
399
|
-
mmsi:
|
|
400
|
-
sog: Math.round(
|
|
401
|
-
cog: Math.round(
|
|
402
|
-
lat: Math.round(
|
|
403
|
-
lng: Math.round(
|
|
404
|
-
positionTime:
|
|
405
|
-
utc:
|
|
491
|
+
for (const d of y) {
|
|
492
|
+
const g = w.unix(d.utc), l = {
|
|
493
|
+
imo: r == null ? void 0 : r.imo,
|
|
494
|
+
mmsi: t,
|
|
495
|
+
sog: Math.round(d.sog * 3600 / 1e3 / 1852 * 100) / 100,
|
|
496
|
+
cog: Math.round(d.cog / 100 * 100) / 100,
|
|
497
|
+
lat: Math.round(d.lat / 1e6 * 1e5) / 1e5,
|
|
498
|
+
lng: Math.round(d.lon / 1e6 * 1e5) / 1e5,
|
|
499
|
+
positionTime: g.unix(),
|
|
500
|
+
utc: g.utc().format(),
|
|
406
501
|
method: "trajectory",
|
|
407
502
|
vendor: "shipxy"
|
|
408
|
-
},
|
|
409
|
-
|
|
503
|
+
}, h = Math.floor(g.diff(I, "minute", !0) / (o || 1));
|
|
504
|
+
h !== p && (p = h, F.push(l));
|
|
410
505
|
}
|
|
411
|
-
return
|
|
506
|
+
return F;
|
|
412
507
|
}
|
|
413
508
|
}
|
|
414
|
-
class
|
|
415
|
-
constructor(
|
|
509
|
+
class Tt extends st {
|
|
510
|
+
constructor(t) {
|
|
416
511
|
super();
|
|
417
|
-
|
|
418
|
-
this.token =
|
|
512
|
+
U(this, "token");
|
|
513
|
+
this.token = t;
|
|
419
514
|
}
|
|
420
|
-
async getShipId(
|
|
515
|
+
async getShipId(t, a = {}) {
|
|
421
516
|
const i = {
|
|
422
517
|
headers: {
|
|
423
518
|
appKey: this.token
|
|
424
519
|
},
|
|
425
520
|
json: {
|
|
426
|
-
mmsiList:
|
|
521
|
+
mmsiList: t
|
|
427
522
|
}
|
|
428
|
-
}, o = "https://api3.myships.com/sp/ships/getShipIdByMMSI", n = await
|
|
429
|
-
return
|
|
523
|
+
}, o = "https://api3.myships.com/sp/ships/getShipIdByMMSI", n = await L.post(o, i).json();
|
|
524
|
+
return M == null || M.info("[%s] fetch ship id from: %s - %j", a.requestId, o, i), n.code !== "0" ? n : n.data[0].shipId;
|
|
430
525
|
}
|
|
431
|
-
async getShipInfo(
|
|
526
|
+
async getShipInfo(t, a = {}) {
|
|
432
527
|
const i = {
|
|
433
528
|
headers: {
|
|
434
529
|
appKey: this.token
|
|
435
530
|
},
|
|
436
531
|
json: {
|
|
437
|
-
shipId:
|
|
532
|
+
shipId: t
|
|
438
533
|
}
|
|
439
|
-
}, o = "https://api3.myships.com/sp/ships/aissta", n = await
|
|
440
|
-
if (
|
|
534
|
+
}, o = "https://api3.myships.com/sp/ships/aissta", n = await L.post(o, i).json();
|
|
535
|
+
if (M == null || M.info("[%s] fetch ship info from: %s - %j", a.requestId, o, i), n.code !== "0")
|
|
441
536
|
return n;
|
|
442
537
|
const s = n.data;
|
|
443
|
-
let
|
|
444
|
-
return
|
|
538
|
+
let r = s.imo;
|
|
539
|
+
return t === "407170" && (r = "9198379", M == null || M.warn("[%s] ship(%s) imo error: %s, should be %s", a.requestId, t, s.imo, r)), {
|
|
445
540
|
mmsi: s.mmsi,
|
|
446
541
|
name: s.shipnameEn,
|
|
447
|
-
imo:
|
|
542
|
+
imo: r,
|
|
448
543
|
callSign: s.callSign,
|
|
449
544
|
length: s.length,
|
|
450
545
|
width: s.breadth,
|
|
451
546
|
draught: (s.draught || 100) / 10
|
|
452
547
|
};
|
|
453
548
|
}
|
|
454
|
-
async realTimePosition(
|
|
455
|
-
const i = await this.getShipId(
|
|
549
|
+
async realTimePosition(t, a = {}) {
|
|
550
|
+
const i = await this.getShipId(t, a), o = await this.getShipInfo(i, a), n = {
|
|
456
551
|
headers: {
|
|
457
552
|
appKey: this.token
|
|
458
553
|
},
|
|
459
554
|
json: {
|
|
460
555
|
shipId: i
|
|
461
556
|
}
|
|
462
|
-
}, s = "https://api3.myships.com/sp/ships/position/latest",
|
|
463
|
-
|
|
464
|
-
const
|
|
465
|
-
for (const
|
|
466
|
-
!isNaN(
|
|
467
|
-
const { labelCn:
|
|
557
|
+
}, s = "https://api3.myships.com/sp/ships/position/latest", r = await L.post(s, n).json();
|
|
558
|
+
M == null || M.info("[%s] fetch realtime position from: %s - %j", a.requestId, s, n);
|
|
559
|
+
const c = r.data[0];
|
|
560
|
+
for (const y in c)
|
|
561
|
+
!isNaN(c[y]) && Number(c[y]) !== 1 / 0 && (c[y] = Number(c[y]));
|
|
562
|
+
const { labelCn: u, labelEn: m } = await this.parseStatus(c.aisNavStatus), f = w.unix(c.posTime);
|
|
468
563
|
return {
|
|
469
564
|
...o,
|
|
470
|
-
mmsi:
|
|
471
|
-
lat: Math.round(
|
|
472
|
-
lng: Math.round(
|
|
473
|
-
sog: Math.round(
|
|
474
|
-
cog: Math.round(
|
|
475
|
-
hdg: Math.round(
|
|
476
|
-
rot: Math.round(
|
|
477
|
-
positionTime:
|
|
478
|
-
utc:
|
|
479
|
-
status:
|
|
480
|
-
labelEn:
|
|
481
|
-
labelCn:
|
|
565
|
+
mmsi: t,
|
|
566
|
+
lat: Math.round(c.lat / 1e4 / 60 * 1e5) / 1e5,
|
|
567
|
+
lng: Math.round(c.lon / 1e4 / 60 * 1e5) / 1e5,
|
|
568
|
+
sog: Math.round(c.sog / 10 * 100) / 100,
|
|
569
|
+
cog: Math.round(c.cog / 10 * 100) / 100,
|
|
570
|
+
hdg: Math.round(c.heading * 100) / 100,
|
|
571
|
+
rot: Math.round(c.rot * 100) / 100,
|
|
572
|
+
positionTime: c.posTime,
|
|
573
|
+
utc: f.utc().format(),
|
|
574
|
+
status: c.aisNavStatus,
|
|
575
|
+
labelEn: m,
|
|
576
|
+
labelCn: u,
|
|
482
577
|
method: "position",
|
|
483
578
|
vendor: "myship"
|
|
484
579
|
};
|
|
485
580
|
}
|
|
486
|
-
async trajectory(
|
|
487
|
-
const
|
|
488
|
-
for (;
|
|
489
|
-
await this.trajectoryIn30Day(
|
|
490
|
-
return await this.trajectoryIn30Day(
|
|
581
|
+
async trajectory(t, a, i, o, n = !0, s = {}) {
|
|
582
|
+
const r = w(a), c = w(i), u = await this.getShipId(t), m = await this.getShipInfo(u), f = [];
|
|
583
|
+
for (; c.diff(r, "day", !0) > 30; )
|
|
584
|
+
await this.trajectoryIn30Day(u, r.unix(), r.add(30, "day").unix(), m, t, o, f);
|
|
585
|
+
return await this.trajectoryIn30Day(u, r.unix(), c.unix(), m, t, o, f), f;
|
|
491
586
|
}
|
|
492
|
-
async trajectoryIn30Day(
|
|
493
|
-
var
|
|
494
|
-
const
|
|
587
|
+
async trajectoryIn30Day(t, a, i, o, n, s, r, c = {}) {
|
|
588
|
+
var I;
|
|
589
|
+
const u = {
|
|
495
590
|
headers: {
|
|
496
591
|
appKey: this.token
|
|
497
592
|
},
|
|
498
593
|
json: {
|
|
499
|
-
shipId:
|
|
594
|
+
shipId: t,
|
|
500
595
|
startTime: a,
|
|
501
596
|
endTime: i
|
|
502
597
|
}
|
|
503
|
-
},
|
|
504
|
-
if (
|
|
505
|
-
return
|
|
506
|
-
const b =
|
|
598
|
+
}, m = "https://api3.myships.com/sp/ships/position/history", f = await L.post(m, u).json();
|
|
599
|
+
if (M == null || M.info("[%s] fetch trajectory from: %s - %j", c.requestId, m, u), f.code !== "0")
|
|
600
|
+
return M == null || M.warn("[%s] invoke myship trajectory failed: %j", c.requestId, f), f;
|
|
601
|
+
const b = f.data;
|
|
507
602
|
for (const p in b)
|
|
508
603
|
!isNaN(b[p]) && Number(b[p]) !== 1 / 0 && (b[p] = Number(b[p]));
|
|
509
|
-
const
|
|
510
|
-
let
|
|
604
|
+
const y = w.unix((I = b[0]) == null ? void 0 : I.posTime);
|
|
605
|
+
let F = -1;
|
|
511
606
|
for (const p of b) {
|
|
512
|
-
const
|
|
607
|
+
const v = w.unix(p.posTime), d = {
|
|
513
608
|
imo: o == null ? void 0 : o.imo,
|
|
514
609
|
mmsi: n,
|
|
515
610
|
lat: Math.round(p.lat / 1e4 / 60 * 1e5) / 1e5,
|
|
@@ -518,23 +613,23 @@ class Nt extends st {
|
|
|
518
613
|
cog: Math.round(p.cog / 10 * 100) / 100,
|
|
519
614
|
hdg: Math.round(p.heading * 100) / 100,
|
|
520
615
|
rot: Math.round(p.rot * 100) / 100,
|
|
521
|
-
positionTime:
|
|
522
|
-
utc:
|
|
616
|
+
positionTime: v.unix(),
|
|
617
|
+
utc: v.utc().format(),
|
|
523
618
|
method: "trajectory",
|
|
524
619
|
vendor: "myship"
|
|
525
|
-
},
|
|
526
|
-
|
|
620
|
+
}, g = Math.floor(v.diff(y, "minute", !0) / (s || 1));
|
|
621
|
+
g !== F && (F = g, r.push(d));
|
|
527
622
|
}
|
|
528
|
-
return
|
|
623
|
+
return r;
|
|
529
624
|
}
|
|
530
625
|
}
|
|
531
|
-
let
|
|
626
|
+
let z;
|
|
532
627
|
try {
|
|
533
|
-
|
|
628
|
+
z = ct.getLogger("vessel");
|
|
534
629
|
} catch {
|
|
535
630
|
} finally {
|
|
536
631
|
}
|
|
537
|
-
var
|
|
632
|
+
var ft = /* @__PURE__ */ ((E) => (E.NOTICE = "NOTICE", E.WARN = "WARN", E.HEAVY = "HEAVY", E.SEVERE = "SEVERE", E.ERROR = "ERROR", E.FATAL = "FATAL", E))(ft || {});
|
|
538
633
|
class yt {
|
|
539
634
|
/**
|
|
540
635
|
* 解析告警规则, 多规则场景
|
|
@@ -544,21 +639,21 @@ class yt {
|
|
|
544
639
|
*
|
|
545
640
|
* @param options
|
|
546
641
|
*/
|
|
547
|
-
parsePrinciple(
|
|
548
|
-
var s,
|
|
549
|
-
|
|
550
|
-
const a = new RegExp("(?<=\\[)(.+)(?=])", "g"), i =
|
|
642
|
+
parsePrinciple(e, t = {}) {
|
|
643
|
+
var s, r, c;
|
|
644
|
+
z == null || z.debug("[%s] parse rule: %s", t.requestId, e);
|
|
645
|
+
const a = new RegExp("(?<=\\[)(.+)(?=])", "g"), i = e.match(a) ? (s = e.match(a)) == null ? void 0 : s[0] : void 0, o = i == null ? void 0 : i.split(";");
|
|
551
646
|
if (!o)
|
|
552
647
|
return;
|
|
553
648
|
const n = {};
|
|
554
|
-
for (let
|
|
555
|
-
const
|
|
556
|
-
if (
|
|
649
|
+
for (let u = 0; u < (o == null ? void 0 : o.length); u++) {
|
|
650
|
+
const m = (c = (r = o[u].match(a)) == null ? void 0 : r[0]) == null ? void 0 : c.split("],");
|
|
651
|
+
if (u === 0 && !m)
|
|
557
652
|
n.scope = o[0];
|
|
558
|
-
else if (
|
|
559
|
-
for (let
|
|
560
|
-
const
|
|
561
|
-
|
|
653
|
+
else if (m)
|
|
654
|
+
for (let f = 0, b = m.length; f < b; f++) {
|
|
655
|
+
const y = this.parseRule(m[f]);
|
|
656
|
+
y && (n[y.level] ? y.key ? n[y.level][y == null ? void 0 : y.key] = y : n[y.level] = y : y.key ? n[y.level] = { [y == null ? void 0 : y.key]: y } : n[y.level] = y);
|
|
562
657
|
}
|
|
563
658
|
}
|
|
564
659
|
return n;
|
|
@@ -569,10 +664,10 @@ class yt {
|
|
|
569
664
|
* @param rule
|
|
570
665
|
* @param options
|
|
571
666
|
*/
|
|
572
|
-
parseRule(
|
|
667
|
+
parseRule(e, t = {}) {
|
|
573
668
|
var n;
|
|
574
|
-
|
|
575
|
-
const a = new RegExp("(?<=\\[)(.+?)(?=])", "g"), i = (n =
|
|
669
|
+
z == null || z.debug("[%s] parse rule: %s", t.requestId, e), e = e.startsWith("[") ? e : `[${e}`, e = e.endsWith("]") ? e : `${e}]`;
|
|
670
|
+
const a = new RegExp("(?<=\\[)(.+?)(?=])", "g"), i = (n = e == null ? void 0 : e.match(a)) == null ? void 0 : n[0], o = i == null ? void 0 : i.split(",");
|
|
576
671
|
if (o) {
|
|
577
672
|
let s = o[3] === "Number.MAX_VALUE" ? 100 : Number(o[3]);
|
|
578
673
|
return s = isNaN(s) ? 1 : s, {
|
|
@@ -590,26 +685,26 @@ class yt {
|
|
|
590
685
|
* @param principle 告警规则
|
|
591
686
|
* @param options
|
|
592
687
|
*/
|
|
593
|
-
checkWeather(
|
|
594
|
-
var
|
|
688
|
+
checkWeather(e, t, a = {}) {
|
|
689
|
+
var y, F, I, p, v, d, g, l, h, k, S, D, P, N, A;
|
|
595
690
|
let i = 0, o = 0, n = 0, s = 0;
|
|
596
|
-
const
|
|
597
|
-
for (let
|
|
598
|
-
const
|
|
599
|
-
s =
|
|
691
|
+
const r = Math.round(((F = (y = t == null ? void 0 : t.SEVERE) == null ? void 0 : y.sigWave) == null ? void 0 : F.number) * 1.6 * 100) / 100, c = (p = (I = t == null ? void 0 : t.SEVERE) == null ? void 0 : I.sigWave) == null ? void 0 : p.number, u = (d = (v = t == null ? void 0 : t.HEAVY) == null ? void 0 : v.sigWave) == null ? void 0 : d.number, m = Math.round((((l = (g = t == null ? void 0 : t.SEVERE) == null ? void 0 : g.wind) == null ? void 0 : l.number) + 2) * 100) / 100, f = (k = (h = t == null ? void 0 : t.SEVERE) == null ? void 0 : h.wind) == null ? void 0 : k.number, b = (D = (S = t == null ? void 0 : t.HEAVY) == null ? void 0 : S.wind) == null ? void 0 : D.number;
|
|
692
|
+
for (let x = 0; x < (e == null ? void 0 : e.length); x++) {
|
|
693
|
+
const T = e[x], q = (N = (P = T == null ? void 0 : T.meteo) == null ? void 0 : P.wave) == null ? void 0 : N.sig, R = (A = T == null ? void 0 : T.meteo) == null ? void 0 : A.wind, J = x ? w(T.eta).diff(w(e[x - 1].eta), "hour", !0) : 0;
|
|
694
|
+
s = J > s ? J : s, z == null || z.debug("[%s] check sig.wave: %j", a.requestId, { ...q, dgThd4Wv: r, svThd4Wv: c, hvThd4Wv: u }), (q == null ? void 0 : q.height) >= r ? T.isDangerous = !0 : (q == null ? void 0 : q.height) >= c ? T.isSevere = !0 : (q == null ? void 0 : q.height) >= u && (T.isHeavy = !0), z == null || z.debug("[%s] check wind: %j", a.requestId, { ...R, dgThd4Wd: m, svThd4Wd: f, hvThd4Wd: b }), (R == null ? void 0 : R.scale) >= m ? (T.isDangerous = !0, delete T.isSevere, delete T.isHeavy) : (R == null ? void 0 : R.scale) > f ? (T.isDangerous || (T.isSevere = !0), delete T.isHeavy) : (R == null ? void 0 : R.scale) === b && !T.isDangerous && !T.isSevere && (T.isHeavy = !0), i += T.isDangerous ? J : 0, o += T.isSevere ? J : 0, n += T.isHeavy ? J : 0;
|
|
600
695
|
}
|
|
601
|
-
return i = Math.round(i * 100) / 100, o = Math.round(o * 100) / 100, n = Math.round(n * 100) / 100, s = Math.round(s), { sample:
|
|
696
|
+
return i = Math.round(i * 100) / 100, o = Math.round(o * 100) / 100, n = Math.round(n * 100) / 100, s = Math.round(s), { sample: e, dangerous: i, severe: o, heavy: n, step: s < 3 ? 3 : s, wind: { dgThd4Wd: m, svThd4Wd: f, hvThd4Wd: b }, sig: { dgThd4Wv: r, svThd4Wv: c, hvThd4Wv: u } };
|
|
602
697
|
}
|
|
603
698
|
}
|
|
604
|
-
const
|
|
605
|
-
let
|
|
699
|
+
const xt = new yt();
|
|
700
|
+
let C;
|
|
606
701
|
try {
|
|
607
|
-
|
|
702
|
+
C = ct.getLogger("vessel");
|
|
608
703
|
} catch {
|
|
609
704
|
} finally {
|
|
610
705
|
}
|
|
611
|
-
const Mt = new
|
|
612
|
-
var
|
|
706
|
+
const Mt = new mt("", !0);
|
|
707
|
+
var gt = /* @__PURE__ */ ((E) => (E.common = "common", E.container = "container", E.tugs = "tugs", E))(gt || {}), bt = /* @__PURE__ */ ((E) => (E.Ballast = "Ballast", E.Laden = "Laden", E))(bt || {}), vt = /* @__PURE__ */ ((E) => (E.Cp = "CP", E.Perf = "Basis", E.Instruct = "Other", E))(vt || {});
|
|
613
708
|
class O {
|
|
614
709
|
/**
|
|
615
710
|
* @see https://baike.baidu.com/item/%E6%96%B9%E5%BD%A2%E7%B3%BB%E6%95%B0/4965568?fr=aladdin
|
|
@@ -623,10 +718,10 @@ class O {
|
|
|
623
718
|
* @param draught 吃水 m
|
|
624
719
|
* @return [0.55, 0.85]
|
|
625
720
|
*/
|
|
626
|
-
static blockCoefficient(
|
|
627
|
-
let o = Math.round(
|
|
721
|
+
static blockCoefficient(e, t, a, i) {
|
|
722
|
+
let o = Math.round(e / (t * a * i) * 100) / 100;
|
|
628
723
|
o = o < 0.55 ? 0.55 : o > 0.85 ? 0.85 : o;
|
|
629
|
-
const n = [0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85], s = n.map((
|
|
724
|
+
const n = [0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85], s = n.map((r) => Math.abs(r - o));
|
|
630
725
|
return n[s.indexOf(Math.min(...s))];
|
|
631
726
|
}
|
|
632
727
|
/**
|
|
@@ -640,8 +735,8 @@ class O {
|
|
|
640
735
|
* @param g 重力加速度 9.80 m/s^2
|
|
641
736
|
* @return [0.05, 0.30]
|
|
642
737
|
*/
|
|
643
|
-
static froudeNumber(
|
|
644
|
-
let i = Math.round(Math.sqrt(
|
|
738
|
+
static froudeNumber(e, t, a = 9.8) {
|
|
739
|
+
let i = Math.round(Math.sqrt(e * e / (a * t)) * 100) / 100;
|
|
645
740
|
return i = i < 0.05 ? 0.05 : i > 0.3 ? 0.3 : i, i;
|
|
646
741
|
}
|
|
647
742
|
/**
|
|
@@ -651,7 +746,7 @@ class O {
|
|
|
651
746
|
* @param loadCondition
|
|
652
747
|
* @private
|
|
653
748
|
*/
|
|
654
|
-
static amendFactor(
|
|
749
|
+
static amendFactor(e, t, a) {
|
|
655
750
|
const i = {
|
|
656
751
|
0.55: [1.7, -1.4, -7.4],
|
|
657
752
|
0.6: [2.2, -2.5, -9.7],
|
|
@@ -669,8 +764,8 @@ class O {
|
|
|
669
764
|
0.75: [2.6, -12.5, -13.5],
|
|
670
765
|
0.8: [3, -16.3, -21.6],
|
|
671
766
|
0.85: [3.4, -20.9, 31.8]
|
|
672
|
-
}[
|
|
673
|
-
return a === "Laden" && (n = i[
|
|
767
|
+
}[e];
|
|
768
|
+
return a === "Laden" && (n = i[e]), n[0] + n[1] * t + n[2] * Math.pow(t, 2);
|
|
674
769
|
}
|
|
675
770
|
/**
|
|
676
771
|
* 失速方向因子
|
|
@@ -683,9 +778,9 @@ class O {
|
|
|
683
778
|
* @param bn
|
|
684
779
|
* @private
|
|
685
780
|
*/
|
|
686
|
-
static directionFactor(
|
|
781
|
+
static directionFactor(e, t = 0) {
|
|
687
782
|
let a;
|
|
688
|
-
return
|
|
783
|
+
return e > 30 && e <= 60 ? a = (1.7 - 0.03 * Math.pow(t - 4, 2)) / 2 : e > 60 && e <= 150 ? a = (0.9 - 0.06 * Math.pow(t - 6, 2)) / 2 : e > 150 && e <= 180 ? a = (0.4 - 0.03 * Math.pow(t - 8, 2)) / 2 : a = 1, Math.round(a * 1e5) / 1e5;
|
|
689
784
|
}
|
|
690
785
|
/**
|
|
691
786
|
* 失速船型因子
|
|
@@ -698,20 +793,20 @@ class O {
|
|
|
698
793
|
* @param bn
|
|
699
794
|
* @private
|
|
700
795
|
*/
|
|
701
|
-
static vesselTagFactor(
|
|
796
|
+
static vesselTagFactor(e, t, a, i = 0) {
|
|
702
797
|
i = i > 6 ? i - 0.9 * (i - 6) : i;
|
|
703
798
|
let o;
|
|
704
|
-
return a === "container" ? o = 0.7 * i + Math.pow(i, 6.5) / (22 * Math.pow(
|
|
799
|
+
return a === "container" ? o = 0.7 * i + Math.pow(i, 6.5) / (22 * Math.pow(e, 2 / 3)) : t === "Ballast" ? o = 0.7 * i + Math.pow(i, 6.5) / (2.7 * Math.pow(e, 2 / 3)) : o = 0.5 * i + Math.pow(i, 6.5) / (2.7 * Math.pow(e, 2 / 3)), o;
|
|
705
800
|
}
|
|
706
801
|
/**
|
|
707
802
|
* 浪高影响因子
|
|
708
803
|
* @param ht 浪高,单位m
|
|
709
804
|
* @private
|
|
710
805
|
*/
|
|
711
|
-
static waveHeightFactor(
|
|
712
|
-
|
|
806
|
+
static waveHeightFactor(e, t) {
|
|
807
|
+
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;
|
|
713
808
|
let a;
|
|
714
|
-
return
|
|
809
|
+
return t > 30 && t <= 60 ? a = -0.6 : t > 60 && t <= 90 ? a = -0.4 : t > 90 && t <= 120 ? a = e < 3 ? 0.4 : -0.3 : t > 120 && t <= 150 ? a = e < 3 ? 0.6 : -0.5 : t > 150 && t <= 180 ? a = e < 3 ? 0.7 : -0.6 : a = -0.7, Math.round(a * (0.144 * Math.pow(e, 2) + 0.278 * e) * 1e4) / 1e4;
|
|
715
810
|
}
|
|
716
811
|
/**
|
|
717
812
|
* 组装船舶运行参数
|
|
@@ -721,18 +816,18 @@ class O {
|
|
|
721
816
|
* @param bearing 方位角
|
|
722
817
|
* @private
|
|
723
818
|
*/
|
|
724
|
-
static assembleProperties(
|
|
725
|
-
var
|
|
726
|
-
const o =
|
|
819
|
+
static assembleProperties(e, t, a, i) {
|
|
820
|
+
var f;
|
|
821
|
+
const o = 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, c = ((f = e == null ? void 0 : e.type) == null ? void 0 : f.toLowerCase()) || "common";
|
|
727
822
|
return {
|
|
728
|
-
tag:
|
|
823
|
+
tag: c.indexOf("container") > -1 ? "container" : c.indexOf("tugs") > -1 ? "tugs" : "common",
|
|
729
824
|
lbp: o,
|
|
730
|
-
loadCondition:
|
|
825
|
+
loadCondition: t,
|
|
731
826
|
draught: n,
|
|
732
827
|
breadthMoulded: s,
|
|
733
828
|
// 排水量(吨)= 载重量(吨)/ 1.025 + 吃水(米)× 船舶型宽(米)× 船舶型长(米)× 0.7
|
|
734
829
|
// 其中,1.025是指海水的密度,吨是指公吨,吃水是指船舶的最大吃水深度。船舶型宽是指船舶的最大型宽,船舶型长是指船舶的设计型长。上述公式是针对常规船舶适用的,不同类型的船舶可能会有一些差异。
|
|
735
|
-
displacement: Math.round((
|
|
830
|
+
displacement: Math.round((r / 1.025 + n * s * o * 0.7) * 1e4) / 1e4,
|
|
736
831
|
// 换算为m/s
|
|
737
832
|
speed: Math.round((a ?? 14.1382) * 1852 / 3600 * 1e4) / 1e4,
|
|
738
833
|
bearing: i || 90
|
|
@@ -749,41 +844,41 @@ class O {
|
|
|
749
844
|
* @param useRouteParam true 启用设置速度
|
|
750
845
|
* @param options
|
|
751
846
|
*/
|
|
752
|
-
static async speedLoseAt(
|
|
753
|
-
let
|
|
754
|
-
if (
|
|
755
|
-
let
|
|
847
|
+
static async speedLoseAt(e, t, a, i = "", o = 2, n = !0, s = !1, r = {}) {
|
|
848
|
+
let c;
|
|
849
|
+
if (t.velocity && s && (e.speed = _.roundPrecision(t.velocity * 1852 / 3600, 6)), n) {
|
|
850
|
+
let u;
|
|
756
851
|
try {
|
|
757
852
|
i = (i == null ? void 0 : i.toUpperCase()) === "CMEMS" ? "ECMWF" : i, i = (i == null ? void 0 : i.toUpperCase()) === "METEO2" ? "best_match" : i;
|
|
758
|
-
const { weatherModels:
|
|
759
|
-
...
|
|
853
|
+
const { weatherModels: y, marineModels: F } = await it.autoPickMeteoModel(i), I = await Mt.spotForecast(t.lat, t.lng, a.utc().format(), !1, !1, !0, {
|
|
854
|
+
...r,
|
|
760
855
|
pastDays: 1,
|
|
761
856
|
forecastDays: 1,
|
|
762
|
-
weatherModels:
|
|
763
|
-
marineModels:
|
|
764
|
-
}), [p] = it.pickHourly(
|
|
765
|
-
|
|
766
|
-
} catch (
|
|
767
|
-
|
|
857
|
+
weatherModels: y,
|
|
858
|
+
marineModels: F
|
|
859
|
+
}), [p] = it.pickHourly(I, a);
|
|
860
|
+
u = it.toLegacy(p);
|
|
861
|
+
} catch (y) {
|
|
862
|
+
C.warn("[%s] meteo2 spot(%j) forecast failed: %s", r.requestId, { ...t, eta: a.utc().format(), source: i }, y);
|
|
768
863
|
}
|
|
769
|
-
const
|
|
770
|
-
|
|
771
|
-
meteo: { ...
|
|
772
|
-
wxFactor:
|
|
773
|
-
cFactor:
|
|
774
|
-
speed:
|
|
864
|
+
const m = O.weatherFactor(e, u), f = O.currentFactor(e.bearing, u == null ? void 0 : u.current, o), b = Math.round((e.speed * 1.943844 + m + f) * 100) / 100;
|
|
865
|
+
c = {
|
|
866
|
+
meteo: { ...u },
|
|
867
|
+
wxFactor: m,
|
|
868
|
+
cFactor: f,
|
|
869
|
+
speed: t.velocity && s ? t.velocity : b < 0 ? 1 : b,
|
|
775
870
|
eta: a.utc().format(),
|
|
776
871
|
etd: a.utc().format()
|
|
777
872
|
};
|
|
778
873
|
} else
|
|
779
|
-
|
|
874
|
+
c = {
|
|
780
875
|
wxFactor: 0,
|
|
781
876
|
cFactor: 0,
|
|
782
|
-
speed:
|
|
877
|
+
speed: t.velocity && s ? t.velocity : Math.round((e.speed * 1.943844 + 0 + 0) * 100) / 100,
|
|
783
878
|
eta: a.utc().format(),
|
|
784
879
|
etd: a.utc().format()
|
|
785
880
|
};
|
|
786
|
-
return delete
|
|
881
|
+
return delete t.meteo, delete t.wxFactor, delete t.cFactor, delete t.speed, delete t.etd, { ...c, ...t };
|
|
787
882
|
}
|
|
788
883
|
/**
|
|
789
884
|
* 基于步长计算失速样本
|
|
@@ -799,53 +894,53 @@ class O {
|
|
|
799
894
|
* @param options
|
|
800
895
|
* @private
|
|
801
896
|
*/
|
|
802
|
-
static async speedLoseInHoursStep(
|
|
803
|
-
|
|
804
|
-
const
|
|
805
|
-
let
|
|
806
|
-
for (let
|
|
807
|
-
let
|
|
808
|
-
|
|
809
|
-
const
|
|
810
|
-
if (
|
|
811
|
-
|
|
812
|
-
const
|
|
813
|
-
if (i -
|
|
814
|
-
i = i -
|
|
897
|
+
static async speedLoseInHoursStep(e, t, a, i, o, n, s = "", r = !0, c = !1, u = {}) {
|
|
898
|
+
t.utc();
|
|
899
|
+
const m = t.clone().add(14, "days"), f = [], b = [];
|
|
900
|
+
let y = 0, F = 0, I, p;
|
|
901
|
+
for (let v = 0; v < n.length - 1; v++) {
|
|
902
|
+
let d = n[v];
|
|
903
|
+
d.distanceFromStart = Math.round((o + F) * 1e3) / 1e3;
|
|
904
|
+
const g = n[v + 1];
|
|
905
|
+
if (e.bearing = W.calculateBearing(d, g, !g.gcToPrevious), d.bearing = e.bearing, d.suspend && c) {
|
|
906
|
+
d.eta = d.eta || t.utc().format(), d.elapsed = d.elapsed ?? 0;
|
|
907
|
+
const k = d.suspend - d.elapsed;
|
|
908
|
+
if (i - y > k)
|
|
909
|
+
i = i - y - k, t.add(k, "hour"), d.elapsed = d.suspend;
|
|
815
910
|
else {
|
|
816
|
-
const
|
|
817
|
-
|
|
911
|
+
const S = i - y;
|
|
912
|
+
d.elapsed += S, t.add(S, "hour"), i = 0;
|
|
818
913
|
}
|
|
819
|
-
if (
|
|
820
|
-
return
|
|
914
|
+
if (C == null || C.info(`[%s] suspend ${d.elapsed} hours at %j, and remain ${i} hours need to go...`, u.requestId, d), i === 0)
|
|
915
|
+
return d.distanceFromPrevious = F, { etd: t, from: p || d, to: d, next: n.filter((S) => S), wps: f, days: b };
|
|
821
916
|
} else
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
const
|
|
825
|
-
let
|
|
826
|
-
if (
|
|
827
|
-
if (
|
|
828
|
-
`[%s] go to %j from %j with ${
|
|
829
|
-
|
|
830
|
-
{ lat:
|
|
917
|
+
d.suspend = 0;
|
|
918
|
+
r = t.isAfter(m) ? !1 : r, d = await O.speedLoseAt(e, d, t, s, 0, r, c, u), p = p || d, d.important && f.push(d), t.isSameOrAfter(a) && (b.push(d), a.add(24, "hour"));
|
|
919
|
+
const l = W.calculateDistance(d, g, !g.gcToPrevious);
|
|
920
|
+
let h = Math.round(l / p.speed * 1e5) / 1e5;
|
|
921
|
+
if (y + h < i) {
|
|
922
|
+
if (y += h, t.add(h, "hour"), delete n[v], C == null || C.debug(
|
|
923
|
+
`[%s] go to %j from %j with ${l}nm, and cost ${h} hours`,
|
|
924
|
+
u.requestId,
|
|
925
|
+
{ lat: g.lat, lng: g.lng },
|
|
831
926
|
{ lat: p.lat, lng: p.lng, etd: p.etd }
|
|
832
|
-
),
|
|
833
|
-
|
|
927
|
+
), F += l, n.filter((k) => k).length <= 1) {
|
|
928
|
+
I = g, I.eta = t.utc().format(), I.distanceFromPrevious = l, I.distanceFromStart = Math.round((o + F) * 1e4) / 1e4, f.push(I), delete n[v + 1];
|
|
834
929
|
break;
|
|
835
930
|
}
|
|
836
931
|
} else {
|
|
837
|
-
|
|
838
|
-
const
|
|
839
|
-
|
|
840
|
-
`[%s] go to %j from %j with ${
|
|
841
|
-
|
|
842
|
-
{ lat:
|
|
843
|
-
{ lat:
|
|
844
|
-
),
|
|
932
|
+
h = i - y, t.add(h, "hour");
|
|
933
|
+
const k = _.roundPrecision(p.speed * h, 5);
|
|
934
|
+
I = W.calculateCoordinate(d, e.bearing, k, "nauticalmiles", !g.gcToPrevious), I.eta = t.utc().format(), n[v] = I, C == null || C.debug(
|
|
935
|
+
`[%s] go to %j from %j with ${k}nm, and cost ${h} hours`,
|
|
936
|
+
u.requestId,
|
|
937
|
+
{ lat: I.lat, lng: I.lng },
|
|
938
|
+
{ lat: d.lat, lng: d.lng, etd: d.etd }
|
|
939
|
+
), F += k, I.distanceFromPrevious = Math.round(F * 1e4) / 1e4, I.distanceFromStart = Math.round((o + F) * 1e4) / 1e4;
|
|
845
940
|
break;
|
|
846
941
|
}
|
|
847
942
|
}
|
|
848
|
-
return { etd:
|
|
943
|
+
return { etd: t, from: p, to: I, next: n.filter((v) => v), wps: f, days: b };
|
|
849
944
|
}
|
|
850
945
|
/**
|
|
851
946
|
* 洋流影响因子
|
|
@@ -853,11 +948,11 @@ class O {
|
|
|
853
948
|
* @param current 洋流要素
|
|
854
949
|
* @param role 1: 船东, 2: 租家, 0: 未知
|
|
855
950
|
*/
|
|
856
|
-
static currentFactor(
|
|
857
|
-
const i = (
|
|
951
|
+
static currentFactor(e, t, a = 0) {
|
|
952
|
+
const i = (e - (t == null ? void 0 : t.degree) || 0) / 180 * Math.PI;
|
|
858
953
|
if (Math.abs(i) === Math.PI / 2)
|
|
859
954
|
return 0;
|
|
860
|
-
let o = ((
|
|
955
|
+
let o = ((t == null ? void 0 : t.kts) || 0) * Math.cos(i);
|
|
861
956
|
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;
|
|
862
957
|
}
|
|
863
958
|
/**
|
|
@@ -865,17 +960,17 @@ class O {
|
|
|
865
960
|
* @param props 船舶档案
|
|
866
961
|
* @param wwc 气象要素
|
|
867
962
|
*/
|
|
868
|
-
static weatherFactor(
|
|
869
|
-
var
|
|
870
|
-
|
|
871
|
-
const a = O.blockCoefficient(
|
|
872
|
-
let n = Math.abs(
|
|
963
|
+
static weatherFactor(e, t) {
|
|
964
|
+
var m, f, b, y, F, I, p;
|
|
965
|
+
C == null || C.debug("calculate weather factor via: %j", { ...e, ...t });
|
|
966
|
+
const a = O.blockCoefficient(e.displacement, e.lbp, e.breadthMoulded, e.draught), i = O.froudeNumber(e.speed, e.lbp), o = O.amendFactor(a, i, e.loadCondition);
|
|
967
|
+
let n = Math.abs(e.bearing % 360 - (((m = t == null ? void 0 : t.wind) == null ? void 0 : m.degree) % 360 || 0));
|
|
873
968
|
n = n > 180 ? 360 - n : n;
|
|
874
|
-
const s = O.directionFactor(n, (
|
|
875
|
-
let
|
|
876
|
-
|
|
877
|
-
const
|
|
878
|
-
return
|
|
969
|
+
const s = O.directionFactor(n, (f = t == null ? void 0 : t.wind) == null ? void 0 : f.scale), r = O.vesselTagFactor(e.displacement, e.loadCondition, e.tag, (b = t == null ? void 0 : t.wind) == null ? void 0 : b.scale);
|
|
970
|
+
let c = s * o * r / 100 * e.speed;
|
|
971
|
+
c = Math.round(c * 1.943844 * 1e4) / 1e4 * -1, e.tag === "tugs" && Math.abs(c) > 1 && (c = c / (Math.abs(Math.round(c)) + 1)), C == null || C.debug("wind wx factor = %d", c), n = Math.abs(e.bearing % 360 - (((F = (y = t == null ? void 0 : t.wave) == null ? void 0 : y.sig) == null ? void 0 : F.degree) % 360 || 0));
|
|
972
|
+
const u = O.waveHeightFactor(((p = (I = t == null ? void 0 : t.wave) == null ? void 0 : I.sig) == null ? void 0 : p.height) ?? 1, n);
|
|
973
|
+
return C == null || C.debug("wave wx factor = %d", u), c = Math.abs(c) > Math.abs(u) ? c : c * 0.3 + u * 0.7, C == null || C.debug("weather factor = %d", c), c = Math.abs(c) > 3 ? 3 * (Math.abs(c) / c) + Math.abs(c) / c * (Math.abs(c) - 2) * 0.1 : c, Math.round((c || 0) * 100) / 100;
|
|
879
974
|
}
|
|
880
975
|
/**
|
|
881
976
|
* 全程失速分析(走完航程)
|
|
@@ -890,77 +985,77 @@ class O {
|
|
|
890
985
|
* @param useRouteParam
|
|
891
986
|
* @param options
|
|
892
987
|
*/
|
|
893
|
-
static async analyseInstant(
|
|
894
|
-
var
|
|
895
|
-
const
|
|
896
|
-
|
|
897
|
-
const { route:
|
|
898
|
-
if (((
|
|
988
|
+
static async analyseInstant(e, t, a, i, o, n = "", s = 0, r = !0, c = !1, u = {}) {
|
|
989
|
+
var K, G, X, Q, Z, $;
|
|
990
|
+
const m = w().valueOf();
|
|
991
|
+
e.lng = _.convertToStdLng(e.lng);
|
|
992
|
+
const { route: f, waypoints: b } = o.points, y = W.calculateSubRoute(e, f);
|
|
993
|
+
if (((K = y[0]) == null ? void 0 : K.length) <= 1)
|
|
899
994
|
return;
|
|
900
|
-
const { v0:
|
|
901
|
-
v0:
|
|
902
|
-
label:
|
|
995
|
+
const { v0: F, label: I } = e.sog ? {
|
|
996
|
+
v0: e.sog,
|
|
997
|
+
label: e.label || "Other"
|
|
903
998
|
/* Instruct */
|
|
904
999
|
} : {
|
|
905
1000
|
v0: i.speed,
|
|
906
1001
|
label: "CP"
|
|
907
1002
|
/* Cp */
|
|
908
|
-
}, p = O.assembleProperties(a, i.loadCondition,
|
|
909
|
-
|
|
910
|
-
const
|
|
911
|
-
from: { ...
|
|
912
|
-
route:
|
|
913
|
-
waypoints:
|
|
914
|
-
v0:
|
|
915
|
-
label:
|
|
916
|
-
},
|
|
1003
|
+
}, p = O.assembleProperties(a, i.loadCondition, F, 0), v = b.length ? W.calculateSubWaypoints(e, b) : [];
|
|
1004
|
+
v.forEach((Y) => Y.important = !0);
|
|
1005
|
+
const d = {
|
|
1006
|
+
from: { ...e },
|
|
1007
|
+
route: y,
|
|
1008
|
+
waypoints: v,
|
|
1009
|
+
v0: F,
|
|
1010
|
+
label: I
|
|
1011
|
+
}, g = {
|
|
917
1012
|
hours: [],
|
|
918
1013
|
days: [],
|
|
919
1014
|
wps: []
|
|
920
1015
|
};
|
|
921
|
-
s || (W.calculateRouteDistance(
|
|
922
|
-
let
|
|
923
|
-
|
|
924
|
-
const
|
|
925
|
-
for (;
|
|
926
|
-
const
|
|
1016
|
+
s || (W.calculateRouteDistance(y) / i.speed <= 72 ? s = 3 : s = 6);
|
|
1017
|
+
let l = W.simplifyRouteToCoordinates(y, v, 0), h = 0, k = 0, S = 0, D = 0;
|
|
1018
|
+
t = w(t).utc();
|
|
1019
|
+
const P = t.clone();
|
|
1020
|
+
for (; l.length > 0; ) {
|
|
1021
|
+
const Y = s - t.hour() % s, B = Math.ceil(t.clone().add(Y, "h").set({ minute: 0, second: 0, millisecond: 0 }).diff(t, "h", !0) * 1e4) / 1e4, j = await O.speedLoseInHoursStep(
|
|
927
1022
|
p,
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
u,
|
|
1023
|
+
t,
|
|
1024
|
+
P,
|
|
1025
|
+
B,
|
|
932
1026
|
h,
|
|
1027
|
+
l,
|
|
933
1028
|
n,
|
|
934
|
-
d,
|
|
935
1029
|
r,
|
|
936
|
-
|
|
1030
|
+
c,
|
|
1031
|
+
u
|
|
937
1032
|
);
|
|
938
|
-
(G =
|
|
1033
|
+
(G = j.from) != null && G.speed && (g.hours.push(j.from), g.wps.push(...j.wps), g.days.push(...j.days)), l = j == null ? void 0 : j.next, l.length || g.hours.push(j == null ? void 0 : j.to), h += Math.round((((X = j == null ? void 0 : j.to) == null ? void 0 : X.distanceFromPrevious) ?? 0) * 1e4) / 1e4;
|
|
939
1034
|
}
|
|
940
|
-
const
|
|
941
|
-
for (let
|
|
942
|
-
const
|
|
943
|
-
|
|
1035
|
+
const N = g.hours;
|
|
1036
|
+
for (let Y = 0; Y < N.length - 1; Y++) {
|
|
1037
|
+
const B = w(N[Y + 1].eta).diff(N[Y].etd, "hour", !0) || 1;
|
|
1038
|
+
k += (N[Y].wxFactor || 0) * B, S += (N[Y].cFactor || 0) * B, D += B;
|
|
944
1039
|
}
|
|
945
|
-
(Q =
|
|
946
|
-
|
|
947
|
-
const
|
|
948
|
-
if (
|
|
949
|
-
const
|
|
950
|
-
|
|
1040
|
+
(Q = g.wps) == null || Q.forEach((Y, B) => {
|
|
1041
|
+
Y.positionTime = w.utc(Y.etd || Y.eta).unix();
|
|
1042
|
+
const j = g.wps[B - 1];
|
|
1043
|
+
if (j) {
|
|
1044
|
+
const V = Y.distanceFromStart - j.distanceFromStart, H = w(Y.eta || Y.etd).diff(w(j.etd || j.eta), "h", !0);
|
|
1045
|
+
Y.avgSpd = Math.round(V / H * 100) / 100, j.bearing = W.calculateBearing(j, Y);
|
|
951
1046
|
}
|
|
952
|
-
}),
|
|
953
|
-
const A =
|
|
954
|
-
|
|
955
|
-
const { distanceInECA:
|
|
956
|
-
|
|
957
|
-
eca:
|
|
958
|
-
distanceInECA:
|
|
959
|
-
hoursInECA:
|
|
1047
|
+
}), g.wps = (Z = g.wps) == null ? void 0 : Z.reduce((Y, B) => (Y.some((j) => Math.round(j.positionTime / 60) === Math.round(B.positionTime / 60)) || Y.push(B), Y), []), d.sample = g;
|
|
1048
|
+
const A = g.hours.at(0), x = g.hours.at(-1);
|
|
1049
|
+
d.distance = Math.round(x.distanceFromStart * 1e3) / 1e3, d.etd = w(A.eta).utc().format(), d.eta = w(x.eta).utc().format(), d.wxFactor = Math.round(k / D * 1e3) / 1e3, d.cFactor = Math.round(S / D * 1e3) / 1e3, d.avgSpeed = Math.round(x.distanceFromStart / D * 1e3) / 1e3, d.totalHrs = Math.round(D * 1e3) / 1e3;
|
|
1050
|
+
const { distanceInECA: T, hoursInECA: q, totalDgoConsInECA: R, eca: J } = await this.calculateECA(d, i, u), tt = _.roundPrecision(i.fo / 24 * (D - q), 3), at = _.roundPrecision(i.dgo / 24 * D, 3);
|
|
1051
|
+
d.extend = {
|
|
1052
|
+
eca: J,
|
|
1053
|
+
distanceInECA: T,
|
|
1054
|
+
hoursInECA: q,
|
|
960
1055
|
totalDgoConsInECA: R
|
|
961
|
-
},
|
|
962
|
-
const et =
|
|
963
|
-
return
|
|
1056
|
+
}, d.totalFoCons = tt < 0 ? 0 : tt, d.totalDgoCons = at;
|
|
1057
|
+
const et = w().valueOf() - m, ot = (($ = g == null ? void 0 : g.hours) == null ? void 0 : $.length) || 1;
|
|
1058
|
+
return C == null || C.info("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms", u == null ? void 0 : u.requestId, et, ot, Math.round(et / ot * 1e3) / 1e3), d;
|
|
964
1059
|
}
|
|
965
1060
|
/**
|
|
966
1061
|
* 分段失速分析(最多走hours 小时)
|
|
@@ -975,78 +1070,78 @@ class O {
|
|
|
975
1070
|
* @param useMeteo true 启用气象分析
|
|
976
1071
|
* @param useRouteParam
|
|
977
1072
|
*/
|
|
978
|
-
static async analyseInstantWithThreshed(
|
|
979
|
-
var X, Q, Z, $,
|
|
980
|
-
const b =
|
|
981
|
-
|
|
982
|
-
const { v0:
|
|
983
|
-
v0:
|
|
984
|
-
label:
|
|
1073
|
+
static async analyseInstantWithThreshed(e, t, a, i, o, n, s, r = "", c = 3, u = !0, m = !1, f = {}) {
|
|
1074
|
+
var X, Q, Z, $, Y, B;
|
|
1075
|
+
const b = w().valueOf();
|
|
1076
|
+
e.lng = _.convertToStdLng(e.lng);
|
|
1077
|
+
const { v0: y, label: F } = e.sog ? {
|
|
1078
|
+
v0: e.sog,
|
|
1079
|
+
label: e.label || "Other"
|
|
985
1080
|
/* Instruct */
|
|
986
1081
|
} : {
|
|
987
1082
|
v0: o.speed,
|
|
988
1083
|
label: "CP"
|
|
989
1084
|
/* Cp */
|
|
990
|
-
},
|
|
1085
|
+
}, I = O.assembleProperties(i, o.loadCondition, y, 0), p = W.calculateSubRoute(e, n);
|
|
991
1086
|
if (((X = p[0]) == null ? void 0 : X.length) <= 1)
|
|
992
1087
|
return;
|
|
993
|
-
const
|
|
994
|
-
|
|
995
|
-
let
|
|
996
|
-
const
|
|
1088
|
+
const v = s.length ? W.calculateSubWaypoints(e, s) : [];
|
|
1089
|
+
v.forEach((j) => j.important = !0);
|
|
1090
|
+
let d = W.simplifyRouteToCoordinates(p, v, 0), g = 0, l = 0, h = 0, k = 0;
|
|
1091
|
+
const S = {
|
|
997
1092
|
hours: [],
|
|
998
1093
|
wps: [],
|
|
999
1094
|
days: []
|
|
1000
1095
|
};
|
|
1001
|
-
|
|
1002
|
-
const D =
|
|
1003
|
-
for (;
|
|
1004
|
-
const
|
|
1005
|
-
let
|
|
1006
|
-
|
|
1007
|
-
const H = await O.speedLoseInHoursStep(
|
|
1008
|
-
if ((Q = H.from) != null && Q.speed && (
|
|
1096
|
+
t = w(t).utc();
|
|
1097
|
+
const D = t.clone();
|
|
1098
|
+
for (; d.length > 0; ) {
|
|
1099
|
+
const j = c - t.hour() % c;
|
|
1100
|
+
let V = Math.ceil(t.clone().add(j, "h").set({ minute: 0, second: 0, millisecond: 0 }).diff(t, "h", !0) * 1e4) / 1e4;
|
|
1101
|
+
V = t.clone().add(V, "h").isSameOrAfter(a) ? a.diff(t, "h", !0) * 1e4 / 1e4 : V;
|
|
1102
|
+
const H = await O.speedLoseInHoursStep(I, t, D, V, g, d, r, u, m, f);
|
|
1103
|
+
if ((Q = H.from) != null && Q.speed && (S.hours.push(H.from), H != null && H.wps && S.wps.push(...H.wps), S.days.push(...H.days)), d = H == null ? void 0 : H.next, d.length || S.hours.push(H == null ? void 0 : H.to), g += Math.round((((Z = H == null ? void 0 : H.to) == null ? void 0 : Z.distanceFromPrevious) ?? 0) * 1e4) / 1e4, !V)
|
|
1009
1104
|
break;
|
|
1010
1105
|
}
|
|
1011
|
-
|
|
1012
|
-
const H =
|
|
1106
|
+
S.wps = ($ = S.wps) == null ? void 0 : $.reduce((j, V) => (j.some((H) => Math.round(w(H.etd).unix() / 60) === Math.round(w(V.etd).unix() / 60)) || j.push(V), j), []), (Y = S.wps) == null || Y.forEach((j, V) => {
|
|
1107
|
+
const H = S.wps[V - 1];
|
|
1013
1108
|
if (H) {
|
|
1014
|
-
const
|
|
1015
|
-
|
|
1016
|
-
const ut = W.calculateBearing(H,
|
|
1109
|
+
const rt = j.distanceFromStart - H.distanceFromStart, dt = w(j.eta || j.etd).diff(w(H.etd || H.eta), "h", !0);
|
|
1110
|
+
j.avgSpd = Math.round(rt / dt * 100) / 100;
|
|
1111
|
+
const ut = W.calculateBearing(H, j);
|
|
1017
1112
|
H.bearing = ut;
|
|
1018
1113
|
}
|
|
1019
1114
|
});
|
|
1020
|
-
const
|
|
1021
|
-
for (let
|
|
1022
|
-
const
|
|
1023
|
-
|
|
1115
|
+
const P = S.hours;
|
|
1116
|
+
for (let j = 0; j < P.length - 1; j++) {
|
|
1117
|
+
const V = w(P[j + 1].eta).diff(P[j].etd, "hour", !0);
|
|
1118
|
+
l += P[j].wxFactor * V, h += P[j].cFactor * V, k += V;
|
|
1024
1119
|
}
|
|
1025
|
-
const
|
|
1026
|
-
sample:
|
|
1120
|
+
const N = S.hours.at(0), A = S.hours.at(-1), x = await W.calculateRangeRoute(N, A, p), T = await W.calculateRangeWaypoints(N, A, p, v), q = {
|
|
1121
|
+
sample: S,
|
|
1027
1122
|
distance: Math.round(((A == null ? void 0 : A.distanceFromStart) || 0) * 1e4) / 1e4,
|
|
1028
1123
|
// 注意,可能会在first节点Drift,所有采用eta做为初始出发时间
|
|
1029
|
-
etd:
|
|
1030
|
-
eta:
|
|
1031
|
-
wxFactor: Math.round(
|
|
1032
|
-
cFactor: Math.round(
|
|
1033
|
-
avgSpeed: Math.round(((A == null ? void 0 : A.distanceFromStart) || 0) /
|
|
1034
|
-
totalHrs: Math.round(
|
|
1035
|
-
from:
|
|
1124
|
+
etd: w(N.eta).utc().format(),
|
|
1125
|
+
eta: w(A == null ? void 0 : A.eta).utc().format(),
|
|
1126
|
+
wxFactor: Math.round(l / k * 1e3) / 1e3,
|
|
1127
|
+
cFactor: Math.round(h / k * 1e3) / 1e3,
|
|
1128
|
+
avgSpeed: Math.round(((A == null ? void 0 : A.distanceFromStart) || 0) / k * 1e3) / 1e3,
|
|
1129
|
+
totalHrs: Math.round(k * 1e3) / 1e3,
|
|
1130
|
+
from: N,
|
|
1036
1131
|
to: A,
|
|
1037
|
-
route:
|
|
1038
|
-
waypoints:
|
|
1039
|
-
v0:
|
|
1040
|
-
label:
|
|
1041
|
-
}, { distanceInECA: R, hoursInECA:
|
|
1042
|
-
|
|
1132
|
+
route: x,
|
|
1133
|
+
waypoints: T,
|
|
1134
|
+
v0: y,
|
|
1135
|
+
label: F
|
|
1136
|
+
}, { distanceInECA: R, hoursInECA: J, totalDgoConsInECA: tt, eca: at } = await this.calculateECA(q, o, f), nt = _.roundPrecision(o.fo / 24 * (k - J), 3), et = _.roundPrecision(o.dgo / 24 * k, 3);
|
|
1137
|
+
q.extend = {
|
|
1043
1138
|
eca: at,
|
|
1044
1139
|
distanceInECA: R,
|
|
1045
|
-
hoursInECA:
|
|
1140
|
+
hoursInECA: J,
|
|
1046
1141
|
totalDgoConsInECA: tt
|
|
1047
|
-
},
|
|
1048
|
-
const
|
|
1049
|
-
return
|
|
1142
|
+
}, q.totalDgoCons = et, q.totalFoCons = nt < 0 ? 0 : nt;
|
|
1143
|
+
const K = w().valueOf() - b, G = ((B = S == null ? void 0 : S.hours) == null ? void 0 : B.length) || 1;
|
|
1144
|
+
return C == null || C.debug("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms", f == null ? void 0 : f.requestId, K, G, Math.round(K / G * 1e3) / 1e3), q;
|
|
1050
1145
|
}
|
|
1051
1146
|
/**
|
|
1052
1147
|
* 在指定航线条件下,基于多CP,动态计算最优成本(租金+油费)方案
|
|
@@ -1063,59 +1158,59 @@ class O {
|
|
|
1063
1158
|
* @param lane 基础航线(重要转向点)
|
|
1064
1159
|
* @param options
|
|
1065
1160
|
*/
|
|
1066
|
-
static async analyseCost(
|
|
1067
|
-
var p,
|
|
1068
|
-
const n =
|
|
1069
|
-
|
|
1070
|
-
const
|
|
1071
|
-
let
|
|
1072
|
-
a.forEach((
|
|
1073
|
-
const
|
|
1074
|
-
|
|
1075
|
-
}),
|
|
1076
|
-
const
|
|
1077
|
-
let
|
|
1078
|
-
for (const
|
|
1079
|
-
const
|
|
1080
|
-
{ lat:
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1161
|
+
static async analyseCost(e, t, a, i, o = {}) {
|
|
1162
|
+
var p, v;
|
|
1163
|
+
const n = w().valueOf(), s = [];
|
|
1164
|
+
e.speedStep = e.speedStep || 3, e.alterStep = e.alterStep ?? 1;
|
|
1165
|
+
const r = W.calculateRouteDistance(i.route);
|
|
1166
|
+
let c = 0;
|
|
1167
|
+
a.forEach((d) => {
|
|
1168
|
+
const g = Math.ceil(r / d.speed / 24);
|
|
1169
|
+
c = c < g ? g : c;
|
|
1170
|
+
}), c = c * 1.3;
|
|
1171
|
+
const u = w.utc(e.etd).add(c ?? 14, "day");
|
|
1172
|
+
let m = 1;
|
|
1173
|
+
for (const d of a) {
|
|
1174
|
+
const g = JSON.parse(JSON.stringify(i.route)), l = JSON.parse(JSON.stringify(i.waypoints)), h = await O.analyseInstantWithThreshed(
|
|
1175
|
+
{ lat: e.lat, lng: e.lng },
|
|
1176
|
+
e.etd,
|
|
1177
|
+
u,
|
|
1178
|
+
t,
|
|
1179
|
+
d,
|
|
1180
|
+
g,
|
|
1181
|
+
l,
|
|
1182
|
+
e.meteoVendor,
|
|
1183
|
+
e.speedStep,
|
|
1184
|
+
e.useMeteo,
|
|
1185
|
+
e.useRouteParam,
|
|
1091
1186
|
o
|
|
1092
1187
|
);
|
|
1093
|
-
|
|
1094
|
-
cost:
|
|
1095
|
-
hire:
|
|
1096
|
-
bunker:
|
|
1097
|
-
distance:
|
|
1098
|
-
hours:
|
|
1099
|
-
cp: `${
|
|
1100
|
-
})),
|
|
1188
|
+
h && (await O.calculateCost(h, d, e, o), s.push(h), C == null || C.info("[%s][L%d-%d] analyse from %s to %s cost: %j", o.requestId, 1, m, e.etd, u.format(), {
|
|
1189
|
+
cost: h.cost.total,
|
|
1190
|
+
hire: h.cost.hire,
|
|
1191
|
+
bunker: h.cost.bunker,
|
|
1192
|
+
distance: h.distance,
|
|
1193
|
+
hours: h.totalHrs,
|
|
1194
|
+
cp: `${d.speed}/${d.fo}/${d.dgo}`
|
|
1195
|
+
})), m++;
|
|
1101
1196
|
}
|
|
1102
|
-
s.sort((
|
|
1103
|
-
const
|
|
1104
|
-
if (
|
|
1105
|
-
const
|
|
1106
|
-
let
|
|
1107
|
-
|
|
1108
|
-
let D = 2,
|
|
1109
|
-
for (;
|
|
1110
|
-
const A = await O.combinedAnalyse(
|
|
1111
|
-
if (
|
|
1197
|
+
s.sort((d, g) => d.cost.total - g.cost.total);
|
|
1198
|
+
const f = s.at(0), b = s.at(1), y = [];
|
|
1199
|
+
if (y.push({ combined: !1, speeds: [f], cost: (p = f.cost) == null ? void 0 : p.total }), b) {
|
|
1200
|
+
const d = f.cost.cp, g = b.cost.cp, l = w(f.eta), h = w(f.etd), k = l.diff(h, "days", !0);
|
|
1201
|
+
let S = Math.ceil(k / 2);
|
|
1202
|
+
S = S > 7 ? 7 : S < e.alterStep ? e.alterStep : S;
|
|
1203
|
+
let D = 2, P = { combined: !1, speeds: [b], cost: (v = b.cost) == null ? void 0 : v.total }, N;
|
|
1204
|
+
for (; S >= e.alterStep; ) {
|
|
1205
|
+
const A = await O.combinedAnalyse(e, t, u, [d, g], i, S, { ...o, level: D });
|
|
1206
|
+
if (P.cost > A.cost ? N ? (N == null ? void 0 : N.cost) > A.cost && (N = A) : (N = P, P = A) : (!N || (N == null ? void 0 : N.cost) > A.cost) && (N = A), S <= e.alterStep)
|
|
1112
1207
|
break;
|
|
1113
|
-
|
|
1208
|
+
S = Math.ceil(S / 2), D += 1;
|
|
1114
1209
|
}
|
|
1115
|
-
|
|
1210
|
+
y.push(P), N && y.push(N);
|
|
1116
1211
|
}
|
|
1117
|
-
const
|
|
1118
|
-
return
|
|
1212
|
+
const I = w().valueOf() - n;
|
|
1213
|
+
return C == null || C.info("[%s] analyse elapsed: %d ms", o == null ? void 0 : o.requestId, I), y.sort((d, g) => d.cost - g.cost);
|
|
1119
1214
|
}
|
|
1120
1215
|
/**
|
|
1121
1216
|
* 按步长多次减半,分别用7,4,2,1天步长及cpa,cpb交替计算各种组合下的成本
|
|
@@ -1127,24 +1222,24 @@ class O {
|
|
|
1127
1222
|
* @param step 步长,7,4,2,1
|
|
1128
1223
|
* @param options
|
|
1129
1224
|
*/
|
|
1130
|
-
static async combinedAnalyse(
|
|
1131
|
-
s.counter = 1,
|
|
1132
|
-
const
|
|
1133
|
-
|
|
1134
|
-
cost:
|
|
1135
|
-
hire:
|
|
1136
|
-
bunker:
|
|
1137
|
-
distance:
|
|
1225
|
+
static async combinedAnalyse(e, t, a, i, o, n, s = {}) {
|
|
1226
|
+
s.counter = 1, C == null || C.info("[%s][L%d] analyse with alternate cp in every %d days", s.requestId, s.level, n);
|
|
1227
|
+
const r = await O.alternateAnalyse(e, t, a, i, 0, o, n, s), c = r.reduce((g, l) => g + l.cost.total, 0), u = r.reduce((g, l) => g + l.cost.hire, 0), m = r.reduce((g, l) => g + l.cost.bunker, 0), f = r.reduce((g, l) => g + l.distance, 0), b = r.reduce((g, l) => g + l.totalHrs, 0);
|
|
1228
|
+
C == null || C.info("[%s][L%d] cost with cpa/cpb turn: %j", s.requestId, s.level, {
|
|
1229
|
+
cost: c,
|
|
1230
|
+
hire: u,
|
|
1231
|
+
bunker: m,
|
|
1232
|
+
distance: f,
|
|
1138
1233
|
hours: b
|
|
1139
1234
|
});
|
|
1140
|
-
const
|
|
1141
|
-
return
|
|
1142
|
-
cost:
|
|
1143
|
-
hire:
|
|
1235
|
+
const y = await O.alternateAnalyse(e, t, a, i, 1, o, n, s), F = y.reduce((g, l) => g + l.cost.total, 0), I = y.reduce((g, l) => g + l.cost.hire, 0), p = y.reduce((g, l) => g + l.cost.bunker, 0), v = y.reduce((g, l) => g + l.distance, 0), d = y.reduce((g, l) => g + l.totalHrs, 0);
|
|
1236
|
+
return C == null || C.info("[%s][L%d] cost with cpb/cpa turn: %j", s.requestId, s.level, {
|
|
1237
|
+
cost: F,
|
|
1238
|
+
hire: I,
|
|
1144
1239
|
bunker: p,
|
|
1145
|
-
distance:
|
|
1146
|
-
hours:
|
|
1147
|
-
}),
|
|
1240
|
+
distance: v,
|
|
1241
|
+
hours: d
|
|
1242
|
+
}), c < F ? { combined: !0, cost: Math.round(c * 1e3) / 1e3, speeds: r, step: n } : { combined: !0, cost: Math.round(F * 1e3) / 1e3, speeds: y, step: n };
|
|
1148
1243
|
}
|
|
1149
1244
|
/**
|
|
1150
1245
|
* 基于cp索引,交替计算指定步长下的成本
|
|
@@ -1157,48 +1252,48 @@ class O {
|
|
|
1157
1252
|
* @param step 步长,7,4,2,1
|
|
1158
1253
|
* @param options
|
|
1159
1254
|
*/
|
|
1160
|
-
static async alternateAnalyse(
|
|
1161
|
-
var
|
|
1162
|
-
let
|
|
1163
|
-
const
|
|
1164
|
-
for (;
|
|
1165
|
-
const
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1255
|
+
static async alternateAnalyse(e, t, a, i, o, n, s, r = {}) {
|
|
1256
|
+
var f, b;
|
|
1257
|
+
let c = w.utc(e.etd);
|
|
1258
|
+
const u = { lat: e.lat, lng: e.lng }, m = [];
|
|
1259
|
+
for (; c.isBefore(a); ) {
|
|
1260
|
+
const y = c.clone().utc().add(s, "day"), F = JSON.parse(JSON.stringify(n.route)), I = JSON.parse(JSON.stringify(n.waypoints)), p = i[o], v = await O.analyseInstantWithThreshed(
|
|
1261
|
+
u,
|
|
1262
|
+
c.utc().format(),
|
|
1263
|
+
y,
|
|
1264
|
+
t,
|
|
1170
1265
|
p,
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1266
|
+
F,
|
|
1267
|
+
I,
|
|
1268
|
+
e.meteoVendor,
|
|
1269
|
+
e.speedStep,
|
|
1270
|
+
e.useMeteo,
|
|
1271
|
+
e.useRouteParam,
|
|
1272
|
+
r
|
|
1178
1273
|
);
|
|
1179
|
-
|
|
1274
|
+
v && (await O.calculateCost(v, p, e, r), C == null || C.info(
|
|
1180
1275
|
"[%s][L%d-%d] analyse from %s to %s cost: %j",
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1276
|
+
r.requestId,
|
|
1277
|
+
r.level,
|
|
1278
|
+
r.counter,
|
|
1279
|
+
c.utc().format(),
|
|
1280
|
+
y.utc().format(),
|
|
1186
1281
|
{
|
|
1187
|
-
cost:
|
|
1188
|
-
hire:
|
|
1189
|
-
bunker:
|
|
1190
|
-
distance:
|
|
1191
|
-
hours:
|
|
1282
|
+
cost: v.cost.total,
|
|
1283
|
+
hire: v.cost.hire,
|
|
1284
|
+
bunker: v.cost.bunker,
|
|
1285
|
+
distance: v.distance,
|
|
1286
|
+
hours: v.totalHrs,
|
|
1192
1287
|
cp: `${p.speed}/${p.fo}/${p.dgo}`
|
|
1193
1288
|
}
|
|
1194
|
-
)),
|
|
1195
|
-
const
|
|
1196
|
-
if (
|
|
1197
|
-
|
|
1289
|
+
)), r.counter = r.counter + 1;
|
|
1290
|
+
const d = (b = (f = v == null ? void 0 : v.sample) == null ? void 0 : f.hours) == null ? void 0 : b.at(-1);
|
|
1291
|
+
if (d)
|
|
1292
|
+
u.lat = d.lat, u.lng = d.lng, c = w(d.eta), m.push(v), o = o ? 0 : 1;
|
|
1198
1293
|
else
|
|
1199
1294
|
break;
|
|
1200
1295
|
}
|
|
1201
|
-
return
|
|
1296
|
+
return m;
|
|
1202
1297
|
}
|
|
1203
1298
|
/**
|
|
1204
1299
|
* 计算Speed的cost
|
|
@@ -1207,36 +1302,36 @@ class O {
|
|
|
1207
1302
|
* @param props
|
|
1208
1303
|
* @param options
|
|
1209
1304
|
*/
|
|
1210
|
-
static async calculateCost(
|
|
1305
|
+
static async calculateCost(e, t, a, i = {}) {
|
|
1211
1306
|
var o;
|
|
1212
|
-
if (
|
|
1213
|
-
const n = (a.addComm || 0) >= 1 ? (a.addComm || 0) / 100 : a.addComm || 0, s = Math.round(
|
|
1214
|
-
|
|
1215
|
-
total: Math.round((s +
|
|
1307
|
+
if (e) {
|
|
1308
|
+
const n = (a.addComm || 0) >= 1 ? (a.addComm || 0) / 100 : a.addComm || 0, s = Math.round(e.totalHrs / 24 * (a.dailyHire || 0) * (1 - n) * 1e3) / 1e3, r = Math.round(e.totalFoCons * (a.priceFO || 0) * 1e3) / 1e3, c = Math.round((e.totalDgoCons + (((o = e.extend) == null ? void 0 : o.totalDgoConsInECA) || 0)) * (a.priceDGO || 0) * 1e3) / 1e3;
|
|
1309
|
+
e.cost = {
|
|
1310
|
+
total: Math.round((s + r + c) * 1e3) / 1e3,
|
|
1216
1311
|
hire: s,
|
|
1217
|
-
bunker: Math.round((
|
|
1218
|
-
cp:
|
|
1312
|
+
bunker: Math.round((r + c) * 1e3) / 1e3,
|
|
1313
|
+
cp: t
|
|
1219
1314
|
};
|
|
1220
1315
|
}
|
|
1221
|
-
return
|
|
1316
|
+
return e;
|
|
1222
1317
|
}
|
|
1223
1318
|
/**
|
|
1224
1319
|
* 计算单cp模式下的ECA属性
|
|
1225
1320
|
*
|
|
1226
1321
|
*/
|
|
1227
|
-
static async calculateECA(
|
|
1228
|
-
var
|
|
1229
|
-
const i = await W.intersectInECA((
|
|
1322
|
+
static async calculateECA(e, t, a = {}) {
|
|
1323
|
+
var r, c, u, m;
|
|
1324
|
+
const i = await W.intersectInECA((e == null ? void 0 : e.route) || []);
|
|
1230
1325
|
let o = 0, n = 0, s = 0;
|
|
1231
|
-
(
|
|
1232
|
-
|
|
1326
|
+
(c = (r = e == null ? void 0 : e.sample) == null ? void 0 : r.wps) == null || c.forEach((f) => {
|
|
1327
|
+
f.positionTime = w.utc(f.etd || f.eta).unix();
|
|
1233
1328
|
});
|
|
1234
|
-
for (const
|
|
1235
|
-
o +=
|
|
1236
|
-
const b = await W.deadReckoningTime((
|
|
1237
|
-
|
|
1329
|
+
for (const f of i) {
|
|
1330
|
+
o += f.distance;
|
|
1331
|
+
const b = await W.deadReckoningTime((u = f.waypoints) == null ? void 0 : u.at(0), e.sample.wps), y = await W.deadReckoningTime((m = f.waypoints) == null ? void 0 : m.at(-1), e.sample.wps);
|
|
1332
|
+
f.in = b, f.out = y, f.totalHrs = _.roundPrecision((y.positionTime - b.positionTime) / 3600, 3), f.totalDgoCons = _.roundPrecision(t.fo / 24 * f.totalHrs, 3), n += f.totalHrs, s += f.totalDgoCons;
|
|
1238
1333
|
}
|
|
1239
|
-
return o =
|
|
1334
|
+
return o = _.roundPrecision(o, 3), n = _.roundPrecision(n, 3), s = _.roundPrecision(s, 3), {
|
|
1240
1335
|
distanceInECA: o,
|
|
1241
1336
|
hoursInECA: n,
|
|
1242
1337
|
totalDgoConsInECA: s,
|
|
@@ -1248,84 +1343,84 @@ class O {
|
|
|
1248
1343
|
* @param speeds
|
|
1249
1344
|
* @param options
|
|
1250
1345
|
*/
|
|
1251
|
-
static async mergeSpeeds(
|
|
1252
|
-
var
|
|
1346
|
+
static async mergeSpeeds(e, t = {}) {
|
|
1347
|
+
var d, g;
|
|
1253
1348
|
const a = {
|
|
1254
1349
|
hours: [],
|
|
1255
1350
|
wps: [],
|
|
1256
1351
|
days: []
|
|
1257
|
-
}, i =
|
|
1258
|
-
var
|
|
1259
|
-
return
|
|
1260
|
-
}, 0), n =
|
|
1261
|
-
var
|
|
1262
|
-
return
|
|
1263
|
-
}, 0),
|
|
1264
|
-
var
|
|
1265
|
-
return
|
|
1266
|
-
}, 0),
|
|
1267
|
-
let
|
|
1268
|
-
for (const
|
|
1269
|
-
p.push(...((
|
|
1270
|
-
const
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
}),
|
|
1274
|
-
|
|
1275
|
-
}),
|
|
1276
|
-
|
|
1277
|
-
})), D.cp =
|
|
1278
|
-
const
|
|
1279
|
-
|
|
1280
|
-
var
|
|
1281
|
-
((
|
|
1282
|
-
}),
|
|
1283
|
-
var
|
|
1284
|
-
((
|
|
1285
|
-
}),
|
|
1286
|
-
var
|
|
1287
|
-
((
|
|
1352
|
+
}, i = e.reduce((l, h) => l + h.distance, 0), o = e.reduce((l, h) => {
|
|
1353
|
+
var k;
|
|
1354
|
+
return l + (((k = h.extend) == null ? void 0 : k.distanceInECA) || 0);
|
|
1355
|
+
}, 0), n = e.reduce((l, h) => l + h.totalHrs, 0), s = e.reduce((l, h) => {
|
|
1356
|
+
var k;
|
|
1357
|
+
return l + (((k = h.extend) == null ? void 0 : k.hoursInECA) || 0);
|
|
1358
|
+
}, 0), r = e.reduce((l, h) => {
|
|
1359
|
+
var k;
|
|
1360
|
+
return l + (((k = h.extend) == null ? void 0 : k.totalDgoConsInECA) || 0);
|
|
1361
|
+
}, 0), c = e.reduce((l, h) => l + h.wxFactor * h.totalHrs / n, 0), u = e.reduce((l, h) => l + h.cFactor * h.totalHrs / n, 0), m = e.reduce((l, h) => l + h.totalFoCons, 0), f = e.reduce((l, h) => l + h.totalDgoCons, 0), b = e.reduce((l, h) => l + h.cost.total, 0), y = e.reduce((l, h) => l + h.cost.hire, 0), F = e.reduce((l, h) => l + h.cost.bunker, 0), I = [], p = [];
|
|
1362
|
+
let v;
|
|
1363
|
+
for (const l of e) {
|
|
1364
|
+
p.push(...((d = l.extend) == null ? void 0 : d.eca) || []);
|
|
1365
|
+
const h = l.sample.hours, k = l.sample.wps, S = l.sample.days, D = h.at(0);
|
|
1366
|
+
v && (D.distanceFromPrevious = v.distanceFromPrevious, D.distanceFromStart = v.distanceFromStart, h.forEach((x, T) => {
|
|
1367
|
+
T && (x.distanceFromStart = x.distanceFromStart + v.distanceFromStart);
|
|
1368
|
+
}), k.at(0).distanceFromPrevious = v.distanceFromPrevious, k.at(0).distanceFromStart = v.distanceFromStart, k.forEach((x, T) => {
|
|
1369
|
+
T && (x.distanceFromStart = x.distanceFromStart + v.distanceFromStart);
|
|
1370
|
+
}), S.at(0).distanceFromPrevious = v.distanceFromPrevious, S.at(0).distanceFromStart = v.distanceFromStart, S.forEach((x, T) => {
|
|
1371
|
+
T && (x.distanceFromStart = x.distanceFromStart + v.distanceFromStart);
|
|
1372
|
+
})), D.cp = l.cost.cp;
|
|
1373
|
+
const P = [l.etd, l.eta], N = I.findIndex((x) => x.id === D.cp.id);
|
|
1374
|
+
N === -1 ? (D.cp.segment = [P], I.push(D.cp)) : I[N].segment.push(P), h.forEach((x) => {
|
|
1375
|
+
var q;
|
|
1376
|
+
((q = a.hours) == null ? void 0 : q.findIndex((R) => R.eta === x.eta)) === -1 && a.hours.push(x);
|
|
1377
|
+
}), k.forEach((x) => {
|
|
1378
|
+
var q;
|
|
1379
|
+
((q = a.wps) == null ? void 0 : q.findIndex((R) => R.eta === x.eta)) === -1 && a.wps.push(x);
|
|
1380
|
+
}), S.forEach((x) => {
|
|
1381
|
+
var q;
|
|
1382
|
+
((q = a == null ? void 0 : a.days) == null ? void 0 : q.findIndex((R) => R.eta === x.eta)) === -1 && a.days.push(x);
|
|
1288
1383
|
});
|
|
1289
|
-
const A = (
|
|
1290
|
-
A === -1 ? a.wps.push(D) : a.wps[A] = D,
|
|
1384
|
+
const A = (g = a.wps) == null ? void 0 : g.findIndex((x) => x.eta === D.eta);
|
|
1385
|
+
A === -1 ? a.wps.push(D) : a.wps[A] = D, v = h.at(-1);
|
|
1291
1386
|
}
|
|
1292
|
-
return a.wps.sort((
|
|
1293
|
-
|
|
1294
|
-
}), a.wps.forEach((
|
|
1295
|
-
const
|
|
1296
|
-
if (
|
|
1297
|
-
const
|
|
1298
|
-
|
|
1299
|
-
const
|
|
1300
|
-
|
|
1387
|
+
return a.wps.sort((l, h) => {
|
|
1388
|
+
w(l.etd).unix() - w(h.etd).unix();
|
|
1389
|
+
}), a.wps.forEach((l, h) => {
|
|
1390
|
+
const k = a.wps[h - 1];
|
|
1391
|
+
if (k) {
|
|
1392
|
+
const S = l.distanceFromStart - (k.distanceFromStart || 0), D = w(l.eta || l.etd).diff(w(k.etd || k.eta), "hour", !0), P = Math.round(S / D * 100) / 100;
|
|
1393
|
+
l.avgSpd = P;
|
|
1394
|
+
const N = W.calculateBearing(k, l);
|
|
1395
|
+
k.bearing = N;
|
|
1301
1396
|
}
|
|
1302
1397
|
}), {
|
|
1303
1398
|
sample: a,
|
|
1304
|
-
etd:
|
|
1305
|
-
eta:
|
|
1306
|
-
from:
|
|
1307
|
-
to:
|
|
1308
|
-
v0:
|
|
1399
|
+
etd: e.at(0).etd,
|
|
1400
|
+
eta: e.at(-1).eta,
|
|
1401
|
+
from: e.at(0).from,
|
|
1402
|
+
to: e.at(-1).to,
|
|
1403
|
+
v0: e.at(0).v0,
|
|
1309
1404
|
label: "Combined",
|
|
1310
1405
|
distance: Math.round(i * 1e3) / 1e3,
|
|
1311
1406
|
totalHrs: Math.round(n * 1e3) / 1e3,
|
|
1312
1407
|
avgSpeed: Math.round(i / n * 1e3) / 1e3,
|
|
1313
|
-
wxFactor: Math.round(
|
|
1314
|
-
cFactor: Math.round(
|
|
1315
|
-
totalFoCons: Math.round(
|
|
1316
|
-
totalDgoCons: Math.round(
|
|
1408
|
+
wxFactor: Math.round(c * 1e3) / 1e3,
|
|
1409
|
+
cFactor: Math.round(u * 1e3) / 1e3,
|
|
1410
|
+
totalFoCons: Math.round(m * 1e3) / 1e3,
|
|
1411
|
+
totalDgoCons: Math.round(f * 1e3) / 1e3,
|
|
1317
1412
|
cost: {
|
|
1318
1413
|
total: Math.round(b * 1e3) / 1e3,
|
|
1319
|
-
hire: Math.round(
|
|
1320
|
-
bunker: Math.round(
|
|
1414
|
+
hire: Math.round(y * 1e3) / 1e3,
|
|
1415
|
+
bunker: Math.round(F * 1e3) / 1e3
|
|
1321
1416
|
},
|
|
1322
1417
|
extend: {
|
|
1323
|
-
cps:
|
|
1418
|
+
cps: I,
|
|
1324
1419
|
eca: p,
|
|
1325
1420
|
distanceInECA: Math.round(o * 1e3) / 1e3,
|
|
1326
1421
|
hoursInECA: Math.round(s * 1e3) / 1e3,
|
|
1327
|
-
totalDgoConsInECA: Math.round(
|
|
1328
|
-
speeds:
|
|
1422
|
+
totalDgoConsInECA: Math.round(r * 1e3) / 1e3,
|
|
1423
|
+
speeds: e
|
|
1329
1424
|
}
|
|
1330
1425
|
};
|
|
1331
1426
|
}
|
|
@@ -1333,14 +1428,14 @@ class O {
|
|
|
1333
1428
|
export {
|
|
1334
1429
|
st as AISImpl,
|
|
1335
1430
|
yt as AlertHelper,
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1431
|
+
ft as AlertLevel,
|
|
1432
|
+
Et as HifleetImpl,
|
|
1433
|
+
bt as LoadCondition,
|
|
1434
|
+
Tt as MyShipImpl,
|
|
1435
|
+
jt as MyVesselImpl,
|
|
1436
|
+
Nt as ShipxyImpl,
|
|
1342
1437
|
O as SpeedHelper,
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1438
|
+
vt as SpeedLabel,
|
|
1439
|
+
gt as VesselTag,
|
|
1440
|
+
xt as alertHelper
|
|
1346
1441
|
};
|