Skip to content

Commit 4de3042

Browse files
committed
Reorganizing into core for m4 and web for m5
1 parent 77d3f6e commit 4de3042

File tree

4 files changed

+166
-162
lines changed

4 files changed

+166
-162
lines changed

project.clj

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,6 @@
1111
[compojure "1.1.6"]
1212
[hiccup "1.0.4"]]
1313
:main ^:skip-aot global-growth.core
14-
:ring {:handler global-growth.core/handler}
14+
:ring {:handler global-growth.web/handler}
1515
:target-path "target/%s"
1616
:profiles {:uberjar {:aot :all}})

src/global_growth/core.clj

+59-95
Original file line numberDiff line numberDiff line change
@@ -1,106 +1,70 @@
11
(ns global-growth.core
2-
(:require [global-growth.world-bank :as world-bank]
3-
[compojure.core :refer [defroutes GET]]
4-
[compojure.handler :refer [site]]
5-
[hiccup.core :as hiccup]
6-
[hiccup.page :as page]
7-
[hiccup.form :as form]))
2+
(:require [clj-http.client :as client]
3+
[cheshire.core :as json]))
84

9-
; TODO: handle paging: right now just getting a large value
10-
; for 'per_page' parameter.
11-
; Maybe that is fine for simplicity. But that could be a
12-
; problem if we get things with large result sets. Not
13-
; getting large results as of now.
5+
(defn TODO [msg]
6+
(throw (Exception. msg)))
147

15-
;; WEB APP
8+
(defn parse-json [str]
9+
(json/parse-string str true))
1610

17-
(defn layout
18-
[title & content]
19-
(page/html5
20-
[:head
21-
[:title title]
22-
(page/include-css "//netdna.bootstrapcdn.com/bootstrap/3.1.0/css/bootstrap.min.css")
23-
(page/include-css "//netdna.bootstrapcdn.com/bootstrap/3.1.0/css/bootstrap-theme.min.css")
24-
[:meta {:name "viewport" :content "width=device-width, initial-scale=1"}]]
25-
[:body
26-
[:nav.navbar.navbar-default {:role "navigation"}
27-
[:div.container-fluid
28-
[:div.navbar-header
29-
[:a.navbar-brand {:href "/"} "World Bank Indicators"]]]]
30-
[:div.container
31-
content]]))
11+
;; WORLD BANK API CALLS
12+
(defn get-api
13+
"Returns map representing API response."
14+
[path params]
15+
(let [base-path (str "http://api.worldbank.org" path)
16+
query-params (merge params {:format "json" :per_page 10000})
17+
response (parse-json (:body (client/get base-path {:query-params query-params})))
18+
metadata (first response)
19+
results (second response)]
20+
{:metadata metadata
21+
:results results}))
3222

33-
(defn ordered-list
34-
[coll]
35-
[:ol
36-
(for [list-item coll]
37-
[:li list-item])])
23+
(defn get-values
24+
"Returns a relation of two keys from API response."
25+
[path query-params key1 key2]
26+
(let [response (get-api path query-params)]
27+
(for [item (:results response)]
28+
[(key1 item) (key2 item)])))
3829

39-
(defn format-indicator-value
40-
[value]
41-
(if (number? value)
42-
(format "%,.2f" (float value))
43-
(str value)))
30+
(defn remove-aggregate-countries
31+
"Remove all countries that aren't actually countries, but are aggregates."
32+
[countries]
33+
(remove (fn [country]
34+
(= (get-in country [:region :value]) "Aggregates")) countries))
4435

45-
(defn indicator-list
46-
[indicators]
47-
(ordered-list
48-
(for [country-pair indicators]
49-
(let [country (first country-pair)
50-
value (second country-pair)]
51-
(str country " (" (format-indicator-value value) ")")))))
36+
(def indicators
37+
(delay (get-values "/topics/16/indicators" {} :name :id)))
5238

53-
(defn view-indicators
54-
[indicator1 indicator2 year]
55-
(let [inds1 (world-bank/get-indicator-values indicator1 year)
56-
inds2 (world-bank/get-indicator-values indicator2 year)
57-
indicator-map (into {}
58-
(map (fn [indicator]
59-
[(second indicator) (first indicator)])
60-
(world-bank/get-indicators)))]
61-
(layout "Sorted Indicators"
62-
[:h1 "Sorted Indicators"]
63-
[:div.row
64-
[:div.form-group.col-md-6
65-
(form/label indicator1 (get indicator-map indicator1))
66-
(if (empty? inds1)
67-
[:p "No indicator values for this year."]
68-
(indicator-list inds1))
69-
]
70-
[:div.form-group.col-md-6
71-
(form/label indicator2 (get indicator-map indicator2))
72-
(if (empty? inds2)
73-
[:p "No indicator values for this year."]
74-
(indicator-list inds2))]])))
39+
;; Get set of country ids so we can filter out aggregate values.
40+
(def country-ids
41+
(delay
42+
(let [countries (remove-aggregate-countries (:results (get-api "/countries" {})))]
43+
(set (map :iso2Code countries)))))
7544

76-
(defn main-page []
77-
(layout "World Bank Indicators"
78-
[:h1 "World Bank Indicators"]
79-
[:p "Choose one of these world development indicators."]
80-
(form/form-to {:role "form"} [:get "/indicators"]
81-
[:div.row
82-
[:div.form-group.col-md-5
83-
(form/label "indicator1" "Indicator 1: ")
84-
(form/drop-down {:class "form-control"}
85-
"indicator1"
86-
(world-bank/get-indicators))]
87-
[:div.form-group.col-md-5
88-
(form/label "indicator2" "Indicator 2: ")
89-
(form/drop-down {:class "form-control"}
90-
"indicator2"
91-
(world-bank/get-indicators))]
92-
[:div.form-group.col-md-2
93-
(form/label "year" "Year: ")
94-
(form/drop-down {:class "form-control"}
95-
"year"
96-
(reverse (range 1960 2013))
97-
2010)]]
98-
(form/submit-button "Submit"))))
45+
(defn get-indicators []
46+
"Gets vector of indicators.
47+
/topics/16/indicators: All urban development
48+
--- Other possibilities ---
49+
/sources/2/indicators: All world development indicators (about 1300)
50+
/indicators: All Indicators (about 8800)"
51+
@indicators)
9952

100-
(defroutes main-routes
101-
(GET "/" [] (main-page))
102-
(GET "/indicators" [indicator1 indicator2 year]
103-
(view-indicators indicator1 indicator2 year)))
104-
105-
(def handler (site main-routes))
53+
(defn get-indicator-values
54+
"Returns indicator values for a specified year for all countries."
55+
[indicator year list-size]
56+
(let [values (get-values (str "/countries/all/indicators/" indicator)
57+
{:date (str year)}
58+
:country :value)]
59+
(take list-size
60+
(sort-by second >
61+
(for [[country value] values
62+
:when (and (not (nil? value))
63+
(contains? @country-ids (:id country)))]
64+
[(:value country) (read-string value)])))))
10665

66+
(defn -main
67+
[& args]
68+
(let [indicator-values (get-indicator-values "EN.POP.DNST" 2010 10)]
69+
(doseq [value indicator-values]
70+
(println (str (first value) " " (second value))))))

src/global_growth/web.clj

+106
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
(ns global-growth.web
2+
(:require [global-growth.core :as global-growth]
3+
[compojure.core :refer [defroutes GET]]
4+
[compojure.handler :refer [site]]
5+
[hiccup.core :as hiccup]
6+
[hiccup.page :as page]
7+
[hiccup.form :as form]))
8+
9+
; TODO: handle paging: right now just getting a large value
10+
; for 'per_page' parameter.
11+
; Maybe that is fine for simplicity. But that could be a
12+
; problem if we get things with large result sets. Not
13+
; getting large results as of now.
14+
15+
;; WEB APP
16+
17+
(defn layout
18+
[title & content]
19+
(page/html5
20+
[:head
21+
[:title title]
22+
(page/include-css "//netdna.bootstrapcdn.com/bootstrap/3.1.0/css/bootstrap.min.css")
23+
(page/include-css "//netdna.bootstrapcdn.com/bootstrap/3.1.0/css/bootstrap-theme.min.css")
24+
[:meta {:name "viewport" :content "width=device-width, initial-scale=1"}]]
25+
[:body
26+
[:nav.navbar.navbar-default {:role "navigation"}
27+
[:div.container-fluid
28+
[:div.navbar-header
29+
[:a.navbar-brand {:href "/"} "World Bank Indicators"]]]]
30+
[:div.container
31+
content]]))
32+
33+
(defn ordered-list
34+
[coll]
35+
[:ol
36+
(for [list-item coll]
37+
[:li list-item])])
38+
39+
(defn format-indicator-value
40+
[value]
41+
(if (number? value)
42+
(format "%,.2f" (float value))
43+
(str value)))
44+
45+
(defn indicator-list
46+
[indicators]
47+
(ordered-list
48+
(for [country-pair indicators]
49+
(let [country (first country-pair)
50+
value (second country-pair)]
51+
(str country " (" (format-indicator-value value) ")")))))
52+
53+
(defn view-indicators
54+
[indicator1 indicator2 year]
55+
(let [inds1 (global-growth/get-indicator-values indicator1 year)
56+
inds2 (global-growth/get-indicator-values indicator2 year)
57+
indicator-map (into {}
58+
(map (fn [indicator]
59+
[(second indicator) (first indicator)])
60+
(global-growth/get-indicators)))]
61+
(layout "Sorted Indicators"
62+
[:h1 "Sorted Indicators"]
63+
[:div.row
64+
[:div.form-group.col-md-6
65+
(form/label indicator1 (get indicator-map indicator1))
66+
(if (empty? inds1)
67+
[:p "No indicator values for this year."]
68+
(indicator-list inds1))
69+
]
70+
[:div.form-group.col-md-6
71+
(form/label indicator2 (get indicator-map indicator2))
72+
(if (empty? inds2)
73+
[:p "No indicator values for this year."]
74+
(indicator-list inds2))]])))
75+
76+
(defn main-page []
77+
(layout "World Bank Indicators"
78+
[:h1 "World Bank Indicators"]
79+
[:p "Choose one of these world development indicators."]
80+
(form/form-to {:role "form"} [:get "/indicators"]
81+
[:div.row
82+
[:div.form-group.col-md-5
83+
(form/label "indicator1" "Indicator 1: ")
84+
(form/drop-down {:class "form-control"}
85+
"indicator1"
86+
(global-growth/get-indicators))]
87+
[:div.form-group.col-md-5
88+
(form/label "indicator2" "Indicator 2: ")
89+
(form/drop-down {:class "form-control"}
90+
"indicator2"
91+
(global-growth/get-indicators))]
92+
[:div.form-group.col-md-2
93+
(form/label "year" "Year: ")
94+
(form/drop-down {:class "form-control"}
95+
"year"
96+
(reverse (range 1960 2013))
97+
2010)]]
98+
(form/submit-button "Submit"))))
99+
100+
(defroutes main-routes
101+
(GET "/" [] (main-page))
102+
(GET "/indicators" [indicator1 indicator2 year]
103+
(view-indicators indicator1 indicator2 year)))
104+
105+
(def handler (site main-routes))
106+

src/global_growth/world_bank.clj

-66
This file was deleted.

0 commit comments

Comments
 (0)