Skip to content

Instantly share code, notes, and snippets.

@mmzsource
Last active February 20, 2021 20:36
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 mmzsource/a732950aa43d19c5a9b63bbb7f20b7eb to your computer and use it in GitHub Desktop.
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.
#!/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