From 82a78da81b22862fe73e701425e7c6a4eb1b4e40 Mon Sep 17 00:00:00 2001 From: js0ny Date: Sat, 6 Dec 2025 09:48:30 +0000 Subject: [PATCH] feat: containerize --- compose.yaml | 8 - compose.yml | 28 ++++ drone-black-box/Dockerfile | 14 ++ drone-black-box/go.mod | 25 +++- drone-black-box/go.sum | 75 +++++++++- drone-black-box/main.go | 4 +- drone-black-box/main_test.go | 140 ++++++++++++++++++ drone-frontend/Dockerfile | 11 ++ drone-frontend/src/App.svelte | 55 +++---- .../ilp-cw-api/Front-end Test/Imperative.bru | 14 -- 10 files changed, 319 insertions(+), 55 deletions(-) delete mode 100644 compose.yaml create mode 100644 compose.yml create mode 100644 drone-black-box/Dockerfile create mode 100644 drone-black-box/main_test.go create mode 100644 drone-frontend/Dockerfile diff --git a/compose.yaml b/compose.yaml deleted file mode 100644 index 45ad745..0000000 --- a/compose.yaml +++ /dev/null @@ -1,8 +0,0 @@ -# compose.yaml -services: - app: - build: . - image: ilp-coursework:0.2 - container_name: ilp-coursework-app - ports: - - "8080:8080" diff --git a/compose.yml b/compose.yml new file mode 100644 index 0000000..1b03d77 --- /dev/null +++ b/compose.yml @@ -0,0 +1,28 @@ +version: "3.9" + +services: + rest: + build: + context: ./ilp-rest-service + dockerfile: Dockerfile + ports: + - "8080:8080" + + blackbox: + build: + context: ./drone-black-box + dockerfile: Dockerfile + ports: + - "3000:3000" + depends_on: + - rest + + frontend: + build: + context: ./drone-frontend + dockerfile: Dockerfile + ports: + - "4173:4173" + depends_on: + - rest + - blackbox diff --git a/drone-black-box/Dockerfile b/drone-black-box/Dockerfile new file mode 100644 index 0000000..ffb4c7a --- /dev/null +++ b/drone-black-box/Dockerfile @@ -0,0 +1,14 @@ +# Build stage +FROM golang:1.22-bullseye AS builder +WORKDIR /app +COPY go.mod ./ +RUN go mod download +COPY . . +RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o blackbox + +# Run stage +FROM gcr.io/distroless/base-debian12 +WORKDIR /app +COPY --from=builder /app/blackbox /app/blackbox +EXPOSE 3000 +ENTRYPOINT ["/app/blackbox"] diff --git a/drone-black-box/go.mod b/drone-black-box/go.mod index 92a5046..3039410 100644 --- a/drone-black-box/go.mod +++ b/drone-black-box/go.mod @@ -1,5 +1,26 @@ module drone-black-box -go 1.25.3 +go 1.22.0 -require github.com/mattn/go-sqlite3 v1.14.32 +require modernc.org/sqlite v1.27.0 + +require ( + github.com/dustin/go-humanize v1.0.1 // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect + github.com/mattn/go-isatty v0.0.16 // indirect + github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect + golang.org/x/mod v0.3.0 // indirect + golang.org/x/sys v0.9.0 // indirect + golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78 // indirect + golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect + lukechampine.com/uint128 v1.2.0 // indirect + modernc.org/cc/v3 v3.40.0 // indirect + modernc.org/ccgo/v3 v3.16.13 // indirect + modernc.org/libc v1.29.0 // indirect + modernc.org/mathutil v1.6.0 // indirect + modernc.org/memory v1.7.2 // indirect + modernc.org/opt v0.1.3 // indirect + modernc.org/strutil v1.1.3 // indirect + modernc.org/token v1.0.1 // indirect +) diff --git a/drone-black-box/go.sum b/drone-black-box/go.sum index 66f7516..96e23b9 100644 --- a/drone-black-box/go.sum +++ b/drone-black-box/go.sum @@ -1,2 +1,73 @@ -github.com/mattn/go-sqlite3 v1.14.32 h1:JD12Ag3oLy1zQA+BNn74xRgaBbdhbNIDYvQUEuuErjs= -github.com/mattn/go-sqlite3 v1.14.32/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ= +github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= +github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= +github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s= +golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78 h1:M8tBwCtWD/cZV9DZpFYRUgaymAYAr+aIUTWzDaM3uPs= +golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI= +lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= +modernc.org/cc/v3 v3.40.0 h1:P3g79IUS/93SYhtoeaHW+kRCIrYaxJ27MFPv+7kaTOw= +modernc.org/cc/v3 v3.40.0/go.mod h1:/bTg4dnWkSXowUO6ssQKnOV0yMVxDYNIsIrzqTFDGH0= +modernc.org/ccgo/v3 v3.16.13 h1:Mkgdzl46i5F/CNR/Kj80Ri59hC8TKAhZrYSaqvkwzUw= +modernc.org/ccgo/v3 v3.16.13/go.mod h1:2Quk+5YgpImhPjv2Qsob1DnZ/4som1lJTodubIcoUkY= +modernc.org/ccorpus v1.11.6 h1:J16RXiiqiCgua6+ZvQot4yUuUy8zxgqbqEEUuGPlISk= +modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ= +modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM= +modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM= +modernc.org/libc v1.29.0 h1:tTFRFq69YKCF2QyGNuRUQxKBm1uZZLubf6Cjh/pVHXs= +modernc.org/libc v1.29.0/go.mod h1:DaG/4Q3LRRdqpiLyP0C2m1B8ZMGkQ+cCgOIjEtQlYhQ= +modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4= +modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo= +modernc.org/memory v1.7.2 h1:Klh90S215mmH8c9gO98QxQFsY+W451E8AnzjoE2ee1E= +modernc.org/memory v1.7.2/go.mod h1:NO4NVCQy0N7ln+T9ngWqOQfi7ley4vpwvARR+Hjw95E= +modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4= +modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= +modernc.org/sqlite v1.27.0 h1:MpKAHoyYB7xqcwnUwkuD+npwEa0fojF0B5QRbN+auJ8= +modernc.org/sqlite v1.27.0/go.mod h1:Qxpazz0zH8Z1xCFyi5GSL3FzbtZ3fvbjmywNogldEW0= +modernc.org/strutil v1.1.3 h1:fNMm+oJklMGYfU9Ylcywl0CO5O6nTfaowNsh2wpPjzY= +modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw= +modernc.org/tcl v1.15.2 h1:C4ybAYCGJw968e+Me18oW55kD/FexcHbqH2xak1ROSY= +modernc.org/tcl v1.15.2/go.mod h1:3+k/ZaEbKrC8ePv8zJWPtBSW0V7Gg9g8rkmhI1Kfs3c= +modernc.org/token v1.0.1 h1:A3qvTqOwexpfZZeyI0FeGPDlSWX5pjZu9hF4lU+EKWg= +modernc.org/token v1.0.1/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= +modernc.org/z v1.7.3 h1:zDJf6iHjrnB+WRD88stbXokugjyc0/pB91ri1gO6LZY= +modernc.org/z v1.7.3/go.mod h1:Ipv4tsdxZRbQyLq9Q1M6gdbkxYzdlrciF2Hi/lS7nWE= diff --git a/drone-black-box/main.go b/drone-black-box/main.go index 70d5898..00cd28c 100644 --- a/drone-black-box/main.go +++ b/drone-black-box/main.go @@ -11,7 +11,7 @@ import ( "syscall" "time" - _ "github.com/mattn/go-sqlite3" + _ "modernc.org/sqlite" ) // DroneEvent defines the DroneEvent struct as JSON @@ -114,7 +114,7 @@ func main() { } // Open database - db, err := sql.Open("sqlite3", "./drone_black_box.db") + db, err := sql.Open("sqlite", "./drone_black_box.db") if err != nil { slog.Error("Failed to open database", "error", err) os.Exit(1) diff --git a/drone-black-box/main_test.go b/drone-black-box/main_test.go new file mode 100644 index 0000000..6fc24b0 --- /dev/null +++ b/drone-black-box/main_test.go @@ -0,0 +1,140 @@ +package main + +import ( + "bytes" + "context" + "database/sql" + "encoding/json" + "net/http" + "net/http/httptest" + "net/url" + "strings" + "testing" + "time" + + _ "modernc.org/sqlite" +) + +// create an in-memory DB with schema/index identical to main +func newTestDB(t *testing.T) *sql.DB { + t.Helper() + db, err := sql.Open("sqlite", "file:testdb?mode=memory&cache=shared") + if err != nil { + t.Fatalf("open db: %v", err) + } + schema := `CREATE TABLE IF NOT EXISTS drone_events ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + drone_id TEXT NOT NULL, + latitude REAL NOT NULL, + longitude REAL NOT NULL, + timestamp TEXT NOT NULL + );` + if _, err := db.Exec(schema); err != nil { + t.Fatalf("schema: %v", err) + } + if _, err := db.Exec(`CREATE INDEX IF NOT EXISTS idx_drone_timestamp ON drone_events(drone_id, timestamp);`); err != nil { + t.Fatalf("index: %v", err) + } + return db +} + +func TestIngestAndSnapshot(t *testing.T) { + db := newTestDB(t) + srv := &Server{db: db} + + // ingest two drones with multiple timestamps + events := []DroneEvent{ + {"d1", 1.0, 2.0, "2025-12-06T00:00:00Z"}, + {"d1", 1.1, 2.1, "2025-12-06T00:00:10Z"}, + {"d2", 3.0, 4.0, "2025-12-06T00:00:05Z"}, + } + for _, ev := range events { + body, _ := json.Marshal(ev) + req := httptest.NewRequest(http.MethodPost, "/ingest", bytes.NewReader(body)) + rec := httptest.NewRecorder() + srv.ingestHandler(rec, req) + if rec.Code != http.StatusCreated { + t.Fatalf("ingest %v code=%d body=%s", ev, rec.Code, rec.Body.String()) + } + } + + // snapshot at 00:00:07 should pick d1@00:00:00? no 00:00:10 too new -> d1@0, d2@5 + q := url.Values{} + q.Set("time", "2025-12-06T00:00:07Z") + req := httptest.NewRequest(http.MethodGet, "/snapshot?"+q.Encode(), nil) + rec := httptest.NewRecorder() + srv.snapshotHandler(rec, req) + if rec.Code != http.StatusOK { + t.Fatalf("snapshot code=%d body=%s", rec.Code, rec.Body.String()) + } + + var resp []DroneEvent + if err := json.Unmarshal(rec.Body.Bytes(), &resp); err != nil { + t.Fatalf("decode snapshot: %v", err) + } + if len(resp) != 2 { + t.Fatalf("expected 2 events, got %d", len(resp)) + } + // map by drone + got := map[string]DroneEvent{} + for _, e := range resp { + got[e.DroneID] = e + } + if got["d1"].Timestamp != "2025-12-06T00:00:00Z" { + t.Fatalf("d1 timestamp mismatch: %v", got["d1"]) + } + if got["d2"].Timestamp != "2025-12-06T00:00:05Z" { + t.Fatalf("d2 timestamp mismatch: %v", got["d2"]) + } +} + +func TestSnapshotMissingTime(t *testing.T) { + db := newTestDB(t) + srv := &Server{db: db} + + req := httptest.NewRequest(http.MethodGet, "/snapshot", nil) + rec := httptest.NewRecorder() + srv.snapshotHandler(rec, req) + if rec.Code != http.StatusBadRequest { + t.Fatalf("expected 400, got %d", rec.Code) + } +} + +func TestHealth(t *testing.T) { + db := newTestDB(t) + srv := &Server{db: db} + req := httptest.NewRequest(http.MethodGet, "/health", nil) + rec := httptest.NewRecorder() + srv.healthHandler(rec, req) + if rec.Code != http.StatusOK { + t.Fatalf("health code=%d body=%s", rec.Code, rec.Body.String()) + } +} + +func TestIngestBadJSON(t *testing.T) { + db := newTestDB(t) + srv := &Server{db: db} + req := httptest.NewRequest(http.MethodPost, "/ingest", strings.NewReader("{bad")) + rec := httptest.NewRecorder() + srv.ingestHandler(rec, req) + if rec.Code != http.StatusBadRequest { + t.Fatalf("expected 400, got %d", rec.Code) + } +} + +// Ensure graceful shutdown path does not hang: start a server and shut it down quickly. +func TestGracefulShutdown(t *testing.T) { + db := newTestDB(t) + srv := &Server{db: db} + mux := http.NewServeMux() + mux.HandleFunc("GET /health", srv.healthHandler) + testSrv := &http.Server{Addr: "127.0.0.1:0", Handler: mux} + + go func() { _ = testSrv.ListenAndServe() }() + + ctx, cancel := context.WithTimeout(context.Background(), time.Second) + defer cancel() + if err := testSrv.Shutdown(ctx); err != nil { + t.Fatalf("shutdown: %v", err) + } +} diff --git a/drone-frontend/Dockerfile b/drone-frontend/Dockerfile new file mode 100644 index 0000000..5657851 --- /dev/null +++ b/drone-frontend/Dockerfile @@ -0,0 +1,11 @@ +# Build stage +FROM oven/bun:1.3-debian as builder +WORKDIR /app +COPY bun.lock package.json . +RUN bun install --frozen-lockfile +COPY . . +RUN bun run build + +# Serve built assets via Vite preview +EXPOSE 4173 +CMD ["bun", "run", "preview", "--", "--host", "0.0.0.0", "--port", "4173"] diff --git a/drone-frontend/src/App.svelte b/drone-frontend/src/App.svelte index 10be888..187727f 100644 --- a/drone-frontend/src/App.svelte +++ b/drone-frontend/src/App.svelte @@ -3,7 +3,6 @@ import L from "leaflet"; import { theme } from "./stores.js"; import { - STEP_SECONDS, defaultDispatch, samplePathResponse, fallbackBounds, @@ -20,6 +19,8 @@ let palette = []; let lightTiles, darkTiles; + let STEP_SECONDS = 1; + function updatePalette() { if (typeof document === "undefined") return; const style = getComputedStyle(document.documentElement); @@ -197,7 +198,7 @@ fitMapToBounds(); refreshMap(); loadRestrictedAreas(); - loadServicePoints(); + // loadServicePoints(); return () => map?.remove(); }); @@ -346,31 +347,31 @@ currentPositions.forEach((drone, idx) => { const color = colorFor(idx, palette); - // Draw Full Trajectory (Dimmed) - if (drone.path.length > 1) { - L.polyline( - drone.path.map((p) => [p.lat, p.lng]), - { - color: color, - weight: 2, - opacity: 0.2, - dashArray: "4, 8", // Dashed line for future path - }, - ).addTo(pathLayer); - } - - // Draw Visited Trajectory (Bright) - if (drone.visited.length > 1) { - L.polyline( - drone.visited.map((p) => [p.lat, p.lng]), - { - color: color, - weight: 3, - opacity: 0.9, - className: "neon-path", // Can add glow via CSS if desired - }, - ).addTo(pathLayer); - } + // // Draw Full Trajectory (Dimmed) + // if (drone.path.length > 1) { + // L.polyline( + // drone.path.map((p) => [p.lat, p.lng]), + // { + // color: color, + // weight: 2, + // opacity: 0.2, + // dashArray: "4, 8", // Dashed line for future path + // }, + // ).addTo(pathLayer); + // } + // + // // Draw Visited Trajectory (Bright) + // if (drone.visited.length > 1) { + // L.polyline( + // drone.visited.map((p) => [p.lat, p.lng]), + // { + // color: color, + // weight: 3, + // opacity: 0.9, + // className: "neon-path", // Can add glow via CSS if desired + // }, + // ).addTo(pathLayer); + // } // Draw Drone Marker if (drone.current) { 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 65082bf..32a6e68 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,20 +25,6 @@ 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 - } } ] }