@idm-plugin/vessel 2.3.0 → 2.3.1

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.
@@ -138,7 +138,7 @@ export declare class MyVesselImpl extends AISImpl {
138
138
  passengerCapacity: any;
139
139
  vendor: string;
140
140
  raw: any;
141
- }>;
141
+ } | null>;
142
142
  archives(mmsi: any, options?: {
143
143
  requestId?: string;
144
144
  }): Promise<any>;
package/dist/index.js CHANGED
@@ -133,31 +133,33 @@ class jt extends st {
133
133
  if (r.status !== 200)
134
134
  return M == null || M.warn("[%s] fetch suggest vessels failed: %j", a.requestId, { message: r.message, status: r.status, code: r.code }), {};
135
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
- };
136
+ const l = r.data;
137
+ if (l)
138
+ return {
139
+ mmsi: l.mmsi,
140
+ imo: Number.isNaN(l.imo) ? null : Number(l.imo),
141
+ callSign: l.callsign,
142
+ name: l.nameEn,
143
+ nameCn: l.nameCn,
144
+ type: l.vesselTypeNameEn,
145
+ flagName: l.flagCtry,
146
+ clasz: l.classSociety,
147
+ dateOfBuild: l.buildYearMonth,
148
+ deadweight: l.dwt,
149
+ grossTonnage: l.grt,
150
+ netTonnage: l.net,
151
+ teu: l.teu,
152
+ length: l.length,
153
+ breadth: l.width,
154
+ height: l.height,
155
+ draught: l.draught,
156
+ speed: l.speed,
157
+ passengerCapacity: l.passengercapacity,
158
+ vendor: "myvessel",
159
+ raw: l
160
+ };
160
161
  }
162
+ return null;
161
163
  }
162
164
  async archives(t, a = {}) {
163
165
  var s, r;
@@ -228,10 +230,10 @@ class jt extends st {
228
230
  }
229
231
  async trajectory(t, a, i, o, n = !0, s = {}) {
230
232
  await this.checkToken(s);
231
- const r = await this.realTimePosition(t, s), c = w(a), u = w(i), m = [];
233
+ const r = await this.realTimePosition(t, s), c = w(a), u = w(i), l = [];
232
234
  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;
235
+ await this.trajectoryIn30Day(t, c, c.clone().add(30, "day"), r, o, l, s), c.add(30, "day");
236
+ return await this.trajectoryIn30Day(t, c, u, r, o, l, s), l;
235
237
  }
236
238
  async trajectoryIn30Day(t, a, i, o, n, s, r = {}) {
237
239
  var y, F, I, p, v;
@@ -246,15 +248,15 @@ class jt extends st {
246
248
  }
247
249
  };
248
250
  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;
251
+ const l = await L.post(c, u).json();
252
+ if (l.code)
253
+ return M == null || M.warn("[%s] fetch trajectory failed: %j", r.requestId, c, { message: l.message, status: l.status, code: l.code }), l;
252
254
  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
+ const b = w(`${(p = (I = l.data) == null ? void 0 : I[0]) == null ? void 0 : p.postime} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
256
+ return (v = l.data) == null || v.forEach((d) => {
255
257
  for (const P in d)
256
258
  !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 = {
259
+ const g = w(`${d.postime} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00"), m = d.status, { labelCn: h, labelEn: k } = this.parseStatus(m), S = {
258
260
  mmsi: d.mmsi,
259
261
  imo: o == null ? void 0 : o.imo,
260
262
  lat: d.lat,
@@ -263,7 +265,7 @@ class jt extends st {
263
265
  cog: d.cog,
264
266
  hdg: d.hdg,
265
267
  draught: d.draught,
266
- status: l,
268
+ status: m,
267
269
  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
270
  destination: d.dest,
269
271
  positionTime: g.unix(),
@@ -297,7 +299,7 @@ class Et extends st {
297
299
  for (const b in s)
298
300
  !isNaN(s[b]) && Number(s[b]) !== 1 / 0 && (s[b] = Number(s[b]));
299
301
  s.status = s.sp > 3 ? 0 : 1;
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");
302
+ const r = s.status, { labelCn: c, labelEn: u } = this.parseStatus(r), l = w(`${s.ti} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
301
303
  return {
302
304
  mmsi: s.m,
303
305
  name: s.n,
@@ -318,8 +320,8 @@ class Et extends st {
318
320
  dwt: s.dwt,
319
321
  build: s.buildyear,
320
322
  flag: s.fn,
321
- positionTime: m.unix(),
322
- utc: m.utc().format(),
323
+ positionTime: l.unix(),
324
+ utc: l.utc().format(),
323
325
  status: r,
324
326
  labelCn: c,
325
327
  labelEn: u,
@@ -379,13 +381,13 @@ class Et extends st {
379
381
  return s.sort((r, c) => c.score - r.score), s;
380
382
  }
381
383
  async trajectory(t, a, i, o, n = !0, s = {}) {
382
- var d, g, l;
384
+ var d, g, m;
383
385
  const r = await this.realTimePosition(t, s);
384
386
  let c = w(a);
385
- const u = w(i), m = w();
387
+ const u = w(i), l = w();
386
388
  if (n) {
387
389
  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");
390
+ 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 = l.diff(u, "d", !0), u.add(h > 10 ? 240 : h * 24, "h");
389
391
  }
390
392
  const f = {
391
393
  searchParams: {
@@ -400,7 +402,7 @@ class Et extends st {
400
402
  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
403
  const I = [];
402
404
  let p = -1;
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");
405
+ const v = w(`${(m = F == null ? void 0 : F[0]) == null ? void 0 : m.ti} +08:00`, "YYYY-MM-DD HH:mm:ss +08:00");
404
406
  for (const h of F) {
405
407
  for (const A in h)
406
408
  !isNaN(h[A]) && Number(h[A]) !== 1 / 0 && (h[A] = Number(h[A]));
@@ -474,7 +476,7 @@ class Nt extends st {
474
476
  }
475
477
  async trajectory(t, a, i, o, n = !0, s = {}) {
476
478
  var v;
477
- const r = await this.realTimePosition(t, s), c = w(a), u = w(i), m = "https://api.shipxy.com/apicall/GetShipTrack", f = {
479
+ const r = await this.realTimePosition(t, s), c = w(a), u = w(i), l = "https://api.shipxy.com/apicall/GetShipTrack", f = {
478
480
  searchParams: {
479
481
  id: t,
480
482
  k: this.token,
@@ -483,13 +485,13 @@ class Nt extends st {
483
485
  btm: c.unix(),
484
486
  etm: u.unix()
485
487
  }
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)
488
+ }, b = await L.get(l, f).json();
489
+ if (M == null || M.info("[%s] fetch trajectory from: %s - %j", s.requestId, l, f), (b == null ? void 0 : b.status) !== 0)
488
490
  return b;
489
491
  const y = b == null ? void 0 : b.points, F = [], I = w.unix((v = y[0]) == null ? void 0 : v.utc);
490
492
  let p = -1;
491
493
  for (const d of y) {
492
- const g = w.unix(d.utc), l = {
494
+ const g = w.unix(d.utc), m = {
493
495
  imo: r == null ? void 0 : r.imo,
494
496
  mmsi: t,
495
497
  sog: Math.round(d.sog * 3600 / 1e3 / 1852 * 100) / 100,
@@ -501,7 +503,7 @@ class Nt extends st {
501
503
  method: "trajectory",
502
504
  vendor: "shipxy"
503
505
  }, h = Math.floor(g.diff(I, "minute", !0) / (o || 1));
504
- h !== p && (p = h, F.push(l));
506
+ h !== p && (p = h, F.push(m));
505
507
  }
506
508
  return F;
507
509
  }
@@ -559,7 +561,7 @@ class Tt extends st {
559
561
  const c = r.data[0];
560
562
  for (const y in c)
561
563
  !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);
564
+ const { labelCn: u, labelEn: l } = await this.parseStatus(c.aisNavStatus), f = w.unix(c.posTime);
563
565
  return {
564
566
  ...o,
565
567
  mmsi: t,
@@ -572,17 +574,17 @@ class Tt extends st {
572
574
  positionTime: c.posTime,
573
575
  utc: f.utc().format(),
574
576
  status: c.aisNavStatus,
575
- labelEn: m,
577
+ labelEn: l,
576
578
  labelCn: u,
577
579
  method: "position",
578
580
  vendor: "myship"
579
581
  };
580
582
  }
581
583
  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 = [];
584
+ const r = w(a), c = w(i), u = await this.getShipId(t), l = await this.getShipInfo(u), f = [];
583
585
  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;
586
+ await this.trajectoryIn30Day(u, r.unix(), r.add(30, "day").unix(), l, t, o, f);
587
+ return await this.trajectoryIn30Day(u, r.unix(), c.unix(), l, t, o, f), f;
586
588
  }
587
589
  async trajectoryIn30Day(t, a, i, o, n, s, r, c = {}) {
588
590
  var I;
@@ -595,8 +597,8 @@ class Tt extends st {
595
597
  startTime: a,
596
598
  endTime: i
597
599
  }
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
+ }, l = "https://api3.myships.com/sp/ships/position/history", f = await L.post(l, u).json();
601
+ if (M == null || M.info("[%s] fetch trajectory from: %s - %j", c.requestId, l, u), f.code !== "0")
600
602
  return M == null || M.warn("[%s] invoke myship trajectory failed: %j", c.requestId, f), f;
601
603
  const b = f.data;
602
604
  for (const p in b)
@@ -647,12 +649,12 @@ class yt {
647
649
  return;
648
650
  const n = {};
649
651
  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)
652
+ const l = (c = (r = o[u].match(a)) == null ? void 0 : r[0]) == null ? void 0 : c.split("],");
653
+ if (u === 0 && !l)
652
654
  n.scope = o[0];
653
- else if (m)
654
- for (let f = 0, b = m.length; f < b; f++) {
655
- const y = this.parseRule(m[f]);
655
+ else if (l)
656
+ for (let f = 0, b = l.length; f < b; f++) {
657
+ const y = this.parseRule(l[f]);
656
658
  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);
657
659
  }
658
660
  }
@@ -686,14 +688,14 @@ class yt {
686
688
  * @param options
687
689
  */
688
690
  checkWeather(e, t, a = {}) {
689
- var y, F, I, p, v, d, g, l, h, k, S, D, P, N, A;
691
+ var y, F, I, p, v, d, g, m, h, k, S, D, P, N, A;
690
692
  let i = 0, o = 0, n = 0, s = 0;
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;
693
+ 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, l = Math.round((((m = (g = t == null ? void 0 : t.SEVERE) == null ? void 0 : g.wind) == null ? void 0 : m.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
694
  for (let x = 0; x < (e == null ? void 0 : e.length); x++) {
693
695
  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;
696
+ 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: l, svThd4Wd: f, hvThd4Wd: b }), (R == null ? void 0 : R.scale) >= l ? (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;
695
697
  }
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 } };
698
+ 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: l, svThd4Wd: f, hvThd4Wd: b }, sig: { dgThd4Wv: r, svThd4Wv: c, hvThd4Wv: u } };
697
699
  }
698
700
  }
699
701
  const xt = new yt();
@@ -861,10 +863,10 @@ class O {
861
863
  } catch (y) {
862
864
  C.warn("[%s] meteo2 spot(%j) forecast failed: %s", r.requestId, { ...t, eta: a.utc().format(), source: i }, y);
863
865
  }
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;
866
+ const l = O.weatherFactor(e, u), f = O.currentFactor(e.bearing, u == null ? void 0 : u.current, o), b = Math.round((e.speed * 1.943844 + l + f) * 100) / 100;
865
867
  c = {
866
868
  meteo: { ...u },
867
- wxFactor: m,
869
+ wxFactor: l,
868
870
  cFactor: f,
869
871
  speed: t.velocity && s ? t.velocity : b < 0 ? 1 : b,
870
872
  eta: a.utc().format(),
@@ -896,7 +898,7 @@ class O {
896
898
  */
897
899
  static async speedLoseInHoursStep(e, t, a, i, o, n, s = "", r = !0, c = !1, u = {}) {
898
900
  t.utc();
899
- const m = t.clone().add(14, "days"), f = [], b = [];
901
+ const l = t.clone().add(14, "days"), f = [], b = [];
900
902
  let y = 0, F = 0, I, p;
901
903
  for (let v = 0; v < n.length - 1; v++) {
902
904
  let d = n[v];
@@ -915,17 +917,17 @@ class O {
915
917
  return d.distanceFromPrevious = F, { etd: t, from: p || d, to: d, next: n.filter((S) => S), wps: f, days: b };
916
918
  } else
917
919
  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;
920
+ r = t.isAfter(l) ? !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"));
921
+ const m = W.calculateDistance(d, g, !g.gcToPrevious);
922
+ let h = Math.round(m / p.speed * 1e5) / 1e5;
921
923
  if (y + h < i) {
922
924
  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`,
925
+ `[%s] go to %j from %j with ${m}nm, and cost ${h} hours`,
924
926
  u.requestId,
925
927
  { lat: g.lat, lng: g.lng },
926
928
  { lat: p.lat, lng: p.lng, etd: p.etd }
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];
929
+ ), F += m, n.filter((k) => k).length <= 1) {
930
+ I = g, I.eta = t.utc().format(), I.distanceFromPrevious = m, I.distanceFromStart = Math.round((o + F) * 1e4) / 1e4, f.push(I), delete n[v + 1];
929
931
  break;
930
932
  }
931
933
  } else {
@@ -961,10 +963,10 @@ class O {
961
963
  * @param wwc 气象要素
962
964
  */
963
965
  static weatherFactor(e, t) {
964
- var m, f, b, y, F, I, p;
966
+ var l, f, b, y, F, I, p;
965
967
  C == null || C.debug("calculate weather factor via: %j", { ...e, ...t });
966
968
  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));
969
+ let n = Math.abs(e.bearing % 360 - (((l = t == null ? void 0 : t.wind) == null ? void 0 : l.degree) % 360 || 0));
968
970
  n = n > 180 ? 360 - n : n;
969
971
  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
972
  let c = s * o * r / 100 * e.speed;
@@ -987,7 +989,7 @@ class O {
987
989
  */
988
990
  static async analyseInstant(e, t, a, i, o, n = "", s = 0, r = !0, c = !1, u = {}) {
989
991
  var K, G, X, Q, Z, $;
990
- const m = w().valueOf();
992
+ const l = w().valueOf();
991
993
  e.lng = _.convertToStdLng(e.lng);
992
994
  const { route: f, waypoints: b } = o.points, y = W.calculateSubRoute(e, f);
993
995
  if (((K = y[0]) == null ? void 0 : K.length) <= 1)
@@ -1014,23 +1016,23 @@ class O {
1014
1016
  wps: []
1015
1017
  };
1016
1018
  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;
1019
+ let m = W.simplifyRouteToCoordinates(y, v, 0), h = 0, k = 0, S = 0, D = 0;
1018
1020
  t = w(t).utc();
1019
1021
  const P = t.clone();
1020
- for (; l.length > 0; ) {
1022
+ for (; m.length > 0; ) {
1021
1023
  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(
1022
1024
  p,
1023
1025
  t,
1024
1026
  P,
1025
1027
  B,
1026
1028
  h,
1027
- l,
1029
+ m,
1028
1030
  n,
1029
1031
  r,
1030
1032
  c,
1031
1033
  u
1032
1034
  );
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;
1035
+ (G = j.from) != null && G.speed && (g.hours.push(j.from), g.wps.push(...j.wps), g.days.push(...j.days)), m = j == null ? void 0 : j.next, m.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;
1034
1036
  }
1035
1037
  const N = g.hours;
1036
1038
  for (let Y = 0; Y < N.length - 1; Y++) {
@@ -1054,7 +1056,7 @@ class O {
1054
1056
  hoursInECA: q,
1055
1057
  totalDgoConsInECA: R
1056
1058
  }, 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;
1059
+ const et = w().valueOf() - l, ot = (($ = g == null ? void 0 : g.hours) == null ? void 0 : $.length) || 1;
1058
1060
  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;
1059
1061
  }
1060
1062
  /**
@@ -1065,12 +1067,14 @@ class O {
1065
1067
  * @param vessel 船舶属性 @see VesselAssemble, 注意吃水为船舶实时吃水,非档案中的固定吃水,一般可以从ais获取; 如获取不得,用档案吃水代替
1066
1068
  * @param cp { loadCondition, speed } LoadCondition: Ballast or Laden, speed(kts)
1067
1069
  * @param route 航路[[[lng, lat]]]
1070
+ * @param waypoints
1068
1071
  * @param source 气象数据源,GFS or CMEMES, 默认CMEMS
1069
1072
  * @param stepHrs
1070
1073
  * @param useMeteo true 启用气象分析
1071
1074
  * @param useRouteParam
1075
+ * @param options
1072
1076
  */
1073
- static async analyseInstantWithThreshed(e, t, a, i, o, n, s, r = "", c = 3, u = !0, m = !1, f = {}) {
1077
+ static async analyseInstantWithThreshed(e, t, a, i, o, n, s, r = "", c = 3, u = !0, l = !1, f = {}) {
1074
1078
  var X, Q, Z, $, Y, B;
1075
1079
  const b = w().valueOf();
1076
1080
  e.lng = _.convertToStdLng(e.lng);
@@ -1087,7 +1091,7 @@ class O {
1087
1091
  return;
1088
1092
  const v = s.length ? W.calculateSubWaypoints(e, s) : [];
1089
1093
  v.forEach((j) => j.important = !0);
1090
- let d = W.simplifyRouteToCoordinates(p, v, 0), g = 0, l = 0, h = 0, k = 0;
1094
+ let d = W.simplifyRouteToCoordinates(p, v, 0), g = 0, m = 0, h = 0, k = 0;
1091
1095
  const S = {
1092
1096
  hours: [],
1093
1097
  wps: [],
@@ -1099,7 +1103,7 @@ class O {
1099
1103
  const j = c - t.hour() % c;
1100
1104
  let V = Math.ceil(t.clone().add(j, "h").set({ minute: 0, second: 0, millisecond: 0 }).diff(t, "h", !0) * 1e4) / 1e4;
1101
1105
  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);
1106
+ const H = await O.speedLoseInHoursStep(I, t, D, V, g, d, r, u, l, f);
1103
1107
  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)
1104
1108
  break;
1105
1109
  }
@@ -1115,7 +1119,7 @@ class O {
1115
1119
  const P = S.hours;
1116
1120
  for (let j = 0; j < P.length - 1; j++) {
1117
1121
  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;
1122
+ m += P[j].wxFactor * V, h += P[j].cFactor * V, k += V;
1119
1123
  }
1120
1124
  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
1125
  sample: S,
@@ -1123,7 +1127,7 @@ class O {
1123
1127
  // 注意,可能会在first节点Drift,所有采用eta做为初始出发时间
1124
1128
  etd: w(N.eta).utc().format(),
1125
1129
  eta: w(A == null ? void 0 : A.eta).utc().format(),
1126
- wxFactor: Math.round(l / k * 1e3) / 1e3,
1130
+ wxFactor: Math.round(m / k * 1e3) / 1e3,
1127
1131
  cFactor: Math.round(h / k * 1e3) / 1e3,
1128
1132
  avgSpeed: Math.round(((A == null ? void 0 : A.distanceFromStart) || 0) / k * 1e3) / 1e3,
1129
1133
  totalHrs: Math.round(k * 1e3) / 1e3,
@@ -1169,35 +1173,35 @@ class O {
1169
1173
  c = c < g ? g : c;
1170
1174
  }), c = c * 1.3;
1171
1175
  const u = w.utc(e.etd).add(c ?? 14, "day");
1172
- let m = 1;
1176
+ let l = 1;
1173
1177
  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(
1178
+ const g = JSON.parse(JSON.stringify(i.route)), m = JSON.parse(JSON.stringify(i.waypoints)), h = await O.analyseInstantWithThreshed(
1175
1179
  { lat: e.lat, lng: e.lng },
1176
1180
  e.etd,
1177
1181
  u,
1178
1182
  t,
1179
1183
  d,
1180
1184
  g,
1181
- l,
1185
+ m,
1182
1186
  e.meteoVendor,
1183
1187
  e.speedStep,
1184
1188
  e.useMeteo,
1185
1189
  e.useRouteParam,
1186
1190
  o
1187
1191
  );
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(), {
1192
+ 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, l, e.etd, u.format(), {
1189
1193
  cost: h.cost.total,
1190
1194
  hire: h.cost.hire,
1191
1195
  bunker: h.cost.bunker,
1192
1196
  distance: h.distance,
1193
1197
  hours: h.totalHrs,
1194
1198
  cp: `${d.speed}/${d.fo}/${d.dgo}`
1195
- })), m++;
1199
+ })), l++;
1196
1200
  }
1197
1201
  s.sort((d, g) => d.cost.total - g.cost.total);
1198
1202
  const f = s.at(0), b = s.at(1), y = [];
1199
1203
  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);
1204
+ const d = f.cost.cp, g = b.cost.cp, m = w(f.eta), h = w(f.etd), k = m.diff(h, "days", !0);
1201
1205
  let S = Math.ceil(k / 2);
1202
1206
  S = S > 7 ? 7 : S < e.alterStep ? e.alterStep : S;
1203
1207
  let D = 2, P = { combined: !1, speeds: [b], cost: (v = b.cost) == null ? void 0 : v.total }, N;
@@ -1224,15 +1228,15 @@ class O {
1224
1228
  */
1225
1229
  static async combinedAnalyse(e, t, a, i, o, n, s = {}) {
1226
1230
  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);
1231
+ const r = await O.alternateAnalyse(e, t, a, i, 0, o, n, s), c = r.reduce((g, m) => g + m.cost.total, 0), u = r.reduce((g, m) => g + m.cost.hire, 0), l = r.reduce((g, m) => g + m.cost.bunker, 0), f = r.reduce((g, m) => g + m.distance, 0), b = r.reduce((g, m) => g + m.totalHrs, 0);
1228
1232
  C == null || C.info("[%s][L%d] cost with cpa/cpb turn: %j", s.requestId, s.level, {
1229
1233
  cost: c,
1230
1234
  hire: u,
1231
- bunker: m,
1235
+ bunker: l,
1232
1236
  distance: f,
1233
1237
  hours: b
1234
1238
  });
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);
1239
+ const y = await O.alternateAnalyse(e, t, a, i, 1, o, n, s), F = y.reduce((g, m) => g + m.cost.total, 0), I = y.reduce((g, m) => g + m.cost.hire, 0), p = y.reduce((g, m) => g + m.cost.bunker, 0), v = y.reduce((g, m) => g + m.distance, 0), d = y.reduce((g, m) => g + m.totalHrs, 0);
1236
1240
  return C == null || C.info("[%s][L%d] cost with cpb/cpa turn: %j", s.requestId, s.level, {
1237
1241
  cost: F,
1238
1242
  hire: I,
@@ -1255,7 +1259,7 @@ class O {
1255
1259
  static async alternateAnalyse(e, t, a, i, o, n, s, r = {}) {
1256
1260
  var f, b;
1257
1261
  let c = w.utc(e.etd);
1258
- const u = { lat: e.lat, lng: e.lng }, m = [];
1262
+ const u = { lat: e.lat, lng: e.lng }, l = [];
1259
1263
  for (; c.isBefore(a); ) {
1260
1264
  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
1265
  u,
@@ -1289,11 +1293,11 @@ class O {
1289
1293
  )), r.counter = r.counter + 1;
1290
1294
  const d = (b = (f = v == null ? void 0 : v.sample) == null ? void 0 : f.hours) == null ? void 0 : b.at(-1);
1291
1295
  if (d)
1292
- u.lat = d.lat, u.lng = d.lng, c = w(d.eta), m.push(v), o = o ? 0 : 1;
1296
+ u.lat = d.lat, u.lng = d.lng, c = w(d.eta), l.push(v), o = o ? 0 : 1;
1293
1297
  else
1294
1298
  break;
1295
1299
  }
1296
- return m;
1300
+ return l;
1297
1301
  }
1298
1302
  /**
1299
1303
  * 计算Speed的cost
@@ -1320,7 +1324,7 @@ class O {
1320
1324
  *
1321
1325
  */
1322
1326
  static async calculateECA(e, t, a = {}) {
1323
- var r, c, u, m;
1327
+ var r, c, u, l;
1324
1328
  const i = await W.intersectInECA((e == null ? void 0 : e.route) || []);
1325
1329
  let o = 0, n = 0, s = 0;
1326
1330
  (c = (r = e == null ? void 0 : e.sample) == null ? void 0 : r.wps) == null || c.forEach((f) => {
@@ -1328,7 +1332,7 @@ class O {
1328
1332
  });
1329
1333
  for (const f of i) {
1330
1334
  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);
1335
+ const b = await W.deadReckoningTime((u = f.waypoints) == null ? void 0 : u.at(0), e.sample.wps), y = await W.deadReckoningTime((l = f.waypoints) == null ? void 0 : l.at(-1), e.sample.wps);
1332
1336
  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;
1333
1337
  }
1334
1338
  return o = _.roundPrecision(o, 3), n = _.roundPrecision(n, 3), s = _.roundPrecision(s, 3), {
@@ -1349,28 +1353,28 @@ class O {
1349
1353
  hours: [],
1350
1354
  wps: [],
1351
1355
  days: []
1352
- }, i = e.reduce((l, h) => l + h.distance, 0), o = e.reduce((l, h) => {
1356
+ }, i = e.reduce((m, h) => m + h.distance, 0), o = e.reduce((m, h) => {
1353
1357
  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) => {
1358
+ return m + (((k = h.extend) == null ? void 0 : k.distanceInECA) || 0);
1359
+ }, 0), n = e.reduce((m, h) => m + h.totalHrs, 0), s = e.reduce((m, h) => {
1356
1360
  var k;
1357
- return l + (((k = h.extend) == null ? void 0 : k.hoursInECA) || 0);
1358
- }, 0), r = e.reduce((l, h) => {
1361
+ return m + (((k = h.extend) == null ? void 0 : k.hoursInECA) || 0);
1362
+ }, 0), r = e.reduce((m, h) => {
1359
1363
  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 = [];
1364
+ return m + (((k = h.extend) == null ? void 0 : k.totalDgoConsInECA) || 0);
1365
+ }, 0), c = e.reduce((m, h) => m + h.wxFactor * h.totalHrs / n, 0), u = e.reduce((m, h) => m + h.cFactor * h.totalHrs / n, 0), l = e.reduce((m, h) => m + h.totalFoCons, 0), f = e.reduce((m, h) => m + h.totalDgoCons, 0), b = e.reduce((m, h) => m + h.cost.total, 0), y = e.reduce((m, h) => m + h.cost.hire, 0), F = e.reduce((m, h) => m + h.cost.bunker, 0), I = [], p = [];
1362
1366
  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);
1367
+ for (const m of e) {
1368
+ p.push(...((d = m.extend) == null ? void 0 : d.eca) || []);
1369
+ const h = m.sample.hours, k = m.sample.wps, S = m.sample.days, D = h.at(0);
1366
1370
  v && (D.distanceFromPrevious = v.distanceFromPrevious, D.distanceFromStart = v.distanceFromStart, h.forEach((x, T) => {
1367
1371
  T && (x.distanceFromStart = x.distanceFromStart + v.distanceFromStart);
1368
1372
  }), k.at(0).distanceFromPrevious = v.distanceFromPrevious, k.at(0).distanceFromStart = v.distanceFromStart, k.forEach((x, T) => {
1369
1373
  T && (x.distanceFromStart = x.distanceFromStart + v.distanceFromStart);
1370
1374
  }), S.at(0).distanceFromPrevious = v.distanceFromPrevious, S.at(0).distanceFromStart = v.distanceFromStart, S.forEach((x, T) => {
1371
1375
  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);
1376
+ })), D.cp = m.cost.cp;
1377
+ const P = [m.etd, m.eta], N = I.findIndex((x) => x.id === D.cp.id);
1374
1378
  N === -1 ? (D.cp.segment = [P], I.push(D.cp)) : I[N].segment.push(P), h.forEach((x) => {
1375
1379
  var q;
1376
1380
  ((q = a.hours) == null ? void 0 : q.findIndex((R) => R.eta === x.eta)) === -1 && a.hours.push(x);
@@ -1384,14 +1388,14 @@ class O {
1384
1388
  const A = (g = a.wps) == null ? void 0 : g.findIndex((x) => x.eta === D.eta);
1385
1389
  A === -1 ? a.wps.push(D) : a.wps[A] = D, v = h.at(-1);
1386
1390
  }
1387
- return a.wps.sort((l, h) => {
1388
- w(l.etd).unix() - w(h.etd).unix();
1389
- }), a.wps.forEach((l, h) => {
1391
+ return a.wps.sort((m, h) => {
1392
+ w(m.etd).unix() - w(h.etd).unix();
1393
+ }), a.wps.forEach((m, h) => {
1390
1394
  const k = a.wps[h - 1];
1391
1395
  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);
1396
+ const S = m.distanceFromStart - (k.distanceFromStart || 0), D = w(m.eta || m.etd).diff(w(k.etd || k.eta), "hour", !0), P = Math.round(S / D * 100) / 100;
1397
+ m.avgSpd = P;
1398
+ const N = W.calculateBearing(k, m);
1395
1399
  k.bearing = N;
1396
1400
  }
1397
1401
  }), {
@@ -1407,7 +1411,7 @@ class O {
1407
1411
  avgSpeed: Math.round(i / n * 1e3) / 1e3,
1408
1412
  wxFactor: Math.round(c * 1e3) / 1e3,
1409
1413
  cFactor: Math.round(u * 1e3) / 1e3,
1410
- totalFoCons: Math.round(m * 1e3) / 1e3,
1414
+ totalFoCons: Math.round(l * 1e3) / 1e3,
1411
1415
  totalDgoCons: Math.round(f * 1e3) / 1e3,
1412
1416
  cost: {
1413
1417
  total: Math.round(b * 1e3) / 1e3,
@@ -1 +1 @@
1
- (function(q,A){typeof exports=="object"&&typeof module<"u"?A(exports,require("got"),require("@log4js-node/log4js-api"),require("moment"),require("@idm-plugin/geo2"),require("@idm-plugin/meteo2"),require("@idm-plugin/meteo")):typeof define=="function"&&define.amd?define(["exports","got","@log4js-node/log4js-api","moment","@idm-plugin/geo2","@idm-plugin/meteo2","@idm-plugin/meteo"],A):(q=typeof globalThis<"u"?globalThis:q||self,A(q["idm-plugin-vessel"]={},q.got,q["@log4js-node/log4js-api"],q.moment,q["@idm-plugin/geo2"],q["@idm-plugin/meteo2"],q["@idm-plugin/meteo"]))})(this,function(q,A,U,g,H,ft,nt){"use strict";var It=Object.defineProperty;var St=(q,A,U)=>A in q?It(q,A,{enumerable:!0,configurable:!0,writable:!0,value:U}):q[A]=U;var K=(q,A,U)=>(St(q,typeof A!="symbol"?A+"":A,U),U);let p;try{p=U.getLogger("vessel")}catch{}finally{}class G{parseStatus(s){let t,a;switch(s){case 0:t="在航(主机推动)",a="Underway Using Engine";break;case 1:t="锚泊",a="Anchored";break;case 2:t="失控",a="Not under command";break;case 3:t="操纵受限",a="Limited airworthiness";break;case 4:t="吃水受限",a="Limited by ship's draft";break;case 5:t="靠泊",a="Mooring";break;case 6:t="搁浅",a="Stranded";break;case 7:t="捕捞作业",a="Engaged in fishing";break;case 8:t="靠帆船提供动力",a="Sailing";break;default:t="未定义",a="Undefined"}return{labelCn:t,labelEn:a}}}class mt extends G{constructor(t,a){super();K(this,"clientId");K(this,"clientSecret");K(this,"token");this.clientId=t,this.clientSecret=a}async authToken(t={}){const a="https://svc.data.myvessel.cn/ada/oauth/token",i={searchParams:{client_id:this.clientId,client_secret:this.clientSecret,grant_type:"client_credentials"}},o=await A.post(a,i).json();p==null||p.info("[%s] fetch access token from: %s - %j",t.requestId,a,o),o.error||(this.token={accessToken:o.access_token,tokenType:o.token_type,expiresIn:o.expires_in,scope:o.scope,jti:o.jti,issuedAt:g().utc().format()})}async checkToken(t={}){var a;return(!this.token||g().diff(g(this.token.issuedAt),"seconds")>(((a=this.token)==null?void 0:a.expiresIn)||0)-300)&&await this.authToken(t),this.token}async suggest(t,a={}){var e,c;await this.checkToken(a);const i="https://market.myvessel.cn/sdc/v1/mkt/vessels/fuzzy",o={headers:{Authorization:`${(e=this.token)==null?void 0:e.tokenType} ${(c=this.token)==null?void 0:c.accessToken}`},json:{kw:t,recordNum:a.ps||10}};p==null||p.info("[%s] fetch suggest vessels from: %s - %j",a.requestId,i,o);const n=await A.post(i,o).json();return n.code?(p==null||p.warn("[%s] fetch suggest vessels failed: %j",a.requestId,{message:n.message,status:n.status,code:n.code}),[]):n.data.map(u=>({mmsi:u.mmsi,name:u.nameEn,nameCn:u.nameCn,imo:Number.isNaN(u.imo)?null:Number(u.imo),callSign:u.callsign,type:u.vesselTypeNameEn,flagName:u.flagCtry,vendor:"myvessel",raw:u}))}async search(t,a={}){var r,u;await this.checkToken(a);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},e={headers:{Authorization:`${(r=this.token)==null?void 0:r.tokenType} ${(u=this.token)==null?void 0:u.accessToken}`},searchParams:n};p==null||p.info("[%s] fetch vessel from: %s - %j",a.requestId,o,e);const c=await A.get(o,e).json();if(c.status!==200)return p==null||p.warn("[%s] fetch suggest vessels failed: %j",a.requestId,{message:c.message,status:c.status,code:c.code}),{};{const f=c.data;return{mmsi:f.mmsi,imo:Number.isNaN(f.imo)?null:Number(f.imo),callSign:f.callsign,name:f.nameEn,nameCn:f.nameCn,type:f.vesselTypeNameEn,flagName:f.flagCtry,clasz:f.classSociety,dateOfBuild:f.buildYearMonth,deadweight:f.dwt,grossTonnage:f.grt,netTonnage:f.net,teu:f.teu,length:f.length,breadth:f.width,height:f.height,draught:f.draught,speed:f.speed,passengerCapacity:f.passengercapacity,vendor:"myvessel",raw:f}}}async archives(t,a={}){var e,c;await this.checkToken(a);const i="https://svc.data.myvessel.cn/sdc/v1/ship/info/batch",o={headers:{Authorization:`${(e=this.token)==null?void 0:e.tokenType} ${(c=this.token)==null?void 0:c.accessToken}`},json:{mmsiList:typeof t=="number"?[t]:t}};p==null||p.info("[%s] fetch vessel archive from: %s - %j",a.requestId,i,o);const n=await A.post(i,o).json();return n.status!==200?(p==null||p.warn("[%s] fetch vessel archive failed: %j",a.requestId,{message:n.message,status:n.status,code:n.code}),{}):n.data}async realTimePosition(t,a={}){var c,r;await this.checkToken(a);const i="https://svc.data.myvessel.cn/sdc/v1/vessels/status/location/unit",o={headers:{Authorization:`${(c=this.token)==null?void 0:c.tokenType} ${(r=this.token)==null?void 0:r.accessToken}`},searchParams:{mmsi:t}};p==null||p.info("[%s] fetch realtime position from: %s - %j",a.requestId,i,o);const n=await A.get(i,o).json();if(n.code)return p==null||p.warn("[%s] fetch realtime position failed: %j",a.requestId,{message:n.message,status:n.status,code:n.code}),n;const e=n.data;for(const u in e)!isNaN(e[u])&&Number(e[u])!==1/0&&(e[u]=Number(e[u]));if(e){const u=g(`${e.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return{mmsi:e.mmsi,name:e.vesselName||e.aisVesselName,imo:e.imo,callSign:e.callsign||e.aisCallSign,lat:e.lat,lng:e.lon,length:e.length,width:e.width,draught:e.currDraught,sog:e.sog,cog:e.cog,hdg:e.hdg,rot:e.rot,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(e.eta)?g.utc(e.eta).format():void 0,destination:e.dest,positionTime:u.unix(),status:e.status,labelCn:e.statusNameCn,labelEn:e.statusNameEn,vesselType:e.vesselTypeNameEn,flag:e.flagCtryNameEn,clasz:e.classSociety,build:e.buildYear,dwt:e.dwt,grt:e.grt,net:e.net,method:"position",vendor:"myVessel",utc:u.utc().format()}}else return{}}async trajectory(t,a,i,o,n=!0,e={}){await this.checkToken(e);const c=await this.realTimePosition(t,e),r=g(a),u=g(i),f=[];for(;u.diff(r,"day",!0)>30;)await this.trajectoryIn30Day(t,r,r.clone().add(30,"day"),c,o,f,e),r.add(30,"day");return await this.trajectoryIn30Day(t,r,u,c,o,f,e),f}async trajectoryIn30Day(t,a,i,o,n,e,c={}){var y,j,S,w,v;const r="https://svc.data.myvessel.cn/sdc/v1/vessels/status/track",u={headers:{Authorization:`${(y=this.token)==null?void 0:y.tokenType} ${(j=this.token)==null?void 0:j.accessToken}`},json:{mmsi:t,startTime:a.utcOffset(8).format("YYYY-MM-DD HH:mm:ss"),endTime:i.utcOffset(8).format("YYYY-MM-DD HH:mm:ss")}};p==null||p.info("[%s] fetch trajectory from: %s - %j",c.requestId,r,u);const f=await A.post(r,u).json();if(f.code)return p==null||p.warn("[%s] fetch trajectory failed: %j",c.requestId,r,{message:f.message,status:f.status,code:f.code}),f;let m=-1;const b=g(`${(w=(S=f.data)==null?void 0:S[0])==null?void 0:w.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return(v=f.data)==null||v.forEach(d=>{for(const Y in d)!isNaN(d[Y])&&Number(d[Y])!==1/0&&(d[Y]=Number(d[Y]));const M=g(`${d.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00"),h=d.status,{labelCn:l,labelEn:k}=this.parseStatus(h),C={mmsi:d.mmsi,imo:o==null?void 0:o.imo,lat:d.lat,lng:d.lon,sog:d.sog,cog:d.cog,hdg:d.hdg,draught:d.draught,status:h,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(d.eta)?g(`${d.eta} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00").utc().format():void 0,destination:d.dest,positionTime:M.unix(),labelCn:l,labelEn:k,method:"trajectory",vendor:"myVessel",utc:M.utc().format()},x=Math.floor(M.diff(b,"minute",!0)/(n||1));x!==m&&(m=x,e.push(C))}),e}}class yt extends G{constructor(t){super();K(this,"token");this.token=t}async realTimePosition(t,a={}){const i="https://api.hifleet.com/position/position/get/token",o={searchParams:{mmsi:t,usertoken:this.token}},n=await A.post(i,o).json();p==null||p.info("[%s] fetch realtime position from: %s - %j",a.requestId,i,o);const e=n==null?void 0:n.list;if(!e)return p==null||p.warn("[%s] fetch realtime position failed: %j",a.requestId,i,n),n;for(const b in e)!isNaN(e[b])&&Number(e[b])!==1/0&&(e[b]=Number(e[b]));e.status=e.sp>3?0:1;const c=e.status,{labelCn:r,labelEn:u}=this.parseStatus(c),f=g(`${e.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return{mmsi:e.m,name:e.n,imo:e.imonumber,callSign:e.callsign,lat:Math.round(e.la/60*1e5)/1e5,lng:Math.round(e.lo/60*1e5)/1e5,length:e.l,width:e.w,draught:e.draught,sog:e.sp,cog:e.co,hdg:e.h,rot:isNaN(e.rot)?0:e.rot,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(e.eta)?g.utc(e.eta).format():void 0,destination:e.destination,vesselType:e.type,dwt:e.dwt,build:e.buildyear,flag:e.fn,positionTime:f.unix(),utc:f.utc().format(),status:c,labelCn:r,labelEn:u,method:"position",vendor:"hifleet"}}async search(t,a={}){let i="https://www.hifleet.com/hifleetapi/searchVesselOL.do";const o={searchParams:{keyword:t},headers:{Referer:"https://www.hifleet.com",Origin:"https://www.hifleet.com",Host:"www.hifleet.com"}};let n=await A.post(i,o).json();p==null||p.info("[%s] fetch vessel props from: %s - %j",a.requestId,i,o),n instanceof Array&&(n=n[0]);for(const c in n)!isNaN(n[c])&&Number(n[c])!==1/0&&(n[c]=Number(n[c]));const e={mmsi:n.m,name:n.n,imo:n.i,callSign:n.c,length:n.l,breadth:n.b,draught:n.dr,type:n.t};return i="https://www.hifleet.com/hifleetapi/sameShipSearch.do",n=await A.post(i,o).json(),p==null||p.info("[%s] search vessel dead weight from: %s - %j",a.requestId,i,o),n instanceof Array&&(n=n[0]),n&&(e.deadweight=Number(n.dwt)),e}async suggest(t,a={}){const i="https://www.hifleet.com/hifleetapi/getShipSuggest.do",o={searchParams:{q:t},headers:{Referer:"https://www.hifleet.com",Origin:"https://www.hifleet.com",Host:"www.hifleet.com"}},n=await A.post(i,o).json();p==null||p.info("[%s] suggest vessel props from: %s - %j",a.requestId,i,o);const e=[];for(const c of n)e.push({mmsi:!c.mmsi||isNaN(c.mmsi)?null:Number(c.mmsi),name:c.name,callSign:c.callsign,imo:!c.imo||isNaN(c.imo)?null:Number(c.imo),score:c._score});return e.sort((c,r)=>r.score-c.score),e}async trajectory(t,a,i,o,n=!0,e={}){var d,M,h;const c=await this.realTimePosition(t,e);let r=g(a);const u=g(i),f=g();if(n){let l=u.diff(r,"d",!0);l<0?r=u.clone().subtract(40,"d"):l<30?r.subtract(10,"d"):l<60?r.subtract(5,"d"):r=u.clone().subtract(80,"d"),l=f.diff(u,"d",!0),u.add(l>10?240:l*24,"h")}const m={searchParams:{endtime:u.utcOffset("+8:00").format("YYYY-MM-DD HH:mm:ss"),starttime:r.utcOffset("+8:00").format("YYYY-MM-DD HH:mm:ss"),mmsi:t,usertoken:this.token}},b="https://api.hifleet.com/position/trajectory/nocompressed/withstatic/token",y=await A.get(b,m).json();p==null||p.info("[%s] fetch trajectory from: %s - %j",e.requestId,b,m);let j;y&&(j=((M=(d=y.ships)==null?void 0:d.offors)==null?void 0:M.ship)||[],j.length||p==null||p.warn("[%s] fetch trajectory failed: %j",e.requestId,y));const S=[];let w=-1;const v=g(`${(h=j==null?void 0:j[0])==null?void 0:h.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");for(const l of j){for(const L in l)!isNaN(l[L])&&Number(l[L])!==1/0&&(l[L]=Number(l[L]));const k=g(`${l.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");l.status=l.sp>4?0:1;const{labelEn:C,labelCn:x}=this.parseStatus(l.status),Y={mmsi:l.m,name:l.n,imo:c==null?void 0:c.imo,lat:l.la,lng:l.lo,draught:l.draught,sog:l.sp,cog:l.co,hdg:l.hdg,positionTime:k.unix(),utc:k.utc().format(),status:l.status,labelCn:x,labelEn:C,method:"trajectory",vendor:"hifleet"},T=Math.floor(k.diff(v,"minute",!0)/(o||1));T!==w&&(w=T,S.push(Y))}return S}}class pt extends G{constructor(t){super();K(this,"token");this.token=t}async realTimePosition(t,a={}){const i={searchParams:{id:t,k:this.token,enc:1}},o="https://api.shipxy.com/apicall/GetSingleShip",n=await A.get(o,i).json();if(p==null||p.info("[%s] fetch realtime position from: %s - %j",a.requestId,o,i),(n==null?void 0:n.status)!==0)return n;const e=n.data[0];for(const m in e)!isNaN(e[m])&&Number(e[m])!==1/0&&(e[m]=Number(e[m]));const{labelCn:c,labelEn:r}=await this.parseStatus(e.navistat),u=g.unix(e.lasttime);return{mmsi:e.ShipID,name:e.name,imo:e.imo,callSign:e.callsign,lat:Math.round(e.lat/1e6*1e5)/1e5,lng:Math.round(e.lon/1e6*1e5)/1e5,length:Math.round(e.length/10*100)/100,width:Math.round(e.width/10*100)/100,draught:Math.round(e.draught/1e3*100)/100,sog:Math.round(e.sog*3600/1e3/1852*100)/100,cog:Math.round(e.cog/100*100)/100,hdg:Math.round(e.hdg/100*100)/100,rot:Math.round(e.rot/100*100)/100,positionTime:e.lasttime,utc:u.utc().format(),status:e.navistat,labelEn:r,labelCn:c,method:"position",vendor:"shipxy"}}async trajectory(t,a,i,o,n=!0,e={}){var v;const c=await this.realTimePosition(t,e),r=g(a),u=g(i),f="https://api.shipxy.com/apicall/GetShipTrack",m={searchParams:{id:t,k:this.token,enc:1,cut:0,btm:r.unix(),etm:u.unix()}},b=await A.get(f,m).json();if(p==null||p.info("[%s] fetch trajectory from: %s - %j",e.requestId,f,m),(b==null?void 0:b.status)!==0)return b;const y=b==null?void 0:b.points,j=[],S=g.unix((v=y[0])==null?void 0:v.utc);let w=-1;for(const d of y){const M=g.unix(d.utc),h={imo:c==null?void 0:c.imo,mmsi:t,sog:Math.round(d.sog*3600/1e3/1852*100)/100,cog:Math.round(d.cog/100*100)/100,lat:Math.round(d.lat/1e6*1e5)/1e5,lng:Math.round(d.lon/1e6*1e5)/1e5,positionTime:M.unix(),utc:M.utc().format(),method:"trajectory",vendor:"shipxy"},l=Math.floor(M.diff(S,"minute",!0)/(o||1));l!==w&&(w=l,j.push(h))}return j}}class Mt extends G{constructor(t){super();K(this,"token");this.token=t}async getShipId(t,a={}){const i={headers:{appKey:this.token},json:{mmsiList:t}},o="https://api3.myships.com/sp/ships/getShipIdByMMSI",n=await A.post(o,i).json();return p==null||p.info("[%s] fetch ship id from: %s - %j",a.requestId,o,i),n.code!=="0"?n:n.data[0].shipId}async getShipInfo(t,a={}){const i={headers:{appKey:this.token},json:{shipId:t}},o="https://api3.myships.com/sp/ships/aissta",n=await A.post(o,i).json();if(p==null||p.info("[%s] fetch ship info from: %s - %j",a.requestId,o,i),n.code!=="0")return n;const e=n.data;let c=e.imo;return t==="407170"&&(c="9198379",p==null||p.warn("[%s] ship(%s) imo error: %s, should be %s",a.requestId,t,e.imo,c)),{mmsi:e.mmsi,name:e.shipnameEn,imo:c,callSign:e.callSign,length:e.length,width:e.breadth,draught:(e.draught||100)/10}}async realTimePosition(t,a={}){const i=await this.getShipId(t,a),o=await this.getShipInfo(i,a),n={headers:{appKey:this.token},json:{shipId:i}},e="https://api3.myships.com/sp/ships/position/latest",c=await A.post(e,n).json();p==null||p.info("[%s] fetch realtime position from: %s - %j",a.requestId,e,n);const r=c.data[0];for(const y in r)!isNaN(r[y])&&Number(r[y])!==1/0&&(r[y]=Number(r[y]));const{labelCn:u,labelEn:f}=await this.parseStatus(r.aisNavStatus),m=g.unix(r.posTime);return{...o,mmsi:t,lat:Math.round(r.lat/1e4/60*1e5)/1e5,lng:Math.round(r.lon/1e4/60*1e5)/1e5,sog:Math.round(r.sog/10*100)/100,cog:Math.round(r.cog/10*100)/100,hdg:Math.round(r.heading*100)/100,rot:Math.round(r.rot*100)/100,positionTime:r.posTime,utc:m.utc().format(),status:r.aisNavStatus,labelEn:f,labelCn:u,method:"position",vendor:"myship"}}async trajectory(t,a,i,o,n=!0,e={}){const c=g(a),r=g(i),u=await this.getShipId(t),f=await this.getShipInfo(u),m=[];for(;r.diff(c,"day",!0)>30;)await this.trajectoryIn30Day(u,c.unix(),c.add(30,"day").unix(),f,t,o,m);return await this.trajectoryIn30Day(u,c.unix(),r.unix(),f,t,o,m),m}async trajectoryIn30Day(t,a,i,o,n,e,c,r={}){var S;const u={headers:{appKey:this.token},json:{shipId:t,startTime:a,endTime:i}},f="https://api3.myships.com/sp/ships/position/history",m=await A.post(f,u).json();if(p==null||p.info("[%s] fetch trajectory from: %s - %j",r.requestId,f,u),m.code!=="0")return p==null||p.warn("[%s] invoke myship trajectory failed: %j",r.requestId,m),m;const b=m.data;for(const w in b)!isNaN(b[w])&&Number(b[w])!==1/0&&(b[w]=Number(b[w]));const y=g.unix((S=b[0])==null?void 0:S.posTime);let j=-1;for(const w of b){const v=g.unix(w.posTime),d={imo:o==null?void 0:o.imo,mmsi:n,lat:Math.round(w.lat/1e4/60*1e5)/1e5,lng:Math.round(w.lon/1e4/60*1e5)/1e5,sog:Math.round(w.sog/10*100)/100,cog:Math.round(w.cog/10*100)/100,hdg:Math.round(w.heading*100)/100,rot:Math.round(w.rot*100)/100,positionTime:v.unix(),utc:v.utc().format(),method:"trajectory",vendor:"myship"},M=Math.floor(v.diff(y,"minute",!0)/(e||1));M!==j&&(j=M,c.push(d))}return c}}let z;try{z=U.getLogger("vessel")}catch{}finally{}var ct=(D=>(D.NOTICE="NOTICE",D.WARN="WARN",D.HEAVY="HEAVY",D.SEVERE="SEVERE",D.ERROR="ERROR",D.FATAL="FATAL",D))(ct||{});class dt{parsePrinciple(s,t={}){var e,c,r;z==null||z.debug("[%s] parse rule: %s",t.requestId,s);const a=new RegExp("(?<=\\[)(.+)(?=])","g"),i=s.match(a)?(e=s.match(a))==null?void 0:e[0]:void 0,o=i==null?void 0:i.split(";");if(!o)return;const n={};for(let u=0;u<(o==null?void 0:o.length);u++){const f=(r=(c=o[u].match(a))==null?void 0:c[0])==null?void 0:r.split("],");if(u===0&&!f)n.scope=o[0];else if(f)for(let m=0,b=f.length;m<b;m++){const y=this.parseRule(f[m]);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)}}return n}parseRule(s,t={}){var n;z==null||z.debug("[%s] parse rule: %s",t.requestId,s),s=s.startsWith("[")?s:`[${s}`,s=s.endsWith("]")?s:`${s}]`;const a=new RegExp("(?<=\\[)(.+?)(?=])","g"),i=(n=s==null?void 0:s.match(a))==null?void 0:n[0],o=i==null?void 0:i.split(",");if(o){let e=o[3]==="Number.MAX_VALUE"?100:Number(o[3]);return e=isNaN(e)?1:e,{operator:o[0],number:Number.isNaN(Number(o[1]))?o[1]:Number(o[1]),level:o[2],time:e,key:o[4]}}}checkWeather(s,t,a={}){var y,j,S,w,v,d,M,h,l,k,C,x,Y,T,L;let i=0,o=0,n=0,e=0;const c=Math.round(((j=(y=t==null?void 0:t.SEVERE)==null?void 0:y.sigWave)==null?void 0:j.number)*1.6*100)/100,r=(w=(S=t==null?void 0:t.SEVERE)==null?void 0:S.sigWave)==null?void 0:w.number,u=(d=(v=t==null?void 0:t.HEAVY)==null?void 0:v.sigWave)==null?void 0:d.number,f=Math.round((((h=(M=t==null?void 0:t.SEVERE)==null?void 0:M.wind)==null?void 0:h.number)+2)*100)/100,m=(k=(l=t==null?void 0:t.SEVERE)==null?void 0:l.wind)==null?void 0:k.number,b=(x=(C=t==null?void 0:t.HEAVY)==null?void 0:C.wind)==null?void 0:x.number;for(let N=0;N<(s==null?void 0:s.length);N++){const E=s[N],P=(T=(Y=E==null?void 0:E.meteo)==null?void 0:Y.wave)==null?void 0:T.sig,V=(L=E==null?void 0:E.meteo)==null?void 0:L.wind,J=N?g(E.eta).diff(g(s[N-1].eta),"hour",!0):0;e=J>e?J:e,z==null||z.debug("[%s] check sig.wave: %j",a.requestId,{...P,dgThd4Wv:c,svThd4Wv:r,hvThd4Wv:u}),(P==null?void 0:P.height)>=c?E.isDangerous=!0:(P==null?void 0:P.height)>=r?E.isSevere=!0:(P==null?void 0:P.height)>=u&&(E.isHeavy=!0),z==null||z.debug("[%s] check wind: %j",a.requestId,{...V,dgThd4Wd:f,svThd4Wd:m,hvThd4Wd:b}),(V==null?void 0:V.scale)>=f?(E.isDangerous=!0,delete E.isSevere,delete E.isHeavy):(V==null?void 0:V.scale)>m?(E.isDangerous||(E.isSevere=!0),delete E.isHeavy):(V==null?void 0:V.scale)===b&&!E.isDangerous&&!E.isSevere&&(E.isHeavy=!0),i+=E.isDangerous?J:0,o+=E.isSevere?J:0,n+=E.isHeavy?J:0}return i=Math.round(i*100)/100,o=Math.round(o*100)/100,n=Math.round(n*100)/100,e=Math.round(e),{sample:s,dangerous:i,severe:o,heavy:n,step:e<3?3:e,wind:{dgThd4Wd:f,svThd4Wd:m,hvThd4Wd:b},sig:{dgThd4Wv:c,svThd4Wv:r,hvThd4Wv:u}}}}const bt=new dt;let I;try{I=U.getLogger("vessel")}catch{}finally{}const vt=new ft.MeteoHelper2("",!0);var ut=(D=>(D.common="common",D.container="container",D.tugs="tugs",D))(ut||{}),lt=(D=>(D.Ballast="Ballast",D.Laden="Laden",D))(lt||{}),ht=(D=>(D.Cp="CP",D.Perf="Basis",D.Instruct="Other",D))(ht||{});class W{static blockCoefficient(s,t,a,i){let o=Math.round(s/(t*a*i)*100)/100;o=o<.55?.55:o>.85?.85:o;const n=[.55,.6,.65,.7,.75,.8,.85],e=n.map(c=>Math.abs(c-o));return n[e.indexOf(Math.min(...e))]}static froudeNumber(s,t,a=9.8){let i=Math.round(Math.sqrt(s*s/(a*t))*100)/100;return i=i<.05?.05:i>.3?.3:i,i}static amendFactor(s,t,a){const i={.55:[1.7,-1.4,-7.4],.6:[2.2,-2.5,-9.7],.65:[2.6,-3.7,-11.6],.7:[3.1,-5.3,-12.4],.75:[2.4,-10.6,-9.5],.8:[2.6,-13.1,-15.1],.85:[3.1,-18.7,28]};let n={.55:[1.7,-1.4,-7.4],.6:[2.2,-2.5,-9.7],.65:[2.6,-3.7,-11.6],.7:[3.1,-5.3,-12.4],.75:[2.6,-12.5,-13.5],.8:[3,-16.3,-21.6],.85:[3.4,-20.9,31.8]}[s];return a==="Laden"&&(n=i[s]),n[0]+n[1]*t+n[2]*Math.pow(t,2)}static directionFactor(s,t=0){let a;return s>30&&s<=60?a=(1.7-.03*Math.pow(t-4,2))/2:s>60&&s<=150?a=(.9-.06*Math.pow(t-6,2))/2:s>150&&s<=180?a=(.4-.03*Math.pow(t-8,2))/2:a=1,Math.round(a*1e5)/1e5}static vesselTagFactor(s,t,a,i=0){i=i>6?i-.9*(i-6):i;let o;return a==="container"?o=.7*i+Math.pow(i,6.5)/(22*Math.pow(s,2/3)):t==="Ballast"?o=.7*i+Math.pow(i,6.5)/(2.7*Math.pow(s,2/3)):o=.5*i+Math.pow(i,6.5)/(2.7*Math.pow(s,2/3)),o}static waveHeightFactor(s,t){s=s<3?s*.7:s,s=s<0?.2:s,s=s>6?s-.9*(s-6):s,s=s>9?9:s;let a;return t>30&&t<=60?a=-.6:t>60&&t<=90?a=-.4:t>90&&t<=120?a=s<3?.4:-.3:t>120&&t<=150?a=s<3?.6:-.5:t>150&&t<=180?a=s<3?.7:-.6:a=-.7,Math.round(a*(.144*Math.pow(s,2)+.278*s)*1e4)/1e4}static assembleProperties(s,t,a,i){var m;const o=s.lbp??s.length??s.lengthOverall??198.9642,n=s.draught??8,e=s.breadthMoulded??s.breadth??s.breadthExtreme??32.4572,c=s.deadweight??67035.7773,r=((m=s==null?void 0:s.type)==null?void 0:m.toLowerCase())||"common";return{tag:r.indexOf("container")>-1?"container":r.indexOf("tugs")>-1?"tugs":"common",lbp:o,loadCondition:t,draught:n,breadthMoulded:e,displacement:Math.round((c/1.025+n*e*o*.7)*1e4)/1e4,speed:Math.round((a??14.1382)*1852/3600*1e4)/1e4,bearing:i||90}}static async speedLoseAt(s,t,a,i="",o=2,n=!0,e=!1,c={}){let r;if(t.velocity&&e&&(s.speed=H.LngLatHelper.roundPrecision(t.velocity*1852/3600,6)),n){let u;try{i=(i==null?void 0:i.toUpperCase())==="CMEMS"?"ECMWF":i,i=(i==null?void 0:i.toUpperCase())==="METEO2"?"best_match":i;const{weatherModels:y,marineModels:j}=await nt.Meteo2Assist.autoPickMeteoModel(i),S=await vt.spotForecast(t.lat,t.lng,a.utc().format(),!1,!1,!0,{...c,pastDays:1,forecastDays:1,weatherModels:y,marineModels:j}),[w]=nt.Meteo2Assist.pickHourly(S,a);u=nt.Meteo2Assist.toLegacy(w)}catch(y){I.warn("[%s] meteo2 spot(%j) forecast failed: %s",c.requestId,{...t,eta:a.utc().format(),source:i},y)}const f=W.weatherFactor(s,u),m=W.currentFactor(s.bearing,u==null?void 0:u.current,o),b=Math.round((s.speed*1.943844+f+m)*100)/100;r={meteo:{...u},wxFactor:f,cFactor:m,speed:t.velocity&&e?t.velocity:b<0?1:b,eta:a.utc().format(),etd:a.utc().format()}}else r={wxFactor:0,cFactor:0,speed:t.velocity&&e?t.velocity:Math.round((s.speed*1.943844+0+0)*100)/100,eta:a.utc().format(),etd:a.utc().format()};return delete t.meteo,delete t.wxFactor,delete t.cFactor,delete t.speed,delete t.etd,{...r,...t}}static async speedLoseInHoursStep(s,t,a,i,o,n,e="",c=!0,r=!1,u={}){t.utc();const f=t.clone().add(14,"days"),m=[],b=[];let y=0,j=0,S,w;for(let v=0;v<n.length-1;v++){let d=n[v];d.distanceFromStart=Math.round((o+j)*1e3)/1e3;const M=n[v+1];if(s.bearing=H.LaneHelper.calculateBearing(d,M,!M.gcToPrevious),d.bearing=s.bearing,d.suspend&&r){d.eta=d.eta||t.utc().format(),d.elapsed=d.elapsed??0;const k=d.suspend-d.elapsed;if(i-y>k)i=i-y-k,t.add(k,"hour"),d.elapsed=d.suspend;else{const C=i-y;d.elapsed+=C,t.add(C,"hour"),i=0}if(I==null||I.info(`[%s] suspend ${d.elapsed} hours at %j, and remain ${i} hours need to go...`,u.requestId,d),i===0)return d.distanceFromPrevious=j,{etd:t,from:w||d,to:d,next:n.filter(C=>C),wps:m,days:b}}else d.suspend=0;c=t.isAfter(f)?!1:c,d=await W.speedLoseAt(s,d,t,e,0,c,r,u),w=w||d,d.important&&m.push(d),t.isSameOrAfter(a)&&(b.push(d),a.add(24,"hour"));const h=H.LaneHelper.calculateDistance(d,M,!M.gcToPrevious);let l=Math.round(h/w.speed*1e5)/1e5;if(y+l<i){if(y+=l,t.add(l,"hour"),delete n[v],I==null||I.debug(`[%s] go to %j from %j with ${h}nm, and cost ${l} hours`,u.requestId,{lat:M.lat,lng:M.lng},{lat:w.lat,lng:w.lng,etd:w.etd}),j+=h,n.filter(k=>k).length<=1){S=M,S.eta=t.utc().format(),S.distanceFromPrevious=h,S.distanceFromStart=Math.round((o+j)*1e4)/1e4,m.push(S),delete n[v+1];break}}else{l=i-y,t.add(l,"hour");const k=H.LngLatHelper.roundPrecision(w.speed*l,5);S=H.LaneHelper.calculateCoordinate(d,s.bearing,k,"nauticalmiles",!M.gcToPrevious),S.eta=t.utc().format(),n[v]=S,I==null||I.debug(`[%s] go to %j from %j with ${k}nm, and cost ${l} hours`,u.requestId,{lat:S.lat,lng:S.lng},{lat:d.lat,lng:d.lng,etd:d.etd}),j+=k,S.distanceFromPrevious=Math.round(j*1e4)/1e4,S.distanceFromStart=Math.round((o+j)*1e4)/1e4;break}}return{etd:t,from:w,to:S,next:n.filter(v=>v),wps:m,days:b}}static currentFactor(s,t,a=0){const i=(s-(t==null?void 0:t.degree)||0)/180*Math.PI;if(Math.abs(i)===Math.PI/2)return 0;let o=((t==null?void 0:t.kts)||0)*Math.cos(i);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}static weatherFactor(s,t){var f,m,b,y,j,S,w;I==null||I.debug("calculate weather factor via: %j",{...s,...t});const a=W.blockCoefficient(s.displacement,s.lbp,s.breadthMoulded,s.draught),i=W.froudeNumber(s.speed,s.lbp),o=W.amendFactor(a,i,s.loadCondition);let n=Math.abs(s.bearing%360-(((f=t==null?void 0:t.wind)==null?void 0:f.degree)%360||0));n=n>180?360-n:n;const e=W.directionFactor(n,(m=t==null?void 0:t.wind)==null?void 0:m.scale),c=W.vesselTagFactor(s.displacement,s.loadCondition,s.tag,(b=t==null?void 0:t.wind)==null?void 0:b.scale);let r=e*o*c/100*s.speed;r=Math.round(r*1.943844*1e4)/1e4*-1,s.tag==="tugs"&&Math.abs(r)>1&&(r=r/(Math.abs(Math.round(r))+1)),I==null||I.debug("wind wx factor = %d",r),n=Math.abs(s.bearing%360-(((j=(y=t==null?void 0:t.wave)==null?void 0:y.sig)==null?void 0:j.degree)%360||0));const u=W.waveHeightFactor(((w=(S=t==null?void 0:t.wave)==null?void 0:S.sig)==null?void 0:w.height)??1,n);return I==null||I.debug("wave wx factor = %d",u),r=Math.abs(r)>Math.abs(u)?r:r*.3+u*.7,I==null||I.debug("weather factor = %d",r),r=Math.abs(r)>3?3*(Math.abs(r)/r)+Math.abs(r)/r*(Math.abs(r)-2)*.1:r,Math.round((r||0)*100)/100}static async analyseInstant(s,t,a,i,o,n="",e=0,c=!0,r=!1,u={}){var X,Q,Z,$,tt,et;const f=g().valueOf();s.lng=H.LngLatHelper.convertToStdLng(s.lng);const{route:m,waypoints:b}=o.points,y=H.LaneHelper.calculateSubRoute(s,m);if(((X=y[0])==null?void 0:X.length)<=1)return;const{v0:j,label:S}=s.sog?{v0:s.sog,label:s.label||"Other"}:{v0:i.speed,label:"CP"},w=W.assembleProperties(a,i.loadCondition,j,0),v=b.length?H.LaneHelper.calculateSubWaypoints(s,b):[];v.forEach(O=>O.important=!0);const d={from:{...s},route:y,waypoints:v,v0:j,label:S},M={hours:[],days:[],wps:[]};e||(H.LaneHelper.calculateRouteDistance(y)/i.speed<=72?e=3:e=6);let h=H.LaneHelper.simplifyRouteToCoordinates(y,v,0),l=0,k=0,C=0,x=0;t=g(t).utc();const Y=t.clone();for(;h.length>0;){const O=e-t.hour()%e,_=Math.ceil(t.clone().add(O,"h").set({minute:0,second:0,millisecond:0}).diff(t,"h",!0)*1e4)/1e4,F=await W.speedLoseInHoursStep(w,t,Y,_,l,h,n,c,r,u);(Q=F.from)!=null&&Q.speed&&(M.hours.push(F.from),M.wps.push(...F.wps),M.days.push(...F.days)),h=F==null?void 0:F.next,h.length||M.hours.push(F==null?void 0:F.to),l+=Math.round((((Z=F==null?void 0:F.to)==null?void 0:Z.distanceFromPrevious)??0)*1e4)/1e4}const T=M.hours;for(let O=0;O<T.length-1;O++){const _=g(T[O+1].eta).diff(T[O].etd,"hour",!0)||1;k+=(T[O].wxFactor||0)*_,C+=(T[O].cFactor||0)*_,x+=_}($=M.wps)==null||$.forEach((O,_)=>{O.positionTime=g.utc(O.etd||O.eta).unix();const F=M.wps[_-1];if(F){const B=O.distanceFromStart-F.distanceFromStart,R=g(O.eta||O.etd).diff(g(F.etd||F.eta),"h",!0);O.avgSpd=Math.round(B/R*100)/100,F.bearing=H.LaneHelper.calculateBearing(F,O)}}),M.wps=(tt=M.wps)==null?void 0:tt.reduce((O,_)=>(O.some(F=>Math.round(F.positionTime/60)===Math.round(_.positionTime/60))||O.push(_),O),[]),d.sample=M;const L=M.hours.at(0),N=M.hours.at(-1);d.distance=Math.round(N.distanceFromStart*1e3)/1e3,d.etd=g(L.eta).utc().format(),d.eta=g(N.eta).utc().format(),d.wxFactor=Math.round(k/x*1e3)/1e3,d.cFactor=Math.round(C/x*1e3)/1e3,d.avgSpeed=Math.round(N.distanceFromStart/x*1e3)/1e3,d.totalHrs=Math.round(x*1e3)/1e3;const{distanceInECA:E,hoursInECA:P,totalDgoConsInECA:V,eca:J}=await this.calculateECA(d,i,u),st=H.LngLatHelper.roundPrecision(i.fo/24*(x-P),3),ot=H.LngLatHelper.roundPrecision(i.dgo/24*x,3);d.extend={eca:J,distanceInECA:E,hoursInECA:P,totalDgoConsInECA:V},d.totalFoCons=st<0?0:st,d.totalDgoCons=ot;const at=g().valueOf()-f,rt=((et=M==null?void 0:M.hours)==null?void 0:et.length)||1;return I==null||I.info("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms",u==null?void 0:u.requestId,at,rt,Math.round(at/rt*1e3)/1e3),d}static async analyseInstantWithThreshed(s,t,a,i,o,n,e,c="",r=3,u=!0,f=!1,m={}){var Z,$,tt,et,O,_;const b=g().valueOf();s.lng=H.LngLatHelper.convertToStdLng(s.lng);const{v0:y,label:j}=s.sog?{v0:s.sog,label:s.label||"Other"}:{v0:o.speed,label:"CP"},S=W.assembleProperties(i,o.loadCondition,y,0),w=H.LaneHelper.calculateSubRoute(s,n);if(((Z=w[0])==null?void 0:Z.length)<=1)return;const v=e.length?H.LaneHelper.calculateSubWaypoints(s,e):[];v.forEach(F=>F.important=!0);let d=H.LaneHelper.simplifyRouteToCoordinates(w,v,0),M=0,h=0,l=0,k=0;const C={hours:[],wps:[],days:[]};t=g(t).utc();const x=t.clone();for(;d.length>0;){const F=r-t.hour()%r;let B=Math.ceil(t.clone().add(F,"h").set({minute:0,second:0,millisecond:0}).diff(t,"h",!0)*1e4)/1e4;B=t.clone().add(B,"h").isSameOrAfter(a)?a.diff(t,"h",!0)*1e4/1e4:B;const R=await W.speedLoseInHoursStep(S,t,x,B,M,d,c,u,f,m);if(($=R.from)!=null&&$.speed&&(C.hours.push(R.from),R!=null&&R.wps&&C.wps.push(...R.wps),C.days.push(...R.days)),d=R==null?void 0:R.next,d.length||C.hours.push(R==null?void 0:R.to),M+=Math.round((((tt=R==null?void 0:R.to)==null?void 0:tt.distanceFromPrevious)??0)*1e4)/1e4,!B)break}C.wps=(et=C.wps)==null?void 0:et.reduce((F,B)=>(F.some(R=>Math.round(g(R.etd).unix()/60)===Math.round(g(B.etd).unix()/60))||F.push(B),F),[]),(O=C.wps)==null||O.forEach((F,B)=>{const R=C.wps[B-1];if(R){const gt=F.distanceFromStart-R.distanceFromStart,wt=g(F.eta||F.etd).diff(g(R.etd||R.eta),"h",!0);F.avgSpd=Math.round(gt/wt*100)/100;const kt=H.LaneHelper.calculateBearing(R,F);R.bearing=kt}});const Y=C.hours;for(let F=0;F<Y.length-1;F++){const B=g(Y[F+1].eta).diff(Y[F].etd,"hour",!0);h+=Y[F].wxFactor*B,l+=Y[F].cFactor*B,k+=B}const T=C.hours.at(0),L=C.hours.at(-1),N=await H.LaneHelper.calculateRangeRoute(T,L,w),E=await H.LaneHelper.calculateRangeWaypoints(T,L,w,v),P={sample:C,distance:Math.round(((L==null?void 0:L.distanceFromStart)||0)*1e4)/1e4,etd:g(T.eta).utc().format(),eta:g(L==null?void 0:L.eta).utc().format(),wxFactor:Math.round(h/k*1e3)/1e3,cFactor:Math.round(l/k*1e3)/1e3,avgSpeed:Math.round(((L==null?void 0:L.distanceFromStart)||0)/k*1e3)/1e3,totalHrs:Math.round(k*1e3)/1e3,from:T,to:L,route:N,waypoints:E,v0:y,label:j},{distanceInECA:V,hoursInECA:J,totalDgoConsInECA:st,eca:ot}=await this.calculateECA(P,o,m),it=H.LngLatHelper.roundPrecision(o.fo/24*(k-J),3),at=H.LngLatHelper.roundPrecision(o.dgo/24*k,3);P.extend={eca:ot,distanceInECA:V,hoursInECA:J,totalDgoConsInECA:st},P.totalDgoCons=at,P.totalFoCons=it<0?0:it;const X=g().valueOf()-b,Q=((_=C==null?void 0:C.hours)==null?void 0:_.length)||1;return I==null||I.debug("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms",m==null?void 0:m.requestId,X,Q,Math.round(X/Q*1e3)/1e3),P}static async analyseCost(s,t,a,i,o={}){var w,v;const n=g().valueOf(),e=[];s.speedStep=s.speedStep||3,s.alterStep=s.alterStep??1;const c=H.LaneHelper.calculateRouteDistance(i.route);let r=0;a.forEach(d=>{const M=Math.ceil(c/d.speed/24);r=r<M?M:r}),r=r*1.3;const u=g.utc(s.etd).add(r??14,"day");let f=1;for(const d of a){const M=JSON.parse(JSON.stringify(i.route)),h=JSON.parse(JSON.stringify(i.waypoints)),l=await W.analyseInstantWithThreshed({lat:s.lat,lng:s.lng},s.etd,u,t,d,M,h,s.meteoVendor,s.speedStep,s.useMeteo,s.useRouteParam,o);l&&(await W.calculateCost(l,d,s,o),e.push(l),I==null||I.info("[%s][L%d-%d] analyse from %s to %s cost: %j",o.requestId,1,f,s.etd,u.format(),{cost:l.cost.total,hire:l.cost.hire,bunker:l.cost.bunker,distance:l.distance,hours:l.totalHrs,cp:`${d.speed}/${d.fo}/${d.dgo}`})),f++}e.sort((d,M)=>d.cost.total-M.cost.total);const m=e.at(0),b=e.at(1),y=[];if(y.push({combined:!1,speeds:[m],cost:(w=m.cost)==null?void 0:w.total}),b){const d=m.cost.cp,M=b.cost.cp,h=g(m.eta),l=g(m.etd),k=h.diff(l,"days",!0);let C=Math.ceil(k/2);C=C>7?7:C<s.alterStep?s.alterStep:C;let x=2,Y={combined:!1,speeds:[b],cost:(v=b.cost)==null?void 0:v.total},T;for(;C>=s.alterStep;){const L=await W.combinedAnalyse(s,t,u,[d,M],i,C,{...o,level:x});if(Y.cost>L.cost?T?(T==null?void 0:T.cost)>L.cost&&(T=L):(T=Y,Y=L):(!T||(T==null?void 0:T.cost)>L.cost)&&(T=L),C<=s.alterStep)break;C=Math.ceil(C/2),x+=1}y.push(Y),T&&y.push(T)}const S=g().valueOf()-n;return I==null||I.info("[%s] analyse elapsed: %d ms",o==null?void 0:o.requestId,S),y.sort((d,M)=>d.cost-M.cost)}static async combinedAnalyse(s,t,a,i,o,n,e={}){e.counter=1,I==null||I.info("[%s][L%d] analyse with alternate cp in every %d days",e.requestId,e.level,n);const c=await W.alternateAnalyse(s,t,a,i,0,o,n,e),r=c.reduce((M,h)=>M+h.cost.total,0),u=c.reduce((M,h)=>M+h.cost.hire,0),f=c.reduce((M,h)=>M+h.cost.bunker,0),m=c.reduce((M,h)=>M+h.distance,0),b=c.reduce((M,h)=>M+h.totalHrs,0);I==null||I.info("[%s][L%d] cost with cpa/cpb turn: %j",e.requestId,e.level,{cost:r,hire:u,bunker:f,distance:m,hours:b});const y=await W.alternateAnalyse(s,t,a,i,1,o,n,e),j=y.reduce((M,h)=>M+h.cost.total,0),S=y.reduce((M,h)=>M+h.cost.hire,0),w=y.reduce((M,h)=>M+h.cost.bunker,0),v=y.reduce((M,h)=>M+h.distance,0),d=y.reduce((M,h)=>M+h.totalHrs,0);return I==null||I.info("[%s][L%d] cost with cpb/cpa turn: %j",e.requestId,e.level,{cost:j,hire:S,bunker:w,distance:v,hours:d}),r<j?{combined:!0,cost:Math.round(r*1e3)/1e3,speeds:c,step:n}:{combined:!0,cost:Math.round(j*1e3)/1e3,speeds:y,step:n}}static async alternateAnalyse(s,t,a,i,o,n,e,c={}){var m,b;let r=g.utc(s.etd);const u={lat:s.lat,lng:s.lng},f=[];for(;r.isBefore(a);){const y=r.clone().utc().add(e,"day"),j=JSON.parse(JSON.stringify(n.route)),S=JSON.parse(JSON.stringify(n.waypoints)),w=i[o],v=await W.analyseInstantWithThreshed(u,r.utc().format(),y,t,w,j,S,s.meteoVendor,s.speedStep,s.useMeteo,s.useRouteParam,c);v&&(await W.calculateCost(v,w,s,c),I==null||I.info("[%s][L%d-%d] analyse from %s to %s cost: %j",c.requestId,c.level,c.counter,r.utc().format(),y.utc().format(),{cost:v.cost.total,hire:v.cost.hire,bunker:v.cost.bunker,distance:v.distance,hours:v.totalHrs,cp:`${w.speed}/${w.fo}/${w.dgo}`})),c.counter=c.counter+1;const d=(b=(m=v==null?void 0:v.sample)==null?void 0:m.hours)==null?void 0:b.at(-1);if(d)u.lat=d.lat,u.lng=d.lng,r=g(d.eta),f.push(v),o=o?0:1;else break}return f}static async calculateCost(s,t,a,i={}){var o;if(s){const n=(a.addComm||0)>=1?(a.addComm||0)/100:a.addComm||0,e=Math.round(s.totalHrs/24*(a.dailyHire||0)*(1-n)*1e3)/1e3,c=Math.round(s.totalFoCons*(a.priceFO||0)*1e3)/1e3,r=Math.round((s.totalDgoCons+(((o=s.extend)==null?void 0:o.totalDgoConsInECA)||0))*(a.priceDGO||0)*1e3)/1e3;s.cost={total:Math.round((e+c+r)*1e3)/1e3,hire:e,bunker:Math.round((c+r)*1e3)/1e3,cp:t}}return s}static async calculateECA(s,t,a={}){var c,r,u,f;const i=await H.LaneHelper.intersectInECA((s==null?void 0:s.route)||[]);let o=0,n=0,e=0;(r=(c=s==null?void 0:s.sample)==null?void 0:c.wps)==null||r.forEach(m=>{m.positionTime=g.utc(m.etd||m.eta).unix()});for(const m of i){o+=m.distance;const b=await H.LaneHelper.deadReckoningTime((u=m.waypoints)==null?void 0:u.at(0),s.sample.wps),y=await H.LaneHelper.deadReckoningTime((f=m.waypoints)==null?void 0:f.at(-1),s.sample.wps);m.in=b,m.out=y,m.totalHrs=H.LngLatHelper.roundPrecision((y.positionTime-b.positionTime)/3600,3),m.totalDgoCons=H.LngLatHelper.roundPrecision(t.fo/24*m.totalHrs,3),n+=m.totalHrs,e+=m.totalDgoCons}return o=H.LngLatHelper.roundPrecision(o,3),n=H.LngLatHelper.roundPrecision(n,3),e=H.LngLatHelper.roundPrecision(e,3),{distanceInECA:o,hoursInECA:n,totalDgoConsInECA:e,eca:i}}static async mergeSpeeds(s,t={}){var d,M;const a={hours:[],wps:[],days:[]},i=s.reduce((h,l)=>h+l.distance,0),o=s.reduce((h,l)=>{var k;return h+(((k=l.extend)==null?void 0:k.distanceInECA)||0)},0),n=s.reduce((h,l)=>h+l.totalHrs,0),e=s.reduce((h,l)=>{var k;return h+(((k=l.extend)==null?void 0:k.hoursInECA)||0)},0),c=s.reduce((h,l)=>{var k;return h+(((k=l.extend)==null?void 0:k.totalDgoConsInECA)||0)},0),r=s.reduce((h,l)=>h+l.wxFactor*l.totalHrs/n,0),u=s.reduce((h,l)=>h+l.cFactor*l.totalHrs/n,0),f=s.reduce((h,l)=>h+l.totalFoCons,0),m=s.reduce((h,l)=>h+l.totalDgoCons,0),b=s.reduce((h,l)=>h+l.cost.total,0),y=s.reduce((h,l)=>h+l.cost.hire,0),j=s.reduce((h,l)=>h+l.cost.bunker,0),S=[],w=[];let v;for(const h of s){w.push(...((d=h.extend)==null?void 0:d.eca)||[]);const l=h.sample.hours,k=h.sample.wps,C=h.sample.days,x=l.at(0);v&&(x.distanceFromPrevious=v.distanceFromPrevious,x.distanceFromStart=v.distanceFromStart,l.forEach((N,E)=>{E&&(N.distanceFromStart=N.distanceFromStart+v.distanceFromStart)}),k.at(0).distanceFromPrevious=v.distanceFromPrevious,k.at(0).distanceFromStart=v.distanceFromStart,k.forEach((N,E)=>{E&&(N.distanceFromStart=N.distanceFromStart+v.distanceFromStart)}),C.at(0).distanceFromPrevious=v.distanceFromPrevious,C.at(0).distanceFromStart=v.distanceFromStart,C.forEach((N,E)=>{E&&(N.distanceFromStart=N.distanceFromStart+v.distanceFromStart)})),x.cp=h.cost.cp;const Y=[h.etd,h.eta],T=S.findIndex(N=>N.id===x.cp.id);T===-1?(x.cp.segment=[Y],S.push(x.cp)):S[T].segment.push(Y),l.forEach(N=>{var P;((P=a.hours)==null?void 0:P.findIndex(V=>V.eta===N.eta))===-1&&a.hours.push(N)}),k.forEach(N=>{var P;((P=a.wps)==null?void 0:P.findIndex(V=>V.eta===N.eta))===-1&&a.wps.push(N)}),C.forEach(N=>{var P;((P=a==null?void 0:a.days)==null?void 0:P.findIndex(V=>V.eta===N.eta))===-1&&a.days.push(N)});const L=(M=a.wps)==null?void 0:M.findIndex(N=>N.eta===x.eta);L===-1?a.wps.push(x):a.wps[L]=x,v=l.at(-1)}return a.wps.sort((h,l)=>{g(h.etd).unix()-g(l.etd).unix()}),a.wps.forEach((h,l)=>{const k=a.wps[l-1];if(k){const C=h.distanceFromStart-(k.distanceFromStart||0),x=g(h.eta||h.etd).diff(g(k.etd||k.eta),"hour",!0),Y=Math.round(C/x*100)/100;h.avgSpd=Y;const T=H.LaneHelper.calculateBearing(k,h);k.bearing=T}}),{sample:a,etd:s.at(0).etd,eta:s.at(-1).eta,from:s.at(0).from,to:s.at(-1).to,v0:s.at(0).v0,label:"Combined",distance:Math.round(i*1e3)/1e3,totalHrs:Math.round(n*1e3)/1e3,avgSpeed:Math.round(i/n*1e3)/1e3,wxFactor:Math.round(r*1e3)/1e3,cFactor:Math.round(u*1e3)/1e3,totalFoCons:Math.round(f*1e3)/1e3,totalDgoCons:Math.round(m*1e3)/1e3,cost:{total:Math.round(b*1e3)/1e3,hire:Math.round(y*1e3)/1e3,bunker:Math.round(j*1e3)/1e3},extend:{cps:S,eca:w,distanceInECA:Math.round(o*1e3)/1e3,hoursInECA:Math.round(e*1e3)/1e3,totalDgoConsInECA:Math.round(c*1e3)/1e3,speeds:s}}}}q.AISImpl=G,q.AlertHelper=dt,q.AlertLevel=ct,q.HifleetImpl=yt,q.LoadCondition=lt,q.MyShipImpl=Mt,q.MyVesselImpl=mt,q.ShipxyImpl=pt,q.SpeedHelper=W,q.SpeedLabel=ht,q.VesselTag=ut,q.alertHelper=bt,Object.defineProperty(q,Symbol.toStringTag,{value:"Module"})});
1
+ (function(q,A){typeof exports=="object"&&typeof module<"u"?A(exports,require("got"),require("@log4js-node/log4js-api"),require("moment"),require("@idm-plugin/geo2"),require("@idm-plugin/meteo2"),require("@idm-plugin/meteo")):typeof define=="function"&&define.amd?define(["exports","got","@log4js-node/log4js-api","moment","@idm-plugin/geo2","@idm-plugin/meteo2","@idm-plugin/meteo"],A):(q=typeof globalThis<"u"?globalThis:q||self,A(q["idm-plugin-vessel"]={},q.got,q["@log4js-node/log4js-api"],q.moment,q["@idm-plugin/geo2"],q["@idm-plugin/meteo2"],q["@idm-plugin/meteo"]))})(this,function(q,A,U,g,H,ft,nt){"use strict";var It=Object.defineProperty;var St=(q,A,U)=>A in q?It(q,A,{enumerable:!0,configurable:!0,writable:!0,value:U}):q[A]=U;var K=(q,A,U)=>(St(q,typeof A!="symbol"?A+"":A,U),U);let p;try{p=U.getLogger("vessel")}catch{}finally{}class G{parseStatus(s){let t,a;switch(s){case 0:t="在航(主机推动)",a="Underway Using Engine";break;case 1:t="锚泊",a="Anchored";break;case 2:t="失控",a="Not under command";break;case 3:t="操纵受限",a="Limited airworthiness";break;case 4:t="吃水受限",a="Limited by ship's draft";break;case 5:t="靠泊",a="Mooring";break;case 6:t="搁浅",a="Stranded";break;case 7:t="捕捞作业",a="Engaged in fishing";break;case 8:t="靠帆船提供动力",a="Sailing";break;default:t="未定义",a="Undefined"}return{labelCn:t,labelEn:a}}}class mt extends G{constructor(t,a){super();K(this,"clientId");K(this,"clientSecret");K(this,"token");this.clientId=t,this.clientSecret=a}async authToken(t={}){const a="https://svc.data.myvessel.cn/ada/oauth/token",i={searchParams:{client_id:this.clientId,client_secret:this.clientSecret,grant_type:"client_credentials"}},o=await A.post(a,i).json();p==null||p.info("[%s] fetch access token from: %s - %j",t.requestId,a,o),o.error||(this.token={accessToken:o.access_token,tokenType:o.token_type,expiresIn:o.expires_in,scope:o.scope,jti:o.jti,issuedAt:g().utc().format()})}async checkToken(t={}){var a;return(!this.token||g().diff(g(this.token.issuedAt),"seconds")>(((a=this.token)==null?void 0:a.expiresIn)||0)-300)&&await this.authToken(t),this.token}async suggest(t,a={}){var e,c;await this.checkToken(a);const i="https://market.myvessel.cn/sdc/v1/mkt/vessels/fuzzy",o={headers:{Authorization:`${(e=this.token)==null?void 0:e.tokenType} ${(c=this.token)==null?void 0:c.accessToken}`},json:{kw:t,recordNum:a.ps||10}};p==null||p.info("[%s] fetch suggest vessels from: %s - %j",a.requestId,i,o);const n=await A.post(i,o).json();return n.code?(p==null||p.warn("[%s] fetch suggest vessels failed: %j",a.requestId,{message:n.message,status:n.status,code:n.code}),[]):n.data.map(u=>({mmsi:u.mmsi,name:u.nameEn,nameCn:u.nameCn,imo:Number.isNaN(u.imo)?null:Number(u.imo),callSign:u.callsign,type:u.vesselTypeNameEn,flagName:u.flagCtry,vendor:"myvessel",raw:u}))}async search(t,a={}){var r,u;await this.checkToken(a);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},e={headers:{Authorization:`${(r=this.token)==null?void 0:r.tokenType} ${(u=this.token)==null?void 0:u.accessToken}`},searchParams:n};p==null||p.info("[%s] fetch vessel from: %s - %j",a.requestId,o,e);const c=await A.get(o,e).json();if(c.status!==200)return p==null||p.warn("[%s] fetch suggest vessels failed: %j",a.requestId,{message:c.message,status:c.status,code:c.code}),{};{const h=c.data;if(h)return{mmsi:h.mmsi,imo:Number.isNaN(h.imo)?null:Number(h.imo),callSign:h.callsign,name:h.nameEn,nameCn:h.nameCn,type:h.vesselTypeNameEn,flagName:h.flagCtry,clasz:h.classSociety,dateOfBuild:h.buildYearMonth,deadweight:h.dwt,grossTonnage:h.grt,netTonnage:h.net,teu:h.teu,length:h.length,breadth:h.width,height:h.height,draught:h.draught,speed:h.speed,passengerCapacity:h.passengercapacity,vendor:"myvessel",raw:h}}return null}async archives(t,a={}){var e,c;await this.checkToken(a);const i="https://svc.data.myvessel.cn/sdc/v1/ship/info/batch",o={headers:{Authorization:`${(e=this.token)==null?void 0:e.tokenType} ${(c=this.token)==null?void 0:c.accessToken}`},json:{mmsiList:typeof t=="number"?[t]:t}};p==null||p.info("[%s] fetch vessel archive from: %s - %j",a.requestId,i,o);const n=await A.post(i,o).json();return n.status!==200?(p==null||p.warn("[%s] fetch vessel archive failed: %j",a.requestId,{message:n.message,status:n.status,code:n.code}),{}):n.data}async realTimePosition(t,a={}){var c,r;await this.checkToken(a);const i="https://svc.data.myvessel.cn/sdc/v1/vessels/status/location/unit",o={headers:{Authorization:`${(c=this.token)==null?void 0:c.tokenType} ${(r=this.token)==null?void 0:r.accessToken}`},searchParams:{mmsi:t}};p==null||p.info("[%s] fetch realtime position from: %s - %j",a.requestId,i,o);const n=await A.get(i,o).json();if(n.code)return p==null||p.warn("[%s] fetch realtime position failed: %j",a.requestId,{message:n.message,status:n.status,code:n.code}),n;const e=n.data;for(const u in e)!isNaN(e[u])&&Number(e[u])!==1/0&&(e[u]=Number(e[u]));if(e){const u=g(`${e.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return{mmsi:e.mmsi,name:e.vesselName||e.aisVesselName,imo:e.imo,callSign:e.callsign||e.aisCallSign,lat:e.lat,lng:e.lon,length:e.length,width:e.width,draught:e.currDraught,sog:e.sog,cog:e.cog,hdg:e.hdg,rot:e.rot,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(e.eta)?g.utc(e.eta).format():void 0,destination:e.dest,positionTime:u.unix(),status:e.status,labelCn:e.statusNameCn,labelEn:e.statusNameEn,vesselType:e.vesselTypeNameEn,flag:e.flagCtryNameEn,clasz:e.classSociety,build:e.buildYear,dwt:e.dwt,grt:e.grt,net:e.net,method:"position",vendor:"myVessel",utc:u.utc().format()}}else return{}}async trajectory(t,a,i,o,n=!0,e={}){await this.checkToken(e);const c=await this.realTimePosition(t,e),r=g(a),u=g(i),h=[];for(;u.diff(r,"day",!0)>30;)await this.trajectoryIn30Day(t,r,r.clone().add(30,"day"),c,o,h,e),r.add(30,"day");return await this.trajectoryIn30Day(t,r,u,c,o,h,e),h}async trajectoryIn30Day(t,a,i,o,n,e,c={}){var y,j,S,w,v;const r="https://svc.data.myvessel.cn/sdc/v1/vessels/status/track",u={headers:{Authorization:`${(y=this.token)==null?void 0:y.tokenType} ${(j=this.token)==null?void 0:j.accessToken}`},json:{mmsi:t,startTime:a.utcOffset(8).format("YYYY-MM-DD HH:mm:ss"),endTime:i.utcOffset(8).format("YYYY-MM-DD HH:mm:ss")}};p==null||p.info("[%s] fetch trajectory from: %s - %j",c.requestId,r,u);const h=await A.post(r,u).json();if(h.code)return p==null||p.warn("[%s] fetch trajectory failed: %j",c.requestId,r,{message:h.message,status:h.status,code:h.code}),h;let m=-1;const b=g(`${(w=(S=h.data)==null?void 0:S[0])==null?void 0:w.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return(v=h.data)==null||v.forEach(d=>{for(const Y in d)!isNaN(d[Y])&&Number(d[Y])!==1/0&&(d[Y]=Number(d[Y]));const M=g(`${d.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00"),f=d.status,{labelCn:l,labelEn:k}=this.parseStatus(f),C={mmsi:d.mmsi,imo:o==null?void 0:o.imo,lat:d.lat,lng:d.lon,sog:d.sog,cog:d.cog,hdg:d.hdg,draught:d.draught,status:f,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(d.eta)?g(`${d.eta} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00").utc().format():void 0,destination:d.dest,positionTime:M.unix(),labelCn:l,labelEn:k,method:"trajectory",vendor:"myVessel",utc:M.utc().format()},x=Math.floor(M.diff(b,"minute",!0)/(n||1));x!==m&&(m=x,e.push(C))}),e}}class yt extends G{constructor(t){super();K(this,"token");this.token=t}async realTimePosition(t,a={}){const i="https://api.hifleet.com/position/position/get/token",o={searchParams:{mmsi:t,usertoken:this.token}},n=await A.post(i,o).json();p==null||p.info("[%s] fetch realtime position from: %s - %j",a.requestId,i,o);const e=n==null?void 0:n.list;if(!e)return p==null||p.warn("[%s] fetch realtime position failed: %j",a.requestId,i,n),n;for(const b in e)!isNaN(e[b])&&Number(e[b])!==1/0&&(e[b]=Number(e[b]));e.status=e.sp>3?0:1;const c=e.status,{labelCn:r,labelEn:u}=this.parseStatus(c),h=g(`${e.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return{mmsi:e.m,name:e.n,imo:e.imonumber,callSign:e.callsign,lat:Math.round(e.la/60*1e5)/1e5,lng:Math.round(e.lo/60*1e5)/1e5,length:e.l,width:e.w,draught:e.draught,sog:e.sp,cog:e.co,hdg:e.h,rot:isNaN(e.rot)?0:e.rot,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(e.eta)?g.utc(e.eta).format():void 0,destination:e.destination,vesselType:e.type,dwt:e.dwt,build:e.buildyear,flag:e.fn,positionTime:h.unix(),utc:h.utc().format(),status:c,labelCn:r,labelEn:u,method:"position",vendor:"hifleet"}}async search(t,a={}){let i="https://www.hifleet.com/hifleetapi/searchVesselOL.do";const o={searchParams:{keyword:t},headers:{Referer:"https://www.hifleet.com",Origin:"https://www.hifleet.com",Host:"www.hifleet.com"}};let n=await A.post(i,o).json();p==null||p.info("[%s] fetch vessel props from: %s - %j",a.requestId,i,o),n instanceof Array&&(n=n[0]);for(const c in n)!isNaN(n[c])&&Number(n[c])!==1/0&&(n[c]=Number(n[c]));const e={mmsi:n.m,name:n.n,imo:n.i,callSign:n.c,length:n.l,breadth:n.b,draught:n.dr,type:n.t};return i="https://www.hifleet.com/hifleetapi/sameShipSearch.do",n=await A.post(i,o).json(),p==null||p.info("[%s] search vessel dead weight from: %s - %j",a.requestId,i,o),n instanceof Array&&(n=n[0]),n&&(e.deadweight=Number(n.dwt)),e}async suggest(t,a={}){const i="https://www.hifleet.com/hifleetapi/getShipSuggest.do",o={searchParams:{q:t},headers:{Referer:"https://www.hifleet.com",Origin:"https://www.hifleet.com",Host:"www.hifleet.com"}},n=await A.post(i,o).json();p==null||p.info("[%s] suggest vessel props from: %s - %j",a.requestId,i,o);const e=[];for(const c of n)e.push({mmsi:!c.mmsi||isNaN(c.mmsi)?null:Number(c.mmsi),name:c.name,callSign:c.callsign,imo:!c.imo||isNaN(c.imo)?null:Number(c.imo),score:c._score});return e.sort((c,r)=>r.score-c.score),e}async trajectory(t,a,i,o,n=!0,e={}){var d,M,f;const c=await this.realTimePosition(t,e);let r=g(a);const u=g(i),h=g();if(n){let l=u.diff(r,"d",!0);l<0?r=u.clone().subtract(40,"d"):l<30?r.subtract(10,"d"):l<60?r.subtract(5,"d"):r=u.clone().subtract(80,"d"),l=h.diff(u,"d",!0),u.add(l>10?240:l*24,"h")}const m={searchParams:{endtime:u.utcOffset("+8:00").format("YYYY-MM-DD HH:mm:ss"),starttime:r.utcOffset("+8:00").format("YYYY-MM-DD HH:mm:ss"),mmsi:t,usertoken:this.token}},b="https://api.hifleet.com/position/trajectory/nocompressed/withstatic/token",y=await A.get(b,m).json();p==null||p.info("[%s] fetch trajectory from: %s - %j",e.requestId,b,m);let j;y&&(j=((M=(d=y.ships)==null?void 0:d.offors)==null?void 0:M.ship)||[],j.length||p==null||p.warn("[%s] fetch trajectory failed: %j",e.requestId,y));const S=[];let w=-1;const v=g(`${(f=j==null?void 0:j[0])==null?void 0:f.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");for(const l of j){for(const L in l)!isNaN(l[L])&&Number(l[L])!==1/0&&(l[L]=Number(l[L]));const k=g(`${l.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");l.status=l.sp>4?0:1;const{labelEn:C,labelCn:x}=this.parseStatus(l.status),Y={mmsi:l.m,name:l.n,imo:c==null?void 0:c.imo,lat:l.la,lng:l.lo,draught:l.draught,sog:l.sp,cog:l.co,hdg:l.hdg,positionTime:k.unix(),utc:k.utc().format(),status:l.status,labelCn:x,labelEn:C,method:"trajectory",vendor:"hifleet"},T=Math.floor(k.diff(v,"minute",!0)/(o||1));T!==w&&(w=T,S.push(Y))}return S}}class pt extends G{constructor(t){super();K(this,"token");this.token=t}async realTimePosition(t,a={}){const i={searchParams:{id:t,k:this.token,enc:1}},o="https://api.shipxy.com/apicall/GetSingleShip",n=await A.get(o,i).json();if(p==null||p.info("[%s] fetch realtime position from: %s - %j",a.requestId,o,i),(n==null?void 0:n.status)!==0)return n;const e=n.data[0];for(const m in e)!isNaN(e[m])&&Number(e[m])!==1/0&&(e[m]=Number(e[m]));const{labelCn:c,labelEn:r}=await this.parseStatus(e.navistat),u=g.unix(e.lasttime);return{mmsi:e.ShipID,name:e.name,imo:e.imo,callSign:e.callsign,lat:Math.round(e.lat/1e6*1e5)/1e5,lng:Math.round(e.lon/1e6*1e5)/1e5,length:Math.round(e.length/10*100)/100,width:Math.round(e.width/10*100)/100,draught:Math.round(e.draught/1e3*100)/100,sog:Math.round(e.sog*3600/1e3/1852*100)/100,cog:Math.round(e.cog/100*100)/100,hdg:Math.round(e.hdg/100*100)/100,rot:Math.round(e.rot/100*100)/100,positionTime:e.lasttime,utc:u.utc().format(),status:e.navistat,labelEn:r,labelCn:c,method:"position",vendor:"shipxy"}}async trajectory(t,a,i,o,n=!0,e={}){var v;const c=await this.realTimePosition(t,e),r=g(a),u=g(i),h="https://api.shipxy.com/apicall/GetShipTrack",m={searchParams:{id:t,k:this.token,enc:1,cut:0,btm:r.unix(),etm:u.unix()}},b=await A.get(h,m).json();if(p==null||p.info("[%s] fetch trajectory from: %s - %j",e.requestId,h,m),(b==null?void 0:b.status)!==0)return b;const y=b==null?void 0:b.points,j=[],S=g.unix((v=y[0])==null?void 0:v.utc);let w=-1;for(const d of y){const M=g.unix(d.utc),f={imo:c==null?void 0:c.imo,mmsi:t,sog:Math.round(d.sog*3600/1e3/1852*100)/100,cog:Math.round(d.cog/100*100)/100,lat:Math.round(d.lat/1e6*1e5)/1e5,lng:Math.round(d.lon/1e6*1e5)/1e5,positionTime:M.unix(),utc:M.utc().format(),method:"trajectory",vendor:"shipxy"},l=Math.floor(M.diff(S,"minute",!0)/(o||1));l!==w&&(w=l,j.push(f))}return j}}class Mt extends G{constructor(t){super();K(this,"token");this.token=t}async getShipId(t,a={}){const i={headers:{appKey:this.token},json:{mmsiList:t}},o="https://api3.myships.com/sp/ships/getShipIdByMMSI",n=await A.post(o,i).json();return p==null||p.info("[%s] fetch ship id from: %s - %j",a.requestId,o,i),n.code!=="0"?n:n.data[0].shipId}async getShipInfo(t,a={}){const i={headers:{appKey:this.token},json:{shipId:t}},o="https://api3.myships.com/sp/ships/aissta",n=await A.post(o,i).json();if(p==null||p.info("[%s] fetch ship info from: %s - %j",a.requestId,o,i),n.code!=="0")return n;const e=n.data;let c=e.imo;return t==="407170"&&(c="9198379",p==null||p.warn("[%s] ship(%s) imo error: %s, should be %s",a.requestId,t,e.imo,c)),{mmsi:e.mmsi,name:e.shipnameEn,imo:c,callSign:e.callSign,length:e.length,width:e.breadth,draught:(e.draught||100)/10}}async realTimePosition(t,a={}){const i=await this.getShipId(t,a),o=await this.getShipInfo(i,a),n={headers:{appKey:this.token},json:{shipId:i}},e="https://api3.myships.com/sp/ships/position/latest",c=await A.post(e,n).json();p==null||p.info("[%s] fetch realtime position from: %s - %j",a.requestId,e,n);const r=c.data[0];for(const y in r)!isNaN(r[y])&&Number(r[y])!==1/0&&(r[y]=Number(r[y]));const{labelCn:u,labelEn:h}=await this.parseStatus(r.aisNavStatus),m=g.unix(r.posTime);return{...o,mmsi:t,lat:Math.round(r.lat/1e4/60*1e5)/1e5,lng:Math.round(r.lon/1e4/60*1e5)/1e5,sog:Math.round(r.sog/10*100)/100,cog:Math.round(r.cog/10*100)/100,hdg:Math.round(r.heading*100)/100,rot:Math.round(r.rot*100)/100,positionTime:r.posTime,utc:m.utc().format(),status:r.aisNavStatus,labelEn:h,labelCn:u,method:"position",vendor:"myship"}}async trajectory(t,a,i,o,n=!0,e={}){const c=g(a),r=g(i),u=await this.getShipId(t),h=await this.getShipInfo(u),m=[];for(;r.diff(c,"day",!0)>30;)await this.trajectoryIn30Day(u,c.unix(),c.add(30,"day").unix(),h,t,o,m);return await this.trajectoryIn30Day(u,c.unix(),r.unix(),h,t,o,m),m}async trajectoryIn30Day(t,a,i,o,n,e,c,r={}){var S;const u={headers:{appKey:this.token},json:{shipId:t,startTime:a,endTime:i}},h="https://api3.myships.com/sp/ships/position/history",m=await A.post(h,u).json();if(p==null||p.info("[%s] fetch trajectory from: %s - %j",r.requestId,h,u),m.code!=="0")return p==null||p.warn("[%s] invoke myship trajectory failed: %j",r.requestId,m),m;const b=m.data;for(const w in b)!isNaN(b[w])&&Number(b[w])!==1/0&&(b[w]=Number(b[w]));const y=g.unix((S=b[0])==null?void 0:S.posTime);let j=-1;for(const w of b){const v=g.unix(w.posTime),d={imo:o==null?void 0:o.imo,mmsi:n,lat:Math.round(w.lat/1e4/60*1e5)/1e5,lng:Math.round(w.lon/1e4/60*1e5)/1e5,sog:Math.round(w.sog/10*100)/100,cog:Math.round(w.cog/10*100)/100,hdg:Math.round(w.heading*100)/100,rot:Math.round(w.rot*100)/100,positionTime:v.unix(),utc:v.utc().format(),method:"trajectory",vendor:"myship"},M=Math.floor(v.diff(y,"minute",!0)/(e||1));M!==j&&(j=M,c.push(d))}return c}}let z;try{z=U.getLogger("vessel")}catch{}finally{}var ct=(D=>(D.NOTICE="NOTICE",D.WARN="WARN",D.HEAVY="HEAVY",D.SEVERE="SEVERE",D.ERROR="ERROR",D.FATAL="FATAL",D))(ct||{});class dt{parsePrinciple(s,t={}){var e,c,r;z==null||z.debug("[%s] parse rule: %s",t.requestId,s);const a=new RegExp("(?<=\\[)(.+)(?=])","g"),i=s.match(a)?(e=s.match(a))==null?void 0:e[0]:void 0,o=i==null?void 0:i.split(";");if(!o)return;const n={};for(let u=0;u<(o==null?void 0:o.length);u++){const h=(r=(c=o[u].match(a))==null?void 0:c[0])==null?void 0:r.split("],");if(u===0&&!h)n.scope=o[0];else if(h)for(let m=0,b=h.length;m<b;m++){const y=this.parseRule(h[m]);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)}}return n}parseRule(s,t={}){var n;z==null||z.debug("[%s] parse rule: %s",t.requestId,s),s=s.startsWith("[")?s:`[${s}`,s=s.endsWith("]")?s:`${s}]`;const a=new RegExp("(?<=\\[)(.+?)(?=])","g"),i=(n=s==null?void 0:s.match(a))==null?void 0:n[0],o=i==null?void 0:i.split(",");if(o){let e=o[3]==="Number.MAX_VALUE"?100:Number(o[3]);return e=isNaN(e)?1:e,{operator:o[0],number:Number.isNaN(Number(o[1]))?o[1]:Number(o[1]),level:o[2],time:e,key:o[4]}}}checkWeather(s,t,a={}){var y,j,S,w,v,d,M,f,l,k,C,x,Y,T,L;let i=0,o=0,n=0,e=0;const c=Math.round(((j=(y=t==null?void 0:t.SEVERE)==null?void 0:y.sigWave)==null?void 0:j.number)*1.6*100)/100,r=(w=(S=t==null?void 0:t.SEVERE)==null?void 0:S.sigWave)==null?void 0:w.number,u=(d=(v=t==null?void 0:t.HEAVY)==null?void 0:v.sigWave)==null?void 0:d.number,h=Math.round((((f=(M=t==null?void 0:t.SEVERE)==null?void 0:M.wind)==null?void 0:f.number)+2)*100)/100,m=(k=(l=t==null?void 0:t.SEVERE)==null?void 0:l.wind)==null?void 0:k.number,b=(x=(C=t==null?void 0:t.HEAVY)==null?void 0:C.wind)==null?void 0:x.number;for(let N=0;N<(s==null?void 0:s.length);N++){const E=s[N],P=(T=(Y=E==null?void 0:E.meteo)==null?void 0:Y.wave)==null?void 0:T.sig,V=(L=E==null?void 0:E.meteo)==null?void 0:L.wind,J=N?g(E.eta).diff(g(s[N-1].eta),"hour",!0):0;e=J>e?J:e,z==null||z.debug("[%s] check sig.wave: %j",a.requestId,{...P,dgThd4Wv:c,svThd4Wv:r,hvThd4Wv:u}),(P==null?void 0:P.height)>=c?E.isDangerous=!0:(P==null?void 0:P.height)>=r?E.isSevere=!0:(P==null?void 0:P.height)>=u&&(E.isHeavy=!0),z==null||z.debug("[%s] check wind: %j",a.requestId,{...V,dgThd4Wd:h,svThd4Wd:m,hvThd4Wd:b}),(V==null?void 0:V.scale)>=h?(E.isDangerous=!0,delete E.isSevere,delete E.isHeavy):(V==null?void 0:V.scale)>m?(E.isDangerous||(E.isSevere=!0),delete E.isHeavy):(V==null?void 0:V.scale)===b&&!E.isDangerous&&!E.isSevere&&(E.isHeavy=!0),i+=E.isDangerous?J:0,o+=E.isSevere?J:0,n+=E.isHeavy?J:0}return i=Math.round(i*100)/100,o=Math.round(o*100)/100,n=Math.round(n*100)/100,e=Math.round(e),{sample:s,dangerous:i,severe:o,heavy:n,step:e<3?3:e,wind:{dgThd4Wd:h,svThd4Wd:m,hvThd4Wd:b},sig:{dgThd4Wv:c,svThd4Wv:r,hvThd4Wv:u}}}}const bt=new dt;let I;try{I=U.getLogger("vessel")}catch{}finally{}const vt=new ft.MeteoHelper2("",!0);var ut=(D=>(D.common="common",D.container="container",D.tugs="tugs",D))(ut||{}),lt=(D=>(D.Ballast="Ballast",D.Laden="Laden",D))(lt||{}),ht=(D=>(D.Cp="CP",D.Perf="Basis",D.Instruct="Other",D))(ht||{});class W{static blockCoefficient(s,t,a,i){let o=Math.round(s/(t*a*i)*100)/100;o=o<.55?.55:o>.85?.85:o;const n=[.55,.6,.65,.7,.75,.8,.85],e=n.map(c=>Math.abs(c-o));return n[e.indexOf(Math.min(...e))]}static froudeNumber(s,t,a=9.8){let i=Math.round(Math.sqrt(s*s/(a*t))*100)/100;return i=i<.05?.05:i>.3?.3:i,i}static amendFactor(s,t,a){const i={.55:[1.7,-1.4,-7.4],.6:[2.2,-2.5,-9.7],.65:[2.6,-3.7,-11.6],.7:[3.1,-5.3,-12.4],.75:[2.4,-10.6,-9.5],.8:[2.6,-13.1,-15.1],.85:[3.1,-18.7,28]};let n={.55:[1.7,-1.4,-7.4],.6:[2.2,-2.5,-9.7],.65:[2.6,-3.7,-11.6],.7:[3.1,-5.3,-12.4],.75:[2.6,-12.5,-13.5],.8:[3,-16.3,-21.6],.85:[3.4,-20.9,31.8]}[s];return a==="Laden"&&(n=i[s]),n[0]+n[1]*t+n[2]*Math.pow(t,2)}static directionFactor(s,t=0){let a;return s>30&&s<=60?a=(1.7-.03*Math.pow(t-4,2))/2:s>60&&s<=150?a=(.9-.06*Math.pow(t-6,2))/2:s>150&&s<=180?a=(.4-.03*Math.pow(t-8,2))/2:a=1,Math.round(a*1e5)/1e5}static vesselTagFactor(s,t,a,i=0){i=i>6?i-.9*(i-6):i;let o;return a==="container"?o=.7*i+Math.pow(i,6.5)/(22*Math.pow(s,2/3)):t==="Ballast"?o=.7*i+Math.pow(i,6.5)/(2.7*Math.pow(s,2/3)):o=.5*i+Math.pow(i,6.5)/(2.7*Math.pow(s,2/3)),o}static waveHeightFactor(s,t){s=s<3?s*.7:s,s=s<0?.2:s,s=s>6?s-.9*(s-6):s,s=s>9?9:s;let a;return t>30&&t<=60?a=-.6:t>60&&t<=90?a=-.4:t>90&&t<=120?a=s<3?.4:-.3:t>120&&t<=150?a=s<3?.6:-.5:t>150&&t<=180?a=s<3?.7:-.6:a=-.7,Math.round(a*(.144*Math.pow(s,2)+.278*s)*1e4)/1e4}static assembleProperties(s,t,a,i){var m;const o=s.lbp??s.length??s.lengthOverall??198.9642,n=s.draught??8,e=s.breadthMoulded??s.breadth??s.breadthExtreme??32.4572,c=s.deadweight??67035.7773,r=((m=s==null?void 0:s.type)==null?void 0:m.toLowerCase())||"common";return{tag:r.indexOf("container")>-1?"container":r.indexOf("tugs")>-1?"tugs":"common",lbp:o,loadCondition:t,draught:n,breadthMoulded:e,displacement:Math.round((c/1.025+n*e*o*.7)*1e4)/1e4,speed:Math.round((a??14.1382)*1852/3600*1e4)/1e4,bearing:i||90}}static async speedLoseAt(s,t,a,i="",o=2,n=!0,e=!1,c={}){let r;if(t.velocity&&e&&(s.speed=H.LngLatHelper.roundPrecision(t.velocity*1852/3600,6)),n){let u;try{i=(i==null?void 0:i.toUpperCase())==="CMEMS"?"ECMWF":i,i=(i==null?void 0:i.toUpperCase())==="METEO2"?"best_match":i;const{weatherModels:y,marineModels:j}=await nt.Meteo2Assist.autoPickMeteoModel(i),S=await vt.spotForecast(t.lat,t.lng,a.utc().format(),!1,!1,!0,{...c,pastDays:1,forecastDays:1,weatherModels:y,marineModels:j}),[w]=nt.Meteo2Assist.pickHourly(S,a);u=nt.Meteo2Assist.toLegacy(w)}catch(y){I.warn("[%s] meteo2 spot(%j) forecast failed: %s",c.requestId,{...t,eta:a.utc().format(),source:i},y)}const h=W.weatherFactor(s,u),m=W.currentFactor(s.bearing,u==null?void 0:u.current,o),b=Math.round((s.speed*1.943844+h+m)*100)/100;r={meteo:{...u},wxFactor:h,cFactor:m,speed:t.velocity&&e?t.velocity:b<0?1:b,eta:a.utc().format(),etd:a.utc().format()}}else r={wxFactor:0,cFactor:0,speed:t.velocity&&e?t.velocity:Math.round((s.speed*1.943844+0+0)*100)/100,eta:a.utc().format(),etd:a.utc().format()};return delete t.meteo,delete t.wxFactor,delete t.cFactor,delete t.speed,delete t.etd,{...r,...t}}static async speedLoseInHoursStep(s,t,a,i,o,n,e="",c=!0,r=!1,u={}){t.utc();const h=t.clone().add(14,"days"),m=[],b=[];let y=0,j=0,S,w;for(let v=0;v<n.length-1;v++){let d=n[v];d.distanceFromStart=Math.round((o+j)*1e3)/1e3;const M=n[v+1];if(s.bearing=H.LaneHelper.calculateBearing(d,M,!M.gcToPrevious),d.bearing=s.bearing,d.suspend&&r){d.eta=d.eta||t.utc().format(),d.elapsed=d.elapsed??0;const k=d.suspend-d.elapsed;if(i-y>k)i=i-y-k,t.add(k,"hour"),d.elapsed=d.suspend;else{const C=i-y;d.elapsed+=C,t.add(C,"hour"),i=0}if(I==null||I.info(`[%s] suspend ${d.elapsed} hours at %j, and remain ${i} hours need to go...`,u.requestId,d),i===0)return d.distanceFromPrevious=j,{etd:t,from:w||d,to:d,next:n.filter(C=>C),wps:m,days:b}}else d.suspend=0;c=t.isAfter(h)?!1:c,d=await W.speedLoseAt(s,d,t,e,0,c,r,u),w=w||d,d.important&&m.push(d),t.isSameOrAfter(a)&&(b.push(d),a.add(24,"hour"));const f=H.LaneHelper.calculateDistance(d,M,!M.gcToPrevious);let l=Math.round(f/w.speed*1e5)/1e5;if(y+l<i){if(y+=l,t.add(l,"hour"),delete n[v],I==null||I.debug(`[%s] go to %j from %j with ${f}nm, and cost ${l} hours`,u.requestId,{lat:M.lat,lng:M.lng},{lat:w.lat,lng:w.lng,etd:w.etd}),j+=f,n.filter(k=>k).length<=1){S=M,S.eta=t.utc().format(),S.distanceFromPrevious=f,S.distanceFromStart=Math.round((o+j)*1e4)/1e4,m.push(S),delete n[v+1];break}}else{l=i-y,t.add(l,"hour");const k=H.LngLatHelper.roundPrecision(w.speed*l,5);S=H.LaneHelper.calculateCoordinate(d,s.bearing,k,"nauticalmiles",!M.gcToPrevious),S.eta=t.utc().format(),n[v]=S,I==null||I.debug(`[%s] go to %j from %j with ${k}nm, and cost ${l} hours`,u.requestId,{lat:S.lat,lng:S.lng},{lat:d.lat,lng:d.lng,etd:d.etd}),j+=k,S.distanceFromPrevious=Math.round(j*1e4)/1e4,S.distanceFromStart=Math.round((o+j)*1e4)/1e4;break}}return{etd:t,from:w,to:S,next:n.filter(v=>v),wps:m,days:b}}static currentFactor(s,t,a=0){const i=(s-(t==null?void 0:t.degree)||0)/180*Math.PI;if(Math.abs(i)===Math.PI/2)return 0;let o=((t==null?void 0:t.kts)||0)*Math.cos(i);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}static weatherFactor(s,t){var h,m,b,y,j,S,w;I==null||I.debug("calculate weather factor via: %j",{...s,...t});const a=W.blockCoefficient(s.displacement,s.lbp,s.breadthMoulded,s.draught),i=W.froudeNumber(s.speed,s.lbp),o=W.amendFactor(a,i,s.loadCondition);let n=Math.abs(s.bearing%360-(((h=t==null?void 0:t.wind)==null?void 0:h.degree)%360||0));n=n>180?360-n:n;const e=W.directionFactor(n,(m=t==null?void 0:t.wind)==null?void 0:m.scale),c=W.vesselTagFactor(s.displacement,s.loadCondition,s.tag,(b=t==null?void 0:t.wind)==null?void 0:b.scale);let r=e*o*c/100*s.speed;r=Math.round(r*1.943844*1e4)/1e4*-1,s.tag==="tugs"&&Math.abs(r)>1&&(r=r/(Math.abs(Math.round(r))+1)),I==null||I.debug("wind wx factor = %d",r),n=Math.abs(s.bearing%360-(((j=(y=t==null?void 0:t.wave)==null?void 0:y.sig)==null?void 0:j.degree)%360||0));const u=W.waveHeightFactor(((w=(S=t==null?void 0:t.wave)==null?void 0:S.sig)==null?void 0:w.height)??1,n);return I==null||I.debug("wave wx factor = %d",u),r=Math.abs(r)>Math.abs(u)?r:r*.3+u*.7,I==null||I.debug("weather factor = %d",r),r=Math.abs(r)>3?3*(Math.abs(r)/r)+Math.abs(r)/r*(Math.abs(r)-2)*.1:r,Math.round((r||0)*100)/100}static async analyseInstant(s,t,a,i,o,n="",e=0,c=!0,r=!1,u={}){var X,Q,Z,$,tt,et;const h=g().valueOf();s.lng=H.LngLatHelper.convertToStdLng(s.lng);const{route:m,waypoints:b}=o.points,y=H.LaneHelper.calculateSubRoute(s,m);if(((X=y[0])==null?void 0:X.length)<=1)return;const{v0:j,label:S}=s.sog?{v0:s.sog,label:s.label||"Other"}:{v0:i.speed,label:"CP"},w=W.assembleProperties(a,i.loadCondition,j,0),v=b.length?H.LaneHelper.calculateSubWaypoints(s,b):[];v.forEach(O=>O.important=!0);const d={from:{...s},route:y,waypoints:v,v0:j,label:S},M={hours:[],days:[],wps:[]};e||(H.LaneHelper.calculateRouteDistance(y)/i.speed<=72?e=3:e=6);let f=H.LaneHelper.simplifyRouteToCoordinates(y,v,0),l=0,k=0,C=0,x=0;t=g(t).utc();const Y=t.clone();for(;f.length>0;){const O=e-t.hour()%e,_=Math.ceil(t.clone().add(O,"h").set({minute:0,second:0,millisecond:0}).diff(t,"h",!0)*1e4)/1e4,F=await W.speedLoseInHoursStep(w,t,Y,_,l,f,n,c,r,u);(Q=F.from)!=null&&Q.speed&&(M.hours.push(F.from),M.wps.push(...F.wps),M.days.push(...F.days)),f=F==null?void 0:F.next,f.length||M.hours.push(F==null?void 0:F.to),l+=Math.round((((Z=F==null?void 0:F.to)==null?void 0:Z.distanceFromPrevious)??0)*1e4)/1e4}const T=M.hours;for(let O=0;O<T.length-1;O++){const _=g(T[O+1].eta).diff(T[O].etd,"hour",!0)||1;k+=(T[O].wxFactor||0)*_,C+=(T[O].cFactor||0)*_,x+=_}($=M.wps)==null||$.forEach((O,_)=>{O.positionTime=g.utc(O.etd||O.eta).unix();const F=M.wps[_-1];if(F){const B=O.distanceFromStart-F.distanceFromStart,R=g(O.eta||O.etd).diff(g(F.etd||F.eta),"h",!0);O.avgSpd=Math.round(B/R*100)/100,F.bearing=H.LaneHelper.calculateBearing(F,O)}}),M.wps=(tt=M.wps)==null?void 0:tt.reduce((O,_)=>(O.some(F=>Math.round(F.positionTime/60)===Math.round(_.positionTime/60))||O.push(_),O),[]),d.sample=M;const L=M.hours.at(0),N=M.hours.at(-1);d.distance=Math.round(N.distanceFromStart*1e3)/1e3,d.etd=g(L.eta).utc().format(),d.eta=g(N.eta).utc().format(),d.wxFactor=Math.round(k/x*1e3)/1e3,d.cFactor=Math.round(C/x*1e3)/1e3,d.avgSpeed=Math.round(N.distanceFromStart/x*1e3)/1e3,d.totalHrs=Math.round(x*1e3)/1e3;const{distanceInECA:E,hoursInECA:P,totalDgoConsInECA:V,eca:J}=await this.calculateECA(d,i,u),st=H.LngLatHelper.roundPrecision(i.fo/24*(x-P),3),ot=H.LngLatHelper.roundPrecision(i.dgo/24*x,3);d.extend={eca:J,distanceInECA:E,hoursInECA:P,totalDgoConsInECA:V},d.totalFoCons=st<0?0:st,d.totalDgoCons=ot;const at=g().valueOf()-h,rt=((et=M==null?void 0:M.hours)==null?void 0:et.length)||1;return I==null||I.info("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms",u==null?void 0:u.requestId,at,rt,Math.round(at/rt*1e3)/1e3),d}static async analyseInstantWithThreshed(s,t,a,i,o,n,e,c="",r=3,u=!0,h=!1,m={}){var Z,$,tt,et,O,_;const b=g().valueOf();s.lng=H.LngLatHelper.convertToStdLng(s.lng);const{v0:y,label:j}=s.sog?{v0:s.sog,label:s.label||"Other"}:{v0:o.speed,label:"CP"},S=W.assembleProperties(i,o.loadCondition,y,0),w=H.LaneHelper.calculateSubRoute(s,n);if(((Z=w[0])==null?void 0:Z.length)<=1)return;const v=e.length?H.LaneHelper.calculateSubWaypoints(s,e):[];v.forEach(F=>F.important=!0);let d=H.LaneHelper.simplifyRouteToCoordinates(w,v,0),M=0,f=0,l=0,k=0;const C={hours:[],wps:[],days:[]};t=g(t).utc();const x=t.clone();for(;d.length>0;){const F=r-t.hour()%r;let B=Math.ceil(t.clone().add(F,"h").set({minute:0,second:0,millisecond:0}).diff(t,"h",!0)*1e4)/1e4;B=t.clone().add(B,"h").isSameOrAfter(a)?a.diff(t,"h",!0)*1e4/1e4:B;const R=await W.speedLoseInHoursStep(S,t,x,B,M,d,c,u,h,m);if(($=R.from)!=null&&$.speed&&(C.hours.push(R.from),R!=null&&R.wps&&C.wps.push(...R.wps),C.days.push(...R.days)),d=R==null?void 0:R.next,d.length||C.hours.push(R==null?void 0:R.to),M+=Math.round((((tt=R==null?void 0:R.to)==null?void 0:tt.distanceFromPrevious)??0)*1e4)/1e4,!B)break}C.wps=(et=C.wps)==null?void 0:et.reduce((F,B)=>(F.some(R=>Math.round(g(R.etd).unix()/60)===Math.round(g(B.etd).unix()/60))||F.push(B),F),[]),(O=C.wps)==null||O.forEach((F,B)=>{const R=C.wps[B-1];if(R){const gt=F.distanceFromStart-R.distanceFromStart,wt=g(F.eta||F.etd).diff(g(R.etd||R.eta),"h",!0);F.avgSpd=Math.round(gt/wt*100)/100;const kt=H.LaneHelper.calculateBearing(R,F);R.bearing=kt}});const Y=C.hours;for(let F=0;F<Y.length-1;F++){const B=g(Y[F+1].eta).diff(Y[F].etd,"hour",!0);f+=Y[F].wxFactor*B,l+=Y[F].cFactor*B,k+=B}const T=C.hours.at(0),L=C.hours.at(-1),N=await H.LaneHelper.calculateRangeRoute(T,L,w),E=await H.LaneHelper.calculateRangeWaypoints(T,L,w,v),P={sample:C,distance:Math.round(((L==null?void 0:L.distanceFromStart)||0)*1e4)/1e4,etd:g(T.eta).utc().format(),eta:g(L==null?void 0:L.eta).utc().format(),wxFactor:Math.round(f/k*1e3)/1e3,cFactor:Math.round(l/k*1e3)/1e3,avgSpeed:Math.round(((L==null?void 0:L.distanceFromStart)||0)/k*1e3)/1e3,totalHrs:Math.round(k*1e3)/1e3,from:T,to:L,route:N,waypoints:E,v0:y,label:j},{distanceInECA:V,hoursInECA:J,totalDgoConsInECA:st,eca:ot}=await this.calculateECA(P,o,m),it=H.LngLatHelper.roundPrecision(o.fo/24*(k-J),3),at=H.LngLatHelper.roundPrecision(o.dgo/24*k,3);P.extend={eca:ot,distanceInECA:V,hoursInECA:J,totalDgoConsInECA:st},P.totalDgoCons=at,P.totalFoCons=it<0?0:it;const X=g().valueOf()-b,Q=((_=C==null?void 0:C.hours)==null?void 0:_.length)||1;return I==null||I.debug("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms",m==null?void 0:m.requestId,X,Q,Math.round(X/Q*1e3)/1e3),P}static async analyseCost(s,t,a,i,o={}){var w,v;const n=g().valueOf(),e=[];s.speedStep=s.speedStep||3,s.alterStep=s.alterStep??1;const c=H.LaneHelper.calculateRouteDistance(i.route);let r=0;a.forEach(d=>{const M=Math.ceil(c/d.speed/24);r=r<M?M:r}),r=r*1.3;const u=g.utc(s.etd).add(r??14,"day");let h=1;for(const d of a){const M=JSON.parse(JSON.stringify(i.route)),f=JSON.parse(JSON.stringify(i.waypoints)),l=await W.analyseInstantWithThreshed({lat:s.lat,lng:s.lng},s.etd,u,t,d,M,f,s.meteoVendor,s.speedStep,s.useMeteo,s.useRouteParam,o);l&&(await W.calculateCost(l,d,s,o),e.push(l),I==null||I.info("[%s][L%d-%d] analyse from %s to %s cost: %j",o.requestId,1,h,s.etd,u.format(),{cost:l.cost.total,hire:l.cost.hire,bunker:l.cost.bunker,distance:l.distance,hours:l.totalHrs,cp:`${d.speed}/${d.fo}/${d.dgo}`})),h++}e.sort((d,M)=>d.cost.total-M.cost.total);const m=e.at(0),b=e.at(1),y=[];if(y.push({combined:!1,speeds:[m],cost:(w=m.cost)==null?void 0:w.total}),b){const d=m.cost.cp,M=b.cost.cp,f=g(m.eta),l=g(m.etd),k=f.diff(l,"days",!0);let C=Math.ceil(k/2);C=C>7?7:C<s.alterStep?s.alterStep:C;let x=2,Y={combined:!1,speeds:[b],cost:(v=b.cost)==null?void 0:v.total},T;for(;C>=s.alterStep;){const L=await W.combinedAnalyse(s,t,u,[d,M],i,C,{...o,level:x});if(Y.cost>L.cost?T?(T==null?void 0:T.cost)>L.cost&&(T=L):(T=Y,Y=L):(!T||(T==null?void 0:T.cost)>L.cost)&&(T=L),C<=s.alterStep)break;C=Math.ceil(C/2),x+=1}y.push(Y),T&&y.push(T)}const S=g().valueOf()-n;return I==null||I.info("[%s] analyse elapsed: %d ms",o==null?void 0:o.requestId,S),y.sort((d,M)=>d.cost-M.cost)}static async combinedAnalyse(s,t,a,i,o,n,e={}){e.counter=1,I==null||I.info("[%s][L%d] analyse with alternate cp in every %d days",e.requestId,e.level,n);const c=await W.alternateAnalyse(s,t,a,i,0,o,n,e),r=c.reduce((M,f)=>M+f.cost.total,0),u=c.reduce((M,f)=>M+f.cost.hire,0),h=c.reduce((M,f)=>M+f.cost.bunker,0),m=c.reduce((M,f)=>M+f.distance,0),b=c.reduce((M,f)=>M+f.totalHrs,0);I==null||I.info("[%s][L%d] cost with cpa/cpb turn: %j",e.requestId,e.level,{cost:r,hire:u,bunker:h,distance:m,hours:b});const y=await W.alternateAnalyse(s,t,a,i,1,o,n,e),j=y.reduce((M,f)=>M+f.cost.total,0),S=y.reduce((M,f)=>M+f.cost.hire,0),w=y.reduce((M,f)=>M+f.cost.bunker,0),v=y.reduce((M,f)=>M+f.distance,0),d=y.reduce((M,f)=>M+f.totalHrs,0);return I==null||I.info("[%s][L%d] cost with cpb/cpa turn: %j",e.requestId,e.level,{cost:j,hire:S,bunker:w,distance:v,hours:d}),r<j?{combined:!0,cost:Math.round(r*1e3)/1e3,speeds:c,step:n}:{combined:!0,cost:Math.round(j*1e3)/1e3,speeds:y,step:n}}static async alternateAnalyse(s,t,a,i,o,n,e,c={}){var m,b;let r=g.utc(s.etd);const u={lat:s.lat,lng:s.lng},h=[];for(;r.isBefore(a);){const y=r.clone().utc().add(e,"day"),j=JSON.parse(JSON.stringify(n.route)),S=JSON.parse(JSON.stringify(n.waypoints)),w=i[o],v=await W.analyseInstantWithThreshed(u,r.utc().format(),y,t,w,j,S,s.meteoVendor,s.speedStep,s.useMeteo,s.useRouteParam,c);v&&(await W.calculateCost(v,w,s,c),I==null||I.info("[%s][L%d-%d] analyse from %s to %s cost: %j",c.requestId,c.level,c.counter,r.utc().format(),y.utc().format(),{cost:v.cost.total,hire:v.cost.hire,bunker:v.cost.bunker,distance:v.distance,hours:v.totalHrs,cp:`${w.speed}/${w.fo}/${w.dgo}`})),c.counter=c.counter+1;const d=(b=(m=v==null?void 0:v.sample)==null?void 0:m.hours)==null?void 0:b.at(-1);if(d)u.lat=d.lat,u.lng=d.lng,r=g(d.eta),h.push(v),o=o?0:1;else break}return h}static async calculateCost(s,t,a,i={}){var o;if(s){const n=(a.addComm||0)>=1?(a.addComm||0)/100:a.addComm||0,e=Math.round(s.totalHrs/24*(a.dailyHire||0)*(1-n)*1e3)/1e3,c=Math.round(s.totalFoCons*(a.priceFO||0)*1e3)/1e3,r=Math.round((s.totalDgoCons+(((o=s.extend)==null?void 0:o.totalDgoConsInECA)||0))*(a.priceDGO||0)*1e3)/1e3;s.cost={total:Math.round((e+c+r)*1e3)/1e3,hire:e,bunker:Math.round((c+r)*1e3)/1e3,cp:t}}return s}static async calculateECA(s,t,a={}){var c,r,u,h;const i=await H.LaneHelper.intersectInECA((s==null?void 0:s.route)||[]);let o=0,n=0,e=0;(r=(c=s==null?void 0:s.sample)==null?void 0:c.wps)==null||r.forEach(m=>{m.positionTime=g.utc(m.etd||m.eta).unix()});for(const m of i){o+=m.distance;const b=await H.LaneHelper.deadReckoningTime((u=m.waypoints)==null?void 0:u.at(0),s.sample.wps),y=await H.LaneHelper.deadReckoningTime((h=m.waypoints)==null?void 0:h.at(-1),s.sample.wps);m.in=b,m.out=y,m.totalHrs=H.LngLatHelper.roundPrecision((y.positionTime-b.positionTime)/3600,3),m.totalDgoCons=H.LngLatHelper.roundPrecision(t.fo/24*m.totalHrs,3),n+=m.totalHrs,e+=m.totalDgoCons}return o=H.LngLatHelper.roundPrecision(o,3),n=H.LngLatHelper.roundPrecision(n,3),e=H.LngLatHelper.roundPrecision(e,3),{distanceInECA:o,hoursInECA:n,totalDgoConsInECA:e,eca:i}}static async mergeSpeeds(s,t={}){var d,M;const a={hours:[],wps:[],days:[]},i=s.reduce((f,l)=>f+l.distance,0),o=s.reduce((f,l)=>{var k;return f+(((k=l.extend)==null?void 0:k.distanceInECA)||0)},0),n=s.reduce((f,l)=>f+l.totalHrs,0),e=s.reduce((f,l)=>{var k;return f+(((k=l.extend)==null?void 0:k.hoursInECA)||0)},0),c=s.reduce((f,l)=>{var k;return f+(((k=l.extend)==null?void 0:k.totalDgoConsInECA)||0)},0),r=s.reduce((f,l)=>f+l.wxFactor*l.totalHrs/n,0),u=s.reduce((f,l)=>f+l.cFactor*l.totalHrs/n,0),h=s.reduce((f,l)=>f+l.totalFoCons,0),m=s.reduce((f,l)=>f+l.totalDgoCons,0),b=s.reduce((f,l)=>f+l.cost.total,0),y=s.reduce((f,l)=>f+l.cost.hire,0),j=s.reduce((f,l)=>f+l.cost.bunker,0),S=[],w=[];let v;for(const f of s){w.push(...((d=f.extend)==null?void 0:d.eca)||[]);const l=f.sample.hours,k=f.sample.wps,C=f.sample.days,x=l.at(0);v&&(x.distanceFromPrevious=v.distanceFromPrevious,x.distanceFromStart=v.distanceFromStart,l.forEach((N,E)=>{E&&(N.distanceFromStart=N.distanceFromStart+v.distanceFromStart)}),k.at(0).distanceFromPrevious=v.distanceFromPrevious,k.at(0).distanceFromStart=v.distanceFromStart,k.forEach((N,E)=>{E&&(N.distanceFromStart=N.distanceFromStart+v.distanceFromStart)}),C.at(0).distanceFromPrevious=v.distanceFromPrevious,C.at(0).distanceFromStart=v.distanceFromStart,C.forEach((N,E)=>{E&&(N.distanceFromStart=N.distanceFromStart+v.distanceFromStart)})),x.cp=f.cost.cp;const Y=[f.etd,f.eta],T=S.findIndex(N=>N.id===x.cp.id);T===-1?(x.cp.segment=[Y],S.push(x.cp)):S[T].segment.push(Y),l.forEach(N=>{var P;((P=a.hours)==null?void 0:P.findIndex(V=>V.eta===N.eta))===-1&&a.hours.push(N)}),k.forEach(N=>{var P;((P=a.wps)==null?void 0:P.findIndex(V=>V.eta===N.eta))===-1&&a.wps.push(N)}),C.forEach(N=>{var P;((P=a==null?void 0:a.days)==null?void 0:P.findIndex(V=>V.eta===N.eta))===-1&&a.days.push(N)});const L=(M=a.wps)==null?void 0:M.findIndex(N=>N.eta===x.eta);L===-1?a.wps.push(x):a.wps[L]=x,v=l.at(-1)}return a.wps.sort((f,l)=>{g(f.etd).unix()-g(l.etd).unix()}),a.wps.forEach((f,l)=>{const k=a.wps[l-1];if(k){const C=f.distanceFromStart-(k.distanceFromStart||0),x=g(f.eta||f.etd).diff(g(k.etd||k.eta),"hour",!0),Y=Math.round(C/x*100)/100;f.avgSpd=Y;const T=H.LaneHelper.calculateBearing(k,f);k.bearing=T}}),{sample:a,etd:s.at(0).etd,eta:s.at(-1).eta,from:s.at(0).from,to:s.at(-1).to,v0:s.at(0).v0,label:"Combined",distance:Math.round(i*1e3)/1e3,totalHrs:Math.round(n*1e3)/1e3,avgSpeed:Math.round(i/n*1e3)/1e3,wxFactor:Math.round(r*1e3)/1e3,cFactor:Math.round(u*1e3)/1e3,totalFoCons:Math.round(h*1e3)/1e3,totalDgoCons:Math.round(m*1e3)/1e3,cost:{total:Math.round(b*1e3)/1e3,hire:Math.round(y*1e3)/1e3,bunker:Math.round(j*1e3)/1e3},extend:{cps:S,eca:w,distanceInECA:Math.round(o*1e3)/1e3,hoursInECA:Math.round(e*1e3)/1e3,totalDgoConsInECA:Math.round(c*1e3)/1e3,speeds:s}}}}q.AISImpl=G,q.AlertHelper=dt,q.AlertLevel=ct,q.HifleetImpl=yt,q.LoadCondition=lt,q.MyShipImpl=Mt,q.MyVesselImpl=mt,q.ShipxyImpl=pt,q.SpeedHelper=W,q.SpeedLabel=ht,q.VesselTag=ut,q.alertHelper=bt,Object.defineProperty(q,Symbol.toStringTag,{value:"Module"})});
@@ -230,10 +230,12 @@ export declare class SpeedHelper {
230
230
  * @param vessel 船舶属性 @see VesselAssemble, 注意吃水为船舶实时吃水,非档案中的固定吃水,一般可以从ais获取; 如获取不得,用档案吃水代替
231
231
  * @param cp { loadCondition, speed } LoadCondition: Ballast or Laden, speed(kts)
232
232
  * @param route 航路[[[lng, lat]]]
233
+ * @param waypoints
233
234
  * @param source 气象数据源,GFS or CMEMES, 默认CMEMS
234
235
  * @param stepHrs
235
236
  * @param useMeteo true 启用气象分析
236
237
  * @param useRouteParam
238
+ * @param options
237
239
  */
238
240
  static analyseInstantWithThreshed(from: any, etd: string | moment.Moment | number, threshed: moment.Moment, vessel: VesselAssemble, cp: CpProps, route: number[][][], waypoints: any[], source?: string, stepHrs?: number, useMeteo?: boolean, useRouteParam?: boolean, options?: {
239
241
  requestId?: string;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@idm-plugin/vessel",
3
3
  "private": false,
4
- "version": "2.3.0",
4
+ "version": "2.3.1",
5
5
  "description": "idm plugin for vessel",
6
6
  "type": "module",
7
7
  "keywords": [