Added biggest-to-the-middle-sort
This commit is contained in:
parent
e392369373
commit
3ae27a4012
8
.gitignore
vendored
8
.gitignore
vendored
|
@ -3,3 +3,11 @@
|
|||
/*-init.clj
|
||||
/resources/public/js/compiled
|
||||
out
|
||||
|
||||
\.lein-repl-history
|
||||
|
||||
\.nrepl-port
|
||||
|
||||
*.tgz
|
||||
|
||||
*.zip
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# swingometer
|
||||
|
||||
A [re-frame](https://github.com/Day8/re-frame) application designed to ... well, that part is up to you.
|
||||
A [re-frame](https://github.com/Day8/re-frame) application designed to show votes in an election.
|
||||
|
||||
## Development Mode
|
||||
|
||||
|
|
1
resources/public/swingometer
Symbolic link
1
resources/public/swingometer
Symbolic link
|
@ -0,0 +1 @@
|
|||
swingometer
|
|
@ -61,13 +61,11 @@
|
|||
:validate-fn html-attr? :description [:span "HTML attributes, like " [:code ":on-mouse-move"] [:br] "No " [:code ":class"] " or " [:code ":style"] "allowed"]}])
|
||||
|
||||
|
||||
(def log (.-log js/console))
|
||||
;; (defn abs
|
||||
;; "Return the absolute value of the (numeric) argument."
|
||||
;; [n] (max n (- n)))
|
||||
|
||||
|
||||
(defn abs
|
||||
"Return the absolute value of the (numeric) argument."
|
||||
[n] (max n (- n)))
|
||||
|
||||
;; the constant 140 represents the full sweep of the needle
|
||||
;; from the left end of the scale to right end, in degrees.
|
||||
(def full-scale-deflection 140)
|
||||
|
@ -112,7 +110,7 @@
|
|||
[arg]
|
||||
(if
|
||||
(and (number? arg) (not (integer? arg)))
|
||||
(.toFixed arg 2)
|
||||
(.toFixed arg 1)
|
||||
arg))
|
||||
|
||||
|
||||
|
@ -136,27 +134,51 @@
|
|||
:x cx
|
||||
:y (- cy min-radius)} (as-label label)]])
|
||||
|
||||
(def model {:snp {:id :snp :name "Scottish National Party" :colour "yellow" :votes 100}
|
||||
:lab {:id :lab :name "Labour Party" :colour "red" :votes 90}
|
||||
:con {:id :con :name "Conservative Party" :colour "blue" :votes 80}
|
||||
:ld {:id :ld :name "Liberal Democrats" :colour "GoldenRod" :votes 70}
|
||||
:grn {:id :grn :name "Scottish Green Party" :colour "green" :votes 60}
|
||||
:ukp {:id :ukp :name "United Kingdom Independence Party" :colour "DarkViolet" :votes 50}})
|
||||
|
||||
(defn biggest-to-the-middle-sort
|
||||
"Sort this list of `maps` representing parties so that those with the most votes are in
|
||||
the middle."
|
||||
[maps]
|
||||
(let [first-sort (sort-by :votes maps)
|
||||
evens (take-nth 2 first-sort)
|
||||
odds (take-nth 2 (rest first-sort))]
|
||||
(concat evens (reverse odds))))
|
||||
|
||||
|
||||
(defn recursively-draw-segments
|
||||
"Walk down a list of parties, returning a labelled SVG arc segment for each one.
|
||||
`still-to-do` is the (remainder of the) list of parties being scanned, should
|
||||
initially be the whole list;
|
||||
`done` is the parties which have been scanned, and should initially be `nil`.
|
||||
`total-votes` is the total number of votes for all parties.
|
||||
`cx` and `cy` are the cartesian coordinates of the centre of arc.
|
||||
`radius` is the radius of the arc."
|
||||
[still-to-do done total-votes cx cy radius]
|
||||
(log (string/join " " ["\nstill-to-do" still-to-do "\ndone" done "\ntotal-votes" total-votes "cx" cx "cy" cy "radius" radius]))
|
||||
(if
|
||||
(empty? still-to-do) nil
|
||||
(let [votes-done (reduce + (map :votes done))
|
||||
start-angle (deflection votes-done 0 total-votes)
|
||||
party (first still-to-do)
|
||||
end-angle (deflection (+ (:votes party) votes-done) 0 total-votes)]
|
||||
end-angle (deflection (+ (:votes party) votes-done) 0 total-votes)
|
||||
others (recursively-draw-segments (rest still-to-do) (cons party done) total-votes cx cy radius)
|
||||
vote-share (* (/ (:votes party) total-votes) 100)]
|
||||
(if (> vote-share 1)
|
||||
(cons [:g [:path {:class "snm-scale"
|
||||
:id (str (:id party) "-segment")
|
||||
:style {:stroke (:colour party)}
|
||||
:d (describe-arc cx cy radius start-angle end-angle)}]
|
||||
(gradation cx cy (* radius 0.8) (* radius 1.1) start-angle
|
||||
(let [vote-share (* (/ (:votes party) total-votes) 100)]
|
||||
(str
|
||||
(if (> vote-share 5) (name (:id party)) "")
|
||||
(if (> vote-share 10) (str " " (int vote-share) "%")))))]
|
||||
(recursively-draw-segments (rest still-to-do) (cons party done) total-votes cx cy radius)))))
|
||||
|
||||
(if (> vote-share 10) (str " " (as-label vote-share) "%"))))]
|
||||
others)
|
||||
others))))
|
||||
|
||||
|
||||
(defn swingometer
|
||||
|
@ -209,23 +231,8 @@
|
|||
:d (describe-arc cx cy scale-radius
|
||||
(- 0 mid-point-deflection)
|
||||
mid-point-deflection)}]
|
||||
;; (if (and (> gradations 0) (> total-votes 0))
|
||||
;; (apply vector (cons :g (map #(let
|
||||
;; [value (*
|
||||
;; (/
|
||||
;; total-votes
|
||||
;; gradations) %)]
|
||||
;; (gradation cx cy gradation-inner needle-length
|
||||
;; (deflection value 0 total-votes)
|
||||
;; value))
|
||||
;; (range 0 (+ gradations 1))))))
|
||||
(apply vector
|
||||
(cons :g (recursively-draw-segments (map model (sort (keys model))) nil total-votes cx cy scale-radius)))
|
||||
(cons :g (recursively-draw-segments (biggest-to-the-middle-sort (vals model)) nil total-votes cx cy scale-radius)))
|
||||
[:rect {:class frame-class
|
||||
:id (str id "-frame")
|
||||
:x (* width 0.05) :y (* height .05) :height cy :width (* width 0.9)}]
|
||||
;; [:circle {:class hub-class
|
||||
;; :id (str id "-hub")
|
||||
;; :r (/ height 10) :cx cx :cy cy}]
|
||||
]
|
||||
]]))
|
||||
:x (* width 0.05) :y (* height .05) :height cy :width (* width 0.9)}]]]]))
|
||||
|
|
Loading…
Reference in a new issue