diff --git a/src/icw/async/albums_stream.clj b/src/icw/async/albums_stream.clj index 8b492e5..470b51d 100644 --- a/src/icw/async/albums_stream.clj +++ b/src/icw/async/albums_stream.clj @@ -6,7 +6,7 @@ [icw.data.gen :as data-gen])) ;; Preamble:1 ends here -;; [[file:~/github/intermediate-clojure-workshop/content/async/albums_stream.org::*Outline][Outline:2]] +;; [[file:~/github/intermediate-clojure-workshop/content/async/albums_stream.org::*Solution][Solution:2]] (defonce counter (atom 0)) (def observing-mapper (map (fn [e] (swap! counter inc) @@ -19,15 +19,16 @@ (defonce generator-loop (go-loop [stream (data-gen/get-albums-xs)] - #_("Introduce an appropriate delay") + ; FIXME + ; (a/! in-ch #_(FIXME stream) :dummy)) - (recur #_(FIXME stream) :dummy))))) + (a/>! in-ch (first stream))) + (recur (rest stream)))))) (defn enable-stream! [] (reset! enabled? true)) (defn disable-stream! [] (reset! enabled? false)) -;; Outline:2 ends here +;; Solution:2 ends here diff --git a/src/icw/async/rlsc.clj b/src/icw/async/rlsc.clj index 6eb0bc5..a7cccc5 100644 --- a/src/icw/async/rlsc.clj +++ b/src/icw/async/rlsc.clj @@ -53,42 +53,51 @@ (shutdown! [this])) ;; The API:1 ends here -;; [[file:~/github/intermediate-clojure-workshop/content/async/rlsc.org::*Outline][Outline:1]] -(defrecord RLSC - [in-ch out-ch process-fn time-gap-ms burst-count] - ;; Any internal state to track?? - +;; [[file:~/github/intermediate-clojure-workshop/content/async/rlsc.org::*Solution][Solution:1]] +(defrecord RLSC [in-ch out-ch process-fn time-gap-ms burst-count + -tokens -shutdown?] RLSCController - ; We need two go processes - ; 1. One that tracks consumption and burst-rate limits - ; 2. The other processes messages per the policy (start! [_] + + ; An independent go process that tracks appropriate increments to the + ; burst-count (go-loop [] - #_("A periodic process that increments tokens")) - (go-loop [#_v #_("read a message")] - "If we have capacity process, else simply pass on to the output channel" - (recur #_("read next message if no shutdown signal")))) - - ; Policy change at run-time - ; This needs to be conveyed to the go-blocks - ; which help us conform to policy - (modify-burst! [this new-burst-count] - #_("update the burst-count") - #_("update tokens available")) - - ; Stop all transformation - ; Signal the go-block logic to clamp down on transformations. + (!! out-ch (process-fn v))) + (counter-- -tokens)) + (do + "No spare capacity. Short-circuit the inward message to the next sink." + (>! out-ch v))) + (if-not @-shutdown? + (recur (RLSC in-ch out-ch process-fn time-gap-ms - (atom burst-count))) -;; Outline:1 ends here + (atom burst-count) + (new-counter burst-count) + (atom false))) +;; Solution:1 ends here ;; [[file:~/github/intermediate-clojure-workshop/content/async/rlsc.org::*Test%20runs][Test runs:1]] (comment diff --git a/src/icw/data/process.clj b/src/icw/data/process.clj index db9c5a3..4aee6c9 100644 --- a/src/icw/data/process.clj +++ b/src/icw/data/process.clj @@ -29,14 +29,20 @@ \"Rock\" [\"Rock & Roll\" \"Psychedelic Rock\"]" [line] - ) + (let [line-v (-> line + csv/read-csv + first) + subgenres (-> (last line-v) + csv/read-csv)] + (concat (butlast line-v) + subgenres))) (comment - (= (parse-line "1,1967,Sgt. Pepper's Lonely Hearts Club Band,The Beatles,Rock,\"Rock & Roll, Psychedelic Rock\"") + (= (parse-line "1,1967,Sgt. Pepper's Lonely Hearts Club Band,The Beatles,Rock,\"Rock & Roll,Psychedelic Rock\"") ["1" "1967" - "Sgt. Pepper's Lonely Hearts Club BandThe Beatles" + "Sgt. Pepper's Lonely Hearts Club Band" "The Beatles" "Rock" ["Rock & Roll" @@ -57,13 +63,19 @@ Output {:number \"1\" :year \"1967\" - :artist \"The beatles\"p + :artist \"The beatles\" :album \"Sgt. Pepper's Lonely Hearts Club BandThe Beatles\" :genre \"Rock\" :subgenre-xs [\"Rock & Roll\" \"Psychedelic Rock\"]}" [xs] - ) + (let [[number year album artist genre subgenre] xs] + {:number number + :year year + :artist artist + :album album + :genre genre + :subgenre subgenre})) (comment (= (line-vec->line-map ["1" @@ -81,18 +93,17 @@ :subgenre ["Rock & Roll" "Psychedelic Rock"]})) -(comment - (take 10 - (map #_FIXME - (map #_FIXME - album-lines)))) - (defn line-xs->album-xs [line-xs] ;; Use parse-line to convert list of strings to list of vectors ;; Use line-vec->line-map to convert list of vectors to list of map - ) + (map line-vec->line-map + (map parse-line + line-xs))) + + +(comment (take 1 (line-xs->album-xs album-lines))) (defn populate-db [] @@ -125,14 +136,15 @@ (defn line-xs->albums-xs-before "Lists all albums before 'year'" - [line-xs year] - (comment (filter #_FIXME - (map #_FIXME - #_FIXME)))) + [year line-xs] + (filter #(< (:year %) year) + (map (fn [album] + (update-in album [:year] #(Integer/parseInt %))) + line-xs))) (comment (= (take 5 (map (juxt :year :album) (line-xs->albums-xs-before 1987 - album-lines))) + (line-xs->album-xs album-lines)))) '([1967 "Sgt. Pepper's Lonely Hearts Club Band"] [1966 "Pet Sounds"] [1966 "Revolver"] @@ -165,11 +177,13 @@ (defn find-popular-year ;; Find top years for album releases [line-xs] - (sort-by #_FIXME - (reduce #_FIXME - {} - (map #_ME - line-xs)))) + (sort-by (comp - second) + (frequencies (map :year + (map line-xs->album-xs + line-xs))))) + +(take 5 (map line-xs->album-xs + album-lines)) (comment (= (take 5 (find-popular-year album-lines)) '(["1970" 26] @@ -205,7 +219,7 @@ data-gen/get-albums-xs ;; DONT evaluate the function in REPL it's a lazy sequence. -;; It's a list of albums generated from 2040 till infinity +;; It's a list of albums generated from year 2040 till infinity (take 10 (data-gen/get-albums-xs)) @@ -220,19 +234,34 @@ data-gen/get-albums-xs (comment ;; This will evaluate for infinity since filter does not stop evaluation ;; We will just get infinite list of nils after year 2045 - (line-xs->albums-xs-before (data-gen/get-albums-xs) - 2045)) + (line-xs->albums-xs-before 2045 + (data-gen/get-albums-xs))) ;; https://clojure.org/api/cheatsheet -;; Espeically look for seq in and seq out +;; Especially look for seq in and seq out + +(defn albums-until-year + [year] + (take-while identity + (line-xs->albums-xs-before year + (line-xs->album-xs + (take 1 (data-gen/get-albums-xs)))))) -(#_FIXME identity - (line-xs->albums-xs-before (data-gen/get-albums-xs) - 2045)) +(comment + (take 10 (albums-until-year 2041))) ;; Try applying functions we have created till now +(comment + (-> 2045 + albums-until-year + find-popular-year + (take 10))) + +(comment + (find-popular-artists (until-year 2045))) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; END of chapter 1 diff --git a/src/icw/search/core.clj b/src/icw/search/core.clj index e109daa..5994807 100644 --- a/src/icw/search/core.clj +++ b/src/icw/search/core.clj @@ -30,5 +30,5 @@ (r/search @index field query-term (standard-analyzer))) (comment - (search :subgenre "classic rock")) + (search :album "pepper's")) ;; The Preamble:1 ends here diff --git a/src/icw/search/reader.clj b/src/icw/search/reader.clj index bea5eba..3ad9f36 100644 --- a/src/icw/search/reader.clj +++ b/src/icw/search/reader.clj @@ -9,33 +9,40 @@ [org.apache.lucene.util QueryBuilder])) ;; Code Template:1 ends here -;; [[file:~/github/intermediate-clojure-workshop/content/search/reader.org::*Outline][Outline:1]] -(defn ^IndexReader index-reader [^Directory directory]) - -(defn ^IndexSearcher searcher [^Directory directory]) - -(defn field->kv [^Field f]) - -(defn doc->map [^Document doc]) - -(defn ^Query query [^clojure.lang.Keyword field - ^String term - ^Analyzer analyzer]) - -(defn score-docs->ids [^"[Lorg.apache.lucene.search.ScoreDoc;" score-docs]) - -(defn doc-ids->docs [^IndexSearcher searcher doc-ids]) - -; Create IndexSearcher given the index (Directory instance) -; Create a Query object given the field, term and analyzer -; .search on the IndexSearcher the generated Query -; Get .scoreDocs from the response -; ScoreDoc instances give you document-ids as handles -; Using the document-ids, get the Document instances from the IndexSearcher -; Convert the collection to maps with doc->map -; Enjoy the convenience of Clojure's support for Iterable -(defn search [^Directory directory - ^clojure.lang.Keyword field - ^String search-term - ^Analyzer analyzer]) -;; Outline:1 ends here +;; [[file:~/github/intermediate-clojure-workshop/content/search/reader.org::*Solution][Solution:1]] +(defn index-reader [directory] + (DirectoryReader/open directory)) + +(defn searcher [directory] + (IndexSearcher. (index-reader directory))) + +(defn field->kv [f] + [(-> f .name keyword) + (.stringValue f)]) + +(defn doc->map [d] + (into + {} + (map field->kv d))) + +(defn query [field term analyzer] + (let [qb (QueryBuilder. analyzer) + field (name field)] + (. qb + (createBooleanQuery field term)))) + +(defn score-docs->ids [^"[Lorg.apache.lucene.search.ScoreDoc;" score-docs] + (map (fn [score-doc] (.doc score-doc)) score-docs)) + +(defn doc-ids->docs [searcher doc-ids] + (map (fn [doc-id] (.doc searcher doc-id)) doc-ids)) + +(defn search [directory field search-term analyzer] + (let [q (query field search-term analyzer) + searcher (searcher directory) + search-results (.search searcher q 10) + score-docs (.scoreDocs search-results) + doc-ids (score-docs->ids score-docs) + docs (doc-ids->docs searcher doc-ids)] + (map doc->map docs))) +;; Solution:1 ends here pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy