@idm-plugin/vessel 1.5.8 → 1.6.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/index.js +711 -517
- package/dist/index.umd.cjs +1 -1
- package/dist/speed/src/index.d.ts +119 -33
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,157 +1,157 @@
|
|
|
1
1
|
var st = Object.defineProperty;
|
|
2
|
-
var at = (
|
|
3
|
-
var Z = (
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import { LngLatHelper as
|
|
2
|
+
var at = (j, e, t) => e in j ? st(j, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : j[e] = t;
|
|
3
|
+
var Z = (j, e, t) => (at(j, typeof e != "symbol" ? e + "" : e, t), t);
|
|
4
|
+
import L from "got";
|
|
5
|
+
import Q from "@log4js-node/log4js-api";
|
|
6
|
+
import I from "moment";
|
|
7
|
+
import { LngLatHelper as z, LaneHelper as B } from "@idm-plugin/geo";
|
|
8
8
|
import { MeteoHelper2 as ot, MeteoHelper as nt } from "@idm-plugin/meteo2";
|
|
9
9
|
import { Meteo2Assist as tt } from "@idm-plugin/meteo";
|
|
10
|
-
let
|
|
10
|
+
let b;
|
|
11
11
|
try {
|
|
12
|
-
|
|
12
|
+
b = Q.getLogger("vessel");
|
|
13
13
|
} catch {
|
|
14
14
|
} finally {
|
|
15
15
|
}
|
|
16
|
-
class
|
|
16
|
+
class U {
|
|
17
17
|
/**
|
|
18
18
|
* 解析AIS状态码
|
|
19
19
|
* @param status
|
|
20
20
|
*/
|
|
21
|
-
parseStatus(
|
|
22
|
-
let t,
|
|
23
|
-
switch (
|
|
21
|
+
parseStatus(e) {
|
|
22
|
+
let t, o;
|
|
23
|
+
switch (e) {
|
|
24
24
|
case 0:
|
|
25
|
-
t = "在航(主机推动)",
|
|
25
|
+
t = "在航(主机推动)", o = "The engine is in use";
|
|
26
26
|
break;
|
|
27
27
|
case 1:
|
|
28
|
-
t = "锚泊",
|
|
28
|
+
t = "锚泊", o = "Anchored";
|
|
29
29
|
break;
|
|
30
30
|
case 2:
|
|
31
|
-
t = "失控",
|
|
31
|
+
t = "失控", o = "Not operated";
|
|
32
32
|
break;
|
|
33
33
|
case 3:
|
|
34
|
-
t = "操纵受限",
|
|
34
|
+
t = "操纵受限", o = "Limited airworthiness";
|
|
35
35
|
break;
|
|
36
36
|
case 4:
|
|
37
|
-
t = "吃水受限",
|
|
37
|
+
t = "吃水受限", o = "Limited by ship's draft";
|
|
38
38
|
break;
|
|
39
39
|
case 5:
|
|
40
|
-
t = "靠泊",
|
|
40
|
+
t = "靠泊", o = "Mooring";
|
|
41
41
|
break;
|
|
42
42
|
case 6:
|
|
43
|
-
t = "搁浅",
|
|
43
|
+
t = "搁浅", o = "Stranded";
|
|
44
44
|
break;
|
|
45
45
|
case 7:
|
|
46
|
-
t = "捕捞作业",
|
|
46
|
+
t = "捕捞作业", o = "Engaged in fishing";
|
|
47
47
|
break;
|
|
48
48
|
case 8:
|
|
49
|
-
t = "靠帆船提供动力",
|
|
49
|
+
t = "靠帆船提供动力", o = "Sailing";
|
|
50
50
|
break;
|
|
51
51
|
default:
|
|
52
|
-
t = "未定义",
|
|
52
|
+
t = "未定义", o = "Undefined";
|
|
53
53
|
}
|
|
54
|
-
return { labelCn: t, labelEn:
|
|
54
|
+
return { labelCn: t, labelEn: o };
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
|
-
class
|
|
58
|
-
constructor(t,
|
|
57
|
+
class wt extends U {
|
|
58
|
+
constructor(t, o) {
|
|
59
59
|
super();
|
|
60
60
|
Z(this, "clientId");
|
|
61
61
|
Z(this, "clientSecret");
|
|
62
62
|
Z(this, "token");
|
|
63
|
-
this.clientId = t, this.clientSecret =
|
|
63
|
+
this.clientId = t, this.clientSecret = o;
|
|
64
64
|
}
|
|
65
65
|
async authToken(t = {}) {
|
|
66
|
-
const
|
|
66
|
+
const o = "https://svc.data.myvessel.cn/ada/oauth/token", i = {
|
|
67
67
|
searchParams: {
|
|
68
68
|
client_id: this.clientId,
|
|
69
69
|
client_secret: this.clientSecret,
|
|
70
70
|
grant_type: "client_credentials"
|
|
71
71
|
}
|
|
72
|
-
},
|
|
73
|
-
|
|
74
|
-
accessToken:
|
|
75
|
-
tokenType:
|
|
76
|
-
expiresIn:
|
|
77
|
-
scope:
|
|
78
|
-
jti:
|
|
79
|
-
issuedAt:
|
|
72
|
+
}, a = await L.post(o, i).json();
|
|
73
|
+
b == null || b.info("[%s] fetch access token from: %s - %j", t.requestId, o, a), a.error || (this.token = {
|
|
74
|
+
accessToken: a.access_token,
|
|
75
|
+
tokenType: a.token_type,
|
|
76
|
+
expiresIn: a.expires_in,
|
|
77
|
+
scope: a.scope,
|
|
78
|
+
jti: a.jti,
|
|
79
|
+
issuedAt: I().utc().format()
|
|
80
80
|
});
|
|
81
81
|
}
|
|
82
|
-
async realTimePosition(t,
|
|
83
|
-
var
|
|
84
|
-
(!this.token ||
|
|
85
|
-
const
|
|
82
|
+
async realTimePosition(t, o = {}) {
|
|
83
|
+
var l, m, f;
|
|
84
|
+
(!this.token || I().diff(I(this.token.issuedAt), "seconds") > ((l = this.token) == null ? void 0 : l.expiresIn) - 300) && await this.authToken(o);
|
|
85
|
+
const i = "https://svc.data.myvessel.cn/sdc/v1/vessels/status/location/unit", a = {
|
|
86
86
|
headers: {
|
|
87
87
|
Authorization: `${(m = this.token) == null ? void 0 : m.tokenType} ${(f = this.token) == null ? void 0 : f.accessToken}`
|
|
88
88
|
},
|
|
89
89
|
searchParams: { mmsi: t }
|
|
90
90
|
};
|
|
91
|
-
|
|
92
|
-
const
|
|
93
|
-
if (
|
|
94
|
-
return
|
|
95
|
-
const
|
|
96
|
-
for (const
|
|
97
|
-
!isNaN(
|
|
98
|
-
const d =
|
|
91
|
+
b == null || b.info("[%s] fetch realtime position from: %s - %j", o.requestId, i, a);
|
|
92
|
+
const n = await L.get(i, a).json();
|
|
93
|
+
if (n.code)
|
|
94
|
+
return b == null || b.warn("[%s] fetch realtime position failed: %j", o.requestId, i, { message: n.message, status: n.status, code: n.code }), n;
|
|
95
|
+
const s = n.data;
|
|
96
|
+
for (const h in s)
|
|
97
|
+
!isNaN(s[h]) && Number(s[h]) !== 1 / 0 && (s[h] = Number(s[h]));
|
|
98
|
+
const d = I(`${s.postime} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
99
99
|
return {
|
|
100
|
-
mmsi:
|
|
101
|
-
name:
|
|
102
|
-
imo:
|
|
103
|
-
callSign:
|
|
104
|
-
lat:
|
|
105
|
-
lng:
|
|
106
|
-
length:
|
|
107
|
-
width:
|
|
108
|
-
draught:
|
|
109
|
-
sog:
|
|
110
|
-
cog:
|
|
111
|
-
hdg:
|
|
112
|
-
rot:
|
|
113
|
-
eta: /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(
|
|
114
|
-
destination:
|
|
100
|
+
mmsi: s.mmsi,
|
|
101
|
+
name: s.vesselName,
|
|
102
|
+
imo: s.imo,
|
|
103
|
+
callSign: s.callsign,
|
|
104
|
+
lat: s.lat,
|
|
105
|
+
lng: s.lon,
|
|
106
|
+
length: s.length,
|
|
107
|
+
width: s.width,
|
|
108
|
+
draught: s.currDraught,
|
|
109
|
+
sog: s.sog,
|
|
110
|
+
cog: s.cog,
|
|
111
|
+
hdg: s.hdg,
|
|
112
|
+
rot: s.rot,
|
|
113
|
+
eta: /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(s.eta) ? I.utc(s.eta).format() : void 0,
|
|
114
|
+
destination: s.dest,
|
|
115
115
|
positionTime: d.unix(),
|
|
116
|
-
status:
|
|
117
|
-
labelCn:
|
|
118
|
-
labelEn:
|
|
116
|
+
status: s.status,
|
|
117
|
+
labelCn: s.statusNameCn,
|
|
118
|
+
labelEn: s.statusNameEn,
|
|
119
119
|
method: "position",
|
|
120
120
|
vendor: "myVessel",
|
|
121
121
|
utc: d.utc().format()
|
|
122
122
|
};
|
|
123
123
|
}
|
|
124
|
-
async trajectory(t, i,
|
|
125
|
-
(!this.token ||
|
|
126
|
-
const d = await this.realTimePosition(t,
|
|
127
|
-
for (;
|
|
128
|
-
await this.trajectoryIn30Day(t, r, r.clone().add(30, "day"), d,
|
|
129
|
-
return await this.trajectoryIn30Day(t, r,
|
|
124
|
+
async trajectory(t, o, i, a, n = !0, s = {}) {
|
|
125
|
+
(!this.token || I().diff(I(this.token.issuedAt), "seconds") > this.token.expiresIn - 300) && await this.authToken(s);
|
|
126
|
+
const d = await this.realTimePosition(t, s), r = I(o), l = I(i), m = [];
|
|
127
|
+
for (; l.diff(r, "day", !0) > 30; )
|
|
128
|
+
await this.trajectoryIn30Day(t, r, r.clone().add(30, "day"), d, a, m, s), r.add(30, "day");
|
|
129
|
+
return await this.trajectoryIn30Day(t, r, l, d, a, m, s), m;
|
|
130
130
|
}
|
|
131
|
-
async trajectoryIn30Day(t, i,
|
|
132
|
-
var
|
|
133
|
-
const r = "https://svc.data.myvessel.cn/sdc/v1/vessels/status/track",
|
|
131
|
+
async trajectoryIn30Day(t, o, i, a, n, s, d = {}) {
|
|
132
|
+
var u, p, k, y, w;
|
|
133
|
+
const r = "https://svc.data.myvessel.cn/sdc/v1/vessels/status/track", l = {
|
|
134
134
|
headers: {
|
|
135
|
-
Authorization: `${(
|
|
135
|
+
Authorization: `${(u = this.token) == null ? void 0 : u.tokenType} ${(p = this.token) == null ? void 0 : p.accessToken}`
|
|
136
136
|
},
|
|
137
137
|
json: {
|
|
138
138
|
mmsi: t,
|
|
139
|
-
startTime:
|
|
140
|
-
endTime:
|
|
139
|
+
startTime: o.utcOffset(8).format("YYYY-MM-DD HH:mm:ss"),
|
|
140
|
+
endTime: i.utcOffset(8).format("YYYY-MM-DD HH:mm:ss")
|
|
141
141
|
}
|
|
142
142
|
};
|
|
143
|
-
|
|
144
|
-
const m = await
|
|
143
|
+
b == null || b.info("[%s] fetch trajectory from: %s - %j", d.requestId, r, l);
|
|
144
|
+
const m = await L.post(r, l).json();
|
|
145
145
|
if (m.code)
|
|
146
|
-
return
|
|
146
|
+
return b == null || b.warn("[%s] fetch trajectory failed: %j", d.requestId, r, { message: m.message, status: m.status, code: m.code }), m;
|
|
147
147
|
let f = -1;
|
|
148
|
-
const
|
|
149
|
-
return (
|
|
150
|
-
for (const
|
|
151
|
-
!isNaN(c[
|
|
152
|
-
const
|
|
148
|
+
const h = I(`${(y = (k = m.data) == null ? void 0 : k[0]) == null ? void 0 : y.postime} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
149
|
+
return (w = m.data) == null || w.forEach((c) => {
|
|
150
|
+
for (const C in c)
|
|
151
|
+
!isNaN(c[C]) && Number(c[C]) !== 1 / 0 && (c[C] = Number(c[C]));
|
|
152
|
+
const M = I(`${c.postime} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00"), D = c.status, { labelCn: g, labelEn: Y } = this.parseStatus(D), S = {
|
|
153
153
|
mmsi: c.mmsi,
|
|
154
|
-
imo:
|
|
154
|
+
imo: a == null ? void 0 : a.imo,
|
|
155
155
|
lat: c.lat,
|
|
156
156
|
lng: c.lon,
|
|
157
157
|
sog: c.sog,
|
|
@@ -159,68 +159,68 @@ class bt extends K {
|
|
|
159
159
|
hdg: c.hdg,
|
|
160
160
|
draught: c.draught,
|
|
161
161
|
status: D,
|
|
162
|
-
eta: /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(c.eta) ?
|
|
162
|
+
eta: /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(c.eta) ? I(`${c.eta} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00").utc().format() : void 0,
|
|
163
163
|
destination: c.dest,
|
|
164
|
-
positionTime:
|
|
165
|
-
labelCn:
|
|
166
|
-
labelEn:
|
|
164
|
+
positionTime: M.unix(),
|
|
165
|
+
labelCn: g,
|
|
166
|
+
labelEn: Y,
|
|
167
167
|
method: "trajectory",
|
|
168
168
|
vendor: "myVessel",
|
|
169
|
-
utc:
|
|
170
|
-
},
|
|
171
|
-
|
|
172
|
-
}),
|
|
169
|
+
utc: M.utc().format()
|
|
170
|
+
}, x = Math.floor(M.diff(h, "minute", !0) / (n || 1));
|
|
171
|
+
x !== f && (f = x, s.push(S));
|
|
172
|
+
}), s;
|
|
173
173
|
}
|
|
174
174
|
}
|
|
175
|
-
class
|
|
175
|
+
class gt extends U {
|
|
176
176
|
constructor(t) {
|
|
177
177
|
super();
|
|
178
178
|
Z(this, "token");
|
|
179
179
|
this.token = t;
|
|
180
180
|
}
|
|
181
|
-
async realTimePosition(t,
|
|
182
|
-
const
|
|
181
|
+
async realTimePosition(t, o = {}) {
|
|
182
|
+
const i = "https://api.hifleet.com/position/position/get/token", a = {
|
|
183
183
|
searchParams: {
|
|
184
184
|
mmsi: t,
|
|
185
185
|
usertoken: this.token
|
|
186
186
|
}
|
|
187
|
-
},
|
|
188
|
-
|
|
189
|
-
const
|
|
190
|
-
if (!
|
|
191
|
-
return
|
|
192
|
-
for (const
|
|
193
|
-
!isNaN(
|
|
194
|
-
|
|
195
|
-
const d =
|
|
187
|
+
}, n = await L.post(i, a).json();
|
|
188
|
+
b == null || b.info("[%s] fetch realtime position from: %s - %j", o.requestId, i, a);
|
|
189
|
+
const s = n == null ? void 0 : n.list;
|
|
190
|
+
if (!s)
|
|
191
|
+
return b == null || b.warn("[%s] fetch realtime position failed: %j", o.requestId, i, n), n;
|
|
192
|
+
for (const h in s)
|
|
193
|
+
!isNaN(s[h]) && Number(s[h]) !== 1 / 0 && (s[h] = Number(s[h]));
|
|
194
|
+
s.status = s.sp > 3 ? 0 : 1;
|
|
195
|
+
const d = s.status, { labelCn: r, labelEn: l } = this.parseStatus(d), m = I(`${s.ti} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
196
196
|
return {
|
|
197
|
-
mmsi:
|
|
198
|
-
name:
|
|
199
|
-
imo:
|
|
200
|
-
callSign:
|
|
201
|
-
lat: Math.round(
|
|
202
|
-
lng: Math.round(
|
|
203
|
-
length:
|
|
204
|
-
width:
|
|
205
|
-
draught:
|
|
206
|
-
sog:
|
|
207
|
-
cog:
|
|
208
|
-
hdg:
|
|
209
|
-
rot: isNaN(
|
|
210
|
-
eta: /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(
|
|
211
|
-
destination:
|
|
197
|
+
mmsi: s.m,
|
|
198
|
+
name: s.n,
|
|
199
|
+
imo: s.imonumber,
|
|
200
|
+
callSign: s.callsign,
|
|
201
|
+
lat: Math.round(s.la / 60 * 1e5) / 1e5,
|
|
202
|
+
lng: Math.round(s.lo / 60 * 1e5) / 1e5,
|
|
203
|
+
length: s.l,
|
|
204
|
+
width: s.w,
|
|
205
|
+
draught: s.draught,
|
|
206
|
+
sog: s.sp,
|
|
207
|
+
cog: s.co,
|
|
208
|
+
hdg: s.h,
|
|
209
|
+
rot: isNaN(s.rot) ? 0 : s.rot,
|
|
210
|
+
eta: /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(s.eta) ? I.utc(s.eta).format() : void 0,
|
|
211
|
+
destination: s.destination,
|
|
212
212
|
positionTime: m.unix(),
|
|
213
213
|
utc: m.utc().format(),
|
|
214
214
|
status: d,
|
|
215
215
|
labelCn: r,
|
|
216
|
-
labelEn:
|
|
216
|
+
labelEn: l,
|
|
217
217
|
method: "position",
|
|
218
218
|
vendor: "hifleet"
|
|
219
219
|
};
|
|
220
220
|
}
|
|
221
|
-
async search(t,
|
|
222
|
-
let
|
|
223
|
-
const
|
|
221
|
+
async search(t, o = {}) {
|
|
222
|
+
let i = "https://www.hifleet.com/hifleetapi/searchVesselOL.do";
|
|
223
|
+
const a = {
|
|
224
224
|
searchParams: {
|
|
225
225
|
keyword: t
|
|
226
226
|
},
|
|
@@ -230,24 +230,24 @@ class vt extends K {
|
|
|
230
230
|
Host: "www.hifleet.com"
|
|
231
231
|
}
|
|
232
232
|
};
|
|
233
|
-
let
|
|
234
|
-
|
|
235
|
-
for (const d in
|
|
236
|
-
!isNaN(
|
|
237
|
-
const
|
|
238
|
-
mmsi:
|
|
239
|
-
name:
|
|
240
|
-
imo:
|
|
241
|
-
callSign:
|
|
242
|
-
length:
|
|
243
|
-
breadth:
|
|
244
|
-
draught:
|
|
245
|
-
type:
|
|
233
|
+
let n = await L.post(i, a).json();
|
|
234
|
+
b == null || b.info("[%s] fetch vessel props from: %s - %j", o.requestId, i, a), n instanceof Array && (n = n[0]);
|
|
235
|
+
for (const d in n)
|
|
236
|
+
!isNaN(n[d]) && Number(n[d]) !== 1 / 0 && (n[d] = Number(n[d]));
|
|
237
|
+
const s = {
|
|
238
|
+
mmsi: n.m,
|
|
239
|
+
name: n.n,
|
|
240
|
+
imo: n.i,
|
|
241
|
+
callSign: n.c,
|
|
242
|
+
length: n.l,
|
|
243
|
+
breadth: n.b,
|
|
244
|
+
draught: n.dr,
|
|
245
|
+
type: n.t
|
|
246
246
|
};
|
|
247
|
-
return
|
|
247
|
+
return i = "https://www.hifleet.com/hifleetapi/sameShipSearch.do", n = await L.post(i, a).json(), b == null || b.info("[%s] search vessel dead weight from: %s - %j", o.requestId, i, a), n instanceof Array && (n = n[0]), n && (s.deadweight = Number(n.dwt)), s;
|
|
248
248
|
}
|
|
249
|
-
async suggest(t,
|
|
250
|
-
const
|
|
249
|
+
async suggest(t, o = {}) {
|
|
250
|
+
const i = "https://www.hifleet.com/hifleetapi/getShipSuggest.do", a = {
|
|
251
251
|
searchParams: {
|
|
252
252
|
q: t
|
|
253
253
|
},
|
|
@@ -256,203 +256,203 @@ class vt extends K {
|
|
|
256
256
|
Origin: "https://www.hifleet.com",
|
|
257
257
|
Host: "www.hifleet.com"
|
|
258
258
|
}
|
|
259
|
-
},
|
|
260
|
-
|
|
261
|
-
const
|
|
262
|
-
for (const d of
|
|
263
|
-
|
|
259
|
+
}, n = await L.post(i, a).json();
|
|
260
|
+
b == null || b.info("[%s] suggest vessel props from: %s - %j", o.requestId, i, a);
|
|
261
|
+
const s = [];
|
|
262
|
+
for (const d of n)
|
|
263
|
+
s.push({
|
|
264
264
|
mmsi: !d.mmsi || isNaN(d.mmsi) ? null : Number(d.mmsi),
|
|
265
265
|
name: d.name,
|
|
266
266
|
callSign: d.callsign,
|
|
267
267
|
imo: !d.imo || isNaN(d.imo) ? null : Number(d.imo),
|
|
268
268
|
score: d._score
|
|
269
269
|
});
|
|
270
|
-
return
|
|
270
|
+
return s.sort((d, r) => r.score - d.score), s;
|
|
271
271
|
}
|
|
272
|
-
async trajectory(t, i,
|
|
273
|
-
var c,
|
|
274
|
-
const d = await this.realTimePosition(t,
|
|
275
|
-
let r =
|
|
276
|
-
const
|
|
277
|
-
if (
|
|
278
|
-
let
|
|
279
|
-
|
|
272
|
+
async trajectory(t, o, i, a, n = !0, s = {}) {
|
|
273
|
+
var c, M, D;
|
|
274
|
+
const d = await this.realTimePosition(t, s);
|
|
275
|
+
let r = I(o);
|
|
276
|
+
const l = I(i), m = I();
|
|
277
|
+
if (n) {
|
|
278
|
+
let g = l.diff(r, "d", !0);
|
|
279
|
+
g < 0 ? r = l.clone().subtract(40, "d") : g < 30 ? r.subtract(10, "d") : g < 60 ? r.subtract(5, "d") : r = l.clone().subtract(80, "d"), g = m.diff(l, "d", !0), l.add(g > 10 ? 240 : g * 24, "h");
|
|
280
280
|
}
|
|
281
281
|
const f = {
|
|
282
282
|
searchParams: {
|
|
283
|
-
endtime:
|
|
283
|
+
endtime: l.utcOffset("+8:00").format("YYYY-MM-DD HH:mm:ss"),
|
|
284
284
|
starttime: r.utcOffset("+8:00").format("YYYY-MM-DD HH:mm:ss"),
|
|
285
285
|
mmsi: t,
|
|
286
286
|
usertoken: this.token
|
|
287
287
|
}
|
|
288
|
-
},
|
|
289
|
-
|
|
290
|
-
let
|
|
291
|
-
|
|
288
|
+
}, h = "https://api.hifleet.com/position/trajectory/nocompressed/withstatic/token", u = await L.get(h, f).json();
|
|
289
|
+
b == null || b.info("[%s] fetch trajectory from: %s - %j", s.requestId, h, f);
|
|
290
|
+
let p;
|
|
291
|
+
u && (p = ((M = (c = u.ships) == null ? void 0 : c.offors) == null ? void 0 : M.ship) || [], p.length || b == null || b.warn("[%s] fetch trajectory failed: %j", s.requestId, u));
|
|
292
292
|
const k = [];
|
|
293
|
-
let
|
|
294
|
-
const
|
|
295
|
-
for (const
|
|
296
|
-
for (const
|
|
297
|
-
!isNaN(
|
|
298
|
-
const
|
|
299
|
-
|
|
300
|
-
const { labelEn:
|
|
301
|
-
mmsi:
|
|
302
|
-
name:
|
|
293
|
+
let y = -1;
|
|
294
|
+
const w = I(`${(D = p == null ? void 0 : p[0]) == null ? void 0 : D.ti} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
295
|
+
for (const g of p) {
|
|
296
|
+
for (const q in g)
|
|
297
|
+
!isNaN(g[q]) && Number(g[q]) !== 1 / 0 && (g[q] = Number(g[q]));
|
|
298
|
+
const Y = I(`${g.ti} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
|
|
299
|
+
g.status = g.sp > 4 ? 0 : 1;
|
|
300
|
+
const { labelEn: S, labelCn: x } = this.parseStatus(g.status), C = {
|
|
301
|
+
mmsi: g.m,
|
|
302
|
+
name: g.n,
|
|
303
303
|
imo: d == null ? void 0 : d.imo,
|
|
304
|
-
lat:
|
|
305
|
-
lng:
|
|
306
|
-
draught:
|
|
307
|
-
sog:
|
|
308
|
-
cog:
|
|
309
|
-
hdg:
|
|
310
|
-
positionTime:
|
|
311
|
-
utc:
|
|
312
|
-
status:
|
|
313
|
-
labelCn:
|
|
314
|
-
labelEn:
|
|
304
|
+
lat: g.la,
|
|
305
|
+
lng: g.lo,
|
|
306
|
+
draught: g.draught,
|
|
307
|
+
sog: g.sp,
|
|
308
|
+
cog: g.co,
|
|
309
|
+
hdg: g.hdg,
|
|
310
|
+
positionTime: Y.unix(),
|
|
311
|
+
utc: Y.utc().format(),
|
|
312
|
+
status: g.status,
|
|
313
|
+
labelCn: x,
|
|
314
|
+
labelEn: S,
|
|
315
315
|
method: "trajectory",
|
|
316
316
|
vendor: "hifleet"
|
|
317
|
-
},
|
|
318
|
-
|
|
317
|
+
}, A = Math.floor(Y.diff(w, "minute", !0) / (a || 1));
|
|
318
|
+
A !== y && (y = A, k.push(C));
|
|
319
319
|
}
|
|
320
320
|
return k;
|
|
321
321
|
}
|
|
322
322
|
}
|
|
323
|
-
class
|
|
323
|
+
class It extends U {
|
|
324
324
|
constructor(t) {
|
|
325
325
|
super();
|
|
326
326
|
Z(this, "token");
|
|
327
327
|
this.token = t;
|
|
328
328
|
}
|
|
329
|
-
async realTimePosition(t,
|
|
330
|
-
const
|
|
329
|
+
async realTimePosition(t, o = {}) {
|
|
330
|
+
const i = {
|
|
331
331
|
searchParams: {
|
|
332
332
|
id: t,
|
|
333
333
|
k: this.token,
|
|
334
334
|
enc: 1
|
|
335
335
|
}
|
|
336
|
-
},
|
|
337
|
-
if (
|
|
338
|
-
return
|
|
339
|
-
const
|
|
340
|
-
for (const f in
|
|
341
|
-
!isNaN(
|
|
342
|
-
const { labelCn: d, labelEn: r } = await this.parseStatus(
|
|
336
|
+
}, a = "https://api.shipxy.com/apicall/GetSingleShip", n = await L.get(a, i).json();
|
|
337
|
+
if (b == null || b.info("[%s] fetch realtime position from: %s - %j", o.requestId, a, i), (n == null ? void 0 : n.status) !== 0)
|
|
338
|
+
return n;
|
|
339
|
+
const s = n.data[0];
|
|
340
|
+
for (const f in s)
|
|
341
|
+
!isNaN(s[f]) && Number(s[f]) !== 1 / 0 && (s[f] = Number(s[f]));
|
|
342
|
+
const { labelCn: d, labelEn: r } = await this.parseStatus(s.navistat), l = I.unix(s.lasttime);
|
|
343
343
|
return {
|
|
344
|
-
mmsi:
|
|
345
|
-
name:
|
|
346
|
-
imo:
|
|
347
|
-
callSign:
|
|
348
|
-
lat: Math.round(
|
|
349
|
-
lng: Math.round(
|
|
350
|
-
length: Math.round(
|
|
351
|
-
width: Math.round(
|
|
352
|
-
draught: Math.round(
|
|
353
|
-
sog: Math.round(
|
|
354
|
-
cog: Math.round(
|
|
355
|
-
hdg: Math.round(
|
|
356
|
-
rot: Math.round(
|
|
357
|
-
positionTime:
|
|
358
|
-
utc:
|
|
359
|
-
status:
|
|
344
|
+
mmsi: s.ShipID,
|
|
345
|
+
name: s.name,
|
|
346
|
+
imo: s.imo,
|
|
347
|
+
callSign: s.callsign,
|
|
348
|
+
lat: Math.round(s.lat / 1e6 * 1e5) / 1e5,
|
|
349
|
+
lng: Math.round(s.lon / 1e6 * 1e5) / 1e5,
|
|
350
|
+
length: Math.round(s.length / 10 * 100) / 100,
|
|
351
|
+
width: Math.round(s.width / 10 * 100) / 100,
|
|
352
|
+
draught: Math.round(s.draught / 1e3 * 100) / 100,
|
|
353
|
+
sog: Math.round(s.sog * 3600 / 1e3 / 1852 * 100) / 100,
|
|
354
|
+
cog: Math.round(s.cog / 100 * 100) / 100,
|
|
355
|
+
hdg: Math.round(s.hdg / 100 * 100) / 100,
|
|
356
|
+
rot: Math.round(s.rot / 100 * 100) / 100,
|
|
357
|
+
positionTime: s.lasttime,
|
|
358
|
+
utc: l.utc().format(),
|
|
359
|
+
status: s.navistat,
|
|
360
360
|
labelEn: r,
|
|
361
361
|
labelCn: d,
|
|
362
362
|
method: "position",
|
|
363
363
|
vendor: "shipxy"
|
|
364
364
|
};
|
|
365
365
|
}
|
|
366
|
-
async trajectory(t, i,
|
|
367
|
-
var
|
|
368
|
-
const d = await this.realTimePosition(t,
|
|
366
|
+
async trajectory(t, o, i, a, n = !0, s = {}) {
|
|
367
|
+
var w;
|
|
368
|
+
const d = await this.realTimePosition(t, s), r = I(o), l = I(i), m = "https://api.shipxy.com/apicall/GetShipTrack", f = {
|
|
369
369
|
searchParams: {
|
|
370
370
|
id: t,
|
|
371
371
|
k: this.token,
|
|
372
372
|
enc: 1,
|
|
373
373
|
cut: 0,
|
|
374
374
|
btm: r.unix(),
|
|
375
|
-
etm:
|
|
375
|
+
etm: l.unix()
|
|
376
376
|
}
|
|
377
|
-
},
|
|
378
|
-
if (
|
|
379
|
-
return
|
|
380
|
-
const
|
|
381
|
-
let
|
|
382
|
-
for (const c of
|
|
383
|
-
const
|
|
377
|
+
}, h = await L.get(m, f).json();
|
|
378
|
+
if (b == null || b.info("[%s] fetch trajectory from: %s - %j", s.requestId, m, f), (h == null ? void 0 : h.status) !== 0)
|
|
379
|
+
return h;
|
|
380
|
+
const u = h == null ? void 0 : h.points, p = [], k = I.unix((w = u[0]) == null ? void 0 : w.utc);
|
|
381
|
+
let y = -1;
|
|
382
|
+
for (const c of u) {
|
|
383
|
+
const M = I.unix(c.utc), D = {
|
|
384
384
|
imo: d == null ? void 0 : d.imo,
|
|
385
385
|
mmsi: t,
|
|
386
386
|
sog: Math.round(c.sog * 3600 / 1e3 / 1852 * 100) / 100,
|
|
387
387
|
cog: Math.round(c.cog / 100 * 100) / 100,
|
|
388
388
|
lat: Math.round(c.lat / 1e6 * 1e5) / 1e5,
|
|
389
389
|
lng: Math.round(c.lon / 1e6 * 1e5) / 1e5,
|
|
390
|
-
positionTime:
|
|
391
|
-
utc:
|
|
390
|
+
positionTime: M.unix(),
|
|
391
|
+
utc: M.utc().format(),
|
|
392
392
|
method: "trajectory",
|
|
393
393
|
vendor: "shipxy"
|
|
394
|
-
},
|
|
395
|
-
|
|
394
|
+
}, g = Math.floor(M.diff(k, "minute", !0) / (a || 1));
|
|
395
|
+
g !== y && (y = g, p.push(D));
|
|
396
396
|
}
|
|
397
|
-
return
|
|
397
|
+
return p;
|
|
398
398
|
}
|
|
399
399
|
}
|
|
400
|
-
class
|
|
400
|
+
class pt extends U {
|
|
401
401
|
constructor(t) {
|
|
402
402
|
super();
|
|
403
403
|
Z(this, "token");
|
|
404
404
|
this.token = t;
|
|
405
405
|
}
|
|
406
|
-
async getShipId(t,
|
|
407
|
-
const
|
|
406
|
+
async getShipId(t, o = {}) {
|
|
407
|
+
const i = {
|
|
408
408
|
headers: {
|
|
409
409
|
appKey: this.token
|
|
410
410
|
},
|
|
411
411
|
json: {
|
|
412
412
|
mmsiList: t
|
|
413
413
|
}
|
|
414
|
-
},
|
|
415
|
-
return
|
|
414
|
+
}, a = "https://api3.myships.com/sp/ships/getShipIdByMMSI", n = await L.post(a, i).json();
|
|
415
|
+
return b == null || b.info("[%s] fetch ship id from: %s - %j", o.requestId, a, i), n.code !== "0" ? n : n.data[0].shipId;
|
|
416
416
|
}
|
|
417
|
-
async getShipInfo(t,
|
|
418
|
-
const
|
|
417
|
+
async getShipInfo(t, o = {}) {
|
|
418
|
+
const i = {
|
|
419
419
|
headers: {
|
|
420
420
|
appKey: this.token
|
|
421
421
|
},
|
|
422
422
|
json: {
|
|
423
423
|
shipId: t
|
|
424
424
|
}
|
|
425
|
-
},
|
|
426
|
-
if (
|
|
427
|
-
return
|
|
428
|
-
const
|
|
429
|
-
let d =
|
|
430
|
-
return t === "407170" && (d = "9198379",
|
|
431
|
-
mmsi:
|
|
432
|
-
name:
|
|
425
|
+
}, a = "https://api3.myships.com/sp/ships/aissta", n = await L.post(a, i).json();
|
|
426
|
+
if (b == null || b.info("[%s] fetch ship info from: %s - %j", o.requestId, a, i), n.code !== "0")
|
|
427
|
+
return n;
|
|
428
|
+
const s = n.data;
|
|
429
|
+
let d = s.imo;
|
|
430
|
+
return t === "407170" && (d = "9198379", b == null || b.warn("[%s] ship(%s) imo error: %s, should be %s", o.requestId, t, s.imo, d)), {
|
|
431
|
+
mmsi: s.mmsi,
|
|
432
|
+
name: s.shipnameEn,
|
|
433
433
|
imo: d,
|
|
434
|
-
callSign:
|
|
435
|
-
length:
|
|
436
|
-
width:
|
|
437
|
-
draught: (
|
|
434
|
+
callSign: s.callSign,
|
|
435
|
+
length: s.length,
|
|
436
|
+
width: s.breadth,
|
|
437
|
+
draught: (s.draught || 100) / 10
|
|
438
438
|
};
|
|
439
439
|
}
|
|
440
|
-
async realTimePosition(t,
|
|
441
|
-
const
|
|
440
|
+
async realTimePosition(t, o = {}) {
|
|
441
|
+
const i = await this.getShipId(t, o), a = await this.getShipInfo(i, o), n = {
|
|
442
442
|
headers: {
|
|
443
443
|
appKey: this.token
|
|
444
444
|
},
|
|
445
445
|
json: {
|
|
446
|
-
shipId:
|
|
446
|
+
shipId: i
|
|
447
447
|
}
|
|
448
|
-
},
|
|
449
|
-
|
|
448
|
+
}, s = "https://api3.myships.com/sp/ships/position/latest", d = await L.post(s, n).json();
|
|
449
|
+
b == null || b.info("[%s] fetch realtime position from: %s - %j", o.requestId, s, n);
|
|
450
450
|
const r = d.data[0];
|
|
451
|
-
for (const
|
|
452
|
-
!isNaN(r[
|
|
453
|
-
const { labelCn:
|
|
451
|
+
for (const u in r)
|
|
452
|
+
!isNaN(r[u]) && Number(r[u]) !== 1 / 0 && (r[u] = Number(r[u]));
|
|
453
|
+
const { labelCn: l, labelEn: m } = await this.parseStatus(r.aisNavStatus), f = I.unix(r.posTime);
|
|
454
454
|
return {
|
|
455
|
-
...
|
|
455
|
+
...a,
|
|
456
456
|
mmsi: t,
|
|
457
457
|
lat: Math.round(r.lat / 1e4 / 60 * 1e5) / 1e5,
|
|
458
458
|
lng: Math.round(r.lon / 1e4 / 60 * 1e5) / 1e5,
|
|
@@ -464,63 +464,63 @@ class Yt extends K {
|
|
|
464
464
|
utc: f.utc().format(),
|
|
465
465
|
status: r.aisNavStatus,
|
|
466
466
|
labelEn: m,
|
|
467
|
-
labelCn:
|
|
467
|
+
labelCn: l,
|
|
468
468
|
method: "position",
|
|
469
469
|
vendor: "myship"
|
|
470
470
|
};
|
|
471
471
|
}
|
|
472
|
-
async trajectory(t, i,
|
|
473
|
-
const d =
|
|
472
|
+
async trajectory(t, o, i, a, n = !0, s = {}) {
|
|
473
|
+
const d = I(o), r = I(i), l = await this.getShipId(t), m = await this.getShipInfo(l), f = [];
|
|
474
474
|
for (; r.diff(d, "day", !0) > 30; )
|
|
475
|
-
await this.trajectoryIn30Day(
|
|
476
|
-
return await this.trajectoryIn30Day(
|
|
475
|
+
await this.trajectoryIn30Day(l, d.unix(), d.add(30, "day").unix(), m, t, a, f);
|
|
476
|
+
return await this.trajectoryIn30Day(l, d.unix(), r.unix(), m, t, a, f), f;
|
|
477
477
|
}
|
|
478
|
-
async trajectoryIn30Day(t, i,
|
|
478
|
+
async trajectoryIn30Day(t, o, i, a, n, s, d, r = {}) {
|
|
479
479
|
var k;
|
|
480
|
-
const
|
|
480
|
+
const l = {
|
|
481
481
|
headers: {
|
|
482
482
|
appKey: this.token
|
|
483
483
|
},
|
|
484
484
|
json: {
|
|
485
485
|
shipId: t,
|
|
486
|
-
startTime:
|
|
487
|
-
endTime:
|
|
486
|
+
startTime: o,
|
|
487
|
+
endTime: i
|
|
488
488
|
}
|
|
489
|
-
}, m = "https://api3.myships.com/sp/ships/position/history", f = await
|
|
490
|
-
if (
|
|
491
|
-
return
|
|
492
|
-
const
|
|
493
|
-
for (const
|
|
494
|
-
!isNaN(
|
|
495
|
-
const
|
|
496
|
-
let
|
|
497
|
-
for (const
|
|
498
|
-
const
|
|
499
|
-
imo:
|
|
500
|
-
mmsi:
|
|
501
|
-
lat: Math.round(
|
|
502
|
-
lng: Math.round(
|
|
503
|
-
sog: Math.round(
|
|
504
|
-
cog: Math.round(
|
|
505
|
-
hdg: Math.round(
|
|
506
|
-
rot: Math.round(
|
|
507
|
-
positionTime:
|
|
508
|
-
utc:
|
|
489
|
+
}, m = "https://api3.myships.com/sp/ships/position/history", f = await L.post(m, l).json();
|
|
490
|
+
if (b == null || b.info("[%s] fetch trajectory from: %s - %j", r.requestId, m, l), f.code !== "0")
|
|
491
|
+
return b == null || b.warn("[%s] invoke myship trajectory failed: %j", r.requestId, f), f;
|
|
492
|
+
const h = f.data;
|
|
493
|
+
for (const y in h)
|
|
494
|
+
!isNaN(h[y]) && Number(h[y]) !== 1 / 0 && (h[y] = Number(h[y]));
|
|
495
|
+
const u = I.unix((k = h[0]) == null ? void 0 : k.posTime);
|
|
496
|
+
let p = -1;
|
|
497
|
+
for (const y of h) {
|
|
498
|
+
const w = I.unix(y.posTime), c = {
|
|
499
|
+
imo: a == null ? void 0 : a.imo,
|
|
500
|
+
mmsi: n,
|
|
501
|
+
lat: Math.round(y.lat / 1e4 / 60 * 1e5) / 1e5,
|
|
502
|
+
lng: Math.round(y.lon / 1e4 / 60 * 1e5) / 1e5,
|
|
503
|
+
sog: Math.round(y.sog / 10 * 100) / 100,
|
|
504
|
+
cog: Math.round(y.cog / 10 * 100) / 100,
|
|
505
|
+
hdg: Math.round(y.heading * 100) / 100,
|
|
506
|
+
rot: Math.round(y.rot * 100) / 100,
|
|
507
|
+
positionTime: w.unix(),
|
|
508
|
+
utc: w.utc().format(),
|
|
509
509
|
method: "trajectory",
|
|
510
510
|
vendor: "myship"
|
|
511
|
-
},
|
|
512
|
-
|
|
511
|
+
}, M = Math.floor(w.diff(u, "minute", !0) / (s || 1));
|
|
512
|
+
M !== p && (p = M, d.push(c));
|
|
513
513
|
}
|
|
514
514
|
return d;
|
|
515
515
|
}
|
|
516
516
|
}
|
|
517
|
-
let
|
|
517
|
+
let W;
|
|
518
518
|
try {
|
|
519
|
-
|
|
519
|
+
W = Q.getLogger("vessel");
|
|
520
520
|
} catch {
|
|
521
521
|
} finally {
|
|
522
522
|
}
|
|
523
|
-
var it = /* @__PURE__ */ ((
|
|
523
|
+
var it = /* @__PURE__ */ ((j) => (j.NOTICE = "NOTICE", j.WARN = "WARN", j.HEAVY = "HEAVY", j.SEVERE = "SEVERE", j.ERROR = "ERROR", j.FATAL = "FATAL", j))(it || {});
|
|
524
524
|
class rt {
|
|
525
525
|
/**
|
|
526
526
|
* 解析告警规则, 多规则场景
|
|
@@ -530,24 +530,24 @@ class rt {
|
|
|
530
530
|
*
|
|
531
531
|
* @param options
|
|
532
532
|
*/
|
|
533
|
-
parsePrinciple(
|
|
534
|
-
var
|
|
535
|
-
|
|
536
|
-
const
|
|
537
|
-
if (!
|
|
533
|
+
parsePrinciple(e, t = {}) {
|
|
534
|
+
var s, d, r;
|
|
535
|
+
W == null || W.info("[%s] parse rule: %s", t.requestId, e);
|
|
536
|
+
const o = new RegExp("(?<=\\[)(.+)(?=])", "g"), i = e.match(o) ? (s = e.match(o)) == null ? void 0 : s[0] : void 0, a = i == null ? void 0 : i.split(";");
|
|
537
|
+
if (!a)
|
|
538
538
|
return;
|
|
539
|
-
const
|
|
540
|
-
for (let
|
|
541
|
-
const m = (r = (d =
|
|
542
|
-
if (
|
|
543
|
-
|
|
539
|
+
const n = {};
|
|
540
|
+
for (let l = 0; l < (a == null ? void 0 : a.length); l++) {
|
|
541
|
+
const m = (r = (d = a[l].match(o)) == null ? void 0 : d[0]) == null ? void 0 : r.split("],");
|
|
542
|
+
if (l === 0 && !m)
|
|
543
|
+
n.scope = a[0];
|
|
544
544
|
else if (m)
|
|
545
|
-
for (let f = 0,
|
|
546
|
-
const
|
|
547
|
-
|
|
545
|
+
for (let f = 0, h = m.length; f < h; f++) {
|
|
546
|
+
const u = this.parseRule(m[f]);
|
|
547
|
+
u && (n[u.level] ? u.key ? n[u.level][u == null ? void 0 : u.key] = u : n[u.level] = u : u.key ? n[u.level] = { [u == null ? void 0 : u.key]: u } : n[u.level] = u);
|
|
548
548
|
}
|
|
549
549
|
}
|
|
550
|
-
return
|
|
550
|
+
return n;
|
|
551
551
|
}
|
|
552
552
|
/**
|
|
553
553
|
* 解析单一告警规则
|
|
@@ -555,17 +555,17 @@ class rt {
|
|
|
555
555
|
* @param rule
|
|
556
556
|
* @param options
|
|
557
557
|
*/
|
|
558
|
-
parseRule(
|
|
559
|
-
var
|
|
560
|
-
|
|
561
|
-
const
|
|
562
|
-
if (
|
|
558
|
+
parseRule(e, t = {}) {
|
|
559
|
+
var n;
|
|
560
|
+
W == null || W.info("[%s] parse rule: %s", t.requestId, e), e = e.startsWith("[") ? e : `[${e}`, e = e.endsWith("]") ? e : `${e}]`;
|
|
561
|
+
const o = new RegExp("(?<=\\[)(.+?)(?=])", "g"), i = (n = e == null ? void 0 : e.match(o)) == null ? void 0 : n[0], a = i == null ? void 0 : i.split(",");
|
|
562
|
+
if (a)
|
|
563
563
|
return {
|
|
564
|
-
operator:
|
|
565
|
-
number: Number.isNaN(Number(
|
|
566
|
-
level:
|
|
567
|
-
time: Number(
|
|
568
|
-
key:
|
|
564
|
+
operator: a[0],
|
|
565
|
+
number: Number.isNaN(Number(a[1])) ? a[1] : Number(a[1]),
|
|
566
|
+
level: a[2],
|
|
567
|
+
time: Number(a[3]),
|
|
568
|
+
key: a[4]
|
|
569
569
|
};
|
|
570
570
|
}
|
|
571
571
|
/**
|
|
@@ -574,27 +574,27 @@ class rt {
|
|
|
574
574
|
* @param principle 告警规则
|
|
575
575
|
* @param options
|
|
576
576
|
*/
|
|
577
|
-
checkWeather(
|
|
578
|
-
var
|
|
579
|
-
let
|
|
580
|
-
const d = Math.round(((
|
|
581
|
-
for (let
|
|
582
|
-
const
|
|
583
|
-
|
|
577
|
+
checkWeather(e, t, o = {}) {
|
|
578
|
+
var u, p, k, y, w, c, M, D, g, Y, S, x, C, A, q;
|
|
579
|
+
let i = 0, a = 0, n = 0, s = 0;
|
|
580
|
+
const d = Math.round(((p = (u = t == null ? void 0 : t.SEVERE) == null ? void 0 : u.sigWave) == null ? void 0 : p.number) * 1.6 * 100) / 100, r = (y = (k = t == null ? void 0 : t.SEVERE) == null ? void 0 : k.sigWave) == null ? void 0 : y.number, l = (c = (w = t == null ? void 0 : t.HEAVY) == null ? void 0 : w.sigWave) == null ? void 0 : c.number, m = Math.round((((D = (M = t == null ? void 0 : t.SEVERE) == null ? void 0 : M.wind) == null ? void 0 : D.number) + 2) * 100) / 100, f = (Y = (g = t == null ? void 0 : t.SEVERE) == null ? void 0 : g.wind) == null ? void 0 : Y.number, h = (x = (S = t == null ? void 0 : t.HEAVY) == null ? void 0 : S.wind) == null ? void 0 : x.number;
|
|
581
|
+
for (let V = 0; V < (e == null ? void 0 : e.length); V++) {
|
|
582
|
+
const T = e[V], O = (A = (C = T == null ? void 0 : T.meteo) == null ? void 0 : C.wave) == null ? void 0 : A.sig, P = (q = T == null ? void 0 : T.meteo) == null ? void 0 : q.wind, J = V ? I(T.eta).diff(I(e[V - 1].eta), "hour", !0) : 0;
|
|
583
|
+
s = J > s ? J : s, W == null || W.info("[%s] check sig.wave: %j", o.requestId, { ...O, dgThd4Wv: d, svThd4Wv: r, hvThd4Wv: l }), (O == null ? void 0 : O.height) >= d ? T.isDangerous = !0 : (O == null ? void 0 : O.height) >= r ? T.isSevere = !0 : (O == null ? void 0 : O.height) >= l && (T.isHeavy = !0), W == null || W.info("[%s] check wind: %j", o.requestId, { ...P, dgThd4Wd: m, svThd4Wd: f, hvThd4Wd: h }), (P == null ? void 0 : P.scale) >= m ? (T.isDangerous = !0, delete T.isSevere, delete T.isHeavy) : (P == null ? void 0 : P.scale) > f ? (T.isDangerous || (T.isSevere = !0), delete T.isHeavy) : (P == null ? void 0 : P.scale) === h && !T.isDangerous && !T.isSevere && (T.isHeavy = !0), i += T.isDangerous ? J : 0, a += T.isSevere ? J : 0, n += T.isHeavy ? J : 0;
|
|
584
584
|
}
|
|
585
|
-
return
|
|
585
|
+
return i = Math.round(i * 100) / 100, a = Math.round(a * 100) / 100, n = Math.round(n * 100) / 100, s = Math.round(s), { sample: e, dangerous: i, severe: a, heavy: n, step: s < 3 ? 3 : s, wind: { dgThd4Wd: m, svThd4Wd: f, hvThd4Wd: h }, sig: { dgThd4Wv: d, svThd4Wv: r, hvThd4Wv: l } };
|
|
586
586
|
}
|
|
587
587
|
}
|
|
588
588
|
const kt = new rt();
|
|
589
|
-
let
|
|
589
|
+
let v;
|
|
590
590
|
try {
|
|
591
|
-
|
|
591
|
+
v = Q.getLogger("vessel");
|
|
592
592
|
} catch {
|
|
593
593
|
} finally {
|
|
594
594
|
}
|
|
595
595
|
const ct = new ot("", !0);
|
|
596
|
-
var dt = /* @__PURE__ */ ((
|
|
597
|
-
class
|
|
596
|
+
var dt = /* @__PURE__ */ ((j) => (j.common = "common", j.container = "container", j.tugs = "tugs", j))(dt || {}), ut = /* @__PURE__ */ ((j) => (j.Ballast = "Ballast", j.Laden = "Laden", j))(ut || {}), ht = /* @__PURE__ */ ((j) => (j.Cp = "CP", j.Perf = "Basis", j.Instruct = "Other", j))(ht || {});
|
|
597
|
+
class H {
|
|
598
598
|
/**
|
|
599
599
|
* @see https://baike.baidu.com/item/%E6%96%B9%E5%BD%A2%E7%B3%BB%E6%95%B0/4965568?fr=aladdin
|
|
600
600
|
* 方形系数(block coefficient)
|
|
@@ -607,11 +607,11 @@ class C {
|
|
|
607
607
|
* @param draught 吃水 m
|
|
608
608
|
* @return [0.55, 0.85]
|
|
609
609
|
*/
|
|
610
|
-
static blockCoefficient(
|
|
611
|
-
let
|
|
612
|
-
|
|
613
|
-
const
|
|
614
|
-
return
|
|
610
|
+
static blockCoefficient(e, t, o, i) {
|
|
611
|
+
let a = Math.round(e / (t * o * i) * 100) / 100;
|
|
612
|
+
a = a < 0.55 ? 0.55 : a > 0.85 ? 0.85 : a;
|
|
613
|
+
const n = [0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85], s = n.map((d) => Math.abs(d - a));
|
|
614
|
+
return n[s.indexOf(Math.min(...s))];
|
|
615
615
|
}
|
|
616
616
|
/**
|
|
617
617
|
* @see https://baike.baidu.com/item/%E5%BC%97%E5%8A%B3%E5%BE%B7%E6%95%B0/228891?fromModule=search-result_lemma-recommend
|
|
@@ -624,9 +624,9 @@ class C {
|
|
|
624
624
|
* @param g 重力加速度 9.80 m/s^2
|
|
625
625
|
* @return [0.05, 0.30]
|
|
626
626
|
*/
|
|
627
|
-
static froudeNumber(
|
|
628
|
-
let
|
|
629
|
-
return
|
|
627
|
+
static froudeNumber(e, t, o = 9.8) {
|
|
628
|
+
let i = Math.round(Math.sqrt(e * e / (o * t)) * 100) / 100;
|
|
629
|
+
return i = i < 0.05 ? 0.05 : i > 0.3 ? 0.3 : i, i;
|
|
630
630
|
}
|
|
631
631
|
/**
|
|
632
632
|
* 失速修正系數
|
|
@@ -635,8 +635,8 @@ class C {
|
|
|
635
635
|
* @param loadCondition
|
|
636
636
|
* @private
|
|
637
637
|
*/
|
|
638
|
-
static amendFactor(
|
|
639
|
-
const
|
|
638
|
+
static amendFactor(e, t, o) {
|
|
639
|
+
const i = {
|
|
640
640
|
0.55: [1.7, -1.4, -7.4],
|
|
641
641
|
0.6: [2.2, -2.5, -9.7],
|
|
642
642
|
0.65: [2.6, -3.7, -11.6],
|
|
@@ -645,7 +645,7 @@ class C {
|
|
|
645
645
|
0.8: [2.6, -13.1, -15.1],
|
|
646
646
|
0.85: [3.1, -18.7, 28]
|
|
647
647
|
};
|
|
648
|
-
let
|
|
648
|
+
let n = {
|
|
649
649
|
0.55: [1.7, -1.4, -7.4],
|
|
650
650
|
0.6: [2.2, -2.5, -9.7],
|
|
651
651
|
0.65: [2.6, -3.7, -11.6],
|
|
@@ -653,8 +653,8 @@ class C {
|
|
|
653
653
|
0.75: [2.6, -12.5, -13.5],
|
|
654
654
|
0.8: [3, -16.3, -21.6],
|
|
655
655
|
0.85: [3.4, -20.9, 31.8]
|
|
656
|
-
}[
|
|
657
|
-
return
|
|
656
|
+
}[e];
|
|
657
|
+
return o === "Laden" && (n = i[e]), n[0] + n[1] * t + n[2] * Math.pow(t, 2);
|
|
658
658
|
}
|
|
659
659
|
/**
|
|
660
660
|
* 失速方向因子
|
|
@@ -667,9 +667,9 @@ class C {
|
|
|
667
667
|
* @param bn
|
|
668
668
|
* @private
|
|
669
669
|
*/
|
|
670
|
-
static directionFactor(
|
|
671
|
-
let
|
|
672
|
-
return
|
|
670
|
+
static directionFactor(e, t = 0) {
|
|
671
|
+
let o;
|
|
672
|
+
return e > 30 && e <= 60 ? o = (1.7 - 0.03 * Math.pow(t - 4, 2)) / 2 : e > 60 && e <= 150 ? o = (0.9 - 0.06 * Math.pow(t - 6, 2)) / 2 : e > 150 && e <= 180 ? o = (0.4 - 0.03 * Math.pow(t - 8, 2)) / 2 : o = 1, Math.round(o * 1e5) / 1e5;
|
|
673
673
|
}
|
|
674
674
|
/**
|
|
675
675
|
* 失速船型因子
|
|
@@ -682,20 +682,20 @@ class C {
|
|
|
682
682
|
* @param bn
|
|
683
683
|
* @private
|
|
684
684
|
*/
|
|
685
|
-
static vesselTagFactor(
|
|
686
|
-
|
|
687
|
-
let
|
|
688
|
-
return
|
|
685
|
+
static vesselTagFactor(e, t, o, i = 0) {
|
|
686
|
+
i = i > 6 ? i - 0.9 * (i - 6) : i;
|
|
687
|
+
let a;
|
|
688
|
+
return o === "container" ? a = 0.7 * i + Math.pow(i, 6.5) / (22 * Math.pow(e, 2 / 3)) : t === "Ballast" ? a = 0.7 * i + Math.pow(i, 6.5) / (2.7 * Math.pow(e, 2 / 3)) : a = 0.5 * i + Math.pow(i, 6.5) / (2.7 * Math.pow(e, 2 / 3)), a;
|
|
689
689
|
}
|
|
690
690
|
/**
|
|
691
691
|
* 浪高影响因子
|
|
692
692
|
* @param ht 浪高,单位m
|
|
693
693
|
* @private
|
|
694
694
|
*/
|
|
695
|
-
static waveHeightFactor(
|
|
696
|
-
|
|
697
|
-
let
|
|
698
|
-
return t > 30 && t <= 60 ?
|
|
695
|
+
static waveHeightFactor(e, t) {
|
|
696
|
+
e = e < 0 ? 0.2 : e, e = e > 6 ? e - 0.9 * (e - 6) : e, e = e > 9 ? 9 : e;
|
|
697
|
+
let o;
|
|
698
|
+
return t > 30 && t <= 60 ? o = -0.6 : t > 60 && t <= 90 ? o = -0.4 : t > 90 && t <= 120 ? o = e < 3 ? 0.4 : -0.3 : t > 120 && t <= 150 ? o = e < 3 ? 0.6 : -0.5 : t > 150 && t <= 180 ? o = e < 3 ? 0.7 : -0.6 : o = -0.7, Math.round(o * (0.144 * Math.pow(e, 2) + 0.178 * e) * 1e4) / 1e4;
|
|
699
699
|
}
|
|
700
700
|
/**
|
|
701
701
|
* 组装船舶运行参数
|
|
@@ -705,21 +705,21 @@ class C {
|
|
|
705
705
|
* @param bearing 方位角
|
|
706
706
|
* @private
|
|
707
707
|
*/
|
|
708
|
-
static assembleProperties(
|
|
708
|
+
static assembleProperties(e, t, o, i) {
|
|
709
709
|
var f;
|
|
710
|
-
const
|
|
710
|
+
const a = e.lbp ?? e.length ?? e.lengthOverall ?? 198.9642, n = e.draught ?? 8, s = e.breadthMoulded ?? e.breadth ?? e.breadthExtreme ?? 32.4572, d = e.deadweight ?? 67035.7773, r = ((f = e == null ? void 0 : e.type) == null ? void 0 : f.toLowerCase()) || "common";
|
|
711
711
|
return {
|
|
712
712
|
tag: r.indexOf("container") > -1 ? "container" : r.indexOf("tugs") > -1 ? "tugs" : "common",
|
|
713
|
-
lbp:
|
|
713
|
+
lbp: a,
|
|
714
714
|
loadCondition: t,
|
|
715
|
-
draught:
|
|
716
|
-
breadthMoulded:
|
|
715
|
+
draught: n,
|
|
716
|
+
breadthMoulded: s,
|
|
717
717
|
// 排水量(吨)= 载重量(吨)/ 1.025 + 吃水(米)× 船舶型宽(米)× 船舶型长(米)× 0.7
|
|
718
718
|
// 其中,1.025是指海水的密度,吨是指公吨,吃水是指船舶的最大吃水深度。船舶型宽是指船舶的最大型宽,船舶型长是指船舶的设计型长。上述公式是针对常规船舶适用的,不同类型的船舶可能会有一些差异。
|
|
719
|
-
displacement: Math.round((d / 1.025 +
|
|
719
|
+
displacement: Math.round((d / 1.025 + n * s * a * 0.7) * 1e4) / 1e4,
|
|
720
720
|
// 换算为m/s
|
|
721
|
-
speed: Math.round((
|
|
722
|
-
bearing:
|
|
721
|
+
speed: Math.round((o ?? 14.1382) * 1852 / 3600 * 1e4) / 1e4,
|
|
722
|
+
bearing: i || 90
|
|
723
723
|
};
|
|
724
724
|
}
|
|
725
725
|
/**
|
|
@@ -732,35 +732,35 @@ class C {
|
|
|
732
732
|
* @param useMeteo true 启用气象分析
|
|
733
733
|
* @param useRouteParam true 启用设置速度
|
|
734
734
|
*/
|
|
735
|
-
static async speedLoseAt(
|
|
735
|
+
static async speedLoseAt(e, t, o, i = "", a = 2, n = !0, s = !1, d = {}) {
|
|
736
736
|
let r;
|
|
737
|
-
if (t.velocity &&
|
|
738
|
-
let
|
|
737
|
+
if (t.velocity && s && (e.speed = z.roundPrecision(t.velocity * 1852 / 3600, 6)), n) {
|
|
738
|
+
let l;
|
|
739
739
|
if (d.meteo2)
|
|
740
740
|
try {
|
|
741
|
-
const
|
|
742
|
-
|
|
743
|
-
} catch (
|
|
744
|
-
|
|
741
|
+
const u = await ct.spotForecast(t.lat, t.lng, o.utc().format(), !1, !1, !0, d), [p] = tt.pickHourly(u, o);
|
|
742
|
+
l = tt.toLegacy(p);
|
|
743
|
+
} catch (u) {
|
|
744
|
+
v.warn("[%s] meteo2 spot(%j) forecast failed: %s", d.requestId, { ...t, eta: o.utc().format() }, u);
|
|
745
745
|
}
|
|
746
746
|
else
|
|
747
|
-
|
|
748
|
-
const m =
|
|
747
|
+
l = await nt.queryPointFactor(t.lng, t.lat, o.valueOf(), "wind,wave,current,watertemp", i, d);
|
|
748
|
+
const m = H.weatherFactor(e, l), f = H.currentFactor(e.bearing, l == null ? void 0 : l.current, a), h = Math.round((e.speed * 1.943844 + m + f) * 100) / 100;
|
|
749
749
|
r = {
|
|
750
|
-
meteo: { ...
|
|
750
|
+
meteo: { ...l },
|
|
751
751
|
wxFactor: m,
|
|
752
752
|
cFactor: f,
|
|
753
|
-
speed: t.velocity &&
|
|
754
|
-
eta:
|
|
755
|
-
etd:
|
|
753
|
+
speed: t.velocity && s ? t.velocity : h < 0 ? 1 : h,
|
|
754
|
+
eta: o.utc().format("YYYY-MM-DDTHH:mm[Z]"),
|
|
755
|
+
etd: o.utc().format("YYYY-MM-DDTHH:mm[Z]")
|
|
756
756
|
};
|
|
757
757
|
} else
|
|
758
758
|
r = {
|
|
759
759
|
wxFactor: 0,
|
|
760
760
|
cFactor: 0,
|
|
761
|
-
speed: t.velocity &&
|
|
762
|
-
eta:
|
|
763
|
-
etd:
|
|
761
|
+
speed: t.velocity && s ? t.velocity : Math.round((e.speed * 1.943844 + 0 + 0) * 100) / 100,
|
|
762
|
+
eta: o.utc().format("YYYY-MM-DDTHH:mm[Z]"),
|
|
763
|
+
etd: o.utc().format("YYYY-MM-DDTHH:mm[Z]")
|
|
764
764
|
};
|
|
765
765
|
return delete t.meteo, delete t.wxFactor, delete t.cFactor, delete t.speed, delete t.etd, { ...r, ...t };
|
|
766
766
|
}
|
|
@@ -777,53 +777,53 @@ class C {
|
|
|
777
777
|
* @param useRouteParam true 启用航线上设置的参数 { suspend: 停留时长(小时), velocity: 速度(kts)}
|
|
778
778
|
* @private
|
|
779
779
|
*/
|
|
780
|
-
static async speedLoseInHoursStep(
|
|
780
|
+
static async speedLoseInHoursStep(e, t, o, i, a, n, s = "", d = !0, r = !1, l = {}) {
|
|
781
781
|
t.utc();
|
|
782
|
-
const m =
|
|
783
|
-
let
|
|
784
|
-
for (let
|
|
785
|
-
let c =
|
|
786
|
-
c.distanceFromStart =
|
|
787
|
-
const
|
|
788
|
-
if (
|
|
782
|
+
const m = t.clone().add(14, "days"), f = [], h = [];
|
|
783
|
+
let u = 0, p = 0, k, y;
|
|
784
|
+
for (let w = 0; w < n.length - 1; w++) {
|
|
785
|
+
let c = n[w];
|
|
786
|
+
c.distanceFromStart = Math.round((a + p) * 1e4) / 1e4;
|
|
787
|
+
const M = n[w + 1];
|
|
788
|
+
if (e.bearing = B.calculateBearing(c, M, !M.gcToPrevious), c.bearing = e.bearing, c.suspend && r) {
|
|
789
789
|
c.eta = c.eta || t.format("YYYY-MM-DDTHH:mm[Z]"), c.elapsed = c.elapsed ?? 0;
|
|
790
|
-
const
|
|
791
|
-
if (
|
|
792
|
-
|
|
790
|
+
const Y = c.suspend - c.elapsed;
|
|
791
|
+
if (i - u > Y)
|
|
792
|
+
i = i - u - Y, t.add(Y, "hour"), c.elapsed = c.suspend;
|
|
793
793
|
else {
|
|
794
|
-
const
|
|
795
|
-
c.elapsed +=
|
|
794
|
+
const S = i - u;
|
|
795
|
+
c.elapsed += S, t.add(S, "hour"), i = 0;
|
|
796
796
|
}
|
|
797
|
-
if (
|
|
798
|
-
return c.distanceFromPrevious =
|
|
797
|
+
if (v == null || v.info(`[%s] suspend ${c.elapsed} hours at %j, and remain ${i} hours need to go...`, l.requestId, c), i === 0)
|
|
798
|
+
return c.distanceFromPrevious = p, { etd: t, from: y || c, to: c, next: n.filter((S) => S), wps: f, days: h };
|
|
799
799
|
} else
|
|
800
800
|
c.suspend = 0;
|
|
801
|
-
d = t.isAfter(m) ? !1 : d, c = await
|
|
802
|
-
const D =
|
|
803
|
-
let
|
|
804
|
-
if (
|
|
805
|
-
if (
|
|
806
|
-
`[%s] go to %j from %j with ${D}nm, and cost ${
|
|
807
|
-
|
|
808
|
-
{ lat:
|
|
809
|
-
{ lat:
|
|
810
|
-
),
|
|
811
|
-
k =
|
|
801
|
+
d = t.isAfter(m) ? !1 : d, c = await H.speedLoseAt(e, c, t, s, 0, d, r, l), y = y || c, c.important && f.push(c), t.isSameOrAfter(o) && (h.push(c), o.add(24, "hour"));
|
|
802
|
+
const D = B.calculateDistance(c, M, !M.gcToPrevious);
|
|
803
|
+
let g = Math.ceil(D / y.speed * 1e4) / 1e4;
|
|
804
|
+
if (u + g < i) {
|
|
805
|
+
if (u += g, t.add(g, "hour"), delete n[w], v == null || v.debug(
|
|
806
|
+
`[%s] go to %j from %j with ${D}nm, and cost ${g} hours`,
|
|
807
|
+
l.requestId,
|
|
808
|
+
{ lat: M.lat, lng: M.lng },
|
|
809
|
+
{ lat: y.lat, lng: y.lng, etd: y.etd }
|
|
810
|
+
), p += D, n.filter((Y) => Y).length <= 1) {
|
|
811
|
+
k = M, k.eta = t.format("YYYY-MM-DDTHH:mm[Z]"), k.distanceFromPrevious = D, k.distanceFromStart = Math.round((a + p) * 1e4) / 1e4, f.push(k), delete n[w + 1];
|
|
812
812
|
break;
|
|
813
813
|
}
|
|
814
814
|
} else {
|
|
815
|
-
|
|
816
|
-
const
|
|
817
|
-
k =
|
|
818
|
-
`[%s] go to %j from %j with ${
|
|
819
|
-
|
|
815
|
+
g = i - u, t.add(g, "hour");
|
|
816
|
+
const Y = z.roundPrecision(y.speed * g, 4);
|
|
817
|
+
k = B.calculateCoordinate(c, e.bearing, Y, "nauticalmiles", !M.gcToPrevious), k.eta = t.format("YYYY-MM-DDTHH:mm[Z]"), n[w] = k, v == null || v.debug(
|
|
818
|
+
`[%s] go to %j from %j with ${Y}nm, and cost ${g} hours`,
|
|
819
|
+
l.requestId,
|
|
820
820
|
{ lat: k.lat, lng: k.lng },
|
|
821
821
|
{ lat: c.lat, lng: c.lng, etd: c.etd }
|
|
822
|
-
),
|
|
822
|
+
), p += Y, k.distanceFromPrevious = Math.round(p * 1e4) / 1e4, k.distanceFromStart = Math.round((a + p) * 1e4) / 1e4;
|
|
823
823
|
break;
|
|
824
824
|
}
|
|
825
825
|
}
|
|
826
|
-
return { etd: t, from:
|
|
826
|
+
return { etd: t, from: y, to: k, next: n.filter((w) => w), wps: f, days: h };
|
|
827
827
|
}
|
|
828
828
|
/**
|
|
829
829
|
* 洋流影响因子
|
|
@@ -831,29 +831,29 @@ class C {
|
|
|
831
831
|
* @param current 洋流要素
|
|
832
832
|
* @param role 1: 船东, 2: 租家, 0: 未知
|
|
833
833
|
*/
|
|
834
|
-
static currentFactor(
|
|
835
|
-
const
|
|
836
|
-
if (Math.abs(
|
|
834
|
+
static currentFactor(e, t, o = 0) {
|
|
835
|
+
const i = (e - (t == null ? void 0 : t.degree) || 0) / 180 * Math.PI;
|
|
836
|
+
if (Math.abs(i) === Math.PI / 2)
|
|
837
837
|
return 0;
|
|
838
|
-
let
|
|
839
|
-
return
|
|
838
|
+
let a = ((t == null ? void 0 : t.kts) || 0) * Math.cos(i);
|
|
839
|
+
return o & 2 ? a = Math.ceil(a * 100) / 100 : o & 1 ? a = Math.floor(a * 100) / 100 : a = Math.round(a * 100) / 100, Math.abs(a) > 5 ? 0 : a;
|
|
840
840
|
}
|
|
841
841
|
/**
|
|
842
842
|
* 风浪影响因子
|
|
843
843
|
* @param props 船舶档案
|
|
844
844
|
* @param wwc 气象要素
|
|
845
845
|
*/
|
|
846
|
-
static weatherFactor(
|
|
847
|
-
var m, f,
|
|
848
|
-
|
|
849
|
-
const
|
|
850
|
-
let
|
|
851
|
-
|
|
852
|
-
const
|
|
853
|
-
let r =
|
|
854
|
-
r = Math.round(r * 1.943844 * 1e4) / 1e4 * -1,
|
|
855
|
-
const
|
|
856
|
-
return
|
|
846
|
+
static weatherFactor(e, t) {
|
|
847
|
+
var m, f, h, u, p, k, y;
|
|
848
|
+
v == null || v.debug("calculate weather factor via: %j", { ...e, ...t });
|
|
849
|
+
const o = H.blockCoefficient(e.displacement, e.lbp, e.breadthMoulded, e.draught), i = H.froudeNumber(e.speed, e.lbp), a = H.amendFactor(o, i, e.loadCondition);
|
|
850
|
+
let n = Math.abs(e.bearing % 360 - (((m = t == null ? void 0 : t.wind) == null ? void 0 : m.degree) % 360 || 0));
|
|
851
|
+
n = n > 180 ? 360 - n : n;
|
|
852
|
+
const s = H.directionFactor(n, (f = t == null ? void 0 : t.wind) == null ? void 0 : f.scale), d = H.vesselTagFactor(e.displacement, e.loadCondition, e.tag, (h = t == null ? void 0 : t.wind) == null ? void 0 : h.scale);
|
|
853
|
+
let r = s * a * d / 100 * e.speed;
|
|
854
|
+
r = Math.round(r * 1.943844 * 1e4) / 1e4 * -1, e.tag === "tugs" && Math.abs(r) > 1 && (r = r / (Math.abs(Math.round(r)) + 1)), v == null || v.debug("wind wx factor = %d", r), n = Math.abs(e.bearing % 360 - (((p = (u = t == null ? void 0 : t.wave) == null ? void 0 : u.sig) == null ? void 0 : p.degree) % 360 || 0));
|
|
855
|
+
const l = H.waveHeightFactor(((y = (k = t == null ? void 0 : t.wave) == null ? void 0 : k.sig) == null ? void 0 : y.height) ?? 1, n);
|
|
856
|
+
return v == null || v.debug("wave wx factor = %d", l), r = r * 0.4 + l, v == null || v.debug("weather factor = %d", r), r = Math.abs(r) > 4 ? 4 * (Math.abs(r) / r) + Math.abs(r) / r * (Math.abs(r) - 4) * 0.1 : r, Math.round((r || 0) * 100) / 100;
|
|
857
857
|
}
|
|
858
858
|
/**
|
|
859
859
|
* 全程失速分析(走完航程)
|
|
@@ -867,74 +867,74 @@ class C {
|
|
|
867
867
|
* @param useMeteo true 启用气象分析
|
|
868
868
|
* @param useRouteParam
|
|
869
869
|
*/
|
|
870
|
-
static async analyseInstant(
|
|
871
|
-
var
|
|
872
|
-
const m =
|
|
873
|
-
|
|
874
|
-
const { route: f, waypoints:
|
|
875
|
-
if (((
|
|
870
|
+
static async analyseInstant(e, t, o, i, a, n = "", s = 0, d = !0, r = !1, l = {}) {
|
|
871
|
+
var J, K, _, G, R;
|
|
872
|
+
const m = I().valueOf();
|
|
873
|
+
e.lng = z.convertToStdLng(e.lng);
|
|
874
|
+
const { route: f, waypoints: h } = a.points, u = B.calculateSubRoute(e, f);
|
|
875
|
+
if (((J = u[0]) == null ? void 0 : J.length) <= 1)
|
|
876
876
|
return;
|
|
877
|
-
const { v0:
|
|
878
|
-
v0:
|
|
877
|
+
const { v0: p, label: k } = e.sog ? {
|
|
878
|
+
v0: e.sog,
|
|
879
879
|
label: "Other"
|
|
880
880
|
/* Instruct */
|
|
881
881
|
} : {
|
|
882
|
-
v0:
|
|
882
|
+
v0: i.speed,
|
|
883
883
|
label: "CP"
|
|
884
884
|
/* Cp */
|
|
885
|
-
},
|
|
886
|
-
|
|
885
|
+
}, y = H.assembleProperties(o, i.loadCondition, p, 0), w = h.length ? B.calculateSubWaypoints(e, h) : [];
|
|
886
|
+
w.forEach((N) => N.important = !0);
|
|
887
887
|
const c = {
|
|
888
|
-
from: { ...
|
|
889
|
-
route:
|
|
890
|
-
waypoints:
|
|
891
|
-
v0:
|
|
888
|
+
from: { ...e },
|
|
889
|
+
route: u,
|
|
890
|
+
waypoints: w,
|
|
891
|
+
v0: p,
|
|
892
892
|
label: k
|
|
893
|
-
},
|
|
893
|
+
}, M = {
|
|
894
894
|
hours: [],
|
|
895
895
|
days: [],
|
|
896
896
|
wps: []
|
|
897
897
|
};
|
|
898
|
-
|
|
899
|
-
let D =
|
|
900
|
-
t =
|
|
901
|
-
const
|
|
898
|
+
s || (B.calculateRouteDistance(u) / i.speed <= 72 ? s = 3 : s = 6);
|
|
899
|
+
let D = B.simplifyRouteToCoordinates(u, w, 0), g = 0, Y = 0, S = 0, x = 0;
|
|
900
|
+
t = I(t).utc();
|
|
901
|
+
const C = t.clone();
|
|
902
902
|
for (; D.length > 0; ) {
|
|
903
|
-
const
|
|
904
|
-
b,
|
|
905
|
-
t,
|
|
906
|
-
R,
|
|
907
|
-
_,
|
|
903
|
+
const N = s - t.hour() % s, F = Math.ceil(t.clone().add(N, "h").set({ minute: 0, second: 0, millisecond: 0 }).diff(t, "h", !0) * 1e4) / 1e4, E = await H.speedLoseInHoursStep(
|
|
908
904
|
y,
|
|
905
|
+
t,
|
|
906
|
+
C,
|
|
907
|
+
F,
|
|
908
|
+
g,
|
|
909
909
|
D,
|
|
910
|
-
|
|
910
|
+
n,
|
|
911
911
|
d,
|
|
912
912
|
r,
|
|
913
|
-
|
|
913
|
+
l
|
|
914
914
|
);
|
|
915
|
-
(
|
|
915
|
+
(K = E.from) != null && K.speed && (M.hours.push(E.from), M.wps.push(...E.wps), M.days.push(...E.days)), D = E == null ? void 0 : E.next, D.length || M.hours.push(E == null ? void 0 : E.to), g += Math.round((((_ = E == null ? void 0 : E.to) == null ? void 0 : _.distanceFromPrevious) ?? 0) * 1e4) / 1e4;
|
|
916
916
|
}
|
|
917
|
-
const
|
|
918
|
-
for (let
|
|
919
|
-
const
|
|
920
|
-
|
|
917
|
+
const A = M.hours;
|
|
918
|
+
for (let N = 0; N < A.length - 1; N++) {
|
|
919
|
+
const F = I(A[N + 1].eta).diff(A[N].etd, "hour", !0) || 1;
|
|
920
|
+
Y += (A[N].wxFactor || 0) * F, S += (A[N].cFactor || 0) * F, x += F;
|
|
921
921
|
}
|
|
922
|
-
(
|
|
923
|
-
if (
|
|
924
|
-
const
|
|
922
|
+
(G = M.wps) == null || G.forEach((N, F) => {
|
|
923
|
+
if (F) {
|
|
924
|
+
const E = M.wps[F - 1], et = N.distanceFromStart - E.distanceFromStart, X = I(N.eta).diff(I(E.etd), "h", !0);
|
|
925
925
|
if (X < 1)
|
|
926
|
-
|
|
926
|
+
N.avgSpd = E.speed;
|
|
927
927
|
else {
|
|
928
|
-
|
|
929
|
-
const $ = Math.round((
|
|
930
|
-
|
|
928
|
+
N.avgSpd = Math.round(et / X * 100) / 100;
|
|
929
|
+
const $ = Math.round((E.speed + N.speed) / 2 * 100) / 100;
|
|
930
|
+
N.avgSpd = N.avgSpd > $ ? $ : N.avgSpd;
|
|
931
931
|
}
|
|
932
932
|
}
|
|
933
|
-
}), c.sample =
|
|
934
|
-
const
|
|
935
|
-
c.distance = Math.round(
|
|
936
|
-
const
|
|
937
|
-
return
|
|
933
|
+
}), c.sample = M;
|
|
934
|
+
const q = M.hours.at(0), V = M.hours.at(-1);
|
|
935
|
+
c.distance = Math.round(V.distanceFromStart * 1e4) / 1e4, c.etd = I(q.eta).utc().format(), c.eta = I(V.eta).utc().format(), c.wxFactor = Math.round(Y / x * 1e4) / 1e4, c.cFactor = Math.round(S / x * 1e4) / 1e4, c.avgSpeed = Math.round(V.distanceFromStart / x * 1e4) / 1e4, c.totalHrs = Math.round(x * 1e4) / 1e4, c.totalFoCons = Math.round((i == null ? void 0 : i.fo) / 24 * c.totalHrs * 1e3) / 1e3, c.totalDgoCons = Math.round((i == null ? void 0 : i.dgo) / 24 * c.totalHrs * 1e3) / 1e3;
|
|
936
|
+
const O = I().valueOf() - m, P = ((R = M == null ? void 0 : M.hours) == null ? void 0 : R.length) || 1;
|
|
937
|
+
return v == null || v.info("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms", l == null ? void 0 : l.requestId, O, P, Math.round(O / P * 1e3) / 1e3), c;
|
|
938
938
|
}
|
|
939
939
|
/**
|
|
940
940
|
* 分段失速分析(最多走hours 小时)
|
|
@@ -949,86 +949,280 @@ class C {
|
|
|
949
949
|
* @param useMeteo true 启用气象分析
|
|
950
950
|
* @param useRouteParam
|
|
951
951
|
*/
|
|
952
|
-
static async analyseInstantWithThreshed(
|
|
953
|
-
var
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
952
|
+
static async analyseInstantWithThreshed(e, t, o, i, a, n, s, d = "", r = 3, l = !0, m = !1, f = {}) {
|
|
953
|
+
var J, K, _, G;
|
|
954
|
+
const h = I().valueOf();
|
|
955
|
+
e.lng = z.convertToStdLng(e.lng);
|
|
956
|
+
const { v0: u, label: p } = e.sog ? {
|
|
957
|
+
v0: e.sog,
|
|
957
958
|
label: "Other"
|
|
958
959
|
/* Instruct */
|
|
959
960
|
} : {
|
|
960
|
-
v0:
|
|
961
|
+
v0: a.speed,
|
|
961
962
|
label: "CP"
|
|
962
963
|
/* Cp */
|
|
963
|
-
},
|
|
964
|
-
if (((
|
|
964
|
+
}, k = H.assembleProperties(i, a.loadCondition, u, 0), y = B.calculateSubRoute(e, n);
|
|
965
|
+
if (((J = y[0]) == null ? void 0 : J.length) <= 1)
|
|
965
966
|
return;
|
|
966
|
-
const
|
|
967
|
-
|
|
968
|
-
let
|
|
969
|
-
const
|
|
967
|
+
const w = s.length ? B.calculateSubWaypoints(e, s) : [];
|
|
968
|
+
w.forEach((R) => R.important = !0);
|
|
969
|
+
let c = B.simplifyRouteToCoordinates(y, w, 0), M = 0, D = 0, g = 0, Y = 0;
|
|
970
|
+
const S = {
|
|
970
971
|
hours: [],
|
|
971
972
|
wps: [],
|
|
972
973
|
days: []
|
|
973
974
|
};
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
975
|
+
t = I(t).utc();
|
|
976
|
+
const x = t.clone();
|
|
977
|
+
for (; c.length > 0; ) {
|
|
978
|
+
const R = r - t.hour() % r;
|
|
979
|
+
let N = Math.ceil(t.clone().add(R, "h").set({ minute: 0, second: 0, millisecond: 0 }).diff(t, "h", !0) * 1e4) / 1e4;
|
|
980
|
+
if (N = t.clone().add(N, "h").isAfter(o) ? o.diff(t, "h", !0) * 1e4 / 1e4 : N, N) {
|
|
981
|
+
const F = await H.speedLoseInHoursStep(
|
|
982
|
+
k,
|
|
980
983
|
t,
|
|
981
|
-
|
|
982
|
-
|
|
984
|
+
x,
|
|
985
|
+
N,
|
|
986
|
+
M,
|
|
983
987
|
c,
|
|
984
|
-
I,
|
|
985
988
|
d,
|
|
986
|
-
|
|
989
|
+
l,
|
|
987
990
|
m,
|
|
988
991
|
f
|
|
989
|
-
)
|
|
990
|
-
|
|
991
|
-
|
|
992
|
+
);
|
|
993
|
+
(K = F.from) != null && K.speed && (S.hours.push(F.from), F != null && F.wps && S.wps.push(...F.wps), S.days.push(...F.days)), c = F == null ? void 0 : F.next, c.length || S.hours.push(F == null ? void 0 : F.to), M += Math.round((((_ = F == null ? void 0 : F.to) == null ? void 0 : _.distanceFromPrevious) ?? 0) * 1e4) / 1e4;
|
|
994
|
+
} else
|
|
992
995
|
break;
|
|
996
|
+
}
|
|
997
|
+
const C = S.hours;
|
|
998
|
+
for (let R = 0; R < C.length - 1; R++) {
|
|
999
|
+
const N = I(C[R + 1].eta).diff(C[R].etd, "hour", !0);
|
|
1000
|
+
D += C[R].wxFactor * N, g += C[R].cFactor * N, Y += N;
|
|
1001
|
+
}
|
|
1002
|
+
const A = S.hours.at(0), q = S.hours.at(-1), V = {
|
|
1003
|
+
sample: S,
|
|
1004
|
+
distance: Math.round(((q == null ? void 0 : q.distanceFromStart) || 0) * 1e4) / 1e4,
|
|
1005
|
+
// 注意,可能会在first节点Drift,所有采用eta做为初始出发时间
|
|
1006
|
+
etd: I(A.eta).utc().format(),
|
|
1007
|
+
eta: I(q == null ? void 0 : q.eta).utc().format(),
|
|
1008
|
+
wxFactor: Math.round(D / Y * 1e4) / 1e4,
|
|
1009
|
+
cFactor: Math.round(g / Y * 1e4) / 1e4,
|
|
1010
|
+
avgSpeed: Math.round(((q == null ? void 0 : q.distanceFromStart) || 0) / Y * 1e4) / 1e4,
|
|
1011
|
+
totalHrs: Math.round(Y * 1e4) / 1e4,
|
|
1012
|
+
totalFoCons: Math.round((a == null ? void 0 : a.fo) / 24 * Y * 1e3) / 1e3,
|
|
1013
|
+
totalDgoCons: Math.round((a == null ? void 0 : a.dgo) / 24 * Y * 1e3) / 1e3,
|
|
1014
|
+
from: A,
|
|
1015
|
+
to: q,
|
|
1016
|
+
route: y,
|
|
1017
|
+
waypoints: w,
|
|
1018
|
+
v0: u,
|
|
1019
|
+
label: p
|
|
1020
|
+
}, O = I().valueOf() - h, P = ((G = S == null ? void 0 : S.hours) == null ? void 0 : G.length) || 1;
|
|
1021
|
+
return v == null || v.info("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms", f == null ? void 0 : f.requestId, O, P, Math.round(O / P * 1e3) / 1e3), V;
|
|
1022
|
+
}
|
|
1023
|
+
/**
|
|
1024
|
+
* 在指定航线条件下,基于多CP,动态计算最优成本(租金+油费)方案
|
|
1025
|
+
* 1)首先分别计算单CP下的成本方案,基于成本排序,保留最省成本的两个方案,分别用 a, b 表示;
|
|
1026
|
+
* 2) 选择步骤1)中a,b的CP,分别用 cpa, cpb 表示;
|
|
1027
|
+
* 3) 基于当前有效天气预报时长(14天),按步长多次减半,分别用7,4,2,1天步长及cpa,cpb交替计算各种组合下的成本;
|
|
1028
|
+
* 4)保留步骤3)中的最省成本的两个方案,并与步骤1)合并按成本排序,获取成本较优的三个方案;
|
|
1029
|
+
* 5) 基于步骤4),同客户沟通后,最终基于时间和成本,选择最合适的方案;
|
|
1030
|
+
*
|
|
1031
|
+
*
|
|
1032
|
+
* @param props 基础属性(位置,出发时间等)
|
|
1033
|
+
* @param vessel 船舶档案(长、宽、吃水、船舶类型等)
|
|
1034
|
+
* @param cps CP条款(装载状态,速度、油耗等)
|
|
1035
|
+
* @param lane 基础航线(重要转向点)
|
|
1036
|
+
* @param options
|
|
1037
|
+
*/
|
|
1038
|
+
static async analyseCost(e, t, o, i, a = {}) {
|
|
1039
|
+
var p, k;
|
|
1040
|
+
const n = I().valueOf(), s = [];
|
|
1041
|
+
a.meteo2 = !0, e.speedStep = e.speedStep || 3;
|
|
1042
|
+
const d = I.utc(e.etd).add(14, "day");
|
|
1043
|
+
let r = 1;
|
|
1044
|
+
for (const y of o) {
|
|
1045
|
+
v == null || v.info("[%s][L%d-%d] analyse from %s to %s", a.requestId, 1, r, e.etd, d.format()), v == null || v.info("[%s][L%d-%d] analyse with cp: ", a.requestId, 1, r, y);
|
|
1046
|
+
const w = JSON.parse(JSON.stringify(i.route)), c = JSON.parse(JSON.stringify(i.waypoints)), M = await H.analyseInstantWithThreshed(
|
|
1047
|
+
{ lat: e.lat, lng: e.lng },
|
|
1048
|
+
e.etd,
|
|
1049
|
+
d,
|
|
1050
|
+
t,
|
|
1051
|
+
y,
|
|
1052
|
+
w,
|
|
1053
|
+
c,
|
|
1054
|
+
e.meteoVendor,
|
|
1055
|
+
e.speedStep,
|
|
1056
|
+
!1,
|
|
1057
|
+
e.useRouteParam,
|
|
1058
|
+
a
|
|
1059
|
+
);
|
|
1060
|
+
M && (await H.calculateCost(M, y, e, a), s.push(M), v == null || v.info("[%s][L%d-%d] cost: %j", a.requestId, 1, r, {
|
|
1061
|
+
distance: M.distance,
|
|
1062
|
+
totalHrs: M.totalHrs,
|
|
1063
|
+
totalFoCons: M.totalFoCons,
|
|
1064
|
+
totalDgoCons: M.totalDgoCons,
|
|
1065
|
+
etd: M.etd,
|
|
1066
|
+
eta: M.eta,
|
|
1067
|
+
cost: M.cost
|
|
1068
|
+
})), r++;
|
|
1069
|
+
}
|
|
1070
|
+
s.sort((y, w) => y.cost.total - w.cost.total);
|
|
1071
|
+
const l = s.at(0), m = s.at(1), f = [];
|
|
1072
|
+
if (f.push({ combined: !1, speeds: [l], cost: (p = l.cost) == null ? void 0 : p.total }), m) {
|
|
1073
|
+
const y = l.cost.cp, w = m.cost.cp, c = I(l.eta), M = I(l.etd), D = c.diff(M, "days", !0);
|
|
1074
|
+
let g = Math.ceil(D / 2);
|
|
1075
|
+
g = g > 7 ? 7 : g;
|
|
1076
|
+
let Y = 2, S = { combined: !1, speeds: [m], cost: (k = m.cost) == null ? void 0 : k.total }, x;
|
|
1077
|
+
for (; g >= 1 && (x = await H.combinedAnalyse(e, t, d, [y, w], i, g, { ...a, level: Y }), !(S.cost < x.cost)); ) {
|
|
1078
|
+
const C = S;
|
|
1079
|
+
if (S = x, g === 1) {
|
|
1080
|
+
x = C;
|
|
1081
|
+
break;
|
|
1082
|
+
}
|
|
1083
|
+
x = void 0, g = Math.ceil(g / 2), Y += 1;
|
|
993
1084
|
}
|
|
1085
|
+
f.push(S), x && f.push(x);
|
|
994
1086
|
}
|
|
995
|
-
const
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
1087
|
+
const u = I().valueOf() - n;
|
|
1088
|
+
return v == null || v.info("[%s] analyse elapsed: %d ms", a == null ? void 0 : a.requestId, u), f.sort((y, w) => y.cost - w.cost);
|
|
1089
|
+
}
|
|
1090
|
+
/**
|
|
1091
|
+
* 按步长多次减半,分别用7,4,2,1天步长及cpa,cpb交替计算各种组合下的成本
|
|
1092
|
+
* @param props 基础属性(位置,出发时间,日租金,FO/DO/GO单价等)
|
|
1093
|
+
* @param vessel 船舶档案(长、宽、吃水、船舶类型等)
|
|
1094
|
+
* @param cps CP条款(装载状态,速度、油耗等)
|
|
1095
|
+
* @param max 最长分析未来14天
|
|
1096
|
+
* @param lane 基础航线(重要转向点)
|
|
1097
|
+
* @param step 步长,7,4,2,1
|
|
1098
|
+
* @param options
|
|
1099
|
+
*/
|
|
1100
|
+
static async combinedAnalyse(e, t, o, i, a, n, s = {}) {
|
|
1101
|
+
v == null || v.info("[%s][L%d] analyse with alternate cp in every %d days", s.requestId, s.level, n);
|
|
1102
|
+
const d = await H.alternateAnalyse(e, t, o, i, 0, a, n, s), r = d.reduce((f, h) => f + h.cost.total, 0);
|
|
1103
|
+
v == null || v.info("[%s][L%d] cost with alternate cp a first: %j", s.requestId, s.level, { cost: r });
|
|
1104
|
+
const l = await H.alternateAnalyse(e, t, o, i, 1, a, n, s), m = l.reduce((f, h) => f + h.cost.total, 0);
|
|
1105
|
+
return v == null || v.info("[%s][L%d] cost with alternate cp b first: %j", s.requestId, s.level, { cost: m }), r < m ? { combined: !0, cost: Math.round(r * 1e3) / 1e3, speeds: d } : { combined: !0, cost: Math.round(m * 1e3) / 1e3, speeds: l };
|
|
1106
|
+
}
|
|
1107
|
+
/**
|
|
1108
|
+
* 基于cp索引,交替计算指定步长下的成本
|
|
1109
|
+
* @param props 基础属性(位置,出发时间等)
|
|
1110
|
+
* @param vessel 船舶档案(长、宽、吃水、船舶类型等)
|
|
1111
|
+
* @param cps CP条款(装载状态,速度、油耗等)
|
|
1112
|
+
* @param cpIndex cp索引
|
|
1113
|
+
* @param max 最长分析未来14天
|
|
1114
|
+
* @param lane 基础航线(重要转向点)
|
|
1115
|
+
* @param step 步长,7,4,2,1
|
|
1116
|
+
* @param options
|
|
1117
|
+
*/
|
|
1118
|
+
static async alternateAnalyse(e, t, o, i, a, n, s, d = {}) {
|
|
1119
|
+
var h, u;
|
|
1120
|
+
let r = I.utc(e.etd), l = 1;
|
|
1121
|
+
const m = { lat: e.lat, lng: e.lng }, f = [];
|
|
1122
|
+
for (; r.isBefore(o); ) {
|
|
1123
|
+
const p = r.clone().add(s, "day");
|
|
1124
|
+
v == null || v.info("[%s][L%d-%d] analyse from %s to %s", d.requestId, d.level, l, e.etd, p.format()), v == null || v.info("[%s][L%d-%d] analyse with cp: ", d.requestId, d.level, l, i[a]);
|
|
1125
|
+
const k = JSON.parse(JSON.stringify(n.route)), y = JSON.parse(JSON.stringify(n.waypoints)), w = await H.analyseInstantWithThreshed(
|
|
1126
|
+
m,
|
|
1127
|
+
r.format(),
|
|
1128
|
+
p,
|
|
1129
|
+
t,
|
|
1130
|
+
i[a],
|
|
1131
|
+
k,
|
|
1132
|
+
y,
|
|
1133
|
+
e.meteoVendor,
|
|
1134
|
+
e.speedStep,
|
|
1135
|
+
!1,
|
|
1136
|
+
e.useRouteParam,
|
|
1137
|
+
d
|
|
1138
|
+
);
|
|
1139
|
+
w && (await H.calculateCost(w, i[a], e, d), v == null || v.info("[%s][L%d-%d] cost: %j", d.requestId, d.level, l, {
|
|
1140
|
+
distance: w.distance,
|
|
1141
|
+
totalHrs: w.totalHrs,
|
|
1142
|
+
totalFoCons: w.totalFoCons,
|
|
1143
|
+
totalDgoCons: w.totalDgoCons,
|
|
1144
|
+
etd: w.etd,
|
|
1145
|
+
eta: w.eta,
|
|
1146
|
+
cost: w.cost
|
|
1147
|
+
}));
|
|
1148
|
+
const c = (u = (h = w == null ? void 0 : w.sample) == null ? void 0 : h.hours) == null ? void 0 : u.at(-1);
|
|
1149
|
+
if (c)
|
|
1150
|
+
m.lat = c.lat, m.lng = c.lng, r = I(c.eta), f.push(w), l += 1, a = a ? 0 : 1;
|
|
1151
|
+
else
|
|
1152
|
+
break;
|
|
1153
|
+
}
|
|
1154
|
+
return f;
|
|
1155
|
+
}
|
|
1156
|
+
/**
|
|
1157
|
+
* 计算Speed的cost
|
|
1158
|
+
* @param speed
|
|
1159
|
+
* @param cp
|
|
1160
|
+
* @param props
|
|
1161
|
+
* @param options
|
|
1162
|
+
*/
|
|
1163
|
+
static async calculateCost(e, t, o, i = {}) {
|
|
1164
|
+
if (e) {
|
|
1165
|
+
const a = Math.round(e.totalHrs / 24 * (o.dailyHire || 0) * (1 - (o.addComm || 0)) * 1e3) / 1e3, n = Math.round(e.totalFoCons * (o.priceFO || 0) * 1e3) / 1e3, s = Math.round(e.totalDgoCons * (o.priceDGO || 0) * 1e3) / 1e3;
|
|
1166
|
+
e.cost = {
|
|
1167
|
+
total: Math.round((a + n + s) * 1e3) / 1e3,
|
|
1168
|
+
hire: a,
|
|
1169
|
+
bunker: Math.round((n + s) * 1e3) / 1e3,
|
|
1170
|
+
cp: t
|
|
1171
|
+
};
|
|
1172
|
+
}
|
|
1173
|
+
return e;
|
|
1174
|
+
}
|
|
1175
|
+
static async mergeSpeeds(e, t = {}) {
|
|
1176
|
+
const o = {
|
|
1177
|
+
hours: [],
|
|
1178
|
+
wps: [],
|
|
1179
|
+
days: []
|
|
1180
|
+
}, i = e.reduce((h, u) => h + u.distance, 0), a = e.reduce((h, u) => h + u.totalHrs, 0), n = e.reduce((h, u) => h + u.wxFactor * u.totalHrs / a, 0), s = e.reduce((h, u) => h + u.cFactor * u.totalHrs / a, 0), d = e.reduce((h, u) => h + u.totalFoCons, 0), r = e.reduce((h, u) => h + u.totalDgoCons, 0), l = e.reduce((h, u) => h + u.cost.total, 0), m = e.reduce((h, u) => h + u.cost.hire, 0), f = e.reduce((h, u) => h + u.cost.bunker, 0);
|
|
1181
|
+
for (const h of e) {
|
|
1182
|
+
const u = h.sample.hours, p = h.sample.wps, k = h.sample.days;
|
|
1183
|
+
u.forEach((y) => {
|
|
1184
|
+
var c;
|
|
1185
|
+
((c = o.hours) == null ? void 0 : c.findIndex((M) => M.eta === y.eta)) === -1 && o.hours.push(y);
|
|
1186
|
+
}), p.forEach((y) => {
|
|
1187
|
+
var c;
|
|
1188
|
+
((c = o.wps) == null ? void 0 : c.findIndex((M) => M.eta === y.eta)) === -1 && o.wps.push(y);
|
|
1189
|
+
}), k.forEach((y) => {
|
|
1190
|
+
var c;
|
|
1191
|
+
((c = o == null ? void 0 : o.days) == null ? void 0 : c.findIndex((M) => M.eta === y.eta)) === -1 && o.days.push(y);
|
|
1192
|
+
});
|
|
999
1193
|
}
|
|
1000
|
-
const R = j.hours.at(0), H = j.hours.at(-1);
|
|
1001
1194
|
return {
|
|
1002
|
-
sample:
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1195
|
+
sample: o,
|
|
1196
|
+
etd: e.at(0).etd,
|
|
1197
|
+
eta: e.at(-1).eta,
|
|
1198
|
+
from: e.at(0).from,
|
|
1199
|
+
to: e.at(-1).to,
|
|
1200
|
+
label: "combined",
|
|
1201
|
+
distance: Math.round(i * 1e4) / 1e4,
|
|
1202
|
+
totalHrs: Math.round(a * 1e3) / 1e3,
|
|
1203
|
+
avgSpeed: Math.round(i / a * 1e3) / 1e3,
|
|
1204
|
+
wxFactor: Math.round(n / a * 1e3) / 1e3,
|
|
1205
|
+
cFactor: Math.round(s / a * 1e3) / 1e3,
|
|
1206
|
+
totalFoCons: Math.round(d * 1e3) / 1e3,
|
|
1207
|
+
totalDgoCons: Math.round(r * 1e3) / 1e3,
|
|
1208
|
+
cost: {
|
|
1209
|
+
total: Math.round(l * 1e3) / 1e3,
|
|
1210
|
+
hire: Math.round(m * 1e3) / 1e3,
|
|
1211
|
+
bunker: Math.round(f * 1e3) / 1e3
|
|
1212
|
+
}
|
|
1017
1213
|
};
|
|
1018
1214
|
}
|
|
1019
|
-
static async analyseCost(s, t, i, o, n = {}) {
|
|
1020
|
-
}
|
|
1021
1215
|
}
|
|
1022
1216
|
export {
|
|
1023
|
-
|
|
1217
|
+
U as AISImpl,
|
|
1024
1218
|
rt as AlertHelper,
|
|
1025
1219
|
it as AlertLevel,
|
|
1026
|
-
|
|
1220
|
+
gt as HifleetImpl,
|
|
1027
1221
|
ut as LoadCondition,
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1222
|
+
pt as MyShipImpl,
|
|
1223
|
+
wt as MyVesselImpl,
|
|
1224
|
+
It as ShipxyImpl,
|
|
1225
|
+
H as SpeedHelper,
|
|
1032
1226
|
ht as SpeedLabel,
|
|
1033
1227
|
dt as VesselTag,
|
|
1034
1228
|
kt as alertHelper
|