clementine 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +1 -0
- data/Gemfile +4 -2
- data/LICENSE.txt +22 -0
- data/README.md +11 -6
- data/Rakefile +22 -0
- data/clementine.gemspec +2 -1
- data/ext/clojure-clojurescript-bef56a7/.gitignore +13 -0
- data/ext/clojure-clojurescript-bef56a7/Clojurescript.iml +12 -0
- data/ext/clojure-clojurescript-bef56a7/README.md +29 -0
- data/ext/clojure-clojurescript-bef56a7/benchmark/cljs/benchmark_runner.cljs +155 -0
- data/ext/clojure-clojurescript-bef56a7/bin/cljsc +21 -0
- data/ext/clojure-clojurescript-bef56a7/bin/cljsc.bat +18 -0
- data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/bin/cljsc.clj +0 -0
- data/ext/clojure-clojurescript-bef56a7/devnotes/README.org +35 -0
- data/ext/clojure-clojurescript-bef56a7/devnotes/bcrepl.org +13 -0
- data/ext/clojure-clojurescript-bef56a7/devnotes/cljs.org +500 -0
- data/ext/clojure-clojurescript-bef56a7/devnotes/corelib.org +583 -0
- data/ext/clojure-clojurescript-bef56a7/devnotes/day1.org +203 -0
- data/ext/clojure-clojurescript-bef56a7/devnotes/day2.org +44 -0
- data/ext/clojure-clojurescript-bef56a7/devnotes/talk.org +126 -0
- data/ext/clojure-clojurescript-bef56a7/devnotes/testing +13 -0
- data/ext/clojure-clojurescript-bef56a7/devnotes/todo.org +121 -0
- data/ext/clojure-clojurescript-bef56a7/epl-v10.html +261 -0
- data/ext/clojure-clojurescript-bef56a7/pom.template.xml +88 -0
- data/ext/clojure-clojurescript-bef56a7/samples/dom/.gitignore +2 -0
- data/ext/clojure-clojurescript-bef56a7/samples/dom/src/dom/test.cljs +48 -0
- data/ext/clojure-clojurescript-bef56a7/samples/dom/test.html +30 -0
- data/ext/clojure-clojurescript-bef56a7/samples/hello-js/.gitignore +2 -0
- data/ext/clojure-clojurescript-bef56a7/samples/hello-js/README.md +53 -0
- data/ext/clojure-clojurescript-bef56a7/samples/hello-js/externed-lib.js +7 -0
- data/ext/clojure-clojurescript-bef56a7/samples/hello-js/externs.js +3 -0
- data/ext/clojure-clojurescript-bef56a7/samples/hello-js/hello-extern.html +14 -0
- data/ext/clojure-clojurescript-bef56a7/samples/hello-js/hello-js-dev.html +18 -0
- data/ext/clojure-clojurescript-bef56a7/samples/hello-js/hello-js.html +17 -0
- data/ext/clojure-clojurescript-bef56a7/samples/hello-js/my-external-lib.js +3 -0
- data/ext/clojure-clojurescript-bef56a7/samples/hello-js/src/hello-js/core.cljs +9 -0
- data/ext/clojure-clojurescript-bef56a7/samples/hello-js/src/hello-js/extern-example.cljs +5 -0
- data/ext/clojure-clojurescript-bef56a7/samples/hello/.gitignore +2 -0
- data/ext/clojure-clojurescript-bef56a7/samples/hello/README.md +34 -0
- data/ext/clojure-clojurescript-bef56a7/samples/hello/hello-dev.html +18 -0
- data/ext/clojure-clojurescript-bef56a7/samples/hello/hello.html +13 -0
- data/ext/clojure-clojurescript-bef56a7/samples/hello/src/hello/core.cljs +8 -0
- data/ext/clojure-clojurescript-bef56a7/samples/hello/src/hello/foo/bar.cljs +4 -0
- data/ext/clojure-clojurescript-bef56a7/samples/nodehello.cljs +18 -0
- data/ext/clojure-clojurescript-bef56a7/samples/nodels.cljs +17 -0
- data/ext/clojure-clojurescript-bef56a7/samples/repl/.gitignore +2 -0
- data/ext/clojure-clojurescript-bef56a7/samples/repl/README.md +101 -0
- data/ext/clojure-clojurescript-bef56a7/samples/repl/index.html +27 -0
- data/ext/clojure-clojurescript-bef56a7/samples/repl/src/repl/test.cljs +73 -0
- data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/.gitignore +2 -0
- data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/README.md +42 -0
- data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/index-advanced.html +80 -0
- data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/index.html +88 -0
- data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/reset.css +48 -0
- data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/src/twitterbuzz/anneal.cljs +66 -0
- data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/src/twitterbuzz/core.cljs +307 -0
- data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/src/twitterbuzz/dom-helpers.cljs +95 -0
- data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/src/twitterbuzz/layout.cljs +100 -0
- data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/src/twitterbuzz/leaderboard.cljs +40 -0
- data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/src/twitterbuzz/radial.cljs +91 -0
- data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/src/twitterbuzz/showgraph.cljs +121 -0
- data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/src/twitterbuzz/timeline.cljs +39 -0
- data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/style.css +301 -0
- data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/test_data.txt +1 -0
- data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/tweet_maps.txt +1 -0
- data/ext/clojure-clojurescript-bef56a7/script/benchmark +30 -0
- data/ext/clojure-clojurescript-bef56a7/script/bootstrap +70 -0
- data/ext/clojure-clojurescript-bef56a7/script/browser-repl +16 -0
- data/ext/clojure-clojurescript-bef56a7/script/build +59 -0
- data/ext/clojure-clojurescript-bef56a7/script/clean +5 -0
- data/ext/clojure-clojurescript-bef56a7/script/closure-library-release/google-closure-library-third-party.pom.template +59 -0
- data/ext/clojure-clojurescript-bef56a7/script/closure-library-release/google-closure-library.pom.template +54 -0
- data/ext/clojure-clojurescript-bef56a7/script/closure-library-release/make-closure-library-jars.sh +87 -0
- data/ext/clojure-clojurescript-bef56a7/script/compile +41 -0
- data/ext/clojure-clojurescript-bef56a7/script/repl +13 -0
- data/ext/clojure-clojurescript-bef56a7/script/repl.bat +13 -0
- data/ext/clojure-clojurescript-bef56a7/script/repljs +15 -0
- data/ext/clojure-clojurescript-bef56a7/script/repljs.bat +14 -0
- data/ext/clojure-clojurescript-bef56a7/script/test +38 -0
- data/ext/clojure-clojurescript-bef56a7/script/test-compile +30 -0
- data/ext/clojure-clojurescript-bef56a7/src/clj/cljs/analyzer.clj +975 -0
- data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/clj/cljs/closure.clj +173 -73
- data/ext/clojure-clojurescript-bef56a7/src/clj/cljs/compiler.clj +1081 -0
- data/ext/clojure-clojurescript-bef56a7/src/clj/cljs/core.clj +1158 -0
- data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/clj/cljs/repl.clj +51 -25
- data/ext/clojure-clojurescript-bef56a7/src/clj/cljs/repl/browser.clj +258 -0
- data/ext/clojure-clojurescript-bef56a7/src/clj/cljs/repl/reflect.clj +75 -0
- data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/clj/cljs/repl/rhino.clj +6 -5
- data/ext/clojure-clojurescript-bef56a7/src/clj/cljs/repl/server.clj +173 -0
- data/ext/clojure-clojurescript-bef56a7/src/clj/cljs/tagged_literals.clj +30 -0
- data/ext/clojure-clojurescript-bef56a7/src/cljs/cljs/core.cljs +7197 -0
- data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/cljs/cljs/nodejs.cljs +1 -1
- data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/cljs/cljs/nodejs_externs.js +0 -0
- data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/cljs/cljs/nodejscli.cljs +1 -1
- data/ext/clojure-clojurescript-bef56a7/src/cljs/cljs/reader.cljs +551 -0
- data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/cljs/clojure/browser/dom.cljs +59 -13
- data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/cljs/clojure/browser/event.cljs +0 -0
- data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/cljs/clojure/browser/net.cljs +8 -7
- data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/cljs/clojure/browser/repl.cljs +2 -2
- data/ext/clojure-clojurescript-bef56a7/src/cljs/clojure/core/reducers.cljs +298 -0
- data/ext/clojure-clojurescript-bef56a7/src/cljs/clojure/data.cljs +162 -0
- data/ext/clojure-clojurescript-bef56a7/src/cljs/clojure/reflect.cljs +48 -0
- data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/cljs/clojure/set.cljs +0 -0
- data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/cljs/clojure/string.cljs +4 -10
- data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/cljs/clojure/walk.cljs +0 -0
- data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/cljs/clojure/zip.cljs +0 -0
- data/ext/clojure-clojurescript-bef56a7/test/cljs/cljs/binding_test.cljs +7 -0
- data/ext/clojure-clojurescript-bef56a7/test/cljs/cljs/binding_test_other_ns.cljs +3 -0
- data/ext/clojure-clojurescript-bef56a7/test/cljs/cljs/core_test.cljs +1678 -0
- data/ext/clojure-clojurescript-bef56a7/test/cljs/cljs/import_test.cljs +11 -0
- data/ext/clojure-clojurescript-bef56a7/test/cljs/cljs/import_test/foo.cljs +5 -0
- data/ext/clojure-clojurescript-bef56a7/test/cljs/cljs/letfn_test.cljs +19 -0
- data/ext/clojure-clojurescript-bef56a7/test/cljs/cljs/macro_test.cljs +6 -0
- data/ext/clojure-clojurescript-bef56a7/test/cljs/cljs/macro_test/macros.clj +5 -0
- data/ext/clojure-clojurescript-bef56a7/test/cljs/cljs/ns_test.cljs +14 -0
- data/ext/clojure-clojurescript-bef56a7/test/cljs/cljs/ns_test/bar.cljs +3 -0
- data/ext/clojure-clojurescript-bef56a7/test/cljs/cljs/ns_test/foo.cljs +7 -0
- data/ext/clojure-clojurescript-bef56a7/test/cljs/cljs/reader_test.cljs +124 -0
- data/ext/clojure-clojurescript-bef56a7/test/cljs/clojure/data_test.cljs +22 -0
- data/ext/clojure-clojurescript-bef56a7/test/cljs/clojure/string_test.cljs +97 -0
- data/ext/clojure-clojurescript-bef56a7/test/cljs/foo/ns_shadow_test.cljs +9 -0
- data/ext/clojure-clojurescript-bef56a7/test/cljs/test_runner.cljs +26 -0
- data/lib/clementine.rb +3 -24
- data/lib/clementine/clojurescript_engine.rb +9 -48
- data/lib/clementine/clojurescript_engine/base.rb +15 -0
- data/lib/clementine/clojurescript_engine/jruby.rb +46 -0
- data/lib/clementine/{clojurescript_engine_mri.rb → clojurescript_engine/mri.rb} +17 -10
- data/lib/clementine/version.rb +1 -1
- data/test/clojurescript_engine_test.rb +36 -14
- metadata +177 -83
- data/vendor/assets/lib/clojure.jar +0 -0
- data/vendor/assets/lib/compiler.jar +0 -0
- data/vendor/assets/lib/goog.jar +0 -0
- data/vendor/assets/lib/js.jar +0 -0
- data/vendor/assets/src/clj/cljs/compiler.clj +0 -1341
- data/vendor/assets/src/clj/cljs/core.clj +0 -702
- data/vendor/assets/src/clj/cljs/repl/browser.clj +0 -341
- data/vendor/assets/src/cljs/cljs/core.cljs +0 -3330
- data/vendor/assets/src/cljs/cljs/reader.cljs +0 -360
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
; Copyright (c) Rich Hickey. All rights reserved.
|
|
2
|
+
; The use and distribution terms for this software are covered by the
|
|
3
|
+
; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
|
|
4
|
+
; which can be found in the file epl-v10.html at the root of this distribution.
|
|
5
|
+
; By using this software in any fashion, you are agreeing to be bound by
|
|
6
|
+
; the terms of this license.
|
|
7
|
+
; You must not remove this notice, or any other, from this software.
|
|
8
|
+
|
|
9
|
+
(ns twitterbuzz.dom-helpers
|
|
10
|
+
(:require [clojure.string :as string]
|
|
11
|
+
[goog.dom :as dom]))
|
|
12
|
+
|
|
13
|
+
(defn get-element
|
|
14
|
+
"Return the element with the passed id."
|
|
15
|
+
[id]
|
|
16
|
+
(dom/getElement (name id)))
|
|
17
|
+
|
|
18
|
+
(defn append
|
|
19
|
+
"Append all children to parent."
|
|
20
|
+
[parent & children]
|
|
21
|
+
(do (doseq [child children]
|
|
22
|
+
(dom/appendChild parent child))
|
|
23
|
+
parent))
|
|
24
|
+
|
|
25
|
+
(defn set-text
|
|
26
|
+
"Set the text content for the passed element returning the
|
|
27
|
+
element. If a keyword is passed in the place of e, the element with
|
|
28
|
+
that id will be used and returned."
|
|
29
|
+
[e s]
|
|
30
|
+
(let [e (if (keyword? e) (get-element e) e)]
|
|
31
|
+
(doto e (dom/setTextContent s))))
|
|
32
|
+
|
|
33
|
+
(defn normalize-args [tag args]
|
|
34
|
+
(let [parts (string/split (name tag) #"(\.|#)")
|
|
35
|
+
[tag attrs] [(first parts)
|
|
36
|
+
(apply hash-map (map #(cond (= % ".") :class
|
|
37
|
+
(= % "#") :id
|
|
38
|
+
:else %)
|
|
39
|
+
(rest parts)))]]
|
|
40
|
+
(if (map? (first args))
|
|
41
|
+
[tag (merge attrs (first args)) (rest args)]
|
|
42
|
+
[tag attrs args])))
|
|
43
|
+
|
|
44
|
+
(defn element
|
|
45
|
+
"Create a dom element using a keyword for the element name and a map
|
|
46
|
+
for the attributes. Append all children to parent. If the first
|
|
47
|
+
child is a string then the string will be set as the text content of
|
|
48
|
+
the parent and all remaining children will be appended."
|
|
49
|
+
[tag & args]
|
|
50
|
+
(let [[tag attrs children] (normalize-args tag args)
|
|
51
|
+
parent (dom/createDom (name tag)
|
|
52
|
+
(reduce (fn [o [k v]]
|
|
53
|
+
(aset o k v))
|
|
54
|
+
(js-obj)
|
|
55
|
+
(map #(vector (name %1) %2)
|
|
56
|
+
(keys attrs)
|
|
57
|
+
(vals attrs))))
|
|
58
|
+
[parent children] (if (string? (first children))
|
|
59
|
+
[(set-text (element tag attrs) (first children))
|
|
60
|
+
(rest children)]
|
|
61
|
+
[parent children])]
|
|
62
|
+
(apply append parent children)))
|
|
63
|
+
|
|
64
|
+
(defn remove-children
|
|
65
|
+
"Remove all children from the element with the passed id."
|
|
66
|
+
[id]
|
|
67
|
+
(let [parent (dom/getElement (name id))]
|
|
68
|
+
(do (dom/removeChildren parent))))
|
|
69
|
+
|
|
70
|
+
(defn html
|
|
71
|
+
"Create a dom element from an html string."
|
|
72
|
+
[s]
|
|
73
|
+
(dom/htmlToDocumentFragment s))
|
|
74
|
+
|
|
75
|
+
(defn- element-arg? [x]
|
|
76
|
+
(or (keyword? x)
|
|
77
|
+
(map? x)
|
|
78
|
+
(string? x)))
|
|
79
|
+
|
|
80
|
+
(defn build
|
|
81
|
+
"Build up a dom element from nested vectors."
|
|
82
|
+
[x]
|
|
83
|
+
(if (vector? x)
|
|
84
|
+
(let [[parent children] (if (keyword? (first x))
|
|
85
|
+
[(apply element (take-while element-arg? x))
|
|
86
|
+
(drop-while element-arg? x)]
|
|
87
|
+
[(first x) (rest x)])
|
|
88
|
+
children (map build children)]
|
|
89
|
+
(apply append parent children))
|
|
90
|
+
x))
|
|
91
|
+
|
|
92
|
+
(defn insert-at
|
|
93
|
+
"Insert a child element at a specific location."
|
|
94
|
+
[parent child index]
|
|
95
|
+
(dom/insertChildAt parent child index))
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
; Copyright (c) Rich Hickey. All rights reserved.
|
|
2
|
+
; The use and distribution terms for this software are covered by the
|
|
3
|
+
; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
|
|
4
|
+
; which can be found in the file epl-v10.html at the root of this distribution.
|
|
5
|
+
; By using this software in any fashion, you are agreeing to be bound by
|
|
6
|
+
; the terms of this license.
|
|
7
|
+
; You must not remove this notice, or any other, from this software.
|
|
8
|
+
|
|
9
|
+
(ns twitterbuzz.layout
|
|
10
|
+
(:require [twitterbuzz.anneal :as ann]
|
|
11
|
+
[twitterbuzz.radial :as rad]
|
|
12
|
+
[goog.math :as math]))
|
|
13
|
+
|
|
14
|
+
(defn random-loc []
|
|
15
|
+
{:x (ann/random) :y (ann/random)})
|
|
16
|
+
|
|
17
|
+
(defn sqr [x]
|
|
18
|
+
(* x x))
|
|
19
|
+
|
|
20
|
+
(defn sqrt [x]
|
|
21
|
+
(js/Math.sqrt x))
|
|
22
|
+
|
|
23
|
+
(defn dist [{x1 :x y1 :y} {x2 :x y2 :y}]
|
|
24
|
+
(sqrt (+ (sqr (- x2 x1)) (sqr (- y2 y1)))))
|
|
25
|
+
|
|
26
|
+
(defn init-state [mentions-data]
|
|
27
|
+
(let [connected (reduce (fn [ret [k {:keys [mentions]}]]
|
|
28
|
+
(if (pos? (count mentions))
|
|
29
|
+
(into (conj ret k) (keys mentions))
|
|
30
|
+
ret))
|
|
31
|
+
#{} mentions-data)
|
|
32
|
+
mentions-data (select-keys mentions-data connected)]
|
|
33
|
+
{:locs (zipmap connected (repeatedly #(random-loc)))
|
|
34
|
+
:mentions mentions-data}))
|
|
35
|
+
|
|
36
|
+
(defn roots [mentions-data]
|
|
37
|
+
(let [parents (reduce (fn [ret [k {:keys [mentions]}]]
|
|
38
|
+
(if (pos? (count mentions))
|
|
39
|
+
(conj ret k)
|
|
40
|
+
ret))
|
|
41
|
+
#{} mentions-data)]
|
|
42
|
+
(reduce disj parents (mapcat #(keys (:mentions %)) (vals mentions-data)))))
|
|
43
|
+
|
|
44
|
+
(defn radial
|
|
45
|
+
[mentions-data]
|
|
46
|
+
(let [mentions #(rad/get-mentions mentions-data %)
|
|
47
|
+
weights (rad/weights
|
|
48
|
+
(into (set (roots mentions-data)) (mapcat mentions (keys mentions-data)))
|
|
49
|
+
mentions)]
|
|
50
|
+
{:mentions mentions-data
|
|
51
|
+
:locs (-> (rad/layout (roots mentions-data) weights mentions)
|
|
52
|
+
(rad/polar->cartesian 3))}))
|
|
53
|
+
|
|
54
|
+
(defn score [{:keys [locs mentions]}]
|
|
55
|
+
(let [metric (fn [d w] (sqr (- 1 (* d w))))
|
|
56
|
+
score-user (fn [[k {:keys [mentions]}]]
|
|
57
|
+
(if (zero? (count mentions))
|
|
58
|
+
0
|
|
59
|
+
(let [loc (locs k)]
|
|
60
|
+
(reduce (fn [score [ok w]]
|
|
61
|
+
(+ score (metric (dist loc (locs ok)) w)))
|
|
62
|
+
0
|
|
63
|
+
mentions))))]
|
|
64
|
+
(reduce + (map score-user mentions))))
|
|
65
|
+
|
|
66
|
+
(defn permute-swap [{:keys [locs mentions]} t]
|
|
67
|
+
;;first cut - swap
|
|
68
|
+
(let [xys (vec (vals locs))
|
|
69
|
+
swap1 (math/randomInt (count xys))
|
|
70
|
+
swap2 (math/randomInt (count xys))
|
|
71
|
+
temp (xys swap1)
|
|
72
|
+
xys (assoc xys swap1 (xys swap2))
|
|
73
|
+
xys (assoc xys swap2 temp)]
|
|
74
|
+
{:locs (zipmap (keys locs) xys)
|
|
75
|
+
:mentions mentions}))
|
|
76
|
+
|
|
77
|
+
(defn permute-move [{:keys [locs mentions]} t]
|
|
78
|
+
(let [adj #(min 1.0 (max 0 (+ % (- (* (ann/random) 0.1) 0.05))))
|
|
79
|
+
move (fn [{:keys [x y] :as loc}]
|
|
80
|
+
(if true ;;(> (ann/random) 0.8)
|
|
81
|
+
{:x (adj x)
|
|
82
|
+
:y (adj y)}
|
|
83
|
+
loc))
|
|
84
|
+
xys (vec (vals locs))]
|
|
85
|
+
{:locs (zipmap (keys locs) (map move (vals locs)))
|
|
86
|
+
:mentions mentions}))
|
|
87
|
+
|
|
88
|
+
(comment
|
|
89
|
+
(def test-data {})
|
|
90
|
+
|
|
91
|
+
(def init (init-state test-data))
|
|
92
|
+
|
|
93
|
+
(map (fn [x] {:best-score (:best-score x) :t (:t x)})
|
|
94
|
+
(take 10 (take-nth 100
|
|
95
|
+
(ann/anneal score
|
|
96
|
+
(ann/linear-cooling 1000)
|
|
97
|
+
permute-move
|
|
98
|
+
ann/standard-prob
|
|
99
|
+
init))))
|
|
100
|
+
)
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
; Copyright (c) Rich Hickey. All rights reserved.
|
|
2
|
+
; The use and distribution terms for this software are covered by the
|
|
3
|
+
; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
|
|
4
|
+
; which can be found in the file epl-v10.html at the root of this distribution.
|
|
5
|
+
; By using this software in any fashion, you are agreeing to be bound by
|
|
6
|
+
; the terms of this license.
|
|
7
|
+
; You must not remove this notice, or any other, from this software.
|
|
8
|
+
|
|
9
|
+
(ns twitterbuzz.leaderboard
|
|
10
|
+
(:require [twitterbuzz.core :as buzz]
|
|
11
|
+
[twitterbuzz.dom-helpers :as dom]))
|
|
12
|
+
|
|
13
|
+
(defn leaderboard-element
|
|
14
|
+
"Create a leaderboard element from a user map."
|
|
15
|
+
[user]
|
|
16
|
+
(dom/build [:div.tweet
|
|
17
|
+
[:img.profile-pic {:src (:image-url user)}]
|
|
18
|
+
[:div.tweet-details
|
|
19
|
+
[:div.user-name (:username user)]
|
|
20
|
+
[:div.tweet-text (dom/html (buzz/markup (:last-tweet user)))]
|
|
21
|
+
[:div (str (buzz/num-mentions user))]]]))
|
|
22
|
+
|
|
23
|
+
(defn leaders
|
|
24
|
+
"Given a map of users, return a sequence of users in order of the
|
|
25
|
+
greatest to least number of mentions."
|
|
26
|
+
[nodes]
|
|
27
|
+
(reverse (sort-by #(buzz/num-mentions (second %)) nodes)))
|
|
28
|
+
|
|
29
|
+
(defn update-leaderboard
|
|
30
|
+
"Put the top 5 mentioned users in the leaderboard."
|
|
31
|
+
[graph]
|
|
32
|
+
(do (dom/remove-children :leaderboard-content)
|
|
33
|
+
(doseq [next-node (take 5 (leaders (seq graph)))]
|
|
34
|
+
(dom/append (dom/get-element :leaderboard-content)
|
|
35
|
+
(leaderboard-element (second next-node))))))
|
|
36
|
+
|
|
37
|
+
;; Register event listeners.
|
|
38
|
+
|
|
39
|
+
(buzz/register :track-clicked #(dom/remove-children :leaderboard-content))
|
|
40
|
+
(buzz/register :graph-update update-leaderboard)
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
; Copyright (c) Rich Hickey. All rights reserved.
|
|
2
|
+
; The use and distribution terms for this software are covered by the
|
|
3
|
+
; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
|
|
4
|
+
; which can be found in the file epl-v10.html at the root of this distribution.
|
|
5
|
+
; By using this software in any fashion, you are agreeing to be bound by
|
|
6
|
+
; the terms of this license.
|
|
7
|
+
; You must not remove this notice, or any other, from this software.
|
|
8
|
+
|
|
9
|
+
(ns twitterbuzz.radial
|
|
10
|
+
(:require [clojure.set :as set]
|
|
11
|
+
[goog.math :as math]))
|
|
12
|
+
|
|
13
|
+
(defn get-mentions
|
|
14
|
+
"Returns the set of mentions for k in mentions-data"
|
|
15
|
+
[mentions-data k]
|
|
16
|
+
(-> (get-in mentions-data [k :mentions])
|
|
17
|
+
keys
|
|
18
|
+
set))
|
|
19
|
+
|
|
20
|
+
(defn get-descendants
|
|
21
|
+
"Given child-fn (a map of parent to child), and k, return the
|
|
22
|
+
set of all k's descendants. Set includes k."
|
|
23
|
+
[child-fn k]
|
|
24
|
+
(loop [kids #{k}
|
|
25
|
+
check #{k}]
|
|
26
|
+
(let [[c] (seq check)]
|
|
27
|
+
(if c
|
|
28
|
+
(recur (into kids (child-fn c))
|
|
29
|
+
(into (disj check c) (remove kids (child-fn c))))
|
|
30
|
+
kids))))
|
|
31
|
+
|
|
32
|
+
(defn weight
|
|
33
|
+
"Weight of noce, given child-fn (mapping of node to set
|
|
34
|
+
of kids)."
|
|
35
|
+
[node child-fn]
|
|
36
|
+
(if-let [kids (seq (child-fn node))]
|
|
37
|
+
(reduce + (map #(weight % child-fn) kids))
|
|
38
|
+
1))
|
|
39
|
+
|
|
40
|
+
(defn weights
|
|
41
|
+
"Return a map of node to its weight,
|
|
42
|
+
using child-fn to get the set of children for a node."
|
|
43
|
+
[nodes child-fn]
|
|
44
|
+
(reduce
|
|
45
|
+
(fn [m n] (assoc m n (weight n child-fn)))
|
|
46
|
+
{}
|
|
47
|
+
nodes))
|
|
48
|
+
|
|
49
|
+
(defn layout
|
|
50
|
+
"Returns a map of node => :radius, :slice, :angle.
|
|
51
|
+
|
|
52
|
+
weight-fn: one arg fn of node returning weight
|
|
53
|
+
child-fn: one arg fn of node returning set of nodes"
|
|
54
|
+
([nodes weight-fn child-fn]
|
|
55
|
+
(layout nodes weight-fn child-fn 1 0 360 #{}))
|
|
56
|
+
([nodes weight-fn child-fn radius a1 a2 seen]
|
|
57
|
+
(let [slice (- a2 a1)
|
|
58
|
+
total-weight (reduce + (map #(or (weight-fn %)
|
|
59
|
+
(throw (str "No weight for " %))) nodes))
|
|
60
|
+
seen (into seen nodes)]
|
|
61
|
+
(loop [m {}
|
|
62
|
+
c1 a1
|
|
63
|
+
[node & more] (seq nodes)]
|
|
64
|
+
(if node
|
|
65
|
+
(let [s (* slice (/ (weight-fn node) total-weight))
|
|
66
|
+
c2 (+ c1 s)]
|
|
67
|
+
(recur
|
|
68
|
+
(merge
|
|
69
|
+
m
|
|
70
|
+
{node {:radius radius :slice s :angle (/ (+ c1 c2) 2)}}
|
|
71
|
+
(when-let [children (seq (remove seen (child-fn node)))]
|
|
72
|
+
(layout children weight-fn child-fn (inc radius) c1 c2 seen)))
|
|
73
|
+
c2
|
|
74
|
+
more))
|
|
75
|
+
m)))))
|
|
76
|
+
|
|
77
|
+
(defn polar->cartesian
|
|
78
|
+
"Convert polar coordinates (from layout) into
|
|
79
|
+
cartesian coordinates on the unit square, assuming the
|
|
80
|
+
square will display max-rings rings."
|
|
81
|
+
[polar-map max-rings]
|
|
82
|
+
(reduce
|
|
83
|
+
(fn [m [k {:keys [radius angle]}]]
|
|
84
|
+
(let [r (/ radius (+ 0.5 max-rings) 2)]
|
|
85
|
+
(assoc m k {:x (+ 0.5 (math/angleDx angle r))
|
|
86
|
+
:y (+ 0.5 (math/angleDy angle r))})))
|
|
87
|
+
{}
|
|
88
|
+
polar-map))
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
; Copyright (c) Rich Hickey. All rights reserved.
|
|
2
|
+
; The use and distribution terms for this software are covered by the
|
|
3
|
+
; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
|
|
4
|
+
; which can be found in the file epl-v10.html at the root of this distribution.
|
|
5
|
+
; By using this software in any fashion, you are agreeing to be bound by
|
|
6
|
+
; the terms of this license.
|
|
7
|
+
; You must not remove this notice, or any other, from this software.
|
|
8
|
+
|
|
9
|
+
(ns twitterbuzz.showgraph
|
|
10
|
+
(:require [twitterbuzz.core :as buzz]
|
|
11
|
+
[twitterbuzz.layout :as layout]
|
|
12
|
+
[twitterbuzz.dom-helpers :as dom]
|
|
13
|
+
[twitterbuzz.timeline :as timeline]
|
|
14
|
+
[goog.events :as events]
|
|
15
|
+
[goog.style :as style]
|
|
16
|
+
[goog.math.Coordinate :as Coordinate]
|
|
17
|
+
[goog.ui.HoverCard :as HoverCard]
|
|
18
|
+
[goog.graphics.Font :as Font]
|
|
19
|
+
[goog.graphics.Stroke :as Stroke]
|
|
20
|
+
[goog.graphics.SolidFill :as SolidFill]
|
|
21
|
+
[goog.graphics :as graphics]))
|
|
22
|
+
|
|
23
|
+
; Drawing configuration
|
|
24
|
+
(def avatar-size 32) ; used for both x and y dimensions of avatars
|
|
25
|
+
; fail whale
|
|
26
|
+
;(def default-avatar "http://farm3.static.flickr.com/2562/4140195522_e207b97280_s.jpg")
|
|
27
|
+
; google+ silhouette
|
|
28
|
+
(def default-avatar "http://ssl.gstatic.com/s2/profiles/images/silhouette48.png")
|
|
29
|
+
(defn debug [_])
|
|
30
|
+
;(defn debug [a] (str "t: " (:t a) " score: " (:best-score a)))
|
|
31
|
+
|
|
32
|
+
; BAD HACK: don't change globals like this -- find a better way:
|
|
33
|
+
;(set! anim/TIMEOUT 500)
|
|
34
|
+
|
|
35
|
+
(def edge-stroke (graphics/Stroke. 1 "#009"))
|
|
36
|
+
|
|
37
|
+
(def g
|
|
38
|
+
(doto (graphics/createGraphics "100%" "100%")
|
|
39
|
+
(.render (dom/get-element :network))))
|
|
40
|
+
|
|
41
|
+
(def font (graphics/Font. 12 "Arial"))
|
|
42
|
+
(def fill (graphics/SolidFill. "#f00"))
|
|
43
|
+
|
|
44
|
+
(defn unit-to-pixel [unit-arg canvas-size]
|
|
45
|
+
(+ (* unit-arg (- canvas-size avatar-size)) (/ avatar-size 2)))
|
|
46
|
+
|
|
47
|
+
(defn log [& args]
|
|
48
|
+
(js/console.log (apply pr-str args)))
|
|
49
|
+
|
|
50
|
+
(def avatar-hover
|
|
51
|
+
(doto
|
|
52
|
+
(goog.ui/HoverCard. (js-obj)) ; svg IMAGE tags don't work here
|
|
53
|
+
(.setElement (dom/get-element :avatar-hover))))
|
|
54
|
+
|
|
55
|
+
(defn hide-tooltip [event]
|
|
56
|
+
(.setVisible avatar-hover false))
|
|
57
|
+
|
|
58
|
+
(defn attach-tooltip [img canvas-offset px py tweet]
|
|
59
|
+
(events/listen img events/EventType.MOUSEOUT hide-tooltip)
|
|
60
|
+
(events/listen
|
|
61
|
+
img events/EventType.MOUSEOVER
|
|
62
|
+
(fn [event]
|
|
63
|
+
(hide-tooltip event)
|
|
64
|
+
(.setPosition avatar-hover
|
|
65
|
+
(goog.ui/Tooltip.CursorTooltipPosition.
|
|
66
|
+
(Coordinate/sum (goog.math/Coordinate. px py)
|
|
67
|
+
canvas-offset)))
|
|
68
|
+
(dom/remove-children :avatar-hover-body)
|
|
69
|
+
(dom/append (dom/get-element :avatar-hover-body)
|
|
70
|
+
(timeline/timeline-element tweet))
|
|
71
|
+
(.triggerForElement avatar-hover img))))
|
|
72
|
+
|
|
73
|
+
(defn draw-graph [{:keys [locs mentions]} text]
|
|
74
|
+
(let [canvas-size (. g (getPixelSize))
|
|
75
|
+
canvas-offset (style/getPageOffset (dom/get-element :network))]
|
|
76
|
+
(. g (clear))
|
|
77
|
+
|
|
78
|
+
; Draw mention edges
|
|
79
|
+
(doseq [[username {ux1 :x, uy1 :y}] locs
|
|
80
|
+
:let [x1 (unit-to-pixel ux1 (.-width canvas-size))
|
|
81
|
+
y1 (unit-to-pixel uy1 (.-height canvas-size))]
|
|
82
|
+
[mention-name mention-count] (:mentions (get mentions username))]
|
|
83
|
+
(when-let [{ux2 :x, uy2 :y} (get locs mention-name)]
|
|
84
|
+
(let [x2 (unit-to-pixel ux2 (.-width canvas-size))
|
|
85
|
+
y2 (unit-to-pixel uy2 (.-height canvas-size))]
|
|
86
|
+
(.drawPath g
|
|
87
|
+
(-> (. g (createPath)) (.moveTo x1 y1) (.lineTo x2 y2))
|
|
88
|
+
edge-stroke nil))))
|
|
89
|
+
|
|
90
|
+
; Draw avatar nodes
|
|
91
|
+
(doseq [[username {:keys [x y] :as foo}] locs]
|
|
92
|
+
;(log (pr-str foo))
|
|
93
|
+
(let [px (- (unit-to-pixel x (.-width canvas-size)) (/ avatar-size 2))
|
|
94
|
+
py (- (unit-to-pixel y (.-height canvas-size)) (/ avatar-size 2))
|
|
95
|
+
user (get mentions username)
|
|
96
|
+
image-url (get user :image-url default-avatar)
|
|
97
|
+
img (.drawImage g px py avatar-size avatar-size image-url)]
|
|
98
|
+
(attach-tooltip img canvas-offset px py
|
|
99
|
+
{:profile_image_url image-url
|
|
100
|
+
:text (:last-tweet user)
|
|
101
|
+
:from_user (:username user)})))
|
|
102
|
+
|
|
103
|
+
(let [text (if (empty? locs)
|
|
104
|
+
"No locations to graph"
|
|
105
|
+
text)]
|
|
106
|
+
(when text
|
|
107
|
+
(.drawTextOnLine g text 5 20 (.-width canvas-size) 20
|
|
108
|
+
"left" font nil fill)))))
|
|
109
|
+
|
|
110
|
+
(def graph-data (atom nil))
|
|
111
|
+
|
|
112
|
+
;; Register event listeners.
|
|
113
|
+
|
|
114
|
+
(buzz/register :graph-update
|
|
115
|
+
(fn [data]
|
|
116
|
+
(reset! graph-data data)
|
|
117
|
+
(draw-graph (layout/radial data) nil)))
|
|
118
|
+
|
|
119
|
+
(events/listen (dom/get-element :network) events/EventType.CLICK
|
|
120
|
+
#(draw-graph (layout/radial @graph-data) nil))
|
|
121
|
+
(buzz/register :track-clicked #(. g (clear)))
|