@idm-plugin/vessel 2.2.8 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ais/src/index.d.ts +68 -0
- package/dist/index.js +749 -653
- package/dist/index.umd.cjs +1 -1
- package/dist/speed/src/index.d.ts +4 -1
- package/package.json +1 -1
package/dist/index.umd.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(A,R){typeof exports=="object"&&typeof module<"u"?R(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"],R):(A=typeof globalThis<"u"?globalThis:A||self,R(A["idm-plugin-vessel"]={},A.got,A["@log4js-node/log4js-api"],A.moment,A["@idm-plugin/geo2"],A["@idm-plugin/meteo2"],A["@idm-plugin/meteo"]))})(this,function(A,R,K,p,x,mt,nt){"use strict";var St=Object.defineProperty;var kt=(A,R,K)=>R in A?St(A,R,{enumerable:!0,configurable:!0,writable:!0,value:K}):A[R]=K;var z=(A,R,K)=>(kt(A,typeof R!="symbol"?R+"":R,K),K);let g;try{g=K.getLogger("vessel")}catch{}finally{}class G{parseStatus(t){let e,a;switch(t){case 0:e="在航(主机推动)",a="Underway Using Engine";break;case 1:e="锚泊",a="Anchored";break;case 2:e="失控",a="Not operated";break;case 3:e="操纵受限",a="Limited airworthiness";break;case 4:e="吃水受限",a="Limited by ship's draft";break;case 5:e="靠泊",a="Mooring";break;case 6:e="搁浅",a="Stranded";break;case 7:e="捕捞作业",a="Engaged in fishing";break;case 8:e="靠帆船提供动力",a="Sailing";break;default:e="未定义",a="Undefined"}return{labelCn:e,labelEn:a}}}class yt extends G{constructor(e,a){super();z(this,"clientId");z(this,"clientSecret");z(this,"token");this.clientId=e,this.clientSecret=a}async authToken(e={}){const a="https://svc.data.myvessel.cn/ada/oauth/token",i={searchParams:{client_id:this.clientId,client_secret:this.clientSecret,grant_type:"client_credentials"}},n=await R.post(a,i).json();g==null||g.info("[%s] fetch access token from: %s - %j",e.requestId,a,n),n.error||(this.token={accessToken:n.access_token,tokenType:n.token_type,expiresIn:n.expires_in,scope:n.scope,jti:n.jti,issuedAt:p().utc().format()})}async realTimePosition(e,a={}){var d,r,m;(!this.token||p().diff(p(this.token.issuedAt),"seconds")>((d=this.token)==null?void 0:d.expiresIn)-300)&&await this.authToken(a);const i="https://svc.data.myvessel.cn/sdc/v1/vessels/status/location/unit",n={headers:{Authorization:`${(r=this.token)==null?void 0:r.tokenType} ${(m=this.token)==null?void 0:m.accessToken}`},searchParams:{mmsi:e}};g==null||g.info("[%s] fetch realtime position from: %s - %j",a.requestId,i,n);const o=await R.get(i,n).json();if(o.code)return g==null||g.warn("[%s] fetch realtime position failed: %j",a.requestId,i,{message:o.message,status:o.status,code:o.code}),o;const s=o.data;for(const M in s)!isNaN(s[M])&&Number(s[M])!==1/0&&(s[M]=Number(s[M]));if(s){const M=p(`${s.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return{mmsi:s.mmsi,name:s.vesselName||s.aisVesselName,imo:s.imo,callSign:s.callsign||s.aisCallSign,lat:s.lat,lng:s.lon,length:s.length,width:s.width,draught:s.currDraught,sog:s.sog,cog:s.cog,hdg:s.hdg,rot:s.rot,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(s.eta)?p.utc(s.eta).format():void 0,destination:s.dest,positionTime:M.unix(),status:s.status,labelCn:s.statusNameCn,labelEn:s.statusNameEn,vesselType:s.vesselTypeNameEn,flag:s.flagCtryNameEn,clasz:s.classSociety,build:s.buildYear,dwt:s.dwt,grt:s.grt,net:s.net,method:"position",vendor:"myVessel",utc:M.utc().format()}}else return{}}async trajectory(e,a,i,n,o=!0,s={}){(!this.token||p().diff(p(this.token.issuedAt),"seconds")>this.token.expiresIn-300)&&await this.authToken(s);const d=await this.realTimePosition(e,s),r=p(a),m=p(i),M=[];for(;m.diff(r,"day",!0)>30;)await this.trajectoryIn30Day(e,r,r.clone().add(30,"day"),d,n,M,s),r.add(30,"day");return await this.trajectoryIn30Day(e,r,m,d,n,M,s),M}async trajectoryIn30Day(e,a,i,n,o,s,d={}){var f,C,k,w,v;const r="https://svc.data.myvessel.cn/sdc/v1/vessels/status/track",m={headers:{Authorization:`${(f=this.token)==null?void 0:f.tokenType} ${(C=this.token)==null?void 0:C.accessToken}`},json:{mmsi:e,startTime:a.utcOffset(8).format("YYYY-MM-DD HH:mm:ss"),endTime:i.utcOffset(8).format("YYYY-MM-DD HH:mm:ss")}};g==null||g.info("[%s] fetch trajectory from: %s - %j",d.requestId,r,m);const M=await R.post(r,m).json();if(M.code)return g==null||g.warn("[%s] fetch trajectory failed: %j",d.requestId,r,{message:M.message,status:M.status,code:M.code}),M;let h=-1;const b=p(`${(w=(k=M.data)==null?void 0:k[0])==null?void 0:w.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return(v=M.data)==null||v.forEach(c=>{for(const P in c)!isNaN(c[P])&&Number(c[P])!==1/0&&(c[P]=Number(c[P]));const y=p(`${c.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00"),l=c.status,{labelCn:u,labelEn:I}=this.parseStatus(l),F={mmsi:c.mmsi,imo:n==null?void 0:n.imo,lat:c.lat,lng:c.lon,sog:c.sog,cog:c.cog,hdg:c.hdg,draught:c.draught,status:l,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(c.eta)?p(`${c.eta} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00").utc().format():void 0,destination:c.dest,positionTime:y.unix(),labelCn:u,labelEn:I,method:"trajectory",vendor:"myVessel",utc:y.utc().format()},T=Math.floor(y.diff(b,"minute",!0)/(o||1));T!==h&&(h=T,s.push(F))}),s}}class Mt extends G{constructor(e){super();z(this,"token");this.token=e}async realTimePosition(e,a={}){const i="https://api.hifleet.com/position/position/get/token",n={searchParams:{mmsi:e,usertoken:this.token}},o=await R.post(i,n).json();g==null||g.info("[%s] fetch realtime position from: %s - %j",a.requestId,i,n);const s=o==null?void 0:o.list;if(!s)return g==null||g.warn("[%s] fetch realtime position failed: %j",a.requestId,i,o),o;for(const b in s)!isNaN(s[b])&&Number(s[b])!==1/0&&(s[b]=Number(s[b]));s.status=s.sp>3?0:1;const d=s.status,{labelCn:r,labelEn:m}=this.parseStatus(d),M=p(`${s.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return{mmsi:s.m,name:s.n,imo:s.imonumber,callSign:s.callsign,lat:Math.round(s.la/60*1e5)/1e5,lng:Math.round(s.lo/60*1e5)/1e5,length:s.l,width:s.w,draught:s.draught,sog:s.sp,cog:s.co,hdg:s.h,rot:isNaN(s.rot)?0:s.rot,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(s.eta)?p.utc(s.eta).format():void 0,destination:s.destination,vesselType:s.type,dwt:s.dwt,build:s.buildyear,flag:s.fn,positionTime:M.unix(),utc:M.utc().format(),status:d,labelCn:r,labelEn:m,method:"position",vendor:"hifleet"}}async search(e,a={}){let i="https://www.hifleet.com/hifleetapi/searchVesselOL.do";const n={searchParams:{keyword:e},headers:{Referer:"https://www.hifleet.com",Origin:"https://www.hifleet.com",Host:"www.hifleet.com"}};let o=await R.post(i,n).json();g==null||g.info("[%s] fetch vessel props from: %s - %j",a.requestId,i,n),o instanceof Array&&(o=o[0]);for(const d in o)!isNaN(o[d])&&Number(o[d])!==1/0&&(o[d]=Number(o[d]));const s={mmsi:o.m,name:o.n,imo:o.i,callSign:o.c,length:o.l,breadth:o.b,draught:o.dr,type:o.t};return i="https://www.hifleet.com/hifleetapi/sameShipSearch.do",o=await R.post(i,n).json(),g==null||g.info("[%s] search vessel dead weight from: %s - %j",a.requestId,i,n),o instanceof Array&&(o=o[0]),o&&(s.deadweight=Number(o.dwt)),s}async suggest(e,a={}){const i="https://www.hifleet.com/hifleetapi/getShipSuggest.do",n={searchParams:{q:e},headers:{Referer:"https://www.hifleet.com",Origin:"https://www.hifleet.com",Host:"www.hifleet.com"}},o=await R.post(i,n).json();g==null||g.info("[%s] suggest vessel props from: %s - %j",a.requestId,i,n);const s=[];for(const d of o)s.push({mmsi:!d.mmsi||isNaN(d.mmsi)?null:Number(d.mmsi),name:d.name,callSign:d.callsign,imo:!d.imo||isNaN(d.imo)?null:Number(d.imo),score:d._score});return s.sort((d,r)=>r.score-d.score),s}async trajectory(e,a,i,n,o=!0,s={}){var c,y,l;const d=await this.realTimePosition(e,s);let r=p(a);const m=p(i),M=p();if(o){let u=m.diff(r,"d",!0);u<0?r=m.clone().subtract(40,"d"):u<30?r.subtract(10,"d"):u<60?r.subtract(5,"d"):r=m.clone().subtract(80,"d"),u=M.diff(m,"d",!0),m.add(u>10?240:u*24,"h")}const h={searchParams:{endtime:m.utcOffset("+8:00").format("YYYY-MM-DD HH:mm:ss"),starttime:r.utcOffset("+8:00").format("YYYY-MM-DD HH:mm:ss"),mmsi:e,usertoken:this.token}},b="https://api.hifleet.com/position/trajectory/nocompressed/withstatic/token",f=await R.get(b,h).json();g==null||g.info("[%s] fetch trajectory from: %s - %j",s.requestId,b,h);let C;f&&(C=((y=(c=f.ships)==null?void 0:c.offors)==null?void 0:y.ship)||[],C.length||g==null||g.warn("[%s] fetch trajectory failed: %j",s.requestId,f));const k=[];let w=-1;const v=p(`${(l=C==null?void 0:C[0])==null?void 0:l.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");for(const u of C){for(const L in u)!isNaN(u[L])&&Number(u[L])!==1/0&&(u[L]=Number(u[L]));const I=p(`${u.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");u.status=u.sp>4?0:1;const{labelEn:F,labelCn:T}=this.parseStatus(u.status),P={mmsi:u.m,name:u.n,imo:d==null?void 0:d.imo,lat:u.la,lng:u.lo,draught:u.draught,sog:u.sp,cog:u.co,hdg:u.hdg,positionTime:I.unix(),utc:I.utc().format(),status:u.status,labelCn:T,labelEn:F,method:"trajectory",vendor:"hifleet"},E=Math.floor(I.diff(v,"minute",!0)/(n||1));E!==w&&(w=E,k.push(P))}return k}}class pt extends G{constructor(e){super();z(this,"token");this.token=e}async realTimePosition(e,a={}){const i={searchParams:{id:e,k:this.token,enc:1}},n="https://api.shipxy.com/apicall/GetSingleShip",o=await R.get(n,i).json();if(g==null||g.info("[%s] fetch realtime position from: %s - %j",a.requestId,n,i),(o==null?void 0:o.status)!==0)return o;const s=o.data[0];for(const h in s)!isNaN(s[h])&&Number(s[h])!==1/0&&(s[h]=Number(s[h]));const{labelCn:d,labelEn:r}=await this.parseStatus(s.navistat),m=p.unix(s.lasttime);return{mmsi:s.ShipID,name:s.name,imo:s.imo,callSign:s.callsign,lat:Math.round(s.lat/1e6*1e5)/1e5,lng:Math.round(s.lon/1e6*1e5)/1e5,length:Math.round(s.length/10*100)/100,width:Math.round(s.width/10*100)/100,draught:Math.round(s.draught/1e3*100)/100,sog:Math.round(s.sog*3600/1e3/1852*100)/100,cog:Math.round(s.cog/100*100)/100,hdg:Math.round(s.hdg/100*100)/100,rot:Math.round(s.rot/100*100)/100,positionTime:s.lasttime,utc:m.utc().format(),status:s.navistat,labelEn:r,labelCn:d,method:"position",vendor:"shipxy"}}async trajectory(e,a,i,n,o=!0,s={}){var v;const d=await this.realTimePosition(e,s),r=p(a),m=p(i),M="https://api.shipxy.com/apicall/GetShipTrack",h={searchParams:{id:e,k:this.token,enc:1,cut:0,btm:r.unix(),etm:m.unix()}},b=await R.get(M,h).json();if(g==null||g.info("[%s] fetch trajectory from: %s - %j",s.requestId,M,h),(b==null?void 0:b.status)!==0)return b;const f=b==null?void 0:b.points,C=[],k=p.unix((v=f[0])==null?void 0:v.utc);let w=-1;for(const c of f){const y=p.unix(c.utc),l={imo:d==null?void 0:d.imo,mmsi:e,sog:Math.round(c.sog*3600/1e3/1852*100)/100,cog:Math.round(c.cog/100*100)/100,lat:Math.round(c.lat/1e6*1e5)/1e5,lng:Math.round(c.lon/1e6*1e5)/1e5,positionTime:y.unix(),utc:y.utc().format(),method:"trajectory",vendor:"shipxy"},u=Math.floor(y.diff(k,"minute",!0)/(n||1));u!==w&&(w=u,C.push(l))}return C}}class bt extends G{constructor(e){super();z(this,"token");this.token=e}async getShipId(e,a={}){const i={headers:{appKey:this.token},json:{mmsiList:e}},n="https://api3.myships.com/sp/ships/getShipIdByMMSI",o=await R.post(n,i).json();return g==null||g.info("[%s] fetch ship id from: %s - %j",a.requestId,n,i),o.code!=="0"?o:o.data[0].shipId}async getShipInfo(e,a={}){const i={headers:{appKey:this.token},json:{shipId:e}},n="https://api3.myships.com/sp/ships/aissta",o=await R.post(n,i).json();if(g==null||g.info("[%s] fetch ship info from: %s - %j",a.requestId,n,i),o.code!=="0")return o;const s=o.data;let d=s.imo;return e==="407170"&&(d="9198379",g==null||g.warn("[%s] ship(%s) imo error: %s, should be %s",a.requestId,e,s.imo,d)),{mmsi:s.mmsi,name:s.shipnameEn,imo:d,callSign:s.callSign,length:s.length,width:s.breadth,draught:(s.draught||100)/10}}async realTimePosition(e,a={}){const i=await this.getShipId(e,a),n=await this.getShipInfo(i,a),o={headers:{appKey:this.token},json:{shipId:i}},s="https://api3.myships.com/sp/ships/position/latest",d=await R.post(s,o).json();g==null||g.info("[%s] fetch realtime position from: %s - %j",a.requestId,s,o);const r=d.data[0];for(const f in r)!isNaN(r[f])&&Number(r[f])!==1/0&&(r[f]=Number(r[f]));const{labelCn:m,labelEn:M}=await this.parseStatus(r.aisNavStatus),h=p.unix(r.posTime);return{...n,mmsi:e,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:h.utc().format(),status:r.aisNavStatus,labelEn:M,labelCn:m,method:"position",vendor:"myship"}}async trajectory(e,a,i,n,o=!0,s={}){const d=p(a),r=p(i),m=await this.getShipId(e),M=await this.getShipInfo(m),h=[];for(;r.diff(d,"day",!0)>30;)await this.trajectoryIn30Day(m,d.unix(),d.add(30,"day").unix(),M,e,n,h);return await this.trajectoryIn30Day(m,d.unix(),r.unix(),M,e,n,h),h}async trajectoryIn30Day(e,a,i,n,o,s,d,r={}){var k;const m={headers:{appKey:this.token},json:{shipId:e,startTime:a,endTime:i}},M="https://api3.myships.com/sp/ships/position/history",h=await R.post(M,m).json();if(g==null||g.info("[%s] fetch trajectory from: %s - %j",r.requestId,M,m),h.code!=="0")return g==null||g.warn("[%s] invoke myship trajectory failed: %j",r.requestId,h),h;const b=h.data;for(const w in b)!isNaN(b[w])&&Number(b[w])!==1/0&&(b[w]=Number(b[w]));const f=p.unix((k=b[0])==null?void 0:k.posTime);let C=-1;for(const w of b){const v=p.unix(w.posTime),c={imo:n==null?void 0:n.imo,mmsi:o,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"},y=Math.floor(v.diff(f,"minute",!0)/(s||1));y!==C&&(C=y,d.push(c))}return d}}let _;try{_=K.getLogger("vessel")}catch{}finally{}var dt=(D=>(D.NOTICE="NOTICE",D.WARN="WARN",D.HEAVY="HEAVY",D.SEVERE="SEVERE",D.ERROR="ERROR",D.FATAL="FATAL",D))(dt||{});class ut{parsePrinciple(t,e={}){var s,d,r;_==null||_.debug("[%s] parse rule: %s",e.requestId,t);const a=new RegExp("(?<=\\[)(.+)(?=])","g"),i=t.match(a)?(s=t.match(a))==null?void 0:s[0]:void 0,n=i==null?void 0:i.split(";");if(!n)return;const o={};for(let m=0;m<(n==null?void 0:n.length);m++){const M=(r=(d=n[m].match(a))==null?void 0:d[0])==null?void 0:r.split("],");if(m===0&&!M)o.scope=n[0];else if(M)for(let h=0,b=M.length;h<b;h++){const f=this.parseRule(M[h]);f&&(o[f.level]?f.key?o[f.level][f==null?void 0:f.key]=f:o[f.level]=f:f.key?o[f.level]={[f==null?void 0:f.key]:f}:o[f.level]=f)}}return o}parseRule(t,e={}){var o;_==null||_.debug("[%s] parse rule: %s",e.requestId,t),t=t.startsWith("[")?t:`[${t}`,t=t.endsWith("]")?t:`${t}]`;const a=new RegExp("(?<=\\[)(.+?)(?=])","g"),i=(o=t==null?void 0:t.match(a))==null?void 0:o[0],n=i==null?void 0:i.split(",");if(n){let s=n[3]==="Number.MAX_VALUE"?100:Number(n[3]);return s=isNaN(s)?1:s,{operator:n[0],number:Number.isNaN(Number(n[1]))?n[1]:Number(n[1]),level:n[2],time:s,key:n[4]}}}checkWeather(t,e,a={}){var f,C,k,w,v,c,y,l,u,I,F,T,P,E,L;let i=0,n=0,o=0,s=0;const d=Math.round(((C=(f=e==null?void 0:e.SEVERE)==null?void 0:f.sigWave)==null?void 0:C.number)*1.6*100)/100,r=(w=(k=e==null?void 0:e.SEVERE)==null?void 0:k.sigWave)==null?void 0:w.number,m=(c=(v=e==null?void 0:e.HEAVY)==null?void 0:v.sigWave)==null?void 0:c.number,M=Math.round((((l=(y=e==null?void 0:e.SEVERE)==null?void 0:y.wind)==null?void 0:l.number)+2)*100)/100,h=(I=(u=e==null?void 0:e.SEVERE)==null?void 0:u.wind)==null?void 0:I.number,b=(T=(F=e==null?void 0:e.HEAVY)==null?void 0:F.wind)==null?void 0:T.number;for(let N=0;N<(t==null?void 0:t.length);N++){const H=t[N],q=(E=(P=H==null?void 0:H.meteo)==null?void 0:P.wave)==null?void 0:E.sig,V=(L=H==null?void 0:H.meteo)==null?void 0:L.wind,U=N?p(H.eta).diff(p(t[N-1].eta),"hour",!0):0;s=U>s?U:s,_==null||_.debug("[%s] check sig.wave: %j",a.requestId,{...q,dgThd4Wv:d,svThd4Wv:r,hvThd4Wv:m}),(q==null?void 0:q.height)>=d?H.isDangerous=!0:(q==null?void 0:q.height)>=r?H.isSevere=!0:(q==null?void 0:q.height)>=m&&(H.isHeavy=!0),_==null||_.debug("[%s] check wind: %j",a.requestId,{...V,dgThd4Wd:M,svThd4Wd:h,hvThd4Wd:b}),(V==null?void 0:V.scale)>=M?(H.isDangerous=!0,delete H.isSevere,delete H.isHeavy):(V==null?void 0:V.scale)>h?(H.isDangerous||(H.isSevere=!0),delete H.isHeavy):(V==null?void 0:V.scale)===b&&!H.isDangerous&&!H.isSevere&&(H.isHeavy=!0),i+=H.isDangerous?U:0,n+=H.isSevere?U:0,o+=H.isHeavy?U:0}return i=Math.round(i*100)/100,n=Math.round(n*100)/100,o=Math.round(o*100)/100,s=Math.round(s),{sample:t,dangerous:i,severe:n,heavy:o,step:s<3?3:s,wind:{dgThd4Wd:M,svThd4Wd:h,hvThd4Wd:b},sig:{dgThd4Wv:d,svThd4Wv:r,hvThd4Wv:m}}}}const gt=new ut;let S;try{S=K.getLogger("vessel")}catch{}finally{}const vt=new mt.MeteoHelper2("",!0);var lt=(D=>(D.common="common",D.container="container",D.tugs="tugs",D))(lt||{}),ht=(D=>(D.Ballast="Ballast",D.Laden="Laden",D))(ht||{}),ft=(D=>(D.Cp="CP",D.Perf="Basis",D.Instruct="Other",D))(ft||{});class W{static blockCoefficient(t,e,a,i){let n=Math.round(t/(e*a*i)*100)/100;n=n<.55?.55:n>.85?.85:n;const o=[.55,.6,.65,.7,.75,.8,.85],s=o.map(d=>Math.abs(d-n));return o[s.indexOf(Math.min(...s))]}static froudeNumber(t,e,a=9.8){let i=Math.round(Math.sqrt(t*t/(a*e))*100)/100;return i=i<.05?.05:i>.3?.3:i,i}static amendFactor(t,e,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 o={.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]}[t];return a==="Laden"&&(o=i[t]),o[0]+o[1]*e+o[2]*Math.pow(e,2)}static directionFactor(t,e=0){let a;return t>30&&t<=60?a=(1.7-.03*Math.pow(e-4,2))/2:t>60&&t<=150?a=(.9-.06*Math.pow(e-6,2))/2:t>150&&t<=180?a=(.4-.03*Math.pow(e-8,2))/2:a=1,Math.round(a*1e5)/1e5}static vesselTagFactor(t,e,a,i=0){i=i>6?i-.9*(i-6):i;let n;return a==="container"?n=.7*i+Math.pow(i,6.5)/(22*Math.pow(t,2/3)):e==="Ballast"?n=.7*i+Math.pow(i,6.5)/(2.7*Math.pow(t,2/3)):n=.5*i+Math.pow(i,6.5)/(2.7*Math.pow(t,2/3)),n}static waveHeightFactor(t,e){t=t<3?t*.7:t,t=t<0?.2:t,t=t>6?t-.9*(t-6):t,t=t>9?9:t;let a;return e>30&&e<=60?a=-.6:e>60&&e<=90?a=-.4:e>90&&e<=120?a=t<3?.4:-.3:e>120&&e<=150?a=t<3?.6:-.5:e>150&&e<=180?a=t<3?.7:-.6:a=-.7,Math.round(a*(.144*Math.pow(t,2)+.278*t)*1e4)/1e4}static assembleProperties(t,e,a,i){var h;const n=t.lbp??t.length??t.lengthOverall??198.9642,o=t.draught??8,s=t.breadthMoulded??t.breadth??t.breadthExtreme??32.4572,d=t.deadweight??67035.7773,r=((h=t==null?void 0:t.type)==null?void 0:h.toLowerCase())||"common";return{tag:r.indexOf("container")>-1?"container":r.indexOf("tugs")>-1?"tugs":"common",lbp:n,loadCondition:e,draught:o,breadthMoulded:s,displacement:Math.round((d/1.025+o*s*n*.7)*1e4)/1e4,speed:Math.round((a??14.1382)*1852/3600*1e4)/1e4,bearing:i||90}}static async speedLoseAt(t,e,a,i="",n=2,o=!0,s=!1,d={}){let r;if(e.velocity&&s&&(t.speed=x.LngLatHelper.roundPrecision(e.velocity*1852/3600,6)),o){let m;try{i=(i==null?void 0:i.toUpperCase())==="CMEMS"?"ECMWF":i,i=(i==null?void 0:i.toUpperCase())==="METEO2"?"best_match":i;const{weatherModels:f,marineModels:C}=await nt.Meteo2Assist.autoPickMeteoModel(i),k=await vt.spotForecast(e.lat,e.lng,a.utc().format(),!1,!1,!0,{...d,pastDays:1,forecastDays:1,weatherModels:f,marineModels:C}),[w]=nt.Meteo2Assist.pickHourly(k,a);m=nt.Meteo2Assist.toLegacy(w)}catch(f){S.warn("[%s] meteo2 spot(%j) forecast failed: %s",d.requestId,{...e,eta:a.utc().format(),source:i},f)}const M=W.weatherFactor(t,m),h=W.currentFactor(t.bearing,m==null?void 0:m.current,n),b=Math.round((t.speed*1.943844+M+h)*100)/100;r={meteo:{...m},wxFactor:M,cFactor:h,speed:e.velocity&&s?e.velocity:b<0?1:b,eta:a.utc().format(),etd:a.utc().format()}}else r={wxFactor:0,cFactor:0,speed:e.velocity&&s?e.velocity:Math.round((t.speed*1.943844+0+0)*100)/100,eta:a.utc().format(),etd:a.utc().format()};return delete e.meteo,delete e.wxFactor,delete e.cFactor,delete e.speed,delete e.etd,{...r,...e}}static async speedLoseInHoursStep(t,e,a,i,n,o,s="",d=!0,r=!1,m={}){e.utc();const M=e.clone().add(14,"days"),h=[],b=[];let f=0,C=0,k,w;for(let v=0;v<o.length-1;v++){let c=o[v];c.distanceFromStart=Math.round((n+C)*1e3)/1e3;const y=o[v+1];if(t.bearing=x.LaneHelper.calculateBearing(c,y,!y.gcToPrevious),c.bearing=t.bearing,c.suspend&&r){c.eta=c.eta||e.utc().format(),c.elapsed=c.elapsed??0;const I=c.suspend-c.elapsed;if(i-f>I)i=i-f-I,e.add(I,"hour"),c.elapsed=c.suspend;else{const F=i-f;c.elapsed+=F,e.add(F,"hour"),i=0}if(S==null||S.info(`[%s] suspend ${c.elapsed} hours at %j, and remain ${i} hours need to go...`,m.requestId,c),i===0)return c.distanceFromPrevious=C,{etd:e,from:w||c,to:c,next:o.filter(F=>F),wps:h,days:b}}else c.suspend=0;d=e.isAfter(M)?!1:d,c=await W.speedLoseAt(t,c,e,s,0,d,r,m),w=w||c,c.important&&h.push(c),e.isSameOrAfter(a)&&(b.push(c),a.add(24,"hour"));const l=x.LaneHelper.calculateDistance(c,y,!y.gcToPrevious);let u=Math.round(l/w.speed*1e5)/1e5;if(f+u<i){if(f+=u,e.add(u,"hour"),delete o[v],S==null||S.debug(`[%s] go to %j from %j with ${l}nm, and cost ${u} hours`,m.requestId,{lat:y.lat,lng:y.lng},{lat:w.lat,lng:w.lng,etd:w.etd}),C+=l,o.filter(I=>I).length<=1){k=y,k.eta=e.utc().format(),k.distanceFromPrevious=l,k.distanceFromStart=Math.round((n+C)*1e4)/1e4,h.push(k),delete o[v+1];break}}else{u=i-f,e.add(u,"hour");const I=x.LngLatHelper.roundPrecision(w.speed*u,5);k=x.LaneHelper.calculateCoordinate(c,t.bearing,I,"nauticalmiles",!y.gcToPrevious),k.eta=e.utc().format(),o[v]=k,S==null||S.debug(`[%s] go to %j from %j with ${I}nm, and cost ${u} hours`,m.requestId,{lat:k.lat,lng:k.lng},{lat:c.lat,lng:c.lng,etd:c.etd}),C+=I,k.distanceFromPrevious=Math.round(C*1e4)/1e4,k.distanceFromStart=Math.round((n+C)*1e4)/1e4;break}}return{etd:e,from:w,to:k,next:o.filter(v=>v),wps:h,days:b}}static currentFactor(t,e,a=0){const i=(t-(e==null?void 0:e.degree)||0)/180*Math.PI;if(Math.abs(i)===Math.PI/2)return 0;let n=((e==null?void 0:e.kts)||0)*Math.cos(i);return a&2?n=Math.ceil(n*100)/100:a&1?n=Math.floor(n*100)/100:n=Math.round(n*100)/100,Math.abs(n)>5?0:n}static weatherFactor(t,e){var M,h,b,f,C,k,w;S==null||S.debug("calculate weather factor via: %j",{...t,...e});const a=W.blockCoefficient(t.displacement,t.lbp,t.breadthMoulded,t.draught),i=W.froudeNumber(t.speed,t.lbp),n=W.amendFactor(a,i,t.loadCondition);let o=Math.abs(t.bearing%360-(((M=e==null?void 0:e.wind)==null?void 0:M.degree)%360||0));o=o>180?360-o:o;const s=W.directionFactor(o,(h=e==null?void 0:e.wind)==null?void 0:h.scale),d=W.vesselTagFactor(t.displacement,t.loadCondition,t.tag,(b=e==null?void 0:e.wind)==null?void 0:b.scale);let r=s*n*d/100*t.speed;r=Math.round(r*1.943844*1e4)/1e4*-1,t.tag==="tugs"&&Math.abs(r)>1&&(r=r/(Math.abs(Math.round(r))+1)),S==null||S.debug("wind wx factor = %d",r),o=Math.abs(t.bearing%360-(((C=(f=e==null?void 0:e.wave)==null?void 0:f.sig)==null?void 0:C.degree)%360||0));const m=W.waveHeightFactor(((w=(k=e==null?void 0:e.wave)==null?void 0:k.sig)==null?void 0:w.height)??1,o);return S==null||S.debug("wave wx factor = %d",m),r=Math.abs(r)>Math.abs(m)?r:r*.3+m*.7,S==null||S.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(t,e,a,i,n,o="",s=0,d=!0,r=!1,m={}){var X,Q,Z,$,tt,et;const M=p().valueOf();t.lng=x.LngLatHelper.convertToStdLng(t.lng);const{route:h,waypoints:b}=n.points,f=x.LaneHelper.calculateSubRoute(t,h);if(((X=f[0])==null?void 0:X.length)<=1)return;const{v0:C,label:k}=t.sog?{v0:t.sog,label:t.label||"Other"}:{v0:i.speed,label:"CP"},w=W.assembleProperties(a,i.loadCondition,C,0),v=b.length?x.LaneHelper.calculateSubWaypoints(t,b):[];v.forEach(Y=>Y.important=!0);const c={from:{...t},route:f,waypoints:v,v0:C,label:k},y={hours:[],days:[],wps:[]};s||(x.LaneHelper.calculateRouteDistance(f)/i.speed<=72?s=3:s=6);let l=x.LaneHelper.simplifyRouteToCoordinates(f,v,0),u=0,I=0,F=0,T=0;e=p(e).utc();const P=e.clone();for(;l.length>0;){const Y=s-e.hour()%s,J=Math.ceil(e.clone().add(Y,"h").set({minute:0,second:0,millisecond:0}).diff(e,"h",!0)*1e4)/1e4,j=await W.speedLoseInHoursStep(w,e,P,J,u,l,o,d,r,m);(Q=j.from)!=null&&Q.speed&&(y.hours.push(j.from),y.wps.push(...j.wps),y.days.push(...j.days)),l=j==null?void 0:j.next,l.length||y.hours.push(j==null?void 0:j.to),u+=Math.round((((Z=j==null?void 0:j.to)==null?void 0:Z.distanceFromPrevious)??0)*1e4)/1e4}const E=y.hours;for(let Y=0;Y<E.length-1;Y++){const J=p(E[Y+1].eta).diff(E[Y].etd,"hour",!0)||1;I+=(E[Y].wxFactor||0)*J,F+=(E[Y].cFactor||0)*J,T+=J}($=y.wps)==null||$.forEach((Y,J)=>{Y.positionTime=p.utc(Y.etd||Y.eta).unix();const j=y.wps[J-1];if(j){const B=Y.distanceFromStart-j.distanceFromStart,O=p(Y.eta||Y.etd).diff(p(j.etd||j.eta),"h",!0);Y.avgSpd=Math.round(B/O*100)/100;const ct=x.LaneHelper.calculateBearing(j,Y);j.bearing=ct}}),y.wps=(tt=y.wps)==null?void 0:tt.reduce((Y,J)=>(Y.some(j=>Math.round(j.positionTime/60)===Math.round(J.positionTime/60))||Y.push(J),Y),[]),c.sample=y;const L=y.hours.at(0),N=y.hours.at(-1);c.distance=Math.round(N.distanceFromStart*1e3)/1e3,c.etd=p(L.eta).utc().format(),c.eta=p(N.eta).utc().format(),c.wxFactor=Math.round(I/T*1e3)/1e3,c.cFactor=Math.round(F/T*1e3)/1e3,c.avgSpeed=Math.round(N.distanceFromStart/T*1e3)/1e3,c.totalHrs=Math.round(T*1e3)/1e3;const{distanceInECA:H,hoursInECA:q,totalDgoConsInECA:V,eca:U}=await this.calculateECA(c,i,m),st=x.LngLatHelper.roundPrecision(i.fo/24*(T-q),3),ot=x.LngLatHelper.roundPrecision(i.dgo/24*T,3);c.extend={eca:U,distanceInECA:H,hoursInECA:q,totalDgoConsInECA:V},c.totalFoCons=st<0?0:st,c.totalDgoCons=ot;const at=p().valueOf()-M,rt=((et=y==null?void 0:y.hours)==null?void 0:et.length)||1;return S==null||S.info("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms",m==null?void 0:m.requestId,at,rt,Math.round(at/rt*1e3)/1e3),c}static async analyseInstantWithThreshed(t,e,a,i,n,o,s,d="",r=3,m=!0,M=!1,h={}){var Z,$,tt,et,Y,J;const b=p().valueOf();t.lng=x.LngLatHelper.convertToStdLng(t.lng);const{v0:f,label:C}=t.sog?{v0:t.sog,label:t.label||"Other"}:{v0:n.speed,label:"CP"},k=W.assembleProperties(i,n.loadCondition,f,0),w=x.LaneHelper.calculateSubRoute(t,o);if(((Z=w[0])==null?void 0:Z.length)<=1)return;const v=s.length?x.LaneHelper.calculateSubWaypoints(t,s):[];v.forEach(j=>j.important=!0);let c=x.LaneHelper.simplifyRouteToCoordinates(w,v,0),y=0,l=0,u=0,I=0;const F={hours:[],wps:[],days:[]};e=p(e).utc();const T=e.clone();for(;c.length>0;){const j=r-e.hour()%r;let B=Math.ceil(e.clone().add(j,"h").set({minute:0,second:0,millisecond:0}).diff(e,"h",!0)*1e4)/1e4;B=e.clone().add(B,"h").isSameOrAfter(a)?a.diff(e,"h",!0)*1e4/1e4:B;const O=await W.speedLoseInHoursStep(k,e,T,B,y,c,d,m,M,h);if(($=O.from)!=null&&$.speed&&(F.hours.push(O.from),O!=null&&O.wps&&F.wps.push(...O.wps),F.days.push(...O.days)),c=O==null?void 0:O.next,c.length||F.hours.push(O==null?void 0:O.to),y+=Math.round((((tt=O==null?void 0:O.to)==null?void 0:tt.distanceFromPrevious)??0)*1e4)/1e4,!B)break}F.wps=(et=F.wps)==null?void 0:et.reduce((j,B)=>(j.some(O=>Math.round(p(O.etd).unix()/60)===Math.round(p(B.etd).unix()/60))||j.push(B),j),[]),(Y=F.wps)==null||Y.forEach((j,B)=>{const O=F.wps[B-1];if(O){const ct=j.distanceFromStart-O.distanceFromStart,wt=p(j.eta||j.etd).diff(p(O.etd||O.eta),"h",!0);j.avgSpd=Math.round(ct/wt*100)/100;const It=x.LaneHelper.calculateBearing(O,j);O.bearing=It}});const P=F.hours;for(let j=0;j<P.length-1;j++){const B=p(P[j+1].eta).diff(P[j].etd,"hour",!0);l+=P[j].wxFactor*B,u+=P[j].cFactor*B,I+=B}const E=F.hours.at(0),L=F.hours.at(-1),N=await x.LaneHelper.calculateRangeRoute(E,L,w),H=await x.LaneHelper.calculateRangeWaypoints(E,L,w,v),q={sample:F,distance:Math.round(((L==null?void 0:L.distanceFromStart)||0)*1e4)/1e4,etd:p(E.eta).utc().format(),eta:p(L==null?void 0:L.eta).utc().format(),wxFactor:Math.round(l/I*1e3)/1e3,cFactor:Math.round(u/I*1e3)/1e3,avgSpeed:Math.round(((L==null?void 0:L.distanceFromStart)||0)/I*1e3)/1e3,totalHrs:Math.round(I*1e3)/1e3,from:E,to:L,route:N,waypoints:H,v0:f,label:C},{distanceInECA:V,hoursInECA:U,totalDgoConsInECA:st,eca:ot}=await this.calculateECA(q,n,h),it=x.LngLatHelper.roundPrecision(n.fo/24*(I-U),3),at=x.LngLatHelper.roundPrecision(n.dgo/24*I,3);q.extend={eca:ot,distanceInECA:V,hoursInECA:U,totalDgoConsInECA:st},q.totalDgoCons=at,q.totalFoCons=it<0?0:it;const X=p().valueOf()-b,Q=((J=F==null?void 0:F.hours)==null?void 0:J.length)||1;return S==null||S.debug("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms",h==null?void 0:h.requestId,X,Q,Math.round(X/Q*1e3)/1e3),q}static async analyseCost(t,e,a,i,n={}){var w,v;const o=p().valueOf(),s=[];t.speedStep=t.speedStep||3,t.alterStep=t.alterStep??1;const d=x.LaneHelper.calculateRouteDistance(i.route);let r=0;a.forEach(c=>{const y=Math.ceil(d/c.speed/24);r=r<y?y:r}),r=r*1.3;const m=p.utc(t.etd).add(r??14,"day");let M=1;for(const c of a){const y=JSON.parse(JSON.stringify(i.route)),l=JSON.parse(JSON.stringify(i.waypoints)),u=await W.analyseInstantWithThreshed({lat:t.lat,lng:t.lng},t.etd,m,e,c,y,l,t.meteoVendor,t.speedStep,t.useMeteo,t.useRouteParam,n);u&&(await W.calculateCost(u,c,t,n),s.push(u),S==null||S.info("[%s][L%d-%d] analyse from %s to %s cost: %j",n.requestId,1,M,t.etd,m.format(),{cost:u.cost.total,hire:u.cost.hire,bunker:u.cost.bunker,distance:u.distance,hours:u.totalHrs,cp:`${c.speed}/${c.fo}/${c.dgo}`})),M++}s.sort((c,y)=>c.cost.total-y.cost.total);const h=s.at(0),b=s.at(1),f=[];if(f.push({combined:!1,speeds:[h],cost:(w=h.cost)==null?void 0:w.total}),b){const c=h.cost.cp,y=b.cost.cp,l=p(h.eta),u=p(h.etd),I=l.diff(u,"days",!0);let F=Math.ceil(I/2);F=F>7?7:F<t.alterStep?t.alterStep:F;let T=2,P={combined:!1,speeds:[b],cost:(v=b.cost)==null?void 0:v.total},E;for(;F>=t.alterStep;){const L=await W.combinedAnalyse(t,e,m,[c,y],i,F,{...n,level:T});if(P.cost>L.cost?E?(E==null?void 0:E.cost)>L.cost&&(E=L):(E=P,P=L):(!E||(E==null?void 0:E.cost)>L.cost)&&(E=L),F<=t.alterStep)break;F=Math.ceil(F/2),T+=1}f.push(P),E&&f.push(E)}const k=p().valueOf()-o;return S==null||S.info("[%s] analyse elapsed: %d ms",n==null?void 0:n.requestId,k),f.sort((c,y)=>c.cost-y.cost)}static async combinedAnalyse(t,e,a,i,n,o,s={}){s.counter=1,S==null||S.info("[%s][L%d] analyse with alternate cp in every %d days",s.requestId,s.level,o);const d=await W.alternateAnalyse(t,e,a,i,0,n,o,s),r=d.reduce((y,l)=>y+l.cost.total,0),m=d.reduce((y,l)=>y+l.cost.hire,0),M=d.reduce((y,l)=>y+l.cost.bunker,0),h=d.reduce((y,l)=>y+l.distance,0),b=d.reduce((y,l)=>y+l.totalHrs,0);S==null||S.info("[%s][L%d] cost with cpa/cpb turn: %j",s.requestId,s.level,{cost:r,hire:m,bunker:M,distance:h,hours:b});const f=await W.alternateAnalyse(t,e,a,i,1,n,o,s),C=f.reduce((y,l)=>y+l.cost.total,0),k=f.reduce((y,l)=>y+l.cost.hire,0),w=f.reduce((y,l)=>y+l.cost.bunker,0),v=f.reduce((y,l)=>y+l.distance,0),c=f.reduce((y,l)=>y+l.totalHrs,0);return S==null||S.info("[%s][L%d] cost with cpb/cpa turn: %j",s.requestId,s.level,{cost:C,hire:k,bunker:w,distance:v,hours:c}),r<C?{combined:!0,cost:Math.round(r*1e3)/1e3,speeds:d,step:o}:{combined:!0,cost:Math.round(C*1e3)/1e3,speeds:f,step:o}}static async alternateAnalyse(t,e,a,i,n,o,s,d={}){var h,b;let r=p.utc(t.etd);const m={lat:t.lat,lng:t.lng},M=[];for(;r.isBefore(a);){const f=r.clone().utc().add(s,"day"),C=JSON.parse(JSON.stringify(o.route)),k=JSON.parse(JSON.stringify(o.waypoints)),w=i[n],v=await W.analyseInstantWithThreshed(m,r.utc().format(),f,e,w,C,k,t.meteoVendor,t.speedStep,t.useMeteo,t.useRouteParam,d);v&&(await W.calculateCost(v,w,t,d),S==null||S.info("[%s][L%d-%d] analyse from %s to %s cost: %j",d.requestId,d.level,d.counter,r.utc().format(),f.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}`})),d.counter=d.counter+1;const c=(b=(h=v==null?void 0:v.sample)==null?void 0:h.hours)==null?void 0:b.at(-1);if(c)m.lat=c.lat,m.lng=c.lng,r=p(c.eta),M.push(v),n=n?0:1;else break}return M}static async calculateCost(t,e,a,i={}){var n;if(t){const o=(a.addComm||0)>=1?(a.addComm||0)/100:a.addComm||0,s=Math.round(t.totalHrs/24*(a.dailyHire||0)*(1-o)*1e3)/1e3,d=Math.round(t.totalFoCons*(a.priceFO||0)*1e3)/1e3,r=Math.round((t.totalDgoCons+(((n=t.extend)==null?void 0:n.totalDgoConsInECA)||0))*(a.priceDGO||0)*1e3)/1e3;t.cost={total:Math.round((s+d+r)*1e3)/1e3,hire:s,bunker:Math.round((d+r)*1e3)/1e3,cp:e}}return t}static async calculateECA(t,e,a={}){var d,r,m,M;const i=await x.LaneHelper.intersectInECA((t==null?void 0:t.route)||[]);let n=0,o=0,s=0;(r=(d=t==null?void 0:t.sample)==null?void 0:d.wps)==null||r.forEach(h=>{h.positionTime=p.utc(h.etd||h.eta).unix()});for(const h of i){n+=h.distance;const b=await x.LaneHelper.deadReckoningTime((m=h.waypoints)==null?void 0:m.at(0),t.sample.wps),f=await x.LaneHelper.deadReckoningTime((M=h.waypoints)==null?void 0:M.at(-1),t.sample.wps);h.in=b,h.out=f,h.totalHrs=x.LngLatHelper.roundPrecision((f.positionTime-b.positionTime)/3600,3),h.totalDgoCons=x.LngLatHelper.roundPrecision(e.fo/24*h.totalHrs,3),o+=h.totalHrs,s+=h.totalDgoCons}return n=x.LngLatHelper.roundPrecision(n,3),o=x.LngLatHelper.roundPrecision(o,3),s=x.LngLatHelper.roundPrecision(s,3),{distanceInECA:n,hoursInECA:o,totalDgoConsInECA:s,eca:i}}static async mergeSpeeds(t,e={}){var c,y;const a={hours:[],wps:[],days:[]},i=t.reduce((l,u)=>l+u.distance,0),n=t.reduce((l,u)=>{var I;return l+(((I=u.extend)==null?void 0:I.distanceInECA)||0)},0),o=t.reduce((l,u)=>l+u.totalHrs,0),s=t.reduce((l,u)=>{var I;return l+(((I=u.extend)==null?void 0:I.hoursInECA)||0)},0),d=t.reduce((l,u)=>{var I;return l+(((I=u.extend)==null?void 0:I.totalDgoConsInECA)||0)},0),r=t.reduce((l,u)=>l+u.wxFactor*u.totalHrs/o,0),m=t.reduce((l,u)=>l+u.cFactor*u.totalHrs/o,0),M=t.reduce((l,u)=>l+u.totalFoCons,0),h=t.reduce((l,u)=>l+u.totalDgoCons,0),b=t.reduce((l,u)=>l+u.cost.total,0),f=t.reduce((l,u)=>l+u.cost.hire,0),C=t.reduce((l,u)=>l+u.cost.bunker,0),k=[],w=[];let v;for(const l of t){w.push(...((c=l.extend)==null?void 0:c.eca)||[]);const u=l.sample.hours,I=l.sample.wps,F=l.sample.days,T=u.at(0);v&&(T.distanceFromPrevious=v.distanceFromPrevious,T.distanceFromStart=v.distanceFromStart,u.forEach((N,H)=>{H&&(N.distanceFromStart=N.distanceFromStart+v.distanceFromStart)}),I.at(0).distanceFromPrevious=v.distanceFromPrevious,I.at(0).distanceFromStart=v.distanceFromStart,I.forEach((N,H)=>{H&&(N.distanceFromStart=N.distanceFromStart+v.distanceFromStart)}),F.at(0).distanceFromPrevious=v.distanceFromPrevious,F.at(0).distanceFromStart=v.distanceFromStart,F.forEach((N,H)=>{H&&(N.distanceFromStart=N.distanceFromStart+v.distanceFromStart)})),T.cp=l.cost.cp;const P=[l.etd,l.eta],E=k.findIndex(N=>N.id===T.cp.id);E===-1?(T.cp.segment=[P],k.push(T.cp)):k[E].segment.push(P),u.forEach(N=>{var q;((q=a.hours)==null?void 0:q.findIndex(V=>V.eta===N.eta))===-1&&a.hours.push(N)}),I.forEach(N=>{var q;((q=a.wps)==null?void 0:q.findIndex(V=>V.eta===N.eta))===-1&&a.wps.push(N)}),F.forEach(N=>{var q;((q=a==null?void 0:a.days)==null?void 0:q.findIndex(V=>V.eta===N.eta))===-1&&a.days.push(N)});const L=(y=a.wps)==null?void 0:y.findIndex(N=>N.eta===T.eta);L===-1?a.wps.push(T):a.wps[L]=T,v=u.at(-1)}return a.wps.sort((l,u)=>{p(l.etd).unix()-p(u.etd).unix()}),a.wps.forEach((l,u)=>{const I=a.wps[u-1];if(I){const F=l.distanceFromStart-(I.distanceFromStart||0),T=p(l.eta||l.etd).diff(p(I.etd||I.eta),"hour",!0),P=Math.round(F/T*100)/100;l.avgSpd=P;const E=x.LaneHelper.calculateBearing(I,l);I.bearing=E}}),{sample:a,etd:t.at(0).etd,eta:t.at(-1).eta,from:t.at(0).from,to:t.at(-1).to,v0:t.at(0).v0,label:"Combined",distance:Math.round(i*1e3)/1e3,totalHrs:Math.round(o*1e3)/1e3,avgSpeed:Math.round(i/o*1e3)/1e3,wxFactor:Math.round(r*1e3)/1e3,cFactor:Math.round(m*1e3)/1e3,totalFoCons:Math.round(M*1e3)/1e3,totalDgoCons:Math.round(h*1e3)/1e3,cost:{total:Math.round(b*1e3)/1e3,hire:Math.round(f*1e3)/1e3,bunker:Math.round(C*1e3)/1e3},extend:{cps:k,eca:w,distanceInECA:Math.round(n*1e3)/1e3,hoursInECA:Math.round(s*1e3)/1e3,totalDgoConsInECA:Math.round(d*1e3)/1e3,speeds:t}}}}A.AISImpl=G,A.AlertHelper=ut,A.AlertLevel=dt,A.HifleetImpl=Mt,A.LoadCondition=ht,A.MyShipImpl=bt,A.MyVesselImpl=yt,A.ShipxyImpl=pt,A.SpeedHelper=W,A.SpeedLabel=ft,A.VesselTag=lt,A.alertHelper=gt,Object.defineProperty(A,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 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"})});
|
|
@@ -162,10 +162,11 @@ export declare class SpeedHelper {
|
|
|
162
162
|
* @param props 船舶属性
|
|
163
163
|
* @param coordinate {lat: 纬度, lng: 经度, velocity: 速度(kts, 可选,指定速度) }
|
|
164
164
|
* @param eta 位置时间
|
|
165
|
-
* @param source
|
|
165
|
+
* @param source
|
|
166
166
|
* @param role 1: 船东, 2: 租家, 0: 未知
|
|
167
167
|
* @param useMeteo true 启用气象分析
|
|
168
168
|
* @param useRouteParam true 启用设置速度
|
|
169
|
+
* @param options
|
|
169
170
|
*/
|
|
170
171
|
static speedLoseAt(props: VesselProperties, coordinate: any, eta: moment.Moment, source?: string, role?: number, useMeteo?: boolean, useRouteParam?: boolean, options?: {
|
|
171
172
|
requestId?: string;
|
|
@@ -182,6 +183,7 @@ export declare class SpeedHelper {
|
|
|
182
183
|
* @param source 气象数据源: CMEMS / GFS
|
|
183
184
|
* @param useMeteo true 启用气象分析
|
|
184
185
|
* @param useRouteParam true 启用航线上设置的参数 { suspend: 停留时长(小时), velocity: 速度(kts)}
|
|
186
|
+
* @param options
|
|
185
187
|
* @private
|
|
186
188
|
*/
|
|
187
189
|
private static speedLoseInHoursStep;
|
|
@@ -209,6 +211,7 @@ export declare class SpeedHelper {
|
|
|
209
211
|
* @param stepHrs 样本步长, 0表示动态计算(6 or 3 hrs)
|
|
210
212
|
* @param useMeteo true 启用气象分析
|
|
211
213
|
* @param useRouteParam
|
|
214
|
+
* @param options
|
|
212
215
|
*/
|
|
213
216
|
static analyseInstant(from: any, etd: string | number | moment.Moment, vessel: VesselAssemble, cp: CpProps, lane: {
|
|
214
217
|
points: {
|