Traffic Generator
This commit is contained in:
parent
9f6a9a0943
commit
bd4bdd6b51
95
src/renderer/components/AirlineItem.vue
Normal file
95
src/renderer/components/AirlineItem.vue
Normal file
@ -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>
|
||||||
|
|
||||||
|
|
@ -16,12 +16,13 @@ You should have received a copy of the GNU General Public License along with FG
|
|||||||
title="Add Airline"
|
title="Add Airline"
|
||||||
:visible.sync="dialogVisible"
|
:visible.sync="dialogVisible"
|
||||||
width="40%"
|
width="40%"
|
||||||
:before-close="handleClose">
|
:before-close="handleClose"
|
||||||
|
>
|
||||||
<span>Add an selectable airline to {{ icao }} {{ name }}</span>
|
<span>Add an selectable airline to {{ icao }} {{ name }}</span>
|
||||||
<el-input
|
<el-input
|
||||||
placeholder="Please input airline(s)"
|
placeholder="Please input airline(s)"
|
||||||
v-model="airlineCode"
|
v-model="airlineCode"
|
||||||
></el-input>
|
></el-input>
|
||||||
<span slot="footer" class="dialog-footer">
|
<span slot="footer" class="dialog-footer">
|
||||||
<el-button @click="dialogVisible = false">Cancel</el-button>
|
<el-button @click="dialogVisible = false">Cancel</el-button>
|
||||||
<el-button type="primary" @click="addAirline">Confirm</el-button>
|
<el-button type="primary" @click="addAirline">Confirm</el-button>
|
||||||
@ -31,116 +32,143 @@ You should have received a copy of the GNU General Public License along with FG
|
|||||||
title="Import File"
|
title="Import File"
|
||||||
:visible.sync="showImportFile"
|
:visible.sync="showImportFile"
|
||||||
width="20%"
|
width="20%"
|
||||||
:before-close="handleClose">
|
:before-close="handleClose"
|
||||||
<span>Beware wip will be overwritten</span>
|
>
|
||||||
<el-row>
|
<span>Beware wip will be overwritten</span>
|
||||||
<el-col :span="20">
|
<el-row>
|
||||||
<el-input
|
<el-col :span="20">
|
||||||
placeholder="Please input file"
|
<el-input placeholder="Please input file" v-model="fileImportName">
|
||||||
v-model="fileImportName">
|
</el-input>
|
||||||
</el-input>
|
</el-col>
|
||||||
</el-col>
|
<el-col :span="4">
|
||||||
<el-col :span="4">
|
<file-select @input="fileImportFileName"></file-select>
|
||||||
<file-select @input="fileImportFileName"></file-select>
|
</el-col>
|
||||||
</el-col>
|
</el-row>
|
||||||
</el-row>
|
|
||||||
<span slot="footer" class="dialog-footer">
|
<span slot="footer" class="dialog-footer">
|
||||||
<el-button @click="showImportFile = false">Cancel</el-button>
|
<el-button @click="showImportFile = false">Cancel</el-button>
|
||||||
<el-button type="primary" @click="importFile">Confirm</el-button>
|
<el-button type="primary" @click="importFile">Confirm</el-button>
|
||||||
</span>
|
</span>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
<h1 class="leaflet-sidebar-header">{{ icao }} {{ name }}</h1>
|
<h1 class="leaflet-sidebar-header">{{ icao }} {{ name }}</h1>
|
||||||
<div width="100%" >
|
<div width="100%">
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-popover
|
<el-popover
|
||||||
placement="top-start"
|
placement="top-start"
|
||||||
title="Description"
|
title="Description"
|
||||||
width="50"
|
width="50"
|
||||||
trigger="hover"
|
trigger="hover"
|
||||||
content="Edit"
|
content="Edit"
|
||||||
>
|
>
|
||||||
<el-button @click="edit" v-if="!editing" slot="reference"><i class="fas fa-edit"></i></el-button>
|
<el-button @click="edit" v-if="!editing" slot="reference"
|
||||||
</el-popover>
|
><i class="fas fa-edit"></i
|
||||||
<el-popover
|
></el-button>
|
||||||
placement="top-start"
|
</el-popover>
|
||||||
title="Description"
|
<el-popover
|
||||||
width="200"
|
placement="top-start"
|
||||||
trigger="hover"
|
title="Description"
|
||||||
content="Import groundnet"
|
width="200"
|
||||||
>
|
trigger="hover"
|
||||||
<el-button @click="showImportFile = true" v-if="!editing" slot="reference"><i class="fas fa-file-import"></i></el-button>
|
content="Import groundnet"
|
||||||
</el-popover>
|
>
|
||||||
<el-popover
|
<el-button
|
||||||
placement="top-start"
|
@click="showImportFile = true"
|
||||||
title="Description"
|
v-if="!editing"
|
||||||
width="220"
|
slot="reference"
|
||||||
trigger="hover"
|
><i class="fas fa-file-import"></i
|
||||||
content="Export groundnet to export directory"
|
></el-button>
|
||||||
>
|
</el-popover>
|
||||||
<el-button @click="test" v-if="!editing" slot="reference"><i class="fas fa-file-export"></i></el-button>
|
<el-popover
|
||||||
</el-popover>
|
placement="top-start"
|
||||||
<el-popover
|
title="Description"
|
||||||
placement="top-start"
|
width="220"
|
||||||
title="Description"
|
trigger="hover"
|
||||||
width="200"
|
content="Export groundnet to export directory"
|
||||||
trigger="hover"
|
>
|
||||||
content="Upload Airport"
|
<el-button @click="test" v-if="!editing" slot="reference"
|
||||||
>
|
><i class="fas fa-file-export"></i
|
||||||
<el-button @click="upload" v-if="!editing" slot="reference"><i class="fas fa-upload"></i></el-button>
|
></el-button>
|
||||||
</el-popover>
|
</el-popover>
|
||||||
</el-row>
|
<el-popover
|
||||||
<el-row>
|
placement="top-start"
|
||||||
<el-col :span="7"><span class="label"> Airlines :</span></el-col>
|
title="Description"
|
||||||
<el-col :span="15">
|
width="200"
|
||||||
<el-tag v-for="item in airlines" :key="item.value">{{item.value}}</el-tag>
|
trigger="hover"
|
||||||
</el-col>
|
content="Upload Airport"
|
||||||
<el-col :span="2">
|
>
|
||||||
<el-button @click="dialogVisible = true" v-if="editing" ><i class="fas fa-plus"></i></el-button>
|
<el-button @click="upload" v-if="!editing" slot="reference"
|
||||||
</el-col>
|
><i class="fas fa-upload"></i
|
||||||
</el-row>
|
></el-button>
|
||||||
|
</el-popover>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="7"><span class="label"> Airlines :</span></el-col>
|
||||||
|
<el-col :span="15">
|
||||||
|
<el-tag v-for="item in airlines" :key="item.value">{{
|
||||||
|
item.value
|
||||||
|
}}</el-tag>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="2">
|
||||||
|
<el-button @click="dialogVisible = true" v-if="editing"
|
||||||
|
><i class="fas fa-plus"></i
|
||||||
|
></el-button>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
</div>
|
</div>
|
||||||
<el-tabs v-model="activeTab" >
|
<el-tabs v-model="activeTab">
|
||||||
<el-tab-pane label="Frequencies" name="first">
|
<el-tab-pane label="Frequencies" name="first">
|
||||||
<div>
|
<div>
|
||||||
<el-row v-for="f in frequencyList" :key="f.index">
|
<el-row v-for="f in frequencyList" :key="f.index">
|
||||||
<Frequency :frequency="f"></Frequency>
|
<Frequency :frequency="f"></Frequency>
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-button @click="addFrequency" v-if="editing" >Add</el-button>
|
<el-button @click="addFrequency" v-if="editing">Add</el-button>
|
||||||
</div>
|
</div>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<el-tab-pane label="Parkings" name="second">
|
<el-tab-pane label="Parkings" name="second">
|
||||||
<ParkingList></ParkingList>
|
<ParkingList></ParkingList>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<el-tab-pane label="Statistics" name="third">
|
<el-tab-pane label="Statistics" name="third">
|
||||||
<el-row><el-col :span="8"><span class="label">Traffic :</span></el-col></el-row>
|
<el-row
|
||||||
|
><el-col :span="8"
|
||||||
|
><span class="label">Traffic :</span></el-col
|
||||||
|
></el-row
|
||||||
|
>
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="8">Flights :</el-col>
|
<el-col :span="8">Flights :</el-col>
|
||||||
<el-col :span="4">{{ flights }}</el-col>
|
<el-col :span="4">{{ flights }}</el-col>
|
||||||
<el-col :span="8"></el-col>
|
<el-col :span="8"></el-col>
|
||||||
<el-col :span="4"></el-col>
|
<el-col :span="4"></el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-row><el-col :span="16"><span class="label">GIT/Terrasync :</span></el-col></el-row>
|
<el-row
|
||||||
|
><el-col :span="16"
|
||||||
|
><span class="label">GIT/Terrasync :</span></el-col
|
||||||
|
></el-row
|
||||||
|
>
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="8">Parking Positions :</el-col>
|
<el-col :span="8">Parking Positions :</el-col>
|
||||||
<el-col :span="4">{{ parking }}</el-col>
|
<el-col :span="4">{{ parking }}</el-col>
|
||||||
<el-col :span="8">Groundnet Nodes :</el-col>
|
<el-col :span="8">Groundnet Nodes :</el-col>
|
||||||
<el-col :span="4">{{groundnet}}</el-col>
|
<el-col :span="4">{{ groundnet }}</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-row><el-col :span="8"><span class="label">Work :</span></el-col></el-row>
|
<el-row
|
||||||
|
><el-col :span="8"><span class="label">Work :</span></el-col></el-row
|
||||||
|
>
|
||||||
<el-row v-if="wip">
|
<el-row v-if="wip">
|
||||||
<el-col :span="8">Work Parking Positions :</el-col>
|
<el-col :span="8">Work Parking Positions :</el-col>
|
||||||
<el-col :span="4">{{ wipparking }}</el-col>
|
<el-col :span="4">{{ wipparking }}</el-col>
|
||||||
<el-col :span="8">Work Groundnet Nodes :</el-col>
|
<el-col :span="8">Work Groundnet Nodes :</el-col>
|
||||||
<el-col :span="4">{{wipgroundnet}}</el-col>
|
<el-col :span="4">{{ wipgroundnet }}</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-row v-if="wip">
|
<el-row v-if="wip">
|
||||||
<el-col :span="4">Saved :</el-col>
|
<el-col :span="4">Saved :</el-col>
|
||||||
<el-col :span="8" class="text">{{date}}</el-col>
|
<el-col :span="8" class="text">{{ date }}</el-col>
|
||||||
<el-col :span="4">Uploaded :</el-col>
|
<el-col :span="4">Uploaded :</el-col>
|
||||||
<el-col :span="8" class="text">{{upload_date}}</el-col>
|
<el-col :span="8" class="text">{{ upload_date }}</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
</el-tabs>
|
<el-tab-pane label="Traffic" name="fourth">
|
||||||
|
<TrafficList></TrafficList>
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -149,8 +177,9 @@ You should have received a copy of the GNU General Public License along with FG
|
|||||||
import FileSelect from './FileSelect'
|
import FileSelect from './FileSelect'
|
||||||
import Frequency from './Frequency'
|
import Frequency from './Frequency'
|
||||||
import ParkingList from './ParkingList'
|
import ParkingList from './ParkingList'
|
||||||
|
import TrafficList from './TrafficList'
|
||||||
import Upload from './Upload'
|
import Upload from './Upload'
|
||||||
|
|
||||||
const fs = require('fs')
|
const fs = require('fs')
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
|
|
||||||
@ -159,7 +188,7 @@ export default {
|
|||||||
return {showImportFile: false, activeTab: 'first', editing: false, uploadVisible: false, dialogVisible: false, airlineCode: '', fileImport: null}
|
return {showImportFile: false, activeTab: 'first', editing: false, uploadVisible: false, dialogVisible: false, airlineCode: '', fileImport: null}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
EditButton, FileSelect, Frequency, ParkingList, Upload
|
EditButton, FileSelect, Frequency, ParkingList, TrafficList, Upload
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
fileImportFileName (f) {
|
fileImportFileName (f) {
|
||||||
@ -291,10 +320,10 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.el-row {
|
.el-row {
|
||||||
padding: 0em;
|
padding: 0em;
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
}
|
}
|
||||||
.label {
|
.label {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: left;
|
justify-content: left;
|
||||||
|
@ -1,3 +1,14 @@
|
|||||||
|
<!--
|
||||||
|
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>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<el-link v-if="!editing" type="primary" @click="show(parking.index)">{{parking.name}} {{number}} {{parking.type}}</el-link>
|
<el-link v-if="!editing" type="primary" @click="show(parking.index)">{{parking.name}} {{number}} {{parking.type}}</el-link>
|
||||||
|
97
src/renderer/components/TrafficList.vue
Normal file
97
src/renderer/components/TrafficList.vue
Normal file
@ -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>
|
||||||
|
|
||||||
|
|
@ -23,9 +23,9 @@ function addFrequencies (type, value) {
|
|||||||
value.split(' ').forEach(frequencyValue => {
|
value.split(' ').forEach(frequencyValue => {
|
||||||
if( value.length > 0) {
|
if( value.length > 0) {
|
||||||
var frequency = {type: type, value: frequencyValue};
|
var frequency = {type: type, value: frequencyValue};
|
||||||
frequencies.push(frequency);
|
frequencies.push(frequency);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.addFeature = function (feature) {
|
exports.addFeature = function (feature) {
|
||||||
@ -38,10 +38,10 @@ exports.listSaves = function (fDir, icao) {
|
|||||||
var ret = files
|
var ret = files
|
||||||
.filter(f => f.includes(icao) )
|
.filter(f => f.includes(icao) )
|
||||||
.filter(f => f.includes('groundnet') )
|
.filter(f => f.includes('groundnet') )
|
||||||
.map(f => {
|
.map(f => {
|
||||||
try {
|
try {
|
||||||
var fileDate = fs.lstatSync(path.join(directory, f));
|
var fileDate = fs.lstatSync(path.join(directory, f));
|
||||||
return {file: f, mtime: `${fileDate.mtime}`, mtimeMs: `${fileDate.mtimeMs}`};
|
return {file: f, mtime: `${fileDate.mtime}`, mtimeMs: `${fileDate.mtimeMs}`};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
@ -99,7 +99,7 @@ exports.readGroundnetXML = function (fDir, icao, f) {
|
|||||||
addFrequencies('UNICOM', unicom);
|
addFrequencies('UNICOM', unicom);
|
||||||
|
|
||||||
store.default.dispatch('setFrequencies', frequencies);
|
store.default.dispatch('setFrequencies', frequencies);
|
||||||
|
|
||||||
var parkingNodes = xml.find('groundnet/parkingList/Parking');
|
var parkingNodes = xml.find('groundnet/parkingList/Parking');
|
||||||
console.debug("Parking Nodes length" + parkingNodes.length);
|
console.debug("Parking Nodes length" + parkingNodes.length);
|
||||||
|
|
||||||
@ -118,9 +118,9 @@ exports.readGroundnetXML = function (fDir, icao, f) {
|
|||||||
layerGroup.maxId = Math.max(layerGroup.maxId, Number(n.attr('index')))
|
layerGroup.maxId = Math.max(layerGroup.maxId, Number(n.attr('index')))
|
||||||
features.push(circle);
|
features.push(circle);
|
||||||
}).sort();
|
}).sort();
|
||||||
|
|
||||||
store.default.dispatch('setParkings', parkingNodes.map(
|
store.default.dispatch('setParkings', parkingNodes.map(
|
||||||
p => ({index: Number(p.attrs.index), name: String(p.attrs.name), number: String(p.attrs.number), type: String(p.attrs.type)}
|
p => ({index: Number(p.attrs.index), radius: Number(p.attrs.radius), name: String(p.attrs.name), number: String(p.attrs.number), type: String(p.attrs.type)}
|
||||||
)).sort((p1, p2) => {
|
)).sort((p1, p2) => {
|
||||||
if (p1.name === p2.name) {
|
if (p1.name === p2.name) {
|
||||||
return p1.number?p1.number.localeCompare(p2.number):-1;
|
return p1.number?p1.number.localeCompare(p2.number):-1;
|
||||||
@ -134,7 +134,7 @@ exports.readGroundnetXML = function (fDir, icao, f) {
|
|||||||
//attrs.lat
|
//attrs.lat
|
||||||
//console.log(n.attr('lat') + " " + n.attr('lon'));
|
//console.log(n.attr('lat') + " " + n.attr('lon'));
|
||||||
try {
|
try {
|
||||||
var latlon = convert(n.attr('lat') + " " + n.attr('lon'));
|
var latlon = convert(n.attr('lat') + " " + n.attr('lon'));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn(n.attr('lat') + " " + n.attr('lon'));
|
console.warn(n.attr('lat') + " " + n.attr('lon'));
|
||||||
convert(n.attr('lat') + " " + n.attr('lon'));
|
convert(n.attr('lat') + " " + n.attr('lon'));
|
||||||
@ -186,7 +186,7 @@ exports.readGroundnetXML = function (fDir, icao, f) {
|
|||||||
if (element instanceof L.Polyline && element.end === n.attr('begin') && element.begin === n.attr('end')) {
|
if (element instanceof L.Polyline && element.end === n.attr('begin') && element.begin === n.attr('end')) {
|
||||||
element.bidirectional = true;
|
element.bidirectional = true;
|
||||||
element.options.attributes.direction = 'bi-directional'
|
element.options.attributes.direction = 'bi-directional'
|
||||||
bidirectional = true;
|
bidirectional = true;
|
||||||
element.updateStyle();
|
element.updateStyle();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -194,11 +194,11 @@ exports.readGroundnetXML = function (fDir, icao, f) {
|
|||||||
if (!bidirectional) {
|
if (!bidirectional) {
|
||||||
var beginlatlon = convert(beginNode.attr('lat') + " " + beginNode.attr('lon'));
|
var beginlatlon = convert(beginNode.attr('lat') + " " + beginNode.attr('lon'));
|
||||||
var endlatlon = convert(endNode.attr('lat') + " " + endNode.attr('lon'));
|
var endlatlon = convert(endNode.attr('lat') + " " + endNode.attr('lon'));
|
||||||
|
|
||||||
var pane = 'route-pane';
|
var pane = 'route-pane';
|
||||||
if(n.attr('isPushBackRoute') === '1') {
|
if(n.attr('isPushBackRoute') === '1') {
|
||||||
pane = 'pushback-pane';
|
pane = 'pushback-pane';
|
||||||
}
|
}
|
||||||
|
|
||||||
var polyline = new L.Polyline([[beginlatlon.decimalLatitude, beginlatlon.decimalLongitude], [endlatlon.decimalLatitude, endlatlon.decimalLongitude]], { pane: pane, attributes: {} }).addTo(layerGroup);
|
var polyline = new L.Polyline([[beginlatlon.decimalLatitude, beginlatlon.decimalLongitude], [endlatlon.decimalLatitude, endlatlon.decimalLongitude]], { pane: pane, attributes: {} }).addTo(layerGroup);
|
||||||
extendTaxiSegment(polyline);
|
extendTaxiSegment(polyline);
|
||||||
|
122
src/renderer/loaders/traffic_loader.js
Normal file
122
src/renderer/loaders/traffic_loader.js
Normal file
@ -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(),
|
||||||
|
};
|
||||||
|
}
|
180
src/renderer/loaders/traffic_writer.js
Normal file
180
src/renderer/loaders/traffic_writer.js
Normal file
@ -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 };
|
@ -43,7 +43,7 @@ const mutations = {
|
|||||||
|
|
||||||
const actions = {
|
const actions = {
|
||||||
async addParking (context, p) {
|
async addParking (context, p) {
|
||||||
context.commit('ADD_FREADD_PARKINGQUENCY', p)
|
context.commit('ADD_PARKING', p)
|
||||||
},
|
},
|
||||||
async updatedParking (context, p) {
|
async updatedParking (context, p) {
|
||||||
context.commit('UPDATE_PARKING', p)
|
context.commit('UPDATE_PARKING', p)
|
||||||
|
Loading…
Reference in New Issue
Block a user