;;; see next comments on how to start this ;; boat service: (use srfi-18 medea comparse) ;; workaround for blocking on i/o when reading json from stdin (include "nonblocking-input-ports.scm") (current-input-port (open-input-file*/nonblock 0)) ;; ==================== globals (define state '()) (define (limit lst num) (take lst (min (length lst) num))) ;; ==================== boat utils (define (geojson-mmsi geojson) (alist-ref 'mmsi (or (alist-ref 'properties geojson) '()))) ;; (pp (extract (include "./boat.data.scm"))) ;; input: alist ((pos . (lat . lon)) (mmsi . mmsi)) ;; state is a map of : (define (prj-geojson geojson state) ;; set properties for mmsi key: (alist-update (geojson-mmsi geojson) ;; key (mmsi) geojson ;; value (geojson feature) state)) ;; (rect-inside? 0 0 1 -1 -1 1) (define (rect-inside? x y top left bottom right) (and (>= x left) (<= x right) (>= y bottom) (<= y top))) ;; (length (filter (lambda (pair) (geojson-inside? (cdr pair) 61 5 60 6)) _state)) (define (geojson-inside? geojson top left bottom right) (and-let* ((gm (alist-ref 'geometry geojson)) (pos (alist-ref 'coordinates gm)) (lon (vector-ref pos 0)) (lat (vector-ref pos 1))) (and lon lat (rect-inside? lon lat top left bottom right)))) ;; query boats based on region (bounding box). typical json is "[60, ;; 5, 61, 5.5]" (define (bb-query state bbox) ;; bad naming here, sorry. need a rect abstraction (define (corner x) (vector-ref bbox x)) (define result (filter (lambda (pair) (geojson-inside? (cdr pair) (corner 0) (corner 1) (corner 2) (corner 3))) state)) (print "found " (length result) "/" (length state) " boats") (json->string `((type . "FeatureCollection") (features . ,(list->vector (limit (map cdr result) 100)))))) (define (query-handler json) (print "boats: got query " json) (bb-query state json)) ;; uri to bounding-box query. ie: ;; (uri-bbq (uri-reference "?bb=1/2/3/4")) ;; (uri-bbq (uri-reference "?nothing=false")) (define (get-bbq bb) (list->vector (map string->number (string-split bb "/")))) (define (top-handler) (query-handler (get-bbq "67.1016555307692/-28.256835937499996/53.61857936489517/46.669921875"))) (define server-thread (thread-start! (lambda () (let lp () (thread-sleep! 0.01) (print "boats!" (top-handler)) (lp))))) (define count 0) (let loop ((input (current-input-port))) (receive (json rest) (read-json input) (set! count (add1 count)) (set! state (prj-geojson json state)) (if (not (parser-input-end? rest)) (loop rest))))