                             (when (or wanted (not infaction))
                               (let [influence (* (:factioncost card) (:qty line))]
                                 [:span.influence
-                                 {:class (-> card :faction .toLowerCase (.replace " " "-"))
+                                 {:class (faction-label card)
                                   :dangerouslySetInnerHTML
                                   #js {:__html (str (if-not infaction (apply str (for [_ (range influence)] "&#9679;")))
                                                     (if wanted (apply str (for [_ (range (:qty line))] "&#9675;"))))}}]))])

    (om/set-state! owner :deck-edit str)))

(defn influence [deck]
  (let [identity (:identity deck)
        cards (:cards deck)
        inf (reduce #(let [card (:card %2)]
                       (if (= (:faction card) (:faction identity))
                         %1
                         (+ %1 (* (:qty %2) (:factioncost card)))))
                    0 (:cards deck))]
    (if (= (:title identity) "The Professor: Keeper of Knowledge")
      (- inf (reduce #(+ %1 (get-in %2 [:card :factioncost])) 0
                     (filter #(let [card (:card %)]
                                (and (= (:type card) "Program")
                                     (not= (:faction card) (:faction identity))))
                             cards)))
      inf)))

(defn card-count [cards]
  (reduce #(+ %1 (:qty %2)) 0 cards))

(defn parse-deck [side deck]
  (reduce #(if-let [card (parse-line side %2)] (conj %1 card) %1) [] (split-lines deck)))

(defn faction-label [card]
  "Returns faction of a card as a keyword"
  (-> card :faction .toLowerCase (.replace " " "-")))

(defn allowed? [card {:keys [side faction title] :as identity}]
  "Checks if a card is allowed in deck of a given identity - not accounting for influence"
  (and (not= (:type card) "Identity")
