Browse Source

continuing work on formula evaluation

Brandon Wong 4 years ago
parent
commit
e6e3f96c86
1 changed files with 79 additions and 51 deletions
  1. 79 51
      frontend/src/microtables_frontend/core.cljs

+ 79 - 51
frontend/src/microtables_frontend/core.cljs

@@ -5,18 +5,21 @@
 
 ; to generate random values
 ;for(let i = 0, s = new Set(); i < 10; i++){ let r = Math.floor(Math.random() * 15)+1, c = a[Math.floor(Math.random() * a.length)], k = `${c}${r}`; if(s.has(k)){ i--; continue; } s.add(k); v.push(`{:row ${r} :col "${c}" :value "${Math.floor(Math.random() * 10000)}"}`); }
-(def sample-data [{:row 1 :col "A" :value "59"}
-                  {:row 5 :col "C" :value "269"}
-                  {:row 4 :col "B" :value "7893"}
-                  {:row 2 :col "F" :value "8650"}
-                  {:row 6 :col "D" :value "4065"}
-                  {:row 7 :col "F" :value "5316"}
-                  {:row 12 :col "A" :value "2405"}
-                  {:row 5 :col "B" :value "7863"}
-                  {:row 9 :col "E" :value "3144"}
-                  {:row 10 :col "D" :value "8272"}
-                  {:row 11 :col "D" :value "2495"}
-                  {:row 15 :col "E" :value "8968"}])
+(def sample-data [{:row 1 :col "A" :value "59" :view :display}
+                  {:row 5 :col "C" :value "269" :view :display}
+                  {:row 4 :col "B" :value "7893" :view :display}
+                  {:row 2 :col "F" :value "8650" :view :display}
+                  {:row 6 :col "D" :value "4065" :view :display}
+                  {:row 7 :col "F" :value "5316" :view :display}
+                  {:row 12 :col "A" :value "2405" :view :display}
+                  {:row 5 :col "B" :value "7863" :view :display}
+                  {:row 9 :col "E" :value "3144" :view :display}
+                  {:row 10 :col "D" :value "8272" :view :display}
+                  {:row 11 :col "D" :value "2495" :view :display}
+                  {:row 15 :col "E" :value "8968" :view :display}
+                  {:row 7 :col "B" :value "=C5 + D6" :view :display}
+                  {:row 8 :col "B" :value "=B7 * 2" :view :display}
+                  {:row 7 :col "C" :value "=D1" :view :display}])
 
 (defonce data-atom (r/atom sample-data))
 
@@ -39,38 +42,14 @@
   (if (nil? datum)
     (swap! data-atom conj {:row r :col c :value value})
     (swap! data-atom (fn [d] (map #(if (and (= r (:row %)) (= c (:col %))) (assoc % :value value) %) d)))))
+(defn update-display [c r display]
+  (println (str "trying to update " c r " to " display))
+  (swap! data-atom (fn [d] (map #(if (and (= r (:row %)) (= c (:col %))) (assoc % :display display) %) d))))
+(defn toggle-display [c r view-mode]
+  (println (str "toggling " c r " to " view-mode))
+  (swap! data-atom (fn [d] (map #(if (and (= r (:row %)) (= c (:col %))) (assoc % :view view-mode) %) d))))
 
-
-;; -------------------------
-;; Views
-
-(defn cell [c r data]
-  (let [datum (some #(if (and (= c (:col %)) (= r (:row %))) %) data)]
-    ^{:key (str c r)} [:td [:input {:value (or (:value datum) "")
-                                    :on-change #(update-value c r datum (.. % -target -value))
-                                    :on-blur (fn [e] (println (str "blur! " c r)))
-                                    :on-focus (fn [e] (println (str "focus! " c r)))}]]
-    )
-  )
-(defn row [r cols data]
-  ^{:key (str "row-" r)} [:tr
-                          (cons
-                            ^{:key (str "row-head-" r)} [:th (str r)]
-                            (map #(cell % r data) cols))])
-(defn header-row [cols]
-  ^{:key "header"} [:tr
-   (cons
-     ^{:key "corner"} [:th]
-     (map (fn [c] ^{:key (str "col-head-" c)} [:th c]) cols))])
-
-(defn sheet [data]
-  [:table [:tbody
-           (let [maxrow (highest :row data)
-                 cols (take-while (partial not= (next-letter (highest :col data))) col-letters)]
-             (cons
-               (header-row cols)
-               (map #(row % cols data) (range 1 (inc maxrow)))))
-           ]])
+; CALCULATION / FORMULA EVALUATION FUNCTIONS
 
 (defn temp1 [data]
   (let [first-order (group-by #(not= (first (:value %)) "=") data)
@@ -81,11 +60,22 @@
     {:remaining (zipmap non-evaluated-cells non-evaluated-values)
      :evaluated (zipmap evaluated-cells evaluated-values)}))
 
+(def parse-variables (memoize (fn [expression]
+                                (js->clj (.getVariables mathjs expression)))))
+(defn temp3 [[k v]]
+  (let [w (name k)
+        c (re-find #"^[A-Z]+" w)
+        r (.parseInt js/window (re-find #"[0-9]+$" w))]
+    (do
+      (update-display c r v)
+      )
+    )
+  )
+
 (defn temp2 [evaluated remaining]
   (if (empty? remaining)
     evaluated
-    (let [jsvars (map #(.getVariables mathjs (val %)) remaining)
-          vars (js->clj jsvars)
+    (let [vars (map #(parse-variables (val %)) remaining)
           remaining-vars (zipmap (keys remaining) vars)
           evaluated-vars (map (fn [x] (map #(let [item (keyword %)]
                                               (cond
@@ -96,24 +86,60 @@
           parsed (zipmap (keys remaining) evaluated-vars)
           ready-or-not (group-by (fn [[ k v ]] (some #(not= :not-yet (last %)) v)) parsed)
           ;TODO: detect circular references
-          ;prepared (map #([(key %) (.stringify js/JSON (apply js-obj (flatten (val %))))]) (ready-or-not true))
-          ;prepared (map (fn [[k v]] [k (.evaluate mathjs (remaining k) (.stringify js/JSON (apply js-obj (flatten v)))) (.stringify js/JSON (apply js-obj (flatten v)))]) (ready-or-not true))
           prepared (map (fn [[k v]] [k (.evaluate mathjs (remaining k) (apply js-obj (flatten v)))]) (ready-or-not true))
-          ;TODO: merge new values into data with the :display keyword (or similar)
+          new-evaluated (reduce conj evaluated prepared)
+          still-remaining (apply hash-map (flatten (map #(list (key %) (remaining (key %))) (ready-or-not nil))))
+          ;merged (map temp3 prepared) ;TODO: only merge after recursion is complete (outside this function)
           ]
       ;remaining ; {:B8 B7 * 2, :C7 D1, :B7 C5 + D6}
+      ;vars ; ([B7] [D1] [C5 D6])
       ;remaining-vars ; {:B8 [B7], :C7 [D1], :B7 [C5 D6]}
       ;parsed ; {:B8 ([B7 :not-yet]), :C7 ([D1 0]), :B7 ([C5 269] [D6 4065])}
       ;ready-or-not ; {nil [[:B8 ([B7 :not-yet])]], true [[:C7 ([D1 0])] [:B7 ([C5 269] [D6 4065])]]}
-      prepared ; ([:C7 0] [:B7 4334])
+      ;prepared ; ([:C7 0] [:B7 4334])
+      ;still-remaining ; {:B8 B7 * 2}
+      ;evaluated; TODO: change name, consider putting "data" directly in here
+      (recur new-evaluated still-remaining)
+      ;new-evaluated
       )
     )
   )
 
+;; -------------------------
+;; Views
+
+(defn cell [c r data]
+  (let [datum (some #(if (and (= c (:col %)) (= r (:row %))) %) data)]
+    ^{:key (str c r)} [:td [:input {:value (if (= (get datum :view nil) :value) (get datum :value "") (get datum :display (get datum :value "")))
+                                    :on-change #(update-value c r datum (.. % -target -value))
+                                    :on-blur (fn [e] (println (str "blur! " c r)) (toggle-display c r :display))
+                                    :on-focus (fn [e] (println (str "focus! " c r)) (toggle-display c r :value))}]]
+    )
+  )
+(defn row [r cols data]
+  ^{:key (str "row-" r)} [:tr
+                          (cons
+                            ^{:key (str "row-head-" r)} [:th (str r)]
+                            (map #(cell % r data) cols))])
+(defn header-row [cols]
+  ^{:key "header"} [:tr
+   (cons
+     ^{:key "corner"} [:th]
+     (map (fn [c] ^{:key (str "col-head-" c)} [:th c]) cols))])
+
+(defn sheet [data]
+  [:table [:tbody
+           (let [maxrow (highest :row data)
+                 cols (take-while (partial not= (next-letter (highest :col data))) col-letters)]
+             (cons
+               (header-row cols)
+               (map #(row % cols data) (range 1 (inc maxrow)))))
+           ]])
+
 (defn app []
   [:div
-   ;[:h3 "Microtables"]
-   (do
+   [:h3 "Microtables"]
+   #_(do
      (println (.stringify js/JSON (.parse mathjs "3 + 4x")))
      (println (js->clj (.parse js/JSON (.stringify js/JSON (.parse mathjs "3 + 4x")))))
      (println (type (js->clj (.stringify js/JSON (.parse mathjs "3 + 4x")))))
@@ -140,6 +166,8 @@
        (do
          (println rt)
          (println (temp2 (:evaluated rt) (:remaining rt)))))
+     (println "data-atom")
+     (println @data-atom)
      "hi")
    [sheet @data-atom]])