548 lines
22 KiB
JavaScript
548 lines
22 KiB
JavaScript
/* eslint-disable */
|
|
const winURL = process.env.NODE_ENV === 'development'
|
|
? `http://localhost:9080/src/renderer/utils/`
|
|
: `file://${process.resourcesPath}/workers/`
|
|
|
|
var path = require('path');
|
|
const fs = require('fs');
|
|
//debugger;
|
|
var turf;
|
|
|
|
var check_msg;
|
|
|
|
if (process.env.NODE_ENV === 'development') {
|
|
importScripts('../../../node_modules/dijkstrajs/dijkstra.js');
|
|
turf = require('./node_modules/@turf/turf');
|
|
} else if (process.env.NODE_ENV === 'mocha') {
|
|
importScripts('../../../node_modules/dijkstrajs/dijkstra.js');
|
|
turf = require('../../../node_modules/@turf/turf')
|
|
} else {
|
|
importScripts('dijkstra.js');
|
|
turf = require('@turf/turf')
|
|
}
|
|
|
|
const homedir = require('os').homedir();
|
|
|
|
importScripts('logger.js');
|
|
importScripts('haversine.js');
|
|
|
|
function errorReceiver(event) {
|
|
throw event.data;
|
|
}
|
|
|
|
onmessage = function (event) {
|
|
postMessage('checkStarted');
|
|
logger('info', 'Check Started');
|
|
console.log(event.data);
|
|
if (event.data[0] === 'check') {
|
|
checkGroundnet(event.data[1]).then(result => {
|
|
console.log("DONE Checking");
|
|
postMessage(['DONE', result]);
|
|
// event.origin.webContents.send('scanFinished');
|
|
}
|
|
).catch(result => {
|
|
console.error('Crashed');
|
|
console.error(result);
|
|
postMessage(['DONE', [{ id: -1, message: ['Crashed', result] }]]);
|
|
});
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Implements the checks of the groundnet
|
|
* @param {*} data
|
|
*/
|
|
|
|
async function checkGroundnet(data) {
|
|
var promise = new Promise(function (resolve, reject) {
|
|
try {
|
|
const fName = process.env.NODE_ENV === 'development'
|
|
? './src/renderer/utils/check_msg.json'
|
|
: path.join(`${process.resourcesPath}`, 'workers', 'check_msg.json');
|
|
check_msg = JSON.parse(fs.readFileSync(fName, 'utf8').toString());
|
|
//debugger;
|
|
var parkings = data.map(mapParkings).filter(n => n !== undefined);
|
|
var runwayNodeIDs = data.map(mapRunwayNodeId).filter(n => n !== undefined);
|
|
var runwayNodes = data.map(mapRunwayNode).filter(n => n !== undefined);
|
|
var pushbackNodes = data.map(mapPushbackNodes).filter(n => n !== undefined);
|
|
var edges = data.map(mapEdges).filter(n => n !== undefined);
|
|
|
|
var normalNodes = data.map(mapEdges).filter(n => n !== undefined)
|
|
.flatMap(m => m.latLngs).filter(n => runwayNodeIDs.indexOf(Number(n.index)) < 0);
|
|
|
|
var takeoffPads = data.map(mapTakeoffPads).filter(n => n !== undefined);
|
|
|
|
this.max = 30;
|
|
this.postMessage(['max', this.max]);
|
|
|
|
var boxes = {};
|
|
//debugger;
|
|
data.forEach(element => {
|
|
//debugger;
|
|
if (element.box !== undefined && element.box !== null) {
|
|
boxes[element.index] = element.box[0].map(latlng => [latlng.lat, latlng.lng]);
|
|
boxes[element.index].push(boxes[element.index][0]);
|
|
}
|
|
});
|
|
var directionalGraph = {};
|
|
var bidirectionalGraph = {};
|
|
|
|
console.debug(parkings);
|
|
parkings.forEach(element => {
|
|
directionalGraph[element] = {};
|
|
bidirectionalGraph[element] = {};
|
|
});
|
|
runwayNodeIDs.forEach(element => {
|
|
directionalGraph[element] = {};
|
|
bidirectionalGraph[element] = {};
|
|
});
|
|
var notOkNodes = [];
|
|
//debugger;
|
|
|
|
console.debug(edges);
|
|
if (edges === undefined) {
|
|
resolve([{ id: -1, message: check_msg.NO_EDGES }]);
|
|
}
|
|
this.postMessage(['progress', 1]);
|
|
//debugger;
|
|
if (takeoffPads.length === 0) {
|
|
resolve([{ id: -1, message: check_msg.NO_RUNWAYS }]);
|
|
}
|
|
this.postMessage(['progress', 1]);
|
|
edges.forEach(edge => {
|
|
directionalGraph[edge.start] = {};
|
|
bidirectionalGraph[edge.start] = {};
|
|
directionalGraph[edge.end] = {};
|
|
bidirectionalGraph[edge.end] = {};
|
|
if (edge.latLngs !== undefined) {
|
|
// Check if there are segments > 2km
|
|
edge.latLngs.forEach((latLng, index, arr) => {
|
|
if (index > 0) {
|
|
var d = distance([arr[index - 1].lng, arr[index - 1].lat], [latLng.lng, latLng.lat]);
|
|
if (d > 2000) {
|
|
notOkNodes.push({ id: Number(arr[index - 1].index), message: check_msg.LONG_ROUTE_START });
|
|
notOkNodes.push({ id: Number(arr[index].index), message: check_msg.LONG_ROUTE_END });
|
|
}
|
|
//console.log(d);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
this.postMessage(['progress', 1]);
|
|
this.postMessage(['progress', 1]);
|
|
// Add edges to graphs
|
|
edges.forEach(element => {
|
|
var node1 = directionalGraph[element.start];
|
|
var node2 = directionalGraph[element.end];
|
|
if (element.direction === undefined) {
|
|
notOkNodes.push({ id: Number(element._leaflet_id), message: check_msg.EDGE_MISSING_DIRECTION });
|
|
}
|
|
if (element.direction === 'bi-directional' || element.direction === 'forward') {
|
|
node1[Number(element.end)] = 1;
|
|
}
|
|
if (element.direction === 'bi-directional' || element.direction === 'backward') {
|
|
node2[Number(element.start)] = 1;
|
|
}
|
|
|
|
var node3 = bidirectionalGraph[element.start];
|
|
var node4 = bidirectionalGraph[element.end];
|
|
node3[Number(element.end)] = 1;
|
|
node4[Number(element.start)] = 1;
|
|
});
|
|
this.postMessage(['progress', 1]);
|
|
var isLegitEnd = function (v) {
|
|
if (bidirectionalGraph[v] === undefined) {
|
|
debugger;
|
|
}
|
|
if (Object.keys(bidirectionalGraph[v]).length <= 1) {
|
|
return true;
|
|
}
|
|
return Object.keys(bidirectionalGraph[v]).filter(v => runwayNodeIDs[v]).length === 0;
|
|
}
|
|
runwayNodeIDs = runwayNodeIDs.filter(
|
|
(v, i) => isLegitEnd(v)
|
|
);
|
|
// Check if there is a route from every parking to every runway node
|
|
var okNodes = [];
|
|
logger('info', directionalGraph);
|
|
parkings.forEach(parkingNode => {
|
|
runwayNodeIDs.forEach(runwayNode => {
|
|
var ok = checkRoute(directionalGraph, parkingNode, runwayNode);
|
|
if (ok) {
|
|
okNodes.push(parkingNode);
|
|
okNodes.push(runwayNode);
|
|
} else {
|
|
console.log(`No route from Parking ${parkingNode} to Runwaynode ${runwayNode}`);
|
|
}
|
|
|
|
});
|
|
});
|
|
// Build pushback directionalGraph
|
|
var noPushbackGraph = {};
|
|
parkings.forEach(element => {
|
|
noPushbackGraph[element] = {};
|
|
});
|
|
pushbackNodes.forEach(element => {
|
|
noPushbackGraph[element] = {};
|
|
});
|
|
edges.filter(element => element.isPushBackRoute).forEach(element => {
|
|
noPushbackGraph[element.start] = {};
|
|
noPushbackGraph[element.end] = {};
|
|
});
|
|
// add all pushback edges
|
|
edges.filter(element => element.isPushBackRoute).forEach(element => {
|
|
var node1 = noPushbackGraph[Number(element.start)];
|
|
node1[Number(element.end)] = 1;
|
|
var node2 = noPushbackGraph[Number(element.end)];
|
|
node2[Number(element.start)] = 1;
|
|
});
|
|
|
|
|
|
var okPushbacks = [];
|
|
// Check pushback
|
|
var multiplePushbackRoutes = {};
|
|
parkings.forEach(parkingNode => {
|
|
pushbackNodes.forEach(pushbackNode => {
|
|
var numRoutes = checkRoute(noPushbackGraph, parkingNode, pushbackNode);
|
|
if (numRoutes === 0) {
|
|
if (multiplePushbackRoutes[parkingNode] === undefined &&
|
|
Object.keys(noPushbackGraph[parkingNode]) > 0) {
|
|
// Only when there is a edge leaving
|
|
multiplePushbackRoutes[parkingNode] = [];
|
|
}
|
|
} else if (numRoutes === 1) {
|
|
if (multiplePushbackRoutes[parkingNode] === undefined) {
|
|
multiplePushbackRoutes[parkingNode] = [pushbackNode];
|
|
} else {
|
|
multiplePushbackRoutes[parkingNode].push(pushbackNode);
|
|
}
|
|
} else if (numRoutes > 1) {
|
|
if (multiplePushbackRoutes[parkingNode] === undefined) {
|
|
multiplePushbackRoutes[parkingNode] = [pushbackNode];
|
|
} else {
|
|
multiplePushbackRoutes[parkingNode].push(pushbackNode);
|
|
}
|
|
}
|
|
|
|
});
|
|
});
|
|
var notConnectedToPushback = pushbackNodes.map(
|
|
id => {
|
|
var normalRoutes = bidirectionalGraph[id];
|
|
var pushbackRoutes = noPushbackGraph[id];
|
|
if (Object.keys(pushbackRoutes).length < 1)
|
|
return { id: id, message: check_msg.PUSHBACK_NOT_CONNECTED }
|
|
}).filter(n => n !== undefined);
|
|
this.postMessage(['progress', 1]);
|
|
var multipleTaxiRoutes = pushbackNodes.map(
|
|
id => {
|
|
var normalRoutes = bidirectionalGraph[id];
|
|
var pushbackRoutes = noPushbackGraph[id];
|
|
if (normalRoutes !== undefined) {
|
|
var nonPushbackRoutes = Object.keys(normalRoutes).filter(r => pushbackRoutes[r] === undefined);
|
|
if (nonPushbackRoutes.length > 1)
|
|
return { id: id, message: check_msg.TO_MANY_PUSHBACK_TAXI_ROUTES }
|
|
}
|
|
}).filter(n => n !== undefined);
|
|
this.postMessage(['progress', 1]);
|
|
var pushbackExitNotBidirectional = pushbackNodes.map(
|
|
id => {
|
|
var normalRoutes = bidirectionalGraph[id];
|
|
var pushbackRoutes = noPushbackGraph[id];
|
|
if (normalRoutes !== undefined) {
|
|
var nonPushbackRoutes = Object.keys(normalRoutes).filter(r => pushbackRoutes[r] === undefined);
|
|
if(nonPushbackRoutes.length > 0) {
|
|
var returnRoute = Object.keys(bidirectionalGraph[nonPushbackRoutes[0]]).map(id => Number(id)).filter(retId =>id === retId);
|
|
if (returnRoute.length === 0)
|
|
return { id: id, message: check_msg.PUSHBACK_EXIT_NOT_BIDRECTIONAL }
|
|
}
|
|
}
|
|
}).filter(n => n !== undefined);
|
|
this.postMessage(['progress', 1]);
|
|
var rogueHoldPoints = pushbackNodes.map(
|
|
id => {
|
|
var routes = noPushbackGraph[id];
|
|
if (Object.keys(routes).length < 1)
|
|
return { id: id, message: check_msg.UNCONNECTED_PUSHBACK }
|
|
/*
|
|
else if(Object.keys(routes).length>1)
|
|
return { id: id, message: 'Multiple connected pushback node' }
|
|
*/
|
|
}
|
|
).filter(n => n !== undefined);
|
|
this.postMessage(['progress', 1]);
|
|
var wrongPushbackRoutes = parkings.filter(
|
|
function (e) {
|
|
return this[e] != undefined && this[e].length != 1;
|
|
}
|
|
, multiplePushbackRoutes).map(
|
|
id => {
|
|
var endPoints = multiplePushbackRoutes[id];
|
|
if (endPoints.length < 1)
|
|
return { id: id, message: check_msg.NO_WAY_TO_HOLDPOINT }
|
|
else
|
|
return { id: id, message: check_msg.MULTIPLE_PUSHBACK }
|
|
}
|
|
);
|
|
|
|
|
|
this.postMessage(['progress', 1]);
|
|
okNodes = okNodes.filter((v, i) => okNodes.indexOf(v) === i);
|
|
var notOkNodesParkings = parkings.filter(
|
|
(v, i) => okNodes.indexOf(v) < 0
|
|
).map(
|
|
id => { return { id: id, message: check_msg.NO_RUNWAY_ROUTE } }
|
|
);
|
|
this.postMessage(['progress', 1]);
|
|
|
|
var notOkNodesRunways = runwayNodeIDs.filter(
|
|
(v, i) => okNodes.indexOf(v) < 0
|
|
).map(
|
|
id => { return { id: id, message: check_msg.NO_PARKING_ROUTE } }
|
|
);
|
|
this.postMessage(['progress', 1]);
|
|
|
|
if (parkings.length === 0) {
|
|
notOkNodes.push({ id: -2, message: check_msg.NO_PARKINGS });
|
|
}
|
|
this.postMessage(['progress', 1]);
|
|
if (runwayNodeIDs.length === 0) {
|
|
notOkNodes.push({ id: -2, message: check_msg.NO_RUNWAY_NODES });
|
|
}
|
|
this.postMessage(['progress', 1]);
|
|
var allEnds = Object.entries(bidirectionalGraph).filter(
|
|
(v, i) => Object.keys(v[1]).length <= 1
|
|
);
|
|
// Ends that are not on Runway and not a Parking or Pushback
|
|
var allLegitimateEndNodes = parkings.concat(runwayNodeIDs).concat(pushbackNodes);
|
|
var danglingEnds = allEnds.filter(
|
|
(v, i) => allLegitimateEndNodes.indexOf(Number(v[0])) < 0
|
|
).map(
|
|
v => { return { id: Number(v[0]), message: check_msg.NOT_LEGIT_END } }
|
|
);
|
|
this.postMessage(['progress', 1]);
|
|
|
|
var parkingNodes = data.map(mapParkingNode).filter(n => n !== undefined);
|
|
|
|
var overlappingParkings = [];
|
|
parkingNodes.forEach(parkingNode => {
|
|
if (boxes[parkingNode.index] === undefined) {
|
|
overlappingParkings.push({ id: parkingNode.index, message: check_msg.UNKNOWN_RADIUS });
|
|
}
|
|
});
|
|
// Check for intersecting radii
|
|
parkingNodes.forEach(parkingNode => {
|
|
parkingNodes.forEach(parkingNode1 => {
|
|
console.log(parkingNode, parkingNode1);
|
|
if (parkingNode.index !== parkingNode1.index) {
|
|
var d = distance([parkingNode.lng, parkingNode.lat],
|
|
[parkingNode1.lng, parkingNode1.lat]);
|
|
if (d < parkingNode.radius + parkingNode1.radius + 10) {
|
|
// If bigger circles intersect we should check the boxes
|
|
if (boxes[parkingNode.index] !== null && boxes[parkingNode1.index] !== null &&
|
|
boxes[parkingNode.index] !== undefined && boxes[parkingNode1.index] !== undefined) {
|
|
var poly1 = turf.polygon([boxes[parkingNode.index]]);
|
|
|
|
var poly2 = turf.polygon([boxes[parkingNode1.index]]);
|
|
|
|
var intersection = turf.intersect(poly1, poly2);
|
|
if (intersection !== null) {
|
|
overlappingParkings.push({ id: parkingNode.index, message: check_msg.OVERLAPPING_PARKINGS });
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
});
|
|
});
|
|
this.postMessage(['progress', 1]);
|
|
var invalidParkings = [];
|
|
// Check for name
|
|
parkingNodes.forEach(parkingNode => {
|
|
if (!parkingNode.name || /^\s*$/.test(parkingNode.name)) {
|
|
invalidParkings.push({ id: parkingNode.index, message: check_msg.NAME_EMPTY });
|
|
|
|
}
|
|
if (!parkingNode.type) {
|
|
invalidParkings.push({ id: parkingNode.index, message: check_msg.TYPE_EMPTY });
|
|
|
|
}
|
|
if (['ga', 'cargo', 'gate', 'mil-fighter', 'mil-cargo'].indexOf(parkingNode.parkingType) < 0) {
|
|
invalidParkings.push({ id: parkingNode.index, message: check_msg.PARKING_TYPE_INVALID });
|
|
}
|
|
});
|
|
this.postMessage(['progress', 1]);
|
|
this.postMessage(['progress', 1]);
|
|
|
|
//Check for dual pushback/runway nodes
|
|
runwayNodeIDs.forEach(runwayNode => {
|
|
if (pushbackNodes.indexOf(runwayNode) >= 0) {
|
|
notOkNodes.push({ id: runwayNode, message: check_msg.DUAL_PUSHBACK });
|
|
}
|
|
});
|
|
this.postMessage(['progress', 1]);
|
|
//Check if runwaynodes are on runway
|
|
runwayNodes.forEach(runwayNode => {
|
|
// debugger;
|
|
if (takeoffPads.filter(r => turf.booleanContains(r, latToTurf(runwayNode))).length === 0) {
|
|
notOkNodes.push({ id: runwayNode.index, message: check_msg.RUNWAY_NODE_NOT_ON_RUNWAY });
|
|
}
|
|
});
|
|
this.postMessage(['progress', 1]);
|
|
|
|
//Check if nodes no normal nodes are on runway
|
|
normalNodes.forEach(normalNode => {
|
|
//debugger;
|
|
if (takeoffPads.filter(r => turf.booleanContains(r, latToTurf(normalNode))).length > 0) {
|
|
notOkNodes.push({ id: normalNode.index, message: check_msg.NON_RUNWAYNODE_ON_RUNWAY });
|
|
}
|
|
});
|
|
this.postMessage(['progress', 1]);
|
|
|
|
var doubleEdges = edges.filter((v, i, a) => a.findIndex(t => (t.start === v.start && t.end === v.end) ) !== i);
|
|
doubleEdges.forEach(e => {
|
|
notOkNodes.push({ id: e.id, message: check_msg.DOUBLE_EDGE });
|
|
});
|
|
|
|
// debugger;
|
|
|
|
notOkNodes = notOkNodes.concat(invalidParkings);
|
|
if (invalidParkings.length === 0) {
|
|
notOkNodes.push({ id: -1, message: check_msg.PARKINGS_VALID });
|
|
}
|
|
notOkNodes = notOkNodes.concat(overlappingParkings);
|
|
if (overlappingParkings.length === 0) {
|
|
notOkNodes.push({ id: -1, message: check_msg.NO_OVERLAPPING_PARKINGS });
|
|
}
|
|
notOkNodes = notOkNodes.concat(danglingEnds);
|
|
if (danglingEnds.length === 0) {
|
|
notOkNodes.push({ id: -1, message: check_msg.NO_INVALID_ENDS });
|
|
}
|
|
notOkNodes = notOkNodes.concat(notOkNodesParkings).concat(rogueHoldPoints);
|
|
if (notOkNodesParkings.length === 0 && rogueHoldPoints === 0) {
|
|
notOkNodes.push({ id: -1, message: check_msg.ROUTES_FROM_PARKINGS_OK });
|
|
}
|
|
|
|
notOkNodes = notOkNodes.concat(notOkNodesRunways);
|
|
if (notOkNodesRunways.length === 0) {
|
|
notOkNodes.push({ id: -1, message: check_msg.ROUTES_FROM_RUNWAYS_OK });
|
|
}
|
|
notOkNodes = notOkNodes.concat(wrongPushbackRoutes);
|
|
notOkNodes = notOkNodes.concat(notConnectedToPushback);
|
|
notOkNodes = notOkNodes.concat(multipleTaxiRoutes);
|
|
notOkNodes = notOkNodes.concat(pushbackExitNotBidirectional);
|
|
if (wrongPushbackRoutes.length === 0 &&
|
|
notConnectedToPushback.length === 0 &&
|
|
multipleTaxiRoutes.length === 0 &&
|
|
pushbackExitNotBidirectional.length === 0
|
|
) {
|
|
notOkNodes.push({ id: -1, message: check_msg.PUSHBACK_ROUTES_OK });
|
|
}
|
|
resolve(notOkNodes);
|
|
} catch (error) {
|
|
reject(error);
|
|
}
|
|
});
|
|
return promise;
|
|
}
|
|
|
|
function checkRoute(directionalGraph, from, to) {
|
|
try {
|
|
var pathD = this.dijkstra.find_path(directionalGraph, from, to);
|
|
if (pathD.length > 0) {
|
|
console.log(pathD);
|
|
return pathD.length;
|
|
}
|
|
return 0;
|
|
} catch (error) {
|
|
// console.error(error);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
function check1(directionalGraph) {
|
|
var directionalGraph1 = {
|
|
a: { b: 1, d: 1 },
|
|
b: { a: 1, c: 1, e: 1 },
|
|
c: { b: 1, f: 1 },
|
|
d: { a: 1, e: 1, g: 1 },
|
|
e: { b: 1, d: 1, f: 1, h: 1 },
|
|
f: { c: 1, e: 1, i: 1 },
|
|
g: { d: 1, h: 1 },
|
|
h: { e: 1, g: 1, i: 1 },
|
|
i: { f: 1, h: 1 }
|
|
};
|
|
var path = this.dijkstra.find_path(directionalGraph, 'a', 'i');
|
|
console.log(path);
|
|
}
|
|
|
|
function check2(params) {
|
|
|
|
}
|
|
|
|
var mapPushbackNodes = function (o) {
|
|
if (o.type === 'PushBack') {
|
|
return o.index;
|
|
}
|
|
}
|
|
|
|
var mapParkings = function (o) {
|
|
if (o.type === 'parking')
|
|
return o.index;
|
|
}
|
|
|
|
var mapParkingNode = function (o) {
|
|
// debugger;
|
|
if (o.type === 'parking')
|
|
return { index: o.index, lat: o.lat, lng: o.lng, name: o.name, radius: Number(o.radius), type: o.type, parkingType: o.parkingType };
|
|
console.debug(o);
|
|
}
|
|
|
|
var mapBoxes = function (o) {
|
|
// debugger;
|
|
if (o.type === 'parking')
|
|
return { index: o.index };
|
|
}
|
|
|
|
var mapRunwayNodeId = function (o) {
|
|
if (o.type === 'runway')
|
|
return o.index;
|
|
console.debug(o);
|
|
}
|
|
|
|
var mapRunwayNode = function (o) {
|
|
if (o.type === 'runway') {
|
|
return { index: o.index, lat: o.lat, lng: o.lng };
|
|
}
|
|
}
|
|
|
|
var mapTakeoffPads = function (o) {
|
|
if (o.type === 'takeoffpad_poly') {
|
|
var pts = o.pavement[0].map(latLngToArray);
|
|
pts.push(pts[0]);
|
|
return turf.polygon([pts]);
|
|
}
|
|
}
|
|
|
|
var mapEdges = function (o) {
|
|
if (o.type === 'poly')
|
|
return {
|
|
id: o._leaflet_id, start: o.start, end: o.end, isPushBackRoute: o.isPushBackRoute !== undefined &&
|
|
o.isPushBackRoute !== 0, direction: o.direction, latLngs: o.latLngs
|
|
};
|
|
}
|
|
|
|
var latToTurf = function (turfPoint) {
|
|
return turf.point([turfPoint.lng, turfPoint.lat]);
|
|
};
|
|
|
|
var latLngToArray = function (turfPoint) {
|
|
//debugger;
|
|
|
|
return [turfPoint.lng, turfPoint.lat];
|
|
};
|
|
|
|
var turfToLatLng = function (turfPoint) {
|
|
return '' + turfPoint.geometry.coordinates[1].toFixed(6) + ',' + turfPoint.geometry.coordinates[0].toFixed(6);
|
|
};
|