From 3124a0f6b551fd5bb47fafa5254994fca5c0c1f1 Mon Sep 17 00:00:00 2001 From: PeekabooSteam Date: Thu, 20 Apr 2023 14:22:16 +0100 Subject: [PATCH] Added assigned speeds, alts, select unit. --- client/public/stylesheets/atc.css | 31 ++++++++--- client/routes/api/atc.js | 74 +++++++++++++++++++++----- client/src/atc/atc.ts | 55 +++++++++++-------- client/src/atc/atcboard.ts | 88 ++++++++++++++++++++++--------- client/views/atc.ejs | 2 +- 5 files changed, 184 insertions(+), 66 deletions(-) diff --git a/client/public/stylesheets/atc.css b/client/public/stylesheets/atc.css index 9258da8c..c19e19fd 100644 --- a/client/public/stylesheets/atc.css +++ b/client/public/stylesheets/atc.css @@ -84,8 +84,8 @@ -.ol-strip-board-headers :nth-child(6), -.ol-strip-board-strip :nth-child(6) { +.ol-strip-board-headers :last-child, +.ol-strip-board-strip :last-child { width:20px; } @@ -98,12 +98,17 @@ text-align: center; } -[data-board-type="tower"] .ol-strip-board-strip > :first-child { +[data-board-type="tower"] .ol-strip-board-strip a { + color:white; +} + +[data-board-type="tower"] .ol-strip-board-strip > :nth-child(2) { text-align: left; } -[data-board-type="tower"] .ol-strip-board-strip :nth-child(3) input { - width:25px; +[data-board-type="tower"] .ol-strip-board-strip :nth-child(3) input, +[data-board-type="tower"] .ol-strip-board-strip :nth-child(5) input { + width:30px; } [data-board-type="tower"] .ol-strip-board-strip :nth-child(3) { @@ -111,6 +116,19 @@ } +[data-altitude-assigned] [data-point="assignedAltitude"] input, +[data-speed-assigned] [data-point="assignedSpeed"] input { + background-color:#ffffffbb; + color: black; + font-weight: var( --font-weight-bolder ); +} + +[data-warning-altitude] [data-point="altitude"], +[data-warning-speed] [data-point="speed"] { + background:#cc0000; + border-radius: var( --border-radius-sm ); +} + .ol-strip-board-strip > [data-point="name"] { @@ -172,5 +190,6 @@ } [data-board-type="tower"] { - top:100px; + right:10px; + top:10px; } \ No newline at end of file diff --git a/client/routes/api/atc.js b/client/routes/api/atc.js index a89df3b0..2429cdce 100644 --- a/client/routes/api/atc.js +++ b/client/routes/api/atc.js @@ -26,26 +26,56 @@ function uuidv4() { function Flight( name, boardId, unitId ) { - this.id = uuidv4(); - this.boardId = boardId; - this.name = name; - this.status = "unknown"; - this.takeoffTime = -1; - this.unitId = parseInt( unitId ); + this.assignedAltitude = 0; + this.assignedSpeed = 0; + this.id = uuidv4(); + this.boardId = boardId; + this.name = name; + this.status = "unknown"; + this.takeoffTime = -1; + this.unitId = parseInt( unitId ); } Flight.prototype.getData = function() { return { - "id" : this.id, - "boardId" : this.boardId, - "name" : this.name, - "status" : this.status, - "takeoffTime" : this.takeoffTime, - "unitId" : this.unitId + "assignedAltitude" : this.assignedAltitude, + "assignedSpeed" : this.assignedSpeed, + "id" : this.id, + "boardId" : this.boardId, + "name" : this.name, + "status" : this.status, + "takeoffTime" : this.takeoffTime, + "unitId" : this.unitId }; } +Flight.prototype.setAssignedAltitude = function( assignedAltitude ) { + + if ( isNaN( assignedAltitude ) ) { + return "Altitude must be a number" + } + + this.assignedAltitude = parseInt( assignedAltitude ); + + return true; + +} + + +Flight.prototype.setAssignedSpeed = function( assignedSpeed ) { + + if ( isNaN( assignedSpeed ) ) { + return "Speed must be a number" + } + + this.assignedSpeed = parseInt( assignedSpeed ); + + return true; + +} + + Flight.prototype.setOrder = function( order ) { this.order = order; @@ -156,6 +186,26 @@ app.patch( "/flight/:flightId", ( req, res ) => { res.status( 400 ).send( `Unrecognised flight ID (given: "${req.params.flightId}")` ); } + if ( req.body.hasOwnProperty( "assignedAltitude" ) ) { + + const altitudeChangeSuccess = flight.setAssignedAltitude( req.body.assignedAltitude ); + + if ( altitudeChangeSuccess !== true ) { + res.status( 400 ).send( altitudeChangeSuccess ); + } + + } + + if ( req.body.hasOwnProperty( "assignedSpeed" ) ) { + + const speedChangeSuccess = flight.setAssignedSpeed( req.body.assignedSpeed ); + + if ( speedChangeSuccess !== true ) { + res.status( 400 ).send( speedChangeSuccess ); + } + + } + if ( req.body.status ) { const statusChangeSuccess = flight.setStatus( req.body.status ); diff --git a/client/src/atc/atc.ts b/client/src/atc/atc.ts index 4855eaaf..856380ec 100644 --- a/client/src/atc/atc.ts +++ b/client/src/atc/atc.ts @@ -3,13 +3,15 @@ import { ATCBoardGround } from "./board/ground"; import { ATCBoardTower } from "./board/tower"; export interface FlightInterface { - id : string; - boardId : string; - name : string; - order : number; - status : "unknown"; - takeoffTime : number; - unitId : number; + assignedSpeed: any; + assignedAltitude : any; + id : string; + boardId : string; + name : string; + order : number; + status : "unknown"; + takeoffTime : number; + unitId : number; } @@ -19,7 +21,7 @@ class ATCDataHandler { #flights:{[key:string]: FlightInterface} = {}; #updateInterval:number|undefined = undefined; - #updateIntervalDelay:number = 1000; + #updateIntervalDelay:number = 2500; // Wait between unit update requests constructor( atc:ATC ) { @@ -43,23 +45,29 @@ class ATCDataHandler { startUpdates() { - + this.#updateInterval = setInterval( () => { - fetch( '/api/atc/flight', { - method: 'GET', - headers: { - 'Accept': '*/*', - 'Content-Type': 'application/json' - } - }) - .then( response => response.json() ) - .then( data => { - this.setFlights( data ); - }); + const aBoardIsVisible = this.#atc.getBoards().some( board => board.boardIsVisible() ); + + if ( aBoardIsVisible ) { + + fetch( '/api/atc/flight', { + method: 'GET', + headers: { + 'Accept': '*/*', + 'Content-Type': 'application/json' + } + }) + .then( response => response.json() ) + .then( data => { + this.setFlights( data ); + }); + + } }, this.#updateIntervalDelay ); - + } @@ -106,6 +114,11 @@ export class ATC { } + getBoards() { + return this.#boards; + } + + getDataHandler() { return this.#dataHandler; } diff --git a/client/src/atc/atcboard.ts b/client/src/atc/atcboard.ts index 52877996..205cd6a1 100644 --- a/client/src/atc/atcboard.ts +++ b/client/src/atc/atcboard.ts @@ -45,6 +45,19 @@ export abstract class ATCBoard { this.#stripBoardElement = this.getBoardElement().querySelector( ".ol-strip-board-strips" ); this.#clockElement = this.getBoardElement().querySelector( ".ol-strip-board-clock" ); + + new MutationObserver( () => { + if ( this.boardIsVisible() ) { + this.startUpdates(); + } else { + this.stopUpdates(); + } + }).observe( this.getBoardElement(), { + "attributes": true, + "childList": false, + "subtree": false + }); + new Sortable( this.getStripBoardElement(), { "handle": ".handle", @@ -90,7 +103,7 @@ export abstract class ATCBoard { this.#setupAddFlight(); - //this.#_setupDemoData(); + // this.#_setupDemoData(); } @@ -152,6 +165,11 @@ export abstract class ATCBoard { } + boardIsVisible() { + return ( !this.getBoardElement().classList.contains( "hide" ) ); + } + + calculateTimeToGo( fromTimestamp:number, toTimestamp:number ) { let timestamp = ( toTimestamp - fromTimestamp ) / 1000; @@ -386,6 +404,10 @@ export abstract class ATCBoard { startUpdates() { + if ( !this.boardIsVisible() ) { + return; + } + this.#updateInterval = setInterval( () => { this.update(); @@ -417,7 +439,6 @@ export abstract class ATCBoard { } - protected update() { console.warn( "No custom update method defined." ); } @@ -431,6 +452,20 @@ export abstract class ATCBoard { } + updateFlight( flightId:string, reqBody:object ) { + + return fetch( '/api/atc/flight/' + flightId, { + method: 'PATCH', + headers: { + 'Accept': '*/*', + 'Content-Type': 'application/json' + }, + "body": JSON.stringify( reqBody ) + }); + + } + + #_setupDemoData() { fetch( '/api/atc/flight/', { @@ -446,31 +481,32 @@ export abstract class ATCBoard { }) }); - fetch( '/api/atc/flight/', { - method: 'POST', - headers: { - 'Accept': '*/*', - 'Content-Type': 'application/json' - }, - "body": JSON.stringify({ - "boardId" : this.getBoardId(), - "name" : this.getBoardId() + " 2", - "unitId" : 1 - }) - }); + + // fetch( '/api/atc/flight/', { + // method: 'POST', + // headers: { + // 'Accept': '*/*', + // 'Content-Type': 'application/json' + // }, + // "body": JSON.stringify({ + // "boardId" : this.getBoardId(), + // "name" : this.getBoardId() + " 2", + // "unitId" : 2 + // }) + // }); - fetch( '/api/atc/flight/', { - method: 'POST', - headers: { - 'Accept': '*/*', - 'Content-Type': 'application/json' - }, - "body": JSON.stringify({ - "boardId" : this.getBoardId(), - "name" : this.getBoardId() + " 3", - "unitId" : 1 - }) - }); + // fetch( '/api/atc/flight/', { + // method: 'POST', + // headers: { + // 'Accept': '*/*', + // 'Content-Type': 'application/json' + // }, + // "body": JSON.stringify({ + // "boardId" : this.getBoardId(), + // "name" : this.getBoardId() + " 3", + // "unitId" : 9 + // }) + // }); } diff --git a/client/views/atc.ejs b/client/views/atc.ejs index 3e969e33..19046c70 100644 --- a/client/views/atc.ejs +++ b/client/views/atc.ejs @@ -1,7 +1,7 @@ <%- include('atc/board.ejs', { "boardId": "strip-board-tower", "boardType": "tower", - "headers": [ "Flight", "a-Alt", "alt" ] + "headers": [ "Flight", "a. Alt", "alt", "a. Speed", "Speed" ] }) %> <%- include('atc/board.ejs', {