clementine 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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,80 @@
1
+ <!doctype html>
2
+ <!--[if lt IE 7 ]> <html lang="en" class="no-js ie6"> <![endif]-->
3
+ <!--[if IE 7 ]> <html lang="en" class="no-js ie7"> <![endif]-->
4
+ <!--[if IE 8 ]> <html lang="en" class="no-js ie8"> <![endif]-->
5
+ <!--[if IE 9 ]> <html lang="en" class="no-js ie9"> <![endif]-->
6
+ <!--[if (gt IE 9)|!(IE)]><!--> <html lang="en" class="no-js"> <!--<![endif]-->
7
+ <head>
8
+ <meta charset="UTF-8">
9
+ <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
10
+
11
+ <title>TwitterBuzz: A ClojureScript Demo</title>
12
+ <meta name="description" content="Demo showing off the ClojureScript hotness">
13
+ <meta name="author" content="Clojure/core">
14
+
15
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
16
+
17
+ <link rel="apple-touch-icon" href="/apple-touch-icon.png">
18
+ <link rel="stylesheet" href="reset.css">
19
+ <link rel="stylesheet" href="style.css">
20
+
21
+ <!--[if lt IE 9]>
22
+ <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
23
+ <![endif]-->
24
+
25
+ </head>
26
+ <body>
27
+ <header>
28
+ <section id="header-inner">
29
+ <h1>TwitterBuzz: A ClojureScript Demo</h1>
30
+ <div>Learn more:
31
+ <a href="https://github.com/clojure/clojurescript" target="_clojurescript">ClojureScript</a> |
32
+ <a href="https://github.com/clojure/clojurescript/wiki" target="_clojurescript">Documentation</a> |
33
+ <a href="https://github.com/clojure/clojurescript/tree/master/samples/twitterbuzz"
34
+ target="_clojurescript">Source Code</a>
35
+ </div>
36
+ <h2 id="clojure"><img src="http://clojure.org/space/showimage/clojure-icon-50x50.png" width="50" height="50" alt="Clojure"></h2>
37
+ </section>
38
+ </header>
39
+
40
+ <section id="status-bar-wrap">
41
+ <section id="status-bar">
42
+ <input id="twitter-search-tag" value="" type="text" class="search" results="5" autosave="clojure" placeholder="Enter keywords..." autofocus />
43
+ <button id="twitter-search-button" type="submit" class="button green">Track</button>
44
+ <span id="tweet-status" class="tweet-status">Not Connected</span>
45
+ </section>
46
+ </section>
47
+
48
+ <section id="main-wrap">
49
+ <section id="main">
50
+
51
+ <section id="network">
52
+ </section>
53
+
54
+ <section id="leaderboard">
55
+ <h2>Leaderboard</h2>
56
+ <div id="leaderboard-content">
57
+ </div>
58
+ </section>
59
+
60
+ <section id="timeline" class="tweetbox">
61
+ <h2>Timeline</h2>
62
+ <div id="timeline-content">
63
+ </div>
64
+ </section>
65
+
66
+ <div class="clear"></div>
67
+ </section>
68
+
69
+ <div class="clear"></div>
70
+ </section>
71
+
72
+ <section id="avatar-hover" style="display: none">
73
+ <div id="avatar-hover-body" class="tweetbox"></div>
74
+ </section>
75
+
76
+ <script type="text/javascript" src="twitterbuzz.js"></script>
77
+
78
+ </body>
79
+ </html>
80
+
@@ -0,0 +1,88 @@
1
+ <!doctype html>
2
+ <!--[if lt IE 7 ]> <html lang="en" class="no-js ie6"> <![endif]-->
3
+ <!--[if IE 7 ]> <html lang="en" class="no-js ie7"> <![endif]-->
4
+ <!--[if IE 8 ]> <html lang="en" class="no-js ie8"> <![endif]-->
5
+ <!--[if IE 9 ]> <html lang="en" class="no-js ie9"> <![endif]-->
6
+ <!--[if (gt IE 9)|!(IE)]><!--> <html lang="en" class="no-js"> <!--<![endif]-->
7
+ <head>
8
+ <meta charset="UTF-8">
9
+ <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
10
+
11
+ <title>TwitterBuzz: A ClojureScript Demo</title>
12
+ <meta name="description" content="Demo showing off the ClojureScript hotness">
13
+ <meta name="author" content="Clojure/core">
14
+
15
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
16
+
17
+ <link rel="apple-touch-icon" href="/apple-touch-icon.png">
18
+ <link rel="stylesheet" href="reset.css">
19
+ <link rel="stylesheet" href="style.css">
20
+
21
+ <!--[if lt IE 9]>
22
+ <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
23
+ <![endif]-->
24
+
25
+ </head>
26
+ <body>
27
+ <header>
28
+ <section id="header-inner">
29
+ <h1>TwitterBuzz: A ClojureScript Demo</h1>
30
+ <div>Learn more:
31
+ <a href="https://github.com/clojure/clojurescript" target="_clojurescript">ClojureScript</a> |
32
+ <a href="https://github.com/clojure/clojurescript/wiki" target="_clojurescript">Documentation</a> |
33
+ <a href="https://github.com/clojure/clojurescript/tree/master/samples/twitterbuzz"
34
+ target="_clojurescript">Source Code</a>
35
+ </div>
36
+ <h2 id="clojure"><img src="http://clojure.org/space/showimage/clojure-icon-50x50.png" width="50" height="50" alt="Clojure"></h2>
37
+ </section>
38
+ </header>
39
+
40
+ <section id="status-bar-wrap">
41
+ <section id="status-bar">
42
+ <input id="twitter-search-tag" value="" type="text" class="search" results="5" autosave="clojure" placeholder="Enter keywords..." autofocus />
43
+ <button id="twitter-search-button" type="submit" class="button green">Track</button>
44
+ <span id="tweet-status">Not Connected</span>
45
+ </section>
46
+ </section>
47
+
48
+ <section id="main-wrap">
49
+ <section id="main">
50
+
51
+ <section id="network">
52
+ </section>
53
+
54
+ <section id="leaderboard">
55
+ <h2>Leaderboard</h2>
56
+ <div id="leaderboard-content">
57
+ </div>
58
+ </section>
59
+
60
+ <section id="timeline" class="tweetbox">
61
+ <h2>Timeline</h2>
62
+ <div id="timeline-content">
63
+ </div>
64
+ </section>
65
+
66
+ <div class="clear"></div>
67
+ </section>
68
+
69
+ <div class="clear"></div>
70
+ </section>
71
+
72
+ <section id="avatar-hover" style="display: none">
73
+ <div id="avatar-hover-body" class="tweetbox"></div>
74
+ </section>
75
+
76
+ <!-- In unoptimized mode, additional script tags are required -->
77
+ <script type="text/javascript" src="out/goog/base.js"></script>
78
+ <script type="text/javascript" src="twitterbuzz.js"></script>
79
+ <script type="text/javascript">
80
+ goog.require('twitterbuzz.core');
81
+ goog.require('twitterbuzz.timeline');
82
+ goog.require('twitterbuzz.leaderboard');
83
+ goog.require('twitterbuzz.showgraph');
84
+ </script>
85
+
86
+ </body>
87
+ </html>
88
+
@@ -0,0 +1,48 @@
1
+ /* Eric Meyer's Reset Reloaded */
2
+ html, body, div, span, applet, object, iframe,
3
+ h1, h2, h3, h4, h5, h6, p, blockquote, pre,
4
+ a, abbr, acronym, address, big, cite, code,
5
+ del, dfn, em, font, img, ins, kbd, q, s, samp,
6
+ small, strike, strong, sub, sup, tt, var,
7
+ dl, dt, dd, ol, ul, li,
8
+ fieldset, form, label, legend,
9
+ table, caption, tbody, tfoot, thead, tr, th, td {
10
+ margin: 0;
11
+ padding: 0;
12
+ border: 0;
13
+ outline: 0;
14
+ font-weight: inherit;
15
+ font-style: inherit;
16
+ font-size: 100%;
17
+ font-family: inherit;
18
+ vertical-align: baseline;
19
+ }
20
+ /* remember to define focus styles! */
21
+ :focus {
22
+ outline: 0;
23
+ }
24
+ body {
25
+ line-height: 1;
26
+ color: black;
27
+ background: white;
28
+ }
29
+ ol, ul {
30
+ list-style: none;
31
+ }
32
+ /* tables still need 'cellspacing="0"' in the markup */
33
+ table {
34
+ border-collapse: separate;
35
+ border-spacing: 0;
36
+ }
37
+ caption, th, td {
38
+ text-align: left;
39
+ font-weight: normal;
40
+ }
41
+ blockquote:before, blockquote:after,
42
+ q:before, q:after {
43
+ content: "";
44
+ }
45
+ blockquote, q {
46
+ quotes: "" "";
47
+ }
48
+
@@ -0,0 +1,66 @@
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.anneal)
10
+
11
+ (defn exp [x]
12
+ (js/Math.exp x))
13
+
14
+ (defn abs [x]
15
+ (js/Math.abs x))
16
+
17
+ (defn random []
18
+ (js/Math.random))
19
+
20
+ (defn standard-prob [e e1 temp]
21
+ (if (< e1 e)
22
+ 1
23
+ (exp (/ (- e e1) temp))))
24
+
25
+ (defn linear-cooling [steps]
26
+ (let [min (- 1 (/ steps (dec steps)))]
27
+ (fn [t]
28
+ (max min (- 1 (/ t steps))))))
29
+
30
+ (defn anneal
31
+ "Given an energy scoring function, a temperature function
32
+ (calculates temp given iteration t), a permutation function (creates
33
+ a candidate next state given a current state and iteration t), and
34
+ an acceptance probability function (of last next energy and temp),
35
+ yields a lazy seq of (accepted?) states of the form
36
+ {:state s :score :best best :best-score :t t}"
37
+
38
+ [energy ;;(energy state) -> score
39
+ temp ;;(temp t) -> 0-1.0
40
+ permute ;;(permute state t) -> new-state
41
+ prob ;;(prob e e1 temp) -> 0-1.0
42
+ state]
43
+
44
+ (let [init state
45
+ init-score (energy state)
46
+ step (fn step [{:keys [state score best best-score t]:as ret}]
47
+ (loop [next (permute state) t (inc t)]
48
+ (let [next-score (energy next)]
49
+ (if (> (prob score next-score (temp t)) (random))
50
+ (let [ret {:state next :score next-score :t t
51
+ :best (if (< next-score best-score) next best)
52
+ :best-score (min next-score best-score)}]
53
+ (lazy-seq (cons ret (step ret))))
54
+ (recur (permute state) (inc t))))))]
55
+ (step {:state init :score init-score :best init :best-score init-score :t 0})))
56
+
57
+
58
+ (comment
59
+
60
+ (take 10 (take-nth 100
61
+ (anneal #(abs (- % 42))
62
+ (linear-cooling 1000)
63
+ (fn [s _] (+ s (- (random) 0.5)))
64
+ standard-prob
65
+ 55)))
66
+ )
@@ -0,0 +1,307 @@
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.core
10
+ (:require [twitterbuzz.dom-helpers :as dom]
11
+ [clojure.string :as string]
12
+ [goog.string :as gstring]
13
+ [goog.net.Jsonp :as jsonp]
14
+ [goog.Timer :as timer]
15
+ [goog.events :as events]
16
+ [goog.events.EventType :as event-type]
17
+ [goog.dom.classes :as classes]))
18
+
19
+ (def results-per-page 100)
20
+ (def max-missing-query 20)
21
+
22
+ (def initial-state {:max-id 0
23
+ :graph {}
24
+ :listeners {}
25
+ :tweet-count 0
26
+ :search-tag nil
27
+ :ignore-mentions #{}})
28
+
29
+ (def state (atom initial-state))
30
+
31
+ (defn add-listener
32
+ "Add a listener to the graph."
33
+ [graph k f]
34
+ (let [l (-> graph :listeners k)]
35
+ (assoc-in graph [:listeners k] (conj l f))))
36
+
37
+ (defn register
38
+ "Register a function to be called when new data arrives specifying
39
+ the event to receive updates for."
40
+ [event f]
41
+ (swap! state add-listener event f))
42
+
43
+ (def twitter-uri (goog.Uri. "http://search.twitter.com/search.json"))
44
+
45
+ (defn search-tag
46
+ "Get the current tag value from the page."
47
+ []
48
+ (.-value (dom/get-element :twitter-search-tag)))
49
+
50
+ (defn retrieve
51
+ "Send request to twitter."
52
+ [payload callback error-callback]
53
+ (.send (goog.net.Jsonp. twitter-uri)
54
+ payload
55
+ callback
56
+ error-callback))
57
+
58
+ (defn send-event
59
+ "For the given event, call every listener for that event, passing the
60
+ message."
61
+ ([event]
62
+ (send-event event nil))
63
+ ([event message]
64
+ (doseq [f (-> @state :listeners event)]
65
+ (f message))))
66
+
67
+ (defn parse-mentions
68
+ "Given a map representing a single tweet, return all mentions that
69
+ are found within the tweet text. Twitter usernames are not case
70
+ sensitive so mentioned usernames are always returned in lower case."
71
+ [tweet]
72
+ (map #(string/lower-case (apply str (drop 1 %)))
73
+ (re-seq (re-pattern "@\\w+") (:text tweet))))
74
+
75
+ (defn add-mentions
76
+ "Add the user to the mentions map for first user she mentions,
77
+ clearing the mentions map of user."
78
+ [graph user mentions]
79
+ (if-let [mention (first mentions)]
80
+ (let [graph (assoc graph mention (get graph mention {:username mention}))
81
+ node (get graph mention)
82
+ mentions-map (get node :mentions {})
83
+ graph (assoc-in graph [mention :mentions user] (inc (get mentions-map user 0)))]
84
+ (assoc-in graph [user :mentions] {}))
85
+ graph))
86
+
87
+ (defn update-graph
88
+ "Given a graph and a sequence of new tweets in chronological order,
89
+ update the graph."
90
+ [graph tweet-maps]
91
+ (reduce (fn [acc tweet]
92
+ (let [user (string/lower-case (:from_user tweet))
93
+ mentions (parse-mentions tweet)
94
+ node (get acc user {:mentions {}})]
95
+ (-> (assoc acc user
96
+ (assoc node :last-tweet (:text tweet)
97
+ :image-url (:profile_image_url tweet)
98
+ :username (:from_user tweet)))
99
+ (add-mentions user mentions))))
100
+ graph
101
+ (map #(select-keys % [:text :from_user :profile_image_url]) tweet-maps)))
102
+
103
+ (defn num-mentions [user]
104
+ (reduce + (vals (:mentions user))))
105
+
106
+ (defn update-state
107
+ "Given an old state, maximum id and a new sequence of tweets, return
108
+ an updated state."
109
+ [old-state max-id tweets]
110
+ (-> old-state
111
+ (assoc :max-id max-id)
112
+ (update-in [:tweet-count] #(+ % (count tweets)))
113
+ (assoc :graph (update-graph (:graph old-state) (reverse tweets)))))
114
+
115
+ (defn new-tweets [max-id tweets]
116
+ (filter #(> (:id %) max-id) tweets))
117
+
118
+ (defn new-tweets-callback
119
+ "Given a json object, update the state with any new information and
120
+ fire events."
121
+ [json]
122
+ (let [{:keys [max_id results]} (js->clj json :keywordize-keys true)
123
+ tweets (new-tweets (:max-id @state) results)]
124
+ (do (swap! state update-state max_id tweets)
125
+ (send-event :new-tweets tweets)
126
+ (send-event :graph-update (:graph @state)))))
127
+
128
+ (defn set-tweet-status [css-class message]
129
+ (doto (dom/set-text :tweet-status message)
130
+ (classes/set (name css-class))))
131
+
132
+ (defn error-callback [error]
133
+ (set-tweet-status :error "Twitter error"))
134
+
135
+ (defn add-missing-tweets
136
+ "Add missing data to the graph."
137
+ [graph tweets]
138
+ (let [new-tweets (reduce (fn [acc next-tweet]
139
+ (assoc acc (string/lower-case (:from_user next-tweet))
140
+ next-tweet))
141
+ {}
142
+ (sort-by :id tweets))]
143
+ (reduce (fn [acc [node-name {:keys [from_user text profile_image_url]}]]
144
+ (if-let [old-tweet (get graph node-name)]
145
+ (if (:last-tweet old-tweet)
146
+ acc
147
+ (assoc acc node-name
148
+ (merge old-tweet {:last-tweet text
149
+ :image-url profile_image_url
150
+ :username from_user})))
151
+ acc))
152
+ graph
153
+ new-tweets)))
154
+
155
+ (defn ignored
156
+ "Given a list of the usernames for missing tweets and the tweets
157
+ which are the result of a query for this missing data, return a set of
158
+ twitter usernames which will be ignored moving forward.
159
+
160
+ Names may be ignored because the twitter user does not exist or
161
+ just doesn't tweet."
162
+ [missing tweets]
163
+ (when (< (count tweets) results-per-page)
164
+ (let [users (set (map #(string/lower-case (:from_user %)) tweets))
165
+ missing (map string/lower-case missing)]
166
+ (reduce (fn [acc next-missing]
167
+ (if (contains? users next-missing)
168
+ acc
169
+ (conj acc next-missing)))
170
+ #{}
171
+ missing))))
172
+
173
+ (defn add-missing-callback
174
+ "Update the graph and the ignore-mentions list when data is received
175
+ from a missing user query."
176
+ [missing json]
177
+ (let [response (js->clj json :keywordize-keys true)
178
+ tweets (:results response)]
179
+ (if-let [error (:error response)]
180
+ (set-tweet-status :error error)
181
+ (do (swap! state (fn [old-state]
182
+ (assoc old-state
183
+ :graph (add-missing-tweets (:graph old-state) tweets)
184
+ :ignore-mentions (into (:ignore-mentions old-state)
185
+ (ignored missing tweets)))))
186
+ (send-event :new-tweets [])
187
+ (send-event :graph-update (:graph @state))))))
188
+
189
+ (defn missing-tweets
190
+ "Return a list of usernames with missing tweets in the graph."
191
+ [graph]
192
+ (->> (map second graph)
193
+ (remove :last-tweet)
194
+ (map :username)
195
+ (remove empty?)
196
+ (remove (:ignore-mentions @state))))
197
+
198
+ (defn fetch-mentioned-tweets
199
+ "Query twitter for usernames which are currently missing data in the
200
+ graph. Limit this query to max-missing-query names."
201
+ [missing]
202
+ (let [q (apply str (interpose " OR " (map #(str "from:" %)
203
+ (take max-missing-query missing))))]
204
+ (set-tweet-status :okay "Fetching mentioned tweets")
205
+ (retrieve (doto (js-obj)
206
+ (aset "q" q)
207
+ (aset "rpp" results-per-page))
208
+ #(add-missing-callback missing %)
209
+ error-callback)))
210
+
211
+ (defn fetch-new-tweets
212
+ "Use the current search tag to fetch new tweets from twitter."
213
+ []
214
+ (when-let [tag (:search-tag @state)]
215
+ (set-tweet-status :okay "Fetching tweets")
216
+ (retrieve (doto (js-obj)
217
+ (aset "q" tag)
218
+ (aset "rpp" results-per-page))
219
+ new-tweets-callback
220
+ error-callback)))
221
+
222
+ (defn fetch-tweets
223
+ "If there are missing tweets then fetch them, if not fetch new tweets."
224
+ []
225
+ (let [missing (missing-tweets (:graph @state))]
226
+ (if (seq missing)
227
+ (fetch-mentioned-tweets missing)
228
+ (fetch-new-tweets))))
229
+
230
+ (defn poll
231
+ "Request new data from twitter once every 24 seconds. This will put
232
+ you at the 150 request/hour rate limit. We can speed it up for the demo."
233
+ []
234
+ (let [timer (goog.Timer. 24000)]
235
+ (do (fetch-tweets)
236
+ (. timer (start))
237
+ (events/listen timer goog.Timer/TICK fetch-tweets))))
238
+
239
+ (defn do-track-button-clicked
240
+ "When the track button is clicked, reset to the initial state
241
+ keeping only the event listeners."
242
+ []
243
+ (do (let [listeners (:listeners @state)]
244
+ (reset! state (assoc initial-state :listeners listeners :search-tag (search-tag))))
245
+ (fetch-tweets)
246
+ (send-event :track-clicked)))
247
+
248
+ (defn start-app
249
+ "Start polling and listen for UI events."
250
+ []
251
+ (do (poll)
252
+ (events/listen (dom/get-element :twitter-search-button)
253
+ "click"
254
+ do-track-button-clicked)
255
+ (events/listen (dom/get-element :twitter-search-tag)
256
+ event-type/CHANGE
257
+ do-track-button-clicked)))
258
+
259
+ (start-app)
260
+
261
+ (defn link [url s]
262
+ (str "<a href='" url "' target='_twitterbuzz'>" s "</a>"))
263
+
264
+ (defn markup
265
+ "Add markup to tweet text to activate links."
266
+ [s]
267
+ (let [markup-f (fn [s] (let [w (string/trim s)]
268
+ (cond (gstring/startsWith w "http://")
269
+ (link w w)
270
+ (gstring/startsWith w "@")
271
+ (link (str "http://twitter.com/#!/" (re-find #"\w+" w)) w)
272
+ :else s)))]
273
+ (string/join " " (map markup-f (string/split s #"[ ]")))))
274
+
275
+ (comment
276
+
277
+ (parse-mentions {:text "What's up @sue: and @Larry"})
278
+
279
+ (add-mentions {} "jim" ["sue"])
280
+ (add-mentions {"sue" {}} "jim" ["sue"])
281
+
282
+ (def tweets [{:profile_image_url "url1"
283
+ :from_user "Jim"
284
+ :text "I like cookies!"}
285
+ {:profile_image_url "url2"
286
+ :from_user "sue"
287
+ :text "Me to @jim."}
288
+ {:profile_image_url "url3"
289
+ :from_user "bob"
290
+ :text "You shouldn't eat so many cookies @sue"}
291
+ {:profile_image_url "url4"
292
+ :from_user "sam"
293
+ :text "@Bob that was a cruel thing to say to @Sue."}
294
+ {:profile_image_url "url5"
295
+ :from_user "ted"
296
+ :text "@foo is awesome!"}])
297
+
298
+ (def graph (update-graph {} tweets))
299
+ (count graph)
300
+
301
+ (num-mentions (get graph "sue"))
302
+ (num-mentions (get graph "bob"))
303
+ (num-mentions (get graph "sam"))
304
+
305
+ (take 1 (reverse (sort-by #(num-mentions (second %)) (seq graph))))
306
+
307
+ )