generate.clj

Pinchord · pinchord.git · Tickets · Changelog

Branches > build-process > a725ca6 > files / src / org / pinchord / generate.clj

(ns org.pinchord.generate
  (:require
   [clj-yaml.core :as yaml]
   [clojure.edn :as edn]
   [clojure.string :as str]))

(defn finalize [m]
  (update-keys m (partial str "-")))

(defn mask [s1 s2]
  (apply str (remove (set s1) s2)))

(defn abbreviate
  "Abbreviates chords that are more than 6 characters,
   as Javelin entries can only be 6 characters long."
  [s]
  (if (> (count s) 6)
    (let [new-s (-> s
                    (str/replace #"TSPW" "G")
                    (str/replace #"PKS" "C")
                    (str/replace #"PKFS" "G")
                    (str/replace #"KFS" "SH")
                    (str/replace #"LR" "N"))]
      (if (> (count new-s) 6)
        (throw (ex-info "Too long!" {:s s :new-s new-s}))
        new-s))
    s))

(defn all-chords
  "Returns a set of all chord combinations of a given string of keys.
   E.g. (all-chords \"AO\") -> #{\"\" \"O\" \"AO\" \"A\"}"
  [s]
  (if (empty? s)
    #{""}
    (let [rest-combos (all-chords (rest s))]
      (set (concat
             rest-combos
             (map #(str (first s) %) rest-combos))))))

(defn fill-gaps-in-banks [{:chords/keys [bank-chords bank-keys]}]
  (reduce (fn [acc [bank chords]]
            (let [default-chords (all-chords (bank-keys bank))]
              (assoc acc bank (-> (merge (zipmap default-chords default-chords) chords)
                                  (update-vals abbreviate)))))
          {} bank-chords))

(defn with-gaps-filled [chords]
  (assoc chords :chords/bank-chords (fill-gaps-in-banks chords)))

(defn build-javelin-dictionary [{:chords/keys [banks bank-keys bank-chords]
                                 :keys [version]}]
  (let [bank->priority (zipmap banks (map inc (range)))]
    {:name (str "Pinchord Base " version)
     :maximumOutlineLength 1
     :starters [{:stroke "#+" :definition "{^}{-|}" :mask "#+"}
                {:stroke "" :definition "{}" :mask ""}]
     :letters (->> (reduce (fn [acc [bank entries]]
                             (if-let [bank-keys (bank-keys bank)]
                               (into acc (mapv (fn [[stroke translation]]
                                                 {:stroke stroke :data translation :order (bank->priority bank)
                                                  :avoidMask (str (when (= bank :finals)
                                                                    "-")
                                                                  (mask stroke bank-keys))})
                                               entries))
                               (into acc (mapv (fn [[stroke translation]]
                                                 {:stroke stroke :data translation :order (bank->priority bank)})
                                               entries))))
                           #{} bank-chords)
                   (sort-by (comp - count :stroke)))}))

(defn -main [& _args]
  (let [chords (-> (edn/read-string (slurp "chords.edn"))
                   with-gaps-filled
                   (update-in [:chords/bank-chords :finals] finalize)
                   (update-in [:chords/bank-chords :suffixes] finalize))
        dict (build-javelin-dictionary chords)
        dict-path (str "pinchord-javelin-dictionary-" (:version chords) ".yaml")]
    (spit dict-path (yaml/generate-string dict))))