From 5832b23d3b8af0ffa2d03d92b93d94443d908bd5 Mon Sep 17 00:00:00 2001 From: xtreak Date: Sat, 24 Mar 2018 15:02:31 +0530 Subject: [PATCH] Add specs and single arity for word-cloud --- examples/examples.clj | 2 +- src/clj_wordcloud/core.clj | 50 ++++++++++++++++++++++++++++++-- test/clj_wordcloud/core_test.clj | 2 +- 3 files changed, 50 insertions(+), 4 deletions(-) diff --git a/examples/examples.clj b/examples/examples.clj index 77cacf9..d24a273 100644 --- a/examples/examples.clj +++ b/examples/examples.clj @@ -28,7 +28,7 @@ (write-to-file word-cloud "example_circle.png")) -(let [frequency-map (zipmap (range 100 150) (shuffle (range 300))) +(let [frequency-map (zipmap (map str (range 100 150)) (shuffle (range 300))) word-cloud (word-cloud frequency-map {:dimension {:width 600 :height 600} diff --git a/src/clj_wordcloud/core.clj b/src/clj_wordcloud/core.clj index 01a038d..d000c6c 100644 --- a/src/clj_wordcloud/core.clj +++ b/src/clj_wordcloud/core.clj @@ -1,4 +1,5 @@ (ns clj-wordcloud.core + (:require [clojure.spec.alpha :as spec]) (:import (java.awt Dimension Color) (java.awt.image BufferedImage) (javax.imageio ImageIO) @@ -75,6 +76,45 @@ [word-cloud filename] (.writeToFile word-cloud filename)) +; Frequency-map specs + +(spec/def ::frequency-map (spec/map-of string? (spec/and int? #(>= %1 0)))) + +; Dimension specs +(spec/def ::width (spec/and number? pos?)) +(spec/def ::height (spec/and number? pos?)) +(spec/def ::dimension (spec/keys :req-un [::width ::height])) + +; background specs +(spec/def :circle/type #{:circle}) +(spec/def :rectangle/type #{:rectangle}) +(spec/def :pixel/type #{:pixel}) +(spec/def ::size (spec/and number? pos?)) +(spec/def ::bitmap string?) +(spec/def ::color (spec/and string? #(re-matches #"0x[0-9A-F]{1,6}" %1))) + +(spec/def ::circle (spec/keys :req-un [:circle/type ::size] :opt-un [::color])) +(spec/def ::rectangle (spec/keys :req-un [:rectangle/type ::size] :opt-un [::color])) +(spec/def ::pixel (spec/keys :req-un [:pixel/type ::bitmap])) + +(spec/def ::background (spec/or :circle ::circle :rectangle ::rectangle :pixel ::pixel)) + +; font specs +(spec/def :font/type string?) +(spec/def :font/weight #{:plain :bold :italic}) +(spec/def :font/scale-type #{:linear}) +(spec/def :font/x-scale (spec/and number? pos?)) +(spec/def :font/y-scale (spec/and number? pos?)) +(spec/def :font/padding (spec/and number? pos?)) +(spec/def :font/colors (spec/coll-of ::color)) + +(spec/def ::font (spec/keys :opt-un [:font/type :font/weight :font/scale-type + :font/x-scale :font/y-scale :font/padding :font/colors])) + +(spec/def ::options (spec/keys :req-un [::dimension ::background] :opt-un [::font])) + +(spec/fdef word-cloud + :args (spec/cat :frequency-map ::frequency-map :options ::options)) (defn word-cloud " @@ -93,7 +133,13 @@ :y-scale 20 ; y scale of font :padding 5}} ; padding between entries " - [frequency-map options] + ([frequency-map] + (word-cloud frequency-map {})) + ([frequency-map options] + (if-not (spec/valid? ::frequency-map frequency-map) + (throw (ex-info "Invalid data : " (spec/explain-data ::frequency-map frequency-map)))) + (if-not (spec/valid? ::options options) + (throw (ex-info "Invalid options : " (spec/explain-data ::options options)))) (let [word-frequencies (build-word-frequency frequency-map) dimension (build-dimension options) word-cloud (WordCloud. dimension CollisionMode/PIXEL_PERFECT) @@ -108,4 +154,4 @@ (.setBackground background) (.setFontScalar font-scalar) (.setKumoFont kumo-font) - (.build word-frequencies)))) + (.build word-frequencies))))) diff --git a/test/clj_wordcloud/core_test.clj b/test/clj_wordcloud/core_test.clj index bbadbb9..fa0c279 100644 --- a/test/clj_wordcloud/core_test.clj +++ b/test/clj_wordcloud/core_test.clj @@ -12,7 +12,7 @@ (deftest image-dimensions-test (testing "Test width and height of the generated image" - (let [freq-map (zipmap (range 100 130) (range 300)) + (let [freq-map (zipmap (map str (range 100 130)) (range 300)) word-cloud (word-cloud freq-map {:dimension {:width 600 :height 600}