From 83bb72faacc2913fab9f759af3411b81058aed74 Mon Sep 17 00:00:00 2001 From: js0ny Date: Sat, 6 Dec 2025 05:55:59 +0000 Subject: [PATCH] feat(frontend): Add restricted area visualisation --- drone-frontend/src/App.svelte | 105 +- drone-frontend/src/app.css | 31 +- .../src/components/PlaybackControls.svelte | 12 +- drone-frontend/src/components/Sidebar.svelte | 38 +- drone-frontend/src/main.js | 6 +- drone-frontend/src/sampleData.js | 2564 ++++++++--------- drone-frontend/src/stores.js | 4 +- drone-frontend/src/utils.js | 151 +- flake.nix | 1 + .../ilp-cw-api/Front-end Test/Imperative.bru | 14 + .../controller/GeoJsonDataController.java | 25 - .../controller/MapMetaController.java | 32 + .../service/DroneInfoService.java | 71 +- 13 files changed, 1589 insertions(+), 1465 deletions(-) delete mode 100644 ilp-rest-service/src/main/java/io/github/js0ny/ilp_coursework/controller/GeoJsonDataController.java create mode 100644 ilp-rest-service/src/main/java/io/github/js0ny/ilp_coursework/controller/MapMetaController.java diff --git a/drone-frontend/src/App.svelte b/drone-frontend/src/App.svelte index cb62793..10be888 100644 --- a/drone-frontend/src/App.svelte +++ b/drone-frontend/src/App.svelte @@ -48,12 +48,16 @@ let map; let pathLayer; let markerLayer; + let restrictedLayer; + let servicePointLayer; let currentBounds = fallbackBounds; let apiBase = "http://localhost:8080/api/v1"; let blackBoxBase = "http://localhost:3000"; let dispatchBody = JSON.stringify(defaultDispatch, null, 2); let plannedPath = samplePathResponse; + let restrictedAreas = []; + let servicePoints = []; let stepSeconds = STEP_SECONDS; let status = "System Ready. Waiting for dispatch payload."; @@ -101,7 +105,11 @@ // Reactive Statements $: timeline = buildTimeline(plannedPath); - $: totalSteps = Math.max(timeline.totalSteps, plannedPath?.totalMoves || 1, 1); + $: totalSteps = Math.max( + timeline.totalSteps, + plannedPath?.totalMoves || 1, + 1, + ); $: tick = Math.min(tick, totalSteps - 1); $: playbackSeconds = tick * stepSeconds; $: wallClock = computeWallClock(startTime, playbackSeconds); @@ -112,7 +120,12 @@ ? computeBounds( positionsNow .map((d) => d.current) - .filter((p) => p && typeof p.lat === "number" && typeof p.lng === "number"), + .filter( + (p) => + p && + typeof p.lat === "number" && + typeof p.lng === "number", + ), ) : timeline.bounds || fallbackBounds; @@ -178,9 +191,13 @@ pathLayer = L.layerGroup().addTo(map); markerLayer = L.layerGroup().addTo(map); + restrictedLayer = L.layerGroup().addTo(map); + servicePointLayer = L.layerGroup().addTo(map); fitMapToBounds(); refreshMap(); + loadRestrictedAreas(); + loadServicePoints(); return () => map?.remove(); }); @@ -223,7 +240,40 @@ await fetchSnapshotForTime(wallClock, false); } - async function fetchSnapshotForTime(requestedTime = wallClock, silent = false) { + async function loadRestrictedAreas() { + try { + const res = await fetch(`${apiBase}/restrictedAreas`); + if (!res.ok) + throw new Error( + res.statusText || "failed to load restricted areas", + ); + const data = await res.json(); + restrictedAreas = Array.isArray(data) ? data : []; + drawRestrictedAreas(); + } catch (err) { + console.error("[RestrictedAreas] fetch failed:", err); + } + } + + async function loadServicePoints() { + try { + const res = await fetch(`${apiBase}/servicePoints`); + if (!res.ok) + throw new Error( + res.statusText || "failed to load service points", + ); + const data = await res.json(); + servicePoints = Array.isArray(data) ? data : []; + drawServicePoints(); + } catch (err) { + console.error("[ServicePoints] fetch failed:", err); + } + } + + async function fetchSnapshotForTime( + requestedTime = wallClock, + silent = false, + ) { if (!requestedTime) return; if (silent && requestedTime === lastSnapshotTime) return; @@ -366,6 +416,50 @@ }); } + function drawRestrictedAreas() { + if (!restrictedLayer) return; + restrictedLayer.clearLayers(); + restrictedAreas.forEach((area) => { + const coords = (area?.vertices || []) + .map((v) => [v.lat, v.lng]) + .filter((p) => Array.isArray(p) && p.length === 2); + if (coords.length < 3) return; + L.polygon(coords, { + color: "#ef4444", // red + weight: 2, + fill: false, + dashArray: "6,6", + }) + .bindTooltip(area?.name || "Restricted Area", { sticky: true }) + .addTo(restrictedLayer); + }); + } + + function drawServicePoints() { + if (!servicePointLayer) return; + servicePointLayer.clearLayers(); + servicePoints.forEach((sp) => { + const loc = sp?.location; + if ( + !loc || + typeof loc.lat !== "number" || + typeof loc.lng !== "number" + ) + return; + const marker = L.marker([loc.lat, loc.lng], { + icon: L.divIcon({ + className: "service-point-icon", + html: `
`, + iconSize: [16, 16], + iconAnchor: [8, 8], + }), + }).bindTooltip(sp?.name || `Service Point ${sp?.id ?? ""}`, { + sticky: true, + }); + marker.addTo(servicePointLayer); + }); + } + function toggleTheme() { theme.update((t) => (t === "dark" ? "light" : "dark")); } @@ -410,9 +504,7 @@ const coords = timelinePaths.get(String(id)) || []; const matchedIdx = findClosestIndex(coords, point); const visited = - matchedIdx >= 0 - ? coords.slice(0, matchedIdx + 1) - : [point]; + matchedIdx >= 0 ? coords.slice(0, matchedIdx + 1) : [point]; const fullPath = coords.length ? coords : [point]; return { id, @@ -477,7 +569,6 @@ {formatDuration(playbackSeconds)} -
- Total Cost - {totalCost ?? "—"} -
Active Drones {activeDrones ?? 0}{snapshot.length ?? 0}
diff --git a/drone-frontend/src/components/Sidebar.svelte b/drone-frontend/src/components/Sidebar.svelte index 15260fe..45a0612 100644 --- a/drone-frontend/src/components/Sidebar.svelte +++ b/drone-frontend/src/components/Sidebar.svelte @@ -5,7 +5,7 @@ export let open = true; export let status = ""; export let loading = false; - + // Configuration Bindings export let apiBase = ""; export let blackBoxBase = ""; @@ -23,7 +23,9 @@ diff --git a/drone-frontend/src/main.js b/drone-frontend/src/main.js index 09f41e9..7ece250 100644 --- a/drone-frontend/src/main.js +++ b/drone-frontend/src/main.js @@ -1,8 +1,8 @@ -import './app.css'; -import App from './App.svelte'; +import "./app.css"; +import App from "./App.svelte"; const app = new App({ - target: document.getElementById('app') + target: document.getElementById("app"), }); export default app; diff --git a/drone-frontend/src/sampleData.js b/drone-frontend/src/sampleData.js index 2378094..d745659 100644 --- a/drone-frontend/src/sampleData.js +++ b/drone-frontend/src/sampleData.js @@ -2,32 +2,32 @@ export const STEP_SECONDS = 1; export const fallbackBounds = { - minLng: -3.19, - maxLng: -3.17, - minLat: 55.94, - maxLat: 55.99, + minLng: -3.19, + maxLng: -3.17, + minLat: 55.94, + maxLat: 55.99, }; export const defaultDispatch = [ - { - id: 501, - date: "2025-01-06", - time: "12:00:00", - requirements: { capacity: 0.5, cooling: false, heating: true, maxCost: 50 }, - delivery: { lng: -3.1852, lat: 55.9451 }, - }, - { - id: 502, - date: "2025-01-06", - time: "12:15:00", - requirements: { - capacity: 1.5, - cooling: true, - heating: false, - maxCost: 120, - }, - delivery: { lng: -3.1776, lat: 55.9498 }, + { + id: 501, + date: "2025-01-06", + time: "12:00:00", + requirements: { capacity: 0.5, cooling: false, heating: true, maxCost: 50 }, + delivery: { lng: -3.1852, lat: 55.9451 }, + }, + { + id: 502, + date: "2025-01-06", + time: "12:15:00", + requirements: { + capacity: 1.5, + cooling: true, + heating: false, + maxCost: 120, }, + delivery: { lng: -3.1776, lat: 55.9498 }, + }, ]; // export const samplePathResponse = { @@ -69,1268 +69,1268 @@ export const defaultDispatch = [ // }; export const samplePathResponse = { - totalCost: 18.43, - totalMoves: 306, - dronePaths: [ + totalCost: 18.43, + totalMoves: 306, + dronePaths: [ + { + droneId: 1, + deliveries: [ { - droneId: 1, - deliveries: [ - { - deliveryId: 123, - flightPath: [ - { - lng: -3.1863580788986368, - lat: 55.94468066708487, - }, - { - lng: -3.186464144915815, - lat: 55.94478673310204, - }, - { - lng: -3.186570210932993, - lat: 55.944892799119216, - }, - { - lng: -3.186676276950171, - lat: 55.94499886513639, - }, - { - lng: -3.186782342967349, - lat: 55.945104931153566, - }, - { - lng: -3.1868884089845273, - lat: 55.94521099717074, - }, - { - lng: -3.1869944750017054, - lat: 55.945317063187915, - }, - { - lng: -3.1871005410188835, - lat: 55.94542312920509, - }, - { - lng: -3.1872066070360616, - lat: 55.945529195222264, - }, - { - lng: -3.1873126730532397, - lat: 55.94563526123944, - }, - { - lng: -3.187418739070418, - lat: 55.94574132725661, - }, - { - lng: -3.187524805087596, - lat: 55.94584739327379, - }, - { - lng: -3.187630871104774, - lat: 55.94595345929096, - }, - { - lng: -3.187736937121952, - lat: 55.94605952530814, - }, - { - lng: -3.1878430031391303, - lat: 55.94616559132531, - }, - { - lng: -3.1879490691563084, - lat: 55.946271657342486, - }, - { - lng: -3.1880551351734865, - lat: 55.94637772335966, - }, - { - lng: -3.1881612011906646, - lat: 55.946483789376835, - }, - { - lng: -3.1882672672078427, - lat: 55.94658985539401, - }, - { - lng: -3.188373333225021, - lat: 55.946695921411184, - }, - { - lng: -3.188479399242199, - lat: 55.94680198742836, - }, - { - lng: -3.188585465259377, - lat: 55.94690805344553, - }, - { - lng: -3.188691531276555, - lat: 55.94701411946271, - }, - { - lng: -3.1887975972937332, - lat: 55.94712018547988, - }, - { - lng: -3.1889036633109114, - lat: 55.94722625149706, - }, - { - lng: -3.1890097293280895, - lat: 55.94733231751423, - }, - { - lng: -3.189067131842944, - lat: 55.947470899444106, - }, - { - lng: -3.1891731978601223, - lat: 55.94757696546128, - }, - { - lng: -3.189230600374977, - lat: 55.947715547391155, - }, - { - lng: -3.189336666392155, - lat: 55.94782161340833, - }, - { - lng: -3.18939406890701, - lat: 55.947960195338204, - }, - { - lng: -3.189500134924188, - lat: 55.94806626135538, - }, - { - lng: -3.189557537439043, - lat: 55.948204843285254, - }, - { - lng: -3.189663603456221, - lat: 55.94831090930243, - }, - { - lng: -3.1897210059710757, - lat: 55.9484494912323, - }, - { - lng: -3.1898270719882538, - lat: 55.94855555724948, - }, - { - lng: -3.1898844745031085, - lat: 55.94869413917935, - }, - { - lng: -3.1899905405202866, - lat: 55.94880020519653, - }, - { - lng: -3.1900479430351414, - lat: 55.9489387871264, - }, - { - lng: -3.1901540090523195, - lat: 55.949044853143576, - }, - { - lng: -3.1902114115671742, - lat: 55.94918343507345, - }, - { - lng: -3.1903174775843524, - lat: 55.949289501090625, - }, - { - lng: -3.190374880099207, - lat: 55.9494280830205, - }, - { - lng: -3.190480946116385, - lat: 55.949534149037675, - }, - { - lng: -3.19053834863124, - lat: 55.94967273096755, - }, - { - lng: -3.190644414648418, - lat: 55.949778796984724, - }, - { - lng: -3.190701817163273, - lat: 55.9499173789146, - }, - { - lng: -3.190807883180451, - lat: 55.95002344493177, - }, - { - lng: -3.1908652856953057, - lat: 55.95016202686165, - }, - { - lng: -3.190971351712484, - lat: 55.95026809287882, - }, - { - lng: -3.1910287542273386, - lat: 55.9504066748087, - }, - { - lng: -3.1911348202445167, - lat: 55.95051274082587, - }, - { - lng: -3.1911922227593714, - lat: 55.950651322755746, - }, - { - lng: -3.1912982887765495, - lat: 55.95075738877292, - }, - { - lng: -3.1913556912914043, - lat: 55.950895970702796, - }, - { - lng: -3.1914617573085824, - lat: 55.95100203671997, - }, - { - lng: -3.191499773625054, - lat: 55.9510924649214, - }, - { - lng: -3.191499773625054, - lat: 55.9510924649214, - }, - { - lng: -3.191393707607876, - lat: 55.95098639890423, - }, - { - lng: -3.191287641590698, - lat: 55.95088033288705, - }, - { - lng: -3.19118157557352, - lat: 55.95077426686988, - }, - { - lng: -3.1910755095563417, - lat: 55.950668200852704, - }, - { - lng: -3.1909694435391636, - lat: 55.95056213483553, - }, - { - lng: -3.1908633775219855, - lat: 55.950456068818355, - }, - { - lng: -3.1907573115048073, - lat: 55.95035000280118, - }, - { - lng: -3.1906512454876292, - lat: 55.950243936784005, - }, - { - lng: -3.190545179470451, - lat: 55.95013787076683, - }, - { - lng: -3.190439113453273, - lat: 55.950031804749656, - }, - { - lng: -3.190333047436095, - lat: 55.94992573873248, - }, - { - lng: -3.190226981418917, - lat: 55.94981967271531, - }, - { - lng: -3.1901209154017387, - lat: 55.94971360669813, - }, - { - lng: -3.1900148493845606, - lat: 55.94960754068096, - }, - { - lng: -3.1899087833673825, - lat: 55.94950147466378, - }, - { - lng: -3.1898027173502044, - lat: 55.94939540864661, - }, - { - lng: -3.1896966513330263, - lat: 55.949289342629434, - }, - { - lng: -3.189590585315848, - lat: 55.94918327661226, - }, - { - lng: -3.18948451929867, - lat: 55.949077210595085, - }, - { - lng: -3.189378453281492, - lat: 55.94897114457791, - }, - { - lng: -3.189272387264314, - lat: 55.948865078560736, - }, - { - lng: -3.1891663212471357, - lat: 55.94875901254356, - }, - { - lng: -3.1890602552299576, - lat: 55.94865294652639, - }, - { - lng: -3.1889541892127795, - lat: 55.94854688050921, - }, - { - lng: -3.1888481231956014, - lat: 55.94844081449204, - }, - { - lng: -3.1887907206807466, - lat: 55.94830223256216, - }, - { - lng: -3.1886846546635685, - lat: 55.94819616654499, - }, - { - lng: -3.188627252148714, - lat: 55.948057584615114, - }, - { - lng: -3.1885211861315357, - lat: 55.94795151859794, - }, - { - lng: -3.188463783616681, - lat: 55.947812936668065, - }, - { - lng: -3.188357717599503, - lat: 55.94770687065089, - }, - { - lng: -3.188300315084648, - lat: 55.947568288721016, - }, - { - lng: -3.18819424906747, - lat: 55.94746222270384, - }, - { - lng: -3.188136846552615, - lat: 55.947323640773966, - }, - { - lng: -3.188030780535437, - lat: 55.94721757475679, - }, - { - lng: -3.1879733780205823, - lat: 55.94707899282692, - }, - { - lng: -3.1878673120034042, - lat: 55.94697292680974, - }, - { - lng: -3.1878099094885495, - lat: 55.94683434487987, - }, - { - lng: -3.1877038434713714, - lat: 55.94672827886269, - }, - { - lng: -3.1876464409565166, - lat: 55.94658969693282, - }, - { - lng: -3.1875403749393385, - lat: 55.946483630915644, - }, - { - lng: -3.1874829724244838, - lat: 55.94634504898577, - }, - { - lng: -3.1873769064073056, - lat: 55.946238982968595, - }, - { - lng: -3.187319503892451, - lat: 55.94610040103872, - }, - { - lng: -3.187213437875273, - lat: 55.945994335021545, - }, - { - lng: -3.187156035360418, - lat: 55.94585575309167, - }, - { - lng: -3.18704996934324, - lat: 55.945749687074496, - }, - { - lng: -3.186992566828385, - lat: 55.94561110514462, - }, - { - lng: -3.186886500811207, - lat: 55.94550503912745, - }, - { - lng: -3.1868290982963523, - lat: 55.94536645719757, - }, - { - lng: -3.186723032279174, - lat: 55.9452603911804, - }, - { - lng: -3.1866656297643194, - lat: 55.94512180925052, - }, - { - lng: -3.1865595637471413, - lat: 55.94501574323335, - }, - { - lng: -3.1865021612322866, - lat: 55.944877161303474, - }, - { - lng: -3.1863960952151085, - lat: 55.9447710952863, - }, - { - lng: -3.1863580788986368, - lat: 55.94468066708487, - }, - ], - }, - ], + deliveryId: 123, + flightPath: [ + { + lng: -3.1863580788986368, + lat: 55.94468066708487, + }, + { + lng: -3.186464144915815, + lat: 55.94478673310204, + }, + { + lng: -3.186570210932993, + lat: 55.944892799119216, + }, + { + lng: -3.186676276950171, + lat: 55.94499886513639, + }, + { + lng: -3.186782342967349, + lat: 55.945104931153566, + }, + { + lng: -3.1868884089845273, + lat: 55.94521099717074, + }, + { + lng: -3.1869944750017054, + lat: 55.945317063187915, + }, + { + lng: -3.1871005410188835, + lat: 55.94542312920509, + }, + { + lng: -3.1872066070360616, + lat: 55.945529195222264, + }, + { + lng: -3.1873126730532397, + lat: 55.94563526123944, + }, + { + lng: -3.187418739070418, + lat: 55.94574132725661, + }, + { + lng: -3.187524805087596, + lat: 55.94584739327379, + }, + { + lng: -3.187630871104774, + lat: 55.94595345929096, + }, + { + lng: -3.187736937121952, + lat: 55.94605952530814, + }, + { + lng: -3.1878430031391303, + lat: 55.94616559132531, + }, + { + lng: -3.1879490691563084, + lat: 55.946271657342486, + }, + { + lng: -3.1880551351734865, + lat: 55.94637772335966, + }, + { + lng: -3.1881612011906646, + lat: 55.946483789376835, + }, + { + lng: -3.1882672672078427, + lat: 55.94658985539401, + }, + { + lng: -3.188373333225021, + lat: 55.946695921411184, + }, + { + lng: -3.188479399242199, + lat: 55.94680198742836, + }, + { + lng: -3.188585465259377, + lat: 55.94690805344553, + }, + { + lng: -3.188691531276555, + lat: 55.94701411946271, + }, + { + lng: -3.1887975972937332, + lat: 55.94712018547988, + }, + { + lng: -3.1889036633109114, + lat: 55.94722625149706, + }, + { + lng: -3.1890097293280895, + lat: 55.94733231751423, + }, + { + lng: -3.189067131842944, + lat: 55.947470899444106, + }, + { + lng: -3.1891731978601223, + lat: 55.94757696546128, + }, + { + lng: -3.189230600374977, + lat: 55.947715547391155, + }, + { + lng: -3.189336666392155, + lat: 55.94782161340833, + }, + { + lng: -3.18939406890701, + lat: 55.947960195338204, + }, + { + lng: -3.189500134924188, + lat: 55.94806626135538, + }, + { + lng: -3.189557537439043, + lat: 55.948204843285254, + }, + { + lng: -3.189663603456221, + lat: 55.94831090930243, + }, + { + lng: -3.1897210059710757, + lat: 55.9484494912323, + }, + { + lng: -3.1898270719882538, + lat: 55.94855555724948, + }, + { + lng: -3.1898844745031085, + lat: 55.94869413917935, + }, + { + lng: -3.1899905405202866, + lat: 55.94880020519653, + }, + { + lng: -3.1900479430351414, + lat: 55.9489387871264, + }, + { + lng: -3.1901540090523195, + lat: 55.949044853143576, + }, + { + lng: -3.1902114115671742, + lat: 55.94918343507345, + }, + { + lng: -3.1903174775843524, + lat: 55.949289501090625, + }, + { + lng: -3.190374880099207, + lat: 55.9494280830205, + }, + { + lng: -3.190480946116385, + lat: 55.949534149037675, + }, + { + lng: -3.19053834863124, + lat: 55.94967273096755, + }, + { + lng: -3.190644414648418, + lat: 55.949778796984724, + }, + { + lng: -3.190701817163273, + lat: 55.9499173789146, + }, + { + lng: -3.190807883180451, + lat: 55.95002344493177, + }, + { + lng: -3.1908652856953057, + lat: 55.95016202686165, + }, + { + lng: -3.190971351712484, + lat: 55.95026809287882, + }, + { + lng: -3.1910287542273386, + lat: 55.9504066748087, + }, + { + lng: -3.1911348202445167, + lat: 55.95051274082587, + }, + { + lng: -3.1911922227593714, + lat: 55.950651322755746, + }, + { + lng: -3.1912982887765495, + lat: 55.95075738877292, + }, + { + lng: -3.1913556912914043, + lat: 55.950895970702796, + }, + { + lng: -3.1914617573085824, + lat: 55.95100203671997, + }, + { + lng: -3.191499773625054, + lat: 55.9510924649214, + }, + { + lng: -3.191499773625054, + lat: 55.9510924649214, + }, + { + lng: -3.191393707607876, + lat: 55.95098639890423, + }, + { + lng: -3.191287641590698, + lat: 55.95088033288705, + }, + { + lng: -3.19118157557352, + lat: 55.95077426686988, + }, + { + lng: -3.1910755095563417, + lat: 55.950668200852704, + }, + { + lng: -3.1909694435391636, + lat: 55.95056213483553, + }, + { + lng: -3.1908633775219855, + lat: 55.950456068818355, + }, + { + lng: -3.1907573115048073, + lat: 55.95035000280118, + }, + { + lng: -3.1906512454876292, + lat: 55.950243936784005, + }, + { + lng: -3.190545179470451, + lat: 55.95013787076683, + }, + { + lng: -3.190439113453273, + lat: 55.950031804749656, + }, + { + lng: -3.190333047436095, + lat: 55.94992573873248, + }, + { + lng: -3.190226981418917, + lat: 55.94981967271531, + }, + { + lng: -3.1901209154017387, + lat: 55.94971360669813, + }, + { + lng: -3.1900148493845606, + lat: 55.94960754068096, + }, + { + lng: -3.1899087833673825, + lat: 55.94950147466378, + }, + { + lng: -3.1898027173502044, + lat: 55.94939540864661, + }, + { + lng: -3.1896966513330263, + lat: 55.949289342629434, + }, + { + lng: -3.189590585315848, + lat: 55.94918327661226, + }, + { + lng: -3.18948451929867, + lat: 55.949077210595085, + }, + { + lng: -3.189378453281492, + lat: 55.94897114457791, + }, + { + lng: -3.189272387264314, + lat: 55.948865078560736, + }, + { + lng: -3.1891663212471357, + lat: 55.94875901254356, + }, + { + lng: -3.1890602552299576, + lat: 55.94865294652639, + }, + { + lng: -3.1889541892127795, + lat: 55.94854688050921, + }, + { + lng: -3.1888481231956014, + lat: 55.94844081449204, + }, + { + lng: -3.1887907206807466, + lat: 55.94830223256216, + }, + { + lng: -3.1886846546635685, + lat: 55.94819616654499, + }, + { + lng: -3.188627252148714, + lat: 55.948057584615114, + }, + { + lng: -3.1885211861315357, + lat: 55.94795151859794, + }, + { + lng: -3.188463783616681, + lat: 55.947812936668065, + }, + { + lng: -3.188357717599503, + lat: 55.94770687065089, + }, + { + lng: -3.188300315084648, + lat: 55.947568288721016, + }, + { + lng: -3.18819424906747, + lat: 55.94746222270384, + }, + { + lng: -3.188136846552615, + lat: 55.947323640773966, + }, + { + lng: -3.188030780535437, + lat: 55.94721757475679, + }, + { + lng: -3.1879733780205823, + lat: 55.94707899282692, + }, + { + lng: -3.1878673120034042, + lat: 55.94697292680974, + }, + { + lng: -3.1878099094885495, + lat: 55.94683434487987, + }, + { + lng: -3.1877038434713714, + lat: 55.94672827886269, + }, + { + lng: -3.1876464409565166, + lat: 55.94658969693282, + }, + { + lng: -3.1875403749393385, + lat: 55.946483630915644, + }, + { + lng: -3.1874829724244838, + lat: 55.94634504898577, + }, + { + lng: -3.1873769064073056, + lat: 55.946238982968595, + }, + { + lng: -3.187319503892451, + lat: 55.94610040103872, + }, + { + lng: -3.187213437875273, + lat: 55.945994335021545, + }, + { + lng: -3.187156035360418, + lat: 55.94585575309167, + }, + { + lng: -3.18704996934324, + lat: 55.945749687074496, + }, + { + lng: -3.186992566828385, + lat: 55.94561110514462, + }, + { + lng: -3.186886500811207, + lat: 55.94550503912745, + }, + { + lng: -3.1868290982963523, + lat: 55.94536645719757, + }, + { + lng: -3.186723032279174, + lat: 55.9452603911804, + }, + { + lng: -3.1866656297643194, + lat: 55.94512180925052, + }, + { + lng: -3.1865595637471413, + lat: 55.94501574323335, + }, + { + lng: -3.1865021612322866, + lat: 55.944877161303474, + }, + { + lng: -3.1863960952151085, + lat: 55.9447710952863, + }, + { + lng: -3.1863580788986368, + lat: 55.94468066708487, + }, + ], }, + ], + }, + { + droneId: 7, + deliveries: [ { - droneId: 7, - deliveries: [ - { - deliveryId: 456, - flightPath: [ - { - lng: -3.17732611501824, - lat: 55.981186279333656, - }, - { - lng: -3.1774321810354182, - lat: 55.98108021331648, - }, - { - lng: -3.1775382470525964, - lat: 55.98097414729931, - }, - { - lng: -3.1776443130697745, - lat: 55.98086808128213, - }, - { - lng: -3.1777503790869526, - lat: 55.98076201526496, - }, - { - lng: -3.1778564451041307, - lat: 55.98065594924778, - }, - { - lng: -3.177962511121309, - lat: 55.98054988323061, - }, - { - lng: -3.178068577138487, - lat: 55.980443817213434, - }, - { - lng: -3.178174643155665, - lat: 55.98033775119626, - }, - { - lng: -3.178280709172843, - lat: 55.980231685179085, - }, - { - lng: -3.178386775190021, - lat: 55.98012561916191, - }, - { - lng: -3.1784928412071993, - lat: 55.980019553144736, - }, - { - lng: -3.1785989072243774, - lat: 55.97991348712756, - }, - { - lng: -3.1787049732415555, - lat: 55.97980742111039, - }, - { - lng: -3.1788110392587337, - lat: 55.97970135509321, - }, - { - lng: -3.1789171052759118, - lat: 55.97959528907604, - }, - { - lng: -3.17902317129309, - lat: 55.97948922305886, - }, - { - lng: -3.179129237310268, - lat: 55.97938315704169, - }, - { - lng: -3.179235303327446, - lat: 55.979277091024514, - }, - { - lng: -3.179341369344624, - lat: 55.97917102500734, - }, - { - lng: -3.1794474353618023, - lat: 55.979064958990165, - }, - { - lng: -3.1795535013789804, - lat: 55.97895889297299, - }, - { - lng: -3.1796595673961585, - lat: 55.978852826955816, - }, - { - lng: -3.1797656334133366, - lat: 55.97874676093864, - }, - { - lng: -3.1798716994305147, - lat: 55.97864069492147, - }, - { - lng: -3.179977765447693, - lat: 55.97853462890429, - }, - { - lng: -3.180083831464871, - lat: 55.97842856288712, - }, - { - lng: -3.180189897482049, - lat: 55.97832249686994, - }, - { - lng: -3.180295963499227, - lat: 55.97821643085277, - }, - { - lng: -3.1804020295164053, - lat: 55.978110364835594, - }, - { - lng: -3.1805080955335834, - lat: 55.97800429881842, - }, - { - lng: -3.1806141615507615, - lat: 55.977898232801245, - }, - { - lng: -3.1807202275679396, - lat: 55.97779216678407, - }, - { - lng: -3.1808262935851177, - lat: 55.977686100766896, - }, - { - lng: -3.180932359602296, - lat: 55.97758003474972, - }, - { - lng: -3.181038425619474, - lat: 55.977473968732546, - }, - { - lng: -3.181144491636652, - lat: 55.97736790271537, - }, - { - lng: -3.18125055765383, - lat: 55.9772618366982, - }, - { - lng: -3.1813566236710082, - lat: 55.97715577068102, - }, - { - lng: -3.1814626896881864, - lat: 55.97704970466385, - }, - { - lng: -3.1815687557053645, - lat: 55.976943638646674, - }, - { - lng: -3.1816748217225426, - lat: 55.9768375726295, - }, - { - lng: -3.1817808877397207, - lat: 55.976731506612325, - }, - { - lng: -3.181886953756899, - lat: 55.97662544059515, - }, - { - lng: -3.181993019774077, - lat: 55.976519374577975, - }, - { - lng: -3.182099085791255, - lat: 55.9764133085608, - }, - { - lng: -3.182205151808433, - lat: 55.976307242543626, - }, - { - lng: -3.182311217825611, - lat: 55.97620117652645, - }, - { - lng: -3.1824172838427893, - lat: 55.97609511050928, - }, - { - lng: -3.1825233498599674, - lat: 55.9759890444921, - }, - { - lng: -3.1826294158771455, - lat: 55.97588297847493, - }, - { - lng: -3.1827354818943236, - lat: 55.975776912457754, - }, - { - lng: -3.1828415479115018, - lat: 55.97567084644058, - }, - { - lng: -3.18294761392868, - lat: 55.975564780423404, - }, - { - lng: -3.183053679945858, - lat: 55.97545871440623, - }, - { - lng: -3.183159745963036, - lat: 55.975352648389055, - }, - { - lng: -3.183265811980214, - lat: 55.97524658237188, - }, - { - lng: -3.1833718779973923, - lat: 55.975140516354706, - }, - { - lng: -3.1834779440145704, - lat: 55.97503445033753, - }, - { - lng: -3.1835840100317485, - lat: 55.97492838432036, - }, - { - lng: -3.1836900760489266, - lat: 55.97482231830318, - }, - { - lng: -3.1837961420661047, - lat: 55.97471625228601, - }, - { - lng: -3.183902208083283, - lat: 55.97461018626883, - }, - { - lng: -3.184008274100461, - lat: 55.97450412025166, - }, - { - lng: -3.184114340117639, - lat: 55.974398054234484, - }, - { - lng: -3.184220406134817, - lat: 55.97429198821731, - }, - { - lng: -3.1843264721519953, - lat: 55.974185922200135, - }, - { - lng: -3.1844325381691734, - lat: 55.97407985618296, - }, - { - lng: -3.1845386041863515, - lat: 55.973973790165786, - }, - { - lng: -3.1846446702035296, - lat: 55.97386772414861, - }, - { - lng: -3.1847507362207077, - lat: 55.97376165813144, - }, - { - lng: -3.184856802237886, - lat: 55.97365559211426, - }, - { - lng: -3.1849953841677623, - lat: 55.97359818959941, - }, - { - lng: -3.1851014501849404, - lat: 55.97349212358223, - }, - { - lng: -3.185240032114817, - lat: 55.97343472106738, - }, - { - lng: -3.185346098131995, - lat: 55.9733286550502, - }, - { - lng: -3.1854846800618715, - lat: 55.97327125253535, - }, - { - lng: -3.1855907460790496, - lat: 55.97316518651817, - }, - { - lng: -3.185729328008926, - lat: 55.97310778400332, - }, - { - lng: -3.185835394026104, - lat: 55.97300171798614, - }, - { - lng: -3.1859739759559806, - lat: 55.97294431547129, - }, - { - lng: -3.1860800419731587, - lat: 55.972838249454114, - }, - { - lng: -3.1862186239030352, - lat: 55.97278084693926, - }, - { - lng: -3.1863246899202133, - lat: 55.972674780922084, - }, - { - lng: -3.18646327185009, - lat: 55.97261737840723, - }, - { - lng: -3.186569337867268, - lat: 55.972511312390054, - }, - { - lng: -3.1867079197971444, - lat: 55.9724539098752, - }, - { - lng: -3.1868139858143225, - lat: 55.972347843858024, - }, - { - lng: -3.186952567744199, - lat: 55.97229044134317, - }, - { - lng: -3.187058633761377, - lat: 55.972184375325995, - }, - { - lng: -3.1871972156912536, - lat: 55.97212697281114, - }, - { - lng: -3.1873032817084317, - lat: 55.972020906793965, - }, - { - lng: -3.187441863638308, - lat: 55.97196350427911, - }, - { - lng: -3.1875479296554863, - lat: 55.971857438261935, - }, - { - lng: -3.1876865115853628, - lat: 55.97180003574708, - }, - { - lng: -3.187792577602541, - lat: 55.971693969729905, - }, - { - lng: -3.1879311595324173, - lat: 55.97163656721505, - }, - { - lng: -3.187986659939753, - lat: 55.97157210129231, - }, - { - lng: -3.187986659939753, - lat: 55.97157210129231, - }, - { - lng: -3.187880593922575, - lat: 55.971678167309484, - }, - { - lng: -3.187774527905397, - lat: 55.97178423332666, - }, - { - lng: -3.1876684618882187, - lat: 55.97189029934383, - }, - { - lng: -3.1875623958710406, - lat: 55.97199636536101, - }, - { - lng: -3.1874563298538625, - lat: 55.97210243137818, - }, - { - lng: -3.1873502638366844, - lat: 55.97220849739536, - }, - { - lng: -3.1872441978195063, - lat: 55.97231456341253, - }, - { - lng: -3.187138131802328, - lat: 55.972420629429706, - }, - { - lng: -3.18703206578515, - lat: 55.97252669544688, - }, - { - lng: -3.186925999767972, - lat: 55.972632761464055, - }, - { - lng: -3.186819933750794, - lat: 55.97273882748123, - }, - { - lng: -3.1867138677336158, - lat: 55.972844893498404, - }, - { - lng: -3.1866078017164376, - lat: 55.97295095951558, - }, - { - lng: -3.1865017356992595, - lat: 55.97305702553275, - }, - { - lng: -3.1863956696820814, - lat: 55.97316309154993, - }, - { - lng: -3.1862896036649033, - lat: 55.9732691575671, - }, - { - lng: -3.186183537647725, - lat: 55.97337522358428, - }, - { - lng: -3.186077471630547, - lat: 55.97348128960145, - }, - { - lng: -3.185971405613369, - lat: 55.973587355618626, - }, - { - lng: -3.185865339596191, - lat: 55.9736934216358, - }, - { - lng: -3.185759273579013, - lat: 55.973799487652975, - }, - { - lng: -3.1856532075618347, - lat: 55.97390555367015, - }, - { - lng: -3.1855471415446566, - lat: 55.974011619687325, - }, - { - lng: -3.1854410755274785, - lat: 55.9741176857045, - }, - { - lng: -3.1853350095103004, - lat: 55.974223751721674, - }, - { - lng: -3.1852289434931222, - lat: 55.97432981773885, - }, - { - lng: -3.185122877475944, - lat: 55.97443588375602, - }, - { - lng: -3.185016811458766, - lat: 55.9745419497732, - }, - { - lng: -3.184910745441588, - lat: 55.97464801579037, - }, - { - lng: -3.18480467942441, - lat: 55.974754081807546, - }, - { - lng: -3.1846986134072317, - lat: 55.97486014782472, - }, - { - lng: -3.1845925473900536, - lat: 55.974966213841896, - }, - { - lng: -3.1844864813728755, - lat: 55.97507227985907, - }, - { - lng: -3.1843804153556974, - lat: 55.975178345876245, - }, - { - lng: -3.1842743493385193, - lat: 55.97528441189342, - }, - { - lng: -3.184168283321341, - lat: 55.975390477910594, - }, - { - lng: -3.184062217304163, - lat: 55.97549654392777, - }, - { - lng: -3.183956151286985, - lat: 55.97560260994494, - }, - { - lng: -3.183850085269807, - lat: 55.97570867596212, - }, - { - lng: -3.1837440192526287, - lat: 55.97581474197929, - }, - { - lng: -3.1836379532354506, - lat: 55.97592080799647, - }, - { - lng: -3.1835318872182725, - lat: 55.97602687401364, - }, - { - lng: -3.1834258212010944, - lat: 55.976132940030816, - }, - { - lng: -3.1833197551839163, - lat: 55.97623900604799, - }, - { - lng: -3.183213689166738, - lat: 55.976345072065165, - }, - { - lng: -3.18310762314956, - lat: 55.97645113808234, - }, - { - lng: -3.183001557132382, - lat: 55.976557204099514, - }, - { - lng: -3.182895491115204, - lat: 55.97666327011669, - }, - { - lng: -3.1827894250980258, - lat: 55.97676933613386, - }, - { - lng: -3.1826833590808477, - lat: 55.97687540215104, - }, - { - lng: -3.1825772930636695, - lat: 55.97698146816821, - }, - { - lng: -3.1824712270464914, - lat: 55.97708753418539, - }, - { - lng: -3.1823651610293133, - lat: 55.97719360020256, - }, - { - lng: -3.182259095012135, - lat: 55.977299666219736, - }, - { - lng: -3.182153028994957, - lat: 55.97740573223691, - }, - { - lng: -3.182046962977779, - lat: 55.977511798254085, - }, - { - lng: -3.181940896960601, - lat: 55.97761786427126, - }, - { - lng: -3.181834830943423, - lat: 55.977723930288434, - }, - { - lng: -3.1817287649262447, - lat: 55.97782999630561, - }, - { - lng: -3.1816226989090666, - lat: 55.97793606232278, - }, - { - lng: -3.1815166328918885, - lat: 55.97804212833996, - }, - { - lng: -3.1814105668747104, - lat: 55.97814819435713, - }, - { - lng: -3.1813045008575322, - lat: 55.97825426037431, - }, - { - lng: -3.181198434840354, - lat: 55.97836032639148, - }, - { - lng: -3.181092368823176, - lat: 55.978466392408656, - }, - { - lng: -3.180986302805998, - lat: 55.97857245842583, - }, - { - lng: -3.18088023678882, - lat: 55.978678524443005, - }, - { - lng: -3.1807741707716417, - lat: 55.97878459046018, - }, - { - lng: -3.1806681047544636, - lat: 55.978890656477354, - }, - { - lng: -3.1805620387372855, - lat: 55.97899672249453, - }, - { - lng: -3.1804559727201074, - lat: 55.9791027885117, - }, - { - lng: -3.180317390790231, - lat: 55.97916019102656, - }, - { - lng: -3.180211324773053, - lat: 55.97926625704373, - }, - { - lng: -3.1800727428431763, - lat: 55.97932365955859, - }, - { - lng: -3.179966676825998, - lat: 55.97942972557576, - }, - { - lng: -3.1798280948961217, - lat: 55.97948712809062, - }, - { - lng: -3.1797220288789436, - lat: 55.97959319410779, - }, - { - lng: -3.179583446949067, - lat: 55.97965059662265, - }, - { - lng: -3.179477380931889, - lat: 55.97975666263982, - }, - { - lng: -3.1793387990020125, - lat: 55.97981406515468, - }, - { - lng: -3.1792327329848344, - lat: 55.97992013117185, - }, - { - lng: -3.179094151054958, - lat: 55.97997753368671, - }, - { - lng: -3.17898808503778, - lat: 55.98008359970388, - }, - { - lng: -3.1788495031079034, - lat: 55.98014100221874, - }, - { - lng: -3.1787434370907253, - lat: 55.98024706823591, - }, - { - lng: -3.178604855160849, - lat: 55.98030447075077, - }, - { - lng: -3.1784987891436707, - lat: 55.98041053676794, - }, - { - lng: -3.178360207213794, - lat: 55.980467939282796, - }, - { - lng: -3.178254141196616, - lat: 55.98057400529997, - }, - { - lng: -3.1781155592667396, - lat: 55.980631407814826, - }, - { - lng: -3.1780094932495615, - lat: 55.980737473832, - }, - { - lng: -3.177870911319685, - lat: 55.980794876346856, - }, - { - lng: -3.177764845302507, - lat: 55.98090094236403, - }, - { - lng: -3.1776262633726304, - lat: 55.980958344878886, - }, - { - lng: -3.1775201973554523, - lat: 55.98106441089606, - }, - { - lng: -3.177381615425576, - lat: 55.981121813410915, - }, - { - lng: -3.17732611501824, - lat: 55.981186279333656, - }, - ], - }, - ], + deliveryId: 456, + flightPath: [ + { + lng: -3.17732611501824, + lat: 55.981186279333656, + }, + { + lng: -3.1774321810354182, + lat: 55.98108021331648, + }, + { + lng: -3.1775382470525964, + lat: 55.98097414729931, + }, + { + lng: -3.1776443130697745, + lat: 55.98086808128213, + }, + { + lng: -3.1777503790869526, + lat: 55.98076201526496, + }, + { + lng: -3.1778564451041307, + lat: 55.98065594924778, + }, + { + lng: -3.177962511121309, + lat: 55.98054988323061, + }, + { + lng: -3.178068577138487, + lat: 55.980443817213434, + }, + { + lng: -3.178174643155665, + lat: 55.98033775119626, + }, + { + lng: -3.178280709172843, + lat: 55.980231685179085, + }, + { + lng: -3.178386775190021, + lat: 55.98012561916191, + }, + { + lng: -3.1784928412071993, + lat: 55.980019553144736, + }, + { + lng: -3.1785989072243774, + lat: 55.97991348712756, + }, + { + lng: -3.1787049732415555, + lat: 55.97980742111039, + }, + { + lng: -3.1788110392587337, + lat: 55.97970135509321, + }, + { + lng: -3.1789171052759118, + lat: 55.97959528907604, + }, + { + lng: -3.17902317129309, + lat: 55.97948922305886, + }, + { + lng: -3.179129237310268, + lat: 55.97938315704169, + }, + { + lng: -3.179235303327446, + lat: 55.979277091024514, + }, + { + lng: -3.179341369344624, + lat: 55.97917102500734, + }, + { + lng: -3.1794474353618023, + lat: 55.979064958990165, + }, + { + lng: -3.1795535013789804, + lat: 55.97895889297299, + }, + { + lng: -3.1796595673961585, + lat: 55.978852826955816, + }, + { + lng: -3.1797656334133366, + lat: 55.97874676093864, + }, + { + lng: -3.1798716994305147, + lat: 55.97864069492147, + }, + { + lng: -3.179977765447693, + lat: 55.97853462890429, + }, + { + lng: -3.180083831464871, + lat: 55.97842856288712, + }, + { + lng: -3.180189897482049, + lat: 55.97832249686994, + }, + { + lng: -3.180295963499227, + lat: 55.97821643085277, + }, + { + lng: -3.1804020295164053, + lat: 55.978110364835594, + }, + { + lng: -3.1805080955335834, + lat: 55.97800429881842, + }, + { + lng: -3.1806141615507615, + lat: 55.977898232801245, + }, + { + lng: -3.1807202275679396, + lat: 55.97779216678407, + }, + { + lng: -3.1808262935851177, + lat: 55.977686100766896, + }, + { + lng: -3.180932359602296, + lat: 55.97758003474972, + }, + { + lng: -3.181038425619474, + lat: 55.977473968732546, + }, + { + lng: -3.181144491636652, + lat: 55.97736790271537, + }, + { + lng: -3.18125055765383, + lat: 55.9772618366982, + }, + { + lng: -3.1813566236710082, + lat: 55.97715577068102, + }, + { + lng: -3.1814626896881864, + lat: 55.97704970466385, + }, + { + lng: -3.1815687557053645, + lat: 55.976943638646674, + }, + { + lng: -3.1816748217225426, + lat: 55.9768375726295, + }, + { + lng: -3.1817808877397207, + lat: 55.976731506612325, + }, + { + lng: -3.181886953756899, + lat: 55.97662544059515, + }, + { + lng: -3.181993019774077, + lat: 55.976519374577975, + }, + { + lng: -3.182099085791255, + lat: 55.9764133085608, + }, + { + lng: -3.182205151808433, + lat: 55.976307242543626, + }, + { + lng: -3.182311217825611, + lat: 55.97620117652645, + }, + { + lng: -3.1824172838427893, + lat: 55.97609511050928, + }, + { + lng: -3.1825233498599674, + lat: 55.9759890444921, + }, + { + lng: -3.1826294158771455, + lat: 55.97588297847493, + }, + { + lng: -3.1827354818943236, + lat: 55.975776912457754, + }, + { + lng: -3.1828415479115018, + lat: 55.97567084644058, + }, + { + lng: -3.18294761392868, + lat: 55.975564780423404, + }, + { + lng: -3.183053679945858, + lat: 55.97545871440623, + }, + { + lng: -3.183159745963036, + lat: 55.975352648389055, + }, + { + lng: -3.183265811980214, + lat: 55.97524658237188, + }, + { + lng: -3.1833718779973923, + lat: 55.975140516354706, + }, + { + lng: -3.1834779440145704, + lat: 55.97503445033753, + }, + { + lng: -3.1835840100317485, + lat: 55.97492838432036, + }, + { + lng: -3.1836900760489266, + lat: 55.97482231830318, + }, + { + lng: -3.1837961420661047, + lat: 55.97471625228601, + }, + { + lng: -3.183902208083283, + lat: 55.97461018626883, + }, + { + lng: -3.184008274100461, + lat: 55.97450412025166, + }, + { + lng: -3.184114340117639, + lat: 55.974398054234484, + }, + { + lng: -3.184220406134817, + lat: 55.97429198821731, + }, + { + lng: -3.1843264721519953, + lat: 55.974185922200135, + }, + { + lng: -3.1844325381691734, + lat: 55.97407985618296, + }, + { + lng: -3.1845386041863515, + lat: 55.973973790165786, + }, + { + lng: -3.1846446702035296, + lat: 55.97386772414861, + }, + { + lng: -3.1847507362207077, + lat: 55.97376165813144, + }, + { + lng: -3.184856802237886, + lat: 55.97365559211426, + }, + { + lng: -3.1849953841677623, + lat: 55.97359818959941, + }, + { + lng: -3.1851014501849404, + lat: 55.97349212358223, + }, + { + lng: -3.185240032114817, + lat: 55.97343472106738, + }, + { + lng: -3.185346098131995, + lat: 55.9733286550502, + }, + { + lng: -3.1854846800618715, + lat: 55.97327125253535, + }, + { + lng: -3.1855907460790496, + lat: 55.97316518651817, + }, + { + lng: -3.185729328008926, + lat: 55.97310778400332, + }, + { + lng: -3.185835394026104, + lat: 55.97300171798614, + }, + { + lng: -3.1859739759559806, + lat: 55.97294431547129, + }, + { + lng: -3.1860800419731587, + lat: 55.972838249454114, + }, + { + lng: -3.1862186239030352, + lat: 55.97278084693926, + }, + { + lng: -3.1863246899202133, + lat: 55.972674780922084, + }, + { + lng: -3.18646327185009, + lat: 55.97261737840723, + }, + { + lng: -3.186569337867268, + lat: 55.972511312390054, + }, + { + lng: -3.1867079197971444, + lat: 55.9724539098752, + }, + { + lng: -3.1868139858143225, + lat: 55.972347843858024, + }, + { + lng: -3.186952567744199, + lat: 55.97229044134317, + }, + { + lng: -3.187058633761377, + lat: 55.972184375325995, + }, + { + lng: -3.1871972156912536, + lat: 55.97212697281114, + }, + { + lng: -3.1873032817084317, + lat: 55.972020906793965, + }, + { + lng: -3.187441863638308, + lat: 55.97196350427911, + }, + { + lng: -3.1875479296554863, + lat: 55.971857438261935, + }, + { + lng: -3.1876865115853628, + lat: 55.97180003574708, + }, + { + lng: -3.187792577602541, + lat: 55.971693969729905, + }, + { + lng: -3.1879311595324173, + lat: 55.97163656721505, + }, + { + lng: -3.187986659939753, + lat: 55.97157210129231, + }, + { + lng: -3.187986659939753, + lat: 55.97157210129231, + }, + { + lng: -3.187880593922575, + lat: 55.971678167309484, + }, + { + lng: -3.187774527905397, + lat: 55.97178423332666, + }, + { + lng: -3.1876684618882187, + lat: 55.97189029934383, + }, + { + lng: -3.1875623958710406, + lat: 55.97199636536101, + }, + { + lng: -3.1874563298538625, + lat: 55.97210243137818, + }, + { + lng: -3.1873502638366844, + lat: 55.97220849739536, + }, + { + lng: -3.1872441978195063, + lat: 55.97231456341253, + }, + { + lng: -3.187138131802328, + lat: 55.972420629429706, + }, + { + lng: -3.18703206578515, + lat: 55.97252669544688, + }, + { + lng: -3.186925999767972, + lat: 55.972632761464055, + }, + { + lng: -3.186819933750794, + lat: 55.97273882748123, + }, + { + lng: -3.1867138677336158, + lat: 55.972844893498404, + }, + { + lng: -3.1866078017164376, + lat: 55.97295095951558, + }, + { + lng: -3.1865017356992595, + lat: 55.97305702553275, + }, + { + lng: -3.1863956696820814, + lat: 55.97316309154993, + }, + { + lng: -3.1862896036649033, + lat: 55.9732691575671, + }, + { + lng: -3.186183537647725, + lat: 55.97337522358428, + }, + { + lng: -3.186077471630547, + lat: 55.97348128960145, + }, + { + lng: -3.185971405613369, + lat: 55.973587355618626, + }, + { + lng: -3.185865339596191, + lat: 55.9736934216358, + }, + { + lng: -3.185759273579013, + lat: 55.973799487652975, + }, + { + lng: -3.1856532075618347, + lat: 55.97390555367015, + }, + { + lng: -3.1855471415446566, + lat: 55.974011619687325, + }, + { + lng: -3.1854410755274785, + lat: 55.9741176857045, + }, + { + lng: -3.1853350095103004, + lat: 55.974223751721674, + }, + { + lng: -3.1852289434931222, + lat: 55.97432981773885, + }, + { + lng: -3.185122877475944, + lat: 55.97443588375602, + }, + { + lng: -3.185016811458766, + lat: 55.9745419497732, + }, + { + lng: -3.184910745441588, + lat: 55.97464801579037, + }, + { + lng: -3.18480467942441, + lat: 55.974754081807546, + }, + { + lng: -3.1846986134072317, + lat: 55.97486014782472, + }, + { + lng: -3.1845925473900536, + lat: 55.974966213841896, + }, + { + lng: -3.1844864813728755, + lat: 55.97507227985907, + }, + { + lng: -3.1843804153556974, + lat: 55.975178345876245, + }, + { + lng: -3.1842743493385193, + lat: 55.97528441189342, + }, + { + lng: -3.184168283321341, + lat: 55.975390477910594, + }, + { + lng: -3.184062217304163, + lat: 55.97549654392777, + }, + { + lng: -3.183956151286985, + lat: 55.97560260994494, + }, + { + lng: -3.183850085269807, + lat: 55.97570867596212, + }, + { + lng: -3.1837440192526287, + lat: 55.97581474197929, + }, + { + lng: -3.1836379532354506, + lat: 55.97592080799647, + }, + { + lng: -3.1835318872182725, + lat: 55.97602687401364, + }, + { + lng: -3.1834258212010944, + lat: 55.976132940030816, + }, + { + lng: -3.1833197551839163, + lat: 55.97623900604799, + }, + { + lng: -3.183213689166738, + lat: 55.976345072065165, + }, + { + lng: -3.18310762314956, + lat: 55.97645113808234, + }, + { + lng: -3.183001557132382, + lat: 55.976557204099514, + }, + { + lng: -3.182895491115204, + lat: 55.97666327011669, + }, + { + lng: -3.1827894250980258, + lat: 55.97676933613386, + }, + { + lng: -3.1826833590808477, + lat: 55.97687540215104, + }, + { + lng: -3.1825772930636695, + lat: 55.97698146816821, + }, + { + lng: -3.1824712270464914, + lat: 55.97708753418539, + }, + { + lng: -3.1823651610293133, + lat: 55.97719360020256, + }, + { + lng: -3.182259095012135, + lat: 55.977299666219736, + }, + { + lng: -3.182153028994957, + lat: 55.97740573223691, + }, + { + lng: -3.182046962977779, + lat: 55.977511798254085, + }, + { + lng: -3.181940896960601, + lat: 55.97761786427126, + }, + { + lng: -3.181834830943423, + lat: 55.977723930288434, + }, + { + lng: -3.1817287649262447, + lat: 55.97782999630561, + }, + { + lng: -3.1816226989090666, + lat: 55.97793606232278, + }, + { + lng: -3.1815166328918885, + lat: 55.97804212833996, + }, + { + lng: -3.1814105668747104, + lat: 55.97814819435713, + }, + { + lng: -3.1813045008575322, + lat: 55.97825426037431, + }, + { + lng: -3.181198434840354, + lat: 55.97836032639148, + }, + { + lng: -3.181092368823176, + lat: 55.978466392408656, + }, + { + lng: -3.180986302805998, + lat: 55.97857245842583, + }, + { + lng: -3.18088023678882, + lat: 55.978678524443005, + }, + { + lng: -3.1807741707716417, + lat: 55.97878459046018, + }, + { + lng: -3.1806681047544636, + lat: 55.978890656477354, + }, + { + lng: -3.1805620387372855, + lat: 55.97899672249453, + }, + { + lng: -3.1804559727201074, + lat: 55.9791027885117, + }, + { + lng: -3.180317390790231, + lat: 55.97916019102656, + }, + { + lng: -3.180211324773053, + lat: 55.97926625704373, + }, + { + lng: -3.1800727428431763, + lat: 55.97932365955859, + }, + { + lng: -3.179966676825998, + lat: 55.97942972557576, + }, + { + lng: -3.1798280948961217, + lat: 55.97948712809062, + }, + { + lng: -3.1797220288789436, + lat: 55.97959319410779, + }, + { + lng: -3.179583446949067, + lat: 55.97965059662265, + }, + { + lng: -3.179477380931889, + lat: 55.97975666263982, + }, + { + lng: -3.1793387990020125, + lat: 55.97981406515468, + }, + { + lng: -3.1792327329848344, + lat: 55.97992013117185, + }, + { + lng: -3.179094151054958, + lat: 55.97997753368671, + }, + { + lng: -3.17898808503778, + lat: 55.98008359970388, + }, + { + lng: -3.1788495031079034, + lat: 55.98014100221874, + }, + { + lng: -3.1787434370907253, + lat: 55.98024706823591, + }, + { + lng: -3.178604855160849, + lat: 55.98030447075077, + }, + { + lng: -3.1784987891436707, + lat: 55.98041053676794, + }, + { + lng: -3.178360207213794, + lat: 55.980467939282796, + }, + { + lng: -3.178254141196616, + lat: 55.98057400529997, + }, + { + lng: -3.1781155592667396, + lat: 55.980631407814826, + }, + { + lng: -3.1780094932495615, + lat: 55.980737473832, + }, + { + lng: -3.177870911319685, + lat: 55.980794876346856, + }, + { + lng: -3.177764845302507, + lat: 55.98090094236403, + }, + { + lng: -3.1776262633726304, + lat: 55.980958344878886, + }, + { + lng: -3.1775201973554523, + lat: 55.98106441089606, + }, + { + lng: -3.177381615425576, + lat: 55.981121813410915, + }, + { + lng: -3.17732611501824, + lat: 55.981186279333656, + }, + ], }, - ], + ], + }, + ], }; diff --git a/drone-frontend/src/stores.js b/drone-frontend/src/stores.js index 290fe0d..67d0a91 100644 --- a/drone-frontend/src/stores.js +++ b/drone-frontend/src/stores.js @@ -1,3 +1,3 @@ -import { writable } from 'svelte/store'; +import { writable } from "svelte/store"; -export const theme = writable('dark'); +export const theme = writable("dark"); diff --git a/drone-frontend/src/utils.js b/drone-frontend/src/utils.js index b41e412..c6352e4 100644 --- a/drone-frontend/src/utils.js +++ b/drone-frontend/src/utils.js @@ -1,108 +1,103 @@ import { fallbackBounds } from "./sampleData.js"; export function buildTimeline(response) { - const drones = []; - const allPoints = []; - let longest = 0; + const drones = []; + const allPoints = []; + let longest = 0; - if (!response || !response.dronePaths) { - return { drones, totalSteps: 0, bounds: fallbackBounds }; - } + if (!response || !response.dronePaths) { + return { drones, totalSteps: 0, bounds: fallbackBounds }; + } - for (const path of response.dronePaths) { - const coords = flattenDeliveries(path.deliveries); - if (!coords.length) continue; - drones.push({ id: path.droneId, path: coords }); - coords.forEach((p) => allPoints.push(p)); - longest = Math.max(longest, coords.length); - } + for (const path of response.dronePaths) { + const coords = flattenDeliveries(path.deliveries); + if (!coords.length) continue; + drones.push({ id: path.droneId, path: coords }); + coords.forEach((p) => allPoints.push(p)); + longest = Math.max(longest, coords.length); + } - // Add padding points for bounds calculation if empty - const basePoints = - allPoints.length > 0 - ? allPoints - : [ - { - lng: fallbackBounds.minLng, - lat: fallbackBounds.minLat, - }, - { - lng: fallbackBounds.maxLng, - lat: fallbackBounds.maxLat, - }, - ]; + // Add padding points for bounds calculation if empty + const basePoints = + allPoints.length > 0 + ? allPoints + : [ + { + lng: fallbackBounds.minLng, + lat: fallbackBounds.minLat, + }, + { + lng: fallbackBounds.maxLng, + lat: fallbackBounds.maxLat, + }, + ]; - return { - drones, - totalSteps: longest || 0, - bounds: computeBounds(basePoints), - }; + return { + drones, + totalSteps: longest || 0, + bounds: computeBounds(basePoints), + }; } function flattenDeliveries(deliveries) { - const coords = []; - for (const delivery of deliveries || []) { - for (const point of delivery.flightPath || []) { - if ( - !coords.length || - !samePoint(coords[coords.length - 1], point) - ) { - coords.push(point); - } - } + const coords = []; + for (const delivery of deliveries || []) { + for (const point of delivery.flightPath || []) { + if (!coords.length || !samePoint(coords[coords.length - 1], point)) { + coords.push(point); + } } - return coords; + } + return coords; } function samePoint(a, b) { - return Math.abs(a.lng - b.lng) < 1e-9 && Math.abs(a.lat - b.lat) < 1e-9; + return Math.abs(a.lng - b.lng) < 1e-9 && Math.abs(a.lat - b.lat) < 1e-9; } export function computeBounds(points) { - if (!points.length) return fallbackBounds; - let minLng = Infinity, - maxLng = -Infinity, - minLat = Infinity, - maxLat = -Infinity; - for (const p of points) { - minLng = Math.min(minLng, p.lng); - maxLng = Math.max(maxLng, p.lng); - minLat = Math.min(minLat, p.lat); - maxLat = Math.max(maxLat, p.lat); - } - const padding = 0.002; // Slightly more padding - return { - minLng: minLng - padding, - maxLng: maxLng + padding, - minLat: minLat - padding, - maxLat: maxLat + padding, - }; + if (!points.length) return fallbackBounds; + let minLng = Infinity, + maxLng = -Infinity, + minLat = Infinity, + maxLat = -Infinity; + for (const p of points) { + minLng = Math.min(minLng, p.lng); + maxLng = Math.max(maxLng, p.lng); + minLat = Math.min(minLat, p.lat); + maxLat = Math.max(maxLat, p.lat); + } + const padding = 0.002; // Slightly more padding + return { + minLng: minLng - padding, + maxLng: maxLng + padding, + minLat: minLat - padding, + maxLat: maxLat + padding, + }; } export function colorFor(idx, palette) { - if (!palette || palette.length === 0) return "#000"; - return palette[idx % palette.length]; + if (!palette || palette.length === 0) return "#000"; + return palette[idx % palette.length]; } export function formatDuration(sec) { - const m = Math.floor(sec / 60) - .toString() - .padStart(2, "0"); - const s = Math.floor(sec % 60) - .toString() - .padStart(2, "0"); - return `${m}:${s}`; + const m = Math.floor(sec / 60) + .toString() + .padStart(2, "0"); + const s = Math.floor(sec % 60) + .toString() + .padStart(2, "0"); + return `${m}:${s}`; } export function computeWallClock(start, seconds) { - const base = start ? new Date(start) : new Date(); - const ts = new Date(base.getTime() + seconds * 1000); - return isNaN(ts.getTime()) - ? new Date().toISOString() - : ts.toISOString(); + const base = start ? new Date(start) : new Date(); + const ts = new Date(base.getTime() + seconds * 1000); + return isNaN(ts.getTime()) ? new Date().toISOString() : ts.toISOString(); } export function boundsKey(bounds) { - if (!bounds) return ""; - return `${bounds.minLat}:${bounds.maxLat}:${bounds.minLng}:${bounds.maxLng}`; + if (!bounds) return ""; + return `${bounds.minLat}:${bounds.maxLat}:${bounds.minLng}:${bounds.maxLng}`; } diff --git a/flake.nix b/flake.nix index 4dc25de..596f994 100644 --- a/flake.nix +++ b/flake.nix @@ -38,6 +38,7 @@ bun svelte-language-server typescript-language-server + prettier ]; shellHook = '' export JAVA_HOME=${pkgs.jdk21} diff --git a/ilp-rest-service/ilp-cw-api/Front-end Test/Imperative.bru b/ilp-rest-service/ilp-cw-api/Front-end Test/Imperative.bru index 32a6e68..65082bf 100644 --- a/ilp-rest-service/ilp-cw-api/Front-end Test/Imperative.bru +++ b/ilp-rest-service/ilp-cw-api/Front-end Test/Imperative.bru @@ -25,6 +25,20 @@ body:json { "lng": -3.167074009381139, "lat": 55.94740195123114 } + }, + { + "id": 6, + "date": "2025-11-22", + "time": "09:35", + "requirements": { + "capacity": 0.85, + "heating": true, + "maxCost": 13.5 + }, + "delivery": { + "lng": -3.1891515471685636, + "lat": 55.95347060952466 + } } ] } diff --git a/ilp-rest-service/src/main/java/io/github/js0ny/ilp_coursework/controller/GeoJsonDataController.java b/ilp-rest-service/src/main/java/io/github/js0ny/ilp_coursework/controller/GeoJsonDataController.java deleted file mode 100644 index 0f750f2..0000000 --- a/ilp-rest-service/src/main/java/io/github/js0ny/ilp_coursework/controller/GeoJsonDataController.java +++ /dev/null @@ -1,25 +0,0 @@ -package io.github.js0ny.ilp_coursework.controller; - -import com.fasterxml.jackson.core.JsonProcessingException; - -import io.github.js0ny.ilp_coursework.service.DroneInfoService; - -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -@RestController -@RequestMapping("/api/v1") -public class GeoJsonDataController { - - private final DroneInfoService droneInfoService; - - public GeoJsonDataController(DroneInfoService droneInfoService) { - this.droneInfoService = droneInfoService; - } - - @GetMapping("/getAllRestrictedAreaByGeoJson") - public String getAllRestrictedAreaGeoJson() throws JsonProcessingException { - return droneInfoService.fetchRestrictedAreasInGeoJson().stream().reduce("", String::concat); - } -} diff --git a/ilp-rest-service/src/main/java/io/github/js0ny/ilp_coursework/controller/MapMetaController.java b/ilp-rest-service/src/main/java/io/github/js0ny/ilp_coursework/controller/MapMetaController.java new file mode 100644 index 0000000..d4c81b9 --- /dev/null +++ b/ilp-rest-service/src/main/java/io/github/js0ny/ilp_coursework/controller/MapMetaController.java @@ -0,0 +1,32 @@ +package io.github.js0ny.ilp_coursework.controller; + +import java.util.List; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import io.github.js0ny.ilp_coursework.data.external.RestrictedArea; +import io.github.js0ny.ilp_coursework.data.external.ServicePoint; +import io.github.js0ny.ilp_coursework.service.DroneInfoService; + +@RestController +@RequestMapping("/api/v1") +public class MapMetaController { + + private final DroneInfoService droneInfoService; + + public MapMetaController(DroneInfoService droneInfoService) { + this.droneInfoService = droneInfoService; + } + + @GetMapping("/restrictedAreas") + public List getRestrictedAreas() { + return droneInfoService.fetchRestrictedAreas(); + } + + @GetMapping("/servicePoints") + public List getServicePoints() { + return droneInfoService.fetchServicePoints(); + } +} diff --git a/ilp-rest-service/src/main/java/io/github/js0ny/ilp_coursework/service/DroneInfoService.java b/ilp-rest-service/src/main/java/io/github/js0ny/ilp_coursework/service/DroneInfoService.java index ca34ecc..35ed1e0 100644 --- a/ilp-rest-service/src/main/java/io/github/js0ny/ilp_coursework/service/DroneInfoService.java +++ b/ilp-rest-service/src/main/java/io/github/js0ny/ilp_coursework/service/DroneInfoService.java @@ -54,13 +54,15 @@ public class DroneInfoService { /** * Return an array of ids of drones with/without cooling capability * - *

Associated service method with {@code /dronesWithCooling/{state}} + *

+ * Associated service method with {@code /dronesWithCooling/{state}} * * @param state determines the capability filtering - * @return if {@code state} is true, return ids of drones with cooling capability, else without - * cooling + * @return if {@code state} is true, return ids of drones with cooling + * capability, else without + * cooling * @see - * io.github.js0ny.ilp_coursework.controller.DroneController#getDronesWithCoolingCapability(boolean) + * io.github.js0ny.ilp_coursework.controller.DroneController#getDronesWithCoolingCapability(boolean) */ public List dronesWithCooling(boolean state) { // URI droneUrl = URI.create(baseUrl).resolve(dronesEndpoint); @@ -80,13 +82,16 @@ public class DroneInfoService { /** * Return a {@link Drone}-style json data structure with the given {@code id} * - *

Associated service method with {@code /droneDetails/{id}} + *

+ * Associated service method with {@code /droneDetails/{id}} * * @param id The id of the drone * @return drone json body of given id - * @throws NullPointerException when cannot fetch available drones from remote - * @throws IllegalArgumentException when drone with given {@code id} cannot be found this should - * lead to a 404 + * @throws NullPointerException when cannot fetch available drones from + * remote + * @throws IllegalArgumentException when drone with given {@code id} cannot be + * found this should + * lead to a 404 * @see io.github.js0ny.ilp_coursework.controller.DroneController#getDroneDetail(String) */ public Drone droneDetail(String id) { @@ -103,10 +108,12 @@ public class DroneInfoService { } /** - * Return an array of ids of drones that match all the requirements in the medical dispatch + * Return an array of ids of drones that match all the requirements in the + * medical dispatch * records * - *

Associated service method with + *

+ * Associated service method with * * @param rec array of medical dispatch records * @return List of drone ids that match all the requirements @@ -128,10 +135,9 @@ public class DroneInfoService { return drones.stream() .filter(d -> d != null && d.capability() != null) .filter( - d -> - Arrays.stream(rec) - .filter(r -> r != null && r.requirements() != null) - .allMatch(r -> droneMatchesRequirement(d, r))) + d -> Arrays.stream(rec) + .filter(r -> r != null && r.requirements() != null) + .allMatch(r -> droneMatchesRequirement(d, r))) .map(Drone::id) .collect(Collectors.toList()); } @@ -139,11 +145,13 @@ public class DroneInfoService { /** * Helper to check if a drone meets the requirement of a medical dispatch. * - * @param drone the drone to be checked + * @param drone the drone to be checked * @param record the medical dispatch record containing the requirement * @return true if the drone meets the requirement, false otherwise - * @throws IllegalArgumentException when record requirements or drone capability is invalid - * (capacity and id cannot be null in {@code MedDispathRecDto}) + * @throws IllegalArgumentException when record requirements or drone capability + * is invalid + * (capacity and id cannot be null in + * {@code MedDispathRecDto}) */ public boolean droneMatchesRequirement(Drone drone, MedDispatchRecRequest record) { var requirements = record.requirements(); @@ -183,13 +191,13 @@ public class DroneInfoService { * Helper to check if a drone is available at the required date and time * * @param droneId the id of the drone to be checked - * @param record the medical dispatch record containing the required date and time + * @param record the medical dispatch record containing the required date and + * time * @return true if the drone is available, false otherwise */ private boolean checkAvailability(String droneId, MedDispatchRecRequest record) { URI droneUrl = URI.create(baseUrl).resolve(dronesForServicePointsEndpoint); - ServicePointDrones[] servicePoints = - restTemplate.getForObject(droneUrl, ServicePointDrones[].class); + ServicePointDrones[] servicePoints = restTemplate.getForObject(droneUrl, ServicePointDrones[].class); LocalDate requiredDate = record.date(); DayOfWeek requiredDay = requiredDate.getDayOfWeek(); @@ -208,8 +216,7 @@ public class DroneInfoService { private LngLat queryServicePointLocationByDroneId(String droneId) { URI droneUrl = URI.create(baseUrl).resolve(dronesForServicePointsEndpoint); - ServicePointDrones[] servicePoints = - restTemplate.getForObject(droneUrl, ServicePointDrones[].class); + ServicePointDrones[] servicePoints = restTemplate.getForObject(droneUrl, ServicePointDrones[].class); assert servicePoints != null; for (var sp : servicePoints) { @@ -226,8 +233,7 @@ public class DroneInfoService { private LngLat queryServicePointLocation(int id) { URI servicePointUrl = URI.create(baseUrl).resolve(servicePointsEndpoint); - ServicePoint[] servicePoints = - restTemplate.getForObject(servicePointUrl, ServicePoint[].class); + ServicePoint[] servicePoints = restTemplate.getForObject(servicePointUrl, ServicePoint[].class); assert servicePoints != null; for (var sp : servicePoints) { @@ -250,31 +256,22 @@ public class DroneInfoService { public List fetchRestrictedAreas() { URI restrictedUrl = URI.create(baseUrl).resolve(restrictedAreasEndpoint); - RestrictedArea[] restrictedAreas = - restTemplate.getForObject(restrictedUrl, RestrictedArea[].class); + RestrictedArea[] restrictedAreas = restTemplate.getForObject(restrictedUrl, RestrictedArea[].class); assert restrictedAreas != null; return Arrays.asList(restrictedAreas); } - public List fetchRestrictedAreasInGeoJson() throws JsonProcessingException { - var mapper = new ObjectMapper(); - var ras = fetchRestrictedAreas(); - var geoJson = ras.stream().map(RestrictedArea::toRegion).map(Region::toGeoJson).toList(); - return Collections.singletonList(mapper.writeValueAsString(geoJson)); - } - public List fetchServicePoints() { URI servicePointUrl = URI.create(baseUrl).resolve(servicePointsEndpoint); - ServicePoint[] servicePoints = - restTemplate.getForObject(servicePointUrl, ServicePoint[].class); + ServicePoint[] servicePoints = restTemplate.getForObject(servicePointUrl, ServicePoint[].class); assert servicePoints != null; return Arrays.asList(servicePoints); } public List fetchDronesForServicePoints() { URI servicePointDronesUrl = URI.create(baseUrl).resolve(dronesForServicePointsEndpoint); - ServicePointDrones[] servicePointDrones = - restTemplate.getForObject(servicePointDronesUrl, ServicePointDrones[].class); + ServicePointDrones[] servicePointDrones = restTemplate.getForObject(servicePointDronesUrl, + ServicePointDrones[].class); assert servicePointDrones != null; return Arrays.asList(servicePointDrones); }