Browse Source

added initialization evaluation step

Brandon Wong 3 years ago
parent
commit
95e2c100c5

+ 3 - 1
frontend/src/cljs/microtables_frontend/events.cljs

@@ -14,8 +14,10 @@
    (-> db/default-db
        (update-in [:table-data] (partial map utils/add-parsed-variables))
        (update-in [:table-data] utils/re-evaluate)
+       (update-in [:alt-table-data] #(utils/walk-modify-data % (fn [c r datum] (if (= (first (:value datum)) "=") (assoc datum :dirty true) datum))))
        (update-in [:alt-table-data] utils/create-all-references)
-       (update-in [:alt-table-data] utils/create-all-back-references))))
+       (update-in [:alt-table-data] utils/create-all-back-references)
+       (update-in [:alt-table-data] utils/evaluate-all))))
 
 
 (re-frame/reg-event-db

+ 30 - 19
frontend/src/cljs/microtables_frontend/utils.cljs

@@ -128,8 +128,6 @@
     {}
     data))
 
-;(create-all-back-references (create-all-references {"A" {1 {:value "=B2"}} "B" {2 {:value "=B3"} 3 {:value "=A1"}}}))
-;(= (walk-modify-data (:alt-table-data microtables-frontend.db/default-db) #(-> %3 (dissoc :refs) (dissoc :inbound) (add-references))) (walk-modify-data (:alt-table-data microtables-frontend.db/default-db) #(add-references (dissoc (dissoc %3 :refs) :inbound))) (create-all-references (:alt-table-data microtables-frontend.db/default-db)))
 
 (defn walk-get-refs
   "Walks through the data map and returns a list of :col/:row maps for each cell which satisfies the predicate (a function accepting col, row, datum)."
@@ -166,7 +164,6 @@
                new-queue (concat (rest queue) (:inbound datum))]
            (recur new-data new-queue)))))))
 
-;(walk-get-refs (set-dirty-flags (create-all-back-references (create-all-references (:alt-table-data microtables-frontend.db/default-db))) "C" 5) #(true? (:dirty %3)))
 
 (defn change-datum-value
   "Modify the value of a datum in the table, and update all applicable references"
@@ -269,11 +266,6 @@
                   new-datum (assoc datum :display evaluated-value)]
               (assoc-in data [c r] new-datum)))))
 
-;(time (gather-variables-and-evaluate-cell {"A" {1 {:value "=A2 + 4" :refs '({:col "A" :row 2})} 2 {:value "2"}}} "A" 1))
-;(time (gather-variables-and-evaluate-cell (create-all-back-references (create-all-references (:alt-table-data microtables-frontend.db/default-db))) "B" 7))
-;(time (set-dirty-flags (create-all-back-references (create-all-references (:alt-table-data microtables-frontend.db/default-db))) "B" 7))
-;(zipmap (map #(str (:col %) (:row %)) (list {:col "A" :row 1} {:col "A" :row 2} {:col "A" :row 3} {:col "A" :row 4})) (list 1 3 5 7))
-
 
 ; THE NEW EVALUATE FUNCTION
 ; - check for cycles in the back references, starting from the target cell (if any, use another function to mark it and its back references with :cycle-error and remove :dirty)
@@ -311,15 +303,36 @@
                           (rest queue))]                                                        ; if the current cell is not marked as dirty, then it has already been processed
           (recur re-evaluated-data new-queue))))))
 
-
-(defn alt-re-evaluate
-  "Evaluate the values of cells that contain formulae, following reference chains if applicable."
-  [data]
-  (let [non-empty-cells (flatten (map (fn [[c v]] (map (fn [[r _]] {:col c :row r}) v)) data))
-        {has-formula true original-values false} (group-by #(= (first (get-in data [(:col %) (:row %) :value])) "=") non-empty-cells)
-        found-cycles (map #(let [found (alt-find-cycle data (:col %) (:row %))]
-                             (if found (assoc % :error found) %)) has-formula)]
-    non-empty-cells))
+;TODO: does this need a cycle check?
+(defn evaluate-all
+  "Evaluates all cells marked as \"dirty\". Generally reserved for the initialization."
+  ([data]
+   (evaluate-all data (walk-get-refs data #(:dirty %3))))
+  ([data queue]
+   (if (empty? queue)
+     data
+     (let [cur (first queue)
+           cc (:col cur)
+           cr (:row cur)
+           dirty? (get-in data [cc cr :dirty])]
+       (if dirty?
+         (let [evaluated (evaluate-from-cell data (:col cur) (:row cur))
+               result (get-in evaluated [cc cr :display])]
+           (if (= result :insufficient-data)
+             (recur data (concat (rest queue) (list cur)))
+             (recur evaluated (rest queue))))
+         (recur data (rest queue)))))))
+
+(evaluate-all (walk-modify-data (:alt-table-data microtables-frontend.db/default-db) (fn [c r datum] (if (= (first (:value datum)) "=") (assoc datum :dirty true) datum))))
+
+#_(defn alt-re-evaluate
+    "Evaluate the values of cells that contain formulae, following reference chains if applicable."
+    [data]
+    (let [non-empty-cells (flatten (map (fn [[c v]] (map (fn [[r _]] {:col c :row r}) v)) data))
+          {has-formula true original-values false} (group-by #(= (first (get-in data [(:col %) (:row %) :value])) "=") non-empty-cells)
+          found-cycles (map #(let [found (alt-find-cycle data (:col %) (:row %))]
+                               (if found (assoc % :error found) %)) has-formula)]
+      non-empty-cells))
 
 
 (defn find-val [data c r]
@@ -332,8 +345,6 @@
       formula? :not-yet
       :else v)))
 
-;TODO: ADD DOCSTRINGS TO ALL CONNECTED FUNCTIONS AND RENAME VARIABLES WHERE NEEDED
-;TODO: figure out how to re-evaluate only when the cell modified affects other cells
 (defn re-evaluate [data]
   (println "re-evaluating" data)
   (let [{has-formula true original-values false} (group-by #(= (first (:value %)) "=") data)