Commits

Steve Losh committed f6e6cb5

Wrap up.

  • Participants
  • Parent commits f8dd933

Comments (0)

Files changed (7)

File LICENSE.markdown

+Copyright (c) 2012 Steve Losh and contributors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+**THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.**
+

File README.markdown

+# Typkov
+
+Typekov is a small Clojure/Noir webapp that generates gtypist lessons from
+users' own text.  It's much more fun/productive to practice typing the kind of
+stuff you actually type in real life.
+
+It's MIT/X11 licensed, so feel free to play around with it.

File README.md

-# typkov
-
-A website written in noir. 
-
-## Usage
-
-```bash
-lein deps
-lein run
-```
-
-## License
-
-Copyright (C) 2011 FIXME
-
-Distributed under the Eclipse Public License, the same as Clojure.
-
-(defproject typkov "0.1.0-SNAPSHOT"
-            :description "FIXME: write this!"
+(defproject typkov "1.0.0"
+            :description "A small webapp to generate gtypist lessons from users' own writing."
             :dependencies [[org.clojure/clojure "1.3.0"]
                            [noir "1.2.1"]]
             :main typkov.server)

File resources/public/css/style.less

     padding-left: 0;
 
     .alert-message {
-        width: 280px;
+        width: 368px;
         margin-top: 10px;
     }
 }
 .lesson {
     font-family: 'Menlo', monospace;
+    height: 100px;
 }

File src/typkov/templates.clj

      [:div#content
       [:header
        [:h1 "Typkov"]
-       [:h2 "Create gtypist lessons from your own writing!"]]
+       [:h2
+        "Create "
+        (link-to "http://www.gnu.org/software/gtypist/" "gtypist")
+        " lessons from your own writing!"]]
       content
       [:footer
        [:p
         "Created by "
         (link-to "http://stevelosh.com/" "Steve Losh")
-        "."]]]]))
+        "."
+        [:p
+        "It's open source "
+        (link-to "http://bitbucket.org/sjl/typkov" "on BitBucket")
+        " and "
+        (link-to "http://github.com/sjl/typkov" "on GitHub")
+        "."]]]]]))
+
 
 (defpartial error-item [[first-error]]
   [:div.alert-message.error first-error])
 
+
 (defpartial home [text lesson]
   (base "Typkov"
-        [:p "Enter some text and we'll create a gtypist lesson from it for you."]
+        [:p
+         "Typing practice is great, but wouldn't it be wonderful to "
+         "practice with the kind of words you usually use in your own writing?"]
+        [:p
+         "Enter some text and we'll create a "
+         (link-to "http://www.gnu.org/software/gtypist/" "gtypist")
+         " lesson based on it for you."]
         [:form {:method "post" :action "" :class "form-stacked"}
          [:fieldset.text
           [:label {:for "text"}
-           "Text"]
+           "Paste in some text you've written:"]
           (valid/on-error :text error-item)
           [:textarea#text.error {:name "text"} text]]
          [:button {:type "submit" :class "btn primary"} "Get a Lesson"]]
         (when lesson
-          [:textarea.lesson lesson])))
+          (list
+            [:p
+             "Copy all of the following into a "
+             [:code "whatever.typ"]
+             " file and use "
+             [:code "gtypist whatever.typ"]
+             " to use it!"]
+            [:textarea.lesson lesson]))))

File src/typkov/views/core.clj

 (defn random-choice [coll]
   (nth coll (rand-int (count coll))))
 
+(defn random-choice-weighted [choices]
+  (let [n (apply + (vals choices))
+        i (inc (rand-int n))]
+    (loop [i i
+           choices (seq choices)]
+      (let [[word weight] (first choices)
+            new-i (- i weight)]
+        (if (<= new-i 0)
+          word
+          (recur new-i (rest choices)))))))
+
 
 ; Gtypist ---------------------------------------------------------------------
-
 (defn to-gtypist-single [lesson n]
   (str "*:S_LESSON" n "\n"
        "B:Lesson " n "\n"
                        (range 1 (inc (count lessons)))))))
 
 
+; Markov ----------------------------------------------------------------------
+(defn markov-dict
+  ([words]
+   (markov-dict {} words))
+  ([dict words]
+   (if (not (second words))
+     dict
+     (let [w (first words)
+           n (second words)]
+       (recur (assoc-in dict [w n]
+                        (inc (get-in dict [w n] 0)))
+              (rest words))))))
+
+(defn markov-get [dict word]
+  (if (dict word)
+    (random-choice-weighted (dict word))
+    (random-choice (keys dict))))
+
+
 ; Lesson generation -----------------------------------------------------------
-(defn markov-dict [words]
-  (zipmap words (cycle [""])))
-
-(defn markov-get [dict]
-  (random-choice (keys dict)))
-
 (defn get-line [dict]
-  (let [words (repeatedly 10 (partial markov-get dict))]
+  (let [initial-word (random-choice (keys dict))
+        words (take 10 (iterate (partial markov-get dict) initial-word))]
     (trim (apply str (interleave words (cycle [" "]))))))
 
 (defn get-single [dict n]
   (repeatedly 4 (partial get-line dict)))
 
 (defn get-lesson [text]
-  (let [words (doall (filter (comp not empty?) (split text #"\s+")))
+  (let [words (take 20000 (filter (comp not empty?) (split text #"\s+")))
         dict (markov-dict words)
         lessons (map (partial get-single dict) (range 0 10))]
     (to-gtypist lessons)))
 ; Home page -------------------------------------------------------------------
 (defn text-valid? [{:keys [text]}]
   (valid/rule (valid/min-length? text 24)
-              [:text "You must enter some text!"])
+              [:text "You must enter a decent amount of text!"])
   (not (valid/errors? :text)))