Created
November 29, 2013 22:19
-
-
Save johnwalker/7712723 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (ns factor.handler | |
| (:use [compojure.core] | |
| [hiccup core form page] | |
| [me.raynes.conch :refer [programs with-programs let-programs]] | |
| [clojure.core.async :as async :refer [<! >! chan go put!]] | |
| [ring.middleware.params :only [wrap-params]] | |
| [ring.util.response :as resp] | |
| [incanter core stats charts datasets]) | |
| (:require [compojure.handler :as handler] | |
| [compojure.route :as route] | |
| [korma.db :refer :all] | |
| [korma.core :refer :all] | |
| [clojure.java.jdbc :as j] | |
| [clojure.java.jdbc.sql :as s] | |
| [clojure.string :as str] | |
| [clojure.data.json :as json] | |
| [ring.adapter.jetty :as jetty]) | |
| (:import [java.io ByteArrayOutputStream ByteArrayInputStream]) | |
| (:gen-class)) | |
| (def queue (atom clojure.lang.PersistentQueue/EMPTY)) | |
| (def composites (chan)) | |
| (programs factor) | |
| (def program-map {"factor" factor}) | |
| (def db-spec {:classname "org.h2.Driver" | |
| :subprotocol "h2" | |
| :subname "resources/db" | |
| :user "sa" | |
| :password "" | |
| :naming {:keys str/upper-case | |
| :fields str/upper-case}}) | |
| (defn init [] | |
| (j/with-connection db-spec | |
| (j/create-table :composite | |
| [:id "int auto_increment primary key"] | |
| [:value "varchar(10000)"] | |
| [:duration "varchar(10000)"] | |
| [:algorithm "varchar(100)"] | |
| [:result "varchar(10000)"]))) | |
| (defdb korma-db db-spec) | |
| (defentity composite | |
| (entity-fields :id :value :duration :algorithm :result)) | |
| (defmacro msecs [body] | |
| `(let [start-time# (System/nanoTime) | |
| result# ~body | |
| end-time# (System/nanoTime)] | |
| [(- end-time# start-time#) result#])) | |
| (defn parse-int [s] | |
| (try (BigInteger. s) | |
| (catch Exception e nil))) | |
| (defn draw-chart [algorithm] | |
| (let [records (->> (select composite | |
| (where {:ALGORITHM algorithm})) | |
| (map #(update-in % [:DURATION] (comp count str parse-int))) | |
| (map #(update-in % [:VALUE] (comp count str parse-int))) | |
| (sort-by :VALUE))] | |
| (with-data (dataset [:DURATION :VALUE] records) | |
| (let [out (ByteArrayOutputStream.) | |
| in (do (save (scatter-plot :VALUE :DURATION | |
| :title algorithm | |
| :legend false | |
| :x-label "Number's Value" | |
| :y-label "Factorization Time") | |
| out :width 1200 :height 600) | |
| (ByteArrayInputStream. (.toByteArray out)))] | |
| {:status 200 | |
| :headers {"Content-Type" "image/png"} | |
| :body in})))) | |
| (defn queue-page | |
| ([] | |
| (html5 | |
| [:head | |
| [:title "Factorization"]] | |
| [:body | |
| (form-to {:name "factor-request"} | |
| [:put "/"] | |
| (text-field {:name "composite" | |
| :autofocus true} :composite) | |
| (text-field {:name "algorithm"} :algorithm) | |
| (submit-button "Factor")) | |
| [:img {:src "/factor"}] | |
| [:p "Currently working on:"] | |
| [:ul (for [[number algorithm] @queue] | |
| [:li number " " algorithm])]])) | |
| ([composite algorithm] | |
| (when-let [number (parse-int composite)] | |
| (when (program-map algorithm) | |
| (put! composites [number algorithm]) | |
| (swap! queue conj [number algorithm]))))) | |
| (defroutes app-routes | |
| (GET "/" [] (queue-page)) | |
| (PUT "/" [composite algorithm] (queue-page composite algorithm) (resp/redirect "/")) | |
| (GET "/factor" [] (draw-chart "factor")) | |
| (route/resources "/") | |
| (route/not-found "Not Found")) | |
| (def app | |
| (wrap-params app-routes)) | |
| (defn factor-chan [] | |
| (go (while true | |
| (let [[number algorithm] (<! composites) | |
| program (program-map algorithm) | |
| string-number (str number) | |
| [ms result] (msecs (program string-number))] | |
| (insert composite (values {:value string-number :duration ms | |
| :result result :algorithm algorithm})) | |
| (swap! queue pop))))) | |
| (defn -main [& [port]] | |
| (let [port (Integer. (or port (System/getenv "PORT") 5000))] | |
| (factor-chan) | |
| (jetty/run-jetty #'app {:port port :join? false}))) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment