Continue migration to node express typescript
582
client/package-lock.json
generated
@@ -5,6 +5,7 @@
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "client",
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"@types/geojson": "^7946.0.10",
|
||||
@@ -14,10 +15,13 @@
|
||||
"ejs": "^3.1.8",
|
||||
"express": "~4.16.1",
|
||||
"leaflet": "^1.9.3",
|
||||
"morgan": "~1.9.1"
|
||||
"milsymbol": "^2.0.0",
|
||||
"morgan": "~1.9.1",
|
||||
"save": "^2.9.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"browserify": "^17.0.0",
|
||||
"concurrently": "^7.6.0",
|
||||
"tsify": "^5.0.4",
|
||||
"typescript": "^4.9.4",
|
||||
"watchify": "^4.0.0"
|
||||
@@ -80,6 +84,15 @@
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-regex": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
|
||||
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-styles": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
@@ -584,6 +597,20 @@
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/cliui": {
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
|
||||
"integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"string-width": "^4.2.0",
|
||||
"strip-ansi": "^6.0.1",
|
||||
"wrap-ansi": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
@@ -632,6 +659,48 @@
|
||||
"typedarray": "^0.0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/concurrently": {
|
||||
"version": "7.6.0",
|
||||
"resolved": "https://registry.npmjs.org/concurrently/-/concurrently-7.6.0.tgz",
|
||||
"integrity": "sha512-BKtRgvcJGeZ4XttiDiNcFiRlxoAeZOseqUvyYRUp/Vtd+9p1ULmeoSqGsDA+2ivdeDFpqrJvGvmI+StKfKl5hw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"chalk": "^4.1.0",
|
||||
"date-fns": "^2.29.1",
|
||||
"lodash": "^4.17.21",
|
||||
"rxjs": "^7.0.0",
|
||||
"shell-quote": "^1.7.3",
|
||||
"spawn-command": "^0.0.2-1",
|
||||
"supports-color": "^8.1.0",
|
||||
"tree-kill": "^1.2.2",
|
||||
"yargs": "^17.3.1"
|
||||
},
|
||||
"bin": {
|
||||
"conc": "dist/bin/concurrently.js",
|
||||
"concurrently": "dist/bin/concurrently.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.20.0 || ^14.13.0 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/open-cli-tools/concurrently?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/concurrently/node_modules/supports-color": {
|
||||
"version": "8.1.1",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
|
||||
"integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"has-flag": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/supports-color?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/console-browserify": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz",
|
||||
@@ -768,6 +837,19 @@
|
||||
"integrity": "sha512-Vy4dx7gquTeMcQR/hDkYLGUnwVil6vk4FOOct+djUnHOUWt+zJPJAaRIXaAFkPXtJjvlY7o3rfRu0/3hpnwoUA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/date-fns": {
|
||||
"version": "2.29.3",
|
||||
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz",
|
||||
"integrity": "sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.11"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/date-fns"
|
||||
}
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "2.6.9",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||
@@ -867,6 +949,11 @@
|
||||
"npm": ">=1.2"
|
||||
}
|
||||
},
|
||||
"node_modules/duplexer": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz",
|
||||
"integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg=="
|
||||
},
|
||||
"node_modules/duplexer2": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz",
|
||||
@@ -922,6 +1009,12 @@
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/emoji-regex": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/encodeurl": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
|
||||
@@ -939,6 +1032,15 @@
|
||||
"is-arrayish": "^0.2.1"
|
||||
}
|
||||
},
|
||||
"node_modules/escalade": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
|
||||
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/escape-html": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
|
||||
@@ -952,6 +1054,20 @@
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/event-stream": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/event-stream/-/event-stream-4.0.1.tgz",
|
||||
"integrity": "sha512-qACXdu/9VHPBzcyhdOWR5/IahhGMf0roTeZJfzz077GwylcDd90yOHLouhmv7GJ5XzPi6ekaQWd8AvPP2nOvpA==",
|
||||
"dependencies": {
|
||||
"duplexer": "^0.1.1",
|
||||
"from": "^0.1.7",
|
||||
"map-stream": "0.0.7",
|
||||
"pause-stream": "^0.0.11",
|
||||
"split": "^1.0.1",
|
||||
"stream-combiner": "^0.2.2",
|
||||
"through": "^2.3.8"
|
||||
}
|
||||
},
|
||||
"node_modules/events": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
|
||||
@@ -1106,6 +1222,11 @@
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/from": {
|
||||
"version": "0.1.7",
|
||||
"resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz",
|
||||
"integrity": "sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g=="
|
||||
},
|
||||
"node_modules/fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
@@ -1138,6 +1259,15 @@
|
||||
"integrity": "sha512-mBBwmeGTrxEMO4pMaaf/uUEFHnYtwr8FTe8Y/mer4rcV/bye0qGm6pw1bGZFGStxC5O76c5ZAVBGnqHmOaJpdQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/get-caller-file": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
|
||||
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "6.* || 8.* || >= 10.*"
|
||||
}
|
||||
},
|
||||
"node_modules/get-intrinsic": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz",
|
||||
@@ -1504,6 +1634,15 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-fullwidth-code-point": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
|
||||
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/is-generator-function": {
|
||||
"version": "1.0.10",
|
||||
"resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz",
|
||||
@@ -1628,12 +1767,28 @@
|
||||
"resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.3.tgz",
|
||||
"integrity": "sha512-iB2cR9vAkDOu5l3HAay2obcUHZ7xwUBBjph8+PGtmW/2lYhbLizWtG7nTeYht36WfOslixQF9D/uSIzhZgGMfQ=="
|
||||
},
|
||||
"node_modules/lodash": {
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/lodash.assign": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz",
|
||||
"integrity": "sha512-hFuH8TY+Yji7Eja3mGiuAxBqLagejScbG8GbG0j6o9vzn0YL14My+ktnqtZgFTosKymC9/44wP6s7xyuLfnClw=="
|
||||
},
|
||||
"node_modules/lodash.memoize": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz",
|
||||
"integrity": "sha512-eDn9kqrAmVUC1wmZvlQ6Uhde44n+tXpqPrN8olQJbttgh0oKclk+SF54P47VEGE9CEiMeRwAP8BaM7UHvBkz2A==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/map-stream": {
|
||||
"version": "0.0.7",
|
||||
"resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz",
|
||||
"integrity": "sha512-C0X0KQmGm3N2ftbTGBhSyuydQ+vV1LC3f3zPvT3RXHXNZrvfPZcoXp/N5DOa8vedX/rTMm2CjTtivFg2STJMRQ=="
|
||||
},
|
||||
"node_modules/md5.js": {
|
||||
"version": "1.3.5",
|
||||
"resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
|
||||
@@ -1685,6 +1840,11 @@
|
||||
"integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/milsymbol": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/milsymbol/-/milsymbol-2.0.0.tgz",
|
||||
"integrity": "sha512-GcBFrcIUr8jScaZqZb0SI2W6AbnUrPCTHu2kqHxduQjN2DIN8q5pY6ksSWfnJ4HlcIAWQhyotbdPIr1bBxFbwQ=="
|
||||
},
|
||||
"node_modules/mime": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz",
|
||||
@@ -1712,6 +1872,11 @@
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/mingo": {
|
||||
"version": "6.2.7",
|
||||
"resolved": "https://registry.npmjs.org/mingo/-/mingo-6.2.7.tgz",
|
||||
"integrity": "sha512-r+yKmrZ+6SjwGxSot+/3S8sP9+LCxWNueR6xppMx7BzV60OegjbeklWAf/UveyQi8PDW8g/mwrQSHZVY/5jBJQ=="
|
||||
},
|
||||
"node_modules/minimalistic-assert": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
|
||||
@@ -1951,6 +2116,14 @@
|
||||
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
|
||||
"integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="
|
||||
},
|
||||
"node_modules/pause-stream": {
|
||||
"version": "0.0.11",
|
||||
"resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz",
|
||||
"integrity": "sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==",
|
||||
"dependencies": {
|
||||
"through": "~2.3"
|
||||
}
|
||||
},
|
||||
"node_modules/pbkdf2": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz",
|
||||
@@ -2145,6 +2318,15 @@
|
||||
"node": ">=8.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/require-directory": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
|
||||
"integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/resolve": {
|
||||
"version": "1.22.1",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
|
||||
@@ -2172,6 +2354,15 @@
|
||||
"inherits": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/rxjs": {
|
||||
"version": "7.8.0",
|
||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.0.tgz",
|
||||
"integrity": "sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||
@@ -2182,6 +2373,17 @@
|
||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||
},
|
||||
"node_modules/save": {
|
||||
"version": "2.9.0",
|
||||
"resolved": "https://registry.npmjs.org/save/-/save-2.9.0.tgz",
|
||||
"integrity": "sha512-eg8+g8CjvehE/2C6EbLdtK1pINVD27pcJLj4M9PjWWhoeha/y5bWf4dp/0RF+OzbKTcG1bae9qi3PAqiR8CJTg==",
|
||||
"dependencies": {
|
||||
"async": "^3.2.2",
|
||||
"event-stream": "^4.0.1",
|
||||
"lodash.assign": "^4.2.0",
|
||||
"mingo": "^6.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/semver": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
@@ -2293,6 +2495,23 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/spawn-command": {
|
||||
"version": "0.0.2-1",
|
||||
"resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz",
|
||||
"integrity": "sha512-n98l9E2RMSJ9ON1AKisHzz7V42VDiBQGY6PB1BwRglz99wpVsSuGzQ+jOi6lFXBGVTCrRpltvjm+/XA+tpeJrg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/split": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz",
|
||||
"integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==",
|
||||
"dependencies": {
|
||||
"through": "2"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/statuses": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz",
|
||||
@@ -2331,6 +2550,15 @@
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/stream-combiner": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.2.2.tgz",
|
||||
"integrity": "sha512-6yHMqgLYDzQDcAkL+tjJDC5nSNuNIx0vZtRZeiPh7Saef7VHX9H5Ijn9l2VIol2zaNYlYEX6KyuT/237A58qEQ==",
|
||||
"dependencies": {
|
||||
"duplexer": "~0.1.1",
|
||||
"through": "~2.3.4"
|
||||
}
|
||||
},
|
||||
"node_modules/stream-combiner2": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz",
|
||||
@@ -2412,6 +2640,32 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"node_modules/string-width": {
|
||||
"version": "4.2.3",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
||||
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"emoji-regex": "^8.0.0",
|
||||
"is-fullwidth-code-point": "^3.0.0",
|
||||
"strip-ansi": "^6.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/strip-ansi": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
||||
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"ansi-regex": "^5.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/strip-bom": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
|
||||
@@ -2477,8 +2731,7 @@
|
||||
"node_modules/through": {
|
||||
"version": "2.3.8",
|
||||
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
|
||||
"integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==",
|
||||
"dev": true
|
||||
"integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg=="
|
||||
},
|
||||
"node_modules/through2": {
|
||||
"version": "2.0.5",
|
||||
@@ -2514,6 +2767,15 @@
|
||||
"node": ">=8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tree-kill": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz",
|
||||
"integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"tree-kill": "cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/tsconfig": {
|
||||
"version": "5.0.3",
|
||||
"resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-5.0.3.tgz",
|
||||
@@ -2547,6 +2809,12 @@
|
||||
"typescript": ">= 2.8"
|
||||
}
|
||||
},
|
||||
"node_modules/tslib": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
|
||||
"integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/tty-browserify": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz",
|
||||
@@ -2738,6 +3006,23 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/wrap-ansi": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
|
||||
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"ansi-styles": "^4.0.0",
|
||||
"string-width": "^4.1.0",
|
||||
"strip-ansi": "^6.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
@@ -2752,6 +3037,42 @@
|
||||
"engines": {
|
||||
"node": ">=0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/y18n": {
|
||||
"version": "5.0.8",
|
||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
|
||||
"integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/yargs": {
|
||||
"version": "17.6.2",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz",
|
||||
"integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"cliui": "^8.0.1",
|
||||
"escalade": "^3.1.1",
|
||||
"get-caller-file": "^2.0.5",
|
||||
"require-directory": "^2.1.1",
|
||||
"string-width": "^4.2.3",
|
||||
"y18n": "^5.0.5",
|
||||
"yargs-parser": "^21.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/yargs-parser": {
|
||||
"version": "21.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
|
||||
"integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
@@ -2800,6 +3121,12 @@
|
||||
"integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==",
|
||||
"dev": true
|
||||
},
|
||||
"ansi-regex": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
|
||||
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
|
||||
"dev": true
|
||||
},
|
||||
"ansi-styles": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
@@ -3220,6 +3547,17 @@
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"cliui": {
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
|
||||
"integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"string-width": "^4.2.0",
|
||||
"strip-ansi": "^6.0.1",
|
||||
"wrap-ansi": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
@@ -3262,6 +3600,34 @@
|
||||
"typedarray": "^0.0.6"
|
||||
}
|
||||
},
|
||||
"concurrently": {
|
||||
"version": "7.6.0",
|
||||
"resolved": "https://registry.npmjs.org/concurrently/-/concurrently-7.6.0.tgz",
|
||||
"integrity": "sha512-BKtRgvcJGeZ4XttiDiNcFiRlxoAeZOseqUvyYRUp/Vtd+9p1ULmeoSqGsDA+2ivdeDFpqrJvGvmI+StKfKl5hw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "^4.1.0",
|
||||
"date-fns": "^2.29.1",
|
||||
"lodash": "^4.17.21",
|
||||
"rxjs": "^7.0.0",
|
||||
"shell-quote": "^1.7.3",
|
||||
"spawn-command": "^0.0.2-1",
|
||||
"supports-color": "^8.1.0",
|
||||
"tree-kill": "^1.2.2",
|
||||
"yargs": "^17.3.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"supports-color": {
|
||||
"version": "8.1.1",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
|
||||
"integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"has-flag": "^4.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"console-browserify": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz",
|
||||
@@ -3385,6 +3751,12 @@
|
||||
"integrity": "sha512-Vy4dx7gquTeMcQR/hDkYLGUnwVil6vk4FOOct+djUnHOUWt+zJPJAaRIXaAFkPXtJjvlY7o3rfRu0/3hpnwoUA==",
|
||||
"dev": true
|
||||
},
|
||||
"date-fns": {
|
||||
"version": "2.29.3",
|
||||
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz",
|
||||
"integrity": "sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==",
|
||||
"dev": true
|
||||
},
|
||||
"debug": {
|
||||
"version": "2.6.9",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||
@@ -3467,6 +3839,11 @@
|
||||
"integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==",
|
||||
"dev": true
|
||||
},
|
||||
"duplexer": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz",
|
||||
"integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg=="
|
||||
},
|
||||
"duplexer2": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz",
|
||||
@@ -3518,6 +3895,12 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"emoji-regex": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
|
||||
"dev": true
|
||||
},
|
||||
"encodeurl": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
|
||||
@@ -3532,6 +3915,12 @@
|
||||
"is-arrayish": "^0.2.1"
|
||||
}
|
||||
},
|
||||
"escalade": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
|
||||
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
|
||||
"dev": true
|
||||
},
|
||||
"escape-html": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
|
||||
@@ -3542,6 +3931,20 @@
|
||||
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
|
||||
"integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="
|
||||
},
|
||||
"event-stream": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/event-stream/-/event-stream-4.0.1.tgz",
|
||||
"integrity": "sha512-qACXdu/9VHPBzcyhdOWR5/IahhGMf0roTeZJfzz077GwylcDd90yOHLouhmv7GJ5XzPi6ekaQWd8AvPP2nOvpA==",
|
||||
"requires": {
|
||||
"duplexer": "^0.1.1",
|
||||
"from": "^0.1.7",
|
||||
"map-stream": "0.0.7",
|
||||
"pause-stream": "^0.0.11",
|
||||
"split": "^1.0.1",
|
||||
"stream-combiner": "^0.2.2",
|
||||
"through": "^2.3.8"
|
||||
}
|
||||
},
|
||||
"events": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
|
||||
@@ -3676,6 +4079,11 @@
|
||||
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
|
||||
"integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q=="
|
||||
},
|
||||
"from": {
|
||||
"version": "0.1.7",
|
||||
"resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz",
|
||||
"integrity": "sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g=="
|
||||
},
|
||||
"fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
@@ -3701,6 +4109,12 @@
|
||||
"integrity": "sha512-mBBwmeGTrxEMO4pMaaf/uUEFHnYtwr8FTe8Y/mer4rcV/bye0qGm6pw1bGZFGStxC5O76c5ZAVBGnqHmOaJpdQ==",
|
||||
"dev": true
|
||||
},
|
||||
"get-caller-file": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
|
||||
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
|
||||
"dev": true
|
||||
},
|
||||
"get-intrinsic": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz",
|
||||
@@ -3966,6 +4380,12 @@
|
||||
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
|
||||
"dev": true
|
||||
},
|
||||
"is-fullwidth-code-point": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
|
||||
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
|
||||
"dev": true
|
||||
},
|
||||
"is-generator-function": {
|
||||
"version": "1.0.10",
|
||||
"resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz",
|
||||
@@ -4057,12 +4477,28 @@
|
||||
"resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.3.tgz",
|
||||
"integrity": "sha512-iB2cR9vAkDOu5l3HAay2obcUHZ7xwUBBjph8+PGtmW/2lYhbLizWtG7nTeYht36WfOslixQF9D/uSIzhZgGMfQ=="
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
||||
"dev": true
|
||||
},
|
||||
"lodash.assign": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz",
|
||||
"integrity": "sha512-hFuH8TY+Yji7Eja3mGiuAxBqLagejScbG8GbG0j6o9vzn0YL14My+ktnqtZgFTosKymC9/44wP6s7xyuLfnClw=="
|
||||
},
|
||||
"lodash.memoize": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz",
|
||||
"integrity": "sha512-eDn9kqrAmVUC1wmZvlQ6Uhde44n+tXpqPrN8olQJbttgh0oKclk+SF54P47VEGE9CEiMeRwAP8BaM7UHvBkz2A==",
|
||||
"dev": true
|
||||
},
|
||||
"map-stream": {
|
||||
"version": "0.0.7",
|
||||
"resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz",
|
||||
"integrity": "sha512-C0X0KQmGm3N2ftbTGBhSyuydQ+vV1LC3f3zPvT3RXHXNZrvfPZcoXp/N5DOa8vedX/rTMm2CjTtivFg2STJMRQ=="
|
||||
},
|
||||
"md5.js": {
|
||||
"version": "1.3.5",
|
||||
"resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
|
||||
@@ -4107,6 +4543,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"milsymbol": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/milsymbol/-/milsymbol-2.0.0.tgz",
|
||||
"integrity": "sha512-GcBFrcIUr8jScaZqZb0SI2W6AbnUrPCTHu2kqHxduQjN2DIN8q5pY6ksSWfnJ4HlcIAWQhyotbdPIr1bBxFbwQ=="
|
||||
},
|
||||
"mime": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz",
|
||||
@@ -4125,6 +4566,11 @@
|
||||
"mime-db": "1.52.0"
|
||||
}
|
||||
},
|
||||
"mingo": {
|
||||
"version": "6.2.7",
|
||||
"resolved": "https://registry.npmjs.org/mingo/-/mingo-6.2.7.tgz",
|
||||
"integrity": "sha512-r+yKmrZ+6SjwGxSot+/3S8sP9+LCxWNueR6xppMx7BzV60OegjbeklWAf/UveyQi8PDW8g/mwrQSHZVY/5jBJQ=="
|
||||
},
|
||||
"minimalistic-assert": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
|
||||
@@ -4322,6 +4768,14 @@
|
||||
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
|
||||
"integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="
|
||||
},
|
||||
"pause-stream": {
|
||||
"version": "0.0.11",
|
||||
"resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz",
|
||||
"integrity": "sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==",
|
||||
"requires": {
|
||||
"through": "~2.3"
|
||||
}
|
||||
},
|
||||
"pbkdf2": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz",
|
||||
@@ -4486,6 +4940,12 @@
|
||||
"picomatch": "^2.2.1"
|
||||
}
|
||||
},
|
||||
"require-directory": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
|
||||
"integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
|
||||
"dev": true
|
||||
},
|
||||
"resolve": {
|
||||
"version": "1.22.1",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
|
||||
@@ -4507,6 +4967,15 @@
|
||||
"inherits": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"rxjs": {
|
||||
"version": "7.8.0",
|
||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.0.tgz",
|
||||
"integrity": "sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||
@@ -4517,6 +4986,17 @@
|
||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||
},
|
||||
"save": {
|
||||
"version": "2.9.0",
|
||||
"resolved": "https://registry.npmjs.org/save/-/save-2.9.0.tgz",
|
||||
"integrity": "sha512-eg8+g8CjvehE/2C6EbLdtK1pINVD27pcJLj4M9PjWWhoeha/y5bWf4dp/0RF+OzbKTcG1bae9qi3PAqiR8CJTg==",
|
||||
"requires": {
|
||||
"async": "^3.2.2",
|
||||
"event-stream": "^4.0.1",
|
||||
"lodash.assign": "^4.2.0",
|
||||
"mingo": "^6.1.0"
|
||||
}
|
||||
},
|
||||
"semver": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
@@ -4596,6 +5076,20 @@
|
||||
"integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==",
|
||||
"dev": true
|
||||
},
|
||||
"spawn-command": {
|
||||
"version": "0.0.2-1",
|
||||
"resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz",
|
||||
"integrity": "sha512-n98l9E2RMSJ9ON1AKisHzz7V42VDiBQGY6PB1BwRglz99wpVsSuGzQ+jOi6lFXBGVTCrRpltvjm+/XA+tpeJrg==",
|
||||
"dev": true
|
||||
},
|
||||
"split": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz",
|
||||
"integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==",
|
||||
"requires": {
|
||||
"through": "2"
|
||||
}
|
||||
},
|
||||
"statuses": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz",
|
||||
@@ -4630,6 +5124,15 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"stream-combiner": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.2.2.tgz",
|
||||
"integrity": "sha512-6yHMqgLYDzQDcAkL+tjJDC5nSNuNIx0vZtRZeiPh7Saef7VHX9H5Ijn9l2VIol2zaNYlYEX6KyuT/237A58qEQ==",
|
||||
"requires": {
|
||||
"duplexer": "~0.1.1",
|
||||
"through": "~2.3.4"
|
||||
}
|
||||
},
|
||||
"stream-combiner2": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz",
|
||||
@@ -4698,6 +5201,26 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"string-width": {
|
||||
"version": "4.2.3",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
||||
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"emoji-regex": "^8.0.0",
|
||||
"is-fullwidth-code-point": "^3.0.0",
|
||||
"strip-ansi": "^6.0.1"
|
||||
}
|
||||
},
|
||||
"strip-ansi": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
||||
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-regex": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"strip-bom": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
|
||||
@@ -4748,8 +5271,7 @@
|
||||
"through": {
|
||||
"version": "2.3.8",
|
||||
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
|
||||
"integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==",
|
||||
"dev": true
|
||||
"integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg=="
|
||||
},
|
||||
"through2": {
|
||||
"version": "2.0.5",
|
||||
@@ -4779,6 +5301,12 @@
|
||||
"is-number": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"tree-kill": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz",
|
||||
"integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==",
|
||||
"dev": true
|
||||
},
|
||||
"tsconfig": {
|
||||
"version": "5.0.3",
|
||||
"resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-5.0.3.tgz",
|
||||
@@ -4805,6 +5333,12 @@
|
||||
"tsconfig": "^5.0.3"
|
||||
}
|
||||
},
|
||||
"tslib": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz",
|
||||
"integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==",
|
||||
"dev": true
|
||||
},
|
||||
"tty-browserify": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz",
|
||||
@@ -4960,6 +5494,17 @@
|
||||
"is-typed-array": "^1.1.10"
|
||||
}
|
||||
},
|
||||
"wrap-ansi": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
|
||||
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-styles": "^4.0.0",
|
||||
"string-width": "^4.1.0",
|
||||
"strip-ansi": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
@@ -4971,6 +5516,33 @@
|
||||
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
||||
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
|
||||
"dev": true
|
||||
},
|
||||
"y18n": {
|
||||
"version": "5.0.8",
|
||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
|
||||
"integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
|
||||
"dev": true
|
||||
},
|
||||
"yargs": {
|
||||
"version": "17.6.2",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz",
|
||||
"integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"cliui": "^8.0.1",
|
||||
"escalade": "^3.1.1",
|
||||
"get-caller-file": "^2.0.5",
|
||||
"require-directory": "^2.1.1",
|
||||
"string-width": "^4.2.3",
|
||||
"y18n": "^5.0.5",
|
||||
"yargs-parser": "^21.1.1"
|
||||
}
|
||||
},
|
||||
"yargs-parser": {
|
||||
"version": "21.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
|
||||
"integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"scripts": {
|
||||
"start": "npm run copy & concurrently --kill-others \"npm run watch\" \"nodemon ./bin/www\"",
|
||||
"copy": "copy .\\node_modules\\leaflet\\dist\\leaflet.css .\\public\\stylesheets\\leaflet.css",
|
||||
"watch": "watchify .\\src\\index.ts --debug -p [ tsify --noImplicitAny ] -o .\\public\\javascripts\\bundle.js"
|
||||
"watch": "watchify .\\src\\index.ts --debug -p [ tsify --noImplicitAny ] -o .\\public\\javascripts\\bundle.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/geojson": "^7946.0.10",
|
||||
@@ -15,10 +15,13 @@
|
||||
"ejs": "^3.1.8",
|
||||
"express": "~4.16.1",
|
||||
"leaflet": "^1.9.3",
|
||||
"morgan": "~1.9.1"
|
||||
"milsymbol": "^2.0.0",
|
||||
"morgan": "~1.9.1",
|
||||
"save": "^2.9.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"browserify": "^17.0.0",
|
||||
"concurrently": "^7.6.0",
|
||||
"tsify": "^5.0.4",
|
||||
"typescript": "^4.9.4",
|
||||
"watchify": "^4.0.0"
|
||||
|
||||
BIN
client/public/images/airbase.png
Normal file
|
After Width: | Height: | Size: 8.5 KiB |
BIN
client/public/images/banner.xcf
Normal file
BIN
client/public/images/buttons/attack.png
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
BIN
client/public/images/buttons/formation.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
client/public/images/buttons/rtb.png
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
BIN
client/public/images/buttons/spawnAWACS.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
client/public/images/buttons/spawnAir.png
Normal file
|
After Width: | Height: | Size: 35 KiB |
BIN
client/public/images/buttons/spawnCAP.png
Normal file
|
After Width: | Height: | Size: 5.1 KiB |
BIN
client/public/images/buttons/spawnCAS.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
client/public/images/buttons/spawnDrone.png
Normal file
|
After Width: | Height: | Size: 6.2 KiB |
BIN
client/public/images/buttons/spawnExplosion.png
Normal file
|
After Width: | Height: | Size: 85 KiB |
BIN
client/public/images/buttons/spawnGround.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
client/public/images/buttons/spawnHowitzer.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
client/public/images/buttons/spawnIFV.png
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
BIN
client/public/images/buttons/spawnMLRS.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
client/public/images/buttons/spawnRadar.png
Normal file
|
After Width: | Height: | Size: 141 KiB |
BIN
client/public/images/buttons/spawnSAM.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
client/public/images/buttons/spawnSmoke.png
Normal file
|
After Width: | Height: | Size: 43 KiB |
BIN
client/public/images/buttons/spawnStrike.png
Normal file
|
After Width: | Height: | Size: 8.1 KiB |
BIN
client/public/images/buttons/spawnTank.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
client/public/images/buttons/spawnTanker.png
Normal file
|
After Width: | Height: | Size: 7.0 KiB |
BIN
client/public/images/buttons/spawnTransport.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
client/public/images/buttons/spawnUnarmed.png
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
client/public/images/buttons/tanker.png
Normal file
|
After Width: | Height: | Size: 7.0 KiB |
BIN
client/public/images/buttons/wheelButtons.xcf
Normal file
BIN
client/public/images/patch.png
Normal file
|
After Width: | Height: | Size: 130 KiB |
BIN
client/public/images/selected.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
client/public/images/units/aircraft.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
client/public/images/units/bomb.png
Normal file
|
After Width: | Height: | Size: 8.0 KiB |
BIN
client/public/images/units/ground.png
Normal file
|
After Width: | Height: | Size: 7.1 KiB |
BIN
client/public/images/units/missile.png
Normal file
|
After Width: | Height: | Size: 6.7 KiB |
45
client/public/stylesheets/panels.css
Normal file
@@ -0,0 +1,45 @@
|
||||
/* Panels style */
|
||||
.olympus-panel {
|
||||
background-color: var(--background-color);
|
||||
border: solid white 1px;
|
||||
font-size: 12px;
|
||||
position: fixed;
|
||||
transition: bottom 0.2s;
|
||||
border-radius: 5px;
|
||||
text-shadow: 1px 1px #000, -1px -1px #000, 1px -1px #000, -1px 1px #000;
|
||||
box-shadow: 0px 0px 10px #000000AA;
|
||||
font-family: "Lucida Console", "Courier New", monospace !important;
|
||||
}
|
||||
|
||||
.olympus-panel table{
|
||||
margin: 5px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.olympus-panel-title {
|
||||
font-size: 14px;
|
||||
color: #d3e9ff;
|
||||
}
|
||||
|
||||
.olympus-panel-label {
|
||||
font-size: 12px;
|
||||
color: var(--title-color);
|
||||
margin: 5px;
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
.olympus-panel-content {
|
||||
font-size: 12px;
|
||||
color: var(--text-color);
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
/* Panels position */
|
||||
#olympus-unit-info-panel {
|
||||
height: 100px;
|
||||
width: 800px;
|
||||
left: 10px;
|
||||
bottom: 10px;
|
||||
z-index: 1000;
|
||||
display: flex;
|
||||
}
|
||||
25
client/public/stylesheets/selectionscroll.css
Normal file
@@ -0,0 +1,25 @@
|
||||
.olympus-selection-scroll-container {
|
||||
margin: 0 auto;
|
||||
position: fixed;
|
||||
z-index: 1000;
|
||||
width: 220px;
|
||||
height: 220px;
|
||||
overflow: visible;
|
||||
overflow-y: scroll;
|
||||
background-color: var(--background-color);
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.olympus-selection-scroll-element {
|
||||
margin: 2px;
|
||||
color: white;
|
||||
text-shadow: 1px 1px #000, -1px -1px #000, 1px -1px #000, -1px 1px #000;
|
||||
cursor: pointer;
|
||||
font-size: 12px;
|
||||
opacity: 1;
|
||||
font-family: "Lucida Console", "Courier New", monospace !important;
|
||||
}
|
||||
|
||||
.olympus-selection-scroll-element:hover {
|
||||
background-color: var(--highlight-color);
|
||||
}
|
||||
104
client/public/stylesheets/selectionwheel.css
Normal file
@@ -0,0 +1,104 @@
|
||||
.olympus-selection-wheel {
|
||||
margin: 0;
|
||||
position: fixed;
|
||||
z-index: 1000;
|
||||
width: 220px;
|
||||
height: 220px;
|
||||
overflow: visible;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.olympus-wheel {
|
||||
width: 100%;
|
||||
border-radius: 50%;
|
||||
background-color: var(--active-coalition-color);
|
||||
opacity: 0.8;
|
||||
-webkit-mask: radial-gradient(transparent 30%,#000 31%);
|
||||
mask: radial-gradient(transparent 30%,#000 31%);
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.olympus-wheel:before {
|
||||
content: "";
|
||||
display: block;
|
||||
padding-top: 100%;
|
||||
}
|
||||
|
||||
.selection-wheel-button {
|
||||
position: fixed;
|
||||
z-index: 1000;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
opacity: 0;
|
||||
/*transition: opacity var(--animation_duration), left var(--animation_duration), top var(--animation_duration);*/
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.selection-wheel-image {
|
||||
width: 45px;
|
||||
height: 45px;
|
||||
/*filter: invert(100%);*/
|
||||
transition: width var(--animation_duration), height var(--animation_duration);
|
||||
filter: drop-shadow(1px 1px 0px var(--highlight-color)) drop-shadow(1px -1px 0px var(--highlight-color)) drop-shadow(-1px 1px 0px var(--highlight-color)) drop-shadow(-1px -1px 0px var(--highlight-color));
|
||||
}
|
||||
|
||||
.selection-wheel-button:hover {
|
||||
filter: drop-shadow(1px 1px 2px var(--highlight-color)) drop-shadow(1px -1px 2px var(--highlight-color)) drop-shadow(-1px 1px 2px var(--highlight-color)) drop-shadow(-1px -1px 2px var(--highlight-color));
|
||||
}
|
||||
|
||||
.selection-wheel-button:hover .selection-wheel-image {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
/*filter: invert(21%) sepia(23%) saturate(775%) hue-rotate(170deg) brightness(92%) contrast(90%);*/
|
||||
}
|
||||
|
||||
.olympus-selection-wheel label {
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.olympus-selection-wheel input {
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.olympus-selection-wheel-switch {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
display: inline-block;
|
||||
width: 60px;
|
||||
height: 34px;
|
||||
background-color: #fffa;
|
||||
border: 1px solid var(--active-coalition-color);
|
||||
border-radius: 17px;
|
||||
margin-left: -30px;
|
||||
margin-top: -17px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.olympus-selection-wheel-switch:before {
|
||||
position: absolute;
|
||||
content: "";
|
||||
height: 26px;
|
||||
width: 26px;
|
||||
left: 4px;
|
||||
bottom: 4px;
|
||||
background-color: var(--active-coalition-color);
|
||||
-webkit-transition: 0.2s;
|
||||
transition: 0.2s;
|
||||
border-radius: 50%;
|
||||
|
||||
}
|
||||
|
||||
input:checked + .olympus-selection-wheel-switch:before {
|
||||
-webkit-transform: translateX(26px);
|
||||
-ms-transform: translateX(26px);
|
||||
transform: translateX(26px);
|
||||
}
|
||||
@@ -1,8 +1,17 @@
|
||||
@import url("panels.css");
|
||||
@import url("selectionwheel.css");
|
||||
@import url("selectionscroll.css");
|
||||
@import url("unitmarker.css");
|
||||
|
||||
/* Variables definitions */
|
||||
:root {
|
||||
--background-color:#202831;
|
||||
--title-color:#d3e9ff;
|
||||
--text-color:white;
|
||||
--blue-coalition-color: #2196F3;
|
||||
--red-coalition-color: #f32121;
|
||||
--active-coalition-color: var(--blue-coalition-color);
|
||||
--highlight-color: #FFFFFFAA;
|
||||
}
|
||||
|
||||
/* Page style */
|
||||
@@ -22,48 +31,3 @@ html, body {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Panels style */
|
||||
.olympus-panel {
|
||||
background-color: var(--background-color);
|
||||
border: solid white 1px;
|
||||
font-size: 12px;
|
||||
position: fixed;
|
||||
transition: bottom 0.2s;
|
||||
border-radius: 5px;
|
||||
text-shadow: 1px 1px #000, -1px -1px #000, 1px -1px #000, -1px 1px #000;
|
||||
box-shadow: 0px 0px 10px #000000AA;
|
||||
font-family: "Lucida Console", "Courier New", monospace !important;
|
||||
}
|
||||
|
||||
.olympus-panel table{
|
||||
margin: 5px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.olympus-panel-title {
|
||||
font-size: 14px;
|
||||
color: #d3e9ff;
|
||||
}
|
||||
|
||||
.olympus-panel-label {
|
||||
font-size: 12px;
|
||||
color: var(--title-color);
|
||||
margin: 5px;
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
.olympus-panel-content {
|
||||
font-size: 12px;
|
||||
color: var(--text-color);
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
/* Panels position */
|
||||
#olympus-unit-info {
|
||||
height: 100px;
|
||||
width: 800px;
|
||||
left: 10px;
|
||||
bottom: 10px;
|
||||
z-index: 1000;
|
||||
display: flex;
|
||||
}
|
||||
95
client/public/stylesheets/unitmarker.css
Normal file
@@ -0,0 +1,95 @@
|
||||
.unit-marker-container {
|
||||
height: 60px;
|
||||
width: 60px;
|
||||
left: -30px;
|
||||
top: -30px;
|
||||
border: 0px black solid;
|
||||
position: absolute;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.unit-marker-icon {
|
||||
height: 60px;
|
||||
width: 60px;
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
display: flex;
|
||||
position: absolute;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.unit-marker-icon img {
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
.unit-marker-selected {
|
||||
animation-name: flash;
|
||||
animation-duration: 0.3s;
|
||||
animation-iteration-count: infinite;
|
||||
animation-direction: alternate;
|
||||
animation-timing-function: linear;
|
||||
}
|
||||
|
||||
@keyframes flash {
|
||||
from {filter: brightness(100%); }
|
||||
to {filter: brightness(130%);}
|
||||
}
|
||||
|
||||
.unit-marker-hovered {
|
||||
filter: brightness(130%);
|
||||
}
|
||||
|
||||
.unit-marker-container-table-dead {
|
||||
filter: brightness(50%);
|
||||
}
|
||||
|
||||
.unit-marker-unitName {
|
||||
top: -20px;
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
font: 800 16px Arial;
|
||||
white-space: nowrap;
|
||||
-webkit-text-fill-color: white;
|
||||
-webkit-text-stroke: 1px;
|
||||
}
|
||||
|
||||
.unit-marker-name {
|
||||
bottom: -20px;
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
font: 800 14px Arial;
|
||||
white-space: nowrap;
|
||||
-webkit-text-fill-color: white;
|
||||
-webkit-text-stroke: 1px;
|
||||
}
|
||||
|
||||
.unit-marker-altitude {
|
||||
width: 100%;
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
position: absolute;
|
||||
text-align: right;
|
||||
font: 800 12px Arial;
|
||||
white-space: nowrap;
|
||||
-webkit-text-fill-color: white;
|
||||
-webkit-text-stroke: 1px;
|
||||
}
|
||||
|
||||
.unit-marker-speed {
|
||||
width: 100%;
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
position: absolute;
|
||||
text-align: left;
|
||||
font: 800 12px Arial;
|
||||
white-space: nowrap;
|
||||
-webkit-text-fill-color: white;
|
||||
-webkit-text-stroke: 1px;
|
||||
}
|
||||
|
||||
.unit-marker-container-table-dead .unit-marker-name{
|
||||
opacity: 0;
|
||||
}
|
||||
51
client/src/controls/selectionscroll.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
export class SelectionScroll
|
||||
{
|
||||
#container : HTMLElement | null;
|
||||
#display: string;
|
||||
|
||||
constructor(id: string, )
|
||||
{
|
||||
this.#container = document.getElementById(id);
|
||||
this.#display = '';
|
||||
if (this.#container != null)
|
||||
{
|
||||
this.#display = this.#container.style.display;
|
||||
this.hide();
|
||||
}
|
||||
}
|
||||
|
||||
show(x: number, y: number, options: any, callback: CallableFunction)
|
||||
{
|
||||
/* Hide to remove buttons, if present */
|
||||
this.hide();
|
||||
|
||||
if (this.#container != null && options.length > 1)
|
||||
{
|
||||
this.#container.style.display = this.#display;
|
||||
this.#container.style.left = x - 110 + "px";
|
||||
this.#container.style.top = y - 110 + "px";
|
||||
|
||||
for (let optionID in options)
|
||||
{
|
||||
var node = document.createElement("div");
|
||||
node.classList.add("olympus-selection-scroll-element");
|
||||
node.appendChild(document.createTextNode(options[optionID]));
|
||||
this.#container.appendChild(node);
|
||||
node.addEventListener('click', () => callback(options[optionID]))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hide()
|
||||
{
|
||||
if (this.#container != null)
|
||||
{
|
||||
this.#container.style.display = "none";
|
||||
var buttons = this.#container.querySelectorAll(".olympus-selection-scroll-element");
|
||||
for (let child of buttons)
|
||||
{
|
||||
this.#container.removeChild(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
92
client/src/controls/selectionwheel.ts
Normal file
@@ -0,0 +1,92 @@
|
||||
import { setActiveCoalition } from "..";
|
||||
import { deg2rad } from "../other/utils";
|
||||
|
||||
export class SelectionWheel
|
||||
{
|
||||
#container: HTMLElement | null;
|
||||
#display: string;
|
||||
|
||||
constructor(id: string)
|
||||
{
|
||||
this.#container = document.getElementById(id);
|
||||
this.#display = '';
|
||||
if (this.#container != null)
|
||||
{
|
||||
this.#container.querySelector("#coalition-switch")?.addEventListener('change', (e) => this.#onSwitch(e))
|
||||
this.#display = this.#container.style.display;
|
||||
this.hide();
|
||||
}
|
||||
}
|
||||
|
||||
show(x: number, y: number, options: any, showCoalition: boolean)
|
||||
{
|
||||
/* Hide to remove buttons, if present */
|
||||
this.hide();
|
||||
|
||||
if (this.#container != null)
|
||||
{
|
||||
this.#container.style.display = this.#display;
|
||||
this.#container.style.left = x - 110 + "px";
|
||||
this.#container.style.top = y - 110 + "px";
|
||||
|
||||
var angularSize = 360 / options.length;
|
||||
var r = 80;
|
||||
|
||||
/* Create the buttons */
|
||||
for (let id in options)
|
||||
{
|
||||
var button = document.createElement("div");
|
||||
button.classList.add("selection-wheel-button");
|
||||
button.style.left = x - 25 + "px";
|
||||
button.style.top = y - 25 + "px";
|
||||
button.addEventListener('click', (e) => options[id].callback(e));
|
||||
this.#container.appendChild(button);
|
||||
var angle = parseInt(id) * angularSize;
|
||||
button.style.opacity = "1";
|
||||
button.style.left = x + r * Math.sin(deg2rad(angle)) - 25 + "px";
|
||||
button.style.top = y - r * Math.cos(deg2rad(angle)) - 25 + "px";
|
||||
|
||||
var image = document.createElement("img");
|
||||
image.classList.add("selection-wheel-image");
|
||||
image.src = `images/buttons/${options[id].src}`
|
||||
image.title = options[id].tooltip;
|
||||
if ('tint' in options[id])
|
||||
{
|
||||
button.style.setProperty('background-color', options[id].tint);
|
||||
image.style.opacity = "0";
|
||||
}
|
||||
button.appendChild(image);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hide()
|
||||
{
|
||||
if (this.#container != null)
|
||||
{
|
||||
this.#container.style.display = "none";
|
||||
var buttons = this.#container.querySelectorAll(".selection-wheel-button");
|
||||
for (let child of buttons)
|
||||
{
|
||||
this.#container.removeChild(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#onSwitch(e: any)
|
||||
{
|
||||
if (this.#container != null)
|
||||
{
|
||||
if (e.currentTarget.checked)
|
||||
{
|
||||
document.documentElement.style.setProperty('--active-coalition-color', getComputedStyle(this.#container).getPropertyValue("--red-coalition-color"));
|
||||
setActiveCoalition("red");
|
||||
}
|
||||
else
|
||||
{
|
||||
document.documentElement.style.setProperty('--active-coalition-color', getComputedStyle(this.#container).getPropertyValue("--blue-coalition-color"));
|
||||
setActiveCoalition("blue");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
122
client/src/dcs/dcs.ts
Normal file
@@ -0,0 +1,122 @@
|
||||
import * as L from 'leaflet'
|
||||
import { ConvertDDToDMS } from '../other/utils';
|
||||
|
||||
/* Edit here to change server address */
|
||||
var RESTaddress = "http://localhost:30000/restdemo";
|
||||
|
||||
export function getDataFromDCS(callback: CallableFunction)
|
||||
{
|
||||
/* Request the updated unit data from the server */
|
||||
var xmlHttp = new XMLHttpRequest();
|
||||
xmlHttp.open( "GET", RESTaddress, true);
|
||||
|
||||
xmlHttp.onload = function(e)
|
||||
{
|
||||
var data = JSON.parse(xmlHttp.responseText);
|
||||
callback(data);
|
||||
};
|
||||
|
||||
xmlHttp.onerror = function () {
|
||||
console.error("An error occurred during the XMLHttpRequest");
|
||||
};
|
||||
xmlHttp.send( null );
|
||||
}
|
||||
|
||||
export function addDestination(ID: number, path: any)
|
||||
{
|
||||
// TODO move in dedicated file
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("PUT", RESTaddress);
|
||||
xhr.setRequestHeader("Content-Type", "application/json");
|
||||
xhr.onreadystatechange = () => {};
|
||||
|
||||
var command = {"ID": ID, "path": path}
|
||||
var data = {"setPath": command}
|
||||
|
||||
xhr.send(JSON.stringify(data));
|
||||
}
|
||||
|
||||
export function spawnSmoke(color: string, latlng: L.LatLng)
|
||||
{
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("PUT", RESTaddress);
|
||||
xhr.setRequestHeader("Content-Type", "application/json");
|
||||
xhr.onreadystatechange = () => {
|
||||
if (xhr.readyState === 4) {
|
||||
console.log("Added " + color + " smoke at " + ConvertDDToDMS(latlng.lat, false) + " " + ConvertDDToDMS(latlng.lng, true));
|
||||
}
|
||||
};
|
||||
|
||||
var command = {"color": color, "location": latlng};
|
||||
var data = {"smoke": command}
|
||||
|
||||
xhr.send(JSON.stringify(data));
|
||||
}
|
||||
|
||||
export function spawnGroundUnit(type: string, latlng: L.LatLng, coalition: string)
|
||||
{
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("PUT", RESTaddress);
|
||||
xhr.setRequestHeader("Content-Type", "application/json");
|
||||
xhr.onreadystatechange = () => {
|
||||
if (xhr.readyState === 4) {
|
||||
console.log("Added " + coalition + " " + type + " at " + ConvertDDToDMS(latlng.lat, false) + " " + ConvertDDToDMS(latlng.lng, true));
|
||||
}
|
||||
};
|
||||
|
||||
var command = {"type": type, "location": latlng, "coalition": coalition};
|
||||
var data = {"spawnGround": command}
|
||||
|
||||
xhr.send(JSON.stringify(data));
|
||||
}
|
||||
|
||||
export function spawnAircraft(type: string, latlng: L.LatLng, coalition: string, payloadName = "", airbaseName = "")
|
||||
{
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("PUT", RESTaddress);
|
||||
xhr.setRequestHeader("Content-Type", "application/json");
|
||||
xhr.onreadystatechange = () => {
|
||||
if (xhr.readyState === 4) {
|
||||
console.log("Added " + coalition + " " + type + " at " + ConvertDDToDMS(latlng.lat, false) + " " + ConvertDDToDMS(latlng.lng, true));
|
||||
}
|
||||
};
|
||||
|
||||
var command = {"type": type, "location": latlng, "coalition": coalition, "payloadName": payloadName, "airbaseName": airbaseName};
|
||||
var data = {"spawnAir": command}
|
||||
|
||||
xhr.send(JSON.stringify(data));
|
||||
}
|
||||
|
||||
export function attackUnit(ID: number, targetID: number)
|
||||
{
|
||||
//var xhr = new XMLHttpRequest();
|
||||
//xhr.open("PUT", RESTaddress);
|
||||
//xhr.setRequestHeader("Content-Type", "application/json");
|
||||
//xhr.onreadystatechange = () => {
|
||||
// if (xhr.readyState === 4) {
|
||||
// console.log("Unit " + unitsManager.getUnitByID(ID).unitName + " attack " + unitsManager.getUnitByID(targetID).unitName );
|
||||
// }
|
||||
//};
|
||||
//
|
||||
//var command = {"ID": ID, "targetID": targetID};
|
||||
//var data = {"attackUnit": command}
|
||||
//
|
||||
//xhr.send(JSON.stringify(data));
|
||||
}
|
||||
|
||||
export function cloneUnit(ID: number)
|
||||
{
|
||||
//var xhr = new XMLHttpRequest();
|
||||
//xhr.open("PUT", RESTaddress);
|
||||
//xhr.setRequestHeader("Content-Type", "application/json");
|
||||
//xhr.onreadystatechange = () => {
|
||||
// if (xhr.readyState === 4) {
|
||||
// console.log("Unit " + unitsManager.getUnitByID(ID).unitName + " cloned");
|
||||
// }
|
||||
//};
|
||||
//
|
||||
//var command = {"ID": ID};
|
||||
//var data = {"cloneUnit": command}
|
||||
//
|
||||
//xhr.send(JSON.stringify(data));
|
||||
}
|
||||
@@ -1,3 +1,68 @@
|
||||
import { Olympus } from "./map/map"
|
||||
import { Map } from "./map/map"
|
||||
import { getDataFromDCS } from "./dcs/dcs"
|
||||
import { SelectionWheel } from "./controls/selectionwheel";
|
||||
import { UnitsManager } from "./units/unitsmanager";
|
||||
import { UnitInfoPanel } from "./panels/unitinfopanel";
|
||||
import { SelectionScroll } from "./controls/selectionscroll";
|
||||
|
||||
var map = new Olympus.Map('olympus-map-container');
|
||||
var map: Map;
|
||||
var selectionWheel: SelectionWheel;
|
||||
var selectionScroll: SelectionScroll;
|
||||
var unitsManager: UnitsManager;
|
||||
var unitInfoPanel: UnitInfoPanel;
|
||||
var activeCoalition: string
|
||||
|
||||
function setup()
|
||||
{
|
||||
/* Initialize */
|
||||
map = new Map('olympus-map-container');
|
||||
selectionWheel = new SelectionWheel("selection-wheel");
|
||||
selectionScroll = new SelectionScroll("selection-scroll");
|
||||
unitsManager = new UnitsManager();
|
||||
unitInfoPanel = new UnitInfoPanel("olympus-unit-info-panel");
|
||||
|
||||
/* Main update rate = 250ms is minimum time, equal to server update time. */
|
||||
setInterval(() => getDataFromDCS(update), 250);
|
||||
}
|
||||
|
||||
function update(data: JSON)
|
||||
{
|
||||
unitsManager.update(data);
|
||||
}
|
||||
|
||||
export function getMap()
|
||||
{
|
||||
return map;
|
||||
}
|
||||
|
||||
export function getSelectionWheel()
|
||||
{
|
||||
return selectionWheel;
|
||||
}
|
||||
|
||||
export function getSelectionScroll()
|
||||
{
|
||||
return selectionScroll;
|
||||
}
|
||||
|
||||
export function getUnitsManager()
|
||||
{
|
||||
return unitsManager;
|
||||
}
|
||||
|
||||
export function getUnitInfoPanel()
|
||||
{
|
||||
return unitInfoPanel;
|
||||
}
|
||||
|
||||
export function setActiveCoalition(coalition: string)
|
||||
{
|
||||
activeCoalition = coalition;
|
||||
}
|
||||
|
||||
export function getActiveCoalition()
|
||||
{
|
||||
return activeCoalition;
|
||||
}
|
||||
|
||||
window.onload = setup;
|
||||
@@ -1,17 +1,189 @@
|
||||
import * as L from 'leaflet'
|
||||
import * as L from "leaflet"
|
||||
import { getSelectionWheel, getSelectionScroll, getUnitsManager, getActiveCoalition } from "..";
|
||||
import { spawnAircraft } from "../dcs/dcs";
|
||||
import { payloadNames } from "../units/payloadNames";
|
||||
import { unitTypes } from "../units/unitTypes";
|
||||
|
||||
export namespace Olympus
|
||||
export class Map extends L.Map
|
||||
{
|
||||
export class Map extends L.Map
|
||||
{
|
||||
constructor(containerId: string)
|
||||
{
|
||||
super(containerId, {doubleClickZoom: false});
|
||||
this.setView([37.23, -115.8], 12);
|
||||
#state: string;
|
||||
|
||||
L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {
|
||||
attribution: 'Tiles © Esri — Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community'
|
||||
}).addTo(this);
|
||||
constructor(containerId: string)
|
||||
{
|
||||
/* Init the leaflet map */
|
||||
super(containerId, {doubleClickZoom: false});
|
||||
this.setView([37.23, -115.8], 12);
|
||||
L.tileLayer("https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}", {
|
||||
attribution: "Tiles © Esri — Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community"
|
||||
}).addTo(this);
|
||||
|
||||
/* Init the state machine */
|
||||
this.#state = "IDLE";
|
||||
|
||||
/* Register event handles */
|
||||
this.on("contextmenu", (e) => this.#onContextMenu(e));
|
||||
this.on("click", (e) => this.#onClick(e));
|
||||
this.on("dblclick", (e) => this.#onDoubleClick(e));
|
||||
}
|
||||
|
||||
/* State machine */
|
||||
setState(state: string)
|
||||
{
|
||||
this.#state = state;
|
||||
|
||||
if (this.#state === "IDLE")
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (this.#state === "MOVE_UNIT")
|
||||
{
|
||||
|
||||
}
|
||||
else if (this.#state === "ATTACK")
|
||||
{
|
||||
|
||||
}
|
||||
else if (this.#state === "FORMATION")
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
getState()
|
||||
{
|
||||
return this.#state;
|
||||
}
|
||||
|
||||
/* Selection wheel */
|
||||
showSelectionWheel(e: PointerEvent, options: any, showCoalition: boolean)
|
||||
{
|
||||
var x = e.x;
|
||||
var y = e.y;
|
||||
getSelectionWheel().show(x, y, options, showCoalition);
|
||||
}
|
||||
|
||||
hideSelectionWheel()
|
||||
{
|
||||
getSelectionWheel().hide();
|
||||
}
|
||||
|
||||
/* Selection scroll */
|
||||
showSelectionScroll(e: PointerEvent, options: any, callback: CallableFunction)
|
||||
{
|
||||
var x = e.x;
|
||||
var y = e.y;
|
||||
getSelectionScroll().show(x, y, options, callback);
|
||||
}
|
||||
|
||||
hideSelectionScroll()
|
||||
{
|
||||
getSelectionScroll().hide();
|
||||
}
|
||||
|
||||
/* Event handlers */
|
||||
#onContextMenu(e: any)
|
||||
{
|
||||
this.setState("IDLE");
|
||||
getUnitsManager().deselectAllUnits();
|
||||
this.hideSelectionWheel();
|
||||
this.hideSelectionScroll();
|
||||
}
|
||||
|
||||
#onClick(e: any)
|
||||
{
|
||||
this.hideSelectionWheel();
|
||||
this.hideSelectionScroll();
|
||||
if (this.#state === "IDLE")
|
||||
{
|
||||
|
||||
}
|
||||
else if (this.#state === "MOVE_UNIT")
|
||||
{
|
||||
if (!e.originalEvent.ctrlKey)
|
||||
{
|
||||
//unitsManager.clearDestinations();
|
||||
}
|
||||
//unitsManager.addDestination(e.latlng)
|
||||
}
|
||||
}
|
||||
|
||||
#onDoubleClick(e: any)
|
||||
{
|
||||
if (this.#state == "IDLE")
|
||||
{
|
||||
var options = [
|
||||
{"tooltip": "Air unit", "src": "spawnAir.png", "callback": () => this.#aircraftSpawnMenu(e)},
|
||||
{"tooltip": "Ground unit", "src": "spawnGround.png", "callback": () => this.#groundUnitSpawnMenu(e)},
|
||||
{"tooltip": "Smoke", "src": "spawnSmoke.png", "callback": () => this.#smokeSpawnMenu(e)},
|
||||
{"tooltip": "Explosion", "src": "spawnExplosion.png", "callback": () => this.#explosionSpawnMenu(e)}
|
||||
]
|
||||
this.showSelectionWheel(e.originalEvent, options, true);
|
||||
}
|
||||
}
|
||||
|
||||
/* Spawning menus */
|
||||
#groundUnitSpawnMenu(e: any)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#smokeSpawnMenu(e: any)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#explosionSpawnMenu(e: any)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#aircraftSpawnMenu(e: any)
|
||||
{
|
||||
var options = [
|
||||
{'coalition': true, 'tooltip': 'CAP', 'src': 'spawnCAP.png', 'callback': () => this.#selectAircraft(e, "CAP")},
|
||||
{'coalition': true, 'tooltip': 'CAS', 'src': 'spawnCAS.png', 'callback': () => this.#selectAircraft(e, "CAS")},
|
||||
{'coalition': true, 'tooltip': 'Tanker', 'src': 'spawnTanker.png', 'callback': () => this.#selectAircraft(e, "tanker")},
|
||||
{'coalition': true, 'tooltip': 'AWACS', 'src': 'spawnAWACS.png', 'callback': () => this.#selectAircraft(e, "awacs")},
|
||||
{'coalition': true, 'tooltip': 'Strike', 'src': 'spawnStrike.png', 'callback': () => this.#selectAircraft(e, "strike")},
|
||||
{'coalition': true, 'tooltip': 'Drone', 'src': 'spawnDrone.png', 'callback': () => this.#selectAircraft(e, "drone")},
|
||||
{'coalition': true, 'tooltip': 'Transport', 'src': 'spawnTransport.png','callback': () => this.#selectAircraft(e, "transport")},
|
||||
]
|
||||
this.showSelectionWheel(e.originalEvent, options, true);
|
||||
}
|
||||
|
||||
/* Show unit selection for air units */
|
||||
#selectAircraft(e: any, group: string)
|
||||
{
|
||||
this.hideSelectionWheel();
|
||||
this.hideSelectionScroll();
|
||||
var options = unitTypes.air[group];
|
||||
options.sort();
|
||||
this.showSelectionScroll(e.originalEvent, options, (unitType: string) => {
|
||||
this.hideSelectionWheel();
|
||||
this.hideSelectionScroll();
|
||||
this.#unitSelectPayload(e, unitType);
|
||||
});
|
||||
}
|
||||
|
||||
/* Show weapon selection for air units */
|
||||
#unitSelectPayload(e: any, unitType: string)
|
||||
{
|
||||
this.hideSelectionWheel();
|
||||
this.hideSelectionScroll();
|
||||
var options = [];
|
||||
options = payloadNames[unitType]
|
||||
if (options != undefined && options.length > 0)
|
||||
{
|
||||
options.sort();
|
||||
this.showSelectionScroll(e.originalEvent, options, (payloadName: string) => {
|
||||
this.hideSelectionWheel();
|
||||
this.hideSelectionScroll();
|
||||
spawnAircraft(unitType, e.latlng, getActiveCoalition(), payloadName, e.airbaseName);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
spawnAircraft(unitType, e.latlng, getActiveCoalition());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
65
client/src/other/utils.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
export function distance(lat1: number, lon1: number, lat2: number, lon2: number)
|
||||
{
|
||||
const R = 6371e3; // metres
|
||||
const φ1 = deg2rad(lat1); // φ, λ in radians
|
||||
const φ2 = deg2rad(lat2);
|
||||
const Δφ = deg2rad(lat2-lat1);
|
||||
const Δλ = deg2rad(lon2-lon1);
|
||||
|
||||
const a = Math.sin(Δφ/2) * Math.sin(Δφ/2) + Math.cos(φ1) * Math.cos(φ2) * Math.sin(Δλ/2) * Math.sin(Δλ/2);
|
||||
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
|
||||
|
||||
const d = R * c; // in metres
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
export function bearing(lat1: number, lon1: number, lat2: number, lon2: number)
|
||||
{
|
||||
const φ1 = deg2rad(lat1); // φ, λ in radians
|
||||
const φ2 = deg2rad(lat2);
|
||||
const λ1 = deg2rad(lon1); // φ, λ in radians
|
||||
const λ2 = deg2rad(lon2);
|
||||
const y = Math.sin(λ2-λ1) * Math.cos(φ2);
|
||||
const x = Math.cos(φ1)*Math.sin(φ2) - Math.sin(φ1)*Math.cos(φ2)*Math.cos(λ2-λ1);
|
||||
const θ = Math.atan2(y, x);
|
||||
const brng = (rad2deg(θ) + 360) % 360; // in degrees
|
||||
|
||||
return brng;
|
||||
}
|
||||
|
||||
const zeroPad = function(num: number, places: number)
|
||||
{
|
||||
var string = String(num);
|
||||
while (string.length < places)
|
||||
{
|
||||
string += "0";
|
||||
}
|
||||
return string;
|
||||
}
|
||||
|
||||
export function ConvertDDToDMS(D: number, lng: boolean)
|
||||
{
|
||||
var dir = D < 0 ? (lng ? "W" : "S") : lng ? "E" : "N";
|
||||
var deg = 0 | (D < 0 ? (D = -D) : D);
|
||||
var min = 0 | (((D += 1e-9) % 1) * 60);
|
||||
var sec = (0 | (((D * 60) % 1) * 6000)) / 100;
|
||||
var dec = Math.round((sec - Math.floor(sec)) * 100);
|
||||
var sec = Math.floor(sec);
|
||||
if (lng)
|
||||
return dir + zeroPad(deg, 3) + "°" + zeroPad(min, 2) + "'" + zeroPad(sec, 2) + "." + zeroPad(dec, 2) + "\"";
|
||||
else
|
||||
return dir + zeroPad(deg, 2) + "°" + zeroPad(min, 2) + "'" + zeroPad(sec, 2) + "." + zeroPad(dec, 2) + "\"";
|
||||
}
|
||||
|
||||
export function deg2rad(deg: number)
|
||||
{
|
||||
var pi = Math.PI;
|
||||
return deg * (pi/180);
|
||||
}
|
||||
|
||||
export function rad2deg(rad: number)
|
||||
{
|
||||
var pi = Math.PI;
|
||||
return rad / (pi/180);
|
||||
}
|
||||
43
client/src/panels/unitinfopanel.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import { ConvertDDToDMS, rad2deg } from "../other/utils";
|
||||
import { Unit } from "../units/unit";
|
||||
|
||||
export class UnitInfoPanel
|
||||
{
|
||||
#element: HTMLElement
|
||||
#display: string;
|
||||
|
||||
constructor(ID: string)
|
||||
{
|
||||
this.#element = <HTMLElement>document.getElementById(ID);
|
||||
this.#display = '';
|
||||
if (this.#element != null)
|
||||
{
|
||||
this.#display = this.#element.style.display;
|
||||
this.hide();
|
||||
}
|
||||
}
|
||||
|
||||
show()
|
||||
{
|
||||
this.#element.style.display = this.#display;
|
||||
}
|
||||
|
||||
hide()
|
||||
{
|
||||
this.#element.style.display = "none";
|
||||
}
|
||||
|
||||
update(unit: Unit)
|
||||
{
|
||||
if (this.#element != null)
|
||||
{
|
||||
this.#element.querySelector("#unit-name")!.innerHTML = unit.unitName;
|
||||
this.#element.querySelector("#group-name")!.innerHTML = unit.groupName;
|
||||
this.#element.querySelector("#heading")!.innerHTML = String(Math.floor(rad2deg(unit.heading)) + "°");
|
||||
this.#element.querySelector("#altitude")!.innerHTML = String(Math.floor(unit.altitude / 0.3048) + "ft");
|
||||
this.#element.querySelector("#groundspeed")!.innerHTML = String(Math.floor(unit.speed * 1.94384) + "kts");
|
||||
//this.#element.querySelector("#altitude")!.innerHTML = String(Math.floor(unit.missionData.fuel * 100) + "%");
|
||||
this.#element.querySelector("#position")!.innerHTML = ConvertDDToDMS(unit.latitude, false) + " " + ConvertDDToDMS(unit.longitude, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
1
client/src/units/payloadNames.ts
Normal file
512
client/src/units/unit.ts
Normal file
@@ -0,0 +1,512 @@
|
||||
import { Marker, LatLng, Polyline } from 'leaflet';
|
||||
import { ConvertDDToDMS } from '../other/utils';
|
||||
import { getMap, getUnitsManager } from '..';
|
||||
import { UnitMarker, MarkerOptions } from './unitmarker';
|
||||
import { addDestination } from '../dcs/dcs';
|
||||
//import { attackUnit } from 'DCS/DCSCommands.js'
|
||||
|
||||
export class Unit
|
||||
{
|
||||
ID : number;
|
||||
leader : boolean;
|
||||
wingman : boolean;
|
||||
wingmen : Unit[];
|
||||
formation : string;
|
||||
name : string;
|
||||
unitName : string;
|
||||
groupName : string;
|
||||
latitude : number;
|
||||
longitude : number;
|
||||
altitude : number;
|
||||
heading : number;
|
||||
coalitionID : number;
|
||||
alive : boolean;
|
||||
speed : number;
|
||||
currentTask : string;
|
||||
type : Object | null;
|
||||
flags : Object | null;
|
||||
activePath : any | null; // TODO: declare inteface
|
||||
missionData : Object | null;
|
||||
|
||||
#selectable : boolean;
|
||||
#selected : boolean;
|
||||
#preventClick : boolean;
|
||||
#pathMarkers : Marker[];
|
||||
#pathPolyline : Polyline;
|
||||
#targetsPolylines : Polyline[];
|
||||
#marker : UnitMarker;
|
||||
#timer : number;
|
||||
|
||||
static getConstructor(name: string)
|
||||
{
|
||||
if (name === "GroundUnit") return GroundUnit;
|
||||
if (name === "Aircraft") return Aircraft;
|
||||
if (name === "Helicopter") return Helicopter;
|
||||
if (name === "Missile") return Missile;
|
||||
if (name === "Bomb") return Bomb;
|
||||
if (name === "NavyUnit") return NavyUnit;
|
||||
}
|
||||
|
||||
constructor(ID: number, marker: UnitMarker)
|
||||
{
|
||||
this.ID = ID;
|
||||
|
||||
/* Names */
|
||||
this.name = "";
|
||||
this.unitName = "";
|
||||
this.groupName = "";
|
||||
|
||||
/* Position and speed */
|
||||
this.latitude = 0;
|
||||
this.longitude = 0;
|
||||
this.altitude = 0;
|
||||
this.heading = 0;
|
||||
this.speed = 0;
|
||||
|
||||
/* Tasking */
|
||||
this.coalitionID = 0;
|
||||
this.alive = true;
|
||||
this.currentTask = "";
|
||||
|
||||
/* Formation */
|
||||
this.leader = false;
|
||||
this.wingman = false;
|
||||
this.wingmen = [];
|
||||
this.formation = "";
|
||||
|
||||
/* Structures */
|
||||
this.type = null;
|
||||
this.flags = null;
|
||||
this.activePath = null;
|
||||
this.missionData = null;
|
||||
|
||||
this.#selectable = true;
|
||||
this.#timer = 0;
|
||||
|
||||
/* The marker is set by the inherited class */
|
||||
this.#marker = marker;
|
||||
this.#marker.on('click', (e) => this.#onClick(e));
|
||||
//this.#marker.on('dblclick', (e) => this.#onDoubleClick(e));
|
||||
|
||||
this.#selected = false;
|
||||
this.#preventClick = false;
|
||||
this.#pathMarkers = [];
|
||||
this.#pathPolyline = new Polyline([], {color: '#2d3e50', weight: 3, opacity: 0.5, smoothFactor: 1});
|
||||
this.#pathPolyline.addTo(getMap());
|
||||
this.#targetsPolylines = [];
|
||||
}
|
||||
|
||||
update(response: JSON)
|
||||
{
|
||||
for (let entry in response)
|
||||
{
|
||||
// @ts-ignore
|
||||
this[entry] = response[entry];
|
||||
}
|
||||
|
||||
this.#updateMarker();
|
||||
|
||||
if (this.getSelected())
|
||||
this.#drawPath();
|
||||
else
|
||||
this.#clearPath();
|
||||
|
||||
/*
|
||||
this.wingmen = [];
|
||||
if (response["wingmenIDs"] != undefined)
|
||||
{
|
||||
for (let ID of response["wingmenIDs"])
|
||||
{
|
||||
this.wingmen.push(unitsManager.getUnitByID(ID));
|
||||
}
|
||||
}
|
||||
this.formation = response["formation"];
|
||||
|
||||
this.missionData = missionData.getUnitData(this.ID)
|
||||
|
||||
this.setSelected(this.getSelected() && this.alive)
|
||||
|
||||
|
||||
|
||||
this.clearTargets();
|
||||
this.missionData = missionData.getUnitData(this.ID);
|
||||
if (this.missionData != undefined)
|
||||
{
|
||||
if (this.getSelected())
|
||||
{
|
||||
this.drawTargets();
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
setSelected(selected: boolean)
|
||||
{
|
||||
// Only alive units can be selected. Some units are not selectable (weapons)
|
||||
if ((this.alive || !selected) && this.#selectable && this.#selected != selected)
|
||||
{
|
||||
this.#selected = selected;
|
||||
this.#marker.setSelected(selected);
|
||||
getUnitsManager().onUnitSelection();
|
||||
}
|
||||
}
|
||||
|
||||
getSelected()
|
||||
{
|
||||
return this.#selected;
|
||||
}
|
||||
|
||||
addDestination(latlng: L.LatLng)
|
||||
{
|
||||
var path: any = {};
|
||||
if (this.activePath != undefined)
|
||||
{
|
||||
path = this.activePath;
|
||||
path[(Object.keys(path).length + 1).toString()] = latlng;
|
||||
}
|
||||
else
|
||||
{
|
||||
path = {"1": latlng};
|
||||
}
|
||||
addDestination
|
||||
}
|
||||
|
||||
clearDestinations()
|
||||
{
|
||||
this.activePath = undefined;
|
||||
}
|
||||
|
||||
#onClick(e: any)
|
||||
{
|
||||
this.#timer = setTimeout(() => {
|
||||
if (!this.#preventClick) {
|
||||
if (getMap().getState() === 'IDLE' || getMap().getState() === 'MOVE_UNIT' || e.originalEvent.ctrlKey)
|
||||
{
|
||||
if (!e.originalEvent.ctrlKey)
|
||||
{
|
||||
getUnitsManager().deselectAllUnits();
|
||||
}
|
||||
this.setSelected(true);
|
||||
}
|
||||
}
|
||||
this.#preventClick = false;
|
||||
}, 200);
|
||||
}
|
||||
|
||||
#updateMarker()
|
||||
{
|
||||
/* Add the marker if not present */
|
||||
if (!getMap().hasLayer(this.#marker))
|
||||
{
|
||||
this.#marker.addTo(getMap());
|
||||
}
|
||||
|
||||
this.#marker.setLatLng(new LatLng(this.latitude, this.longitude));
|
||||
this.#marker.draw({
|
||||
heading: this.heading,
|
||||
speed: this.speed,
|
||||
altitude: this.altitude,
|
||||
alive: this.alive
|
||||
});
|
||||
}
|
||||
|
||||
#drawPath()
|
||||
{
|
||||
if (this.activePath != null)
|
||||
{
|
||||
var _points = [];
|
||||
_points.push(new LatLng(this.latitude, this.longitude));
|
||||
|
||||
// Add markers if missing
|
||||
while (this.#pathMarkers.length < Object.keys(this.activePath).length)
|
||||
{
|
||||
var marker = new Marker([0, 0]).addTo(getMap());
|
||||
this.#pathMarkers.push(marker);
|
||||
}
|
||||
|
||||
// Remove markers if too many
|
||||
while (this.#pathMarkers.length > Object.keys(this.activePath).length)
|
||||
{
|
||||
getMap().removeLayer(this.#pathMarkers[this.#pathMarkers.length - 1]);
|
||||
this.#pathMarkers.splice(this.#pathMarkers.length - 1, 1)
|
||||
}
|
||||
|
||||
// Update the position of the existing markers (to avoid creating markers uselessly)
|
||||
for (let WP in this.activePath)
|
||||
{
|
||||
var destination = this.activePath[WP];
|
||||
this.#pathMarkers[parseInt(WP) - 1].setLatLng([destination.lat, destination.lng]);
|
||||
_points.push(new LatLng(destination.lat, destination.lng));
|
||||
this.#pathPolyline.setLatLngs(_points);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#clearPath()
|
||||
{
|
||||
for (let WP in this.#pathMarkers)
|
||||
{
|
||||
getMap().removeLayer(this.#pathMarkers[WP]);
|
||||
}
|
||||
this.#pathMarkers = [];
|
||||
this.#pathPolyline.setLatLngs([]);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
#onDoubleClick(e)
|
||||
{
|
||||
clearTimeout(this.#timer);
|
||||
this.#preventClick = true;
|
||||
|
||||
var options = [
|
||||
{'tooltip': 'Attack', 'src': 'attack.png', 'callback': () => {map.removeSelectionWheel(); unitsManager.attackUnit(this.ID);}},
|
||||
{'tooltip': 'Go to tanker', 'src': 'tanker.png', 'callback': () => {map.removeSelectionWheel(); showMessage("Function not implemented yet");}},
|
||||
{'tooltip': 'RTB', 'src': 'rtb.png', 'callback': () => {map.removeSelectionWheel(); showMessage("Function not implemented yet");}}
|
||||
]
|
||||
|
||||
if (!this.leader && !this.wingman)
|
||||
{
|
||||
options.push({'tooltip': 'Create formation', 'src': 'formation.png', 'callback': () => {map.removeSelectionWheel(); unitsManager.createFormation(this.ID);}});
|
||||
}
|
||||
|
||||
map.showSelectionWheel(e, options, false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
drawPath()
|
||||
{
|
||||
var _points = [];
|
||||
_points.push(new LatLng(this.latitude, this.longitude));
|
||||
|
||||
// Add markers if missing
|
||||
while (this.#pathMarkers.length < Object.keys(this.activePath).length)
|
||||
{
|
||||
var marker = new Marker([0, 0]).addTo(map.getMap());
|
||||
this.#pathMarkers.push(marker);
|
||||
}
|
||||
|
||||
// Remove markers if too many
|
||||
while (this.#pathMarkers.length > Object.keys(this.activePath).length)
|
||||
{
|
||||
map.getMap().removeLayer(this.#pathMarkers[this.#pathMarkers.length - 1]);
|
||||
this.#pathMarkers.splice(this.#pathMarkers.length - 1, 1)
|
||||
}
|
||||
|
||||
// Update the position of the existing markers (to avoid creating markers uselessly)
|
||||
for (let WP in this.activePath)
|
||||
{
|
||||
var destination = this.activePath[WP];
|
||||
this.#pathMarkers[parseInt(WP) - 1].setLatLng([destination.lat, destination.lng]);
|
||||
_points.push(new LatLng(destination.lat, destination.lng));
|
||||
this.#pathPolyline.setLatLngs(_points);
|
||||
}
|
||||
}
|
||||
|
||||
clearPath()
|
||||
{
|
||||
for (let WP in this.#pathMarkers)
|
||||
{
|
||||
map.getMap().removeLayer(this.#pathMarkers[WP]);
|
||||
}
|
||||
this.#pathMarkers = [];
|
||||
this.#pathPolyline.setLatLngs([]);
|
||||
}
|
||||
|
||||
drawTargets()
|
||||
{
|
||||
for (let typeIndex in this.missionData['targets'])
|
||||
{
|
||||
for (let index in this.missionData['targets'][typeIndex])
|
||||
{
|
||||
var targetData = this.missionData['targets'][typeIndex][index];
|
||||
var target = unitsManager.getUnitByID(targetData.object["id_"])
|
||||
if (target != undefined){
|
||||
var startLatLng = new LatLng(this.latitude, this.longitude)
|
||||
var endLatLng = new LatLng(target.latitude, target.longitude)
|
||||
|
||||
var color;
|
||||
if (typeIndex === "radar")
|
||||
{
|
||||
color = "#FFFF00";
|
||||
}
|
||||
else if (typeIndex === "visual")
|
||||
{
|
||||
color = "#FF00FF";
|
||||
}
|
||||
else if (typeIndex === "rwr")
|
||||
{
|
||||
color = "#00FF00";
|
||||
}
|
||||
else
|
||||
{
|
||||
color = "#FFFFFF";
|
||||
}
|
||||
var targetPolyline = new Polyline([startLatLng, endLatLng], {color: color, weight: 3, opacity: 1, smoothFactor: 1});
|
||||
targetPolyline.addTo(map.getMap());
|
||||
this.#targetsPolylines.push(targetPolyline)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
clearTargets()
|
||||
{
|
||||
for (let index in this.#targetsPolylines)
|
||||
{
|
||||
map.getMap().removeLayer(this.#targetsPolylines[index])
|
||||
}
|
||||
}
|
||||
|
||||
attackUnit(targetID)
|
||||
{
|
||||
// Call DCS attackUnit function
|
||||
if (this.ID != targetID)
|
||||
{
|
||||
attackUnit(this.ID, targetID);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: show a message
|
||||
}
|
||||
}
|
||||
|
||||
changeSpeed(speedChange)
|
||||
{
|
||||
// TODO move in dedicated file
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("PUT", RESTaddress);
|
||||
xhr.setRequestHeader("Content-Type", "application/json");
|
||||
xhr.onreadystatechange = () => {
|
||||
if (xhr.readyState === 4) {
|
||||
console.log(this.unitName + " speed change request: " + speedChange);
|
||||
}
|
||||
};
|
||||
|
||||
var command = {"ID": this.ID, "change": speedChange}
|
||||
var data = {"changeSpeed": command}
|
||||
|
||||
xhr.send(JSON.stringify(data));
|
||||
}
|
||||
|
||||
changeAltitude(altitudeChange)
|
||||
{
|
||||
// TODO move in dedicated file
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("PUT", RESTaddress);
|
||||
xhr.setRequestHeader("Content-Type", "application/json");
|
||||
xhr.onreadystatechange = () => {
|
||||
if (xhr.readyState === 4) {
|
||||
console.log(this.unitName + " altitude change request: " + altitudeChange);
|
||||
}
|
||||
};
|
||||
|
||||
var command = {"ID": this.ID, "change": altitudeChange}
|
||||
var data = {"changeAltitude": command}
|
||||
|
||||
xhr.send(JSON.stringify(data));
|
||||
}
|
||||
|
||||
setformation(formation)
|
||||
{
|
||||
// TODO move in dedicated file
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("PUT", RESTaddress);
|
||||
xhr.setRequestHeader("Content-Type", "application/json");
|
||||
xhr.onreadystatechange = () => {
|
||||
if (xhr.readyState === 4) {
|
||||
console.log(this.unitName + " formation change: " + formation);
|
||||
}
|
||||
};
|
||||
|
||||
var command = {"ID": this.ID, "formation": formation}
|
||||
var data = {"setFormation": command}
|
||||
|
||||
xhr.send(JSON.stringify(data));
|
||||
}
|
||||
|
||||
setLeader(wingmenIDs)
|
||||
{
|
||||
// TODO move in dedicated file
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("PUT", RESTaddress);
|
||||
xhr.setRequestHeader("Content-Type", "application/json");
|
||||
xhr.onreadystatechange = () => {
|
||||
if (xhr.readyState === 4) {
|
||||
console.log(this.unitName + " created formation with: " + wingmenIDs);
|
||||
}
|
||||
};
|
||||
|
||||
var command = {"ID": this.ID, "wingmenIDs": wingmenIDs}
|
||||
var data = {"setLeader": command}
|
||||
|
||||
xhr.send(JSON.stringify(data));
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
export class AirUnit extends Unit
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
export class Aircraft extends AirUnit
|
||||
{
|
||||
constructor(ID: number, options: MarkerOptions)
|
||||
{
|
||||
var marker = new UnitMarker(options);
|
||||
super(ID, marker);
|
||||
}
|
||||
}
|
||||
|
||||
export class Helicopter extends AirUnit
|
||||
{
|
||||
constructor(ID: number, options: MarkerOptions)
|
||||
{
|
||||
var marker = new UnitMarker(options);
|
||||
super(ID, marker);
|
||||
}
|
||||
}
|
||||
|
||||
export class GroundUnit extends Unit
|
||||
{
|
||||
constructor(ID: number, options: MarkerOptions)
|
||||
{
|
||||
var marker = new UnitMarker(options);
|
||||
super(ID, marker);
|
||||
}
|
||||
}
|
||||
|
||||
export class NavyUnit extends Unit
|
||||
{
|
||||
constructor(ID: number, options: MarkerOptions)
|
||||
{
|
||||
var marker = new UnitMarker(options);
|
||||
super(ID, marker);
|
||||
}
|
||||
}
|
||||
|
||||
export class Weapon extends Unit
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
export class Missile extends Weapon
|
||||
{
|
||||
constructor(ID: number, options: MarkerOptions)
|
||||
{
|
||||
var marker = new UnitMarker(options);
|
||||
super(ID, marker);
|
||||
}
|
||||
}
|
||||
|
||||
export class Bomb extends Weapon
|
||||
{
|
||||
constructor(ID: number, options: MarkerOptions)
|
||||
{
|
||||
var marker = new UnitMarker(options);
|
||||
super(ID, marker);
|
||||
}
|
||||
}
|
||||
276
client/src/units/unitTypes.ts
Normal file
@@ -0,0 +1,276 @@
|
||||
|
||||
|
||||
export var unitTypes: any = {};
|
||||
/* NAVY */
|
||||
unitTypes.navy = {};
|
||||
unitTypes.navy.blue = [
|
||||
"VINSON",
|
||||
"PERRY",
|
||||
"TICONDEROG"
|
||||
]
|
||||
|
||||
unitTypes.navy.red = [
|
||||
"ALBATROS",
|
||||
"KUZNECOW",
|
||||
"MOLNIYA",
|
||||
"MOSCOW",
|
||||
"NEUSTRASH",
|
||||
"PIOTR",
|
||||
"REZKY"
|
||||
]
|
||||
|
||||
unitTypes.navy.civil = [
|
||||
"ELNYA",
|
||||
"Dry-cargo ship-2",
|
||||
"Dry-cargo ship-1",
|
||||
"ZWEZDNY"
|
||||
]
|
||||
|
||||
unitTypes.navy.submarine = [
|
||||
"KILO",
|
||||
"SOM"
|
||||
]
|
||||
|
||||
unitTypes.navy.speedboat = [
|
||||
"speedboat"
|
||||
]
|
||||
|
||||
/* VEHICLES (GROUND) */
|
||||
unitTypes.vehicles = []
|
||||
unitTypes.vehicles.Howitzers = [
|
||||
"2B11 mortar",
|
||||
"SAU Gvozdika",
|
||||
"SAU Msta",
|
||||
"SAU Akatsia",
|
||||
"SAU 2-C9",
|
||||
"M-109"
|
||||
]
|
||||
|
||||
unitTypes.vehicles.IFV = [
|
||||
"AAV7",
|
||||
"BMD-1",
|
||||
"BMP-1",
|
||||
"BMP-2",
|
||||
"BMP-3",
|
||||
"Boman",
|
||||
"BRDM-2",
|
||||
"BTR-80",
|
||||
"BTR_D",
|
||||
"Bunker",
|
||||
"Cobra",
|
||||
"LAV-25",
|
||||
"M1043 HMMWV Armament",
|
||||
"M1045 HMMWV TOW",
|
||||
"M1126 Stryker ICV",
|
||||
"M-113",
|
||||
"M1134 Stryker ATGM",
|
||||
"M-2 Bradley",
|
||||
"Marder",
|
||||
"MCV-80",
|
||||
"MTLB",
|
||||
"Paratrooper RPG-16",
|
||||
"Paratrooper AKS-74",
|
||||
"Sandbox",
|
||||
"Soldier AK",
|
||||
"Infantry AK",
|
||||
"Soldier M249",
|
||||
"Soldier M4",
|
||||
"Soldier M4 GRG",
|
||||
"Soldier RPG",
|
||||
"TPZ"
|
||||
]
|
||||
|
||||
unitTypes.vehicles.MLRS = [
|
||||
"Grad-URAL",
|
||||
"Uragan_BM-27",
|
||||
"Smerch",
|
||||
"MLRS"
|
||||
]
|
||||
|
||||
unitTypes.vehicles.SAM = [
|
||||
"2S6 Tunguska",
|
||||
"Kub 2P25 ln",
|
||||
"5p73 s-125 ln",
|
||||
"S-300PS 5P85C ln",
|
||||
"S-300PS 5P85D ln",
|
||||
"SA-11 Buk LN 9A310M1",
|
||||
"Osa 9A33 ln",
|
||||
"Tor 9A331",
|
||||
"Strela-10M3",
|
||||
"Strela-1 9P31",
|
||||
"SA-11 Buk CC 9S470M1",
|
||||
"SA-8 Osa LD 9T217",
|
||||
"Patriot AMG",
|
||||
"Patriot ECS",
|
||||
"Gepard",
|
||||
"Hawk pcp",
|
||||
"SA-18 Igla manpad",
|
||||
"SA-18 Igla comm",
|
||||
"Igla manpad INS",
|
||||
"SA-18 Igla-S manpad",
|
||||
"SA-18 Igla-S comm",
|
||||
"Vulcan",
|
||||
"Hawk ln",
|
||||
"M48 Chaparral",
|
||||
"M6 Linebacker",
|
||||
"Patriot ln",
|
||||
"M1097 Avenger",
|
||||
"Patriot EPP",
|
||||
"Patriot cp",
|
||||
"Roland ADS",
|
||||
"S-300PS 54K6 cp",
|
||||
"Stinger manpad GRG",
|
||||
"Stinger manpad dsr",
|
||||
"Stinger comm dsr",
|
||||
"Stinger manpad",
|
||||
"Stinger comm",
|
||||
"ZSU-23-4 Shilka",
|
||||
"ZU-23 Emplacement Closed",
|
||||
"ZU-23 Emplacement",
|
||||
"ZU-23 Closed Insurgent",
|
||||
"Ural-375 ZU-23 Insurgent",
|
||||
"ZU-23 Insurgent",
|
||||
"Ural-375 ZU-23"
|
||||
]
|
||||
|
||||
unitTypes.vehicles.Radar = [
|
||||
"1L13 EWR",
|
||||
"Kub 1S91 str",
|
||||
"S-300PS 40B6M tr",
|
||||
"S-300PS 40B6MD sr",
|
||||
"55G6 EWR",
|
||||
"S-300PS 64H6E sr",
|
||||
"SA-11 Buk SR 9S18M1",
|
||||
"Dog Ear radar",
|
||||
"Hawk tr",
|
||||
"Hawk sr",
|
||||
"Patriot str",
|
||||
"Hawk cwar",
|
||||
"p-19 s-125 sr",
|
||||
"Roland Radar",
|
||||
"snr s-125 tr"
|
||||
]
|
||||
|
||||
unitTypes.vehicles.Structures = [
|
||||
"house1arm",
|
||||
"house2arm",
|
||||
"outpost_road",
|
||||
"outpost",
|
||||
"houseA_arm"
|
||||
]
|
||||
|
||||
unitTypes.vehicles.Tanks = [
|
||||
"Challenger2",
|
||||
"Leclerc",
|
||||
"Leopard1A3",
|
||||
"Leopard-2",
|
||||
"M-60",
|
||||
"M1128 Stryker MGS",
|
||||
"M-1 Abrams",
|
||||
"T-55",
|
||||
"T-72B",
|
||||
"T-80UD",
|
||||
"T-90"
|
||||
]
|
||||
|
||||
unitTypes.vehicles.Unarmed = [
|
||||
"Ural-4320 APA-5D",
|
||||
"ATMZ-5",
|
||||
"ATZ-10",
|
||||
"GAZ-3307",
|
||||
"GAZ-3308",
|
||||
"GAZ-66",
|
||||
"M978 HEMTT Tanker",
|
||||
"HEMTT TFFT",
|
||||
"IKARUS Bus",
|
||||
"KAMAZ Truck",
|
||||
"LAZ Bus",
|
||||
"Hummer",
|
||||
"M 818",
|
||||
"MAZ-6303",
|
||||
"Predator GCS",
|
||||
"Predator TrojanSpirit",
|
||||
"Suidae",
|
||||
"Tigr_233036",
|
||||
"Trolley bus",
|
||||
"UAZ-469",
|
||||
"Ural ATsP-6",
|
||||
"Ural-375 PBU",
|
||||
"Ural-375",
|
||||
"Ural-4320-31",
|
||||
"Ural-4320T",
|
||||
"VAZ Car",
|
||||
"ZiL-131 APA-80",
|
||||
"SKP-11",
|
||||
"ZIL-131 KUNG",
|
||||
"ZIL-4331"
|
||||
]
|
||||
|
||||
/* AIRPLANES */
|
||||
unitTypes.air = {}
|
||||
|
||||
unitTypes.air.CAP = [
|
||||
"F-4E",
|
||||
"F/A-18C",
|
||||
"MiG-29S",
|
||||
"F-14A",
|
||||
"Su-27",
|
||||
"MiG-23MLD",
|
||||
"Su-33",
|
||||
"MiG-25RBT",
|
||||
"Su-30",
|
||||
"MiG-31",
|
||||
"Mirage 2000-5",
|
||||
"F-15C",
|
||||
"F-5E",
|
||||
"F-16C bl.52d",
|
||||
]
|
||||
|
||||
unitTypes.air.CAS = [
|
||||
"Tornado IDS",
|
||||
"F-4E",
|
||||
"F/A-18C",
|
||||
"MiG-27K",
|
||||
"A-10C",
|
||||
"Su-25",
|
||||
"Su-34",
|
||||
"Su-17M4",
|
||||
"F-15E",
|
||||
]
|
||||
|
||||
unitTypes.air.strike = [
|
||||
"Tu-22M3",
|
||||
"B-52H",
|
||||
"F-111F",
|
||||
"Tu-95MS",
|
||||
"Su-24M",
|
||||
"Tu-160",
|
||||
"F-117A",
|
||||
"B-1B",
|
||||
"Tu-142",
|
||||
]
|
||||
|
||||
unitTypes.air.tank = [
|
||||
"S-3B Tanker",
|
||||
"KC-135",
|
||||
"IL-78M",
|
||||
]
|
||||
|
||||
unitTypes.air.awacs = [
|
||||
"A-50",
|
||||
"E-3A",
|
||||
"E-2D",
|
||||
]
|
||||
|
||||
unitTypes.air.drone = [
|
||||
"MQ-1A Predator",
|
||||
"MQ-9 Reaper",
|
||||
]
|
||||
|
||||
unitTypes.air.transport = [
|
||||
"C-130",
|
||||
"An-26B",
|
||||
"An-30M",
|
||||
"C-17A",
|
||||
"IL-76MD",
|
||||
]
|
||||
147
client/src/units/unitmarker.ts
Normal file
@@ -0,0 +1,147 @@
|
||||
import * as L from 'leaflet'
|
||||
import { Symbol } from 'milsymbol'
|
||||
|
||||
export interface MarkerOptions
|
||||
{
|
||||
unitName: string
|
||||
name: string
|
||||
human: boolean
|
||||
coalitionID: number
|
||||
type: any
|
||||
}
|
||||
|
||||
export interface MarkerData
|
||||
{
|
||||
heading: number
|
||||
speed: number
|
||||
altitude: number
|
||||
alive: boolean
|
||||
}
|
||||
|
||||
export class UnitMarker extends L.Marker
|
||||
{
|
||||
#unitName: string
|
||||
#name: string
|
||||
#human: boolean
|
||||
#coalitionID: number
|
||||
#alive: boolean
|
||||
|
||||
constructor(options: MarkerOptions)
|
||||
{
|
||||
super(new L.LatLng(0, 0), {riseOnHover: true});
|
||||
this.#unitName = options.unitName
|
||||
this.#name = options.name
|
||||
this.#human = options.human
|
||||
this.#coalitionID = options.coalitionID
|
||||
|
||||
this.#alive = true;
|
||||
|
||||
var symbol = new Symbol(this.#computeMarkerCode(options), {size: 100});
|
||||
var img = symbol.asCanvas().toDataURL('image/png');
|
||||
|
||||
var icon = new L.DivIcon({
|
||||
html: `<table class="unit-marker-container" id="container">
|
||||
<tr>
|
||||
<td>
|
||||
<div class="unit-marker-icon" id="icon"><img src="${img}"></div>
|
||||
<div class="unit-marker-unitName" id="unitName">${this.#unitName}</div>
|
||||
<div class="unit-marker-altitude" id="altitude"></div>
|
||||
<div class="unit-marker-speed" id="speed"></div>
|
||||
<div class="unit-marker-name" id="name">${this.#name}</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>`,
|
||||
className: 'unit-marker'});
|
||||
this.setIcon(icon);
|
||||
}
|
||||
|
||||
onAdd(map: L.Map): this
|
||||
{
|
||||
super.onAdd(map);
|
||||
var element = <HTMLElement>this.getElement();
|
||||
this.addEventListener('mouseover', function(e: any) { e.target?.setHovered(true);});
|
||||
this.addEventListener('mouseout', function(e: any) { e.target?.setHovered(false);});
|
||||
return this
|
||||
}
|
||||
|
||||
draw(data: MarkerData)
|
||||
{
|
||||
var element = this.getElement();
|
||||
if (element != null)
|
||||
{
|
||||
var nameDiv = <HTMLElement>element.querySelector("#name");
|
||||
var unitNameDiv = <HTMLElement>element.querySelector("#unitName");
|
||||
var container = <HTMLElement>element.querySelector("#container");
|
||||
var icon = <HTMLElement>element.querySelector("#icon");
|
||||
var altitudeDiv = <HTMLElement>element.querySelector("#altitude");
|
||||
var speedDiv = <HTMLElement>element.querySelector("#speed");
|
||||
|
||||
nameDiv.style.left = (-(nameDiv.offsetWidth - container.offsetWidth) / 2) + "px";
|
||||
unitNameDiv.style.left = (-(unitNameDiv.offsetWidth - container.offsetWidth) / 2) + "px";
|
||||
|
||||
icon.style.transform = "rotate(" + data.heading + "rad)";
|
||||
altitudeDiv.innerHTML = String(Math.round(data.altitude / 0.3048 / 100) / 10);
|
||||
speedDiv.innerHTML = String(Math.round(data.speed * 1.94384));
|
||||
}
|
||||
}
|
||||
|
||||
setSelected(selected: boolean)
|
||||
{
|
||||
this.getElement()?.querySelector("#icon")?.classList.remove("unit-marker-hovered");
|
||||
this.getElement()?.querySelector("#icon")?.classList.toggle("unit-marker-selected", selected);
|
||||
}
|
||||
|
||||
setHovered(hovered: boolean)
|
||||
{
|
||||
this.getElement()?.querySelector("#icon")?.classList.toggle("unit-marker-hovered", hovered && this.#alive);
|
||||
}
|
||||
|
||||
#computeMarkerCode(options: MarkerOptions)
|
||||
{
|
||||
var identity = "00";
|
||||
var set = "00";
|
||||
var entity = "00";
|
||||
var entityType = "00";
|
||||
var entitySubtype = "00";
|
||||
|
||||
/* Identity */
|
||||
if (options.coalitionID == 1)
|
||||
identity = "06" /* Hostile */
|
||||
else if (options.coalitionID == 2)
|
||||
identity = "03" /* Friendly */
|
||||
else
|
||||
identity = "04" /* Neutral */
|
||||
|
||||
if (options.type.level1 == 1)
|
||||
{
|
||||
set = "01"
|
||||
entity = "11"
|
||||
if (options.type.level2 == 1)
|
||||
entityType = "01"
|
||||
else if (options.type.level2 == 1)
|
||||
entityType = "02"
|
||||
|
||||
if (options.type.level3 == 1)
|
||||
entitySubtype = "04";
|
||||
else if (options.type.level3 == 2)
|
||||
entitySubtype = "05";
|
||||
else if (options.type.level3 == 3)
|
||||
entitySubtype = "04";
|
||||
else if (options.type.level3 == 4)
|
||||
entitySubtype = "02";
|
||||
else if (options.type.level3 == 5)
|
||||
entitySubtype = "00";
|
||||
else if (options.type.level3 == 6)
|
||||
entitySubtype = "00";
|
||||
}
|
||||
else if (options.type.level1 == 2)
|
||||
set = "10"
|
||||
else if (options.type.level1 == 3)
|
||||
set = "30"
|
||||
else if (options.type.level1 == 2)
|
||||
set = "02"
|
||||
|
||||
|
||||
return `10${identity}${set}0000${entity}${entityType}${entitySubtype}0000`
|
||||
}
|
||||
}
|
||||
260
client/src/units/unitsmanager.ts
Normal file
@@ -0,0 +1,260 @@
|
||||
import { getUnitInfoPanel } from "..";
|
||||
import { Unit, GroundUnit } from "./unit";
|
||||
|
||||
export class UnitsManager
|
||||
{
|
||||
#units: { [ID: number]: Unit};
|
||||
#copiedUnits: Unit[];
|
||||
|
||||
constructor()
|
||||
{
|
||||
this.#units = {};
|
||||
this.#copiedUnits = [];
|
||||
}
|
||||
|
||||
addUnit(ID: number, data: any)
|
||||
{
|
||||
// The name of the unit category is exactly the same as the constructor name
|
||||
var constructor = Unit.getConstructor(data.category);
|
||||
if (constructor != undefined)
|
||||
{
|
||||
var options = {
|
||||
unitName: data.unitName,
|
||||
name: data.name,
|
||||
human: data.human,
|
||||
coalitionID: data.coalitionID,
|
||||
type: data.type
|
||||
}
|
||||
this.#units[ID] = new constructor(ID, options);
|
||||
}
|
||||
}
|
||||
|
||||
getUnitByID(ID: number)
|
||||
{
|
||||
return this.#units[ID];
|
||||
}
|
||||
|
||||
removeUnit(ID: number)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
deselectAllUnits()
|
||||
{
|
||||
for (let ID in this.#units)
|
||||
{
|
||||
this.#units[ID].setSelected(false);
|
||||
}
|
||||
}
|
||||
|
||||
update(data: any)
|
||||
{
|
||||
for (let ID in data["units"])
|
||||
{
|
||||
// Create the unit if missing from the local array, then update the data. Drawing is handled by leaflet.
|
||||
if (!(ID in this.#units))
|
||||
{
|
||||
this.addUnit(parseInt(ID), data["units"][ID]);
|
||||
}
|
||||
this.#units[parseInt(ID)].update(data["units"][ID]);
|
||||
}
|
||||
|
||||
if (this.getSelectedUnits().length == 1)
|
||||
{
|
||||
getUnitInfoPanel().show();
|
||||
getUnitInfoPanel().update(this.getSelectedUnits()[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
getUnitInfoPanel().hide();
|
||||
}
|
||||
}
|
||||
|
||||
onUnitSelection()
|
||||
{
|
||||
//if (this.getSelectedUnits().length > 0)
|
||||
//{
|
||||
// map.setState("MOVE_UNIT");
|
||||
// unitControlPanel.setEnabled(true);
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// map.setState("IDLE");
|
||||
// unitControlPanel.setEnabled(false);
|
||||
//}
|
||||
}
|
||||
|
||||
// selectFromBounds(bounds)
|
||||
// {
|
||||
// this.deselectAllUnits();
|
||||
// for (let ID in this.#units)
|
||||
// {
|
||||
// var latlng = new LatLng(this.#units[ID].latitude, this.#units[ID].longitude);
|
||||
// if (bounds.contains(latlng))
|
||||
// {
|
||||
// this.#units[ID].setSelected(true);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
getSelectedUnits()
|
||||
{
|
||||
var selectedUnits = [];
|
||||
for (let ID in this.#units)
|
||||
{
|
||||
if (this.#units[ID].getSelected())
|
||||
{
|
||||
selectedUnits.push(this.#units[ID]);
|
||||
}
|
||||
}
|
||||
return selectedUnits;
|
||||
}
|
||||
|
||||
// addDestination(latlng)
|
||||
// {
|
||||
// var selectedUnits = this.getSelectedUnits();
|
||||
// for (let idx in selectedUnits)
|
||||
// {
|
||||
// var commandedUnit = selectedUnits[idx];
|
||||
// if (selectedUnits[idx].wingman)
|
||||
// {
|
||||
// commandedUnit = this.getLeader(selectedUnits[idx].ID);
|
||||
// }
|
||||
// commandedUnit.addDestination(latlng);
|
||||
// }
|
||||
// }
|
||||
|
||||
// clearDestinations()
|
||||
// {
|
||||
// var selectedUnits = this.getSelectedUnits();
|
||||
// for (let idx in selectedUnits)
|
||||
// {
|
||||
// var commandedUnit = selectedUnits[idx];
|
||||
// if (selectedUnits[idx].wingman)
|
||||
// {
|
||||
// commandedUnit = this.getLeader(selectedUnits[idx].ID);
|
||||
// }
|
||||
// commandedUnit.clearDestinations();
|
||||
// }
|
||||
// }
|
||||
|
||||
// selectedUnitsMove()
|
||||
// {
|
||||
|
||||
// }
|
||||
|
||||
// selectedUnitsChangeSpeed(speedChange)
|
||||
// {
|
||||
// var selectedUnits = this.getSelectedUnits();
|
||||
// for (let idx in selectedUnits)
|
||||
// {
|
||||
// selectedUnits[idx].changeSpeed(speedChange);
|
||||
// }
|
||||
// }
|
||||
|
||||
// selectedUnitsChangeAltitude(altitudeChange)
|
||||
// {
|
||||
// var selectedUnits = this.getSelectedUnits();
|
||||
// for (let idx in selectedUnits)
|
||||
// {
|
||||
// selectedUnits[idx].changeAltitude(altitudeChange);
|
||||
// }
|
||||
// }
|
||||
|
||||
// handleKeyEvent(e)
|
||||
// {
|
||||
// if (e.originalEvent.code === 'KeyC' && e.originalEvent.ctrlKey)
|
||||
// {
|
||||
// this.copyUnits();
|
||||
// }
|
||||
// else if (e.originalEvent.code === 'KeyV' && e.originalEvent.ctrlKey)
|
||||
// {
|
||||
// this.pasteUnits();
|
||||
// }
|
||||
// }
|
||||
|
||||
// copyUnits()
|
||||
// {
|
||||
// this.#copiedUnits = this.getSelectedUnits();
|
||||
// }
|
||||
|
||||
// pasteUnits()
|
||||
// {
|
||||
// for (let idx in this.#copiedUnits)
|
||||
// {
|
||||
// var unit = this.#copiedUnits[idx];
|
||||
// cloneUnit(unit.ID);
|
||||
// }
|
||||
// }
|
||||
|
||||
// attackUnit(ID)
|
||||
// {
|
||||
// var selectedUnits = this.getSelectedUnits();
|
||||
// for (let idx in selectedUnits)
|
||||
// {
|
||||
// // If a unit is a wingman, send the command to its leader
|
||||
// var commandedUnit = selectedUnits[idx];
|
||||
// if (selectedUnits[idx].wingman)
|
||||
// {
|
||||
// commandedUnit = this.getLeader(selectedUnits[idx].ID);
|
||||
// }
|
||||
// commandedUnit.attackUnit(ID);
|
||||
// }
|
||||
// }
|
||||
|
||||
// createFormation(ID)
|
||||
// {
|
||||
// var selectedUnits = this.getSelectedUnits();
|
||||
// var wingmenIDs = [];
|
||||
// for (let idx in selectedUnits)
|
||||
// {
|
||||
// if (selectedUnits[idx].wingman)
|
||||
// {
|
||||
// showMessage(selectedUnits[idx].unitName + " is already in a formation.");
|
||||
// return;
|
||||
// }
|
||||
// else if (selectedUnits[idx].leader)
|
||||
// {
|
||||
// showMessage(selectedUnits[idx].unitName + " is already in a formation.");
|
||||
// return;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// /* TODO
|
||||
// if (selectedUnits[idx].category !== this.getUnitByID(ID).category)
|
||||
// {
|
||||
// showMessage("All units must be of the same category to create a formation.");
|
||||
// }
|
||||
// */
|
||||
// if (selectedUnits[idx].ID != ID)
|
||||
// {
|
||||
// wingmenIDs.push(selectedUnits[idx].ID);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// if (wingmenIDs.length > 0)
|
||||
// {
|
||||
// this.getUnitByID(ID).setLeader(wingmenIDs);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// showMessage("At least 2 units must be selected to create a formation.");
|
||||
// }
|
||||
// }
|
||||
|
||||
// getLeader(ID)
|
||||
// {
|
||||
// for (let idx in this.#units)
|
||||
// {
|
||||
// var unit = this.#units[idx];
|
||||
// if (unit.leader)
|
||||
// {
|
||||
// if (unit.wingmen.includes(this.getUnitByID(ID)))
|
||||
// {
|
||||
// return unit;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// showMessage("Error: no leader found for this unit")
|
||||
// }
|
||||
}
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
/* Modules */
|
||||
"module": "commonjs", /* Specify what module code is generated. */
|
||||
// "rootDir": "./", /* Specify the root folder within your source files. */
|
||||
"rootDir": "./src", /* Specify the root folder within your source files. */
|
||||
// "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */
|
||||
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
|
||||
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
|
||||
@@ -99,5 +99,8 @@
|
||||
/* Completeness */
|
||||
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
|
||||
"skipLibCheck": true /* Skip type checking all .d.ts files. */
|
||||
}
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.ts"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -8,8 +8,10 @@
|
||||
|
||||
<body>
|
||||
<div id="olympus-map-container">
|
||||
<%- include('unitInfo.ejs') %>
|
||||
<%- include('unitinfo.ejs') %>
|
||||
</div>
|
||||
<%- include('selectionwheel.ejs') %>
|
||||
<%- include('selectionscroll.ejs') %>
|
||||
<script src="javascripts/bundle.js"></script>
|
||||
</body>
|
||||
|
||||
|
||||
3
client/views/selectionscroll.ejs
Normal file
@@ -0,0 +1,3 @@
|
||||
<div id="selection-scroll" class="olympus-selection-scroll-container">
|
||||
|
||||
</div>
|
||||
7
client/views/selectionwheel.ejs
Normal file
@@ -0,0 +1,7 @@
|
||||
<div class="olympus-selection-wheel" id="selection-wheel">
|
||||
<div class="olympus-wheel">
|
||||
</div>
|
||||
<label>
|
||||
<input type="checkbox" id="coalition-switch"> <span class="olympus-selection-wheel-slider olympus-selection-wheel-switch"></span>
|
||||
</label>
|
||||
</div>
|
||||
@@ -1,4 +1,4 @@
|
||||
<div class="olympus-panel" id="olympus-unit-info">
|
||||
<div class="olympus-panel" id="olympus-unit-info-panel">
|
||||
<table>
|
||||
<tr>
|
||||
<td colspan="4" class="olympus-panel-title">
|
||||
|
||||
@@ -14,11 +14,9 @@
|
||||
#selection-wheel {
|
||||
width: 100%;
|
||||
border-radius: 50%;
|
||||
/*background: conic-gradient(from var(--start_angle), var(--highlight) 0deg, var(--highlight) calc(var(--gradient_start) - 1deg), var(--normal) var(--gradient_start), var(--normal) var(--gradient_stop), var(--highlight) calc(var(--gradient_stop) + 1deg), var(--highlight) 360deg);*/
|
||||
background: var(--normal);
|
||||
-webkit-mask: radial-gradient(transparent 30%,#000 31%);
|
||||
mask: radial-gradient(transparent 30%,#000 31%);
|
||||
transition: background-color var(--color_transition);
|
||||
}
|
||||
#selection-wheel:before {
|
||||
content: "";
|
||||
@@ -32,7 +30,6 @@
|
||||
z-index: 1000;
|
||||
width: 0px;
|
||||
height: 0px;
|
||||
transition: width var(--animation_duration), height var(--animation_duration), left var(--animation_duration), top var(--animation_duration);
|
||||
overflow: visible;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -45,7 +42,6 @@
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
opacity: 0;
|
||||
transition: opacity var(--animation_duration), left var(--animation_duration), top var(--animation_duration);
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -57,9 +53,7 @@
|
||||
width: 45px;
|
||||
height: 45px;
|
||||
/*filter: invert(100%);*/
|
||||
transition: width var(--animation_duration), height var(--animation_duration);
|
||||
filter: drop-shadow(1px 1px 0px var(--highlight)) drop-shadow(1px -1px 0px var(--highlight)) drop-shadow(-1px 1px 0px var(--highlight)) drop-shadow(-1px -1px 0px var(--highlight));
|
||||
|
||||
}
|
||||
|
||||
.selection-wheel-button:hover {
|
||||
@@ -69,10 +63,8 @@
|
||||
.selection-wheel-button:hover .selection-wheel-image {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
/*filter: invert(21%) sepia(23%) saturate(775%) hue-rotate(170deg) brightness(92%) contrast(90%);*/
|
||||
}
|
||||
|
||||
/* The switch - the box around the slider */
|
||||
.switch {
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
@@ -81,17 +73,14 @@
|
||||
width: 60px;
|
||||
height: 34px;
|
||||
margin-top: -17px;
|
||||
transition: opacity var(--animation_duration);
|
||||
}
|
||||
|
||||
/* Hide default HTML checkbox */
|
||||
.switch input {
|
||||
opacity: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
/* The slider */
|
||||
.slider {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
@@ -99,9 +88,9 @@
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: var(--blue);
|
||||
-webkit-transition: var(--color_transition);
|
||||
transition: var(--color_transition);
|
||||
background-color: var(--blue-coalition-color);
|
||||
-webkit-transition: 0.2s;
|
||||
transition: 0.2s;
|
||||
}
|
||||
|
||||
.slider:before {
|
||||
@@ -112,16 +101,16 @@
|
||||
left: 4px;
|
||||
bottom: 4px;
|
||||
background-color: white;
|
||||
-webkit-transition: var(--color_transition);
|
||||
transition: var(--color_transition);
|
||||
-webkit-transition: 0.2s;
|
||||
transition: 0.2s;
|
||||
}
|
||||
|
||||
input:checked + .slider {
|
||||
background-color: var(--red);
|
||||
background-color: var(--blue-coalition-color);
|
||||
}
|
||||
|
||||
input:focus + .slider {
|
||||
box-shadow: 0 0 1px var(--red);
|
||||
box-shadow: 0 0 1px var(--blue-coalition-color);
|
||||
}
|
||||
|
||||
input:checked + .slider:before {
|
||||
|
||||
|
Before Width: | Height: | Size: 7.9 KiB |