Skip to content

Instantly share code, notes, and snippets.

/Places.clj Secret

Created April 11, 2012 08:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/2b7b99137ce4e9ee2474 to your computer and use it in GitHub Desktop.
Save anonymous/2b7b99137ce4e9ee2474 to your computer and use it in GitHub Desktop.
Places component file for AS project - unit tests pass, PlacesTest doesn't work
(ns magicInk.Places)
(use 'clojure.java.io)
(use '[clojure.string :only [split]])
(use 'clojure.test)
(defrecord kword [kname kconf])
(defrecord feedback [objname modifier])
; These next three functions are used for reading in an initial map of place-names and confidence values
; and storing them into the place-tuples variable, which is a stateful reference.
;
; We use state here so that we can load the place-tuples in once, and have them modified thereafter when
; feedback is sent into this Component
(defn split-name-and-confidence [s]
"Takes a string, returns a sequence of two comma-separated fields with the second cast to a Double"
(let [fields (split s #",")]
[(first fields) ,(Double/parseDouble (second fields))]
)
)
; Unit test
(is (= ["fred",1.0] (split-name-and-confidence "fred,1")))
(defn sort-map-by-value
"Takes a map, returns it sorted by value"
[m]
(into (sorted-map-by (fn [key2 key1] (<= (m key1) (m key2)))) m)
)
(defn read-from-file
"Reads in Name,Confidence tuples from the text file supplied and returns them in a map"
[f]
(sort-map-by-value (into {} (map split-name-and-confidence
(line-seq (clojure.java.io/reader (clojure.java.io/file f)))
)))
)
(def place-tuples (ref {}))
(defn load-tuples
"Load the map of Name,Confidence tuples"
[f]
(dosync (ref-set place-tuples (read-from-file f)))
)
; These following functions are the meat of the Component, responsible for querying it for possible matches
; given a keyword, and passing feedback into it, updating the map.
(defn inject-keyword-with-map
"Takes a map of Name,Confidence tuples and a Keyword, returns a list of possible object matches"
[m k]
; take all the tuples in our map which contain that keyword
; multiply their confidence by the keyword confidence
; order by confidence
(sort-map-by-value
(into {} (map #(identity [(key %1), (* (:kconf k) (val %1))])
(filter #(not= -1 (.indexOf (first %) (:kname k))) m))))
)
(defn inject-keyword
"Takes a Keyword, returns a list of possible object matches"
[k]
(inject-keyword-with-map @place-tuples k)
)
(defn get-map
"Returns the map"
[]
@place-tuples
)
(defn update-feedback-if-matching
"Takes a single Name,Confidence tuple and a Feedback, returns an updated tuple with feedback applied to it"
[t f]
(if (= (key (first t)) (:objname f))
{ (:objname f) (* (:modifier f) (val (first t)))}
t
)
)
; Unit tests
(is (= {"Harry" 1.1} (update-feedback-if-matching {"Harry" 1.0} (feedback. "Harry" 1.1))))
(is (= {"Harry" 1.0} (update-feedback-if-matching {"Harry" 1.0} (feedback. "Dick" 1.1))))
(defn inject-feedback-into-map
"Takes a map of Name,Confidence tuples and a Feedback, returns an updated map of Name,Confidence tuples"
[m f]
(println m)
(println (clojure.string/join ", " (keys m)))
(println (first (keys m)))
(println (class m))
(println (get m (first (keys m))))
(into {} (map #(update-feedback-if-matching {% (m %)} f) (keys m)))
)
(defn inject-feedback
"Helper method; updates the place-tuples map with the Feedback supplied"
[f]
; (dosync (ref-set place-tuples (inject-feedback-into-map @place-tuples f)))
(inject-feedback-into-map @place-tuples f)
)
; Unit tests
(is (= {"Tom" 1.0, "Dick" 1.0, "Harry" 1.1} (inject-feedback-into-map {"Tom" 1.0, "Dick" 1.0, "Harry" 1.0} (feedback. "Harry" 1.1))))
(is (= {"Tom" 1.0, "Dick" 1.2, "Harry" 1.0} (inject-feedback-into-map {"Tom" 1.0, "Dick" 1.0, "Harry" 1.0} (feedback. "Dick" 1.2))))
(is (= {"Tom" 1.0, "Dick" 1.0, "Harry" 1.0} (inject-feedback-into-map {"Tom" 1.0, "Dick" 1.0, "Harry" 1.0} (feedback. "Jeff" 1.1))))
(ns magicInk.PlacesTest)
(require '[magicInk.Places :as Places])
; This file exercises the Places component. I wrote it so I could test that statefulness works nicely,
; with a dummy data file.
(Places/load-tuples "test-places.txt")
(Places/get-map)
(Places/inject-feedback (magicInk.Places.feedback. "Future Platforms" 1.1))
Google Inc,14.399999999999997
Clearleft Ltd,12.000000000000002
Future Platforms,4.8
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment