@idm-plugin/vessel 3.4.6 → 3.4.7

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.
@@ -1 +1 @@
1
- (function(P,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):(P=typeof globalThis<"u"?globalThis:P||self,A(P["idm-plugin-vessel"]={},P.got,P["@log4js-node/log4js-api"],P.moment,P["@idm-plugin/geo2"],P["@idm-plugin/meteo2"],P["@idm-plugin/meteo"]))})(this,function(P,A,K,v,L,pt,it){"use strict";var Ct=Object.defineProperty;var jt=(P,A,K)=>A in P?Ct(P,A,{enumerable:!0,configurable:!0,writable:!0,value:K}):P[A]=K;var U=(P,A,K)=>(jt(P,typeof A!="symbol"?A+"":A,K),K);let p;try{p=K.getLogger("vessel")}catch{}finally{}class G{parseStatus(s){let e,a;switch(s){case 0:e="在航(主机推动)",a="Underway Using Engine";break;case 1:e="锚泊",a="Anchored";break;case 2:e="失控",a="Not under command";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 Mt extends G{constructor(e,a){super();U(this,"clientId");U(this,"clientSecret");U(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 A.post(a,i).json();p==null||p.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:v().utc().format()})}async checkToken(e={}){var a;return(!this.token||v().diff(v(this.token.issuedAt),"seconds")>(((a=this.token)==null?void 0:a.expiresIn)||0)-300)&&await this.authToken(e),this.token}async suggest(e,a={}){var t,r;await this.checkToken(a);const i="https://market.myvessel.cn/sdc/v1/mkt/vessels/fuzzy",n={headers:{Authorization:`${(t=this.token)==null?void 0:t.tokenType} ${(r=this.token)==null?void 0:r.accessToken}`},json:{kw:e,recordNum:a.ps||10}};p==null||p.info("[%s] fetch suggest vessels from: %s - %j",a.requestId,i,n);const o=await A.post(i,n).json();return o.status!==200?(p==null||p.warn("[%s] fetch suggest vessels failed: %j",a.requestId,{message:o.message,status:o.status,code:o.code}),[]):(o.data||[]).map(h=>({mmsi:h.mmsi,name:h.nameEn,nameCn:h.nameCn,imo:Number.isNaN(h.imo)?null:Number(h.imo),callSign:h.callsign,type:h.vesselTypeNameEn,flagName:h.flagCtry,vendor:"myvessel",raw:h}))}async search(e,a={}){var u,h;await this.checkToken(a);const i=/^\d{7}$/.test(e.toString()),n=i?"https://market.myvessel.cn/sdc/v1/mkt/vessels/detail/imo":"https://market.myvessel.cn/sdc/v1/mkt/vessels/detail/mmsi",o=i?{imo:e}:{mmsi:e},t={headers:{Authorization:`${(u=this.token)==null?void 0:u.tokenType} ${(h=this.token)==null?void 0:h.accessToken}`},searchParams:o};p==null||p.info("[%s] fetch vessel from: %s - %j",a.requestId,n,t);const r=await A.get(n,t).json();if(r.status!==200)return p==null||p.warn("[%s] fetch suggest vessels failed: %j",a.requestId,{message:r.message,status:r.status,code:r.code}),{};{const d=r.data;if(d)return{mmsi:d.mmsi,imo:Number.isNaN(d.imo)?null:Number(d.imo),callSign:d.callsign,name:d.nameEn,nameCn:d.nameCn,type:d.vesselTypeNameEn,flagName:d.flagCtry,clasz:d.classSociety,dateOfBuild:d.buildYearMonth,deadweight:d.dwt,grossTonnage:d.grt,netTonnage:d.net,teu:d.teu,length:d.length,breadth:d.width,height:d.height,draught:d.draught,speed:d.speed,passengerCapacity:d.passengercapacity,vendor:"myvessel",raw:d}}return{}}async archives(e,a={}){var t,r;await this.checkToken(a);const i="https://svc.data.myvessel.cn/sdc/v1/ship/info/batch",n={headers:{Authorization:`${(t=this.token)==null?void 0:t.tokenType} ${(r=this.token)==null?void 0:r.accessToken}`},json:{mmsiList:typeof e=="number"?[e]:e}};p==null||p.info("[%s] fetch vessel archive from: %s - %j",a.requestId,i,n);const o=await A.post(i,n).json();return o.status!==200?(p==null||p.warn("[%s] fetch vessel archive failed: %j",a.requestId,{message:o.message,status:o.status,code:o.code}),{}):o.data}async realTimePosition(e,a={}){var r,u;await this.checkToken(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} ${(u=this.token)==null?void 0:u.accessToken}`},searchParams:{mmsi:e}};p==null||p.info("[%s] fetch realtime position from: %s - %j",a.requestId,i,n);const o=await A.get(i,n).json();if(o.code)return p==null||p.warn("[%s] fetch realtime position failed: %j",a.requestId,{message:o.message,status:o.status,code:o.code}),o;const t=o.data;for(const h in t)!isNaN(t[h])&&Number(t[h])!==1/0&&(t[h]=Number(t[h]));if(t){const h=v(`${t.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return{mmsi:t.mmsi,name:t.vesselName||t.aisVesselName,imo:t.imo,callSign:t.callsign||t.aisCallSign,lat:t.lat,lng:t.lon,length:t.length,width:t.width,draught:t.currDraught,sog:t.sog,cog:t.cog,hdg:t.hdg,rot:t.rot,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(t.eta)?v.utc(t.eta).format():void 0,destination:t.dest,positionTime:h.unix(),status:t.status,labelCn:t.statusNameCn,labelEn:t.statusNameEn,vesselType:t.vesselTypeNameEn,flag:t.flagCtryNameEn,clasz:t.classSociety,build:t.buildYear,dwt:t.dwt,grt:t.grt,net:t.net,method:"position",vendor:"myVessel",utc:h.utc().format()}}else return{}}async calculateRoute(e,a,i,n,o,t={}){var y,w,M;const r=v();await this.checkToken(t);const u="https://svc.data.myvessel.cn/sdc/v1/routes/routing/nodes",h={headers:{Authorization:`${(y=this.token)==null?void 0:y.tokenType} ${(w=this.token)==null?void 0:w.accessToken}`},json:{startPoint:{lon:e.lng,lat:e.lat},endPoint:{lon:a.lng,lat:a.lat},maxDraught:t.draught||10,useAIModel:t.useAIModel||!1,withECA:t.withECA||!1,withSpecialRegion:t.withSpecial||!1}};i!=null&&i.length&&(h.json.crossMonthList=i),n!=null&&n.length&&(h.json.excludeNodes=n),o!=null&&o.length&&(h.json.excludeSeaAreas=o),p==null||p.info("[%s] fetch route from: %s - %j",t.requestId,u,h);const d=await A.post(u,h).json();if(d.status!==200)return p==null||p.warn("[%s] fetch route failed: %j",t.requestId,{message:d.message,status:d.status,code:d.code}),{};{const I={status:"Success",nodes:[],seas:[],regions:[],waypoints:[],route:[],distance:0,memo:""},{nodes:T,seas:b,tracks:g,specialRegions:m}=d.data;I.nodes=T==null?void 0:T.map(c=>({code:c.nodeCode,nameEn:c.nameEn,nameCn:c.nameCn,center:{lat:Math.round(c.lat*1e6)/1e6,lng:Math.round(c.lon*1e6)/1e6},start:{lat:Math.round(c.startLat*1e6)/1e6,lng:Math.round(c.startLon*1e6)/1e6},end:{lat:Math.round(c.endLat*1e6)/1e6,lng:Math.round(c.endLat*1e6)/1e6},isKey:c.isKeyNode,isHub:c.isHubNode})),I.seas=b==null?void 0:b.map(c=>({code:c.mrgidSea,nameEn:c.nameEn,nameCn:c.nameCn,center:{lat:Math.round(c.centerLat*1e6)/1e6,lng:Math.round(c.centerLon*1e6)/1e6},min:{lat:Math.round(c.minLat*1e6)/1e6,lng:Math.round(c.minLon*1e6)/1e6},max:{lat:Math.round(c.maxLat*1e6)/1e6,lng:Math.round(c.maxLon*1e6)/1e6},level:c.mapLevel})),m==null||m.map(c=>{c.regionLength&&I.regions.push({type:c.regionType,distance:c.regionLength,rows:c.regions.map(k=>({code:k.regionCode,nameCn:k.nameCn,nameEn:k.nameEn,type:k.regionType,distance:k.length}))})}),I.waypoints=g==null?void 0:g.map(c=>({lat:Math.round(c.lat*1e5)/1e5,lng:Math.round(c.lon*1e5)/1e5})),(M=I.waypoints)!=null&&M.length&&(I.waypoints=L.LaneHelper.simplifyCoordinates(I.waypoints),I.route=L.LaneHelper.divideAccordingToLng(I.waypoints),I.distance=L.LaneHelper.calculateRouteDistance(I.route));const f=v().diff(r,"second");return I.memo=`time cost: ${f}s`,p.info("[%s] calculate route cost: %d seconds",t.requestId,f),I}}async trajectory(e,a,i,n,o=!0,t={}){await this.checkToken(t);const r=await this.realTimePosition(e,t),u=v(a),h=v(i),d=[];for(;h.diff(u,"day",!0)>30;)await this.trajectoryIn30Day(e,u,u.clone().add(30,"day"),r,n,d,t),u.add(30,"day");return await this.trajectoryIn30Day(e,u,h,r,n,d,t),d}async trajectoryIn30Day(e,a,i,n,o,t,r={}){var M,I,T,b,g;const u="https://svc.data.myvessel.cn/sdc/v1/vessels/status/track",h={headers:{Authorization:`${(M=this.token)==null?void 0:M.tokenType} ${(I=this.token)==null?void 0:I.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")}};p==null||p.info("[%s] fetch trajectory from: %s - %j",r.requestId,u,h);const d=await A.post(u,h).json();if(d.code)return p==null||p.warn("[%s] fetch trajectory failed: %j",r.requestId,u,{message:d.message,status:d.status,code:d.code}),d;let y=-1;const w=v(`${(b=(T=d.data)==null?void 0:T[0])==null?void 0:b.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return(g=d.data)==null||g.forEach(m=>{for(const Y in m)!isNaN(m[Y])&&Number(m[Y])!==1/0&&(m[Y]=Number(m[Y]));const l=v(`${m.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00"),f=m.status,{labelCn:c,labelEn:k}=this.parseStatus(f),S={mmsi:m.mmsi,imo:n==null?void 0:n.imo,lat:m.lat,lng:m.lon,sog:m.sog,cog:m.cog,hdg:m.hdg,draught:m.draught,status:f,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(m.eta)?v(`${m.eta} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00").utc().format():void 0,destination:m.dest,positionTime:l.unix(),labelCn:c,labelEn:k,method:"trajectory",vendor:"myVessel",utc:l.utc().format()},F=Math.floor(l.diff(w,"minute",!0)/(o||1));F!==y&&(y=F,t.push(S))}),t}}class bt extends G{constructor(e){super();U(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 A.post(i,n).json();p==null||p.info("[%s] fetch realtime position from: %s - %j",a.requestId,i,n);const t=o==null?void 0:o.list;if(!t)return p==null||p.warn("[%s] fetch realtime position failed: %j",a.requestId,i,o),o;for(const w in t)!isNaN(t[w])&&Number(t[w])!==1/0&&(t[w]=Number(t[w]));t.status=t.sp>3?0:1;const r=t.status,{labelCn:u,labelEn:h}=this.parseStatus(r),d=v(`${t.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return{mmsi:t.m,name:t.n,imo:t.imonumber,callSign:t.callsign,lat:Math.round(t.la/60*1e5)/1e5,lng:Math.round(t.lo/60*1e5)/1e5,length:t.l,width:t.w,draught:t.draught,sog:t.sp,cog:t.co,hdg:t.h,rot:isNaN(t.rot)?0:t.rot,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(t.eta)?v.utc(t.eta).format():void 0,destination:t.destination,vesselType:t.type,dwt:t.dwt,build:t.buildyear,flag:t.fn,positionTime:d.unix(),utc:d.utc().format(),status:r,labelCn:u,labelEn:h,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 A.post(i,n).json();p==null||p.info("[%s] fetch vessel props from: %s - %j",a.requestId,i,n),o instanceof Array&&(o=o[0]);for(const r in o)!isNaN(o[r])&&Number(o[r])!==1/0&&(o[r]=Number(o[r]));const t={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 A.post(i,n).json(),p==null||p.info("[%s] search vessel dead weight from: %s - %j",a.requestId,i,n),o instanceof Array&&(o=o[0]),o&&(t.deadweight=Number(o.dwt)),t}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 A.post(i,n).json();p==null||p.info("[%s] suggest vessel props from: %s - %j",a.requestId,i,n);const t=[];for(const r of o)t.push({mmsi:!r.mmsi||isNaN(r.mmsi)?null:Number(r.mmsi),name:r.name,callSign:r.callsign,imo:!r.imo||isNaN(r.imo)?null:Number(r.imo),score:r._score});return t.sort((r,u)=>u.score-r.score),t}async trajectory(e,a,i,n,o=!0,t={}){var m,l,f;const r=await this.realTimePosition(e,t);let u=v(a);const h=v(i),d=v();if(o){let c=h.diff(u,"d",!0);c<0?u=h.clone().subtract(40,"d"):c<30?u.subtract(10,"d"):c<60?u.subtract(5,"d"):u=h.clone().subtract(80,"d"),c=d.diff(h,"d",!0),h.add(c>10?240:c*24,"h")}const y={searchParams:{endtime:h.utcOffset("+8:00").format("YYYY-MM-DD HH:mm:ss"),starttime:u.utcOffset("+8:00").format("YYYY-MM-DD HH:mm:ss"),mmsi:e,usertoken:this.token}},w="https://api.hifleet.com/position/trajectory/nocompressed/withstatic/token",M=await A.get(w,y).json();p==null||p.info("[%s] fetch trajectory from: %s - %j",t.requestId,w,y);let I;M&&(I=((l=(m=M.ships)==null?void 0:m.offors)==null?void 0:l.ship)||[],I.length||p==null||p.warn("[%s] fetch trajectory failed: %j",t.requestId,M));const T=[];let b=-1;const g=v(`${(f=I==null?void 0:I[0])==null?void 0:f.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");for(const c of I){for(const R in c)!isNaN(c[R])&&Number(c[R])!==1/0&&(c[R]=Number(c[R]));const k=v(`${c.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");c.status=c.sp>4?0:1;const{labelEn:S,labelCn:F}=this.parseStatus(c.status),Y={mmsi:c.m,name:c.n,imo:r==null?void 0:r.imo,lat:c.la,lng:c.lo,draught:c.draught,sog:c.sp,cog:c.co,hdg:c.hdg,positionTime:k.unix(),utc:k.utc().format(),status:c.status,labelCn:F,labelEn:S,method:"trajectory",vendor:"hifleet"},N=Math.floor(k.diff(g,"minute",!0)/(n||1));N!==b&&(b=N,T.push(Y))}return T}}class gt extends G{constructor(e){super();U(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 A.get(n,i).json();if(p==null||p.info("[%s] fetch realtime position from: %s - %j",a.requestId,n,i),(o==null?void 0:o.status)!==0)return o;const t=o.data[0];for(const y in t)!isNaN(t[y])&&Number(t[y])!==1/0&&(t[y]=Number(t[y]));const{labelCn:r,labelEn:u}=await this.parseStatus(t.navistat),h=v.unix(t.lasttime);return{mmsi:t.ShipID,name:t.name,imo:t.imo,callSign:t.callsign,lat:Math.round(t.lat/1e6*1e5)/1e5,lng:Math.round(t.lon/1e6*1e5)/1e5,length:Math.round(t.length/10*100)/100,width:Math.round(t.width/10*100)/100,draught:Math.round(t.draught/1e3*100)/100,sog:Math.round(t.sog*3600/1e3/1852*100)/100,cog:Math.round(t.cog/100*100)/100,hdg:Math.round(t.hdg/100*100)/100,rot:Math.round(t.rot/100*100)/100,positionTime:t.lasttime,utc:h.utc().format(),status:t.navistat,labelEn:u,labelCn:r,method:"position",vendor:"shipxy"}}async trajectory(e,a,i,n,o=!0,t={}){var g;const r=await this.realTimePosition(e,t),u=v(a),h=v(i),d="https://api.shipxy.com/apicall/GetShipTrack",y={searchParams:{id:e,k:this.token,enc:1,cut:0,btm:u.unix(),etm:h.unix()}},w=await A.get(d,y).json();if(p==null||p.info("[%s] fetch trajectory from: %s - %j",t.requestId,d,y),(w==null?void 0:w.status)!==0)return w;const M=w==null?void 0:w.points,I=[],T=v.unix((g=M[0])==null?void 0:g.utc);let b=-1;for(const m of M){const l=v.unix(m.utc),f={imo:r==null?void 0:r.imo,mmsi:e,sog:Math.round(m.sog*3600/1e3/1852*100)/100,cog:Math.round(m.cog/100*100)/100,lat:Math.round(m.lat/1e6*1e5)/1e5,lng:Math.round(m.lon/1e6*1e5)/1e5,positionTime:l.unix(),utc:l.utc().format(),method:"trajectory",vendor:"shipxy"},c=Math.floor(l.diff(T,"minute",!0)/(n||1));c!==b&&(b=c,I.push(f))}return I}}class vt extends G{constructor(e){super();U(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 A.post(n,i).json();return p==null||p.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 A.post(n,i).json();if(p==null||p.info("[%s] fetch ship info from: %s - %j",a.requestId,n,i),o.code!=="0")return o;const t=o.data;let r=t.imo;return e==="407170"&&(r="9198379",p==null||p.warn("[%s] ship(%s) imo error: %s, should be %s",a.requestId,e,t.imo,r)),{mmsi:t.mmsi,name:t.shipnameEn,imo:r,callSign:t.callSign,length:t.length,width:t.breadth,draught:(t.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}},t="https://api3.myships.com/sp/ships/position/latest",r=await A.post(t,o).json();p==null||p.info("[%s] fetch realtime position from: %s - %j",a.requestId,t,o);const u=r.data[0];for(const M in u)!isNaN(u[M])&&Number(u[M])!==1/0&&(u[M]=Number(u[M]));const{labelCn:h,labelEn:d}=await this.parseStatus(u.aisNavStatus),y=v.unix(u.posTime);return{...n,mmsi:e,lat:Math.round(u.lat/1e4/60*1e5)/1e5,lng:Math.round(u.lon/1e4/60*1e5)/1e5,sog:Math.round(u.sog/10*100)/100,cog:Math.round(u.cog/10*100)/100,hdg:Math.round(u.heading*100)/100,rot:Math.round(u.rot*100)/100,positionTime:u.posTime,utc:y.utc().format(),status:u.aisNavStatus,labelEn:d,labelCn:h,method:"position",vendor:"myship"}}async trajectory(e,a,i,n,o=!0,t={}){const r=v(a),u=v(i),h=await this.getShipId(e),d=await this.getShipInfo(h),y=[];for(;u.diff(r,"day",!0)>30;)await this.trajectoryIn30Day(h,r.unix(),r.add(30,"day").unix(),d,e,n,y);return await this.trajectoryIn30Day(h,r.unix(),u.unix(),d,e,n,y),y}async trajectoryIn30Day(e,a,i,n,o,t,r,u={}){var T;const h={headers:{appKey:this.token},json:{shipId:e,startTime:a,endTime:i}},d="https://api3.myships.com/sp/ships/position/history",y=await A.post(d,h).json();if(p==null||p.info("[%s] fetch trajectory from: %s - %j",u.requestId,d,h),y.code!=="0")return p==null||p.warn("[%s] invoke myship trajectory failed: %j",u.requestId,y),y;const w=y.data;for(const b in w)!isNaN(w[b])&&Number(w[b])!==1/0&&(w[b]=Number(w[b]));const M=v.unix((T=w[0])==null?void 0:T.posTime);let I=-1;for(const b of w){const g=v.unix(b.posTime),m={imo:n==null?void 0:n.imo,mmsi:o,lat:Math.round(b.lat/1e4/60*1e5)/1e5,lng:Math.round(b.lon/1e4/60*1e5)/1e5,sog:Math.round(b.sog/10*100)/100,cog:Math.round(b.cog/10*100)/100,hdg:Math.round(b.heading*100)/100,rot:Math.round(b.rot*100)/100,positionTime:g.unix(),utc:g.utc().format(),method:"trajectory",vendor:"myship"},l=Math.floor(g.diff(M,"minute",!0)/(t||1));l!==I&&(I=l,r.push(m))}return r}}let _;try{_=K.getLogger("vessel")}catch{}finally{}var lt=(D=>(D.NOTICE="NOTICE",D.WARN="WARN",D.HEAVY="HEAVY",D.SEVERE="SEVERE",D.ERROR="ERROR",D.FATAL="FATAL",D))(lt||{});class ht{parsePrinciple(s,e={}){var t,r,u;_==null||_.debug("[%s] parse rule: %s",e.requestId,s);const a=new RegExp("(?<=\\[)(.+)(?=])","g"),i=s.match(a)?(t=s.match(a))==null?void 0:t[0]:void 0,n=i==null?void 0:i.split(";");if(!n)return;const o={};for(let h=0;h<(n==null?void 0:n.length);h++){const d=(u=(r=n[h].match(a))==null?void 0:r[0])==null?void 0:u.split("],");if(h===0&&!d)o.scope=n[0];else if(d)for(let y=0,w=d.length;y<w;y++){const M=this.parseRule(d[y]);M&&(o[M.level]?M.key?o[M.level][M==null?void 0:M.key]=M:o[M.level]=M:M.key?o[M.level]={[M==null?void 0:M.key]:M}:o[M.level]=M)}}return o}parseRule(s,e={}){var o;_==null||_.debug("[%s] parse rule: %s",e.requestId,s),s=s.startsWith("[")?s:`[${s}`,s=s.endsWith("]")?s:`${s}]`;const a=new RegExp("(?<=\\[)(.+?)(?=])","g"),i=(o=s==null?void 0:s.match(a))==null?void 0:o[0],n=i==null?void 0:i.split(",");if(n){let t=n[3]==="Number.MAX_VALUE"?100:Number(n[3]);return t=isNaN(t)?1:t,{operator:n[0],number:Number.isNaN(Number(n[1]))?n[1]:Number(n[1]),level:n[2],time:t,key:n[4]}}}checkWeather(s,e,a={}){var M,I,T,b,g,m,l,f,c,k,S,F,Y,N,R;let i=0,n=0,o=0,t=0;const r=Math.round(((I=(M=e==null?void 0:e.SEVERE)==null?void 0:M.sigWave)==null?void 0:I.number)*1.6*100)/100,u=(b=(T=e==null?void 0:e.SEVERE)==null?void 0:T.sigWave)==null?void 0:b.number,h=(m=(g=e==null?void 0:e.HEAVY)==null?void 0:g.sigWave)==null?void 0:m.number,d=Math.round((((f=(l=e==null?void 0:e.SEVERE)==null?void 0:l.wind)==null?void 0:f.number)+2)*100)/100,y=(k=(c=e==null?void 0:e.SEVERE)==null?void 0:c.wind)==null?void 0:k.number,w=(F=(S=e==null?void 0:e.HEAVY)==null?void 0:S.wind)==null?void 0:F.number;for(let E=0;E<(s==null?void 0:s.length);E++){const H=s[E],W=(N=(Y=H==null?void 0:H.meteo)==null?void 0:Y.wave)==null?void 0:N.sig,V=(R=H==null?void 0:H.meteo)==null?void 0:R.wind,J=E?v(H.eta).diff(v(s[E-1].eta),"hour",!0):0;t=J>t?J:t,_==null||_.debug("[%s] check sig.wave: %j",a.requestId,{...W,dgThd4Wv:r,svThd4Wv:u,hvThd4Wv:h}),(W==null?void 0:W.height)>=r?H.isDangerous=!0:(W==null?void 0:W.height)>=u?H.isSevere=!0:(W==null?void 0:W.height)>=h&&(H.isHeavy=!0),_==null||_.debug("[%s] check wind: %j",a.requestId,{...V,dgThd4Wd:d,svThd4Wd:y,hvThd4Wd:w}),(V==null?void 0:V.scale)>=d?(H.isDangerous=!0,delete H.isSevere,delete H.isHeavy):(V==null?void 0:V.scale)>y?(H.isDangerous||(H.isSevere=!0),delete H.isHeavy):(V==null?void 0:V.scale)===w&&!H.isDangerous&&!H.isSevere&&(H.isHeavy=!0),i+=H.isDangerous?J:0,n+=H.isSevere?J:0,o+=H.isHeavy?J:0}return i=Math.round(i*100)/100,n=Math.round(n*100)/100,o=Math.round(o*100)/100,t=Math.round(t),{sample:s,dangerous:i,severe:n,heavy:o,step:t<3?3:t,wind:{dgThd4Wd:d,svThd4Wd:y,hvThd4Wd:w},sig:{dgThd4Wv:r,svThd4Wv:u,hvThd4Wv:h}}}}const wt=new ht;let j;try{j=K.getLogger("vessel")}catch{}finally{}const It=new pt.MeteoHelper2("",!0);var ft=(D=>(D.common="common",D.container="container",D.tugs="tugs",D))(ft||{}),mt=(D=>(D.Ballast="Ballast",D.Laden="Laden",D))(mt||{}),yt=(D=>(D.Cp="CP",D.Perf="Basis",D.Instruct="Other",D))(yt||{});class B{static blockCoefficient(s,e,a,i){let n=Math.round(s/(e*a*i)*100)/100;n=n<.55?.55:n>.85?.85:n;const o=[.55,.6,.65,.7,.75,.8,.85],t=o.map(r=>Math.abs(r-n));return o[t.indexOf(Math.min(...t))]}static froudeNumber(s,e,a=9.8){let i=Math.round(Math.sqrt(s*s/(a*e))*100)/100;return i=i<.05?.05:i>.3?.3:i,i}static amendFactor(s,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]}[s];return a==="Laden"&&(o=i[s]),o[0]+o[1]*e+o[2]*Math.pow(e,2)}static directionFactor(s,e=0){let a;return s>30&&s<=60?a=(1.7-.03*Math.pow(e-4,2))/2:s>60&&s<=150?a=(.9-.06*Math.pow(e-6,2))/2:s>150&&s<=180?a=(.4-.03*Math.pow(e-8,2))/2:a=1,Math.round(a*1e5)/1e5}static vesselTagFactor(s,e,a,i){let n;return a==="container"?n=.7*i/2+Math.pow(i,3)/(22*Math.pow(s,2/3)):e==="Ballast"?n=.7*i/2+Math.pow(i,3)/(2.7*Math.pow(s,2/3)):n=.5*i/2+Math.pow(i,3)/(2.7*Math.pow(s,2/3)),n}static waveHeightFactor(s,e){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 e>30&&e<=60?a=-.6:e>60&&e<=90?a=-.4:e>90&&e<=120?a=s<3?.4:-.3:e>120&&e<=150?a=s<3?.6:-.5:e>150&&e<=180?a=s<3?.7:-.6:a=-.7,Math.round(a*(.144*Math.pow(s,2)+.278*s)*1e4)/1e4}static assembleProperties(s,e,a,i){var y;const n=s.lbp??s.length??s.lengthOverall??198.9642,o=s.draught??8,t=s.breadthMoulded??s.breadth??s.breadthExtreme??32.4572,r=s.deadweight??67035.7773,u=((y=s==null?void 0:s.type)==null?void 0:y.toLowerCase())||"common";return{tag:u.indexOf("container")>-1?"container":u.indexOf("tugs")>-1?"tugs":"common",lbp:n,loadCondition:e,draught:o,breadthMoulded:t,displacement:Math.round((r/1.025+o*t*n*.7)*1e4)/1e4,speed:Math.round((a??14.1382)*1852/3600*1e4)/1e4,bearing:i||90}}static async speedLoseAt(s,e,a,i="",n=2,o=!0,t=!1,r={}){let u;if(e.velocity&&t&&(s.speed=L.LngLatHelper.roundPrecision(e.velocity*1852/3600,6)),o){let h;try{i=(i==null?void 0:i.toUpperCase())==="CMEMS"?"ECMWF":i,i=(i==null?void 0:i.toUpperCase())==="METEO2"?"best_match":i;const{weatherModels:M,marineModels:I}=await it.Meteo2Assist.autoPickMeteoModel(i),T=await It.spotForecast(e.lat,e.lng,a.utc().format(),!1,!1,!0,{...r,pastDays:1,forecastDays:1,weatherModels:M,marineModels:I}),[b]=it.Meteo2Assist.pickHourly(T,a);h=it.Meteo2Assist.toLegacy(b)}catch(M){j.warn("[%s] meteo2 spot(%j) forecast failed: %s",r.requestId,{...e,eta:a.utc().format(),source:i},M)}const d=B.currentFactor(s.bearing,h==null?void 0:h.current,n),y=B.weatherFactor(s,h,d),w=Math.round((s.speed*1.943844+y+d)*100)/100;u={meteo:{...h},wxFactor:y,cFactor:d,speed:e.velocity&&t?e.velocity:w<0?1:w,eta:a.utc().format(),etd:a.utc().format()}}else u={wxFactor:0,cFactor:0,speed:e.velocity&&t?e.velocity:Math.round(s.speed*1.943844*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,{...u,...e}}static async speedLoseInHoursStep(s,e,a,i,n,o,t="",r=!0,u=!1,h={}){e.utc();const d=e.clone().add(14,"days"),y=[],w=[],M=[];let I=0,T=0,b,g;for(let m=0;m<o.length-1;m++){let l=o[m];l.distanceFromStart=Math.round((n+T)*1e3)/1e3;const f=o[m+1];if(s.bearing=L.LaneHelper.calculateBearing(l,f,!f.gcToPrevious),l.bearing=s.bearing,l.suspend&&u){l.eta=l.eta||e.utc().format(),l.elapsed=l.elapsed??0;const S=l.suspend-l.elapsed;if(i-I>S)i=i-I-S,e.add(S,"hour"),l.elapsed=l.suspend;else{const F=i-I;l.elapsed+=F,e.add(F,"hour"),i=0}if(j==null||j.info(`[%s] suspend ${l.elapsed} hours at %j, and remain ${i} hours need to go...`,h.requestId,l),i===0)return l.distanceFromPrevious=T,{etd:e,from:g||l,to:l,next:o.filter(F=>F),wps:y,days:w,all:M}}else l.suspend=0;r=e.isAfter(d)?!1:r,l=await B.speedLoseAt(s,l,e,t,0,r,u,h),M.push(l),g=g||l,l.important&&y.push(l),e.isSameOrAfter(a)&&(w.push(l),a.add(24,"hour"));const c=L.LaneHelper.calculateDistance(l,f,!f.gcToPrevious);let k=Math.round(c/g.speed*1e5)/1e5;if(I+k<i){if(I+=k,e.add(k,"hour"),delete o[m],j==null||j.debug(`[%s] go to %j from %j with ${c}nm, and cost ${k} hours`,h.requestId,{lat:f.lat,lng:f.lng},{lat:g.lat,lng:g.lng,etd:g.etd}),T+=c,o.filter(S=>S).length<=1){b=f,b.eta=e.utc().format(),b.distanceFromPrevious=c,b.distanceFromStart=Math.round((n+T)*1e4)/1e4,y.push(b),M.push(b),delete o[m+1];break}}else{k=i-I,e.add(k,"hour");const S=L.LngLatHelper.roundPrecision(g.speed*k,5);b=L.LaneHelper.calculateCoordinate(l,s.bearing,S,"nauticalmiles",!f.gcToPrevious),b.eta=e.utc().format(),o[m]=b,j==null||j.debug(`[%s] go to %j from %j with ${S}nm, and cost ${k} hours`,h.requestId,{lat:b.lat,lng:b.lng},{lat:l.lat,lng:l.lng,etd:l.etd}),T+=S,b.distanceFromPrevious=Math.round(T*1e4)/1e4,b.distanceFromStart=Math.round((n+T)*1e4)/1e4;break}}return{etd:e,from:g,to:b,next:o.filter(m=>m),wps:y,days:w,all:M}}static currentFactor(s,e,a=0){const i=(s-(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(s,e,a=0){var w,M,I,T,b,g,m;j==null||j.debug("calculate weather factor via: %j",{...s,...e});const i=B.blockCoefficient(s.displacement,s.lbp,s.breadthMoulded,s.draught),n=L.LngLatHelper.roundPrecision(a*1852/3600,6),o=B.froudeNumber(s.speed-n,s.lbp),t=B.amendFactor(i,o,s.loadCondition);let r=Math.abs(s.bearing%360-(((w=e==null?void 0:e.wind)==null?void 0:w.degree)%360||0));r=r>180?360-r:r;const u=B.directionFactor(r,(M=e==null?void 0:e.wind)==null?void 0:M.scale),h=B.vesselTagFactor(s.displacement,s.loadCondition,s.tag,(I=e==null?void 0:e.wind)==null?void 0:I.kts);let d=u*t*h/100*(s.speed-n);d=Math.round(d*1.943844*1e4)/1e4*-1,s.tag==="tugs"&&Math.abs(d)>1&&(d=d/(Math.abs(Math.round(d))+1)),j==null||j.debug("wind wx factor = %d",d),r=Math.abs(s.bearing%360-(((b=(T=e==null?void 0:e.wave)==null?void 0:T.sig)==null?void 0:b.degree)%360||0)),r=r>180?360-r:r;const y=B.waveHeightFactor(((m=(g=e==null?void 0:e.wave)==null?void 0:g.sig)==null?void 0:m.height)??1,r);return j==null||j.debug("wave wx factor = %d",y),d=Math.abs(d)>Math.abs(y)?d:d*.3+y*.7,j==null||j.debug("weather factor = %d",d),d=Math.abs(d)>3?3*(Math.abs(d)/d)+Math.abs(d)/d*(Math.abs(d)-2)*.1:d,Math.round((d||0)*100)/100}static async analyseInstant(s,e,a,i,n,o="",t=0,r=!0,u=!1,h={}){var X,Q,Z,$,tt,et,st;const d=v().valueOf();s.lng=L.LngLatHelper.convertToStdLng(s.lng);const{route:y,waypoints:w}=n.points,M=L.LaneHelper.calculateSubRoute(s,y);if(((X=M[0])==null?void 0:X.length)<=1)return;const{v0:I,label:T}=s.sog?{v0:s.sog,label:s.label||"Other"}:{v0:i.speed,label:"CP"},b=B.assembleProperties(a,i.loadCondition,I,0),g=w.length?L.LaneHelper.calculateSubWaypoints(s,w):[];g.forEach(x=>x.important=!0);const m={from:{...s},route:M,waypoints:g,v0:I,label:T},l={hours:[],days:[],wps:[],all:[]};t||(L.LaneHelper.calculateRouteDistance(M)/i.speed<=72?t=3:t=6);let f=L.LaneHelper.simplifyRouteToCoordinates(M,g,0),c=0,k=0,S=0,F=0;e=v(e).utc();const Y=e.clone();for(;f.length>0;){const x=t-e.hour()%t,z=Math.ceil(e.clone().add(x,"h").set({minute:0,second:0,millisecond:0}).diff(e,"h",!0)*1e4)/1e4,C=await B.speedLoseInHoursStep(b,e,Y,z,c,f,o,r,u,h);if(l.all.push(...C.all),(Q=C.from)!=null&&Q.speed&&(l.hours.push(C.from),l.wps.push(...C.wps),l.days.push(...C.days)),f=C==null?void 0:C.next,!f.length){const O=await B.speedLoseAt(b,C.to,v(C.to.eta),o,0,r,u,h);O.bearing=b.bearing,l.hours.push(O),l.all.push(O)}c+=Math.round((((Z=C==null?void 0:C.to)==null?void 0:Z.distanceFromPrevious)??0)*1e4)/1e4}const N=l.hours;for(let x=0;x<N.length-1;x++){const z=v(N[x+1].eta).diff(N[x].etd,"hour",!0)||1;k+=(N[x].wxFactor||0)*z,S+=(N[x].cFactor||0)*z,F+=z}const R=N.reduce((x,z)=>x+(z.suspend||0),0);($=l.wps)==null||$.forEach((x,z)=>{x.positionTime=v.utc(x.etd||x.eta).unix();const C=l.wps[z-1];if(C){const O=x.distanceFromStart-C.distanceFromStart,q=v(x.eta||x.etd).diff(v(C.etd||C.eta),"h",!0);x.avgSpd=Math.round(O/q*100)/100,C.bearing=L.LaneHelper.calculateBearing(C,x)}}),l.wps=(tt=l.wps)==null?void 0:tt.reduce((x,z)=>(x.some(C=>Math.round(C.positionTime/60)===Math.round(z.positionTime/60))||x.push(z),x),[]),l.all=(et=l.all)==null?void 0:et.reduce((x,z)=>(z.positionTime=v.utc(z.etd||z.eta).unix(),x.some(C=>Math.round(C.positionTime/60)===Math.round(z.positionTime/60))||x.push(z),x),[]),m.sample=l;const E=l.hours.at(0),H=l.hours.at(-1);m.distance=Math.round(H.distanceFromStart*1e3)/1e3,m.etd=v(E.eta).utc().format(),m.eta=v(H.eta).utc().format(),m.wxFactor=Math.round(k/F*1e3)/1e3,m.cFactor=Math.round(S/F*1e3)/1e3,m.avgSpeed=Math.round(H.distanceFromStart/F*1e3)/1e3,m.totalHrs=Math.round(F*1e3)/1e3,m.suspend=Math.round(R*1e3)/1e3;const W=L.LngLatHelper.roundPrecision(i.dgo/24*R,3),{distanceInECA:V,hoursInECA:J,totalDgoConsInECA:rt,eca:at}=await this.calculateECA(m,i,h),nt=L.LngLatHelper.roundPrecision(i.fo/24*(F-J),3),ct=L.LngLatHelper.roundPrecision(i.dgo/24*F+W,3);m.extend={eca:at,distanceInECA:V,hoursInECA:J,totalDgoConsInECA:rt,totalDgoConsInSuspend:W},m.totalFoCons=nt<0?0:nt,m.totalDgoCons=ct;const ot=v().valueOf()-d,ut=((st=l==null?void 0:l.hours)==null?void 0:st.length)||1;return j==null||j.info("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms",h==null?void 0:h.requestId,ot,ut,Math.round(ot/ut*1e3)/1e3),m}static async analyseInstantWithThreshed(s,e,a,i,n,o,t,r="",u=3,h=!0,d=!1,y={}){var Z,$,tt,et,st,x,z;const w=v().valueOf();s.lng=L.LngLatHelper.convertToStdLng(s.lng);const{v0:M,label:I}=s.sog?{v0:s.sog,label:s.label||"Other"}:{v0:n.speed,label:"CP"},T=B.assembleProperties(i,n.loadCondition,M,0),b=L.LaneHelper.calculateSubRoute(s,o);if(((Z=b[0])==null?void 0:Z.length)<=1)return;const g=t.length?L.LaneHelper.calculateSubWaypoints(s,t):[];g.forEach(C=>C.important=!0);let m=L.LaneHelper.simplifyRouteToCoordinates(b,g,0),l=0,f=0,c=0,k=0;const S={hours:[],wps:[],days:[],all:[]};e=v(e).utc();const F=e.clone();for(;m.length>0;){const C=u-e.hour()%u;let O=Math.ceil(e.clone().add(C,"h").set({minute:0,second:0,millisecond:0}).diff(e,"h",!0)*1e4)/1e4;O=e.clone().add(O,"h").isSameOrAfter(a)?a.diff(e,"h",!0)*1e4/1e4:O;const q=await B.speedLoseInHoursStep(T,e,F,O,l,m,r,h,d,y);if(S.all.push(...q.all),($=q.from)!=null&&$.speed&&(S.hours.push(q.from),q!=null&&q.wps&&S.wps.push(...q.wps),S.days.push(...q.days)),m=q==null?void 0:q.next,m.length||S.hours.push(q==null?void 0:q.to),l+=Math.round((((tt=q==null?void 0:q.to)==null?void 0:tt.distanceFromPrevious)??0)*1e4)/1e4,!O)break}S.wps=(et=S.wps)==null?void 0:et.reduce((C,O)=>(C.some(q=>Math.round(v(q.etd).unix()/60)===Math.round(v(O.etd).unix()/60))||C.push(O),C),[]),S.all=(st=S.all)==null?void 0:st.reduce((C,O)=>(O.positionTime=v.utc(O.etd||O.eta).unix(),C.some(q=>Math.round(v(q.etd).unix()/60)===Math.round(v(O.etd).unix()/60))||C.push(O),C),[]),(x=S.wps)==null||x.forEach((C,O)=>{const q=S.wps[O-1];if(q){const kt=C.distanceFromStart-q.distanceFromStart,St=v(C.eta||C.etd).diff(v(q.etd||q.eta),"h",!0);C.avgSpd=Math.round(kt/St*100)/100,q.bearing=L.LaneHelper.calculateBearing(q,C)}});const Y=S.hours;for(let C=0;C<Y.length-1;C++){const O=v(Y[C+1].eta).diff(Y[C].etd,"hour",!0);f+=Y[C].wxFactor*O,c+=Y[C].cFactor*O,k+=O}const N=Y.reduce((C,O)=>C+(O.suspend||0),0),R=S.hours.at(0),E=S.hours.at(-1),H=await L.LaneHelper.calculateRangeRoute(R,E,b),W=await L.LaneHelper.calculateRangeWaypoints(R,E,b,g),V={sample:S,distance:Math.round(((E==null?void 0:E.distanceFromStart)||0)*1e4)/1e4,etd:v(R.eta).utc().format(),eta:v(E==null?void 0:E.eta).utc().format(),wxFactor:Math.round(f/k*1e3)/1e3,cFactor:Math.round(c/k*1e3)/1e3,avgSpeed:Math.round(((E==null?void 0:E.distanceFromStart)||0)/k*1e3)/1e3,totalHrs:Math.round(k*1e3)/1e3,suspend:Math.round(N*1e3)/1e3,from:R,to:E,route:H,waypoints:W,v0:M,label:I},J=L.LngLatHelper.roundPrecision(n.dgo/24*N,3),{distanceInECA:rt,hoursInECA:at,totalDgoConsInECA:nt,eca:ct}=await this.calculateECA(V,n,y),dt=L.LngLatHelper.roundPrecision(n.fo/24*(k-at),3),ot=L.LngLatHelper.roundPrecision(n.dgo/24*k+J,3);V.extend={eca:ct,distanceInECA:rt,hoursInECA:at,totalDgoConsInECA:nt,totalDgoConsInSuspend:J},V.totalDgoCons=ot,V.totalFoCons=dt<0?0:dt;const X=v().valueOf()-w,Q=((z=S==null?void 0:S.hours)==null?void 0:z.length)||1;return j==null||j.debug("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms",y==null?void 0:y.requestId,X,Q,Math.round(X/Q*1e3)/1e3),V}static async analyseCost(s,e,a,i,n={}){var b,g;const o=v().valueOf(),t=[];s.speedStep=s.speedStep||3,s.alterStep=s.alterStep??1;const r=L.LaneHelper.calculateRouteDistance(i.route);let u=0;a.forEach(m=>{const l=Math.ceil(r/m.speed/24);u=u<l?l:u}),u=u*1.3;const h=v.utc(s.etd).add(u??14,"day");let d=1;for(const m of a){const l=JSON.parse(JSON.stringify(i.route)),f=JSON.parse(JSON.stringify(i.waypoints)),c=await B.analyseInstantWithThreshed({lat:s.lat,lng:s.lng},s.etd,h,e,m,l,f,s.meteoVendor,s.speedStep,s.useMeteo,s.useRouteParam,n);c&&(await B.calculateCost(c,m,s,n),t.push(c),j==null||j.info("[%s][L%d-%d] analyse from %s to %s cost: %j",n.requestId,1,d,s.etd,h.format(),{cost:c.cost.total,hire:c.cost.hire,bunker:c.cost.bunker,distance:c.distance,hours:c.totalHrs,cp:`${m.speed}/${m.fo}/${m.dgo}`})),d++}t.sort((m,l)=>m.cost.total-l.cost.total);const y=t.at(0),w=t.at(1),M=[];if(M.push({combined:!1,speeds:[y],cost:(b=y.cost)==null?void 0:b.total}),w){const m=y.cost.cp,l=w.cost.cp,f=v(y.eta),c=v(y.etd),k=f.diff(c,"days",!0);let S=Math.ceil(k/2);S=S>7?7:S<s.alterStep?s.alterStep:S;let F=2,Y={combined:!1,speeds:[w],cost:(g=w.cost)==null?void 0:g.total},N;for(;S>=s.alterStep;){const R=await B.combinedAnalyse(s,e,h,[m,l],i,S,{...n,level:F});if(Y.cost>R.cost?N?(N==null?void 0:N.cost)>R.cost&&(N=R):(N=Y,Y=R):(!N||(N==null?void 0:N.cost)>R.cost)&&(N=R),S<=s.alterStep)break;S=Math.ceil(S/2),F+=1}M.push(Y),N&&M.push(N)}const T=v().valueOf()-o;return j==null||j.info("[%s] analyse elapsed: %d ms",n==null?void 0:n.requestId,T),M.sort((m,l)=>m.cost-l.cost)}static async combinedAnalyse(s,e,a,i,n,o,t={}){t.counter=1,j==null||j.info("[%s][L%d] analyse with alternate cp in every %d days",t.requestId,t.level,o);const r=await B.alternateAnalyse(s,e,a,i,0,n,o,t),u=r.reduce((l,f)=>l+f.cost.total,0),h=r.reduce((l,f)=>l+f.cost.hire,0),d=r.reduce((l,f)=>l+f.cost.bunker,0),y=r.reduce((l,f)=>l+f.distance,0),w=r.reduce((l,f)=>l+f.totalHrs,0);j==null||j.info("[%s][L%d] cost with cpa/cpb turn: %j",t.requestId,t.level,{cost:u,hire:h,bunker:d,distance:y,hours:w});const M=await B.alternateAnalyse(s,e,a,i,1,n,o,t),I=M.reduce((l,f)=>l+f.cost.total,0),T=M.reduce((l,f)=>l+f.cost.hire,0),b=M.reduce((l,f)=>l+f.cost.bunker,0),g=M.reduce((l,f)=>l+f.distance,0),m=M.reduce((l,f)=>l+f.totalHrs,0);return j==null||j.info("[%s][L%d] cost with cpb/cpa turn: %j",t.requestId,t.level,{cost:I,hire:T,bunker:b,distance:g,hours:m}),u<I?{combined:!0,cost:Math.round(u*1e3)/1e3,speeds:r,step:o}:{combined:!0,cost:Math.round(I*1e3)/1e3,speeds:M,step:o}}static async alternateAnalyse(s,e,a,i,n,o,t,r={}){var y,w;let u=v.utc(s.etd);const h={lat:s.lat,lng:s.lng},d=[];for(;u.isBefore(a);){const M=u.clone().utc().add(t,"day"),I=JSON.parse(JSON.stringify(o.route)),T=JSON.parse(JSON.stringify(o.waypoints)),b=i[n],g=await B.analyseInstantWithThreshed(h,u.utc().format(),M,e,b,I,T,s.meteoVendor,s.speedStep,s.useMeteo,s.useRouteParam,r);g&&(await B.calculateCost(g,b,s,r),j==null||j.info("[%s][L%d-%d] analyse from %s to %s cost: %j",r.requestId,r.level,r.counter,u.utc().format(),M.utc().format(),{cost:g.cost.total,hire:g.cost.hire,bunker:g.cost.bunker,distance:g.distance,hours:g.totalHrs,cp:`${b.speed}/${b.fo}/${b.dgo}`})),r.counter=r.counter+1;const m=(w=(y=g==null?void 0:g.sample)==null?void 0:y.hours)==null?void 0:w.at(-1);if(m)h.lat=m.lat,h.lng=m.lng,u=v(m.eta),d.push(g),n=n?0:1;else break}return d}static async calculateCost(s,e,a,i={}){var n;if(s){const o=(a.addComm||0)>=1?(a.addComm||0)/100:a.addComm||0,t=Math.round((a.dailyHire||0)*(s.suspend||0)/24*1e3)/1e3,r=Math.round(s.totalHrs/24*(a.dailyHire||0)*(1-o)*1e3)/1e3+t,u=Math.round(s.totalFoCons*(a.priceFO||0)*1e3)/1e3,h=Math.round((s.totalDgoCons+(((n=s.extend)==null?void 0:n.totalDgoConsInECA)||0))*(a.priceDGO||0)*1e3)/1e3;s.cost={total:Math.round((r+u+h)*1e3)/1e3,hire:Math.round(r*1e3)/1e3,suspendHire:t,bunker:Math.round((u+h)*1e3)/1e3,cp:e}}return s}static async calculateECA(s,e,a={}){var r,u,h,d;const i=await L.LaneHelper.intersectInECA((s==null?void 0:s.route)||[]);let n=0,o=0,t=0;(u=(r=s==null?void 0:s.sample)==null?void 0:r.wps)==null||u.forEach(y=>{y.positionTime=v.utc(y.etd||y.eta).unix()});for(const y of i){n+=y.distance;const w=await L.LaneHelper.deadReckoningTime((h=y.waypoints)==null?void 0:h.at(0),s.sample.all||s.sample.wps),M=await L.LaneHelper.deadReckoningTime((d=y.waypoints)==null?void 0:d.at(-1),s.sample.all||s.sample.wps);y.in=w,y.out=M,y.totalHrs=L.LngLatHelper.roundPrecision((M.positionTime-w.positionTime)/3600,3),y.totalDgoCons=L.LngLatHelper.roundPrecision(e.fo/24*y.totalHrs,3),o+=y.totalHrs,t+=y.totalDgoCons}return n=L.LngLatHelper.roundPrecision(n,3),o=L.LngLatHelper.roundPrecision(o,3),t=L.LngLatHelper.roundPrecision(t,3),{distanceInECA:n,hoursInECA:o,totalDgoConsInECA:t,eca:i}}static async mergeSpeeds(s,e={}){var m,l;const a={hours:[],wps:[],days:[]},i=s.reduce((f,c)=>f+c.distance,0),n=s.reduce((f,c)=>{var k;return f+(((k=c.extend)==null?void 0:k.distanceInECA)||0)},0),o=s.reduce((f,c)=>f+c.totalHrs,0),t=s.reduce((f,c)=>{var k;return f+(((k=c.extend)==null?void 0:k.hoursInECA)||0)},0),r=s.reduce((f,c)=>{var k;return f+(((k=c.extend)==null?void 0:k.totalDgoConsInECA)||0)},0),u=s.reduce((f,c)=>f+c.wxFactor*c.totalHrs/o,0),h=s.reduce((f,c)=>f+c.cFactor*c.totalHrs/o,0),d=s.reduce((f,c)=>f+c.totalFoCons,0),y=s.reduce((f,c)=>f+c.totalDgoCons,0),w=s.reduce((f,c)=>f+c.cost.total,0),M=s.reduce((f,c)=>f+c.cost.hire,0),I=s.reduce((f,c)=>f+c.cost.bunker,0),T=[],b=[];let g;for(const f of s){b.push(...((m=f.extend)==null?void 0:m.eca)||[]);const c=f.sample.hours,k=f.sample.wps,S=f.sample.days,F=c.at(0);g&&(F.distanceFromPrevious=g.distanceFromPrevious,F.distanceFromStart=g.distanceFromStart,c.forEach((E,H)=>{H&&(E.distanceFromStart=E.distanceFromStart+g.distanceFromStart)}),k.at(0).distanceFromPrevious=g.distanceFromPrevious,k.at(0).distanceFromStart=g.distanceFromStart,k.forEach((E,H)=>{H&&(E.distanceFromStart=E.distanceFromStart+g.distanceFromStart)}),S.at(0).distanceFromPrevious=g.distanceFromPrevious,S.at(0).distanceFromStart=g.distanceFromStart,S.forEach((E,H)=>{H&&(E.distanceFromStart=E.distanceFromStart+g.distanceFromStart)})),F.cp=f.cost.cp;const Y=[f.etd,f.eta],N=T.findIndex(E=>E.id===F.cp.id);N===-1?(F.cp.segment=[Y],T.push(F.cp)):T[N].segment.push(Y),c.forEach(E=>{var W;((W=a.hours)==null?void 0:W.findIndex(V=>V.eta===E.eta))===-1&&a.hours.push(E)}),k.forEach(E=>{var W;((W=a.wps)==null?void 0:W.findIndex(V=>V.eta===E.eta))===-1&&a.wps.push(E)}),S.forEach(E=>{var W;((W=a==null?void 0:a.days)==null?void 0:W.findIndex(V=>V.eta===E.eta))===-1&&a.days.push(E)});const R=(l=a.wps)==null?void 0:l.findIndex(E=>E.eta===F.eta);R===-1?a.wps.push(F):a.wps[R]=F,g=c.at(-1)}return a.wps.sort((f,c)=>{v(f.etd).unix()-v(c.etd).unix()}),a.wps.forEach((f,c)=>{const k=a.wps[c-1];if(k){const S=f.distanceFromStart-(k.distanceFromStart||0),F=v(f.eta||f.etd).diff(v(k.etd||k.eta),"hour",!0),Y=Math.round(S/F*100)/100;f.avgSpd=Y;const N=L.LaneHelper.calculateBearing(k,f);k.bearing=N}}),{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(o*1e3)/1e3,avgSpeed:Math.round(i/o*1e3)/1e3,wxFactor:Math.round(u*1e3)/1e3,cFactor:Math.round(h*1e3)/1e3,totalFoCons:Math.round(d*1e3)/1e3,totalDgoCons:Math.round(y*1e3)/1e3,cost:{total:Math.round(w*1e3)/1e3,hire:Math.round(M*1e3)/1e3,bunker:Math.round(I*1e3)/1e3},extend:{cps:T,eca:b,distanceInECA:Math.round(n*1e3)/1e3,hoursInECA:Math.round(t*1e3)/1e3,totalDgoConsInECA:Math.round(r*1e3)/1e3,speeds:s}}}}P.AISImpl=G,P.AlertHelper=ht,P.AlertLevel=lt,P.HifleetImpl=bt,P.LoadCondition=mt,P.MyShipImpl=vt,P.MyVesselImpl=Mt,P.ShipxyImpl=gt,P.SpeedHelper=B,P.SpeedLabel=yt,P.VesselTag=ft,P.alertHelper=wt,Object.defineProperty(P,Symbol.toStringTag,{value:"Module"})});
1
+ (function(Y,q){typeof exports=="object"&&typeof module<"u"?q(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"],q):(Y=typeof globalThis<"u"?globalThis:Y||self,q(Y["idm-plugin-vessel"]={},Y.got,Y["@log4js-node/log4js-api"],Y.moment,Y["@idm-plugin/geo2"],Y["@idm-plugin/meteo2"],Y["@idm-plugin/meteo"]))})(this,function(Y,q,K,v,L,Mt,rt){"use strict";var Tt=Object.defineProperty;var jt=(Y,q,K)=>q in Y?Tt(Y,q,{enumerable:!0,configurable:!0,writable:!0,value:K}):Y[q]=K;var U=(Y,q,K)=>(jt(Y,typeof q!="symbol"?q+"":q,K),K);let p;try{p=K.getLogger("vessel")}catch{}finally{}class G{parseStatus(s){let e,a;switch(s){case 0:e="在航(主机推动)",a="Underway Using Engine";break;case 1:e="锚泊",a="Anchored";break;case 2:e="失控",a="Not under command";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 bt extends G{constructor(e,a){super();U(this,"clientId");U(this,"clientSecret");U(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 q.post(a,i).json();p==null||p.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:v().utc().format()})}async checkToken(e={}){var a;return(!this.token||v().diff(v(this.token.issuedAt),"seconds")>(((a=this.token)==null?void 0:a.expiresIn)||0)-300)&&await this.authToken(e),this.token}async suggest(e,a={}){var t,r;await this.checkToken(a);const i="https://market.myvessel.cn/sdc/v1/mkt/vessels/fuzzy",n={headers:{Authorization:`${(t=this.token)==null?void 0:t.tokenType} ${(r=this.token)==null?void 0:r.accessToken}`},json:{kw:e,recordNum:a.ps||10}};p==null||p.info("[%s] fetch suggest vessels from: %s - %j",a.requestId,i,n);const o=await q.post(i,n).json();return o.status!==200?(p==null||p.warn("[%s] fetch suggest vessels failed: %j",a.requestId,{message:o.message,status:o.status,code:o.code}),[]):(o.data||[]).map(h=>({mmsi:h.mmsi,name:h.nameEn,nameCn:h.nameCn,imo:Number.isNaN(h.imo)?null:Number(h.imo),callSign:h.callsign,type:h.vesselTypeNameEn,flagName:h.flagCtry,vendor:"myvessel",raw:h}))}async search(e,a={}){var l,h;await this.checkToken(a);const i=/^\d{7}$/.test(e.toString()),n=i?"https://market.myvessel.cn/sdc/v1/mkt/vessels/detail/imo":"https://market.myvessel.cn/sdc/v1/mkt/vessels/detail/mmsi",o=i?{imo:e}:{mmsi:e},t={headers:{Authorization:`${(l=this.token)==null?void 0:l.tokenType} ${(h=this.token)==null?void 0:h.accessToken}`},searchParams:o};p==null||p.info("[%s] fetch vessel from: %s - %j",a.requestId,n,t);const r=await q.get(n,t).json();if(r.status!==200)return p==null||p.warn("[%s] fetch suggest vessels failed: %j",a.requestId,{message:r.message,status:r.status,code:r.code}),{};{const d=r.data;if(d)return{mmsi:d.mmsi,imo:Number.isNaN(d.imo)?null:Number(d.imo),callSign:d.callsign,name:d.nameEn,nameCn:d.nameCn,type:d.vesselTypeNameEn,flagName:d.flagCtry,clasz:d.classSociety,dateOfBuild:d.buildYearMonth,deadweight:d.dwt,grossTonnage:d.grt,netTonnage:d.net,teu:d.teu,length:d.length,breadth:d.width,height:d.height,draught:d.draught,speed:d.speed,passengerCapacity:d.passengercapacity,vendor:"myvessel",raw:d}}return{}}async archives(e,a={}){var t,r;await this.checkToken(a);const i="https://svc.data.myvessel.cn/sdc/v1/ship/info/batch",n={headers:{Authorization:`${(t=this.token)==null?void 0:t.tokenType} ${(r=this.token)==null?void 0:r.accessToken}`},json:{mmsiList:typeof e=="number"?[e]:e}};p==null||p.info("[%s] fetch vessel archive from: %s - %j",a.requestId,i,n);const o=await q.post(i,n).json();return o.status!==200?(p==null||p.warn("[%s] fetch vessel archive failed: %j",a.requestId,{message:o.message,status:o.status,code:o.code}),{}):o.data}async realTimePosition(e,a={}){var r,l;await this.checkToken(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} ${(l=this.token)==null?void 0:l.accessToken}`},searchParams:{mmsi:e}};p==null||p.info("[%s] fetch realtime position from: %s - %j",a.requestId,i,n);const o=await q.get(i,n).json();if(o.code)return p==null||p.warn("[%s] fetch realtime position failed: %j",a.requestId,{message:o.message,status:o.status,code:o.code}),o;const t=o.data;for(const h in t)!isNaN(t[h])&&Number(t[h])!==1/0&&(t[h]=Number(t[h]));if(t){const h=v(`${t.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return{mmsi:t.mmsi,name:t.vesselName||t.aisVesselName,imo:t.imo,callSign:t.callsign||t.aisCallSign,lat:t.lat,lng:t.lon,length:t.length,width:t.width,draught:t.currDraught,sog:t.sog,cog:t.cog,hdg:t.hdg,rot:t.rot,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(t.eta)?v.utc(t.eta).format():void 0,destination:t.dest,positionTime:h.unix(),status:t.status,labelCn:t.statusNameCn,labelEn:t.statusNameEn,vesselType:t.vesselTypeNameEn,flag:t.flagCtryNameEn,clasz:t.classSociety,build:t.buildYear,dwt:t.dwt,grt:t.grt,net:t.net,method:"position",vendor:"myVessel",utc:h.utc().format()}}else return{}}async calculateRoute(e,a,i,n,o,t={}){var y,w,M;const r=v();await this.checkToken(t);const l="https://svc.data.myvessel.cn/sdc/v1/routes/routing/nodes",h={headers:{Authorization:`${(y=this.token)==null?void 0:y.tokenType} ${(w=this.token)==null?void 0:w.accessToken}`},json:{startPoint:{lon:e.lng,lat:e.lat},endPoint:{lon:a.lng,lat:a.lat},maxDraught:t.draught||10,useAIModel:t.useAIModel||!1,withECA:t.withECA||!1,withSpecialRegion:t.withSpecial||!1}};i!=null&&i.length&&(h.json.crossMonthList=i),n!=null&&n.length&&(h.json.excludeNodes=n),o!=null&&o.length&&(h.json.excludeSeaAreas=o),p==null||p.info("[%s] fetch route from: %s - %j",t.requestId,l,h);const d=await q.post(l,h).json();if(d.status!==200)return p==null||p.warn("[%s] fetch route failed: %j",t.requestId,{message:d.message,status:d.status,code:d.code}),{};{const I={status:"Success",nodes:[],seas:[],regions:[],waypoints:[],route:[],distance:0,memo:""},{nodes:j,seas:b,tracks:g,specialRegions:m}=d.data;I.nodes=j==null?void 0:j.map(c=>({code:c.nodeCode,nameEn:c.nameEn,nameCn:c.nameCn,center:{lat:Math.round(c.lat*1e6)/1e6,lng:Math.round(c.lon*1e6)/1e6},start:{lat:Math.round(c.startLat*1e6)/1e6,lng:Math.round(c.startLon*1e6)/1e6},end:{lat:Math.round(c.endLat*1e6)/1e6,lng:Math.round(c.endLat*1e6)/1e6},isKey:c.isKeyNode,isHub:c.isHubNode})),I.seas=b==null?void 0:b.map(c=>({code:c.mrgidSea,nameEn:c.nameEn,nameCn:c.nameCn,center:{lat:Math.round(c.centerLat*1e6)/1e6,lng:Math.round(c.centerLon*1e6)/1e6},min:{lat:Math.round(c.minLat*1e6)/1e6,lng:Math.round(c.minLon*1e6)/1e6},max:{lat:Math.round(c.maxLat*1e6)/1e6,lng:Math.round(c.maxLon*1e6)/1e6},level:c.mapLevel})),m==null||m.map(c=>{c.regionLength&&I.regions.push({type:c.regionType,distance:c.regionLength,rows:c.regions.map(k=>({code:k.regionCode,nameCn:k.nameCn,nameEn:k.nameEn,type:k.regionType,distance:k.length}))})}),I.waypoints=g==null?void 0:g.map(c=>({lat:Math.round(c.lat*1e5)/1e5,lng:Math.round(c.lon*1e5)/1e5})),(M=I.waypoints)!=null&&M.length&&(I.waypoints=L.LaneHelper.simplifyCoordinates(I.waypoints),I.route=L.LaneHelper.divideAccordingToLng(I.waypoints),I.distance=L.LaneHelper.calculateRouteDistance(I.route));const f=v().diff(r,"second");return I.memo=`time cost: ${f}s`,p.info("[%s] calculate route cost: %d seconds",t.requestId,f),I}}async trajectory(e,a,i,n,o=!0,t={}){await this.checkToken(t);const r=await this.realTimePosition(e,t),l=v(a),h=v(i),d=[];for(;h.diff(l,"day",!0)>30;)await this.trajectoryIn30Day(e,l,l.clone().add(30,"day"),r,n,d,t),l.add(30,"day");return await this.trajectoryIn30Day(e,l,h,r,n,d,t),d}async trajectoryIn30Day(e,a,i,n,o,t,r={}){var M,I,j,b,g;const l="https://svc.data.myvessel.cn/sdc/v1/vessels/status/track",h={headers:{Authorization:`${(M=this.token)==null?void 0:M.tokenType} ${(I=this.token)==null?void 0:I.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")}};p==null||p.info("[%s] fetch trajectory from: %s - %j",r.requestId,l,h);const d=await q.post(l,h).json();if(d.code)return p==null||p.warn("[%s] fetch trajectory failed: %j",r.requestId,l,{message:d.message,status:d.status,code:d.code}),d;let y=-1;const w=v(`${(b=(j=d.data)==null?void 0:j[0])==null?void 0:b.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return(g=d.data)==null||g.forEach(m=>{for(const O in m)!isNaN(m[O])&&Number(m[O])!==1/0&&(m[O]=Number(m[O]));const u=v(`${m.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00"),f=m.status,{labelCn:c,labelEn:k}=this.parseStatus(f),S={mmsi:m.mmsi,imo:n==null?void 0:n.imo,lat:m.lat,lng:m.lon,sog:m.sog,cog:m.cog,hdg:m.hdg,draught:m.draught,status:f,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(m.eta)?v(`${m.eta} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00").utc().format():void 0,destination:m.dest,positionTime:u.unix(),labelCn:c,labelEn:k,method:"trajectory",vendor:"myVessel",utc:u.utc().format()},F=Math.floor(u.diff(w,"minute",!0)/(o||1));F!==y&&(y=F,t.push(S))}),t}}class gt extends G{constructor(e){super();U(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 q.post(i,n).json();p==null||p.info("[%s] fetch realtime position from: %s - %j",a.requestId,i,n);const t=o==null?void 0:o.list;if(!t)return p==null||p.warn("[%s] fetch realtime position failed: %j",a.requestId,i,o),o;for(const w in t)!isNaN(t[w])&&Number(t[w])!==1/0&&(t[w]=Number(t[w]));t.status=t.sp>3?0:1;const r=t.status,{labelCn:l,labelEn:h}=this.parseStatus(r),d=v(`${t.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return{mmsi:t.m,name:t.n,imo:t.imonumber,callSign:t.callsign,lat:Math.round(t.la/60*1e5)/1e5,lng:Math.round(t.lo/60*1e5)/1e5,length:t.l,width:t.w,draught:t.draught,sog:t.sp,cog:t.co,hdg:t.h,rot:isNaN(t.rot)?0:t.rot,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(t.eta)?v.utc(t.eta).format():void 0,destination:t.destination,vesselType:t.type,dwt:t.dwt,build:t.buildyear,flag:t.fn,positionTime:d.unix(),utc:d.utc().format(),status:r,labelCn:l,labelEn:h,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 q.post(i,n).json();p==null||p.info("[%s] fetch vessel props from: %s - %j",a.requestId,i,n),o instanceof Array&&(o=o[0]);for(const r in o)!isNaN(o[r])&&Number(o[r])!==1/0&&(o[r]=Number(o[r]));const t={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 q.post(i,n).json(),p==null||p.info("[%s] search vessel dead weight from: %s - %j",a.requestId,i,n),o instanceof Array&&(o=o[0]),o&&(t.deadweight=Number(o.dwt)),t}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 q.post(i,n).json();p==null||p.info("[%s] suggest vessel props from: %s - %j",a.requestId,i,n);const t=[];for(const r of o)t.push({mmsi:!r.mmsi||isNaN(r.mmsi)?null:Number(r.mmsi),name:r.name,callSign:r.callsign,imo:!r.imo||isNaN(r.imo)?null:Number(r.imo),score:r._score});return t.sort((r,l)=>l.score-r.score),t}async trajectory(e,a,i,n,o=!0,t={}){var m,u,f;const r=await this.realTimePosition(e,t);let l=v(a);const h=v(i),d=v();if(o){let c=h.diff(l,"d",!0);c<0?l=h.clone().subtract(40,"d"):c<30?l.subtract(10,"d"):c<60?l.subtract(5,"d"):l=h.clone().subtract(80,"d"),c=d.diff(h,"d",!0),h.add(c>10?240:c*24,"h")}const y={searchParams:{endtime:h.utcOffset("+8:00").format("YYYY-MM-DD HH:mm:ss"),starttime:l.utcOffset("+8:00").format("YYYY-MM-DD HH:mm:ss"),mmsi:e,usertoken:this.token}},w="https://api.hifleet.com/position/trajectory/nocompressed/withstatic/token",M=await q.get(w,y).json();p==null||p.info("[%s] fetch trajectory from: %s - %j",t.requestId,w,y);let I;M&&(I=((u=(m=M.ships)==null?void 0:m.offors)==null?void 0:u.ship)||[],I.length||p==null||p.warn("[%s] fetch trajectory failed: %j",t.requestId,M));const j=[];let b=-1;const g=v(`${(f=I==null?void 0:I[0])==null?void 0:f.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");for(const c of I){for(const R in c)!isNaN(c[R])&&Number(c[R])!==1/0&&(c[R]=Number(c[R]));const k=v(`${c.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");c.status=c.sp>4?0:1;const{labelEn:S,labelCn:F}=this.parseStatus(c.status),O={mmsi:c.m,name:c.n,imo:r==null?void 0:r.imo,lat:c.la,lng:c.lo,draught:c.draught,sog:c.sp,cog:c.co,hdg:c.hdg,positionTime:k.unix(),utc:k.utc().format(),status:c.status,labelCn:F,labelEn:S,method:"trajectory",vendor:"hifleet"},x=Math.floor(k.diff(g,"minute",!0)/(n||1));x!==b&&(b=x,j.push(O))}return j}}class vt extends G{constructor(e){super();U(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 q.get(n,i).json();if(p==null||p.info("[%s] fetch realtime position from: %s - %j",a.requestId,n,i),(o==null?void 0:o.status)!==0)return o;const t=o.data[0];for(const y in t)!isNaN(t[y])&&Number(t[y])!==1/0&&(t[y]=Number(t[y]));const{labelCn:r,labelEn:l}=await this.parseStatus(t.navistat),h=v.unix(t.lasttime);return{mmsi:t.ShipID,name:t.name,imo:t.imo,callSign:t.callsign,lat:Math.round(t.lat/1e6*1e5)/1e5,lng:Math.round(t.lon/1e6*1e5)/1e5,length:Math.round(t.length/10*100)/100,width:Math.round(t.width/10*100)/100,draught:Math.round(t.draught/1e3*100)/100,sog:Math.round(t.sog*3600/1e3/1852*100)/100,cog:Math.round(t.cog/100*100)/100,hdg:Math.round(t.hdg/100*100)/100,rot:Math.round(t.rot/100*100)/100,positionTime:t.lasttime,utc:h.utc().format(),status:t.navistat,labelEn:l,labelCn:r,method:"position",vendor:"shipxy"}}async trajectory(e,a,i,n,o=!0,t={}){var g;const r=await this.realTimePosition(e,t),l=v(a),h=v(i),d="https://api.shipxy.com/apicall/GetShipTrack",y={searchParams:{id:e,k:this.token,enc:1,cut:0,btm:l.unix(),etm:h.unix()}},w=await q.get(d,y).json();if(p==null||p.info("[%s] fetch trajectory from: %s - %j",t.requestId,d,y),(w==null?void 0:w.status)!==0)return w;const M=w==null?void 0:w.points,I=[],j=v.unix((g=M[0])==null?void 0:g.utc);let b=-1;for(const m of M){const u=v.unix(m.utc),f={imo:r==null?void 0:r.imo,mmsi:e,sog:Math.round(m.sog*3600/1e3/1852*100)/100,cog:Math.round(m.cog/100*100)/100,lat:Math.round(m.lat/1e6*1e5)/1e5,lng:Math.round(m.lon/1e6*1e5)/1e5,positionTime:u.unix(),utc:u.utc().format(),method:"trajectory",vendor:"shipxy"},c=Math.floor(u.diff(j,"minute",!0)/(n||1));c!==b&&(b=c,I.push(f))}return I}}class wt extends G{constructor(e){super();U(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 q.post(n,i).json();return p==null||p.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 q.post(n,i).json();if(p==null||p.info("[%s] fetch ship info from: %s - %j",a.requestId,n,i),o.code!=="0")return o;const t=o.data;let r=t.imo;return e==="407170"&&(r="9198379",p==null||p.warn("[%s] ship(%s) imo error: %s, should be %s",a.requestId,e,t.imo,r)),{mmsi:t.mmsi,name:t.shipnameEn,imo:r,callSign:t.callSign,length:t.length,width:t.breadth,draught:(t.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}},t="https://api3.myships.com/sp/ships/position/latest",r=await q.post(t,o).json();p==null||p.info("[%s] fetch realtime position from: %s - %j",a.requestId,t,o);const l=r.data[0];for(const M in l)!isNaN(l[M])&&Number(l[M])!==1/0&&(l[M]=Number(l[M]));const{labelCn:h,labelEn:d}=await this.parseStatus(l.aisNavStatus),y=v.unix(l.posTime);return{...n,mmsi:e,lat:Math.round(l.lat/1e4/60*1e5)/1e5,lng:Math.round(l.lon/1e4/60*1e5)/1e5,sog:Math.round(l.sog/10*100)/100,cog:Math.round(l.cog/10*100)/100,hdg:Math.round(l.heading*100)/100,rot:Math.round(l.rot*100)/100,positionTime:l.posTime,utc:y.utc().format(),status:l.aisNavStatus,labelEn:d,labelCn:h,method:"position",vendor:"myship"}}async trajectory(e,a,i,n,o=!0,t={}){const r=v(a),l=v(i),h=await this.getShipId(e),d=await this.getShipInfo(h),y=[];for(;l.diff(r,"day",!0)>30;)await this.trajectoryIn30Day(h,r.unix(),r.add(30,"day").unix(),d,e,n,y);return await this.trajectoryIn30Day(h,r.unix(),l.unix(),d,e,n,y),y}async trajectoryIn30Day(e,a,i,n,o,t,r,l={}){var j;const h={headers:{appKey:this.token},json:{shipId:e,startTime:a,endTime:i}},d="https://api3.myships.com/sp/ships/position/history",y=await q.post(d,h).json();if(p==null||p.info("[%s] fetch trajectory from: %s - %j",l.requestId,d,h),y.code!=="0")return p==null||p.warn("[%s] invoke myship trajectory failed: %j",l.requestId,y),y;const w=y.data;for(const b in w)!isNaN(w[b])&&Number(w[b])!==1/0&&(w[b]=Number(w[b]));const M=v.unix((j=w[0])==null?void 0:j.posTime);let I=-1;for(const b of w){const g=v.unix(b.posTime),m={imo:n==null?void 0:n.imo,mmsi:o,lat:Math.round(b.lat/1e4/60*1e5)/1e5,lng:Math.round(b.lon/1e4/60*1e5)/1e5,sog:Math.round(b.sog/10*100)/100,cog:Math.round(b.cog/10*100)/100,hdg:Math.round(b.heading*100)/100,rot:Math.round(b.rot*100)/100,positionTime:g.unix(),utc:g.utc().format(),method:"trajectory",vendor:"myship"},u=Math.floor(g.diff(M,"minute",!0)/(t||1));u!==I&&(I=u,r.push(m))}return r}}let _;try{_=K.getLogger("vessel")}catch{}finally{}var ht=(P=>(P.NOTICE="NOTICE",P.WARN="WARN",P.HEAVY="HEAVY",P.SEVERE="SEVERE",P.ERROR="ERROR",P.FATAL="FATAL",P))(ht||{});class ft{parsePrinciple(s,e={}){var t,r,l;_==null||_.debug("[%s] parse rule: %s",e.requestId,s);const a=new RegExp("(?<=\\[)(.+)(?=])","g"),i=s.match(a)?(t=s.match(a))==null?void 0:t[0]:void 0,n=i==null?void 0:i.split(";");if(!n)return;const o={};for(let h=0;h<(n==null?void 0:n.length);h++){const d=(l=(r=n[h].match(a))==null?void 0:r[0])==null?void 0:l.split("],");if(h===0&&!d)o.scope=n[0];else if(d)for(let y=0,w=d.length;y<w;y++){const M=this.parseRule(d[y]);M&&(o[M.level]?M.key?o[M.level][M==null?void 0:M.key]=M:o[M.level]=M:M.key?o[M.level]={[M==null?void 0:M.key]:M}:o[M.level]=M)}}return o}parseRule(s,e={}){var o;_==null||_.debug("[%s] parse rule: %s",e.requestId,s),s=s.startsWith("[")?s:`[${s}`,s=s.endsWith("]")?s:`${s}]`;const a=new RegExp("(?<=\\[)(.+?)(?=])","g"),i=(o=s==null?void 0:s.match(a))==null?void 0:o[0],n=i==null?void 0:i.split(",");if(n){let t=n[3]==="Number.MAX_VALUE"?100:Number(n[3]);return t=isNaN(t)?1:t,{operator:n[0],number:Number.isNaN(Number(n[1]))?n[1]:Number(n[1]),level:n[2],time:t,key:n[4]}}}checkWeather(s,e,a={}){var M,I,j,b,g,m,u,f,c,k,S,F,O,x,R;let i=0,n=0,o=0,t=0;const r=Math.round(((I=(M=e==null?void 0:e.SEVERE)==null?void 0:M.sigWave)==null?void 0:I.number)*1.6*100)/100,l=(b=(j=e==null?void 0:e.SEVERE)==null?void 0:j.sigWave)==null?void 0:b.number,h=(m=(g=e==null?void 0:e.HEAVY)==null?void 0:g.sigWave)==null?void 0:m.number,d=Math.round((((f=(u=e==null?void 0:e.SEVERE)==null?void 0:u.wind)==null?void 0:f.number)+2)*100)/100,y=(k=(c=e==null?void 0:e.SEVERE)==null?void 0:c.wind)==null?void 0:k.number,w=(F=(S=e==null?void 0:e.HEAVY)==null?void 0:S.wind)==null?void 0:F.number;for(let E=0;E<(s==null?void 0:s.length);E++){const H=s[E],V=(x=(O=H==null?void 0:H.meteo)==null?void 0:O.wave)==null?void 0:x.sig,B=(R=H==null?void 0:H.meteo)==null?void 0:R.wind,J=E?v(H.eta).diff(v(s[E-1].eta),"hour",!0):0;t=J>t?J:t,_==null||_.debug("[%s] check sig.wave: %j",a.requestId,{...V,dgThd4Wv:r,svThd4Wv:l,hvThd4Wv:h}),(V==null?void 0:V.height)>=r?H.isDangerous=!0:(V==null?void 0:V.height)>=l?H.isSevere=!0:(V==null?void 0:V.height)>=h&&(H.isHeavy=!0),_==null||_.debug("[%s] check wind: %j",a.requestId,{...B,dgThd4Wd:d,svThd4Wd:y,hvThd4Wd:w}),(B==null?void 0:B.scale)>=d?(H.isDangerous=!0,delete H.isSevere,delete H.isHeavy):(B==null?void 0:B.scale)>y?(H.isDangerous||(H.isSevere=!0),delete H.isHeavy):(B==null?void 0:B.scale)===w&&!H.isDangerous&&!H.isSevere&&(H.isHeavy=!0),i+=H.isDangerous?J:0,n+=H.isSevere?J:0,o+=H.isHeavy?J:0}return i=Math.round(i*100)/100,n=Math.round(n*100)/100,o=Math.round(o*100)/100,t=Math.round(t),{sample:s,dangerous:i,severe:n,heavy:o,step:t<3?3:t,wind:{dgThd4Wd:d,svThd4Wd:y,hvThd4Wd:w},sig:{dgThd4Wv:r,svThd4Wv:l,hvThd4Wv:h}}}}const It=new ft;let T;try{T=K.getLogger("vessel")}catch{}finally{}const kt=new Mt.MeteoHelper2("",!0);var mt=(P=>(P.common="common",P.container="container",P.tugs="tugs",P))(mt||{}),yt=(P=>(P.Ballast="Ballast",P.Laden="Laden",P))(yt||{}),pt=(P=>(P.Cp="CP",P.Perf="Basis",P.Instruct="Other",P))(pt||{});class z{static blockCoefficient(s,e,a,i){let n=Math.round(s/(e*a*i)*100)/100;n=n<.55?.55:n>.85?.85:n;const o=[.55,.6,.65,.7,.75,.8,.85],t=o.map(r=>Math.abs(r-n));return o[t.indexOf(Math.min(...t))]}static froudeNumber(s,e,a=9.8){let i=Math.round(Math.sqrt(s*s/(a*e))*100)/100;return i=i<.05?.05:i>.3?.3:i,i}static amendFactor(s,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]}[s];return a==="Laden"&&(o=i[s]),o[0]+o[1]*e+o[2]*Math.pow(e,2)}static directionFactor(s,e=0){let a;return s>30&&s<=60?a=(1.7-.03*Math.pow(e-4,2))/2:s>60&&s<=150?a=(.9-.06*Math.pow(e-6,2))/2:s>150&&s<=180?a=(.4-.03*Math.pow(e-8,2))/2:a=1,Math.round(a*1e5)/1e5}static vesselTagFactor(s,e,a,i){let n;return a==="container"?n=.7*i/2+Math.pow(i,3)/(22*Math.pow(s,2/3)):e==="Ballast"?n=.7*i/2+Math.pow(i,3)/(2.7*Math.pow(s,2/3)):n=.5*i/2+Math.pow(i,3)/(2.7*Math.pow(s,2/3)),n}static waveHeightFactor(s,e){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 e>30&&e<=60?a=-.6:e>60&&e<=90?a=-.4:e>90&&e<=120?a=s<3?.4:-.3:e>120&&e<=150?a=s<3?.6:-.5:e>150&&e<=180?a=s<3?.7:-.6:a=-.7,Math.round(a*(.144*Math.pow(s,2)+.278*s)*1e4)/1e4}static assembleProperties(s,e,a,i){var y;const n=s.lbp??s.length??s.lengthOverall??198.9642,o=s.draught??8,t=s.breadthMoulded??s.breadth??s.breadthExtreme??32.4572,r=s.deadweight??67035.7773,l=((y=s==null?void 0:s.type)==null?void 0:y.toLowerCase())||"common";return{tag:l.indexOf("container")>-1?"container":l.indexOf("tugs")>-1?"tugs":"common",lbp:n,loadCondition:e,draught:o,breadthMoulded:t,displacement:Math.round((r/1.025+o*t*n*.7)*1e4)/1e4,speed:Math.round((a??14.1382)*1852/3600*1e4)/1e4,bearing:i||90}}static async speedLoseAt(s,e,a,i="",n=2,o=!0,t=!1,r={}){let l;if(e.velocity&&t&&(s.speed=L.LngLatHelper.roundPrecision(e.velocity*1852/3600,6)),o){let h;try{i=(i==null?void 0:i.toUpperCase())==="CMEMS"?"ECMWF":i,i=(i==null?void 0:i.toUpperCase())==="METEO2"?"best_match":i;const{weatherModels:M,marineModels:I}=await rt.Meteo2Assist.autoPickMeteoModel(i),j=await kt.spotForecast(e.lat,e.lng,a.utc().format(),!1,!1,!0,{...r,pastDays:1,forecastDays:1,weatherModels:M,marineModels:I}),[b]=rt.Meteo2Assist.pickHourly(j,a);h=rt.Meteo2Assist.toLegacy(b)}catch(M){T.warn("[%s] meteo2 spot(%j) forecast failed: %s",r.requestId,{...e,eta:a.utc().format(),source:i},M)}const d=z.currentFactor(s.bearing,h==null?void 0:h.current,n),y=z.weatherFactor(s,h,d),w=Math.round((s.speed*1.943844+y+d)*100)/100;l={meteo:{...h},wxFactor:y,cFactor:d,speed:e.velocity&&t?e.velocity:w<0?1:w,eta:a.utc().format(),etd:a.utc().format()}}else l={wxFactor:0,cFactor:0,speed:e.velocity&&t?e.velocity:Math.round(s.speed*1.943844*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,{...l,...e}}static async speedLoseInHoursStep(s,e,a,i,n,o,t="",r=!0,l=!1,h={}){e.utc();const d=e.clone().add(14,"days"),y=[],w=[],M=[];let I=0,j=0,b,g;for(let m=0;m<o.length-1;m++){let u=o[m];u.distanceFromStart=Math.round((n+j)*1e3)/1e3;const f=o[m+1];if(s.bearing=L.LaneHelper.calculateBearing(u,f,!f.gcToPrevious),u.bearing=s.bearing,u.suspend&&l){u.eta=u.eta||e.utc().format(),u.elapsed=u.elapsed??0;const S=u.suspend-u.elapsed;if(i-I>S)i=i-I-S,e.add(S,"hour"),u.elapsed=u.suspend;else{const F=i-I;u.elapsed+=F,e.add(F,"hour"),i=0}if(T==null||T.info(`[%s] suspend ${u.elapsed} hours at %j, and remain ${i} hours need to go...`,h.requestId,u),i===0)return u.distanceFromPrevious=j,{etd:e,from:g||u,to:u,next:o.filter(F=>F),wps:y,days:w,all:M}}else u.suspend=0;r=e.isAfter(d)?!1:r,u=await z.speedLoseAt(s,u,e,t,0,r,l,h),M.push(u),g=g||u,u.important&&y.push(u),e.isSameOrAfter(a)&&(w.push(u),a.add(24,"hour"));const c=L.LaneHelper.calculateDistance(u,f,!f.gcToPrevious);let k=Math.round(c/g.speed*1e5)/1e5;if(I+k<i){if(I+=k,e.add(k,"hour"),delete o[m],T==null||T.debug(`[%s] go to %j from %j with ${c}nm, and cost ${k} hours`,h.requestId,{lat:f.lat,lng:f.lng},{lat:g.lat,lng:g.lng,etd:g.etd}),j+=c,o.filter(S=>S).length<=1){b=f,b.eta=e.utc().format(),b.distanceFromPrevious=c,b.distanceFromStart=Math.round((n+j)*1e4)/1e4,y.push(b),M.push(b),delete o[m+1];break}}else{k=i-I,e.add(k,"hour");const S=L.LngLatHelper.roundPrecision(g.speed*k,5);b=L.LaneHelper.calculateCoordinate(u,s.bearing,S,"nauticalmiles",!f.gcToPrevious),b.eta=e.utc().format(),o[m]=b,T==null||T.debug(`[%s] go to %j from %j with ${S}nm, and cost ${k} hours`,h.requestId,{lat:b.lat,lng:b.lng},{lat:u.lat,lng:u.lng,etd:u.etd}),j+=S,b.distanceFromPrevious=Math.round(j*1e4)/1e4,b.distanceFromStart=Math.round((n+j)*1e4)/1e4;break}}return{etd:e,from:g,to:b,next:o.filter(m=>m),wps:y,days:w,all:M}}static currentFactor(s,e,a=0){const i=(s-(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(s,e,a=0){var w,M,I,j,b,g,m;T==null||T.debug("calculate weather factor via: %j",{...s,...e});const i=z.blockCoefficient(s.displacement,s.lbp,s.breadthMoulded,s.draught),n=L.LngLatHelper.roundPrecision(a*1852/3600,6),o=z.froudeNumber(s.speed-n,s.lbp),t=z.amendFactor(i,o,s.loadCondition);let r=Math.abs(s.bearing%360-(((w=e==null?void 0:e.wind)==null?void 0:w.degree)%360||0));r=r>180?360-r:r;const l=z.directionFactor(r,(M=e==null?void 0:e.wind)==null?void 0:M.scale),h=z.vesselTagFactor(s.displacement,s.loadCondition,s.tag,(I=e==null?void 0:e.wind)==null?void 0:I.kts);let d=l*t*h/100*(s.speed-n);d=Math.round(d*1.943844*1e4)/1e4*-1,s.tag==="tugs"&&Math.abs(d)>1&&(d=d/(Math.abs(Math.round(d))+1)),T==null||T.debug("wind wx factor = %d",d),r=Math.abs(s.bearing%360-(((b=(j=e==null?void 0:e.wave)==null?void 0:j.sig)==null?void 0:b.degree)%360||0)),r=r>180?360-r:r;const y=z.waveHeightFactor(((m=(g=e==null?void 0:e.wave)==null?void 0:g.sig)==null?void 0:m.height)??1,r);return T==null||T.debug("wave wx factor = %d",y),d=Math.abs(d)>Math.abs(y)?d:d*.3+y*.7,T==null||T.debug("weather factor = %d",d),d=Math.abs(d)>3?3*(Math.abs(d)/d)+Math.abs(d)/d*(Math.abs(d)-2)*.1:d,Math.round((d||0)*100)/100}static async analyseInstant(s,e,a,i,n,o="",t=0,r=!0,l=!1,h={}){var X,Q,Z,$,tt,et,st,at;const d=v().valueOf();s.lng=L.LngLatHelper.convertToStdLng(s.lng);const{route:y,waypoints:w}=n.points,M=L.LaneHelper.calculateSubRoute(s,y);if(((X=M[0])==null?void 0:X.length)<=1)return;const{v0:I,label:j}=s.sog?{v0:s.sog,label:s.label||"Other"}:{v0:i.speed,label:"CP"},b=z.assembleProperties(a,i.loadCondition,I,0),g=w.length?L.LaneHelper.calculateSubWaypoints(s,w):[];g.forEach(N=>N.important=!0);const m={from:{...s},route:M,waypoints:g,v0:I,label:j},u={hours:[],days:[],wps:[],all:[]};t||(L.LaneHelper.calculateRouteDistance(M)/i.speed<=72?t=3:t=6);let f=L.LaneHelper.simplifyRouteToCoordinates(M,g,0),c=0,k=0,S=0,F=0;e=v(e).utc();const O=e.clone();for(;f.length>0;){const N=t-e.hour()%t,W=Math.ceil(e.clone().add(N,"h").set({minute:0,second:0,millisecond:0}).diff(e,"h",!0)*1e4)/1e4,C=await z.speedLoseInHoursStep(b,e,O,W,c,f,o,r,l,h);if(u.all.push(...C.all),(Q=C.from)!=null&&Q.speed&&(u.hours.push(C.from),u.wps.push(...C.wps),u.days.push(...C.days)),f=C==null?void 0:C.next,!f.length){const D=await z.speedLoseAt(b,C.to,v(C.to.eta),o,0,r,l,h);D.bearing=b.bearing,u.hours.push(D),u.all.push(D)}c+=Math.round((((Z=C==null?void 0:C.to)==null?void 0:Z.distanceFromPrevious)??0)*1e4)/1e4}const x=u.hours;for(let N=0;N<x.length-1;N++){const W=v(x[N+1].eta).diff(x[N].etd,"hour",!0)||1;k+=(x[N].wxFactor||0)*W,S+=(x[N].cFactor||0)*W,F+=W}const R=x.reduce((N,W)=>N+(W.suspend||0),0);($=u.wps)==null||$.forEach((N,W)=>{N.positionTime=v.utc(N.etd||N.eta).unix();const C=u.wps[W-1];if(C){const D=N.distanceFromStart-C.distanceFromStart,A=v(N.eta||N.etd).diff(v(C.etd||C.eta),"h",!0);N.avgSpd=Math.round(D/A*100)/100,C.bearing=L.LaneHelper.calculateBearing(C,N)}}),u.wps=(tt=u.wps)==null?void 0:tt.reduce((N,W)=>(N.some(C=>Math.round(C.positionTime/60)===Math.round(W.positionTime/60))||N.push(W),N),[]),u.days=(et=u.days)==null?void 0:et.reduce((N,W)=>(N.some(C=>Math.round(C.positionTime/(60*60*12))===Math.round(W.positionTime/(60*60*12)))||N.push(W),N),[]),u.all=(st=u.all)==null?void 0:st.reduce((N,W)=>(W.positionTime=v.utc(W.etd||W.eta).unix(),N.some(C=>Math.round(C.positionTime/60)===Math.round(W.positionTime/60))||N.push(W),N),[]),m.sample=u;const E=u.hours.at(0),H=u.hours.at(-1);m.distance=Math.round(H.distanceFromStart*1e3)/1e3,m.etd=v(E.eta).utc().format(),m.eta=v(H.eta).utc().format(),m.wxFactor=Math.round(k/F*1e3)/1e3,m.cFactor=Math.round(S/F*1e3)/1e3,m.avgSpeed=Math.round(H.distanceFromStart/F*1e3)/1e3,m.totalHrs=Math.round(F*1e3)/1e3,m.suspend=Math.round(R*1e3)/1e3;const V=L.LngLatHelper.roundPrecision(i.dgo/24*R,3),{distanceInECA:B,hoursInECA:J,totalDgoConsInECA:ct,eca:nt}=await this.calculateECA(m,i,h),ot=L.LngLatHelper.roundPrecision(i.fo/24*(F-J),3),dt=L.LngLatHelper.roundPrecision(i.dgo/24*F+V,3);m.extend={eca:nt,distanceInECA:B,hoursInECA:J,totalDgoConsInECA:ct,totalDgoConsInSuspend:V},m.totalFoCons=ot<0?0:ot,m.totalDgoCons=dt;const it=v().valueOf()-d,lt=((at=u==null?void 0:u.hours)==null?void 0:at.length)||1;return T==null||T.info("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms",h==null?void 0:h.requestId,it,lt,Math.round(it/lt*1e3)/1e3),m}static async analyseInstantWithThreshed(s,e,a,i,n,o,t,r="",l=3,h=!0,d=!1,y={}){var Z,$,tt,et,st,at,N,W;const w=v().valueOf();s.lng=L.LngLatHelper.convertToStdLng(s.lng);const{v0:M,label:I}=s.sog?{v0:s.sog,label:s.label||"Other"}:{v0:n.speed,label:"CP"},j=z.assembleProperties(i,n.loadCondition,M,0),b=L.LaneHelper.calculateSubRoute(s,o);if(((Z=b[0])==null?void 0:Z.length)<=1)return;const g=t.length?L.LaneHelper.calculateSubWaypoints(s,t):[];g.forEach(C=>C.important=!0);let m=L.LaneHelper.simplifyRouteToCoordinates(b,g,0),u=0,f=0,c=0,k=0;const S={hours:[],wps:[],days:[],all:[]};e=v(e).utc();const F=e.clone();for(;m.length>0;){const C=l-e.hour()%l;let D=Math.ceil(e.clone().add(C,"h").set({minute:0,second:0,millisecond:0}).diff(e,"h",!0)*1e4)/1e4;D=e.clone().add(D,"h").isSameOrAfter(a)?a.diff(e,"h",!0)*1e4/1e4:D;const A=await z.speedLoseInHoursStep(j,e,F,D,u,m,r,h,d,y);if(S.all.push(...A.all),($=A.from)!=null&&$.speed&&(S.hours.push(A.from),A!=null&&A.wps&&S.wps.push(...A.wps),S.days.push(...A.days)),m=A==null?void 0:A.next,m.length||S.hours.push(A==null?void 0:A.to),u+=Math.round((((tt=A==null?void 0:A.to)==null?void 0:tt.distanceFromPrevious)??0)*1e4)/1e4,!D)break}S.wps=(et=S.wps)==null?void 0:et.reduce((C,D)=>(C.some(A=>Math.round(v(A.etd).unix()/60)===Math.round(v(D.etd).unix()/60))||C.push(D),C),[]),S.days=(st=S.days)==null?void 0:st.reduce((C,D)=>(C.some(A=>Math.round(A.positionTime/(60*60*12))===Math.round(D.positionTime/(60*60*12)))||C.push(D),C),[]),S.all=(at=S.all)==null?void 0:at.reduce((C,D)=>(D.positionTime=v.utc(D.etd||D.eta).unix(),C.some(A=>Math.round(v(A.etd).unix()/60)===Math.round(v(D.etd).unix()/60))||C.push(D),C),[]),(N=S.wps)==null||N.forEach((C,D)=>{const A=S.wps[D-1];if(A){const St=C.distanceFromStart-A.distanceFromStart,Ct=v(C.eta||C.etd).diff(v(A.etd||A.eta),"h",!0);A.bearing=L.LaneHelper.calculateBearing(A,C),C.avgSpd=Math.round(St/Ct*100)/100}});const O=S.hours;for(let C=0;C<O.length-1;C++){const D=v(O[C+1].eta).diff(O[C].etd,"hour",!0);f+=O[C].wxFactor*D,c+=O[C].cFactor*D,k+=D}const x=O.reduce((C,D)=>C+(D.suspend||0),0),R=S.hours.at(0),E=S.hours.at(-1),H=await L.LaneHelper.calculateRangeRoute(R,E,b),V=await L.LaneHelper.calculateRangeWaypoints(R,E,b,g),B={sample:S,distance:Math.round(((E==null?void 0:E.distanceFromStart)||0)*1e4)/1e4,etd:v(R.eta).utc().format(),eta:v(E==null?void 0:E.eta).utc().format(),wxFactor:Math.round(f/k*1e3)/1e3,cFactor:Math.round(c/k*1e3)/1e3,avgSpeed:Math.round(((E==null?void 0:E.distanceFromStart)||0)/k*1e3)/1e3,totalHrs:Math.round(k*1e3)/1e3,suspend:Math.round(x*1e3)/1e3,from:R,to:E,route:H,waypoints:V,v0:M,label:I},J=L.LngLatHelper.roundPrecision(n.dgo/24*x,3),{distanceInECA:ct,hoursInECA:nt,totalDgoConsInECA:ot,eca:dt}=await this.calculateECA(B,n,y),ut=L.LngLatHelper.roundPrecision(n.fo/24*(k-nt),3),it=L.LngLatHelper.roundPrecision(n.dgo/24*k+J,3);B.extend={eca:dt,distanceInECA:ct,hoursInECA:nt,totalDgoConsInECA:ot,totalDgoConsInSuspend:J},B.totalDgoCons=it,B.totalFoCons=ut<0?0:ut;const X=v().valueOf()-w,Q=((W=S==null?void 0:S.hours)==null?void 0:W.length)||1;return T==null||T.debug("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms",y==null?void 0:y.requestId,X,Q,Math.round(X/Q*1e3)/1e3),B}static async analyseCost(s,e,a,i,n={}){var b,g;const o=v().valueOf(),t=[];s.speedStep=s.speedStep||3,s.alterStep=s.alterStep??1;const r=L.LaneHelper.calculateRouteDistance(i.route);let l=0;a.forEach(m=>{const u=Math.ceil(r/m.speed/24);l=l<u?u:l}),l=l*1.3;const h=v.utc(s.etd).add(l??14,"day");let d=1;for(const m of a){const u=JSON.parse(JSON.stringify(i.route)),f=JSON.parse(JSON.stringify(i.waypoints)),c=await z.analyseInstantWithThreshed({lat:s.lat,lng:s.lng},s.etd,h,e,m,u,f,s.meteoVendor,s.speedStep,s.useMeteo,s.useRouteParam,n);c&&(await z.calculateCost(c,m,s,n),t.push(c),T==null||T.info("[%s][L%d-%d] analyse from %s to %s cost: %j",n.requestId,1,d,s.etd,h.format(),{cost:c.cost.total,hire:c.cost.hire,bunker:c.cost.bunker,distance:c.distance,hours:c.totalHrs,cp:`${m.speed}/${m.fo}/${m.dgo}`})),d++}t.sort((m,u)=>m.cost.total-u.cost.total);const y=t.at(0),w=t.at(1),M=[];if(M.push({combined:!1,speeds:[y],cost:(b=y.cost)==null?void 0:b.total}),w){const m=y.cost.cp,u=w.cost.cp,f=v(y.eta),c=v(y.etd),k=f.diff(c,"days",!0);let S=Math.ceil(k/2);S=S>7?7:S<s.alterStep?s.alterStep:S;let F=2,O={combined:!1,speeds:[w],cost:(g=w.cost)==null?void 0:g.total},x;for(;S>=s.alterStep;){const R=await z.combinedAnalyse(s,e,h,[m,u],i,S,{...n,level:F});if(O.cost>R.cost?x?(x==null?void 0:x.cost)>R.cost&&(x=R):(x=O,O=R):(!x||(x==null?void 0:x.cost)>R.cost)&&(x=R),S<=s.alterStep)break;S=Math.ceil(S/2),F+=1}M.push(O),x&&M.push(x)}const j=v().valueOf()-o;return T==null||T.info("[%s] analyse elapsed: %d ms",n==null?void 0:n.requestId,j),M.sort((m,u)=>m.cost-u.cost)}static async combinedAnalyse(s,e,a,i,n,o,t={}){t.counter=1,T==null||T.info("[%s][L%d] analyse with alternate cp in every %d days",t.requestId,t.level,o);const r=await z.alternateAnalyse(s,e,a,i,0,n,o,t),l=r.reduce((u,f)=>u+f.cost.total,0),h=r.reduce((u,f)=>u+f.cost.hire,0),d=r.reduce((u,f)=>u+f.cost.bunker,0),y=r.reduce((u,f)=>u+f.distance,0),w=r.reduce((u,f)=>u+f.totalHrs,0);T==null||T.info("[%s][L%d] cost with cpa/cpb turn: %j",t.requestId,t.level,{cost:l,hire:h,bunker:d,distance:y,hours:w});const M=await z.alternateAnalyse(s,e,a,i,1,n,o,t),I=M.reduce((u,f)=>u+f.cost.total,0),j=M.reduce((u,f)=>u+f.cost.hire,0),b=M.reduce((u,f)=>u+f.cost.bunker,0),g=M.reduce((u,f)=>u+f.distance,0),m=M.reduce((u,f)=>u+f.totalHrs,0);return T==null||T.info("[%s][L%d] cost with cpb/cpa turn: %j",t.requestId,t.level,{cost:I,hire:j,bunker:b,distance:g,hours:m}),l<I?{combined:!0,cost:Math.round(l*1e3)/1e3,speeds:r,step:o}:{combined:!0,cost:Math.round(I*1e3)/1e3,speeds:M,step:o}}static async alternateAnalyse(s,e,a,i,n,o,t,r={}){var y,w;let l=v.utc(s.etd);const h={lat:s.lat,lng:s.lng},d=[];for(;l.isBefore(a);){const M=l.clone().utc().add(t,"day"),I=JSON.parse(JSON.stringify(o.route)),j=JSON.parse(JSON.stringify(o.waypoints)),b=i[n],g=await z.analyseInstantWithThreshed(h,l.utc().format(),M,e,b,I,j,s.meteoVendor,s.speedStep,s.useMeteo,s.useRouteParam,r);g&&(await z.calculateCost(g,b,s,r),T==null||T.info("[%s][L%d-%d] analyse from %s to %s cost: %j",r.requestId,r.level,r.counter,l.utc().format(),M.utc().format(),{cost:g.cost.total,hire:g.cost.hire,bunker:g.cost.bunker,distance:g.distance,hours:g.totalHrs,cp:`${b.speed}/${b.fo}/${b.dgo}`})),r.counter=r.counter+1;const m=(w=(y=g==null?void 0:g.sample)==null?void 0:y.hours)==null?void 0:w.at(-1);if(m)h.lat=m.lat,h.lng=m.lng,l=v(m.eta),d.push(g),n=n?0:1;else break}return d}static async calculateCost(s,e,a,i={}){var n;if(s){const o=(a.addComm||0)>=1?(a.addComm||0)/100:a.addComm||0,t=Math.round((a.dailyHire||0)*(s.suspend||0)/24*1e3)/1e3,r=Math.round(s.totalHrs/24*(a.dailyHire||0)*(1-o)*1e3)/1e3+t,l=Math.round(s.totalFoCons*(a.priceFO||0)*1e3)/1e3,h=Math.round((s.totalDgoCons+(((n=s.extend)==null?void 0:n.totalDgoConsInECA)||0))*(a.priceDGO||0)*1e3)/1e3;s.cost={total:Math.round((r+l+h)*1e3)/1e3,hire:Math.round(r*1e3)/1e3,suspendHire:t,bunker:Math.round((l+h)*1e3)/1e3,cp:e}}return s}static async calculateECA(s,e,a={}){var r,l,h,d;const i=await L.LaneHelper.intersectInECA((s==null?void 0:s.route)||[]);let n=0,o=0,t=0;(l=(r=s==null?void 0:s.sample)==null?void 0:r.wps)==null||l.forEach(y=>{y.positionTime=v.utc(y.etd||y.eta).unix()});for(const y of i){n+=y.distance;const w=await L.LaneHelper.deadReckoningTime((h=y.waypoints)==null?void 0:h.at(0),s.sample.all||s.sample.wps),M=await L.LaneHelper.deadReckoningTime((d=y.waypoints)==null?void 0:d.at(-1),s.sample.all||s.sample.wps);y.in=w,y.out=M,y.totalHrs=L.LngLatHelper.roundPrecision((M.positionTime-w.positionTime)/3600,3),y.totalDgoCons=L.LngLatHelper.roundPrecision(e.fo/24*y.totalHrs,3),o+=y.totalHrs,t+=y.totalDgoCons}return n=L.LngLatHelper.roundPrecision(n,3),o=L.LngLatHelper.roundPrecision(o,3),t=L.LngLatHelper.roundPrecision(t,3),{distanceInECA:n,hoursInECA:o,totalDgoConsInECA:t,eca:i}}static async mergeSpeeds(s,e={}){var m,u;const a={hours:[],wps:[],days:[]},i=s.reduce((f,c)=>f+c.distance,0),n=s.reduce((f,c)=>{var k;return f+(((k=c.extend)==null?void 0:k.distanceInECA)||0)},0),o=s.reduce((f,c)=>f+c.totalHrs,0),t=s.reduce((f,c)=>{var k;return f+(((k=c.extend)==null?void 0:k.hoursInECA)||0)},0),r=s.reduce((f,c)=>{var k;return f+(((k=c.extend)==null?void 0:k.totalDgoConsInECA)||0)},0),l=s.reduce((f,c)=>f+c.wxFactor*c.totalHrs/o,0),h=s.reduce((f,c)=>f+c.cFactor*c.totalHrs/o,0),d=s.reduce((f,c)=>f+c.totalFoCons,0),y=s.reduce((f,c)=>f+c.totalDgoCons,0),w=s.reduce((f,c)=>f+c.cost.total,0),M=s.reduce((f,c)=>f+c.cost.hire,0),I=s.reduce((f,c)=>f+c.cost.bunker,0),j=[],b=[];let g;for(const f of s){b.push(...((m=f.extend)==null?void 0:m.eca)||[]);const c=f.sample.hours,k=f.sample.wps,S=f.sample.days,F=c.at(0);g&&(F.distanceFromPrevious=g.distanceFromPrevious,F.distanceFromStart=g.distanceFromStart,c.forEach((E,H)=>{H&&(E.distanceFromStart=E.distanceFromStart+g.distanceFromStart)}),k.at(0).distanceFromPrevious=g.distanceFromPrevious,k.at(0).distanceFromStart=g.distanceFromStart,k.forEach((E,H)=>{H&&(E.distanceFromStart=E.distanceFromStart+g.distanceFromStart)}),S.at(0).distanceFromPrevious=g.distanceFromPrevious,S.at(0).distanceFromStart=g.distanceFromStart,S.forEach((E,H)=>{H&&(E.distanceFromStart=E.distanceFromStart+g.distanceFromStart)})),F.cp=f.cost.cp;const O=[f.etd,f.eta],x=j.findIndex(E=>E.id===F.cp.id);x===-1?(F.cp.segment=[O],j.push(F.cp)):j[x].segment.push(O),c.forEach(E=>{var V;((V=a.hours)==null?void 0:V.findIndex(B=>B.eta===E.eta))===-1&&a.hours.push(E)}),k.forEach(E=>{var V;((V=a.wps)==null?void 0:V.findIndex(B=>B.eta===E.eta))===-1&&a.wps.push(E)}),S.forEach(E=>{var V;((V=a==null?void 0:a.days)==null?void 0:V.findIndex(B=>B.eta===E.eta))===-1&&a.days.push(E)});const R=(u=a.wps)==null?void 0:u.findIndex(E=>E.eta===F.eta);R===-1?a.wps.push(F):a.wps[R]=F,g=c.at(-1)}return a.wps.sort((f,c)=>{v(f.etd).unix()-v(c.etd).unix()}),a.wps.forEach((f,c)=>{const k=a.wps[c-1];if(k){const S=f.distanceFromStart-(k.distanceFromStart||0),F=v(f.eta||f.etd).diff(v(k.etd||k.eta),"hour",!0),O=Math.round(S/F*100)/100;f.avgSpd=O;const x=L.LaneHelper.calculateBearing(k,f);k.bearing=x}}),{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(o*1e3)/1e3,avgSpeed:Math.round(i/o*1e3)/1e3,wxFactor:Math.round(l*1e3)/1e3,cFactor:Math.round(h*1e3)/1e3,totalFoCons:Math.round(d*1e3)/1e3,totalDgoCons:Math.round(y*1e3)/1e3,cost:{total:Math.round(w*1e3)/1e3,hire:Math.round(M*1e3)/1e3,bunker:Math.round(I*1e3)/1e3},extend:{cps:j,eca:b,distanceInECA:Math.round(n*1e3)/1e3,hoursInECA:Math.round(t*1e3)/1e3,totalDgoConsInECA:Math.round(r*1e3)/1e3,speeds:s}}}}Y.AISImpl=G,Y.AlertHelper=ft,Y.AlertLevel=ht,Y.HifleetImpl=gt,Y.LoadCondition=yt,Y.MyShipImpl=wt,Y.MyVesselImpl=bt,Y.ShipxyImpl=vt,Y.SpeedHelper=z,Y.SpeedLabel=pt,Y.VesselTag=mt,Y.alertHelper=It,Object.defineProperty(Y,Symbol.toStringTag,{value:"Module"})});
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@idm-plugin/vessel",
3
3
  "private": false,
4
- "version": "3.4.6",
4
+ "version": "3.4.7",
5
5
  "description": "idm plugin for vessel",
6
6
  "type": "module",
7
7
  "keywords": [