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.
Files changed (139) hide show
  1. data/.gitignore +1 -0
  2. data/Gemfile +4 -2
  3. data/LICENSE.txt +22 -0
  4. data/README.md +11 -6
  5. data/Rakefile +22 -0
  6. data/clementine.gemspec +2 -1
  7. data/ext/clojure-clojurescript-bef56a7/.gitignore +13 -0
  8. data/ext/clojure-clojurescript-bef56a7/Clojurescript.iml +12 -0
  9. data/ext/clojure-clojurescript-bef56a7/README.md +29 -0
  10. data/ext/clojure-clojurescript-bef56a7/benchmark/cljs/benchmark_runner.cljs +155 -0
  11. data/ext/clojure-clojurescript-bef56a7/bin/cljsc +21 -0
  12. data/ext/clojure-clojurescript-bef56a7/bin/cljsc.bat +18 -0
  13. data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/bin/cljsc.clj +0 -0
  14. data/ext/clojure-clojurescript-bef56a7/devnotes/README.org +35 -0
  15. data/ext/clojure-clojurescript-bef56a7/devnotes/bcrepl.org +13 -0
  16. data/ext/clojure-clojurescript-bef56a7/devnotes/cljs.org +500 -0
  17. data/ext/clojure-clojurescript-bef56a7/devnotes/corelib.org +583 -0
  18. data/ext/clojure-clojurescript-bef56a7/devnotes/day1.org +203 -0
  19. data/ext/clojure-clojurescript-bef56a7/devnotes/day2.org +44 -0
  20. data/ext/clojure-clojurescript-bef56a7/devnotes/talk.org +126 -0
  21. data/ext/clojure-clojurescript-bef56a7/devnotes/testing +13 -0
  22. data/ext/clojure-clojurescript-bef56a7/devnotes/todo.org +121 -0
  23. data/ext/clojure-clojurescript-bef56a7/epl-v10.html +261 -0
  24. data/ext/clojure-clojurescript-bef56a7/pom.template.xml +88 -0
  25. data/ext/clojure-clojurescript-bef56a7/samples/dom/.gitignore +2 -0
  26. data/ext/clojure-clojurescript-bef56a7/samples/dom/src/dom/test.cljs +48 -0
  27. data/ext/clojure-clojurescript-bef56a7/samples/dom/test.html +30 -0
  28. data/ext/clojure-clojurescript-bef56a7/samples/hello-js/.gitignore +2 -0
  29. data/ext/clojure-clojurescript-bef56a7/samples/hello-js/README.md +53 -0
  30. data/ext/clojure-clojurescript-bef56a7/samples/hello-js/externed-lib.js +7 -0
  31. data/ext/clojure-clojurescript-bef56a7/samples/hello-js/externs.js +3 -0
  32. data/ext/clojure-clojurescript-bef56a7/samples/hello-js/hello-extern.html +14 -0
  33. data/ext/clojure-clojurescript-bef56a7/samples/hello-js/hello-js-dev.html +18 -0
  34. data/ext/clojure-clojurescript-bef56a7/samples/hello-js/hello-js.html +17 -0
  35. data/ext/clojure-clojurescript-bef56a7/samples/hello-js/my-external-lib.js +3 -0
  36. data/ext/clojure-clojurescript-bef56a7/samples/hello-js/src/hello-js/core.cljs +9 -0
  37. data/ext/clojure-clojurescript-bef56a7/samples/hello-js/src/hello-js/extern-example.cljs +5 -0
  38. data/ext/clojure-clojurescript-bef56a7/samples/hello/.gitignore +2 -0
  39. data/ext/clojure-clojurescript-bef56a7/samples/hello/README.md +34 -0
  40. data/ext/clojure-clojurescript-bef56a7/samples/hello/hello-dev.html +18 -0
  41. data/ext/clojure-clojurescript-bef56a7/samples/hello/hello.html +13 -0
  42. data/ext/clojure-clojurescript-bef56a7/samples/hello/src/hello/core.cljs +8 -0
  43. data/ext/clojure-clojurescript-bef56a7/samples/hello/src/hello/foo/bar.cljs +4 -0
  44. data/ext/clojure-clojurescript-bef56a7/samples/nodehello.cljs +18 -0
  45. data/ext/clojure-clojurescript-bef56a7/samples/nodels.cljs +17 -0
  46. data/ext/clojure-clojurescript-bef56a7/samples/repl/.gitignore +2 -0
  47. data/ext/clojure-clojurescript-bef56a7/samples/repl/README.md +101 -0
  48. data/ext/clojure-clojurescript-bef56a7/samples/repl/index.html +27 -0
  49. data/ext/clojure-clojurescript-bef56a7/samples/repl/src/repl/test.cljs +73 -0
  50. data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/.gitignore +2 -0
  51. data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/README.md +42 -0
  52. data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/index-advanced.html +80 -0
  53. data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/index.html +88 -0
  54. data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/reset.css +48 -0
  55. data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/src/twitterbuzz/anneal.cljs +66 -0
  56. data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/src/twitterbuzz/core.cljs +307 -0
  57. data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/src/twitterbuzz/dom-helpers.cljs +95 -0
  58. data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/src/twitterbuzz/layout.cljs +100 -0
  59. data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/src/twitterbuzz/leaderboard.cljs +40 -0
  60. data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/src/twitterbuzz/radial.cljs +91 -0
  61. data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/src/twitterbuzz/showgraph.cljs +121 -0
  62. data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/src/twitterbuzz/timeline.cljs +39 -0
  63. data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/style.css +301 -0
  64. data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/test_data.txt +1 -0
  65. data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/tweet_maps.txt +1 -0
  66. data/ext/clojure-clojurescript-bef56a7/script/benchmark +30 -0
  67. data/ext/clojure-clojurescript-bef56a7/script/bootstrap +70 -0
  68. data/ext/clojure-clojurescript-bef56a7/script/browser-repl +16 -0
  69. data/ext/clojure-clojurescript-bef56a7/script/build +59 -0
  70. data/ext/clojure-clojurescript-bef56a7/script/clean +5 -0
  71. data/ext/clojure-clojurescript-bef56a7/script/closure-library-release/google-closure-library-third-party.pom.template +59 -0
  72. data/ext/clojure-clojurescript-bef56a7/script/closure-library-release/google-closure-library.pom.template +54 -0
  73. data/ext/clojure-clojurescript-bef56a7/script/closure-library-release/make-closure-library-jars.sh +87 -0
  74. data/ext/clojure-clojurescript-bef56a7/script/compile +41 -0
  75. data/ext/clojure-clojurescript-bef56a7/script/repl +13 -0
  76. data/ext/clojure-clojurescript-bef56a7/script/repl.bat +13 -0
  77. data/ext/clojure-clojurescript-bef56a7/script/repljs +15 -0
  78. data/ext/clojure-clojurescript-bef56a7/script/repljs.bat +14 -0
  79. data/ext/clojure-clojurescript-bef56a7/script/test +38 -0
  80. data/ext/clojure-clojurescript-bef56a7/script/test-compile +30 -0
  81. data/ext/clojure-clojurescript-bef56a7/src/clj/cljs/analyzer.clj +975 -0
  82. data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/clj/cljs/closure.clj +173 -73
  83. data/ext/clojure-clojurescript-bef56a7/src/clj/cljs/compiler.clj +1081 -0
  84. data/ext/clojure-clojurescript-bef56a7/src/clj/cljs/core.clj +1158 -0
  85. data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/clj/cljs/repl.clj +51 -25
  86. data/ext/clojure-clojurescript-bef56a7/src/clj/cljs/repl/browser.clj +258 -0
  87. data/ext/clojure-clojurescript-bef56a7/src/clj/cljs/repl/reflect.clj +75 -0
  88. data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/clj/cljs/repl/rhino.clj +6 -5
  89. data/ext/clojure-clojurescript-bef56a7/src/clj/cljs/repl/server.clj +173 -0
  90. data/ext/clojure-clojurescript-bef56a7/src/clj/cljs/tagged_literals.clj +30 -0
  91. data/ext/clojure-clojurescript-bef56a7/src/cljs/cljs/core.cljs +7197 -0
  92. data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/cljs/cljs/nodejs.cljs +1 -1
  93. data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/cljs/cljs/nodejs_externs.js +0 -0
  94. data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/cljs/cljs/nodejscli.cljs +1 -1
  95. data/ext/clojure-clojurescript-bef56a7/src/cljs/cljs/reader.cljs +551 -0
  96. data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/cljs/clojure/browser/dom.cljs +59 -13
  97. data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/cljs/clojure/browser/event.cljs +0 -0
  98. data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/cljs/clojure/browser/net.cljs +8 -7
  99. data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/cljs/clojure/browser/repl.cljs +2 -2
  100. data/ext/clojure-clojurescript-bef56a7/src/cljs/clojure/core/reducers.cljs +298 -0
  101. data/ext/clojure-clojurescript-bef56a7/src/cljs/clojure/data.cljs +162 -0
  102. data/ext/clojure-clojurescript-bef56a7/src/cljs/clojure/reflect.cljs +48 -0
  103. data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/cljs/clojure/set.cljs +0 -0
  104. data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/cljs/clojure/string.cljs +4 -10
  105. data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/cljs/clojure/walk.cljs +0 -0
  106. data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/cljs/clojure/zip.cljs +0 -0
  107. data/ext/clojure-clojurescript-bef56a7/test/cljs/cljs/binding_test.cljs +7 -0
  108. data/ext/clojure-clojurescript-bef56a7/test/cljs/cljs/binding_test_other_ns.cljs +3 -0
  109. data/ext/clojure-clojurescript-bef56a7/test/cljs/cljs/core_test.cljs +1678 -0
  110. data/ext/clojure-clojurescript-bef56a7/test/cljs/cljs/import_test.cljs +11 -0
  111. data/ext/clojure-clojurescript-bef56a7/test/cljs/cljs/import_test/foo.cljs +5 -0
  112. data/ext/clojure-clojurescript-bef56a7/test/cljs/cljs/letfn_test.cljs +19 -0
  113. data/ext/clojure-clojurescript-bef56a7/test/cljs/cljs/macro_test.cljs +6 -0
  114. data/ext/clojure-clojurescript-bef56a7/test/cljs/cljs/macro_test/macros.clj +5 -0
  115. data/ext/clojure-clojurescript-bef56a7/test/cljs/cljs/ns_test.cljs +14 -0
  116. data/ext/clojure-clojurescript-bef56a7/test/cljs/cljs/ns_test/bar.cljs +3 -0
  117. data/ext/clojure-clojurescript-bef56a7/test/cljs/cljs/ns_test/foo.cljs +7 -0
  118. data/ext/clojure-clojurescript-bef56a7/test/cljs/cljs/reader_test.cljs +124 -0
  119. data/ext/clojure-clojurescript-bef56a7/test/cljs/clojure/data_test.cljs +22 -0
  120. data/ext/clojure-clojurescript-bef56a7/test/cljs/clojure/string_test.cljs +97 -0
  121. data/ext/clojure-clojurescript-bef56a7/test/cljs/foo/ns_shadow_test.cljs +9 -0
  122. data/ext/clojure-clojurescript-bef56a7/test/cljs/test_runner.cljs +26 -0
  123. data/lib/clementine.rb +3 -24
  124. data/lib/clementine/clojurescript_engine.rb +9 -48
  125. data/lib/clementine/clojurescript_engine/base.rb +15 -0
  126. data/lib/clementine/clojurescript_engine/jruby.rb +46 -0
  127. data/lib/clementine/{clojurescript_engine_mri.rb → clojurescript_engine/mri.rb} +17 -10
  128. data/lib/clementine/version.rb +1 -1
  129. data/test/clojurescript_engine_test.rb +36 -14
  130. metadata +177 -83
  131. data/vendor/assets/lib/clojure.jar +0 -0
  132. data/vendor/assets/lib/compiler.jar +0 -0
  133. data/vendor/assets/lib/goog.jar +0 -0
  134. data/vendor/assets/lib/js.jar +0 -0
  135. data/vendor/assets/src/clj/cljs/compiler.clj +0 -1341
  136. data/vendor/assets/src/clj/cljs/core.clj +0 -702
  137. data/vendor/assets/src/clj/cljs/repl/browser.clj +0 -341
  138. data/vendor/assets/src/cljs/cljs/core.cljs +0 -3330
  139. 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)))