Commit 79eb4054 authored by Bruno Burke's avatar Bruno Burke 🍔
Browse files

Merge branch '28-create-new-multistep-calculation-exercise-type'

parents 62a41be5 9474c40f
......@@ -2,7 +2,6 @@
(:require [clj-helper.vector :as vhelper]
[clj-helper.edn :as edn]))
(defrecord EDNMigrator [type migrations])
(defn get-type "Returns the Schema-Type ID."
......@@ -26,7 +25,7 @@
([schema data version]
(assoc-in data [:_schemas (get-type schema)] version)))
(defn get-pending-migrations [schema data]
(let [current-version (get-current-version (get-type schema) data)
(let [current-version (get-current-version schema data)
all-migrations (get-migrations schema)
vindex (inc (or (vhelper/get-index-by all-migrations :id current-version) -1))]
(drop vindex all-migrations)))
......@@ -43,10 +42,9 @@
(let [pending-migrations (get-pending-migrations schema data)]
(apply-migrations schema data pending-migrations options)))
(defn equal-schemas? [data-a data-b]
(= (get-current-version data-a)
(get-current-version data-b)))
(get-current-version data-b)))
;;; Temporary Testdata, remove before release
......@@ -61,12 +59,10 @@
(defn v3-up [data options]
(assoc data :new-v3-attribute true))
#_(def schema {:type :testobject
:migrations [{:id "20220113-01-initial-version" :up v1-up}
{:id "20220113-02-initial-version" :up v2-up}
{:id "20220113-03-initial-version" :up v3-up}]})
:migrations [{:id "20220113-01-initial-version" :up v1-up}
{:id "20220113-02-initial-version" :up v2-up}
{:id "20220113-03-initial-version" :up v3-up}]})
#_(let [unmigrated-data "hier steht ein Quellcode"
migrator (map->EDNMigrator schema)]
......
(ns leukipp.components.exercise-types.calculation.core
#?(:clj
(:require
[edn-migrator.core :as edn-migrator]
[leukipp.components.exercise-types.create :as create]
[leukipp.components.exercise-types.calculation.build :as build]
[leukipp.components.exercise-types.calculation.check :as check]
[leukipp.components.exercise-types.calculation.migration :as migration]
[leukipp.components.exercise-types.calculation.spec :as spec]
[leukipp.components.exercise-types.calculation.prepare]
[leukipp.components.exercise-types.prepare :as prepare])
:cljs
(:require [reagent.core :as reagent]
[leukipp.components.content-elements.core :as content-manager]
[leukipp.components.exercise-types.calculation.spec :as spec]
[leukipp.components.exercise-types.calculation.prepare]
[leukipp.components.exercise-types.prepare :as prepare]
[leukipp.components.exercise-types.calculation.build :as build]
[leukipp.components.exercise-types.calculation.check :as check]
[leukipp.components.exercise-types.calculation.views.edit :as edit-view]
[leukipp.components.exercise-types.calculation.views.show :as show-view])))
(:require
[edn-migrator.core :as edn-migrator]
[leukipp.components.exercise-types.create :as create]
[leukipp.components.exercise-types.calculation.build :as build]
[leukipp.components.exercise-types.calculation.check :as check]
[leukipp.components.exercise-types.calculation.migration :as migration]
[leukipp.components.exercise-types.calculation.spec :as spec]
[leukipp.components.exercise-types.calculation.views.edit :as edit-view]
[leukipp.components.exercise-types.calculation.views.show :as show-view]
[leukipp.components.exercise-types.prepare :as prepare])))
(def base-core {:type :calculation
:task-description []
:with-oom true
:with-units true
:shuffled true
:calculations []})
(defmethod create/create-exercise :calculation [_ & [{:keys [initial-data]}]]
(let [new-exercise (if initial-data
(update initial-data :core merge base-core)
{:core base-core})]
(edn-migrator/write-schema-information migration/blueprint-migrator new-exercise)))
(defmethod create/create-answer :calculation [_ & [_options]]
(edn-migrator/write-schema-information migration/answer-migrator {:calculations {}}))
(def export {:type :calculation
:title "Berechnung"
:edit {:settings #?(:cljs edit-view/settings :clj nil)
:additional-forms #?(:cljs edit-view/additional-forms :clj nil)}
:build build/build
:prepare {:backend prepare/prepare-backend
:frontend prepare/prepare-frontend}
:build build/build
:migrator {:blueprint migration/blueprint-migrator
:backend migration/backend-migrator
:frontend migration/frontend-migrator
:answer migration/answer-migrator
:result migration/result-migrator}
:renderer #?(:cljs show-view/exercise-renderer :clj nil)
:checker check/calculation-check
:spec ::spec/calculation-question})
(ns leukipp.components.exercise-types.calculation.migrate
(:require
[leukipp.components.exercise-types.multistep-calculation.migrate
:refer
[convert-number-to-object modify-exercise-field-vec set-current-scheme]]))
:refer
[convert-number-to-object modify-exercise-field-vec set-current-scheme]]))
(def exercise-scheme-version "2020-09-07")
......
(ns leukipp.components.exercise-types.calculation.migration
(:require [edn-migrator.core :as migrator]
[leukipp.components.exercise-types.migrate :as migration]
;;Migration 20220114-01
[leukipp.components.exercise-types.calculation.migrations.m20220124-01.answer :as m20220124-01-answer]
[leukipp.components.exercise-types.calculation.migrations.m20220124-01.blueprint :as m20220124-01-blueprint]
[leukipp.components.exercise-types.calculation.migrations.m20220124-01.backend :as m20220124-01-backend]
[leukipp.components.exercise-types.calculation.migrations.m20220124-01.frontend :as m20220124-01-frontend]))
(def blueprint-migrator (migrator/map->EDNMigrator
{:type :exercise-calculation
:migrations [{:id "20220124-01-initial-version" :up m20220124-01-blueprint/up}]}))
(def backend-migrator (migrator/map->EDNMigrator
{:type :exercise-calculation
:migrations [{:id "20220124-01-initial-version" :up m20220124-01-backend/up}]}))
(def frontend-migrator (migrator/map->EDNMigrator
{:type :exercise-calculation
:migrations [{:id "20220124-01-initial-version" :up m20220124-01-frontend/up}]}))
(def answer-migrator (migrator/map->EDNMigrator
{:type :exercise-calculation-answer
:migrations [{:id "20220124-01-initial-version" :up m20220124-01-answer/up}]}))
(def result-migrator (migrator/map->EDNMigrator
{:type :exercise-calculation-result
:migrations []}))
(defn migrate-blueprint [exercise]
(migrator/migrate blueprint-migrator exercise))
(defn migrate-backend [exercise]
(migrator/migrate backend-migrator exercise))
(defn migrate-frontend [exercise]
(migrator/migrate frontend-migrator exercise))
(defn migrate-answer [answer exercise]
(migrator/migrate answer-migrator answer :exercise exercise))
(defn migrate-result [result]
(migrator/migrate result-migrator result))
(defmethod migration/migrate-exercise-blueprint :calculation [exercise & [_options]]
(migrate-blueprint exercise))
(defmethod migration/migrate-exercise-prepared-backend :calculation [exercise & [_options]]
(migrate-backend exercise))
(defmethod migration/migrate-exercise-prepared-frontend :calculation [exercise & [_options]]
(migrate-frontend exercise))
(defmethod migration/migrate-answer :calculation [answer & [options]]
(migrate-answer answer (:exercise options)))
(defmethod migration/migrate-result :calculation [result & [_options]]
(migrate-result result))
(ns leukipp.components.exercise-types.calculation.migrations.m20220124-01.answer
(:require
[clojure.set :refer [difference]]
[leukipp.components.exercise-types.calculation.check :refer [get-calculation-ids]]
[leukipp.components.exercise-types.multistep-calculation.migrations.m20220124-01.blueprint
:refer [migrate-object convert-number-to-object]]))
(def answer-scheme-version "2020-09-07")
(defn convert-calculation-numbers [answer]
(update answer :calculations (fn [calcs] (migrate-object convert-number-to-object calcs))))
(defn add-missing-calculation-objects [exercise answer]
(let [calculations (:calculations answer)
missing-ids (difference (get-calculation-ids exercise) (set (keys calculations)))]
(update answer :calculations (fn [calcs] (reduce (fn [res k] (assoc res k {:number nil}))
calcs missing-ids)))))
(defn wrap-answer-calculations [answer]
(if-not (contains? answer :calculations)
(let [wrapped-answer {}]
(assoc wrapped-answer :calculations answer))
answer))
(defn migrate-answer [answer exercise]
(let [scheme-comparison (compare (get-in answer [:answer-scheme :version]) answer-scheme-version)]
(if (= -1 scheme-comparison)
(->> answer
wrap-answer-calculations
(add-missing-calculation-objects exercise)
convert-calculation-numbers)
answer)))
(defn remove-legacy-migration-info [answer]
(dissoc answer :answer-scheme))
(defn up [answer {:keys [exercise]}]
(-> answer
(migrate-answer exercise)
remove-legacy-migration-info))
(ns leukipp.components.exercise-types.calculation.migrations.m20220124-01.backend
(:require [leukipp.components.exercise-types.calculation.migrations.m20220124-01.blueprint
:refer [migrate-exercise remove-legacy-migration-info]]))
(defn up [exercise _options]
(-> exercise
migrate-exercise
remove-legacy-migration-info))
(ns leukipp.components.exercise-types.calculation.migrations.m20220124-01.blueprint
(:require
[leukipp.components.exercise-types.multistep-calculation.migrations.m20220124-01.blueprint
:refer [convert-number-to-object]]
[leukipp.components.exercise-types.multistep-calculation.prepare :refer [modify-exercise-field-vec]]))
(def exercise-scheme-version "2020-09-07")
(defn modify-calculations [exercise]
(partial modify-exercise-field-vec exercise [:core :calculations]))
(defn set-missing-error-relative [exercise]
((modify-calculations exercise) #(assoc % :error-relative (or (:error-relative %) 1))))
(defn convert-numbers [exercise]
((modify-calculations exercise) convert-number-to-object))
(defn normalize-units [exercise]
(if (get-in exercise [:core :with-units])
((modify-calculations exercise) #(assoc % :units (or (:units %) [])))
((modify-calculations exercise) #(dissoc % :units))))
(defn remove-unneeded-ooms [exercise]
(if-not (get-in exercise [:core :with-oom])
((modify-calculations exercise) #(dissoc % :order-of-magnitude))
exercise))
(defn remove-unneeded-error-keys [exercise]
((modify-calculations exercise) #(dissoc % :error)))
(defn migrate-exercise [exercise]
(let [scheme-comparison (compare (get-in exercise [:exercise-scheme :version]) exercise-scheme-version)]
(if (= -1 scheme-comparison)
(->> exercise
remove-unneeded-error-keys
remove-unneeded-ooms
normalize-units
convert-numbers
set-missing-error-relative)
exercise)))
(defn remove-legacy-migration-info [exercise]
(-> exercise
(dissoc :exercise-scheme)
(dissoc :authoring)))
(defn up [exercise _options]
(-> exercise
migrate-exercise
remove-legacy-migration-info))
(ns leukipp.components.exercise-types.calculation.migrations.m20220124-01.frontend
(:require
[leukipp.components.exercise-types.calculation.migrations.m20220124-01.blueprint
:refer [migrate-exercise remove-legacy-migration-info]]))
(defn up [exercise _options]
(-> exercise
migrate-exercise
remove-legacy-migration-info))
......@@ -2,12 +2,9 @@
(:require
[leukipp.components.exercise-types.build :as e-build]
[leukipp.components.exercise-types.multistep-calculation.check
:refer
[mathjs-eval-and-format mathjs-number-from-number-obj mathjs-str-to-number-obj number-obj]]
[leukipp.components.exercise-types.multistep-calculation.migrate
:refer
[exercise-scheme-version migrate-exercise]]
[leukipp.components.helper :refer [migrate-if-necessary]]))
:refer
[mathjs-eval-and-format mathjs-number-from-number-obj mathjs-str-to-number-obj number-obj]]
[leukipp.components.exercise-types.multistep-calculation.migration :as migration]))
(defmulti number-obj-from-variable (fn [variable] (:type variable)))
......@@ -43,13 +40,7 @@
exercise))
(defn build [exercise]
(if-let [migrated-exercise (migrate-if-necessary exercise :exercise-scheme "multistep-calculation"
exercise-scheme-version migrate-exercise)]
(-> migrated-exercise
prepare-variables)
(-> exercise
(select-keys [:title :id])
(assoc :debug-info "unmigrateable"))))
(prepare-variables (migration/migrate-blueprint exercise)))
(defmethod e-build/build :multistep-calculation [exercise & [options]]
(defmethod e-build/build :multistep-calculation [exercise & [_options]]
(build exercise))
(ns leukipp.components.exercise-types.multistep-calculation.core
#?(:clj
(:require
[edn-migrator.core :as edn-migrator]
[leukipp.components.exercise-types.create :as create]
[leukipp.components.exercise-types.multistep-calculation.build :as build]
[leukipp.components.exercise-types.multistep-calculation.check :as check]
[leukipp.components.exercise-types.multistep-calculation.migration :as migration]
[leukipp.components.exercise-types.multistep-calculation.spec :as spec]
[leukipp.components.exercise-types.multistep-calculation.prepare]
[leukipp.components.exercise-types.prepare :as prepare])
:cljs
(:require [reagent.core :as reagent]
[leukipp.components.content-elements.core :as content-manager]
[leukipp.components.exercise-types.multistep-calculation.spec :as spec]
[leukipp.components.exercise-types.multistep-calculation.build :as build]
[leukipp.components.exercise-types.multistep-calculation.check :as check]
[leukipp.components.exercise-types.multistep-calculation.views.edit :as edit-view]
[leukipp.components.exercise-types.multistep-calculation.views.show :as show-view]
[leukipp.components.exercise-types.multistep-calculation.prepare]
[leukipp.components.exercise-types.prepare :as prepare])))
(:require
[edn-migrator.core :as edn-migrator]
[leukipp.components.exercise-types.create :as create]
[leukipp.components.exercise-types.multistep-calculation.build :as build]
[leukipp.components.exercise-types.multistep-calculation.check :as check]
[leukipp.components.exercise-types.multistep-calculation.migration :as migration]
[leukipp.components.exercise-types.multistep-calculation.spec :as spec]
[leukipp.components.exercise-types.multistep-calculation.views.edit :as edit-view]
[leukipp.components.exercise-types.multistep-calculation.views.show :as show-view]
[leukipp.components.exercise-types.prepare :as prepare])))
(def base-core {:type :multistep-calculation
:task-description []
:with-oom true
:with-units true
:assocs []
:params []
:assignments []
:steps []})
(defmethod create/create-exercise :multistep-calculation [_ & [{:keys [initial-data]}]]
(let [new-exercise (if initial-data
(-> initial-data
(assoc :variables [])
(update :core merge base-core))
{:variables []
:core base-core})]
(edn-migrator/write-schema-information migration/blueprint-migrator new-exercise)))
(defmethod create/create-answer :multistep-calculation [_ & [_options]]
(edn-migrator/write-schema-information migration/answer-migrator {:steps []}))
(def export {:type :multistep-calculation
:title "Multistep-Berechnung"
:edit {:settings #?(:cljs edit-view/settings :clj nil)
:additional-forms #?(:cljs edit-view/additional-forms :clj nil)}
:build build/build
:prepare {:backend prepare/prepare-backend
:frontend prepare/prepare-frontend}
:build build/build
:migrator {:blueprint migration/blueprint-migrator
:backend migration/backend-migrator
:frontend migration/frontend-migrator
:answer migration/answer-migrator
:result migration/result-migrator}
:renderer #?(:cljs show-view/exercise-renderer :clj nil)
:checker check/multistep-calculation-check
:spec ::spec/multistep-calculation-question})
(ns leukipp.components.exercise-types.multistep-calculation.create
(:require [leukipp.components.exercise-types.create :as create])
)
;;; Bei Bedarf kannst du hier noch die defmethods für create/create-answer und create-exercise implementieren
;;; Ansonten werden die default methoden für neue Aufgaben genutzt.
......@@ -82,18 +82,20 @@
(let [base-keys [:id :sign :idx :type :units]]
(modify-exercise-field-vec exercise [:core :assignments]
(fn [assignment]
(if (= (:type assignment) :formula)
(select-keys assignment (concat base-keys [:formula :calc-mapping]))
(select-keys assignment base-keys))))))
(case (:type assignment)
:formula (select-keys assignment (concat base-keys [:formula :calc-mapping]))
:constant (select-keys assignment base-keys)
assignment)))))
(defn select-step-keys [exercise]
(let [assignments (get-in exercise [:core :assignments])
base-keys [:id :assoc-id :assignment-id]]
(modify-exercise-field-vec exercise [:core :steps]
(fn [step] (case (:type (find-in-vec-by-id assignments (:assignment-id step)))
(fn [step] (case (:type (find-in-vec-by-id assignments (:assignment-id step)))
:formula (select-keys step (conj base-keys :var-mapping))
:constant (select-keys step (conj base-keys :number))
nil (select-keys step base-keys))))))
nil (select-keys step base-keys)
step)))))
(defn select-variable-keys [exercise]
(let [base-keys [:id :human-id :type :data]]
......
(ns leukipp.components.exercise-types.multistep-calculation.migration
(:require [edn-migrator.core :as migrator]
[leukipp.components.exercise-types.programming.common :as ep-common]
[leukipp.components.exercise-types.programming.spec :refer [programming-languages]]
[leukipp.components.exercise-types.migrate :as migration]
[clj-helper.vector :as vhelper]
[clojure.string :as str]
[clj-helper.string :as shelper]
;;Migration 20220114-01
[leukipp.components.exercise-types.multistep-calculation.migrations.m20220124-01.answer :as m20220124-01-answer]
[leukipp.components.exercise-types.multistep-calculation.migrations.m20220124-01.blueprint :as m20220124-01-blueprint]
[leukipp.components.exercise-types.multistep-calculation.migrations.m20220124-01.backend :as m20220124-01-backend]
[leukipp.components.exercise-types.multistep-calculation.migrations.m20220124-01.frontend :as m20220124-01-frontend]
[leukipp.components.exercise-types.multistep-calculation.migrations.m20220124-01.result :as m20220124-01-result]))
;;; Ich hab hier beispielhaft eine Migration mit allen Objekten (answer,blueprint,backend,frontend,result) erstellt
;;; du kannst aber problemlos auch z.B. die result-migration weglassen oder in der backend-migration an die blueprint-migration weiterleiten, wenn die in den beiden Fällen identisch ist.
;;; TODO Das bisherige Migration Schema von multistep_calc ist nicht kompatibel mit dem neuen. Folglich werden alle Exercises als noch nicht migriert erkannt.
;;; Du kannst aber in deinen Migrationen deine alten schema Angaben suchen und entsprechend Fälle unterscheiden.
[leukipp.components.exercise-types.multistep-calculation.migrations.m20220124-01.frontend :as m20220124-01-frontend]))
(def blueprint-migrator (migrator/map->EDNMigrator
{:type :exercise-multistep-calculation
:migrations [{:id "20220124-01-initial-version" :up m20220124-01-blueprint/up}]}))
(def backend-migrator (migrator/map->EDNMigrator
{:type :exercise-multistep-calculation
:migrations [{:id "20220124-01-initial-version" :up m20220124-01-backend/up}]}))
{:type :exercise-multistep-calculation
:migrations [{:id "20220124-01-initial-version" :up m20220124-01-backend/up}]}))
(def frontend-migrator (migrator/map->EDNMigrator
{:type :exercise-multistep-calculation
:migrations [{:id "20220124-01-initial-version" :up m20220124-01-frontend/up}]}))
{:type :exercise-multistep-calculation
:migrations [{:id "20220124-01-initial-version" :up m20220124-01-frontend/up}]}))
(def answer-migrator (migrator/map->EDNMigrator
{:type :exercise-multistep-calculation-answer
......@@ -39,9 +25,7 @@
(def result-migrator (migrator/map->EDNMigrator
{:type :exercise-multistep-calculation-result
:migrations [{:id "20220124-01-initial-version" :up m20220124-01-result/up}]}))
:migrations []}))
(defn migrate-blueprint [exercise]
(migrator/migrate blueprint-migrator exercise))
......@@ -58,20 +42,17 @@
(defn migrate-result [result]
(migrator/migrate result-migrator result))
(defmethod migration/migrate-exercise-blueprint :multistep-calculation [exercise & [options]]
(defmethod migration/migrate-exercise-blueprint :multistep-calculation [exercise & [_options]]
(migrate-blueprint exercise))
(defmethod migration/migrate-exercise-prepared-backend :multistep-calculation [exercise & [options]]
(defmethod migration/migrate-exercise-prepared-backend :multistep-calculation [exercise & [_options]]
(migrate-backend exercise))
(defmethod migration/migrate-exercise-prepared-frontend :multistep-calculation [exercise & [options]]
(defmethod migration/migrate-exercise-prepared-frontend :multistep-calculation [exercise & [_options]]
(migrate-frontend exercise))
(defmethod migration/migrate-answer :multistep-calculation [answer & [options]]
(migrate-answer answer (:exercise options)))
(defmethod migration/migrate-result :multistep-calculation [result & [options]]
(defmethod migration/migrate-result :multistep-calculation [result & [_options]]
(migrate-result result))
(ns leukipp.components.exercise-types.multistep-calculation.migrations.m20220124-01.answer)
(defn up [answer options]
;;;TODO Hier kommen Answers rein, die keinen Versionshinweis haben
answer)
(def answer-scheme-version "2020-05-20")
(defn wrap-answer-steps [answer]
(if-not (contains? answer :steps)
(let [wrapped-answer {}]
(assoc wrapped-answer :steps answer))
answer))
(defn vectorize-var-mappings [answer]
(update answer :steps
#(reduce (fn [res step]
(conj res
(if-let [var-mapping (:var-mapping step)]
(-> step
(dissoc :var-mapping)
(assoc :vars (reduce-kv (fn [res _ v] (conj res v)) [] var-mapping)))
step)))
[] %)))
(defn migrate-answer [answer]
(let [scheme-comparison (compare (get-in answer [:answer-scheme :version]) answer-scheme-version)]
(if (= -1 scheme-comparison)
(-> answer
wrap-answer-steps
vectorize-var-mappings)
answer)))
(defn remove-legacy-migration-info [answer]
(dissoc answer :answer-scheme))
(defn up [answer _options]
(-> answer
migrate-answer