Last active
February 20, 2021 20:36
-
-
Save mmzsource/a732950aa43d19c5a9b63bbb7f20b7eb to your computer and use it in GitHub Desktop.
Babashka script to retrieve the current league tables of some popular football competitions.
This file contains hidden or 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
#!/usr/bin/env bb | |
;; This script has 3 dependencies: | |
;; | |
;; 1. Babashka installed: https://github.com/babashka/babashka#installation (and bb on PATH) | |
;; 2. Valid (free) football-data API key: https://www.football-data.org/client/register | |
;; either available as environment variable (FOOTBALL_DATA_API_KEY) or pasted in this script | |
;; 3. File is executable (chmod +x bb-football.clj) | |
;; | |
;; Run like this: ./bb-football.clj | |
;; or like this: bb bb-football.clj | |
;; | |
;; Tested on babashka v0.2.10 | |
;; ============= | |
;; = API CALLS = | |
;; ============= | |
(def base-url "http://api.football-data.org/v2/competitions/") | |
(def headers {"Accept" "application/json" | |
"X-Auth-Token" (System/getenv "FOOTBALL_DATA_API_KEY")}) | |
(defn get-football-data! [url] | |
(-> url | |
(curl/get {:headers headers}) | |
:body | |
(json/parse-string true))) | |
(defn standing! [competition-id] | |
(get-football-data! (str base-url competition-id "/standings?standingType=TOTAL"))) | |
;; ============== | |
;; = USER INPUT = | |
;; ============== | |
(def usage-message | |
(str | |
"\nEnter the number (:key) of the competition you want to get the league table for. \n" | |
"Enter 99 (or CTRL-c) to quit.\n\n" | |
"Make sure you get your free API key at https://www.football-data.org/client/register\n" | |
"and put the API key in the bb script or in your env. Otherwise you won't have permission\n" | |
"to retrieve the tables.\n")) | |
(defn to-int [string] | |
(try | |
(Integer. string) | |
(catch Exception))) | |
(defn quit? [int] | |
(= int 99)) | |
(defn valid-input? [int key->id] | |
(or (contains? key->id int) (quit? int))) | |
;; ======================= | |
;; = DATA TRANSFORMATION = | |
;; ======================= | |
;; Competition | |
(defn make-ctn [{:keys [name id plan lastUpdated]}] | |
{:ctn-name name :ctn-id id :ctn-plan plan :last-updated lastUpdated}) | |
;; Season | |
(defn make-ssn [{:keys [id startDate endDate]}] | |
{:ssn-id id :ssn-start startDate :ssn-end endDate}) | |
(defn make-area [{:keys [name countryCode id]}] | |
{:area-name name :area-code countryCode :area-id id}) | |
(defn transform-competition [{:keys [currentSeason area] :as competition}] | |
(merge | |
(make-ctn competition) | |
(make-ssn currentSeason) | |
(make-area area))) | |
(defn table-meta [{:keys [competition season]}] | |
(merge | |
(make-ctn competition) | |
(make-ssn season) | |
(make-area (:area competition)))) | |
(defn transform-table | |
[{:keys [position playedGames won draw lost points goalsFor goalsAgainst] :as table}] | |
{:pos position :team ((comp :name :team) table) :games playedGames :won won | |
:draw draw :lost lost :points points :goals goalsFor :against goalsAgainst}) | |
(defn tier-one? [competition] | |
(= (:ctn-plan competition) "TIER_ONE")) | |
(defn filter-competitions [competitions] | |
(filter tier-one? competitions)) | |
(defn add-user-keys [competitions-data] | |
(let [;; create keys-map {:key 1} {:key 2} etc. | |
keys-map (map #(hash-map :key %) (range 1 (inc (count competitions-data))))] | |
(map merge competitions-data keys-map))) | |
(defn key->id [competitions'] | |
(reduce | |
(fn [acc item] | |
(assoc acc (:key item) (:ctn-id item))) | |
{} | |
competitions')) | |
;; ========== | |
;; = OUTPUT = | |
;; ========== | |
(defn print-competitions [competitions'] | |
(clojure.pprint/print-table | |
[:key :area-name :ctn-name] | |
competitions')) | |
(defn print-table-meta [standing] | |
(clojure.pprint/print-table | |
[:area-name :ctn-name :ssn-start :ssn-end :last-updated] | |
[(table-meta standing)])) | |
(defn print-group [group] | |
(clojure.pprint/print-table | |
[:pos :team :games :won :draw :lost :points :goals :against] | |
(map transform-table (:table group)))) | |
(defn print-table [standing] | |
(print-table-meta standing) | |
(run! print-group (:standings standing)) | |
(println)) | |
;; ============== | |
;; = SUPER GLUE = | |
;; ============== | |
(let [competitions (get-football-data! base-url) | |
competitions' (->> (:competitions competitions) | |
(map transform-competition) | |
(filter-competitions) | |
(add-user-keys)) | |
key->id (key->id competitions')] | |
(println usage-message) | |
(print-competitions competitions') | |
(println) | |
(loop [user-key (to-int (read-line))] | |
(if (valid-input? user-key key->id) | |
(if (quit? user-key) | |
(System/exit 1) | |
(print-table (standing! (get key->id user-key)))) | |
(do | |
(println "Please enter a valid number.\n") | |
(recur (to-int (read-line))))))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment