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