Skip to content

Instantly share code, notes, and snippets.

@olaugh
Created September 11, 2014 23:07
Show Gist options
  • Save olaugh/08cc05509f70d9f4ad99 to your computer and use it in GitHub Desktop.
Save olaugh/08cc05509f70d9f4ad99 to your computer and use it in GitHub Desktop.
(use 'clojure.contrib.duck-streams)
(import '(org.eclipse.swt SWT))
(import '(org.eclipse.swt.browser Browser))
(import '(org.eclipse.swt.layout GridData GridLayout))
(import '(org.eclipse.swt.widgets Display Label Shell Text Widget))
(import '(org.eclipse.swt.graphics Font))
(import '(org.eclipse.swt.events ModifyListener VerifyListener))
(def *display* (new Display))
(def *shell* (new Shell *display*))
(def *question-browser* (new Browser *shell* SWT/MOZILLA))
(def *timer-label* (new Text *shell* SWT/CENTER))
(def *answer-text* (new Text *shell* SWT/BORDER))
(def *wordmonger-path* "/home/john/sources/clojure/wordmonger/")
(def *question-html-header* "<body bgcolor=\"#eeeeee\"><center><table border=1 cellpadding=10>")
(def *alphabetical-order* "ABCDEFGHIJKLMNOPQRSTUVWXYZ?")
(def *vowel-first-order* "AEIOUBCDFGHJKLMNPQRSTVWXYZ?")
(def *height* 5)
(def *width* 6)
(def *board* [])
(def *timer-max* 180)
(def *timer-value* nil)
(defmacro nary-or [first & rest]
(if rest
`(bit-or ~first (nary-or ~@rest))
first))
(defmacro unless [condition & body]
`(when (not ~condition) ~@body))
(defmacro random [radix]
`(.nextInt (java.util.Random.) ~radix))
(defmacro downcase [string]
`(.toLowerCase ~string))
(defmacro upcase [string]
`(.toUpperCase ~string))
(defn ana-sets-of-length [length]
(let [filename (str *wordmonger-path* "words/twl06/length" length ".txt")
sequence (read-lines filename)]
(map #(re-seq #"\S+" %) sequence)))
(defn random-board [length board-size]
(let [ana-sets (ana-sets-of-length length)
num-sets (count ana-sets)
sets-array (to-array ana-sets)]
(loop [board [], num-more board-size]
(let [random-set (aget sets-array (random num-sets))]
(if (contains? board random-set)
(recur board num-more)
(if (pos? num-more)
(recur (conj board random-set) (dec num-more))
board))))))
(defn set-board-to-random-board []
(let [board (random-board 8 (* *height* *width*))]
(def *board* (ref board))))
(set-board-to-random-board)
(defn word-solved? [word]
(nil? (re-find #"[A-Z]" word)))
(defn ana-set-solved? [ana-set]
(every? word-solved? ana-set))
(defn alphagram [ana-set order-string]
(apply str (sort-by #(.indexOf order-string (str %))
(upcase (first ana-set)))))
(defn word-space [word]
(apply str (take (.length word) (repeat "&#x2012;"))))
(defn ana-set-html [ana-set]
(loop [html (str "<center><b>
<p style=\"font-family: bitstream vera sans;
font-size: 140%;
margin-top: 0;
color: " (if (ana-set-solved? ana-set)
"#a0a0a0;"
"#000000;")
"margin-bottom: 0.25em\">"
(alphagram ana-set *vowel-first-order*)
"</p></b>")
[word & more-words] ana-set]
(let [word-text (if (word-solved? word)
(upcase word)
(word-space word))
word-html (str "<p style=\"font-family: bitstream vera sans;
margin-top: 0;
margin-bottom: 0\">"
word-text
"<br>")
new-html (str html word-html)]
(if (empty? more-words)
new-html
(recur new-html more-words)))))
(defn board-html []
(loop [index 0
html *question-html-header*
[ana-set & more-ana-sets] @*board*]
(let [h-pos (rem index *width*)
set-html (str (if (zero? h-pos) "<tr>" "")
"<td valign=\"top\">" (ana-set-html ana-set) "</td>"
(if (= h-pos (dec *width*)) "</tr>" ""))
new-html (str html set-html)]
(if (empty? more-ana-sets)
new-html
(recur (inc index) new-html more-ana-sets)))))
(doto *question-browser*
(.setFont (new Font *display* "bitstream vera sans" 12 SWT/NORMAL))
(.setLayoutData (new GridData (nary-or GridData/HORIZONTAL_ALIGN_FILL
GridData/GRAB_HORIZONTAL
GridData/VERTICAL_ALIGN_FILL
GridData/GRAB_VERTICAL)))
(.setText (board-html)))
(doto *timer-label*
(.setFont (new Font *display* "bitstream vera sans mono" 12 SWT/NORMAL))
(.setText " ")
(.setLayoutData (new GridData GridData/HORIZONTAL_ALIGN_CENTER)))
(doto *answer-text*
(.setFont (new Font *display* "bitstream vera sans" 12 SWT/NORMAL))
(.setText " ")
(.setLayoutData (new GridData GridData/HORIZONTAL_ALIGN_CENTER)))
(defn replace-in-anagram-set [answer anagram-set]
(loop [checked-words []
[word & more-words] anagram-set]
(if (.equals word answer)
(let [new-set (concat checked-words (cons (downcase word) more-words))]
(list true new-set))
(let [new-checked-words (concat checked-words (list word))]
(if (empty? more-words)
(list false new-checked-words)
(recur new-checked-words more-words))))))
(defn replace-in-board [answer]
(loop [checked-sets []
[anagram-set & more-sets] @*board*]
(let [[changed new-set] (replace-in-anagram-set answer anagram-set)]
(if changed
(let [new-board (concat checked-sets (cons new-set more-sets))]
(list true new-board))
(let [new-checked-sets (concat checked-sets (list anagram-set))]
(if (empty? more-sets)
(list false new-checked-sets)
(recur new-checked-sets more-sets)))))))
(defn answer-modify [event]
(let [[changed new-board] (replace-in-board (.getText *answer-text*))]
(when changed
(def *board* (ref new-board))
(.setText *question-browser* (board-html))
(.setText *answer-text* ""))))
(defn answer-modify-listener []
(proxy [ModifyListener] []
(modifyText [event] (answer-modify event))))
(defn answer-verify [event]
(let [key (.keyCode event)]
(cond (<= (int \a) key (int \z))
(set! (.text event) (upcase (.text event)))
(and (not= key (int \backspace)) (not (zero? key)))
(set! (.doit event) false))))
(defn answer-verify-listener []
(proxy [VerifyListener] []
(verifyText [event] (answer-verify event))))
(doto *answer-text*
(.setFocus))
(let [grid-layout (new GridLayout)]
(doto *shell*
(.setLayout grid-layout)
(.setText "Wordmonger")
(.pack)
(.open)))
(doto *answer-text*
(.setText "")
(.addModifyListener (answer-modify-listener))
(.addVerifyListener (answer-verify-listener)))
(defn initialize-timer []
(def *timer-value* (ref *timer-max*)))
(defn decrement-timer [_]
(let [value @*timer-value*
new-value (dec value)]
(def *timer-value* (ref new-value))
;(.setText *timer-label* (str new-value))
(println new-value)))
(defn start-timer []
(send-off (agent nil)
(fn timer [_]
(Thread/sleep 1000)
(send-off (agent nil) decrement-timer)
(send-off *agent* timer))))
(initialize-timer)
(start-timer)
(loop []
(if (.isDisposed *shell*)
(.dispose *display*)
(do (when (not (.readAndDispatch *display*))
(.sleep *display*))
(recur))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment