Ab sofort ist der Login auf der Weboberfläche von git.fh-muenster.de bevorzugt über FH Muenster SSO möglich.

Commit 8b075062 authored by Bruno Burke's avatar Bruno Burke 😁

Merge branch '28-create-new-multistep-calculation-exercise-type' into bulma-css

parents 84567e86 d85fdd75
<!doctype html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset='utf-8'>
......@@ -27,4 +27,3 @@
<script src="cljs-out/dev-main-devcards.js"></script>
</body>
</html>
......@@ -108,9 +108,10 @@
"d" [{:factor 8.64 :oom 4 :unit "s" :expo 1}]
"l" [{:factor 1 :oom -1 :unit "m" :expo 3}]})
(def dezibel-unit-mapping {"B" [{:factor 1 :oom 1 :unit "dB" :expo 1}]})
(def additional-unit-mappings {"B" [{:factor 1 :oom 1 :unit "dB" :expo 1}]
"°" [{:factor 1 :oom 0 :unit "°" :expo 1}]})
(def base-unit-set #{"m" "kg" "s" "A" "K" "mol" "cd" "dB"})
(def base-unit-set #{"m" "kg" "s" "A" "K" "mol" "cd" "dB" "°"})
(def unit-replace-map {"kg" {:unit "g" :prefix "k"}
"dB" {:unit "B" :prefix "d"}})
......@@ -123,7 +124,7 @@
(def base-unit-map (reduce (fn [res-map base-unit] (assoc res-map base-unit 0)) {} base-unit-set))
(def unit-mapping (conj si-unit-mapping dezibel-unit-mapping))
(def unit-mapping (merge si-unit-mapping additional-unit-mappings))
(def prefix-set (set (keys prefix-mapping)))
......
......@@ -42,7 +42,7 @@
[:span.has-text-info "✘ "]))
(defn binary-input [{:keys [default-bits result on-change-fn bitcount]
:or {bitcount 8}}]
:or {bitcount 8}}]
(let [bits (reagent/atom
(or default-bits
(vec (repeat (or bitcount 8) false))))
......@@ -52,44 +52,42 @@
(fn [this [_ {:as old-args}]]
(let [new-bitcount (:bitcount (reagent/props this))
old-bitcount (:bitcount old-args)]
(when (not= new-bitcount old-bitcount)
(reset! bits (mapv
#(if (< % (count @bits))
(get @bits %)
false)
(range bitcount))))))
:reagent-render
(fn [{:keys [default-bits result on-change-fn bitcount]}]
[:div.row {:style {:margin "auto auto auto auto" :display :inline-block}}
[:div.col.s12.center
[:p.flow-text.center
(when result
(if-not (pos? (:points result))
[wrong-tick]
[correct-tick]))]]
(when-not result
[:div.col.s12
[:div.row
[:div.columns {:key (hash bitcount)}
(doall (for [i (range bitcount #_(count @bits))]
[:div.column {:key (str id "-cb-" i)
:style {:display :inline-block}}
(if (get @bits i)
"1"
"0")[:br]
[ui/checkbox
{:id (str id "-cb-" i)
:type "checkbox"
:checked? (get @bits i)
:on-change #(do
(swap! bits update i not)
(on-change-fn @bits))}]]))]
[:p.is-pulled-left
[:acronym {:title "most significant bit"} "MSB"]]
[:p.is-pulled-right
[:acronym {:title "least significant bit"} "LSB"]
]]])])
})))
(when (not= new-bitcount old-bitcount)
(reset! bits (mapv
#(if (< % (count @bits))
(get @bits %)
false)
(range bitcount))))))
:reagent-render
(fn [{:keys [default-bits result on-change-fn bitcount]}]
[:div.row {:style {:margin "auto auto auto auto" :display :inline-block}}
[:div.col.s12.center
[:p.flow-text.center
(when result
(if-not (pos? (:points result))
[wrong-tick]
[correct-tick]))]]
(when-not result
[:div.col.s12
[:div.row
[:div.columns {:key (hash bitcount)}
(doall (for [i (range bitcount #_(count @bits))]
[:div.column {:key (str id "-cb-" i)
:style {:display :inline-block}}
(if (get @bits i)
"1"
"0") [:br]
[ui/checkbox
{:id (str id "-cb-" i)
:type "checkbox"
:checked? (get @bits i)
:on-change #(do
(swap! bits update i not)
(on-change-fn @bits))}]]))]
[:p.is-pulled-left
[:acronym {:title "most significant bit"} "MSB"]]
[:p.is-pulled-right
[:acronym {:title "least significant bit"} "LSB"]]]])])})))
(defn error-div [error]
(fn [error]
......@@ -135,7 +133,6 @@
[:br]
(str error)]])
(defn styles [style-urls]
[:<>
(for [su style-urls]
......
......@@ -42,7 +42,7 @@
(defn parse-unit [string]
(when (string? string)
(when-let [matched-string (re-matches #"^[a-zA-z]*" string)]
(when-let [matched-string (re-matches #"^[a-zA-ZΩ°]*" string)]
(replace (subs matched-string 0 3) #"Ohm|ohm" "Ω"))))
(defn parse-prefix [string]
......@@ -75,11 +75,16 @@
(if-not (or (= "0" significand) (re-matches #"^\-?0?$" oom))
(str "\\cdot 10^{" oom "}") ""))
(defn latex-replace-unit [unit]
(-> unit
(replace "Ω" "\\Omega ")
(replace "°" "\\degree ")))
(defn build-fraction-map [unit-list]
(reduce
(fn [res-map unit-map]
(let [prefix (replace (:prefix unit-map) "µ" "\\mu ")
unit (replace (:unit unit-map) "Ω" "\\Omega ")
unit (latex-replace-unit (:unit unit-map))
combined-unit (str prefix unit)
expo (:expo unit-map)]
(if (= "-" (first expo))
......
(ns lernmeister.components.exercise-types.multistep-calculation.views.common
(:require [lernmeister.components.common :refer [latex-span]]
[lernmeister.components.exercise-types.calchelper
:refer
[build-units-latex-string units-to-set]]
[lernmeister.components.exercise-types.multistep-calculation.check
:refer
[number-obj]]
......@@ -7,7 +10,9 @@
[lernmeister.components.modal-editor.helper
:refer
[get-var-symbol-data]]
[lernmeister.components.modal-editor.renderers :refer [sign-with-subtext]]
[lernmeister.components.modal-editor.renderers
:refer
[sign-with-subtext]]
[lernmeister.components.ui :as ui]))
(def editor-type-mapping {:edit :calculation :show :calc-answer})
......@@ -68,6 +73,15 @@
{:path (conj step-path :var-mapping)}
{:path [:authoring (keyword step-id) :number]}]))
(defn add-to-selectable-units [path selectable-units subject]
(let [cur-units (get-in subject path)]
(when (not-empty cur-units)
(let [units-ident (units-to-set cur-units)]
(when-not (contains? @selectable-units units-ident)
(swap! selectable-units assoc units-ident
{:units cur-units
:latex-str (build-units-latex-string cur-units)}))))))
(defn assignment-type-from-step-idx [step-idx assignments steps]
(:type (find-in-vec-by-id assignments (get-in steps [step-idx :assignment-id]))))
......@@ -106,8 +120,8 @@
[:div.level-item
[blue-line]]]]]))
(defn discrete-phys-val-editor [{:keys [context assignment-type path collats-fn symbol-data modal-id
modal-state-atom latex-number-str latex-units-str]}]
(defn discrete-phys-val-editor [{:keys [context assignment-type path collats-fn symbol-data modal-state-atom
latex-number-str latex-units-str selectable-units]}]
(let [editable-number? (and assignment-type
(not (and (= context :edit) (not= assignment-type :constant))))
editable-units? (and assignment-type (not= context :edit))]
......@@ -115,12 +129,11 @@
[:div.left-icon (if editable-number?
{:class "has-background-success green-border pointer"
:on-click (fn [] (reset! modal-state-atom
{:modal-visible? true
:path path
:type :number-only
:collats-fn collats-fn
:symbol-data symbol-data})
(ui/open-modal (str "#" modal-id)))}
{:modal-visible? true
:path path
:type :number-only
:collats-fn collats-fn
:symbol-data symbol-data}))}
{:class "has-background-grey-light grey-border"})
[:span.icon [:i.far.fa-edit]]]
[:div.left-latex {:class (if editable-number? "green-border" "grey-border")}
......@@ -130,18 +143,21 @@
[latex-span latex-units-str]]
[:div.right-icon (if editable-units?
{:class "has-background-success green-border pointer"
:on-click (fn [] (reset! modal-state-atom
{:modal-visible? true
:path path
:type :units-only
:collats-fn collats-fn
:symbol-data symbol-data})
(ui/open-modal (str "#" modal-id)))}
:on-click (fn []
(reset! modal-state-atom
{:modal-visible? true
:on-close-fn (partial
add-to-selectable-units
(conj path :units) selectable-units)
:path path
:type :units-only
:collats-fn collats-fn
:symbol-data symbol-data}))}
{:class "has-background-grey-light grey-border"})
[:span.icon [:i.far.fa-edit]]]]))
(defn step-config [{:keys [step vars path assocs params assignments steps change-fn collats-fn
phys-val-collats-fn symbol-data modal-id modal-state-atom latex-number-str
phys-val-collats-fn symbol-data modal-state-atom selectable-units latex-number-str
latex-units-str context assignment-type step-result]}]
[:<>
[:td
......@@ -173,15 +189,14 @@
(when-not step-result
[:div [:a.button.is-success
{:on-click (fn [] (reset! modal-state-atom
{:modal-visible? true
:path path
:type (get editor-type-mapping context)
:with-oom true
:with-units true
:collats-fn phys-val-collats-fn
:symbol-data symbol-data})
(ui/open-modal (str "#" modal-id)))}
[:span.icon [:i.fas.fa-edit]]]])
{:modal-visible? true
:path path
:type (get editor-type-mapping context)
:with-oom true
:with-units true
:collats-fn phys-val-collats-fn
:symbol-data symbol-data}))}
[:span.icon [:i.far.fa-edit]]]])
[:div.symbols
(map-indexed (fn [index var]
(let [symbol-data (get-var-symbol-data var assocs params assignments steps)
......@@ -204,7 +219,7 @@
:path path
:collats-fn phys-val-collats-fn
:symbol-data symbol-data
:modal-id modal-id
:modal-state-atom modal-state-atom
:latex-number-str latex-number-str
:latex-units-str latex-units-str}])]])
:latex-units-str latex-units-str
:selectable-units selectable-units}])]])
......@@ -74,174 +74,158 @@
names-mapping)]])
(defn new-exercise-form [{:keys [exercise-atom change-fn phrase-fn]}]
(let [modal-id (str "multicalc-modal-" (gensym "edit-"))]
(reagent/create-class
{:display-name "multistep-assignment-form"
:reagent-render
(fn [{:keys [exercise-atom change-fn phrase-fn]}]
(let [exercise @exercise-atom
exercise-core (:core exercise)
with-oom (get-in exercise [:core :with-oom])
with-units (get-in exercise [:core :with-units])
additional-descriptions (get-in exercise [:core :additional-descriptions])
description-ids (get-in exercise [:core :description-ids])
add-desc-options (if (not-empty additional-descriptions)
(reduce-kv (fn [res k v] (conj res {:key (keyword k) :title (:name v)}))
[{:key :$-§ :title "-"}] additional-descriptions)
[])
assignment-categories (get-in exercise [:core :assignment-categories])
assocs (get-in exercise [:core :assocs])
params (get-in exercise [:core :params])
assignments (get-in exercise [:core :assignments])
steps (get-in exercise [:core :steps])
authoring (:authoring exercise)]
[:<>
(when assignment-categories
[assignment-categories-input {:assignment-categories assignment-categories
:assignments assignments
:change-fn change-fn
:phrase-fn phrase-fn}])
(when (map? additional-descriptions)
[additional-descriptions-input {:descriptions additional-descriptions
:description-ids description-ids
:assocs assocs
:change-fn change-fn
:exercise-atom exercise-atom}])
[assocs-input {:assocs assocs
:params params
:steps steps
:change-fn change-fn
:phrase-fn phrase-fn
:add-desc-options add-desc-options}]
[params-input {:core exercise-core
:params params
:assocs assocs
:assignments assignments
:steps steps
:authoring authoring
:variables (:variables exercise)
:change-fn change-fn
:with-oom with-oom
:with-units with-units
:modal-id modal-id
:phrase-fn phrase-fn
:description-ids description-ids
:add-desc-options add-desc-options
:modal-state-atom modal-state-atom}]
[assignments-input {:assignment-categories assignment-categories
:assignments assignments
:steps steps
:change-fn change-fn
:with-oom with-oom
:with-units with-units
:modal-id modal-id
:phrase-fn phrase-fn
:modal-state-atom modal-state-atom}]
[steps-input {:core exercise-core
:assocs assocs
:params params
(let [exercise @exercise-atom
exercise-core (:core exercise)
with-oom (get-in exercise [:core :with-oom])
with-units (get-in exercise [:core :with-units])
additional-descriptions (get-in exercise [:core :additional-descriptions])
description-ids (get-in exercise [:core :description-ids])
add-desc-options (if (not-empty additional-descriptions)
(reduce-kv (fn [res k v] (conj res {:key (keyword k) :title (:name v)}))
[{:key :$-§ :title "-"}] additional-descriptions)
[])
assignment-categories (get-in exercise [:core :assignment-categories])
assocs (get-in exercise [:core :assocs])
params (get-in exercise [:core :params])
assignments (get-in exercise [:core :assignments])
steps (get-in exercise [:core :steps])
authoring (:authoring exercise)]
[:<>
(when assignment-categories
[assignment-categories-input {:assignment-categories assignment-categories
:assignments assignments
:change-fn change-fn
:phrase-fn phrase-fn}])
(when (map? additional-descriptions)
[additional-descriptions-input {:descriptions additional-descriptions
:description-ids description-ids
:assocs assocs
:change-fn change-fn
:exercise-atom exercise-atom}])
[assocs-input {:assocs assocs
:params params
:steps steps
:change-fn change-fn
:phrase-fn phrase-fn
:add-desc-options add-desc-options}]
[params-input {:core exercise-core
:params params
:assocs assocs
:assignments assignments
:steps steps
:authoring authoring
:variables (:variables exercise)
:change-fn change-fn
:with-oom with-oom
:with-units with-units
:phrase-fn phrase-fn
:description-ids description-ids
:add-desc-options add-desc-options
:modal-state-atom modal-state-atom}]
[assignments-input {:assignment-categories assignment-categories
:assignments assignments
:steps steps
:authoring authoring
:change-fn change-fn
:modal-id modal-id
:with-oom with-oom
:with-units with-units
:phrase-fn phrase-fn
:description-ids description-ids
:add-desc-options add-desc-options
:modal-state-atom modal-state-atom}]
[ui/modal-panel
{:state (reagent/cursor modal-state-atom [:modal-visible?])
:title [modal-renderers/editor-heading (:symbol-data @modal-state-atom)]
:footer [:div.buttons
[:a.btn.white.black-text
{:on-click (fn []
(swap! modal-state-atom update :modal-visible? not))}
"Schließen"]]}
[:div.content {:id modal-id :key modal-id}
[modal-editor
{:subject exercise
:change-fn change-fn
:phrase-fn phrase-fn
:visible? (:modal-visible? @modal-state-atom)
:path (:path @modal-state-atom)
:variable-idx (:variable-idx @modal-state-atom)
:type (:type @modal-state-atom)
:with-oom (:with-oom @modal-state-atom)
:with-units (:with-units @modal-state-atom)
:collats-fn (:collats-fn @modal-state-atom)
:symbol-data (:symbol-data @modal-state-atom)}]]]]))
:component-did-mount
(fn [] (ui/init-modal (str "#" modal-id)))})))
[steps-input {:core exercise-core
:assocs assocs
:params params
:assignments assignments
:steps steps
:authoring authoring
:change-fn change-fn
:phrase-fn phrase-fn
:description-ids description-ids
:add-desc-options add-desc-options
:modal-state-atom modal-state-atom}]
[ui/modal-panel
{:state (reagent/cursor modal-state-atom [:modal-visible?])
:title [modal-renderers/editor-heading (:symbol-data @modal-state-atom)]
:footer [:div.buttons
[:a.btn.white.black-text
{:on-click (fn []
(swap! modal-state-atom update :modal-visible? not))}
"Schließen"]]}
[:div.content
[modal-editor {:subject exercise
:change-fn change-fn
:phrase-fn phrase-fn
:visible? (:modal-visible? @modal-state-atom)
:path (:path @modal-state-atom)
:variable-idx (:variable-idx @modal-state-atom)
:type (:type @modal-state-atom)
:with-oom (:with-oom @modal-state-atom)
:with-units (:with-units @modal-state-atom)
:collats-fn (:collats-fn @modal-state-atom)
:symbol-data (:symbol-data @modal-state-atom)}]]]]))
(defn new-exercise-options [{:keys [exercise change-fn phrase-fn]}]
(let [id (gensym "phrasing-collaplible")]
(reagent/create-class
{;;;:component-did-mount #(js/M.Collapsible.init (js/document.querySelector (str "#" id)))
:reagent-render
(fn [{:keys [exercise change-fn phrase-fn]}]
(let [exercise-core (:core exercise)
assoc-indices (range (count (:assocs exercise-core)))
assignment-indices (range (count (:assignments exercise-core)))
assignments-phrase (phrase-fn :assignments)
hide-assocs? (boolean (:hide-assocs exercise-core))
hide-assignments? (boolean (:hide-assignments exercise-core))
additional-descriptions? (contains? exercise-core :additional-descriptions)
assignment-categories? (boolean (:assignment-categories exercise-core))]
[:<>
[:div.row
[:div.col.s12 [:p [:b "Optionen:"]]]]
[:div.row
[:div.col.s5
[ui/checkbox
{:on-change #(change-fn [:core :hide-assocs] (not hide-assocs?))
:checked? hide-assocs?
:label (str (phrase-fn :assocs) " verbergen?")}]]]
[:div.row
[:div.col.s5
[ui/checkbox
{:on-change #(change-fn [:core :hide-assignments] (not hide-assignments?))
:checked? hide-assignments?
:label (str assignments-phrase " verbergen?")}]]]
[:div.row
[:div.col.s12
[ui/checkbox
{:on-change #(if assignment-categories?
(change-fn [:core] (dissoc exercise-core :assignment-categories)
(get-collats-for-vec [:core :assignments] assignment-indices
[:category-id]))
(change-fn [:core] (assoc exercise-core :assignment-categories [])
(get-collats-for-vec [:core :assignments] assignment-indices
{:category-id nil})))
:checked? assignment-categories?
:label (str "Kategorien zur Differenzierung von " assignments-phrase "?")}]]]
[:div.row
[:div.col.s12
[ui/checkbox
{:on-change #(if additional-descriptions?
(change-fn [:core] (-> exercise-core
(dissoc :additional-descriptions)
(dissoc :description-ids))
(get-collats-for-vec [:core :assocs] assoc-indices
[:additional-description-id]))
(change-fn [:core] (assoc exercise-core :additional-descriptions {})
(get-collats-for-vec [:core :assocs] assoc-indices
{:additional-description-id nil})))
:checked? additional-descriptions?
:label "Ergänzende Beschreibungen?"}]]]
[ui/collapsible
{:elements [{:icon "edit"
:label "Benennungen"
:content [phrasings-input {:names-mapping (sort-names-mapping names-map)
:phrasing-map (get-in exercise [:core :phrasing])
:path [:core :phrasing]
:change-fn change-fn}]}]}]
[ui/collapsible
{:elements [{:icon "edit"
:label "Transfer-Texte"
:content [phrasings-input {:names-mapping (sort-names-mapping transfer-names)
:phrasing-map (get-in exercise [:core :transfer-phrasing])
:path [:core :transfer-phrasing]
:change-fn change-fn}]}]}]]))})))
(let [exercise-core (:core exercise)
assoc-indices (range (count (:assocs exercise-core)))
assignment-indices (range (count (:assignments exercise-core)))
assignments-phrase (phrase-fn :assignments)
hide-assocs? (boolean (:hide-assocs exercise-core))
hide-assignments? (boolean (:hide-assignments exercise-core))
additional-descriptions? (contains? exercise-core :additional-descriptions)
assignment-categories? (boolean (:assignment-categories exercise-core))]
[:<>
[:div.row
[:div.col.s12 [:p [:b "Optionen:"]]]]
[:div.row
[:div.col.s5
[ui/checkbox
{:on-change #(change-fn [:core :hide-assocs] (not hide-assocs?))
:checked? hide-assocs?
:label (str (phrase-fn :assocs) " verbergen?")}]]]
[:div.row
[:div.col.s5
[ui/checkbox
{:on-change #(change-fn [:core :hide-assignments] (not hide-assignments?))
:checked? hide-assignments?
:label (str assignments-phrase " verbergen?")}]]]
[:div.row
[:div.col.s12
[ui/checkbox
{:on-change #(if assignment-categories?