parent
9f6a9a0943
commit
bd4bdd6b51
@ -0,0 +1,95 @@
|
||||
<!--
|
||||
Copyright 2021 Keith Paterson
|
||||
|
||||
This file is part of FG Airports.
|
||||
|
||||
FG Airports is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
|
||||
FG Airports is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with FG Airports. If not, see http://www.gnu.org/licenses/.
|
||||
-->
|
||||
<template>
|
||||
<div>
|
||||
<div v-for="item in traffic" v-bind:key="item.id">
|
||||
<div v-if="direction == 0">{{ item.departure.time }} {{ item.callsign }} {{ item.departure.port }} --> {{ item.arrival.port }}</div>
|
||||
<div v-if="direction == 1">{{ item.arrival.time }} {{ item.callsign }} {{ item.departure.port }} --> {{ item.arrival.port }}</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="js">
|
||||
import {readTrafficXML} from '../loaders/traffic_loader'
|
||||
import ParkingItem from './ParkingItem'
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
export default {
|
||||
name: 'airline-traffic',
|
||||
components: {ParkingItem},
|
||||
props: {airline: Object},
|
||||
data () {
|
||||
return {}
|
||||
},
|
||||
methods: {
|
||||
traverseDir (dir, airline) {
|
||||
var result = []
|
||||
if (!fs.existsSync(dir)) {
|
||||
return result
|
||||
}
|
||||
var iaco = airline.label
|
||||
fs.readdirSync(dir).forEach(file => {
|
||||
let fullPath = path.join(dir, file)
|
||||
if (fs.lstatSync(fullPath).isDirectory()) {
|
||||
var children = this.traverseDir(fullPath, airline)
|
||||
result = result.concat(children)
|
||||
} else {
|
||||
if (file.match(new RegExp(`${iaco}.xml`, 'i'))) {
|
||||
result.push(fullPath)
|
||||
}
|
||||
}
|
||||
})
|
||||
return result
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
direction: function () {
|
||||
return this.$parent.$parent.$parent.$data.direction
|
||||
},
|
||||
filename: function () {
|
||||
var ret = this.traverseDir(this.$store.state.Settings.settings.flightgearDirectory_traffic, this.airline)
|
||||
if (ret.length > 0) {
|
||||
return ret[0]
|
||||
}
|
||||
},
|
||||
trafficFile: function () {
|
||||
return readTrafficXML(this.filename)
|
||||
},
|
||||
traffic: function () {
|
||||
if (this.filename) {
|
||||
return this.trafficFile.filter(f => f.callsign).filter(f =>
|
||||
(f.departure.port === this.$store.state.Airports.currentAirport.icao && this.direction === 0) ||
|
||||
(f.arrival.port === this.$store.state.Airports.currentAirport.icao && this.direction === 1)
|
||||
)
|
||||
}
|
||||
console.debug(this.filename)
|
||||
},
|
||||
aircraft: function () {
|
||||
if (this.filename) {
|
||||
return this.trafficFile.filter(f => f.registration)
|
||||
}
|
||||
console.debug(this.filename)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
div.row.div {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
@ -0,0 +1,97 @@
|
||||
<!--
|
||||
Copyright 2021 Keith Paterson
|
||||
|
||||
This file is part of FG Airports.
|
||||
|
||||
FG Airports is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
|
||||
FG Airports is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with FG Airports. If not, see http://www.gnu.org/licenses/.
|
||||
-->
|
||||
<template>
|
||||
<div>
|
||||
<el-radio-group v-model="direction">
|
||||
<el-radio :label="departure"
|
||||
><i class="fas fa-plane-departure"></i
|
||||
></el-radio>
|
||||
<el-radio :label="arrival"><i class="fas fa-plane-arrival"></i></el-radio>
|
||||
</el-radio-group>
|
||||
<el-collapse v-model="activeName" accordion ref="collapse">
|
||||
<el-collapse-item
|
||||
v-for="a in airlines"
|
||||
v-bind:key="a.index"
|
||||
class="row"
|
||||
:title="a.label"
|
||||
:name="a.label"
|
||||
>
|
||||
<AirlineItem :airline="a" ref="airline"></AirlineItem>
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
<el-popover
|
||||
placement="top-start"
|
||||
title="Add Test Traffic"
|
||||
width="200"
|
||||
trigger="hover"
|
||||
content="Generate Testtraffic"
|
||||
>
|
||||
<el-button @click="generate" class="button" slot="reference">
|
||||
<i class="fas fa-notes-medical"></i>
|
||||
</el-button>
|
||||
</el-popover>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="js">
|
||||
import AirlineItem from './AirlineItem'
|
||||
import {writeTrafficXML} from '../loaders/traffic_writer'
|
||||
|
||||
export default {
|
||||
name: 'traffic-list',
|
||||
components: {AirlineItem},
|
||||
props: [],
|
||||
data () {
|
||||
return {
|
||||
activeName: '',
|
||||
departure: 0,
|
||||
arrival: 1,
|
||||
direction: 0,
|
||||
activeIndex: '1',
|
||||
activeIndex2: '1'
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
generate () {
|
||||
// .filter((f) => f.$children[0])
|
||||
var aircraft = this.$refs.airline.flatMap((f) => {
|
||||
console.debug(f.aircraft)
|
||||
return f.aircraft
|
||||
}
|
||||
).filter(f => f)
|
||||
|
||||
writeTrafficXML(this.$store.state.Settings.settings.flightgearDirectory_traffic, this.$store.state.Parkings.items, aircraft)
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
airlines: function () {
|
||||
var airlineCodes = []
|
||||
if (this.$store.state.Airports.currentAirport !== undefined && this.$store.state.Airports.currentAirport.airlines) {
|
||||
var storedairlineCodes = this.$store.state.Airports.currentAirport.airlines
|
||||
storedairlineCodes.forEach(element => {
|
||||
airlineCodes.push({value: element, label: element})
|
||||
})
|
||||
}
|
||||
return airlineCodes
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
div.row.div {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
@ -0,0 +1,122 @@
|
||||
/*
|
||||
Copyright 2021 Keith Paterson
|
||||
|
||||
This file is part of FG Airports.
|
||||
|
||||
FG Airports is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
|
||||
FG Airports is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with FG Airports. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
/* eslint-disable */
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
var xamel = require('xamel');
|
||||
|
||||
const store = require('../store');
|
||||
|
||||
const util = require('util');
|
||||
|
||||
exports.readTrafficXML = function (f) {
|
||||
try {
|
||||
var ret = [];
|
||||
var xmlTraffic = fs.readFileSync(f, 'utf8').toString();
|
||||
xamel.parse(xmlTraffic, function (err, xml) {
|
||||
console.debug("parsed " + path.basename(f));
|
||||
if (err !== null) {
|
||||
console.error("Error in " + airline);
|
||||
throw err;
|
||||
}
|
||||
|
||||
var requiredAircraft = xml.find('trafficlist/aircraft');
|
||||
console.log("Aircraft " + requiredAircraft.length);
|
||||
|
||||
ret.concat(requiredAircraft);
|
||||
var flights = xml.find('trafficlist/flight');
|
||||
console.log("Flights " + flights.length);
|
||||
ret.concat(flights);
|
||||
console.log(ret.length);
|
||||
ret = ret.concat(flights.map(flightMapper)).concat(requiredAircraft.map(aircraftMapper))
|
||||
return ret;
|
||||
});
|
||||
return ret;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* <flight>
|
||||
<callsign>Hebridean_1047</callsign>
|
||||
<required-aircraft>HBR_BN_2</required-aircraft>
|
||||
<fltrules>VFR</fltrules>
|
||||
<departure>
|
||||
<port>EGPU</port>
|
||||
<time>4/14:50:00</time>
|
||||
</departure>
|
||||
<cruise-alt>50</cruise-alt>
|
||||
<arrival>
|
||||
<port>EGEO</port>
|
||||
<time>4/15:50:00</time>
|
||||
</arrival>
|
||||
<repeat>WEEK</repeat>
|
||||
</flight>
|
||||
*/
|
||||
|
||||
function flightMapper(params) {
|
||||
return {
|
||||
id: `${btoa(buildId(params))}`,
|
||||
callsign: params.find('callsign').text(),
|
||||
arrival: {
|
||||
port: params.find('arrival/port').text(),
|
||||
time: params.find('arrival/time').text()
|
||||
},
|
||||
departure: {
|
||||
port: params.find('departure/port').text(),
|
||||
time: params.find('departure/time').text()
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function buildId(params) {
|
||||
return `${params.find('callsign').text()}_`+
|
||||
`${params.find('arrival/port').text()}_`+
|
||||
`${params.find('arrival/time').text()}_`+
|
||||
`${params.find('departure/port').text()}_` +
|
||||
`${params.find('departure/time').text()}`;
|
||||
}
|
||||
|
||||
/*
|
||||
<aircraft>
|
||||
<model>Aircraft/BN-2/BN-2-Hebridean.xml</model>
|
||||
<livery>HBR</livery>
|
||||
<airline>HBR</airline>
|
||||
<home-port>EGEO</home-port>
|
||||
<required-aircraft>HBR_BN_2</required-aircraft>
|
||||
<actype>BN2</actype>
|
||||
<offset>0</offset>
|
||||
<radius>8</radius>
|
||||
<flighttype>gate</flighttype>
|
||||
<performance-class>turboprop_transport</performance-class>
|
||||
<registration>G-HEBO</registration>
|
||||
<heavy>false</heavy>
|
||||
</aircraft>
|
||||
*/
|
||||
|
||||
function aircraftMapper(params) {
|
||||
return {
|
||||
model: params.find('model').text(),
|
||||
livery: params.find('livery').text(),
|
||||
airline: params.find('airline').text(),
|
||||
'home-port': params.find('home-port').text(),
|
||||
'required-aircraft': params.find('required-aircraft').text(),
|
||||
actype: params.find('actype').text(),
|
||||
offset: params.find('offset').text(),
|
||||
radius: params.find('radius').text(),
|
||||
flighttype: params.find('flighttype').text(),
|
||||
'performance-class': params.find('performance-class').text(),
|
||||
'registration': params.find('registration').text(),
|
||||
'heavy': params.find('heavy').text(),
|
||||
};
|
||||
}
|
@ -0,0 +1,180 @@
|
||||
/*
|
||||
Copyright 2021 Keith Paterson
|
||||
|
||||
This file is part of FG Airports.
|
||||
|
||||
FG Airports is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
|
||||
FG Airports is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with FG Airports. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
/* eslint-disable */
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const store = require('../store');
|
||||
|
||||
const util = require('util');
|
||||
|
||||
const mathjs = require('mathjs');
|
||||
|
||||
var builder = require('xmlbuilder');
|
||||
|
||||
var parkingStats = (acc, cur) => {
|
||||
if (!acc[cur.radius]) {
|
||||
acc[cur.radius] = { count: 0, radius: cur.radius }
|
||||
}
|
||||
acc[cur.radius].count += 1
|
||||
return acc
|
||||
};
|
||||
|
||||
/**
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<trafficlist xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="traffic.xsd">
|
||||
<aircraft>
|
||||
<model>Aircraft/BN-2/BN-2-Hebridean.xml</model>
|
||||
<livery>HBR</livery>
|
||||
<airline>HBR</airline>
|
||||
<home-port>EGEO</home-port>
|
||||
<required-aircraft>HBR_BN_2</required-aircraft>
|
||||
<actype>BN2</actype>
|
||||
<offset>0</offset>
|
||||
<radius>8</radius>
|
||||
<flighttype>gate</flighttype>
|
||||
<performance-class>turboprop_transport</performance-class>
|
||||
<registration>G-HEBS</registration>
|
||||
<heavy>false</heavy>
|
||||
</aircraft>
|
||||
<flight>
|
||||
<callsign>Hebridean_1047</callsign>
|
||||
<required-aircraft>HBR_BN_2</required-aircraft>
|
||||
<fltrules>VFR</fltrules>
|
||||
<departure>
|
||||
<port>EGPU</port>
|
||||
<time>4/14:50:00</time>
|
||||
</departure>
|
||||
<cruise-alt>50</cruise-alt>
|
||||
<arrival>
|
||||
<port>EGEO</port>
|
||||
<time>4/15:50:00</time>
|
||||
</arrival>
|
||||
<repeat>WEEK</repeat>
|
||||
</flight>
|
||||
</trafficlist>
|
||||
*/
|
||||
|
||||
var writeTrafficXML = function (fDir, parkings, aircraft) {
|
||||
try {
|
||||
var icao = store.default.state.Airports.currentAirport.icao;
|
||||
var aircraftList = aircraft;
|
||||
|
||||
try { fs.mkdirSync(path.join(fDir), { recursive: true }) } catch (err) { }
|
||||
try { fs.mkdirSync(path.join(fDir, 'TST'), { recursive: true }) } catch (err) { }
|
||||
|
||||
var f = path.join(fDir, 'TST', icao + '.xml');
|
||||
|
||||
|
||||
var parkingData = parkings.reduce(parkingStats, {});
|
||||
|
||||
/*
|
||||
*
|
||||
<flight>
|
||||
<callsign>Hebridean_1001</callsign>
|
||||
<required-aircraft>HBR_BN_2</required-aircraft>
|
||||
<fltrules>VFR</fltrules>
|
||||
<departure>
|
||||
<port>EGEO</port>
|
||||
<time>2/14:10:00</time>
|
||||
</departure>
|
||||
<cruise-alt>50</cruise-alt>
|
||||
<arrival>
|
||||
<port>EGEY</port>
|
||||
<time>2/15:20:00</time>
|
||||
</arrival>
|
||||
<repeat>WEEK</repeat>
|
||||
</flight>
|
||||
*/
|
||||
|
||||
var flightMapper = function (pStat) {
|
||||
var ret = [];
|
||||
var blockSize = Math.min( pStat[1].count/6, 6);
|
||||
for (let index = 0; index < pStat[1].count; index++) {
|
||||
var aircraft = this[index];
|
||||
var minutes = `${Math.floor(index/blockSize)}`.padStart(2, '0');
|
||||
var seconds = `${index}`.padStart(2, '0');
|
||||
for (let weekday = 0; weekday < 7; weekday++) {
|
||||
ret.push({
|
||||
callsign: `Test_${index}_${weekday}`,
|
||||
'required-aircraft': aircraft['required-aircraft'],
|
||||
fltrules: 'VFR',
|
||||
departure: {
|
||||
port: icao,
|
||||
time: `${weekday}/12:${minutes}:${seconds}`
|
||||
},
|
||||
'cruise-alt': 50,
|
||||
arrival: {
|
||||
port: icao,
|
||||
time: `${weekday}/13:${minutes}:${seconds}`
|
||||
},
|
||||
repeat: 'WEEK'
|
||||
});
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
<aircraft>
|
||||
<model>Aircraft/BN-2/BN-2-Hebridean.xml</model>
|
||||
<livery>HBR</livery>
|
||||
<airline>HBR</airline>
|
||||
<home-port>EGEO</home-port>
|
||||
<required-aircraft>HBR_BN_2</required-aircraft>
|
||||
<actype>BN2</actype>
|
||||
<offset>0</offset>
|
||||
<radius>8</radius>
|
||||
<flighttype>gate</flighttype>
|
||||
<performance-class>turboprop_transport</performance-class>
|
||||
<registration>G-HEBO</registration>
|
||||
<heavy>false</heavy>
|
||||
</aircraft>
|
||||
|
||||
*/
|
||||
var aircraftMapper = function (pStat) {
|
||||
var ret = [];
|
||||
if (typeof this === 'undefined') {
|
||||
return;
|
||||
}
|
||||
var possibleAircraft = this.filter(a => a.radius <= pStat[1].radius);
|
||||
|
||||
for (let index = 0; index < pStat[1].count; index++) {
|
||||
var aircraft = possibleAircraft[Math.floor(Math.random() * possibleAircraft.length)];
|
||||
aircraft['required-aircraft'] = `GG-${index}`;
|
||||
aircraft.registration = `GG-${index}`;
|
||||
aircraft['home-port'] = icao;
|
||||
ret.push(aircraft);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
var aircraftList = Object.entries(parkingData).flatMap(aircraftMapper, aircraft).sort();
|
||||
var flightList = Object.entries(parkingData).flatMap(flightMapper, aircraftList).sort();
|
||||
|
||||
var xmlObj = { trafficList: { aircraft: aircraftList, flight: flightList } };
|
||||
|
||||
var xmlString = builder.create(xmlObj).end({ pretty: true });
|
||||
fs.writeFileSync(f, xmlString);
|
||||
console.debug(xmlString);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
export { writeTrafficXML as writeTrafficXML };
|
Loading…
Reference in new issue