@idm-plugin/vessel 1.6.3 → 1.6.5

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(T,D){typeof exports=="object"&&typeof module<"u"?D(exports,require("got"),require("@log4js-node/log4js-api"),require("moment"),require("@idm-plugin/geo"),require("@idm-plugin/meteo2"),require("@idm-plugin/meteo")):typeof define=="function"&&define.amd?define(["exports","got","@log4js-node/log4js-api","moment","@idm-plugin/geo","@idm-plugin/meteo2","@idm-plugin/meteo"],D):(T=typeof globalThis<"u"?globalThis:T||self,D(T["idm-plugin-rabbitmq"]={},T.got,T["@log4js-node/log4js-api"],T.moment,T["@idm-plugin/geo"],T["@idm-plugin/meteo2"],T["@idm-plugin/meteo"]))})(this,function(T,D,K,w,R,X,$){"use strict";var mt=Object.defineProperty;var yt=(T,D,K)=>D in T?mt(T,D,{enumerable:!0,configurable:!0,writable:!0,value:K}):T[D]=K;var _=(T,D,K)=>(yt(T,typeof D!="symbol"?D+"":D,K),K);let M;try{M=K.getLogger("vessel")}catch{}finally{}class G{parseStatus(e){let t,o;switch(e){case 0:t="在航(主机推动)",o="The engine is in use";break;case 1:t="锚泊",o="Anchored";break;case 2:t="失控",o="Not operated";break;case 3:t="操纵受限",o="Limited airworthiness";break;case 4:t="吃水受限",o="Limited by ship's draft";break;case 5:t="靠泊",o="Mooring";break;case 6:t="搁浅",o="Stranded";break;case 7:t="捕捞作业",o="Engaged in fishing";break;case 8:t="靠帆船提供动力",o="Sailing";break;default:t="未定义",o="Undefined"}return{labelCn:t,labelEn:o}}}class rt extends G{constructor(t,o){super();_(this,"clientId");_(this,"clientSecret");_(this,"token");this.clientId=t,this.clientSecret=o}async authToken(t={}){const o="https://svc.data.myvessel.cn/ada/oauth/token",i={searchParams:{client_id:this.clientId,client_secret:this.clientSecret,grant_type:"client_credentials"}},a=await D.post(o,i).json();M==null||M.info("[%s] fetch access token from: %s - %j",t.requestId,o,a),a.error||(this.token={accessToken:a.access_token,tokenType:a.token_type,expiresIn:a.expires_in,scope:a.scope,jti:a.jti,issuedAt:w().utc().format()})}async realTimePosition(t,o={}){var l,y,m;(!this.token||w().diff(w(this.token.issuedAt),"seconds")>((l=this.token)==null?void 0:l.expiresIn)-300)&&await this.authToken(o);const i="https://svc.data.myvessel.cn/sdc/v1/vessels/status/location/unit",a={headers:{Authorization:`${(y=this.token)==null?void 0:y.tokenType} ${(m=this.token)==null?void 0:m.accessToken}`},searchParams:{mmsi:t}};M==null||M.info("[%s] fetch realtime position from: %s - %j",o.requestId,i,a);const n=await D.get(i,a).json();if(n.code)return M==null||M.warn("[%s] fetch realtime position failed: %j",o.requestId,i,{message:n.message,status:n.status,code:n.code}),n;const s=n.data;for(const h in s)!isNaN(s[h])&&Number(s[h])!==1/0&&(s[h]=Number(s[h]));const c=w(`${s.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return{mmsi:s.mmsi,name:s.vesselName,imo:s.imo,callSign:s.callsign,lat:s.lat,lng:s.lon,length:s.length,width:s.width,draught:s.currDraught,sog:s.sog,cog:s.cog,hdg:s.hdg,rot:s.rot,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(s.eta)?w.utc(s.eta).format():void 0,destination:s.dest,positionTime:c.unix(),status:s.status,labelCn:s.statusNameCn,labelEn:s.statusNameEn,method:"position",vendor:"myVessel",utc:c.utc().format()}}async trajectory(t,o,i,a,n=!0,s={}){(!this.token||w().diff(w(this.token.issuedAt),"seconds")>this.token.expiresIn-300)&&await this.authToken(s);const c=await this.realTimePosition(t,s),r=w(o),l=w(i),y=[];for(;l.diff(r,"day",!0)>30;)await this.trajectoryIn30Day(t,r,r.clone().add(30,"day"),c,a,y,s),r.add(30,"day");return await this.trajectoryIn30Day(t,r,l,c,a,y,s),y}async trajectoryIn30Day(t,o,i,a,n,s,c={}){var u,I,j,f,g;const r="https://svc.data.myvessel.cn/sdc/v1/vessels/status/track",l={headers:{Authorization:`${(u=this.token)==null?void 0:u.tokenType} ${(I=this.token)==null?void 0:I.accessToken}`},json:{mmsi:t,startTime:o.utcOffset(8).format("YYYY-MM-DD HH:mm:ss"),endTime:i.utcOffset(8).format("YYYY-MM-DD HH:mm:ss")}};M==null||M.info("[%s] fetch trajectory from: %s - %j",c.requestId,r,l);const y=await D.post(r,l).json();if(y.code)return M==null||M.warn("[%s] fetch trajectory failed: %j",c.requestId,r,{message:y.message,status:y.status,code:y.code}),y;let m=-1;const h=w(`${(f=(j=y.data)==null?void 0:j[0])==null?void 0:f.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return(g=y.data)==null||g.forEach(d=>{for(const x in d)!isNaN(d[x])&&Number(d[x])!==1/0&&(d[x]=Number(d[x]));const b=w(`${d.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00"),q=d.status,{labelCn:v,labelEn:k}=this.parseStatus(q),S={mmsi:d.mmsi,imo:a==null?void 0:a.imo,lat:d.lat,lng:d.lon,sog:d.sog,cog:d.cog,hdg:d.hdg,draught:d.draught,status:q,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(d.eta)?w(`${d.eta} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00").utc().format():void 0,destination:d.dest,positionTime:b.unix(),labelCn:v,labelEn:k,method:"trajectory",vendor:"myVessel",utc:b.utc().format()},N=Math.floor(b.diff(h,"minute",!0)/(n||1));N!==m&&(m=N,s.push(S))}),s}}class ct extends G{constructor(t){super();_(this,"token");this.token=t}async realTimePosition(t,o={}){const i="https://api.hifleet.com/position/position/get/token",a={searchParams:{mmsi:t,usertoken:this.token}},n=await D.post(i,a).json();M==null||M.info("[%s] fetch realtime position from: %s - %j",o.requestId,i,a);const s=n==null?void 0:n.list;if(!s)return M==null||M.warn("[%s] fetch realtime position failed: %j",o.requestId,i,n),n;for(const h in s)!isNaN(s[h])&&Number(s[h])!==1/0&&(s[h]=Number(s[h]));s.status=s.sp>3?0:1;const c=s.status,{labelCn:r,labelEn:l}=this.parseStatus(c),y=w(`${s.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return{mmsi:s.m,name:s.n,imo:s.imonumber,callSign:s.callsign,lat:Math.round(s.la/60*1e5)/1e5,lng:Math.round(s.lo/60*1e5)/1e5,length:s.l,width:s.w,draught:s.draught,sog:s.sp,cog:s.co,hdg:s.h,rot:isNaN(s.rot)?0:s.rot,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(s.eta)?w.utc(s.eta).format():void 0,destination:s.destination,positionTime:y.unix(),utc:y.utc().format(),status:c,labelCn:r,labelEn:l,method:"position",vendor:"hifleet"}}async search(t,o={}){let i="https://www.hifleet.com/hifleetapi/searchVesselOL.do";const a={searchParams:{keyword:t},headers:{Referer:"https://www.hifleet.com",Origin:"https://www.hifleet.com",Host:"www.hifleet.com"}};let n=await D.post(i,a).json();M==null||M.info("[%s] fetch vessel props from: %s - %j",o.requestId,i,a),n instanceof Array&&(n=n[0]);for(const c in n)!isNaN(n[c])&&Number(n[c])!==1/0&&(n[c]=Number(n[c]));const s={mmsi:n.m,name:n.n,imo:n.i,callSign:n.c,length:n.l,breadth:n.b,draught:n.dr,type:n.t};return i="https://www.hifleet.com/hifleetapi/sameShipSearch.do",n=await D.post(i,a).json(),M==null||M.info("[%s] search vessel dead weight from: %s - %j",o.requestId,i,a),n instanceof Array&&(n=n[0]),n&&(s.deadweight=Number(n.dwt)),s}async suggest(t,o={}){const i="https://www.hifleet.com/hifleetapi/getShipSuggest.do",a={searchParams:{q:t},headers:{Referer:"https://www.hifleet.com",Origin:"https://www.hifleet.com",Host:"www.hifleet.com"}},n=await D.post(i,a).json();M==null||M.info("[%s] suggest vessel props from: %s - %j",o.requestId,i,a);const s=[];for(const c of n)s.push({mmsi:!c.mmsi||isNaN(c.mmsi)?null:Number(c.mmsi),name:c.name,callSign:c.callsign,imo:!c.imo||isNaN(c.imo)?null:Number(c.imo),score:c._score});return s.sort((c,r)=>r.score-c.score),s}async trajectory(t,o,i,a,n=!0,s={}){var d,b,q;const c=await this.realTimePosition(t,s);let r=w(o);const l=w(i),y=w();if(n){let v=l.diff(r,"d",!0);v<0?r=l.clone().subtract(40,"d"):v<30?r.subtract(10,"d"):v<60?r.subtract(5,"d"):r=l.clone().subtract(80,"d"),v=y.diff(l,"d",!0),l.add(v>10?240:v*24,"h")}const m={searchParams:{endtime:l.utcOffset("+8:00").format("YYYY-MM-DD HH:mm:ss"),starttime:r.utcOffset("+8:00").format("YYYY-MM-DD HH:mm:ss"),mmsi:t,usertoken:this.token}},h="https://api.hifleet.com/position/trajectory/nocompressed/withstatic/token",u=await D.get(h,m).json();M==null||M.info("[%s] fetch trajectory from: %s - %j",s.requestId,h,m);let I;u&&(I=((b=(d=u.ships)==null?void 0:d.offors)==null?void 0:b.ship)||[],I.length||M==null||M.warn("[%s] fetch trajectory failed: %j",s.requestId,u));const j=[];let f=-1;const g=w(`${(q=I==null?void 0:I[0])==null?void 0:q.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");for(const v of I){for(const L in v)!isNaN(v[L])&&Number(v[L])!==1/0&&(v[L]=Number(v[L]));const k=w(`${v.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");v.status=v.sp>4?0:1;const{labelEn:S,labelCn:N}=this.parseStatus(v.status),x={mmsi:v.m,name:v.n,imo:c==null?void 0:c.imo,lat:v.la,lng:v.lo,draught:v.draught,sog:v.sp,cog:v.co,hdg:v.hdg,positionTime:k.unix(),utc:k.utc().format(),status:v.status,labelCn:N,labelEn:S,method:"trajectory",vendor:"hifleet"},W=Math.floor(k.diff(g,"minute",!0)/(a||1));W!==f&&(f=W,j.push(x))}return j}}class dt extends G{constructor(t){super();_(this,"token");this.token=t}async realTimePosition(t,o={}){const i={searchParams:{id:t,k:this.token,enc:1}},a="https://api.shipxy.com/apicall/GetSingleShip",n=await D.get(a,i).json();if(M==null||M.info("[%s] fetch realtime position from: %s - %j",o.requestId,a,i),(n==null?void 0:n.status)!==0)return n;const s=n.data[0];for(const m in s)!isNaN(s[m])&&Number(s[m])!==1/0&&(s[m]=Number(s[m]));const{labelCn:c,labelEn:r}=await this.parseStatus(s.navistat),l=w.unix(s.lasttime);return{mmsi:s.ShipID,name:s.name,imo:s.imo,callSign:s.callsign,lat:Math.round(s.lat/1e6*1e5)/1e5,lng:Math.round(s.lon/1e6*1e5)/1e5,length:Math.round(s.length/10*100)/100,width:Math.round(s.width/10*100)/100,draught:Math.round(s.draught/1e3*100)/100,sog:Math.round(s.sog*3600/1e3/1852*100)/100,cog:Math.round(s.cog/100*100)/100,hdg:Math.round(s.hdg/100*100)/100,rot:Math.round(s.rot/100*100)/100,positionTime:s.lasttime,utc:l.utc().format(),status:s.navistat,labelEn:r,labelCn:c,method:"position",vendor:"shipxy"}}async trajectory(t,o,i,a,n=!0,s={}){var g;const c=await this.realTimePosition(t,s),r=w(o),l=w(i),y="https://api.shipxy.com/apicall/GetShipTrack",m={searchParams:{id:t,k:this.token,enc:1,cut:0,btm:r.unix(),etm:l.unix()}},h=await D.get(y,m).json();if(M==null||M.info("[%s] fetch trajectory from: %s - %j",s.requestId,y,m),(h==null?void 0:h.status)!==0)return h;const u=h==null?void 0:h.points,I=[],j=w.unix((g=u[0])==null?void 0:g.utc);let f=-1;for(const d of u){const b=w.unix(d.utc),q={imo:c==null?void 0:c.imo,mmsi:t,sog:Math.round(d.sog*3600/1e3/1852*100)/100,cog:Math.round(d.cog/100*100)/100,lat:Math.round(d.lat/1e6*1e5)/1e5,lng:Math.round(d.lon/1e6*1e5)/1e5,positionTime:b.unix(),utc:b.utc().format(),method:"trajectory",vendor:"shipxy"},v=Math.floor(b.diff(j,"minute",!0)/(a||1));v!==f&&(f=v,I.push(q))}return I}}class ut extends G{constructor(t){super();_(this,"token");this.token=t}async getShipId(t,o={}){const i={headers:{appKey:this.token},json:{mmsiList:t}},a="https://api3.myships.com/sp/ships/getShipIdByMMSI",n=await D.post(a,i).json();return M==null||M.info("[%s] fetch ship id from: %s - %j",o.requestId,a,i),n.code!=="0"?n:n.data[0].shipId}async getShipInfo(t,o={}){const i={headers:{appKey:this.token},json:{shipId:t}},a="https://api3.myships.com/sp/ships/aissta",n=await D.post(a,i).json();if(M==null||M.info("[%s] fetch ship info from: %s - %j",o.requestId,a,i),n.code!=="0")return n;const s=n.data;let c=s.imo;return t==="407170"&&(c="9198379",M==null||M.warn("[%s] ship(%s) imo error: %s, should be %s",o.requestId,t,s.imo,c)),{mmsi:s.mmsi,name:s.shipnameEn,imo:c,callSign:s.callSign,length:s.length,width:s.breadth,draught:(s.draught||100)/10}}async realTimePosition(t,o={}){const i=await this.getShipId(t,o),a=await this.getShipInfo(i,o),n={headers:{appKey:this.token},json:{shipId:i}},s="https://api3.myships.com/sp/ships/position/latest",c=await D.post(s,n).json();M==null||M.info("[%s] fetch realtime position from: %s - %j",o.requestId,s,n);const r=c.data[0];for(const u in r)!isNaN(r[u])&&Number(r[u])!==1/0&&(r[u]=Number(r[u]));const{labelCn:l,labelEn:y}=await this.parseStatus(r.aisNavStatus),m=w.unix(r.posTime);return{...a,mmsi:t,lat:Math.round(r.lat/1e4/60*1e5)/1e5,lng:Math.round(r.lon/1e4/60*1e5)/1e5,sog:Math.round(r.sog/10*100)/100,cog:Math.round(r.cog/10*100)/100,hdg:Math.round(r.heading*100)/100,rot:Math.round(r.rot*100)/100,positionTime:r.posTime,utc:m.utc().format(),status:r.aisNavStatus,labelEn:y,labelCn:l,method:"position",vendor:"myship"}}async trajectory(t,o,i,a,n=!0,s={}){const c=w(o),r=w(i),l=await this.getShipId(t),y=await this.getShipInfo(l),m=[];for(;r.diff(c,"day",!0)>30;)await this.trajectoryIn30Day(l,c.unix(),c.add(30,"day").unix(),y,t,a,m);return await this.trajectoryIn30Day(l,c.unix(),r.unix(),y,t,a,m),m}async trajectoryIn30Day(t,o,i,a,n,s,c,r={}){var j;const l={headers:{appKey:this.token},json:{shipId:t,startTime:o,endTime:i}},y="https://api3.myships.com/sp/ships/position/history",m=await D.post(y,l).json();if(M==null||M.info("[%s] fetch trajectory from: %s - %j",r.requestId,y,l),m.code!=="0")return M==null||M.warn("[%s] invoke myship trajectory failed: %j",r.requestId,m),m;const h=m.data;for(const f in h)!isNaN(h[f])&&Number(h[f])!==1/0&&(h[f]=Number(h[f]));const u=w.unix((j=h[0])==null?void 0:j.posTime);let I=-1;for(const f of h){const g=w.unix(f.posTime),d={imo:a==null?void 0:a.imo,mmsi:n,lat:Math.round(f.lat/1e4/60*1e5)/1e5,lng:Math.round(f.lon/1e4/60*1e5)/1e5,sog:Math.round(f.sog/10*100)/100,cog:Math.round(f.cog/10*100)/100,hdg:Math.round(f.heading*100)/100,rot:Math.round(f.rot*100)/100,positionTime:g.unix(),utc:g.utc().format(),method:"trajectory",vendor:"myship"},b=Math.floor(g.diff(u,"minute",!0)/(s||1));b!==I&&(I=b,c.push(d))}return c}}let V;try{V=K.getLogger("vessel")}catch{}finally{}var tt=(Y=>(Y.NOTICE="NOTICE",Y.WARN="WARN",Y.HEAVY="HEAVY",Y.SEVERE="SEVERE",Y.ERROR="ERROR",Y.FATAL="FATAL",Y))(tt||{});class et{parsePrinciple(e,t={}){var s,c,r;V==null||V.info("[%s] parse rule: %s",t.requestId,e);const o=new RegExp("(?<=\\[)(.+)(?=])","g"),i=e.match(o)?(s=e.match(o))==null?void 0:s[0]:void 0,a=i==null?void 0:i.split(";");if(!a)return;const n={};for(let l=0;l<(a==null?void 0:a.length);l++){const y=(r=(c=a[l].match(o))==null?void 0:c[0])==null?void 0:r.split("],");if(l===0&&!y)n.scope=a[0];else if(y)for(let m=0,h=y.length;m<h;m++){const u=this.parseRule(y[m]);u&&(n[u.level]?u.key?n[u.level][u==null?void 0:u.key]=u:n[u.level]=u:u.key?n[u.level]={[u==null?void 0:u.key]:u}:n[u.level]=u)}}return n}parseRule(e,t={}){var n;V==null||V.info("[%s] parse rule: %s",t.requestId,e),e=e.startsWith("[")?e:`[${e}`,e=e.endsWith("]")?e:`${e}]`;const o=new RegExp("(?<=\\[)(.+?)(?=])","g"),i=(n=e==null?void 0:e.match(o))==null?void 0:n[0],a=i==null?void 0:i.split(",");if(a)return{operator:a[0],number:Number.isNaN(Number(a[1]))?a[1]:Number(a[1]),level:a[2],time:Number(a[3]),key:a[4]}}checkWeather(e,t,o={}){var u,I,j,f,g,d,b,q,v,k,S,N,x,W,L;let i=0,a=0,n=0,s=0;const c=Math.round(((I=(u=t==null?void 0:t.SEVERE)==null?void 0:u.sigWave)==null?void 0:I.number)*1.6*100)/100,r=(f=(j=t==null?void 0:t.SEVERE)==null?void 0:j.sigWave)==null?void 0:f.number,l=(d=(g=t==null?void 0:t.HEAVY)==null?void 0:g.sigWave)==null?void 0:d.number,y=Math.round((((q=(b=t==null?void 0:t.SEVERE)==null?void 0:b.wind)==null?void 0:q.number)+2)*100)/100,m=(k=(v=t==null?void 0:t.SEVERE)==null?void 0:v.wind)==null?void 0:k.number,h=(N=(S=t==null?void 0:t.HEAVY)==null?void 0:S.wind)==null?void 0:N.number;for(let B=0;B<(e==null?void 0:e.length);B++){const C=e[B],P=(W=(x=C==null?void 0:C.meteo)==null?void 0:x.wave)==null?void 0:W.sig,A=(L=C==null?void 0:C.meteo)==null?void 0:L.wind,Z=B?w(C.eta).diff(w(e[B-1].eta),"hour",!0):0;s=Z>s?Z:s,V==null||V.info("[%s] check sig.wave: %j",o.requestId,{...P,dgThd4Wv:c,svThd4Wv:r,hvThd4Wv:l}),(P==null?void 0:P.height)>=c?C.isDangerous=!0:(P==null?void 0:P.height)>=r?C.isSevere=!0:(P==null?void 0:P.height)>=l&&(C.isHeavy=!0),V==null||V.info("[%s] check wind: %j",o.requestId,{...A,dgThd4Wd:y,svThd4Wd:m,hvThd4Wd:h}),(A==null?void 0:A.scale)>=y?(C.isDangerous=!0,delete C.isSevere,delete C.isHeavy):(A==null?void 0:A.scale)>m?(C.isDangerous||(C.isSevere=!0),delete C.isHeavy):(A==null?void 0:A.scale)===h&&!C.isDangerous&&!C.isSevere&&(C.isHeavy=!0),i+=C.isDangerous?Z:0,a+=C.isSevere?Z:0,n+=C.isHeavy?Z:0}return i=Math.round(i*100)/100,a=Math.round(a*100)/100,n=Math.round(n*100)/100,s=Math.round(s),{sample:e,dangerous:i,severe:a,heavy:n,step:s<3?3:s,wind:{dgThd4Wd:y,svThd4Wd:m,hvThd4Wd:h},sig:{dgThd4Wv:c,svThd4Wv:r,hvThd4Wv:l}}}}const ht=new et;let p;try{p=K.getLogger("vessel")}catch{}finally{}const lt=new X.MeteoHelper2("",!0);var st=(Y=>(Y.common="common",Y.container="container",Y.tugs="tugs",Y))(st||{}),at=(Y=>(Y.Ballast="Ballast",Y.Laden="Laden",Y))(at||{}),ot=(Y=>(Y.Cp="CP",Y.Perf="Basis",Y.Instruct="Other",Y))(ot||{});class E{static blockCoefficient(e,t,o,i){let a=Math.round(e/(t*o*i)*100)/100;a=a<.55?.55:a>.85?.85:a;const n=[.55,.6,.65,.7,.75,.8,.85],s=n.map(c=>Math.abs(c-a));return n[s.indexOf(Math.min(...s))]}static froudeNumber(e,t,o=9.8){let i=Math.round(Math.sqrt(e*e/(o*t))*100)/100;return i=i<.05?.05:i>.3?.3:i,i}static amendFactor(e,t,o){const i={.55:[1.7,-1.4,-7.4],.6:[2.2,-2.5,-9.7],.65:[2.6,-3.7,-11.6],.7:[3.1,-5.3,-12.4],.75:[2.4,-10.6,-9.5],.8:[2.6,-13.1,-15.1],.85:[3.1,-18.7,28]};let n={.55:[1.7,-1.4,-7.4],.6:[2.2,-2.5,-9.7],.65:[2.6,-3.7,-11.6],.7:[3.1,-5.3,-12.4],.75:[2.6,-12.5,-13.5],.8:[3,-16.3,-21.6],.85:[3.4,-20.9,31.8]}[e];return o==="Laden"&&(n=i[e]),n[0]+n[1]*t+n[2]*Math.pow(t,2)}static directionFactor(e,t=0){let o;return e>30&&e<=60?o=(1.7-.03*Math.pow(t-4,2))/2:e>60&&e<=150?o=(.9-.06*Math.pow(t-6,2))/2:e>150&&e<=180?o=(.4-.03*Math.pow(t-8,2))/2:o=1,Math.round(o*1e5)/1e5}static vesselTagFactor(e,t,o,i=0){i=i>6?i-.9*(i-6):i;let a;return o==="container"?a=.7*i+Math.pow(i,6.5)/(22*Math.pow(e,2/3)):t==="Ballast"?a=.7*i+Math.pow(i,6.5)/(2.7*Math.pow(e,2/3)):a=.5*i+Math.pow(i,6.5)/(2.7*Math.pow(e,2/3)),a}static waveHeightFactor(e,t){e=e<0?.2:e,e=e>6?e-.9*(e-6):e,e=e>9?9:e;let o;return t>30&&t<=60?o=-.6:t>60&&t<=90?o=-.4:t>90&&t<=120?o=e<3?.4:-.3:t>120&&t<=150?o=e<3?.6:-.5:t>150&&t<=180?o=e<3?.7:-.6:o=-.7,Math.round(o*(.144*Math.pow(e,2)+.178*e)*1e4)/1e4}static assembleProperties(e,t,o,i){var m;const a=e.lbp??e.length??e.lengthOverall??198.9642,n=e.draught??8,s=e.breadthMoulded??e.breadth??e.breadthExtreme??32.4572,c=e.deadweight??67035.7773,r=((m=e==null?void 0:e.type)==null?void 0:m.toLowerCase())||"common";return{tag:r.indexOf("container")>-1?"container":r.indexOf("tugs")>-1?"tugs":"common",lbp:a,loadCondition:t,draught:n,breadthMoulded:s,displacement:Math.round((c/1.025+n*s*a*.7)*1e4)/1e4,speed:Math.round((o??14.1382)*1852/3600*1e4)/1e4,bearing:i||90}}static async speedLoseAt(e,t,o,i="",a=2,n=!0,s=!1,c={}){let r;if(t.velocity&&s&&(e.speed=R.LngLatHelper.roundPrecision(t.velocity*1852/3600,6)),n){let l;if(c.meteo2)try{const u=await lt.spotForecast(t.lat,t.lng,o.utc().format(),!1,!1,!0,c),[I]=$.Meteo2Assist.pickHourly(u,o);l=$.Meteo2Assist.toLegacy(I)}catch(u){p.warn("[%s] meteo2 spot(%j) forecast failed: %s",c.requestId,{...t,eta:o.utc().format()},u)}else l=await X.MeteoHelper.queryPointFactor(t.lng,t.lat,o.valueOf(),"wind,wave,current,watertemp",i,c);const y=E.weatherFactor(e,l),m=E.currentFactor(e.bearing,l==null?void 0:l.current,a),h=Math.round((e.speed*1.943844+y+m)*100)/100;r={meteo:{...l},wxFactor:y,cFactor:m,speed:t.velocity&&s?t.velocity:h<0?1:h,eta:o.utc().format("YYYY-MM-DDTHH:mm[Z]"),etd:o.utc().format("YYYY-MM-DDTHH:mm[Z]")}}else r={wxFactor:0,cFactor:0,speed:t.velocity&&s?t.velocity:Math.round((e.speed*1.943844+0+0)*100)/100,eta:o.utc().format("YYYY-MM-DDTHH:mm[Z]"),etd:o.utc().format("YYYY-MM-DDTHH:mm[Z]")};return delete t.meteo,delete t.wxFactor,delete t.cFactor,delete t.speed,delete t.etd,{...r,...t}}static async speedLoseInHoursStep(e,t,o,i,a,n,s="",c=!0,r=!1,l={}){t.utc();const y=t.clone().add(14,"days"),m=[],h=[];let u=0,I=0,j,f;for(let g=0;g<n.length-1;g++){let d=n[g];d.distanceFromStart=Math.round((a+I)*1e4)/1e4;const b=n[g+1];if(e.bearing=R.LaneHelper.calculateBearing(d,b,!b.gcToPrevious),d.bearing=e.bearing,d.suspend&&r){d.eta=d.eta||t.format("YYYY-MM-DDTHH:mm[Z]"),d.elapsed=d.elapsed??0;const k=d.suspend-d.elapsed;if(i-u>k)i=i-u-k,t.add(k,"hour"),d.elapsed=d.suspend;else{const S=i-u;d.elapsed+=S,t.add(S,"hour"),i=0}if(p==null||p.info(`[%s] suspend ${d.elapsed} hours at %j, and remain ${i} hours need to go...`,l.requestId,d),i===0)return d.distanceFromPrevious=I,{etd:t,from:f||d,to:d,next:n.filter(S=>S),wps:m,days:h}}else d.suspend=0;c=t.isAfter(y)?!1:c,d=await E.speedLoseAt(e,d,t,s,0,c,r,l),f=f||d,d.important&&m.push(d),t.isSameOrAfter(o)&&(h.push(d),o.add(24,"hour"));const q=R.LaneHelper.calculateDistance(d,b,!b.gcToPrevious);let v=Math.ceil(q/f.speed*1e4)/1e4;if(u+v<i){if(u+=v,t.add(v,"hour"),delete n[g],p==null||p.debug(`[%s] go to %j from %j with ${q}nm, and cost ${v} hours`,l.requestId,{lat:b.lat,lng:b.lng},{lat:f.lat,lng:f.lng,etd:f.etd}),I+=q,n.filter(k=>k).length<=1){j=b,j.eta=t.format("YYYY-MM-DDTHH:mm[Z]"),j.distanceFromPrevious=q,j.distanceFromStart=Math.round((a+I)*1e4)/1e4,m.push(j),delete n[g+1];break}}else{v=i-u,t.add(v,"hour");const k=R.LngLatHelper.roundPrecision(f.speed*v,4);j=R.LaneHelper.calculateCoordinate(d,e.bearing,k,"nauticalmiles",!b.gcToPrevious),j.eta=t.format("YYYY-MM-DDTHH:mm[Z]"),n[g]=j,p==null||p.debug(`[%s] go to %j from %j with ${k}nm, and cost ${v} hours`,l.requestId,{lat:j.lat,lng:j.lng},{lat:d.lat,lng:d.lng,etd:d.etd}),I+=k,j.distanceFromPrevious=Math.round(I*1e4)/1e4,j.distanceFromStart=Math.round((a+I)*1e4)/1e4;break}}return{etd:t,from:f,to:j,next:n.filter(g=>g),wps:m,days:h}}static currentFactor(e,t,o=0){const i=(e-(t==null?void 0:t.degree)||0)/180*Math.PI;if(Math.abs(i)===Math.PI/2)return 0;let a=((t==null?void 0:t.kts)||0)*Math.cos(i);return o&2?a=Math.ceil(a*100)/100:o&1?a=Math.floor(a*100)/100:a=Math.round(a*100)/100,Math.abs(a)>5?0:a}static weatherFactor(e,t){var y,m,h,u,I,j,f;p==null||p.debug("calculate weather factor via: %j",{...e,...t});const o=E.blockCoefficient(e.displacement,e.lbp,e.breadthMoulded,e.draught),i=E.froudeNumber(e.speed,e.lbp),a=E.amendFactor(o,i,e.loadCondition);let n=Math.abs(e.bearing%360-(((y=t==null?void 0:t.wind)==null?void 0:y.degree)%360||0));n=n>180?360-n:n;const s=E.directionFactor(n,(m=t==null?void 0:t.wind)==null?void 0:m.scale),c=E.vesselTagFactor(e.displacement,e.loadCondition,e.tag,(h=t==null?void 0:t.wind)==null?void 0:h.scale);let r=s*a*c/100*e.speed;r=Math.round(r*1.943844*1e4)/1e4*-1,e.tag==="tugs"&&Math.abs(r)>1&&(r=r/(Math.abs(Math.round(r))+1)),p==null||p.debug("wind wx factor = %d",r),n=Math.abs(e.bearing%360-(((I=(u=t==null?void 0:t.wave)==null?void 0:u.sig)==null?void 0:I.degree)%360||0));const l=E.waveHeightFactor(((f=(j=t==null?void 0:t.wave)==null?void 0:j.sig)==null?void 0:f.height)??1,n);return p==null||p.debug("wave wx factor = %d",l),r=r*.4+l,p==null||p.debug("weather factor = %d",r),r=Math.abs(r)>4?4*(Math.abs(r)/r)+Math.abs(r)/r*(Math.abs(r)-4)*.1:r,Math.round((r||0)*100)/100}static async analyseInstant(e,t,o,i,a,n="",s=0,c=!0,r=!1,l={}){var Z,z,U,Q,J;const y=w().valueOf();e.lng=R.LngLatHelper.convertToStdLng(e.lng);const{route:m,waypoints:h}=a.points,u=R.LaneHelper.calculateSubRoute(e,m);if(((Z=u[0])==null?void 0:Z.length)<=1)return;const{v0:I,label:j}=e.sog?{v0:e.sog,label:"Other"}:{v0:i.speed,label:"CP"},f=E.assembleProperties(o,i.loadCondition,I,0),g=h.length?R.LaneHelper.calculateSubWaypoints(e,h):[];g.forEach(H=>H.important=!0);const d={from:{...e},route:u,waypoints:g,v0:I,label:j},b={hours:[],days:[],wps:[]};s||(R.LaneHelper.calculateRouteDistance(u)/i.speed<=72?s=3:s=6);let q=R.LaneHelper.simplifyRouteToCoordinates(u,g,0),v=0,k=0,S=0,N=0;t=w(t).utc();const x=t.clone();for(;q.length>0;){const H=s-t.hour()%s,F=Math.ceil(t.clone().add(H,"h").set({minute:0,second:0,millisecond:0}).diff(t,"h",!0)*1e4)/1e4,O=await E.speedLoseInHoursStep(f,t,x,F,v,q,n,c,r,l);(z=O.from)!=null&&z.speed&&(b.hours.push(O.from),b.wps.push(...O.wps),b.days.push(...O.days)),q=O==null?void 0:O.next,q.length||b.hours.push(O==null?void 0:O.to),v+=Math.round((((U=O==null?void 0:O.to)==null?void 0:U.distanceFromPrevious)??0)*1e4)/1e4}const W=b.hours;for(let H=0;H<W.length-1;H++){const F=w(W[H+1].eta).diff(W[H].etd,"hour",!0)||1;k+=(W[H].wxFactor||0)*F,S+=(W[H].cFactor||0)*F,N+=F}(Q=b.wps)==null||Q.forEach((H,F)=>{if(F){const O=b.wps[F-1],ft=H.distanceFromStart-O.distanceFromStart,nt=w(H.eta).diff(w(O.etd),"h",!0);if(nt<1)H.avgSpd=O.speed;else{H.avgSpd=Math.round(ft/nt*100)/100;const it=Math.round((O.speed+H.speed)/2*100)/100;H.avgSpd=H.avgSpd>it?it:H.avgSpd}}}),d.sample=b;const L=b.hours.at(0),B=b.hours.at(-1);d.distance=Math.round(B.distanceFromStart*1e4)/1e4,d.etd=w(L.eta).utc().format(),d.eta=w(B.eta).utc().format(),d.wxFactor=Math.round(k/N*1e4)/1e4,d.cFactor=Math.round(S/N*1e4)/1e4,d.avgSpeed=Math.round(B.distanceFromStart/N*1e4)/1e4,d.totalHrs=Math.round(N*1e4)/1e4,d.totalFoCons=Math.round((i==null?void 0:i.fo)/24*d.totalHrs*1e3)/1e3,d.totalDgoCons=Math.round((i==null?void 0:i.dgo)/24*d.totalHrs*1e3)/1e3;const P=w().valueOf()-y,A=((J=b==null?void 0:b.hours)==null?void 0:J.length)||1;return p==null||p.info("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms",l==null?void 0:l.requestId,P,A,Math.round(P/A*1e3)/1e3),d}static async analyseInstantWithThreshed(e,t,o,i,a,n,s,c="",r=3,l=!0,y=!1,m={}){var Z,z,U,Q;const h=w().valueOf();e.lng=R.LngLatHelper.convertToStdLng(e.lng);const{v0:u,label:I}=e.sog?{v0:e.sog,label:"Other"}:{v0:a.speed,label:"CP"},j=E.assembleProperties(i,a.loadCondition,u,0),f=R.LaneHelper.calculateSubRoute(e,n);if(((Z=f[0])==null?void 0:Z.length)<=1)return;const g=s.length?R.LaneHelper.calculateSubWaypoints(e,s):[];g.forEach(J=>J.important=!0);let d=R.LaneHelper.simplifyRouteToCoordinates(f,g,0),b=0,q=0,v=0,k=0;const S={hours:[],wps:[],days:[]};t=w(t).utc();const N=t.clone();for(;d.length>0;){const J=r-t.hour()%r;let H=Math.ceil(t.clone().add(J,"h").set({minute:0,second:0,millisecond:0}).diff(t,"h",!0)*1e4)/1e4;if(H=t.clone().add(H,"h").isAfter(o)?o.diff(t,"h",!0)*1e4/1e4:H,H){const F=await E.speedLoseInHoursStep(j,t,N,H,b,d,c,l,y,m);(z=F.from)!=null&&z.speed&&(S.hours.push(F.from),F!=null&&F.wps&&S.wps.push(...F.wps),S.days.push(...F.days)),d=F==null?void 0:F.next,d.length||S.hours.push(F==null?void 0:F.to),b+=Math.round((((U=F==null?void 0:F.to)==null?void 0:U.distanceFromPrevious)??0)*1e4)/1e4}else break}const x=S.hours;for(let J=0;J<x.length-1;J++){const H=w(x[J+1].eta).diff(x[J].etd,"hour",!0);q+=x[J].wxFactor*H,v+=x[J].cFactor*H,k+=H}const W=S.hours.at(0),L=S.hours.at(-1),B={sample:S,distance:Math.round(((L==null?void 0:L.distanceFromStart)||0)*1e4)/1e4,etd:w(W.eta).utc().format(),eta:w(L==null?void 0:L.eta).utc().format(),wxFactor:Math.round(q/k*1e4)/1e4,cFactor:Math.round(v/k*1e4)/1e4,avgSpeed:Math.round(((L==null?void 0:L.distanceFromStart)||0)/k*1e4)/1e4,totalHrs:Math.round(k*1e4)/1e4,totalFoCons:Math.round((a==null?void 0:a.fo)/24*k*1e3)/1e3,totalDgoCons:Math.round((a==null?void 0:a.dgo)/24*k*1e3)/1e3,from:W,to:L,route:f,waypoints:g,v0:u,label:I},P=w().valueOf()-h,A=((Q=S==null?void 0:S.hours)==null?void 0:Q.length)||1;return p==null||p.debug("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms",m==null?void 0:m.requestId,P,A,Math.round(P/A*1e3)/1e3),B}static async analyseCost(e,t,o,i,a={}){var I,j;const n=w().valueOf(),s=[];a.meteo2=!0,e.speedStep=e.speedStep||3;const c=w.utc(e.etd).add(a.maxDays??14,"day");let r=1;for(const f of o){p==null||p.info("[%s][L%d-%d] analyse from %s to %s",a.requestId,1,r,e.etd,c.format());const g=JSON.parse(JSON.stringify(i.route)),d=JSON.parse(JSON.stringify(i.waypoints)),b=await E.analyseInstantWithThreshed({lat:e.lat,lng:e.lng},e.etd,c,t,f,g,d,e.meteoVendor,e.speedStep,e.useMeteo,e.useRouteParam,a);b&&(await E.calculateCost(b,f,e,a),s.push(b),p==null||p.info("[%s][L%d-%d] cost: %j",a.requestId,1,r,{distance:b.distance,totalHrs:b.totalHrs,totalFoCons:b.totalFoCons,totalDgoCons:b.totalDgoCons,etd:b.etd,eta:b.eta,cost:b.cost})),r++}s.sort((f,g)=>f.cost.total-g.cost.total);const l=s.at(0),y=s.at(1),m=[];if(m.push({combined:!1,speeds:[l],cost:(I=l.cost)==null?void 0:I.total}),y){const f=l.cost.cp,g=y.cost.cp,d=w(l.eta),b=w(l.etd),q=d.diff(b,"days",!0);let v=Math.ceil(q/2);v=v>7?7:v;let k=2,S={combined:!1,speeds:[y],cost:(j=y.cost)==null?void 0:j.total},N;for(;v>=1;){const x=await E.combinedAnalyse(e,t,c,[f,g],i,v,{...a,level:k});if(S.cost>x.cost?N?(N==null?void 0:N.cost)>x.cost&&(N=x):(N=S,S=x):(!N||(N==null?void 0:N.cost)>x.cost)&&(N=x),v===1)break;v=Math.ceil(v/2),k+=1}m.push(S),N&&m.push(N)}const u=w().valueOf()-n;return p==null||p.info("[%s] analyse elapsed: %d ms",a==null?void 0:a.requestId,u),m.sort((f,g)=>f.cost-g.cost)}static async combinedAnalyse(e,t,o,i,a,n,s={}){s.counter=1,p==null||p.info("[%s][L%d] analyse with alternate cp in every %d days",s.requestId,s.level,n);const c=await E.alternateAnalyse(e,t,o,i,0,a,n,s),r=c.reduce((m,h)=>m+h.cost.total,0);p==null||p.info("[%s][L%d] cost with cpa/cpb turn: %d",s.requestId,s.level,r);const l=await E.alternateAnalyse(e,t,o,i,1,a,n,s),y=l.reduce((m,h)=>m+h.cost.total,0);return p==null||p.info("[%s][L%d] cost with cpb/cpa turn: %j",s.requestId,s.level,{cost:y}),r<y?{combined:!0,cost:Math.round(r*1e3)/1e3,speeds:c}:{combined:!0,cost:Math.round(y*1e3)/1e3,speeds:l}}static async alternateAnalyse(e,t,o,i,a,n,s,c={}){var m,h;let r=w.utc(e.etd);const l={lat:e.lat,lng:e.lng},y=[];for(;r.isBefore(o);){const u=r.clone().utc().add(s,"day");p==null||p.info("[%s][L%d-%d] analyse from %s to %s",c.requestId,c.level,c.counter,r.format(),u.format());const I=JSON.parse(JSON.stringify(n.route)),j=JSON.parse(JSON.stringify(n.waypoints)),f=await E.analyseInstantWithThreshed(l,r.format(),u,t,i[a],I,j,e.meteoVendor,e.speedStep,e.useMeteo,e.useRouteParam,c);f&&(await E.calculateCost(f,i[a],e,c),p==null||p.info("[%s][L%d-%d] cost: %j",c.requestId,c.level,c.counter,{distance:f.distance,totalHrs:f.totalHrs,totalFoCons:f.totalFoCons,totalDgoCons:f.totalDgoCons,etd:f.etd,eta:f.eta,cost:f.cost})),c.counter=c.counter+1;const g=(h=(m=f==null?void 0:f.sample)==null?void 0:m.hours)==null?void 0:h.at(-1);if(g)l.lat=g.lat,l.lng=g.lng,r=w(g.eta),y.push(f),a=a?0:1;else break}return y}static async calculateCost(e,t,o,i={}){if(e){const a=Math.round(e.totalHrs/24*(o.dailyHire||0)*(1-(o.addComm||0))*1e3)/1e3,n=Math.round(e.totalFoCons*(o.priceFO||0)*1e3)/1e3,s=Math.round(e.totalDgoCons*(o.priceDGO||0)*1e3)/1e3;e.cost={total:Math.round((a+n+s)*1e3)/1e3,hire:a,bunker:Math.round((n+s)*1e3)/1e3,cp:t}}return e}static async mergeSpeeds(e,t={}){const o={hours:[],wps:[],days:[]},i=e.reduce((h,u)=>h+u.distance,0),a=e.reduce((h,u)=>h+u.totalHrs,0),n=e.reduce((h,u)=>h+u.wxFactor*u.totalHrs/a,0),s=e.reduce((h,u)=>h+u.cFactor*u.totalHrs/a,0),c=e.reduce((h,u)=>h+u.totalFoCons,0),r=e.reduce((h,u)=>h+u.totalDgoCons,0),l=e.reduce((h,u)=>h+u.cost.total,0),y=e.reduce((h,u)=>h+u.cost.hire,0),m=e.reduce((h,u)=>h+u.cost.bunker,0);for(const h of e){const u=h.sample.hours,I=h.sample.wps,j=h.sample.days;u.forEach(f=>{var d;((d=o.hours)==null?void 0:d.findIndex(b=>b.eta===f.eta))===-1&&o.hours.push(f)}),I.forEach(f=>{var d;((d=o.wps)==null?void 0:d.findIndex(b=>b.eta===f.eta))===-1&&o.wps.push(f)}),j.forEach(f=>{var d;((d=o==null?void 0:o.days)==null?void 0:d.findIndex(b=>b.eta===f.eta))===-1&&o.days.push(f)})}return{sample:o,etd:e.at(0).etd,eta:e.at(-1).eta,from:e.at(0).from,to:e.at(-1).to,label:"combined",distance:Math.round(i*1e4)/1e4,totalHrs:Math.round(a*1e3)/1e3,avgSpeed:Math.round(i/a*1e3)/1e3,wxFactor:Math.round(n/a*1e3)/1e3,cFactor:Math.round(s/a*1e3)/1e3,totalFoCons:Math.round(c*1e3)/1e3,totalDgoCons:Math.round(r*1e3)/1e3,cost:{total:Math.round(l*1e3)/1e3,hire:Math.round(y*1e3)/1e3,bunker:Math.round(m*1e3)/1e3}}}}T.AISImpl=G,T.AlertHelper=et,T.AlertLevel=tt,T.HifleetImpl=ct,T.LoadCondition=at,T.MyShipImpl=ut,T.MyVesselImpl=rt,T.ShipxyImpl=dt,T.SpeedHelper=E,T.SpeedLabel=ot,T.VesselTag=st,T.alertHelper=ht,Object.defineProperty(T,Symbol.toStringTag,{value:"Module"})});
1
+ (function(T,D){typeof exports=="object"&&typeof module<"u"?D(exports,require("got"),require("@log4js-node/log4js-api"),require("moment"),require("@idm-plugin/geo"),require("@idm-plugin/meteo2"),require("@idm-plugin/meteo")):typeof define=="function"&&define.amd?define(["exports","got","@log4js-node/log4js-api","moment","@idm-plugin/geo","@idm-plugin/meteo2","@idm-plugin/meteo"],D):(T=typeof globalThis<"u"?globalThis:T||self,D(T["idm-plugin-rabbitmq"]={},T.got,T["@log4js-node/log4js-api"],T.moment,T["@idm-plugin/geo"],T["@idm-plugin/meteo2"],T["@idm-plugin/meteo"]))})(this,function(T,D,K,g,R,X,$){"use strict";var mt=Object.defineProperty;var yt=(T,D,K)=>D in T?mt(T,D,{enumerable:!0,configurable:!0,writable:!0,value:K}):T[D]=K;var _=(T,D,K)=>(yt(T,typeof D!="symbol"?D+"":D,K),K);let M;try{M=K.getLogger("vessel")}catch{}finally{}class G{parseStatus(e){let t,o;switch(e){case 0:t="在航(主机推动)",o="The engine is in use";break;case 1:t="锚泊",o="Anchored";break;case 2:t="失控",o="Not operated";break;case 3:t="操纵受限",o="Limited airworthiness";break;case 4:t="吃水受限",o="Limited by ship's draft";break;case 5:t="靠泊",o="Mooring";break;case 6:t="搁浅",o="Stranded";break;case 7:t="捕捞作业",o="Engaged in fishing";break;case 8:t="靠帆船提供动力",o="Sailing";break;default:t="未定义",o="Undefined"}return{labelCn:t,labelEn:o}}}class rt extends G{constructor(t,o){super();_(this,"clientId");_(this,"clientSecret");_(this,"token");this.clientId=t,this.clientSecret=o}async authToken(t={}){const o="https://svc.data.myvessel.cn/ada/oauth/token",i={searchParams:{client_id:this.clientId,client_secret:this.clientSecret,grant_type:"client_credentials"}},a=await D.post(o,i).json();M==null||M.info("[%s] fetch access token from: %s - %j",t.requestId,o,a),a.error||(this.token={accessToken:a.access_token,tokenType:a.token_type,expiresIn:a.expires_in,scope:a.scope,jti:a.jti,issuedAt:g().utc().format()})}async realTimePosition(t,o={}){var l,y,f;(!this.token||g().diff(g(this.token.issuedAt),"seconds")>((l=this.token)==null?void 0:l.expiresIn)-300)&&await this.authToken(o);const i="https://svc.data.myvessel.cn/sdc/v1/vessels/status/location/unit",a={headers:{Authorization:`${(y=this.token)==null?void 0:y.tokenType} ${(f=this.token)==null?void 0:f.accessToken}`},searchParams:{mmsi:t}};M==null||M.info("[%s] fetch realtime position from: %s - %j",o.requestId,i,a);const n=await D.get(i,a).json();if(n.code)return M==null||M.warn("[%s] fetch realtime position failed: %j",o.requestId,i,{message:n.message,status:n.status,code:n.code}),n;const s=n.data;for(const h in s)!isNaN(s[h])&&Number(s[h])!==1/0&&(s[h]=Number(s[h]));const d=g(`${s.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return{mmsi:s.mmsi,name:s.vesselName,imo:s.imo,callSign:s.callsign,lat:s.lat,lng:s.lon,length:s.length,width:s.width,draught:s.currDraught,sog:s.sog,cog:s.cog,hdg:s.hdg,rot:s.rot,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(s.eta)?g.utc(s.eta).format():void 0,destination:s.dest,positionTime:d.unix(),status:s.status,labelCn:s.statusNameCn,labelEn:s.statusNameEn,method:"position",vendor:"myVessel",utc:d.utc().format()}}async trajectory(t,o,i,a,n=!0,s={}){(!this.token||g().diff(g(this.token.issuedAt),"seconds")>this.token.expiresIn-300)&&await this.authToken(s);const d=await this.realTimePosition(t,s),r=g(o),l=g(i),y=[];for(;l.diff(r,"day",!0)>30;)await this.trajectoryIn30Day(t,r,r.clone().add(30,"day"),d,a,y,s),r.add(30,"day");return await this.trajectoryIn30Day(t,r,l,d,a,y,s),y}async trajectoryIn30Day(t,o,i,a,n,s,d={}){var u,I,k,m,v;const r="https://svc.data.myvessel.cn/sdc/v1/vessels/status/track",l={headers:{Authorization:`${(u=this.token)==null?void 0:u.tokenType} ${(I=this.token)==null?void 0:I.accessToken}`},json:{mmsi:t,startTime:o.utcOffset(8).format("YYYY-MM-DD HH:mm:ss"),endTime:i.utcOffset(8).format("YYYY-MM-DD HH:mm:ss")}};M==null||M.info("[%s] fetch trajectory from: %s - %j",d.requestId,r,l);const y=await D.post(r,l).json();if(y.code)return M==null||M.warn("[%s] fetch trajectory failed: %j",d.requestId,r,{message:y.message,status:y.status,code:y.code}),y;let f=-1;const h=g(`${(m=(k=y.data)==null?void 0:k[0])==null?void 0:m.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return(v=y.data)==null||v.forEach(c=>{for(const x in c)!isNaN(c[x])&&Number(c[x])!==1/0&&(c[x]=Number(c[x]));const b=g(`${c.postime} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00"),q=c.status,{labelCn:p,labelEn:j}=this.parseStatus(q),S={mmsi:c.mmsi,imo:a==null?void 0:a.imo,lat:c.lat,lng:c.lon,sog:c.sog,cog:c.cog,hdg:c.hdg,draught:c.draught,status:q,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(c.eta)?g(`${c.eta} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00").utc().format():void 0,destination:c.dest,positionTime:b.unix(),labelCn:p,labelEn:j,method:"trajectory",vendor:"myVessel",utc:b.utc().format()},N=Math.floor(b.diff(h,"minute",!0)/(n||1));N!==f&&(f=N,s.push(S))}),s}}class ct extends G{constructor(t){super();_(this,"token");this.token=t}async realTimePosition(t,o={}){const i="https://api.hifleet.com/position/position/get/token",a={searchParams:{mmsi:t,usertoken:this.token}},n=await D.post(i,a).json();M==null||M.info("[%s] fetch realtime position from: %s - %j",o.requestId,i,a);const s=n==null?void 0:n.list;if(!s)return M==null||M.warn("[%s] fetch realtime position failed: %j",o.requestId,i,n),n;for(const h in s)!isNaN(s[h])&&Number(s[h])!==1/0&&(s[h]=Number(s[h]));s.status=s.sp>3?0:1;const d=s.status,{labelCn:r,labelEn:l}=this.parseStatus(d),y=g(`${s.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");return{mmsi:s.m,name:s.n,imo:s.imonumber,callSign:s.callsign,lat:Math.round(s.la/60*1e5)/1e5,lng:Math.round(s.lo/60*1e5)/1e5,length:s.l,width:s.w,draught:s.draught,sog:s.sp,cog:s.co,hdg:s.h,rot:isNaN(s.rot)?0:s.rot,eta:/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(s.eta)?g.utc(s.eta).format():void 0,destination:s.destination,positionTime:y.unix(),utc:y.utc().format(),status:d,labelCn:r,labelEn:l,method:"position",vendor:"hifleet"}}async search(t,o={}){let i="https://www.hifleet.com/hifleetapi/searchVesselOL.do";const a={searchParams:{keyword:t},headers:{Referer:"https://www.hifleet.com",Origin:"https://www.hifleet.com",Host:"www.hifleet.com"}};let n=await D.post(i,a).json();M==null||M.info("[%s] fetch vessel props from: %s - %j",o.requestId,i,a),n instanceof Array&&(n=n[0]);for(const d in n)!isNaN(n[d])&&Number(n[d])!==1/0&&(n[d]=Number(n[d]));const s={mmsi:n.m,name:n.n,imo:n.i,callSign:n.c,length:n.l,breadth:n.b,draught:n.dr,type:n.t};return i="https://www.hifleet.com/hifleetapi/sameShipSearch.do",n=await D.post(i,a).json(),M==null||M.info("[%s] search vessel dead weight from: %s - %j",o.requestId,i,a),n instanceof Array&&(n=n[0]),n&&(s.deadweight=Number(n.dwt)),s}async suggest(t,o={}){const i="https://www.hifleet.com/hifleetapi/getShipSuggest.do",a={searchParams:{q:t},headers:{Referer:"https://www.hifleet.com",Origin:"https://www.hifleet.com",Host:"www.hifleet.com"}},n=await D.post(i,a).json();M==null||M.info("[%s] suggest vessel props from: %s - %j",o.requestId,i,a);const s=[];for(const d of n)s.push({mmsi:!d.mmsi||isNaN(d.mmsi)?null:Number(d.mmsi),name:d.name,callSign:d.callsign,imo:!d.imo||isNaN(d.imo)?null:Number(d.imo),score:d._score});return s.sort((d,r)=>r.score-d.score),s}async trajectory(t,o,i,a,n=!0,s={}){var c,b,q;const d=await this.realTimePosition(t,s);let r=g(o);const l=g(i),y=g();if(n){let p=l.diff(r,"d",!0);p<0?r=l.clone().subtract(40,"d"):p<30?r.subtract(10,"d"):p<60?r.subtract(5,"d"):r=l.clone().subtract(80,"d"),p=y.diff(l,"d",!0),l.add(p>10?240:p*24,"h")}const f={searchParams:{endtime:l.utcOffset("+8:00").format("YYYY-MM-DD HH:mm:ss"),starttime:r.utcOffset("+8:00").format("YYYY-MM-DD HH:mm:ss"),mmsi:t,usertoken:this.token}},h="https://api.hifleet.com/position/trajectory/nocompressed/withstatic/token",u=await D.get(h,f).json();M==null||M.info("[%s] fetch trajectory from: %s - %j",s.requestId,h,f);let I;u&&(I=((b=(c=u.ships)==null?void 0:c.offors)==null?void 0:b.ship)||[],I.length||M==null||M.warn("[%s] fetch trajectory failed: %j",s.requestId,u));const k=[];let m=-1;const v=g(`${(q=I==null?void 0:I[0])==null?void 0:q.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");for(const p of I){for(const L in p)!isNaN(p[L])&&Number(p[L])!==1/0&&(p[L]=Number(p[L]));const j=g(`${p.ti} +08:00`,"YYYY-MM-DD HH:mm:ss +08:00");p.status=p.sp>4?0:1;const{labelEn:S,labelCn:N}=this.parseStatus(p.status),x={mmsi:p.m,name:p.n,imo:d==null?void 0:d.imo,lat:p.la,lng:p.lo,draught:p.draught,sog:p.sp,cog:p.co,hdg:p.hdg,positionTime:j.unix(),utc:j.utc().format(),status:p.status,labelCn:N,labelEn:S,method:"trajectory",vendor:"hifleet"},W=Math.floor(j.diff(v,"minute",!0)/(a||1));W!==m&&(m=W,k.push(x))}return k}}class dt extends G{constructor(t){super();_(this,"token");this.token=t}async realTimePosition(t,o={}){const i={searchParams:{id:t,k:this.token,enc:1}},a="https://api.shipxy.com/apicall/GetSingleShip",n=await D.get(a,i).json();if(M==null||M.info("[%s] fetch realtime position from: %s - %j",o.requestId,a,i),(n==null?void 0:n.status)!==0)return n;const s=n.data[0];for(const f in s)!isNaN(s[f])&&Number(s[f])!==1/0&&(s[f]=Number(s[f]));const{labelCn:d,labelEn:r}=await this.parseStatus(s.navistat),l=g.unix(s.lasttime);return{mmsi:s.ShipID,name:s.name,imo:s.imo,callSign:s.callsign,lat:Math.round(s.lat/1e6*1e5)/1e5,lng:Math.round(s.lon/1e6*1e5)/1e5,length:Math.round(s.length/10*100)/100,width:Math.round(s.width/10*100)/100,draught:Math.round(s.draught/1e3*100)/100,sog:Math.round(s.sog*3600/1e3/1852*100)/100,cog:Math.round(s.cog/100*100)/100,hdg:Math.round(s.hdg/100*100)/100,rot:Math.round(s.rot/100*100)/100,positionTime:s.lasttime,utc:l.utc().format(),status:s.navistat,labelEn:r,labelCn:d,method:"position",vendor:"shipxy"}}async trajectory(t,o,i,a,n=!0,s={}){var v;const d=await this.realTimePosition(t,s),r=g(o),l=g(i),y="https://api.shipxy.com/apicall/GetShipTrack",f={searchParams:{id:t,k:this.token,enc:1,cut:0,btm:r.unix(),etm:l.unix()}},h=await D.get(y,f).json();if(M==null||M.info("[%s] fetch trajectory from: %s - %j",s.requestId,y,f),(h==null?void 0:h.status)!==0)return h;const u=h==null?void 0:h.points,I=[],k=g.unix((v=u[0])==null?void 0:v.utc);let m=-1;for(const c of u){const b=g.unix(c.utc),q={imo:d==null?void 0:d.imo,mmsi:t,sog:Math.round(c.sog*3600/1e3/1852*100)/100,cog:Math.round(c.cog/100*100)/100,lat:Math.round(c.lat/1e6*1e5)/1e5,lng:Math.round(c.lon/1e6*1e5)/1e5,positionTime:b.unix(),utc:b.utc().format(),method:"trajectory",vendor:"shipxy"},p=Math.floor(b.diff(k,"minute",!0)/(a||1));p!==m&&(m=p,I.push(q))}return I}}class ut extends G{constructor(t){super();_(this,"token");this.token=t}async getShipId(t,o={}){const i={headers:{appKey:this.token},json:{mmsiList:t}},a="https://api3.myships.com/sp/ships/getShipIdByMMSI",n=await D.post(a,i).json();return M==null||M.info("[%s] fetch ship id from: %s - %j",o.requestId,a,i),n.code!=="0"?n:n.data[0].shipId}async getShipInfo(t,o={}){const i={headers:{appKey:this.token},json:{shipId:t}},a="https://api3.myships.com/sp/ships/aissta",n=await D.post(a,i).json();if(M==null||M.info("[%s] fetch ship info from: %s - %j",o.requestId,a,i),n.code!=="0")return n;const s=n.data;let d=s.imo;return t==="407170"&&(d="9198379",M==null||M.warn("[%s] ship(%s) imo error: %s, should be %s",o.requestId,t,s.imo,d)),{mmsi:s.mmsi,name:s.shipnameEn,imo:d,callSign:s.callSign,length:s.length,width:s.breadth,draught:(s.draught||100)/10}}async realTimePosition(t,o={}){const i=await this.getShipId(t,o),a=await this.getShipInfo(i,o),n={headers:{appKey:this.token},json:{shipId:i}},s="https://api3.myships.com/sp/ships/position/latest",d=await D.post(s,n).json();M==null||M.info("[%s] fetch realtime position from: %s - %j",o.requestId,s,n);const r=d.data[0];for(const u in r)!isNaN(r[u])&&Number(r[u])!==1/0&&(r[u]=Number(r[u]));const{labelCn:l,labelEn:y}=await this.parseStatus(r.aisNavStatus),f=g.unix(r.posTime);return{...a,mmsi:t,lat:Math.round(r.lat/1e4/60*1e5)/1e5,lng:Math.round(r.lon/1e4/60*1e5)/1e5,sog:Math.round(r.sog/10*100)/100,cog:Math.round(r.cog/10*100)/100,hdg:Math.round(r.heading*100)/100,rot:Math.round(r.rot*100)/100,positionTime:r.posTime,utc:f.utc().format(),status:r.aisNavStatus,labelEn:y,labelCn:l,method:"position",vendor:"myship"}}async trajectory(t,o,i,a,n=!0,s={}){const d=g(o),r=g(i),l=await this.getShipId(t),y=await this.getShipInfo(l),f=[];for(;r.diff(d,"day",!0)>30;)await this.trajectoryIn30Day(l,d.unix(),d.add(30,"day").unix(),y,t,a,f);return await this.trajectoryIn30Day(l,d.unix(),r.unix(),y,t,a,f),f}async trajectoryIn30Day(t,o,i,a,n,s,d,r={}){var k;const l={headers:{appKey:this.token},json:{shipId:t,startTime:o,endTime:i}},y="https://api3.myships.com/sp/ships/position/history",f=await D.post(y,l).json();if(M==null||M.info("[%s] fetch trajectory from: %s - %j",r.requestId,y,l),f.code!=="0")return M==null||M.warn("[%s] invoke myship trajectory failed: %j",r.requestId,f),f;const h=f.data;for(const m in h)!isNaN(h[m])&&Number(h[m])!==1/0&&(h[m]=Number(h[m]));const u=g.unix((k=h[0])==null?void 0:k.posTime);let I=-1;for(const m of h){const v=g.unix(m.posTime),c={imo:a==null?void 0:a.imo,mmsi:n,lat:Math.round(m.lat/1e4/60*1e5)/1e5,lng:Math.round(m.lon/1e4/60*1e5)/1e5,sog:Math.round(m.sog/10*100)/100,cog:Math.round(m.cog/10*100)/100,hdg:Math.round(m.heading*100)/100,rot:Math.round(m.rot*100)/100,positionTime:v.unix(),utc:v.utc().format(),method:"trajectory",vendor:"myship"},b=Math.floor(v.diff(u,"minute",!0)/(s||1));b!==I&&(I=b,d.push(c))}return d}}let V;try{V=K.getLogger("vessel")}catch{}finally{}var tt=(Y=>(Y.NOTICE="NOTICE",Y.WARN="WARN",Y.HEAVY="HEAVY",Y.SEVERE="SEVERE",Y.ERROR="ERROR",Y.FATAL="FATAL",Y))(tt||{});class et{parsePrinciple(e,t={}){var s,d,r;V==null||V.info("[%s] parse rule: %s",t.requestId,e);const o=new RegExp("(?<=\\[)(.+)(?=])","g"),i=e.match(o)?(s=e.match(o))==null?void 0:s[0]:void 0,a=i==null?void 0:i.split(";");if(!a)return;const n={};for(let l=0;l<(a==null?void 0:a.length);l++){const y=(r=(d=a[l].match(o))==null?void 0:d[0])==null?void 0:r.split("],");if(l===0&&!y)n.scope=a[0];else if(y)for(let f=0,h=y.length;f<h;f++){const u=this.parseRule(y[f]);u&&(n[u.level]?u.key?n[u.level][u==null?void 0:u.key]=u:n[u.level]=u:u.key?n[u.level]={[u==null?void 0:u.key]:u}:n[u.level]=u)}}return n}parseRule(e,t={}){var n;V==null||V.info("[%s] parse rule: %s",t.requestId,e),e=e.startsWith("[")?e:`[${e}`,e=e.endsWith("]")?e:`${e}]`;const o=new RegExp("(?<=\\[)(.+?)(?=])","g"),i=(n=e==null?void 0:e.match(o))==null?void 0:n[0],a=i==null?void 0:i.split(",");if(a)return{operator:a[0],number:Number.isNaN(Number(a[1]))?a[1]:Number(a[1]),level:a[2],time:Number(a[3]),key:a[4]}}checkWeather(e,t,o={}){var u,I,k,m,v,c,b,q,p,j,S,N,x,W,L;let i=0,a=0,n=0,s=0;const d=Math.round(((I=(u=t==null?void 0:t.SEVERE)==null?void 0:u.sigWave)==null?void 0:I.number)*1.6*100)/100,r=(m=(k=t==null?void 0:t.SEVERE)==null?void 0:k.sigWave)==null?void 0:m.number,l=(c=(v=t==null?void 0:t.HEAVY)==null?void 0:v.sigWave)==null?void 0:c.number,y=Math.round((((q=(b=t==null?void 0:t.SEVERE)==null?void 0:b.wind)==null?void 0:q.number)+2)*100)/100,f=(j=(p=t==null?void 0:t.SEVERE)==null?void 0:p.wind)==null?void 0:j.number,h=(N=(S=t==null?void 0:t.HEAVY)==null?void 0:S.wind)==null?void 0:N.number;for(let B=0;B<(e==null?void 0:e.length);B++){const E=e[B],P=(W=(x=E==null?void 0:E.meteo)==null?void 0:x.wave)==null?void 0:W.sig,A=(L=E==null?void 0:E.meteo)==null?void 0:L.wind,Z=B?g(E.eta).diff(g(e[B-1].eta),"hour",!0):0;s=Z>s?Z:s,V==null||V.info("[%s] check sig.wave: %j",o.requestId,{...P,dgThd4Wv:d,svThd4Wv:r,hvThd4Wv:l}),(P==null?void 0:P.height)>=d?E.isDangerous=!0:(P==null?void 0:P.height)>=r?E.isSevere=!0:(P==null?void 0:P.height)>=l&&(E.isHeavy=!0),V==null||V.info("[%s] check wind: %j",o.requestId,{...A,dgThd4Wd:y,svThd4Wd:f,hvThd4Wd:h}),(A==null?void 0:A.scale)>=y?(E.isDangerous=!0,delete E.isSevere,delete E.isHeavy):(A==null?void 0:A.scale)>f?(E.isDangerous||(E.isSevere=!0),delete E.isHeavy):(A==null?void 0:A.scale)===h&&!E.isDangerous&&!E.isSevere&&(E.isHeavy=!0),i+=E.isDangerous?Z:0,a+=E.isSevere?Z:0,n+=E.isHeavy?Z:0}return i=Math.round(i*100)/100,a=Math.round(a*100)/100,n=Math.round(n*100)/100,s=Math.round(s),{sample:e,dangerous:i,severe:a,heavy:n,step:s<3?3:s,wind:{dgThd4Wd:y,svThd4Wd:f,hvThd4Wd:h},sig:{dgThd4Wv:d,svThd4Wv:r,hvThd4Wv:l}}}}const ht=new et;let w;try{w=K.getLogger("vessel")}catch{}finally{}const lt=new X.MeteoHelper2("",!0);var st=(Y=>(Y.common="common",Y.container="container",Y.tugs="tugs",Y))(st||{}),at=(Y=>(Y.Ballast="Ballast",Y.Laden="Laden",Y))(at||{}),ot=(Y=>(Y.Cp="CP",Y.Perf="Basis",Y.Instruct="Other",Y))(ot||{});class C{static blockCoefficient(e,t,o,i){let a=Math.round(e/(t*o*i)*100)/100;a=a<.55?.55:a>.85?.85:a;const n=[.55,.6,.65,.7,.75,.8,.85],s=n.map(d=>Math.abs(d-a));return n[s.indexOf(Math.min(...s))]}static froudeNumber(e,t,o=9.8){let i=Math.round(Math.sqrt(e*e/(o*t))*100)/100;return i=i<.05?.05:i>.3?.3:i,i}static amendFactor(e,t,o){const i={.55:[1.7,-1.4,-7.4],.6:[2.2,-2.5,-9.7],.65:[2.6,-3.7,-11.6],.7:[3.1,-5.3,-12.4],.75:[2.4,-10.6,-9.5],.8:[2.6,-13.1,-15.1],.85:[3.1,-18.7,28]};let n={.55:[1.7,-1.4,-7.4],.6:[2.2,-2.5,-9.7],.65:[2.6,-3.7,-11.6],.7:[3.1,-5.3,-12.4],.75:[2.6,-12.5,-13.5],.8:[3,-16.3,-21.6],.85:[3.4,-20.9,31.8]}[e];return o==="Laden"&&(n=i[e]),n[0]+n[1]*t+n[2]*Math.pow(t,2)}static directionFactor(e,t=0){let o;return e>30&&e<=60?o=(1.7-.03*Math.pow(t-4,2))/2:e>60&&e<=150?o=(.9-.06*Math.pow(t-6,2))/2:e>150&&e<=180?o=(.4-.03*Math.pow(t-8,2))/2:o=1,Math.round(o*1e5)/1e5}static vesselTagFactor(e,t,o,i=0){i=i>6?i-.9*(i-6):i;let a;return o==="container"?a=.7*i+Math.pow(i,6.5)/(22*Math.pow(e,2/3)):t==="Ballast"?a=.7*i+Math.pow(i,6.5)/(2.7*Math.pow(e,2/3)):a=.5*i+Math.pow(i,6.5)/(2.7*Math.pow(e,2/3)),a}static waveHeightFactor(e,t){e=e<0?.2:e,e=e>6?e-.9*(e-6):e,e=e>9?9:e;let o;return t>30&&t<=60?o=-.6:t>60&&t<=90?o=-.4:t>90&&t<=120?o=e<3?.4:-.3:t>120&&t<=150?o=e<3?.6:-.5:t>150&&t<=180?o=e<3?.7:-.6:o=-.7,Math.round(o*(.144*Math.pow(e,2)+.178*e)*1e4)/1e4}static assembleProperties(e,t,o,i){var f;const a=e.lbp??e.length??e.lengthOverall??198.9642,n=e.draught??8,s=e.breadthMoulded??e.breadth??e.breadthExtreme??32.4572,d=e.deadweight??67035.7773,r=((f=e==null?void 0:e.type)==null?void 0:f.toLowerCase())||"common";return{tag:r.indexOf("container")>-1?"container":r.indexOf("tugs")>-1?"tugs":"common",lbp:a,loadCondition:t,draught:n,breadthMoulded:s,displacement:Math.round((d/1.025+n*s*a*.7)*1e4)/1e4,speed:Math.round((o??14.1382)*1852/3600*1e4)/1e4,bearing:i||90}}static async speedLoseAt(e,t,o,i="",a=2,n=!0,s=!1,d={}){let r;if(t.velocity&&s&&(e.speed=R.LngLatHelper.roundPrecision(t.velocity*1852/3600,6)),n){let l;if(d.meteo2)try{const u=await lt.spotForecast(t.lat,t.lng,o.utc().format(),!1,!1,!0,d),[I]=$.Meteo2Assist.pickHourly(u,o);l=$.Meteo2Assist.toLegacy(I)}catch(u){w.warn("[%s] meteo2 spot(%j) forecast failed: %s",d.requestId,{...t,eta:o.utc().format()},u)}else l=await X.MeteoHelper.queryPointFactor(t.lng,t.lat,o.valueOf(),"wind,wave,current,watertemp",i,d);const y=C.weatherFactor(e,l),f=C.currentFactor(e.bearing,l==null?void 0:l.current,a),h=Math.round((e.speed*1.943844+y+f)*100)/100;r={meteo:{...l},wxFactor:y,cFactor:f,speed:t.velocity&&s?t.velocity:h<0?1:h,eta:o.utc().format("YYYY-MM-DDTHH:mm[Z]"),etd:o.utc().format("YYYY-MM-DDTHH:mm[Z]")}}else r={wxFactor:0,cFactor:0,speed:t.velocity&&s?t.velocity:Math.round((e.speed*1.943844+0+0)*100)/100,eta:o.utc().format("YYYY-MM-DDTHH:mm[Z]"),etd:o.utc().format("YYYY-MM-DDTHH:mm[Z]")};return delete t.meteo,delete t.wxFactor,delete t.cFactor,delete t.speed,delete t.etd,{...r,...t}}static async speedLoseInHoursStep(e,t,o,i,a,n,s="",d=!0,r=!1,l={}){t.utc();const y=t.clone().add(14,"days"),f=[],h=[];let u=0,I=0,k,m;for(let v=0;v<n.length-1;v++){let c=n[v];c.distanceFromStart=Math.round((a+I)*1e4)/1e4;const b=n[v+1];if(e.bearing=R.LaneHelper.calculateBearing(c,b,!b.gcToPrevious),c.bearing=e.bearing,c.suspend&&r){c.eta=c.eta||t.format("YYYY-MM-DDTHH:mm[Z]"),c.elapsed=c.elapsed??0;const j=c.suspend-c.elapsed;if(i-u>j)i=i-u-j,t.add(j,"hour"),c.elapsed=c.suspend;else{const S=i-u;c.elapsed+=S,t.add(S,"hour"),i=0}if(w==null||w.info(`[%s] suspend ${c.elapsed} hours at %j, and remain ${i} hours need to go...`,l.requestId,c),i===0)return c.distanceFromPrevious=I,{etd:t,from:m||c,to:c,next:n.filter(S=>S),wps:f,days:h}}else c.suspend=0;d=t.isAfter(y)?!1:d,c=await C.speedLoseAt(e,c,t,s,0,d,r,l),m=m||c,c.important&&f.push(c),t.isSameOrAfter(o)&&(h.push(c),o.add(24,"hour"));const q=R.LaneHelper.calculateDistance(c,b,!b.gcToPrevious);let p=Math.ceil(q/m.speed*1e4)/1e4;if(u+p<i){if(u+=p,t.add(p,"hour"),delete n[v],w==null||w.debug(`[%s] go to %j from %j with ${q}nm, and cost ${p} hours`,l.requestId,{lat:b.lat,lng:b.lng},{lat:m.lat,lng:m.lng,etd:m.etd}),I+=q,n.filter(j=>j).length<=1){k=b,k.eta=t.format("YYYY-MM-DDTHH:mm[Z]"),k.distanceFromPrevious=q,k.distanceFromStart=Math.round((a+I)*1e4)/1e4,f.push(k),delete n[v+1];break}}else{p=i-u,t.add(p,"hour");const j=R.LngLatHelper.roundPrecision(m.speed*p,4);k=R.LaneHelper.calculateCoordinate(c,e.bearing,j,"nauticalmiles",!b.gcToPrevious),k.eta=t.format("YYYY-MM-DDTHH:mm[Z]"),n[v]=k,w==null||w.debug(`[%s] go to %j from %j with ${j}nm, and cost ${p} hours`,l.requestId,{lat:k.lat,lng:k.lng},{lat:c.lat,lng:c.lng,etd:c.etd}),I+=j,k.distanceFromPrevious=Math.round(I*1e4)/1e4,k.distanceFromStart=Math.round((a+I)*1e4)/1e4;break}}return{etd:t,from:m,to:k,next:n.filter(v=>v),wps:f,days:h}}static currentFactor(e,t,o=0){const i=(e-(t==null?void 0:t.degree)||0)/180*Math.PI;if(Math.abs(i)===Math.PI/2)return 0;let a=((t==null?void 0:t.kts)||0)*Math.cos(i);return o&2?a=Math.ceil(a*100)/100:o&1?a=Math.floor(a*100)/100:a=Math.round(a*100)/100,Math.abs(a)>5?0:a}static weatherFactor(e,t){var y,f,h,u,I,k,m;w==null||w.debug("calculate weather factor via: %j",{...e,...t});const o=C.blockCoefficient(e.displacement,e.lbp,e.breadthMoulded,e.draught),i=C.froudeNumber(e.speed,e.lbp),a=C.amendFactor(o,i,e.loadCondition);let n=Math.abs(e.bearing%360-(((y=t==null?void 0:t.wind)==null?void 0:y.degree)%360||0));n=n>180?360-n:n;const s=C.directionFactor(n,(f=t==null?void 0:t.wind)==null?void 0:f.scale),d=C.vesselTagFactor(e.displacement,e.loadCondition,e.tag,(h=t==null?void 0:t.wind)==null?void 0:h.scale);let r=s*a*d/100*e.speed;r=Math.round(r*1.943844*1e4)/1e4*-1,e.tag==="tugs"&&Math.abs(r)>1&&(r=r/(Math.abs(Math.round(r))+1)),w==null||w.debug("wind wx factor = %d",r),n=Math.abs(e.bearing%360-(((I=(u=t==null?void 0:t.wave)==null?void 0:u.sig)==null?void 0:I.degree)%360||0));const l=C.waveHeightFactor(((m=(k=t==null?void 0:t.wave)==null?void 0:k.sig)==null?void 0:m.height)??1,n);return w==null||w.debug("wave wx factor = %d",l),r=r*.4+l,w==null||w.debug("weather factor = %d",r),r=Math.abs(r)>4?4*(Math.abs(r)/r)+Math.abs(r)/r*(Math.abs(r)-4)*.1:r,Math.round((r||0)*100)/100}static async analyseInstant(e,t,o,i,a,n="",s=0,d=!0,r=!1,l={}){var Z,z,U,Q,J;const y=g().valueOf();e.lng=R.LngLatHelper.convertToStdLng(e.lng);const{route:f,waypoints:h}=a.points,u=R.LaneHelper.calculateSubRoute(e,f);if(((Z=u[0])==null?void 0:Z.length)<=1)return;const{v0:I,label:k}=e.sog?{v0:e.sog,label:"Other"}:{v0:i.speed,label:"CP"},m=C.assembleProperties(o,i.loadCondition,I,0),v=h.length?R.LaneHelper.calculateSubWaypoints(e,h):[];v.forEach(H=>H.important=!0);const c={from:{...e},route:u,waypoints:v,v0:I,label:k},b={hours:[],days:[],wps:[]};s||(R.LaneHelper.calculateRouteDistance(u)/i.speed<=72?s=3:s=6);let q=R.LaneHelper.simplifyRouteToCoordinates(u,v,0),p=0,j=0,S=0,N=0;t=g(t).utc();const x=t.clone();for(;q.length>0;){const H=s-t.hour()%s,F=Math.ceil(t.clone().add(H,"h").set({minute:0,second:0,millisecond:0}).diff(t,"h",!0)*1e4)/1e4,O=await C.speedLoseInHoursStep(m,t,x,F,p,q,n,d,r,l);(z=O.from)!=null&&z.speed&&(b.hours.push(O.from),b.wps.push(...O.wps),b.days.push(...O.days)),q=O==null?void 0:O.next,q.length||b.hours.push(O==null?void 0:O.to),p+=Math.round((((U=O==null?void 0:O.to)==null?void 0:U.distanceFromPrevious)??0)*1e4)/1e4}const W=b.hours;for(let H=0;H<W.length-1;H++){const F=g(W[H+1].eta).diff(W[H].etd,"hour",!0)||1;j+=(W[H].wxFactor||0)*F,S+=(W[H].cFactor||0)*F,N+=F}(Q=b.wps)==null||Q.forEach((H,F)=>{if(F){const O=b.wps[F-1],ft=H.distanceFromStart-O.distanceFromStart,nt=g(H.eta).diff(g(O.etd),"h",!0);if(nt<1)H.avgSpd=O.speed;else{H.avgSpd=Math.round(ft/nt*100)/100;const it=Math.round((O.speed+H.speed)/2*100)/100;H.avgSpd=H.avgSpd>it?it:H.avgSpd}}}),c.sample=b;const L=b.hours.at(0),B=b.hours.at(-1);c.distance=Math.round(B.distanceFromStart*1e4)/1e4,c.etd=g(L.eta).utc().format(),c.eta=g(B.eta).utc().format(),c.wxFactor=Math.round(j/N*1e4)/1e4,c.cFactor=Math.round(S/N*1e4)/1e4,c.avgSpeed=Math.round(B.distanceFromStart/N*1e4)/1e4,c.totalHrs=Math.round(N*1e4)/1e4,c.totalFoCons=Math.round((i==null?void 0:i.fo)/24*c.totalHrs*1e3)/1e3,c.totalDgoCons=Math.round((i==null?void 0:i.dgo)/24*c.totalHrs*1e3)/1e3;const P=g().valueOf()-y,A=((J=b==null?void 0:b.hours)==null?void 0:J.length)||1;return w==null||w.info("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms",l==null?void 0:l.requestId,P,A,Math.round(P/A*1e3)/1e3),c}static async analyseInstantWithThreshed(e,t,o,i,a,n,s,d="",r=3,l=!0,y=!1,f={}){var Z,z,U,Q;const h=g().valueOf();e.lng=R.LngLatHelper.convertToStdLng(e.lng);const{v0:u,label:I}=e.sog?{v0:e.sog,label:"Other"}:{v0:a.speed,label:"CP"},k=C.assembleProperties(i,a.loadCondition,u,0),m=R.LaneHelper.calculateSubRoute(e,n);if(((Z=m[0])==null?void 0:Z.length)<=1)return;const v=s.length?R.LaneHelper.calculateSubWaypoints(e,s):[];v.forEach(J=>J.important=!0);let c=R.LaneHelper.simplifyRouteToCoordinates(m,v,0),b=0,q=0,p=0,j=0;const S={hours:[],wps:[],days:[]};t=g(t).utc();const N=t.clone();for(;c.length>0;){const J=r-t.hour()%r;let H=Math.ceil(t.clone().add(J,"h").set({minute:0,second:0,millisecond:0}).diff(t,"h",!0)*1e4)/1e4;if(H=t.clone().add(H,"h").isAfter(o)?o.diff(t,"h",!0)*1e4/1e4:H,H){const F=await C.speedLoseInHoursStep(k,t,N,H,b,c,d,l,y,f);(z=F.from)!=null&&z.speed&&(S.hours.push(F.from),F!=null&&F.wps&&S.wps.push(...F.wps),S.days.push(...F.days)),c=F==null?void 0:F.next,c.length||S.hours.push(F==null?void 0:F.to),b+=Math.round((((U=F==null?void 0:F.to)==null?void 0:U.distanceFromPrevious)??0)*1e4)/1e4}else break}const x=S.hours;for(let J=0;J<x.length-1;J++){const H=g(x[J+1].eta).diff(x[J].etd,"hour",!0);q+=x[J].wxFactor*H,p+=x[J].cFactor*H,j+=H}const W=S.hours.at(0),L=S.hours.at(-1),B={sample:S,distance:Math.round(((L==null?void 0:L.distanceFromStart)||0)*1e4)/1e4,etd:g(W.eta).utc().format(),eta:g(L==null?void 0:L.eta).utc().format(),wxFactor:Math.round(q/j*1e4)/1e4,cFactor:Math.round(p/j*1e4)/1e4,avgSpeed:Math.round(((L==null?void 0:L.distanceFromStart)||0)/j*1e4)/1e4,totalHrs:Math.round(j*1e4)/1e4,totalFoCons:Math.round((a==null?void 0:a.fo)/24*j*1e3)/1e3,totalDgoCons:Math.round((a==null?void 0:a.dgo)/24*j*1e3)/1e3,from:W,to:L,route:m,waypoints:v,v0:u,label:I},P=g().valueOf()-h,A=((Q=S==null?void 0:S.hours)==null?void 0:Q.length)||1;return w==null||w.debug("[%s] each hour-sample speed analyse cost: (%d / %d = %d) ms",f==null?void 0:f.requestId,P,A,Math.round(P/A*1e3)/1e3),B}static async analyseCost(e,t,o,i,a={}){var I,k;const n=g().valueOf(),s=[];a.meteo2=!0,e.speedStep=e.speedStep||3;const d=g.utc(e.etd).add(a.maxDays??14,"day");let r=1;for(const m of o){const v=JSON.parse(JSON.stringify(i.route)),c=JSON.parse(JSON.stringify(i.waypoints)),b=await C.analyseInstantWithThreshed({lat:e.lat,lng:e.lng},e.etd,d,t,m,v,c,e.meteoVendor,e.speedStep,e.useMeteo,e.useRouteParam,a);b&&(await C.calculateCost(b,m,e,a),s.push(b),w==null||w.info("[%s][L%d-%d] analyse from %s to %s cost: %j",a.requestId,1,r,e.etd,d.format(),{cost:b.cost.total,distance:b.distance,hours:b.totalHrs,cp:`${m.speed}/${m.fo}/${m.dgo}`})),r++}s.sort((m,v)=>m.cost.total-v.cost.total);const l=s.at(0),y=s.at(1),f=[];if(f.push({combined:!1,speeds:[l],cost:(I=l.cost)==null?void 0:I.total}),y){const m=l.cost.cp,v=y.cost.cp,c=g(l.eta),b=g(l.etd),q=c.diff(b,"days",!0);let p=Math.ceil(q/2);p=p>7?7:p;let j=2,S={combined:!1,speeds:[y],cost:(k=y.cost)==null?void 0:k.total},N;for(;p>=1;){const x=await C.combinedAnalyse(e,t,d,[m,v],i,p,{...a,level:j});if(S.cost>x.cost?N?(N==null?void 0:N.cost)>x.cost&&(N=x):(N=S,S=x):(!N||(N==null?void 0:N.cost)>x.cost)&&(N=x),p===1)break;p=Math.ceil(p/2),j+=1}f.push(S),N&&f.push(N)}const u=g().valueOf()-n;return w==null||w.info("[%s] analyse elapsed: %d ms",a==null?void 0:a.requestId,u),f.sort((m,v)=>m.cost-v.cost)}static async combinedAnalyse(e,t,o,i,a,n,s={}){s.counter=1,w==null||w.info("[%s][L%d] analyse with alternate cp in every %d days",s.requestId,s.level,n);const d=await C.alternateAnalyse(e,t,o,i,0,a,n,s),r=d.reduce((f,h)=>f+h.cost.total,0);w==null||w.info("[%s][L%d] cost with cpa/cpb turn: %d",s.requestId,s.level,r);const l=await C.alternateAnalyse(e,t,o,i,1,a,n,s),y=l.reduce((f,h)=>f+h.cost.total,0);return w==null||w.info("[%s][L%d] cost with cpb/cpa turn: %d",s.requestId,s.level,y),r<y?{combined:!0,cost:Math.round(r*1e3)/1e3,speeds:d}:{combined:!0,cost:Math.round(y*1e3)/1e3,speeds:l}}static async alternateAnalyse(e,t,o,i,a,n,s,d={}){var f,h;let r=g.utc(e.etd);const l={lat:e.lat,lng:e.lng},y=[];for(;r.isBefore(o);){const u=r.clone().utc().add(s,"day"),I=JSON.parse(JSON.stringify(n.route)),k=JSON.parse(JSON.stringify(n.waypoints)),m=i[a],v=await C.analyseInstantWithThreshed(l,r.format(),u,t,m,I,k,e.meteoVendor,e.speedStep,e.useMeteo,e.useRouteParam,d);v&&(await C.calculateCost(v,m,e,d),w==null||w.info("[%s][L%d-%d] analyse from %s to %s cost: %j",d.requestId,d.level,d.counter,r.utc().format(),u.utc().format(),{cost:v.cost.total,distance:v.distance,hours:v.totalHrs,cp:`${m.speed}/${m.fo}/${m.dgo}`})),d.counter=d.counter+1;const c=(h=(f=v==null?void 0:v.sample)==null?void 0:f.hours)==null?void 0:h.at(-1);if(c)l.lat=c.lat,l.lng=c.lng,r=g(c.eta),y.push(v),a=a?0:1;else break}return y}static async calculateCost(e,t,o,i={}){if(e){const a=Math.round(e.totalHrs/24*(o.dailyHire||0)*(1-(o.addComm||0))*1e3)/1e3,n=Math.round(e.totalFoCons*(o.priceFO||0)*1e3)/1e3,s=Math.round(e.totalDgoCons*(o.priceDGO||0)*1e3)/1e3;e.cost={total:Math.round((a+n+s)*1e3)/1e3,hire:a,bunker:Math.round((n+s)*1e3)/1e3,cp:t}}return e}static async mergeSpeeds(e,t={}){const o={hours:[],wps:[],days:[]},i=e.reduce((h,u)=>h+u.distance,0),a=e.reduce((h,u)=>h+u.totalHrs,0),n=e.reduce((h,u)=>h+u.wxFactor*u.totalHrs/a,0),s=e.reduce((h,u)=>h+u.cFactor*u.totalHrs/a,0),d=e.reduce((h,u)=>h+u.totalFoCons,0),r=e.reduce((h,u)=>h+u.totalDgoCons,0),l=e.reduce((h,u)=>h+u.cost.total,0),y=e.reduce((h,u)=>h+u.cost.hire,0),f=e.reduce((h,u)=>h+u.cost.bunker,0);for(const h of e){const u=h.sample.hours,I=h.sample.wps,k=h.sample.days;u.forEach(m=>{var c;((c=o.hours)==null?void 0:c.findIndex(b=>b.eta===m.eta))===-1&&o.hours.push(m)}),I.forEach(m=>{var c;((c=o.wps)==null?void 0:c.findIndex(b=>b.eta===m.eta))===-1&&o.wps.push(m)}),k.forEach(m=>{var c;((c=o==null?void 0:o.days)==null?void 0:c.findIndex(b=>b.eta===m.eta))===-1&&o.days.push(m)})}return{sample:o,etd:e.at(0).etd,eta:e.at(-1).eta,from:e.at(0).from,to:e.at(-1).to,label:"combined",distance:Math.round(i*1e4)/1e4,totalHrs:Math.round(a*1e3)/1e3,avgSpeed:Math.round(i/a*1e3)/1e3,wxFactor:Math.round(n/a*1e3)/1e3,cFactor:Math.round(s/a*1e3)/1e3,totalFoCons:Math.round(d*1e3)/1e3,totalDgoCons:Math.round(r*1e3)/1e3,cost:{total:Math.round(l*1e3)/1e3,hire:Math.round(y*1e3)/1e3,bunker:Math.round(f*1e3)/1e3}}}}T.AISImpl=G,T.AlertHelper=et,T.AlertLevel=tt,T.HifleetImpl=ct,T.LoadCondition=at,T.MyShipImpl=ut,T.MyVesselImpl=rt,T.ShipxyImpl=dt,T.SpeedHelper=C,T.SpeedLabel=ot,T.VesselTag=st,T.alertHelper=ht,Object.defineProperty(T,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": "1.6.3",
4
+ "version": "1.6.5",
5
5
  "description": "idm plugin for vessel",
6
6
  "type": "module",
7
7
  "keywords": [