fix: will I ever make relative paths work?

This commit is contained in:
Davide Passoni 2024-12-11 10:22:53 +01:00
parent e41d3c93a6
commit dc7fd2c870
30 changed files with 468 additions and 461 deletions

6
frontend/build.bat Normal file
View File

@ -0,0 +1,6 @@
cd react
call npm run build-release
cd ..
cd server
robocopy ./databases ./public/databases /E

View File

@ -3,12 +3,12 @@
"short_name": "DCS Olympus",
"icons": [
{
"src": "./images/favicons/android-chrome-192x192.png",
"src": "/images/favicons/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "./images/favicons/android-chrome-512x512.png",
"src": "/images/favicons/android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
}

View File

@ -31,7 +31,7 @@ export class ExplosionMarker extends CustomMarker {
var el = document.createElement("div");
el.classList.add("ol-explosion-icon");
var img = document.createElement("img");
img.src = "./images/markers/explosion.svg";
img.src = "/images/markers/explosion.svg";
img.onload = () => SVGInjector(img);
el.appendChild(img);
this.getElement()?.appendChild(el);

View File

@ -28,7 +28,7 @@ export class SmokeMarker extends CustomMarker {
el.classList.add("ol-smoke-icon");
el.setAttribute("data-color", this.#color);
var img = document.createElement("img");
img.src = "./images/markers/smoke.svg";
img.src = "/images/markers/smoke.svg";
img.onload = () => SVGInjector(img);
el.appendChild(img);
this.getElement()?.appendChild(el);

View File

@ -1,6 +1,6 @@
.airbase-icon {
align-items: center;
cursor: url("../images/cursors/pointer.svg"), auto;
cursor: url("/images/cursors/pointer.svg"), auto;
display: flex;
justify-content: center;
position: relative;

View File

@ -1,6 +1,6 @@
.bullseye-icon {
align-items: center;
cursor: url("../images/cursors/pointer.svg"), auto;
cursor: url("/images/cursors/pointer.svg"), auto;
display: flex;
justify-content: center;
position: relative;

View File

@ -1,6 +1,6 @@
/*** Unit marker elements ***/
[data-object|="unit"] {
cursor: url("../images/cursors/pointer.svg"), auto;
cursor: url("/images/cursors/pointer.svg"), auto;
display: flex;
height: 100%;
justify-content: center;
@ -9,29 +9,29 @@
}
[data-object|="unit"].attack-cursor {
cursor: url("../images/cursors/attack.svg"), auto !important;
cursor: url("/images/cursors/attack.svg"), auto !important;
}
[data-object|="unit"].follow-cursor {
cursor: url("../images/cursors/follow.svg"), auto !important;
cursor: url("/images/cursors/follow.svg"), auto !important;
}
[data-object|="unit"].fire-at-area-cursor,
[data-object|="unit"].bomb-cursor,
[data-object|="unit"].carpet-bomb-cursor {
cursor: url("../images/cursors/fire-at-area.svg"), auto !important;
cursor: url("/images/cursors/fire-at-area.svg"), auto !important;
}
[data-object|="unit"].land-cursor {
cursor: url("../images/cursors/land.svg"), auto !important;
cursor: url("/images/cursors/land.svg"), auto !important;
}
[data-object|="unit"].land-at-point-cursor {
cursor: url("../images/cursors/land-at-point.svg"), auto !important;
cursor: url("/images/cursors/land-at-point.svg"), auto !important;
}
[data-object|="unit"].simulate-fire-fight-cursor {
cursor: url("../images/cursors/simulate-fire-fight.svg"), auto !important;
cursor: url("/images/cursors/simulate-fire-fight.svg"), auto !important;
}
[data-awacs-mode] .unit-short-label {
@ -439,15 +439,15 @@
}
[data-object|="unit"][data-state="rtb"] .unit-state {
background-image: url("../images/states/rtb.svg");
background-image: url("/images/states/rtb.svg");
}
[data-object|="unit"][data-state="land"] .unit-state {
background-image: url("../images/states/rtb.svg");
background-image: url("/images/states/rtb.svg");
}
[data-object|="unit"][data-state="idle"] .unit-state {
background-image: url("../images/states/idle.svg");
background-image: url("/images/states/idle.svg");
}
[data-object*="groundunit"][data-state="idle"] .unit-state,
@ -459,59 +459,59 @@
[data-object|="unit"][data-state="bomb-point"] .unit-state,
[data-object|="unit"][data-state="carpet-bombing"] .unit-state,
[data-object|="unit"][data-state="fire-at-area"] .unit-state {
background-image: url("../images/states/attack.svg");
background-image: url("/images/states/attack.svg");
}
[data-object|="unit"][data-state="follow"] .unit-state {
background-image: url("../images/states/follow.svg");
background-image: url("/images/states/follow.svg");
}
[data-object|="unit"][data-state="refuel"] .unit-state {
background-image: url("../images/states/refuel.svg");
background-image: url("/images/states/refuel.svg");
}
[data-object|="unit"][data-state="human"] .unit-state {
background-image: url("../images/states/human.svg");
background-image: url("/images/states/human.svg");
}
[data-object|="unit"][data-state="dcs"] .unit-state {
background-image: url("../images/states/dcs.svg");
background-image: url("/images/states/dcs.svg");
}
[data-object|="unit"][data-state="land-at-point"] .unit-state {
background-image: url("../images/states/land-at-point.svg");
background-image: url("/images/states/land-at-point.svg");
}
[data-object|="unit"][data-state="no-task"] .unit-state {
background-image: url("../images/states/no-task.svg");
background-image: url("/images/states/no-task.svg");
}
[data-object|="unit"][data-state="off"] .unit-state {
background-image: url("../images/states/off.svg");
background-image: url("/images/states/off.svg");
}
[data-object|="unit"][data-state="tanker"] .unit-state {
background-image: url("../images/states/tanker.svg");
background-image: url("/images/states/tanker.svg");
}
[data-object|="unit"][data-state="AWACS"] .unit-state {
background-image: url("../images/states/awacs.svg");
background-image: url("/images/states/awacs.svg");
}
[data-object|="unit"][data-state="miss-on-purpose"] .unit-state {
background-image: url("../images/states/miss-on-purpose.svg");
background-image: url("/images/states/miss-on-purpose.svg");
}
[data-object|="unit"][data-state="scenic-aaa"] .unit-state {
background-image: url("../images/states/scenic-aaa.svg");
background-image: url("/images/states/scenic-aaa.svg");
}
[data-object|="unit"][data-state="simulate-fire-fight"] .unit-state {
background-image: url("../images/states/simulate-fire-fight.svg");
background-image: url("/images/states/simulate-fire-fight.svg");
}
[data-object|="unit"] .unit-health::before {
background-image: url("../images/icons/health.svg");
background-image: url("/images/icons/health.svg");
background-repeat: no-repeat;
background-size: contain;
content: " ";

View File

@ -56,7 +56,7 @@ export class TemporaryUnitMarker extends CustomMarker {
var unitIcon = document.createElement("div");
unitIcon.classList.add("unit-icon");
var img = document.createElement("img");
img.src = `./images/units/map/${getApp().getMap().getOptions().AWACSMode ? "awacs" : "normal"}/${this.#coalition}/${blueprint.markerFile ?? blueprint.category}.svg`;
img.src = `/images/units/map/${getApp().getMap().getOptions().AWACSMode ? "awacs" : "normal"}/${this.#coalition}/${blueprint.markerFile ?? blueprint.category}.svg`;
img.onload = () => SVGInjector(img);
unitIcon.appendChild(img);
unitIcon.toggleAttribute("data-rotate-to-heading", false);

View File

@ -132,7 +132,7 @@
}
.ol-target-icon {
background-image: url("../images/markers/target.svg");
background-image: url("/images/markers/target.svg");
height: 100%;
width: 100%;
}
@ -184,53 +184,53 @@ path.leaflet-interactive:focus {
}
.attack-cursor {
cursor: url("../images/cursors/attack.svg"), auto !important;
cursor: url("/images/cursors/attack.svg"), auto !important;
}
.follow-cursor {
cursor: url("../images/cursors/follow.svg"), auto !important;
cursor: url("/images/cursors/follow.svg"), auto !important;
}
.fire-at-area-cursor, .bomb-cursor, .carpet-bomb-cursor {
cursor: url("../images/cursors/fire-at-area.svg"), auto !important;
cursor: url("/images/cursors/fire-at-area.svg"), auto !important;
}
.land-cursor {
cursor: url("../images/cursors/land.svg"), auto !important;
cursor: url("/images/cursors/land.svg"), auto !important;
}
.land-at-point-cursor {
cursor: url("../images/cursors/land-at-point.svg"), auto !important;
cursor: url("/images/cursors/land-at-point.svg"), auto !important;
}
.simulate-fire-fight-cursor {
cursor: url("../images/cursors/simulate-fire-fight.svg"), auto !important;
cursor: url("/images/cursors/simulate-fire-fight.svg"), auto !important;
}
#map-container.leaflet-grab {
cursor: url("../images/cursors/grab.svg") 16 16, auto;
cursor: url("/images/cursors/grab.svg") 16 16, auto;
}
.explosion-cursor {
cursor: url("../images/cursors/explosion.svg"), auto !important;
cursor: url("/images/cursors/explosion.svg"), auto !important;
}
.smoke-white-cursor {
cursor: url("../images/cursors/smoke-white.svg"), auto !important;
cursor: url("/images/cursors/smoke-white.svg"), auto !important;
}
.smoke-blue-cursor {
cursor: url("../images/cursors/smoke-blue.svg"), auto !important;
cursor: url("/images/cursors/smoke-blue.svg"), auto !important;
}
.smoke-red-cursor {
cursor: url("../images/cursors/smoke-red.svg"), auto !important;
cursor: url("/images/cursors/smoke-red.svg"), auto !important;
}
.smoke-green-cursor {
cursor: url("../images/cursors/smoke-green.svg"), auto !important;
cursor: url("/images/cursors/smoke-green.svg"), auto !important;
}
.smoke-orange-cursor {
cursor: url("../images/cursors/smoke-orange.svg"), auto !important;
cursor: url("/images/cursors/smoke-orange.svg"), auto !important;
}

View File

@ -67,7 +67,7 @@ export class Airbase extends CustomMarker {
el.classList.add("airbase-icon");
el.setAttribute("data-object", "airbase");
this.#img.src = "./images/markers/airbase.svg";
this.#img.src = "/images/markers/airbase.svg";
this.#img.onload = () => SVGInjector(this.#img);
el.appendChild(this.#img);
this.getElement()?.appendChild(el);

View File

@ -23,7 +23,7 @@ export class Bullseye extends CustomMarker {
el.classList.add("bullseye-icon");
el.setAttribute("data-object", "bullseye");
var img = document.createElement("img");
img.src = "./images/markers/bullseye.svg";
img.src = "/images/markers/bullseye.svg";
img.onload = () => SVGInjector(img);
el.appendChild(img);
this.getElement()?.appendChild(el);

View File

@ -15,7 +15,7 @@ export class Carrier extends Airbase {
el.classList.add("airbase-icon");
el.setAttribute("data-object", "airbase");
this.getImg().src = "./images/carriers/nimitz.png";
this.getImg().src = "/images/carriers/nimitz.png";
this.getImg().style.width = `0px`; // Make the image immediately small to avoid giant carriers
el.appendChild(this.getImg());
this.getElement()?.appendChild(el);

View File

@ -44,7 +44,7 @@ export function OlUnitListEntry(props: {
invert
`}>
<img
src={`./images/units/${props.silhouette}`}
src={`/images/units/${props.silhouette}`}
className="my-auto max-h-full max-w-full"
/>
</div>

View File

@ -20,7 +20,7 @@ export function OlUnitSummary(props: { blueprint: UnitBlueprint; coalition: Coal
className={`
absolute right-5 top-0 h-full object-cover opacity-10 invert
`}
src={"vite./images/units/" + props.blueprint.filename}
src={"vite/images/units/" + props.blueprint.filename}
alt=""
/>
<div

View File

@ -94,7 +94,7 @@ export function LoginModal(props: { open: boolean }) {
max-md:border-none
`}
>
<img src="./images/splash/1.jpg" className={`
<img src="/images/splash/1.jpg" className={`
contents-center w-full object-cover opacity-[7%]
`}></img>
<div
@ -154,7 +154,7 @@ export function LoginModal(props: { open: boolean }) {
`}
>
<span className="size-[80px] min-w-14">
<img src="./images/olympus-500x500.png" className={`
<img src="/images/olympus-500x500.png" className={`
flex w-full
`}></img>
</span>
@ -360,7 +360,7 @@ export function LoginModal(props: { open: boolean }) {
>
<Card className="flex">
<img
src="./images/splash/1.jpg"
src="/images/splash/1.jpg"
className={`
h-[40%] max-h-[120px] contents-center w-full rounded-md
object-cover
@ -385,7 +385,7 @@ export function LoginModal(props: { open: boolean }) {
</Card>
<Card className="flex">
<img
src="./images/splash/1.jpg"
src="/images/splash/1.jpg"
className={`
h-[40%] max-h-[120px] contents-center w-full rounded-md
object-cover

View File

@ -349,7 +349,7 @@ export function FormationMenu(props: {
translate-y-[-50%] rotate-90 cursor-move opacity-80
invert
`}
src={`./images/units/${unit?.getBlueprint()?.filename}`}
src={`/images/units/${unit?.getBlueprint()?.filename}`}
></img>
</div>
);

View File

@ -66,8 +66,8 @@ import {
const bearingStrings = ["north", "north-east", "east", "south-east", "south", "south-west", "west", "north-west", "north"];
var pathIcon = new Icon({
iconUrl: "./images/markers/marker-icon.png",
shadowUrl: "./images/markers/marker-shadow.png",
iconUrl: "/images/markers/marker-icon.png",
shadowUrl: "/images/markers/marker-shadow.png",
iconAnchor: [13, 41],
});
@ -912,7 +912,7 @@ export abstract class Unit extends CustomMarker {
if (this.belongsToCommandedCoalition() || this.getDetectionMethods().some((value) => [VISUAL, OPTIC].includes(value)))
marker = this.getBlueprint()?.markerFile ?? this.getDefaultMarker();
else marker = "aircraft";
img.src = `./images/units/map/${getApp().getMap().getOptions().AWACSMode ? "awacs" : "normal"}/${this.getCoalition()}/${marker}.svg`;
img.src = `/images/units/map/${getApp().getMap().getOptions().AWACSMode ? "awacs" : "normal"}/${this.getCoalition()}/${marker}.svg`;
img.onload = () => SVGInjector(img);
unitIcon.appendChild(img);

View File

@ -178,7 +178,7 @@ export class Weapon extends CustomMarker {
var unitIcon = document.createElement("div");
unitIcon.classList.add("unit-icon");
var img = document.createElement("img");
img.src = `./images/units/map/${getApp().getMap().getOptions().AWACSMode ? "awacs" : "normal"}/${this.getCoalition()}/${this.getMarkerCategory()}.svg`;
img.src = `/images/units/map/${getApp().getMap().getOptions().AWACSMode ? "awacs" : "normal"}/${this.getCoalition()}/${this.getMarkerCategory()}.svg`;
img.onload = () => SVGInjector(img);
unitIcon.appendChild(img);
unitIcon.toggleAttribute("data-rotate-to-heading", this.getIconOptions().rotateToHeading);

View File

@ -6,10 +6,11 @@ export default defineConfig({
plugins: [react()],
base: "./",
build: {
outDir: '../server/public'
},esbuild: {
outDir: "../server/public",
emptyOutDir : true
},
esbuild: {
minifyIdentifiers: false,
keepNames: true,
}
},
});

View File

@ -1,399 +1,399 @@
{
"airfields": {
"Severomorsk-1": {
"runways": [
{
"headings": [
{
"14": {
"magHeading": "118",
"Heading": "135",
"ILS": ""
}
},
{
"32": {
"magHeading": "299",
"Heading": "315",
"ILS": ""
}
}
],
"length": "9084"
}
],
"TACAN": "",
"ICAO": "ULAK",
"elevation": "261"
},
"Banak": {
"runways": [
{
"headings": [
{
"34": {
"magHeading": "339",
"Heading": "352",
"ILS": "108.30"
}
},
{
"16": {
"magHeading": "159",
"Heading": "172",
"ILS": ""
}
}
],
"length": "8104"
}
],
"TACAN": "47X",
"ICAO": "ENNA",
"elevation": "17"
},
"Severomorsk-3": {
"runways": [
{
"headings": [
{
"35": {
"magHeading": "334",
"Heading": "351",
"ILS": ""
}
},
{
"17": {
"magHeading": "154",
"Heading": "171",
"ILS": ""
}
}
],
"length": "7497"
}
],
"TACAN": "",
"ICAO": "XLMV",
"elevation": "567"
},
"Kemi Tornio": {
"runways": [
{
"headings": [
{
"18": {
"magHeading": "173",
"Heading": "184",
"ILS": ""
}
},
{
"36": {
"magHeading": "355",
"Heading": "4",
"ILS": "110.90"
}
}
],
"length": "7862"
}
],
"TACAN": "",
"ICAO": "EFKE",
"elevation": "46"
},
"Murmansk International": {
"runways": [
{
"headings": [
{
"13": {
"magHeading": "119",
"Heading": "135",
"ILS": "110.30"
}
},
{
"31": {
"magHeading": "299",
"Heading": "315",
"ILS": "108.50"
}
}
],
"length": "7926"
}
],
"TACAN": "",
"ICAO": "ULMM",
"elevation": "249"
},
"Bodo": {
"runways": [
{
"headings": [
{
"07": {
"magHeading": "78",
"Heading": "84",
"ILS": "110.30"
}
},
{
"25": {
"magHeading": "257",
"Heading": "264",
"ILS": "108.70"
}
}
],
"length": "8618"
}
],
"TACAN": "45X",
"ICAO": "ENBO",
"elevation": "25"
},
"Rovaniemi": {
"runways": [
{
"headings": [
{
"21": {
"magHeading": "201",
"Heading": "213",
"ILS": "117.70"
}
},
{
"03": {
"magHeading": "21",
"Heading": "33",
"ILS": ""
}
}
],
"length": "9096"
}
],
"TACAN": "",
"ICAO": "EFRO",
"elevation": "612"
},
"Kalixfors": {
"runways": [
{
"headings": [
{
"17": {
"magHeading": "162",
"Heading": "171",
"ILS": ""
}
},
{
"35": {
"magHeading": "342",
"Heading": "351",
"ILS": ""
}
}
],
"length": "3597"
}
],
"TACAN": "",
"ICAO": "ESUK",
"elevation": "1552"
},
"Jokkmokk": {
"runways": [
{
"headings": [
{
"14": {
"magHeading": "136",
"Heading": "145",
"ILS": ""
}
},
{
"32": {
"magHeading": "316",
"Heading": "325",
"ILS": ""
}
}
],
"length": "6306"
},
{
"headings": [
{
"32": {
"magHeading": "323",
"Heading": "332",
"ILS": ""
}
},
{
"14": {
"magHeading": "143",
"Heading": "152",
"ILS": ""
}
}
],
"length": "6306"
},
{
"headings": [
{
"15": {
"magHeading": "124",
"Heading": "133",
"ILS": ""
}
},
{
"33": {
"magHeading": "302",
"Heading": "313",
"ILS": ""
}
}
],
"length": "3828"
},
{
"headings": [
{
"36": {
"magHeading": "354",
"Heading": "3",
"ILS": ""
}
},
{
"18": {
"magHeading": "174",
"Heading": "183",
"ILS": ""
}
}
],
"length": "3828"
}
],
"TACAN": "",
"ICAO": "ESNJ",
"elevation": "891"
},
"Monchegorsk": {
"runways": [
{
"headings": [
{
"01": {
"magHeading": "001",
"Heading": "16",
"ILS": ""
}
},
{
"19": {
"magHeading": "180",
"Heading": "196",
"ILS": ""
}
}
],
"length": "7509"
}
],
"TACAN": "",
"ICAO": "UMOE",
"elevation": "547"
},
"Olenya": {
"runways": [
{
"headings": [
{
"19": {
"magHeading": "171",
"Heading": "188",
"ILS": ""
}
},
{
"01": {
"magHeading": "352",
"Heading": "8",
"ILS": ""
}
}
],
"length": "10863"
}
],
"TACAN": "",
"ICAO": "UOLE",
"elevation": "721"
},
"Bas 100": {
"runways": [
{
"headings": [
{
"22": {
"magHeading": "210",
"Heading": "223",
"ILS": ""
}
},
{
"04": {
"magHeading": "31",
"Heading": "43",
"ILS": ""
}
}
],
"length": "7719"
}
],
"TACAN": "",
"ICAO": "",
"elevation": "735"
},
"Kiruna": {
"runways": [
{
"headings": [
{
"21": {
"magHeading": "204",
"Heading": "214",
"ILS": "110.30"
}
},
{
"03": {
"magHeading": "25",
"Heading": "34",
"ILS": ""
}
}
],
"length": "7432"
}
],
"TACAN": "",
"ICAO": "ESNQ",
"elevation": "1434"
}
}
{
"airfields": {
"Severomorsk-1": {
"runways": [
{
"headings": [
{
"14": {
"magHeading": "118",
"Heading": "135",
"ILS": ""
}
},
{
"32": {
"magHeading": "299",
"Heading": "315",
"ILS": ""
}
}
],
"length": "9084"
}
],
"TACAN": "",
"ICAO": "ULAK",
"elevation": "261"
},
"Banak": {
"runways": [
{
"headings": [
{
"34": {
"magHeading": "339",
"Heading": "352",
"ILS": "108.30"
}
},
{
"16": {
"magHeading": "159",
"Heading": "172",
"ILS": ""
}
}
],
"length": "8104"
}
],
"TACAN": "47X",
"ICAO": "ENNA",
"elevation": "17"
},
"Severomorsk-3": {
"runways": [
{
"headings": [
{
"35": {
"magHeading": "334",
"Heading": "351",
"ILS": ""
}
},
{
"17": {
"magHeading": "154",
"Heading": "171",
"ILS": ""
}
}
],
"length": "7497"
}
],
"TACAN": "",
"ICAO": "XLMV",
"elevation": "567"
},
"Kemi Tornio": {
"runways": [
{
"headings": [
{
"18": {
"magHeading": "173",
"Heading": "184",
"ILS": ""
}
},
{
"36": {
"magHeading": "355",
"Heading": "4",
"ILS": "110.90"
}
}
],
"length": "7862"
}
],
"TACAN": "",
"ICAO": "EFKE",
"elevation": "46"
},
"Murmansk International": {
"runways": [
{
"headings": [
{
"13": {
"magHeading": "119",
"Heading": "135",
"ILS": "110.30"
}
},
{
"31": {
"magHeading": "299",
"Heading": "315",
"ILS": "108.50"
}
}
],
"length": "7926"
}
],
"TACAN": "",
"ICAO": "ULMM",
"elevation": "249"
},
"Bodo": {
"runways": [
{
"headings": [
{
"07": {
"magHeading": "78",
"Heading": "84",
"ILS": "110.30"
}
},
{
"25": {
"magHeading": "257",
"Heading": "264",
"ILS": "108.70"
}
}
],
"length": "8618"
}
],
"TACAN": "45X",
"ICAO": "ENBO",
"elevation": "25"
},
"Rovaniemi": {
"runways": [
{
"headings": [
{
"21": {
"magHeading": "201",
"Heading": "213",
"ILS": "117.70"
}
},
{
"03": {
"magHeading": "21",
"Heading": "33",
"ILS": ""
}
}
],
"length": "9096"
}
],
"TACAN": "",
"ICAO": "EFRO",
"elevation": "612"
},
"Kalixfors": {
"runways": [
{
"headings": [
{
"17": {
"magHeading": "162",
"Heading": "171",
"ILS": ""
}
},
{
"35": {
"magHeading": "342",
"Heading": "351",
"ILS": ""
}
}
],
"length": "3597"
}
],
"TACAN": "",
"ICAO": "ESUK",
"elevation": "1552"
},
"Jokkmokk": {
"runways": [
{
"headings": [
{
"14": {
"magHeading": "136",
"Heading": "145",
"ILS": ""
}
},
{
"32": {
"magHeading": "316",
"Heading": "325",
"ILS": ""
}
}
],
"length": "6306"
},
{
"headings": [
{
"32": {
"magHeading": "323",
"Heading": "332",
"ILS": ""
}
},
{
"14": {
"magHeading": "143",
"Heading": "152",
"ILS": ""
}
}
],
"length": "6306"
},
{
"headings": [
{
"15": {
"magHeading": "124",
"Heading": "133",
"ILS": ""
}
},
{
"33": {
"magHeading": "302",
"Heading": "313",
"ILS": ""
}
}
],
"length": "3828"
},
{
"headings": [
{
"36": {
"magHeading": "354",
"Heading": "3",
"ILS": ""
}
},
{
"18": {
"magHeading": "174",
"Heading": "183",
"ILS": ""
}
}
],
"length": "3828"
}
],
"TACAN": "",
"ICAO": "ESNJ",
"elevation": "891"
},
"Monchegorsk": {
"runways": [
{
"headings": [
{
"01": {
"magHeading": "001",
"Heading": "16",
"ILS": ""
}
},
{
"19": {
"magHeading": "180",
"Heading": "196",
"ILS": ""
}
}
],
"length": "7509"
}
],
"TACAN": "",
"ICAO": "UMOE",
"elevation": "547"
},
"Olenya": {
"runways": [
{
"headings": [
{
"19": {
"magHeading": "171",
"Heading": "188",
"ILS": ""
}
},
{
"01": {
"magHeading": "352",
"Heading": "8",
"ILS": ""
}
}
],
"length": "10863"
}
],
"TACAN": "",
"ICAO": "UOLE",
"elevation": "721"
},
"Bas 100": {
"runways": [
{
"headings": [
{
"22": {
"magHeading": "210",
"Heading": "223",
"ILS": ""
}
},
{
"04": {
"magHeading": "31",
"Heading": "43",
"ILS": ""
}
}
],
"length": "7719"
}
],
"TACAN": "",
"ICAO": "",
"elevation": "735"
},
"Kiruna": {
"runways": [
{
"headings": [
{
"21": {
"magHeading": "204",
"Heading": "214",
"ILS": "110.30"
}
},
{
"03": {
"magHeading": "25",
"Heading": "34",
"ILS": ""
}
}
],
"length": "7432"
}
],
"TACAN": "",
"ICAO": "ESNQ",
"elevation": "1434"
}
}
}