diff --git a/src/main/lemondronor/advisorycircular.cljs b/src/main/lemondronor/advisorycircular.cljs index 464a839..00c253b 100644 --- a/src/main/lemondronor/advisorycircular.cljs +++ b/src/main/lemondronor/advisorycircular.cljs @@ -267,21 +267,46 @@ v))) +(defn nearby-airports + ([config lat lon] + (nearby-airports config lat lon {})) + ([config lat lon options] + (p/let [radius (or (:radius options) 7) + results (pelias/nearby (:pelias config) + lat lon + {:categories "transport:air:aerodrome" + :boundary.circle.radius radius}) + blocklist (get-in config [:airport :blocklist] []) + blocklist-patterns (map #(re-pattern (str "(?i)" %)) blocklist)] + (->> (:features results) + (remove (fn [airport] (some #(re-find % (get-in airport [:properties :label])) + blocklist-patterns))))))) + + (defn closest-airport [config lat lon] - (p/let [results (pelias/nearby (:pelias config) - lat lon - {:categories "transport:air:aerodrome" - :boundary.circle.radius 7}) - blocklist (get-in config [:airport :blocklist] []) - blocklist-patterns (map #(re-pattern (str "(?i)" %)) blocklist) - _ (println blocklist-patterns)] - (->> (:features results) - (remove (fn [airport] (some #(re-find % (get-in airport [:properties :label])) - blocklist-patterns))) + (p/let [airports (nearby-airports config lat lon)] + (->> airports (sort-by #(get-in % [:properties :distance])) first))) +(defn airport-geojson [config] + (p/let [airport->feature (fn [a] + (let [props (:properties a)] + {:type "Feature" + :properties {:shape "Circle" + :radius (* 1000 (:minimum-airport-distance-km config)) + :name (:label props)} + :geometry {:type "Point" + :coordinates (-> a :geometry :coordinates)}})) + lat (:lat config) + lon (:lon config) + airports (nearby-airports config lat lon {:radius (+ (:radius-km config) + (:minimum-airport-distance-km config))})] + {:type "FeatureCollection" + :features (map airport->feature airports)})) + + (defn log-table [table keys] (let [s (with-out-str (pprint/print-table keys table)) lines (string/split-lines s)] @@ -638,12 +663,11 @@ (.option "--secrets " "Path to the secrets yaml file" "secrets.yaml") (.option "--history " "Path to history/state file" "advisorycircular.json") (.option "--log-prefix " "Log prefix to use") + (.option "--airport-geojson" "Generate airport GEOJSON and exit") (.parse (.-argv js/process))) (logging/set-log-prefix! (or (.-logPrefix commander) "")) (reset! log-prefix (or (.-logPrefix commander) "")) - (let [start-time (current-time)] - ;; If --config-path is specified, definitely try to read that - ;; file. Otherwise, only read config.yaml if it exists. + (if (.-airportGeojson commander) (p/try (p/let [base-config (if-let [config-path (.-config commander)] (util/read-config config-path) @@ -651,45 +675,63 @@ (util/read-config default-config-path) {})) cli-config (build-config-from-commander commander) - secrets (util/read-config (.-secrets commander)) - config (build-config base-config cli-config secrets) - _ (validate-config config) - history-db-path (:history-db-path config) - _ (when (not (fs/existsSync history-db-path)) - (log-info "%s does not exist; creating empty one." history-db-path) - (write-history-db {} history-db-path)) - db (read-history-db history-db-path) - data (get-adsbexchange-live-data - (merge (:adsbx config) - {:lat (:lat config) - :lon (:lon config) - :radius-nm (* (:radius-km config) 0.539957)})) - now (current-time) - [new-db potential-circles] (-> db - (update-history-db (:aircraft data) now config) - (detect-circles now config))] - (p/do - (when potential-circles - (doseq [ac potential-circles] - (log-warn "%s: New circle detected: %s" (:icao ac) (ac-desc ac))) - (process-potential-circles potential-circles config now)) - (write-history-db new-db (:history-db-path config)) - (let [end-time (current-time)] - (log-info - "Finished in %f s: %s aircraft; %s circles; top curvinesses: %s" - (/ (- end-time start-time) 1000) - (count new-db) - (count potential-circles) - (->> (vals new-db) - (sort-by :curviness) - reverse - (take 3) - (map #(str (:icao %) ":" (.toFixed (:curviness %) 0))) - (string/join " ")))))) + config (build-config base-config cli-config {}) + geojson (airport-geojson config)] + (println (.stringify js/JSON (clj->js geojson) nil " "))) (p/catch :default e (log-error "%s" e) (log-error "%s" (.-stack e)) - (.exit js/process 1))))) + (.exit js/process 1))) + (let [start-time (current-time)] + ;; If --config-path is specified, definitely try to read that + ;; file. Otherwise, only read config.yaml if it exists. + (p/try + (println "OMG DOING THIS") + (p/let [base-config (if-let [config-path (.-config commander)] + (util/read-config config-path) + (if (fs/existsSync default-config-path) + (util/read-config default-config-path) + {})) + cli-config (build-config-from-commander commander) + secrets (util/read-config (.-secrets commander)) + config (build-config base-config cli-config secrets) + _ (validate-config config) + history-db-path (:history-db-path config) + _ (when (not (fs/existsSync history-db-path)) + (log-info "%s does not exist; creating empty one." history-db-path) + (write-history-db {} history-db-path)) + db (read-history-db history-db-path) + data (get-adsbexchange-live-data + (merge (:adsbx config) + {:lat (:lat config) + :lon (:lon config) + :radius-nm (* (:radius-km config) 0.539957)})) + now (current-time) + [new-db potential-circles] (-> db + (update-history-db (:aircraft data) now config) + (detect-circles now config))] + (p/do + (when potential-circles + (doseq [ac potential-circles] + (log-warn "%s: New circle detected: %s" (:icao ac) (ac-desc ac))) + (process-potential-circles potential-circles config now)) + (write-history-db new-db (:history-db-path config)) + (let [end-time (current-time)] + (log-info + "Finished in %f s: %s aircraft; %s circles; top curvinesses: %s" + (/ (- end-time start-time) 1000) + (count new-db) + (count potential-circles) + (->> (vals new-db) + (sort-by :curviness) + reverse + (take 3) + (map #(str (:icao %) ":" (.toFixed (:curviness %) 0))) + (string/join " ")))))) + (p/catch :default e + (log-error "%s" e) + (log-error "%s" (.-stack e)) + (.exit js/process 1)))))) ;; (.on js/process "unhandledRejection"