@idm-plugin/vessel 1.2.0 → 1.2.2

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