Last active
July 2, 2022 14:21
-
-
Save athanhat/2ccfad3786934ad41efc7c74674494b5 to your computer and use it in GitHub Desktop.
Alternative Pathom3 Tutorial using GeoJS and AccuWeather APIs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[:name "GeoJS and AccuWeather EQL API with Pathom3" | |
:description "Alternative Pathom3 Tutorial using GeoJS and AccuWeather APIs" | |
:version "0.1" | |
:author "Athanassios I. Hatzis" | |
:copyright "(C) Athanassios I. Hatzis 2022-07-02" | |
:license "Eclipse Public License 2.0" | |
:url "http://healis.eu"] | |
(ns weather-tutorial2 | |
(:require | |
[cheshire.core :as json] | |
[com.wsscode.pathom3.connect.operation :as pco] | |
[com.wsscode.pathom3.interface.smart-map :as psm] | |
[com.wsscode.pathom.viz.ws-connector.core :as pvc] | |
[com.wsscode.pathom3.interface.eql :as p.eql] | |
[com.wsscode.pathom.viz.ws-connector.pathom3 :as p.connector] | |
[com.wsscode.pathom3.connect.indexes :as pci] | |
[clojure.edn :as edn] | |
)) | |
;; ================================================================================================= | |
;; def Section | |
;; ================================================================================================= | |
(def min-hot 32) | |
(def max-cold 15) | |
(def google-ip "142.250.184.142") | |
(def geojs_ip "https://get.geojs.io/v1/ip.json") | |
(def geojs_coords "https://get.geojs.io/v1/ip/geo/") | |
(def accu_url_location_key "http://dataservice.accuweather.com/locations/v1/cities/geoposition/search") | |
(def accu_url_current_weather "http://dataservice.accuweather.com/currentconditions/v1/") | |
(def accu_api_key "PUT YOUR AccuWeather ApiKey HERE") | |
(def geojs_keys [:country | |
:region | |
:city | |
:latitude | |
:longitude | |
:organization_name | |
:timezone | |
:country_code | |
:continent_code]) | |
(def accu_keys [:weather-text | |
:time-local | |
:time-epoch | |
:day? | |
:temperature-val | |
:temperature-unit]) | |
;; =============================================================================================== | |
;; Resolvers Section | |
;; =============================================================================================== | |
(defn add-geojs-ns | |
"Add :geojs to a GeoJS key | |
e.g. :country --> :geojs/country" | |
[key] | |
;; ........................... body ....................................... | |
(keyword "geojs" (name key))) | |
(defn add-accu-ns | |
"Add :geojs to a GeoJS key | |
e.g. :temperature-unit --> :accu/temperature-unit | |
" | |
[key] | |
;; ........................... body ....................................... | |
(keyword "accu" (name key))) | |
(pco/defresolver get-ip | |
"It resolves to an IP of the machine we are invoking this code | |
Arguments: No input | |
Return: {:ip <String>} | |
" | |
[] | |
;; ........................... body ....................................... | |
{::pco/output [:ip]} | |
(json/parse-string (slurp geojs_ip) keyword)) | |
(pco/defresolver ip->geocoords | |
"It receives an IP and resolves to GeoJS info | |
Arguments: {:ip <String>} | |
Return: GeoJS map with the selected keys (see `geojs_keys`) | |
#:geojs{...} | |
" | |
[{:keys [ip]}] | |
;; ........................... body ....................................... | |
{::pco/output (mapv add-geojs-ns geojs_keys)} | |
(let [url (str geojs_coords ip ".json") | |
response-map (json/parse-string (slurp url) keyword)] | |
(update-keys | |
(select-keys response-map geojs_keys) add-geojs-ns) | |
)) | |
(pco/defresolver geocoords->locationkey | |
"It takes GeoJS latitude and longitude and resolves to AccuWeather location | |
Arguments: | |
{:geojs/latitude <Double> | |
:geojs/longitude <Double>} | |
Return: {:accu/location-id <Long>} | |
" | |
[{:geojs/keys [latitude longitude]}] | |
;; ........................... body ....................................... | |
{:accu/location-id (-> (slurp | |
(str accu_url_location_key "?q=" latitude "," longitude "&apikey=" accu_api_key)) | |
(json/parse-string keyword) | |
(:Key) | |
(edn/read-string)) | |
}) | |
(pco/defresolver locationkey->currentweather | |
"It takes an AccuWeather location key and resolves to AccuWeather current conditions | |
Arguments: | |
{:accu/location-id <Long>} | |
Return: AccuWeather map with the selected keys (see `accu_keys`) | |
#:accu{...} | |
" | |
[{:accu/keys [location-id]}] | |
;; ........................... body ....................................... | |
{::pco/output (mapv add-accu-ns accu_keys)} | |
(let [url (str accu_url_current_weather location-id "?apikey=" accu_api_key) | |
response-map (first (json/parse-string (slurp url) keyword)) | |
{weather-text :WeatherText | |
time-local :LocalObservationDateTime | |
time-epoch :EpochTime | |
day? :IsDayTime} response-map | |
temp-metric-val (get-in response-map [:Temperature :Metric :Value]) | |
temp-metric-unit (get-in response-map [:Temperature :Metric :Unit]) | |
] | |
(zipmap (mapv add-accu-ns accu_keys) [ weather-text | |
time-local | |
time-epoch | |
day? | |
temp-metric-val | |
temp-metric-unit]) | |
)) | |
;; | |
(pco/defresolver is-it-cold? | |
"It receives an AccuWeather temperature and resolves to whether it is cold or not | |
Arguments: {:accu/temperature <Double>} | |
Return: {:accu/cold? <Boolean>} | |
" | |
[{:accu/keys [temperature-val]}] | |
;; ........................... body ....................................... | |
{:accu/cold? (< temperature-val max-cold)}) | |
;; check AccuWeather temperature to determine if it is hot | |
(pco/defresolver is-it-hot? | |
"It receives an AccuWeather temperature and resolves to whether it is hot or not | |
Arguments: {:accu/temperature <Double>} | |
Return: {:accu/hot? <Boolean>} | |
" | |
[{:accu/keys [temperature-val]}] | |
;; ........................... body ....................................... | |
{:accu/hot? (> temperature-val min-hot)}) | |
;; Register resolvers | |
(def indexes | |
(pci/register [ get-ip | |
ip->geocoords | |
geocoords->locationkey | |
locationkey->currentweather | |
is-it-cold? | |
is-it-hot?])) | |
;; set up environment and the connector for pathom-vis | |
(def CONNECT_PARSER? true) | |
;; Open Pathom Viz and then send the following expression to REPL | |
(cond-> indexes | |
CONNECT_PARSER? | |
; give your environment a unique parser-id, this will ensure reconnects work as expected | |
(p.connector/connect-env {::pvc/parser-id ::accu-geojs})) | |
;; **************************************************************************************** | |
;; Rich Comment Section | |
;; **************************************************************************************** | |
(comment | |
;; Testing resolvers | |
(get-ip) | |
(ip->geocoords {:ip google-ip}) | |
(geocoords->locationkey {:geojs/latitude "37.751", :geojs/longitude "-97.822"}) | |
(locationkey->currentweather {:accu/location-id 2148551}) | |
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ | |
; Queries using the Smart Map interface | |
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ | |
;; Create pathom smart-map using pathom indexes and some initial data | |
(def smart-map (psm/smart-map indexes {:ip google-ip})) | |
;; Get the country that this IP is located | |
(:geojs/country smart-map) | |
;; Get the temperature at the place where this IP is located | |
(->> {:ip google-ip} | |
(psm/smart-map indexes) | |
:accu/temperature-val) | |
;; Without any initial data, i.e. starting point | |
(:accu/temperature-val (psm/smart-map indexes)) | |
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ | |
; Queries using the EQL interface | |
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ | |
(p.eql/process indexes | |
; we can provide some initial data | |
{:ip google-ip} | |
; then we write an EQL query | |
[:geojs/organization_name | |
:geojs/latitude | |
:geojs/longitude]) | |
; fetch geojs info | |
; ip of the machine we are doing the request is automatically extracted | |
(p.eql/process indexes | |
;; Without any initial data | |
[:geojs/organization_name | |
:geojs/latitude | |
:geojs/longitude]) | |
; fetch temperature and local time at the place where the machine we are doing the request is located | |
(p.eql/process indexes | |
[:accu/temperature-val | |
:accu/temperature-unit | |
:accu/time-local]) | |
;; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ | |
;; Queries using pathom.viz GUI EQL requests | |
;; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ | |
[:geojs/city | |
:geojs/region | |
:geojs/country_code | |
:geojs/organization_name | |
:accu/temperature-val | |
:accu/temperature-unit | |
:accu/time-local | |
:accu/day? | |
:accu/weather-text | |
:accu/hot?] | |
[{[:ip "142.250.184.142"][:accu/temperature-val | |
:accu/temperature-unit | |
:accu/time-local | |
:geojs/city | |
:geojs/region | |
:geojs/country]}] | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment