Skip to content

Instantly share code, notes, and snippets.

@athanhat
Last active July 2, 2022 14:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save athanhat/2ccfad3786934ad41efc7c74674494b5 to your computer and use it in GitHub Desktop.
Save athanhat/2ccfad3786934ad41efc7c74674494b5 to your computer and use it in GitHub Desktop.
Alternative Pathom3 Tutorial using GeoJS and AccuWeather APIs
[: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