diff --git a/client/package.json b/client/package.json index 4e1de078..47eac41c 100644 --- a/client/package.json +++ b/client/package.json @@ -47,6 +47,7 @@ "@types/node": "^18.16.1", "@types/sortablejs": "^1.15.0", "@types/svg-injector": "^0.0.29", + "ajv": "^8.12.0", "babelify": "^10.0.0", "browserify": "^17.0.0", "concurrently": "^7.6.0", diff --git a/client/public/databases/airbases/sinaimap.json b/client/public/databases/airbases/sinaimap.json index 87f5bae6..25850239 100644 --- a/client/public/databases/airbases/sinaimap.json +++ b/client/public/databases/airbases/sinaimap.json @@ -1037,7 +1037,7 @@ "01R": { "magHeading": "11", "Heading": "16", - "ILS": "109.7" + "ILS": "109.70" } }, { @@ -1366,7 +1366,7 @@ "length": "9536" } ], - "TACAN": "0X", + "TACAN": "", "ICAO": "HECW", "elevation": "439" } diff --git a/client/public/stylesheets/leaflet/leaflet.css b/client/public/stylesheets/leaflet/leaflet.css index 9ade8dc4..1981009f 100644 --- a/client/public/stylesheets/leaflet/leaflet.css +++ b/client/public/stylesheets/leaflet/leaflet.css @@ -60,11 +60,6 @@ padding: 0; } -.leaflet-container img.leaflet-tile { - /* See: https://bugs.chromium.org/p/chromium/issues/detail?id=600120 */ - mix-blend-mode: plus-lighter; -} - .leaflet-container.leaflet-touch-zoom { -ms-touch-action: pan-x pan-y; touch-action: pan-x pan-y; @@ -651,7 +646,7 @@ svg.leaflet-image-layer.leaflet-interactive path { } /* Printing */ - + @media print { /* Prevent printers from removing background-images of controls. */ .leaflet-control { diff --git a/client/src/olympusapp.ts b/client/src/olympusapp.ts index aa1d9d7e..0f38ebfb 100644 --- a/client/src/olympusapp.ts +++ b/client/src/olympusapp.ts @@ -18,6 +18,7 @@ import { Manager } from "./other/manager"; import { SVGInjector } from "@tanem/svg-injector"; import { ServerManager } from "./server/servermanager"; import { sha256 } from 'js-sha256'; +import Ajv from "ajv" import { BLUE_COMMANDER, FILL_SELECTED_RING, GAME_MASTER, HIDE_UNITS_SHORT_RANGE_RINGS, RED_COMMANDER, SHOW_UNITS_ACQUISITION_RINGS, SHOW_UNITS_ENGAGEMENT_RINGS, SHOW_UNIT_LABELS } from "./constants/constants"; import { aircraftDatabase } from "./unit/databases/aircraftdatabase"; @@ -27,6 +28,8 @@ import { navyUnitDatabase } from "./unit/databases/navyunitdatabase"; import { UnitListPanel } from "./panels/unitlistpanel"; import { ContextManager } from "./context/contextmanager"; import { Context } from "./context/context"; +import { AirDefenceUnitSpawnMenu } from "./controls/unitspawnmenu"; +import { AirbasesJSONSchemaValidator } from "./schemas/schema"; var VERSION = "{{OLYMPUS_VERSION_NUMBER}}"; @@ -193,6 +196,9 @@ export class OlympusApp { this.#unitsManager = new UnitsManager(); this.#weaponsManager = new WeaponsManager(); + /* Validate data */ + this.#validateData(); + // Toolbars this.getToolbarsManager().add("primaryToolbar", new PrimaryToolbar("primary-toolbar")) .add("commandModeToolbar", new CommandModeToolbar("command-mode-toolbar")); @@ -447,4 +453,28 @@ export class OlympusApp { img.addEventListener("load", () => { SVGInjector(img); }); }) } + + #validateData() { + + const airbasesValidator = new AirbasesJSONSchemaValidator(); + + /* + const validator = new Ajv(); + const schema = { + type: "object", + properties: { + foo: {type: "integer"}, + bar: {type: "string"}, + }, + required: ["foo"], + additionalProperties: false, + } + + const data = this.#getRunwayData(); + + const validate = validator.compile(schema); + const valid = validate(data); + if (!valid) console.log(validate.errors); + //*/ + } } \ No newline at end of file diff --git a/client/src/schemas/airbases.schema.json b/client/src/schemas/airbases.schema.json new file mode 100644 index 00000000..2a47a001 --- /dev/null +++ b/client/src/schemas/airbases.schema.json @@ -0,0 +1,67 @@ +{ + "type": "object", + "additionalProperties": false, + "properties": { + "airfields": { + "type": "object", + "minProperties": 1, + "patternProperties": { + ".*": { + "type": "object", + "properties": { + "elevation": { + "type": "string", + "pattern": "^(0|([1-9][0-9]*))?$" + }, + "ICAO": { + "type": "string" + }, + "runways": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "headings": { + "type": "array", + "items": { + "type": "object", + "patternProperties": { + ".*": { + "type": "object", + "properties": { + "ILS": { + "type": "string", + "pattern": "^(1[0-9]{1,2}\\.[0-9][05])?$" + }, + "magHeading": { + "type": "string", + "pattern": "^([0-2][0-9]{2})|(3[0-6][0-9])?$" + } + }, + "required": ["magHeading"] + } + } + }, + "minItems": 1 + }, + "length": { + "type": "string", + "pattern": "^[1-9][0-9]{3,4}$" + } + }, + "required": [ "headings", "length" ] + } + }, + "TACAN": { + "type": "string", + "pattern": "^([1-9][0-9]{1,2}X)?$" + } + }, + "required": [ "elevation", "runways" ] + } + } + } + }, + "required": ["airfields"] +} \ No newline at end of file diff --git a/client/src/schemas/schema.ts b/client/src/schemas/schema.ts new file mode 100644 index 00000000..8f4a33b6 --- /dev/null +++ b/client/src/schemas/schema.ts @@ -0,0 +1,51 @@ +import Ajv, { JSONSchemaType } from "ajv"; +import { AnySchemaObject, Schema } from "ajv/dist/core"; + + +// For future extension +abstract class JSONSchemaValidator { + + #schema!:AnySchemaObject; + + constructor( schema:AnySchemaObject ) { + this.#schema = schema; + } + + getSchema() { + return this.#schema; + } + +} + + +export class AirbasesJSONSchemaValidator extends JSONSchemaValidator { + + constructor( ) { + + const schema = require("../schemas/airbases.schema.json"); + + super( schema ); + + const ajv = new Ajv({ + "allErrors": true + }); + + [ + require( "../../public/databases/airbases/caucasus.json" ), + require( "../../public/databases/airbases/falklands.json" ), + require( "../../public/databases/airbases/marianas.json" ), + require( "../../public/databases/airbases/nevada.json" ), + require( "../../public/databases/airbases/normandy.json" ), + require( "../../public/databases/airbases/persiangulf.json" ), + require( "../../public/databases/airbases/sinaimap.json" ), + require( "../../public/databases/airbases/syria.json" ), + require( "../../public/databases/airbases/thechannel.json" ) + ].forEach( data => { + const validate = ajv.compile(this.getSchema()); + const valid = validate(data); + + if (!valid) console.error(validate.errors); + }); + } + +} \ No newline at end of file