atriusmaps-node-sdk
Version:
This project provides an API to Atrius Personal Wayfinder maps within a Node environment. See the README.md for more information
2 lines (1 loc) • 6.67 kB
JavaScript
import*as t from"ramda";import n from"zousan";import{buildStructuresLookup as o}from"../../../src/utils/buildStructureLookup.js";import{distance as e}from"../../../src/utils/geodesy.js";import{findRoute as i}from"./findRoute.js";import{createNavGraph as r}from"./navGraph.js";import{enrichDebugNavGraph as a}from"./navGraphDebug.js";import{buildSegments as s}from"./segmentBuilder.js";const u={SECURITY:"SecurityLane",IMMIGRATION:"ImmigrationLane"};function d(d,l){const p=d.log.sublog("wayfinder"),c=async()=>{d.bus.send("venueData/loadNavGraph")};let f=new n;d.bus.on("wayfinder/_getNavGraph",()=>f),d.bus.on("venueData/navGraphLoaded",async({navGraphData:t,structures:n})=>{const e=o(n),i=await m(),a=r(t,e.floorIdToOrdinal,e.floorIdToStructureId,i);f.resolve(a)}),d.bus.on("poi/setDynamicRouting",async({idValuesMap:t})=>{const n=await f,o=Object.values(t).filter(t=>t.position&&void 0!==t.position.floorId&&t.position.latitude&&t.position.longitude).map(t=>n.findClosestNode(t.position.floorId,t.position.latitude,t.position.longitude).id);n.addNodesToAvoid(o)});const m=async()=>{const n=await d.bus.get("poi/getByCategoryId",{categoryId:"security"});return t.pipe(t.map(y),t.filter(t.identity))(n)},y=n=>n.queue&&{type:t.path(["queue","queueType"],n),id:t.path(["queue","queueSubtype"],n)};d.bus.on("wayfinder/showNavLineFromPhysicalLocation",async({toEndpoint:t,selectedSecurityLanes:n=null,requiresAccessibility:o})=>async function(t,n,o){const e=await T({fromEndpoint:t,toEndpoint:n,options:o});if(e){const{segments:t}=e;o.primary&&d.bus.send("map/resetNavlineFeatures"),d.bus.send("map/showNavlineFeatures",{segments:t,category:o.primary?"primary":"alternative"})}return e}(await d.bus.getFirst("user/getPhysicalLocation"),t,{selectedSecurityLanes:n,requiresAccessibility:o,primary:!0}));const g=(t,n)=>d.bus.get("poi/getById",{id:t}).then(o=>{if(o&&o.position)return w(o,n);throw Error("Unknown POI ID "+t)});const h=["lat","lng","floorId","ordinal"],I=t.pipe(t.pick(h),t.keys,t.propEq(h.length,"length"),Boolean),w=(t,n)=>({lat:t.position.latitude,lng:t.position.longitude,floorId:t.position.floorId,ordinal:n(t.position.floorId),title:t.name});async function T({fromEndpoint:t,toEndpoint:n,options:o={}}){const e=await d.bus.get("poi/getAll")||{},r=Array.isArray(e)?e[0]:e,a=Object.values(r).filter(t=>t.category&&t.category.startsWith("security")),u=await d.bus.getFirst("directions/getPreferredUnits")||"meters";return f.then(async e=>{o.compareFindPaths=l.compareFindPaths;const r=i(e,t,n,o);if(!r)return null;const c=await d.bus.get("venueData/getFloorIdToNameMap"),f=await d.bus.get("venueData/getQueueTypes"),m=d.gt(),y=o.requiresAccessibility,{steps:g,segments:h}=s(r.waypoints,t,n,c,m,f,y,a,u);p.info("route",r);const I=Math.round(r.waypoints.reduce((t,{eta:n})=>t+n,0)),w=Math.round(r.waypoints.reduce((t,{distance:n})=>t+n,0));return{...r,segments:h,steps:g,time:I,distance:w}})}function b(n,o,e,i){let r=t.clone(n);return r=E(r,e,i),o&&o.length?{...r,transitTime:v(o,"transitTime"),distance:v(o,"distance")}:(r.distance="start"===i?O(r,e):O(e,r),r.transitTime=S(r.distance),r)}function v(n,o){return t.aperture(2,n).map(([n,o])=>{return(e=o.id,n=>t.find(t=>t.dst===e,n.edges))(n);var e}).map(t.prop(o)).reduce((t,n)=>t+n,0)}function E(t,n,o){return{...t,[o+"Information"]:{lat:n?.lat||n?.position?.latitude,lng:n?.lng||n?.position?.longitude,floorId:n?.floorId||n?.position?.floorId}}}function O(t,n){return e(n?.lat||n?.position?.latitude,n?.lng||n?.position?.longitude,t?.lat||t?.position?.latitude,t?.lng||t?.position?.longitude)}function S(t){return t/60}function L(n){const o=n.filter(t=>null!==t);return t.sortBy(t.propOr(1/0,"transitTime"),o)}function N(t,n){return t&&t.length?v(t,"transitTime"):S(n)}function P(t,n,o){return t&&t.length?v(t,"distance"):O(o,n)}return d.bus.on("wayfinder/getNavigationEndpoint",({ep:t})=>async function(t){return f.then(n=>{if(!t)throw Error("wayfinder: Invalid endpoint definition",t);if("number"==typeof t)return g(t,n.floorIdToOrdinal);if("string"==typeof t){if(t.match(/^\d+$/))return g(parseInt(t),n.floorIdToOrdinal);if(t.indexOf(",")>0){let[o,e,i,r]=t.split(",");if(!n.floorIdToStructureId(i))throw Error("Unknown floorId in endpoint: "+i);return r||(r="Starting Point"),{lat:parseFloat(o),lng:parseFloat(e),ordinal:n.floorIdToOrdinal(i),floorId:i,title:r}}}if(I(t))return t;if(t.latitude)return{lat:t.latitude,lng:t.longitude,floorId:t.floorId,ordinal:n.floorIdToOrdinal(t.floorId),title:t.title};if(t.position&&t.name)return w(t,n.floorIdToOrdinal);throw Error("Invalid start or end point: "+t)})}(t)),d.bus.on("wayfinder/checkIfPathHasSecurity",({fromEndpoint:n,toEndpoint:o,options:e={}})=>f.then(r=>{e.compareFindPaths=l.compareFindPaths;const a=i(r,n,o,e);if(!a)return{routeExists:!1};const s=n=>Boolean(a.waypoints.find(t.pathEq(n,["securityLane","type"])));return{routeExists:!0,queues:a.waypoints.filter(n=>t.pathEq(u.SECURITY,["securityLane","type"],n)||t.pathEq(u.IMMIGRATION,["securityLane","type"],n)),hasSecurity:s(u.SECURITY),hasImmigration:s(u.IMMIGRATION)}})),d.bus.on("wayfinder/getRoute",T),d.bus.on("wayfinder/addPathTimeMultiple",async({pois:n,startLocation:o,options:e={}})=>o?f.then(i=>function(n,o,e,i){try{const r=t.clone(e),a=r.map(t=>w(t,n.floorIdToOrdinal)),s=n.findAllShortestPaths(i,a,o);return L(r.map((t,n)=>b(t,s[n],i,"start")))}catch(t){return p.error(t),e}}(i,e,n,o)):n),d.bus.on("wayfinder/multipointAddPathTimeMultiple",async({pois:n,startLocation:o,endLocation:e,currentLocation:i,options:r={}})=>o||e||i?f.then(a=>function(n,o,e,i,r,a){try{const s=i?w(i,n.floorIdToOrdinal):a,u=r?w(r,n.floorIdToOrdinal):null,d=t.clone(e),l=d.map(t=>w(t,n.floorIdToOrdinal));let p,c,f;return s&&(p=n.findAllShortestPaths(s,l,o)),u&&(c=function(t,n,o,e){const i=[];for(const r of n)i.push(t.findShortestPath(r,o,e));return i}(n,l,u,o)),f=s&&u?d.map((n,o)=>function(n,o,e,i,r){const a=P(o,i,n),s=P(e,n,r);if(!a||!s)return null;const u=N(o,a),d=N(e,s);let l=t.clone(n);return l=E(l,i,"start"),l=E(l,r,"end"),{...l,transitTime:u+d,distance:a+s,startInformation:{...l.startInformation,transitTime:u,distance:a},endInformation:{...l.endInformation,transitTime:d,distance:s}}}(n,p[o],c[o],s,u)):s?d.map((t,n)=>b(t,p[n],s,"start")):d.map((t,n)=>b(t,c[n],u,"end")),L(f)}catch(t){return p.error(t),e}}(a,r,n,o,e,i)):n),d.bus.on("venueData/loadNewVenue",()=>{f=new n,c()}),d.bus.on("poi/setDynamicData",({plugin:t,idValuesMap:n})=>{"security"===t&&f.then(t=>t.updateWithSecurityWaitTime(n))}),d.bus.on("wayfinder/getNavGraphFeatures",()=>f.then(({_nodes:t})=>a(t))),{init:c,internal:{resolveNavGraph:t=>f.resolve(t),prepareSecurityLanes:m}}}export{u as SecurityLaneType,d as create};