From c56a122c242cc489d369a4f6ef0e133f28e54036 Mon Sep 17 00:00:00 2001 From: Bruno Burke Date: Wed, 22 Jan 2020 11:59:49 +0100 Subject: [PATCH] add basic check (with fixed points) for text-correction, also check if corrections are still valid --- .../components/exercise_types/core.cljc | 1 + .../exercise_types/text_correction/check.cljc | 53 +++++++++++++------ .../text_correction/common.cljc | 19 +++++++ .../exercise_types/text_correction/core.cljc | 4 +- .../exercise_types/text_correction/spec.cljc | 31 +++++------ .../text_correction/views/edit.cljs | 21 +++++--- .../text_correction/views/show.cljs | 27 +++++----- 7 files changed, 100 insertions(+), 56 deletions(-) create mode 100644 src/cljc/lernmeister/components/exercise_types/text_correction/common.cljc diff --git a/src/cljc/lernmeister/components/exercise_types/core.cljc b/src/cljc/lernmeister/components/exercise_types/core.cljc index a83dacb..bb9d971 100644 --- a/src/cljc/lernmeister/components/exercise_types/core.cljc +++ b/src/cljc/lernmeister/components/exercise_types/core.cljc @@ -64,6 +64,7 @@ :list :simple-text :sorting + :text-correction } #_(get-types-set)) (s/def :exercise/answers (s/coll-of ::answer :kind vector? :min-count 1 :distinct true)) diff --git a/src/cljc/lernmeister/components/exercise_types/text_correction/check.cljc b/src/cljc/lernmeister/components/exercise_types/text_correction/check.cljc index 3332333..75bded1 100644 --- a/src/cljc/lernmeister/components/exercise_types/text_correction/check.cljc +++ b/src/cljc/lernmeister/components/exercise_types/text_correction/check.cljc @@ -1,24 +1,45 @@ (ns lernmeister.components.exercise-types.text-correction.check - (:require [lernmeister.components.exercise-types.check :as e-check])) + (:require [lernmeister.components.exercise-types.check :as e-check] + [lernmeister.components.exercise-types.text-correction.common :refer [split-text]] + [clojure.string :refer [join]])) -(defn sc-get-points [answer-options answer] - (reduce + - (map (fn [ao] - (if (= (:id ao) answer) - (:selected-points ao) - (:unselected-points ao))) - answer-options))) -(defn single-choice-check [exercise answer callback] - (let [answer-options (get-in exercise [:core :answers]) - points (sc-get-points answer-options answer)] +(defn apply-corrections [text corrections] + (join + (map-indexed + (fn [index text-fragment] + (let [fragment-id (str index "-" text-fragment)] + (if-let [correction (get corrections fragment-id)] + correction + text-fragment) + )) + (split-text text)))) + + +(defn text-correction-check [exercise answer callback] + (let [text (get-in exercise [:core :correction-text]) + reference-corrections (into {} + (map (fn [[id correction]] + (vector id (:correct-word correction))) + (get-in exercise [:core :corrections]))) + user-corrections (into {} + (map (fn [[id correction]] + (vector id (:correct-word correction))) + answer)) + reference-text (apply-corrections text reference-corrections) + user-text (apply-corrections text user-corrections) + points (if (= reference-text user-text) + 5 + 0)] + (println reference-corrections) + (println reference-text) + (println user-corrections) + (println user-text) (callback) - {:answer-id answer + {:corrections answer :correct (pos? points) :points points - :points-max (apply max - (map #(sc-get-points answer-options (:id %)) - answer-options))})) + :points-max 5})) (defmethod e-check/check-answer :text-correction [exercise answer callback] - (single-choice-check exercise answer callback)) + (text-correction-check exercise answer callback)) diff --git a/src/cljc/lernmeister/components/exercise_types/text_correction/common.cljc b/src/cljc/lernmeister/components/exercise_types/text_correction/common.cljc new file mode 100644 index 0000000..d99ac3e --- /dev/null +++ b/src/cljc/lernmeister/components/exercise_types/text_correction/common.cljc @@ -0,0 +1,19 @@ +(ns lernmeister.components.exercise-types.text-correction.common + (:require [clojure.string :refer [split]])) + +(defn split-text [text] + (-> text + ;;(split #"(\ |\. |\,)") + (split #"(\b[\wäÄöÖüÜß]+|\W)") + (->> + (filter not-empty) + ) + )) + + +(defn valid-correction? [text correction] + (let [fragments (split-text text)] + (and + (>= (count fragments) (:index correction)) + (= (nth fragments (:index correction)) + (:word correction))))) diff --git a/src/cljc/lernmeister/components/exercise_types/text_correction/core.cljc b/src/cljc/lernmeister/components/exercise_types/text_correction/core.cljc index 09149f9..f2dc5c0 100644 --- a/src/cljc/lernmeister/components/exercise_types/text_correction/core.cljc +++ b/src/cljc/lernmeister/components/exercise_types/text_correction/core.cljc @@ -16,6 +16,6 @@ :additional-forms #?(:cljs edit-view/additional-forms :clj nil)} :prepare prepare/prepare :renderer #?(:cljs show-view/exercise-renderer :clj nil) - :checker check/single-choice-check - :spec ::tc-spec/single-choice}) + :checker check/text-correction-check + :spec ::tc-spec/text-correction}) diff --git a/src/cljc/lernmeister/components/exercise_types/text_correction/spec.cljc b/src/cljc/lernmeister/components/exercise_types/text_correction/spec.cljc index 90205db..f8b5014 100644 --- a/src/cljc/lernmeister/components/exercise_types/text_correction/spec.cljc +++ b/src/cljc/lernmeister/components/exercise_types/text_correction/spec.cljc @@ -4,25 +4,22 @@ :clj (:require [clojure.spec.alpha :as s]))) -(s/def :text-correction/unselected-points number?) -(s/def :text-correction/selected-points number?) -(s/def :text-correction/answer (s/keys :req-un [:answer/id - :answer/text - :text-correction/selected-points - :text-correction/unselected-points])) -(s/def :text-correction/answers (s/and - (s/coll-of :text-correction/answer - :kind vector? - :min-count 1 - :distinct true) - #(= 1 (count (filter (comp pos? :selected-points) %))))) +(s/def :correction/word string?) +(s/def :correction/index number?) +(s/def :correction/correct-word string?) +(s/def :text-correction/correction-text string?) +(s/def :text-correction/correction (s/keys :req-un [:correction/word + :correction/index + :correction/correct-word])) +(s/def :text-correction/corrections (s/and + (s/map-of string? + :text-correction/correction))) + (s/def :text-correction/type #{:text-correction}) -(s/def :text-correction/core (s/and (s/keys :req-un [:text-correction/answers - :text-correction/type] - :opt-un [:exercise/shuffled - :exercise/voting]) - #(= 1 (count (filter (comp pos? :selected-points) (:answers %)))))) +(s/def :text-correction/core (s/and (s/keys :req-un [:text-correction/correction-text + :text-correction/corrections + :text-correction/type]))) (s/def ::text-correction (s/keys :req-un [:text-correction/core])) diff --git a/src/cljs/lernmeister/components/exercise_types/text_correction/views/edit.cljs b/src/cljs/lernmeister/components/exercise_types/text_correction/views/edit.cljs index 87b7e0b..94ba46e 100644 --- a/src/cljs/lernmeister/components/exercise_types/text_correction/views/edit.cljs +++ b/src/cljs/lernmeister/components/exercise_types/text_correction/views/edit.cljs @@ -2,7 +2,7 @@ (:require [reagent.core :as reagent] [lernmeister.components.ui :as ui] [lernmeister.components.exercise-types.edit :as e-edit] - [clojure.string :refer [split]]) + [lernmeister.components.exercise-types.text-correction.common :refer [split-text valid-correction?]]) (:use [lernmeister.components.jshelper :only [get-unique-id try-number-parse]] [lernmeister.components.helper :only [vec-remove]])) @@ -48,24 +48,24 @@ #(swap! all-options vec-remove index)} [:i.material-icons "remove"]]]])) (defn selectable-text [text & {:keys []}] + (let [component-id (gensym "selectable-text")] (fn [text & {:keys [on-select]}] [:<> [:div (map-indexed (fn [index text-fragment] (let [fragment-id (str index "-" text-fragment)] + ^{:key (str component-id "-" fragment-id)} [:span.text-fragment {:id fragment-id :on-click #(on-select fragment-id text-fragment index)} text-fragment ])) - (-> text - (split #"(\ |\. |\,)") - ) + (split-text text) ) ]] ) - ) + )) (defn new-exercise-form [core] (let [edit-text (reagent/atom nil)] @@ -105,11 +105,16 @@ [:th {:width "10%"} ""] ]] [:tbody - (for [[id c] (:corrections @core)] + (doall + (for [[id c] (sort-by :index (:corrections @core))] ^{:key (str "tcorrection_" id)} [:tr [:td (:word c)] - [:td (str (:index c))] + [:td + (if (valid-correction? (:correction-text @core) c) + (str (:index c)) + [:span [:i.material-icons.left "error"] "Korrektur nicht mehr gültig"]) + ] [:td [:input {:type :text :on-change #(swap! core update-in [:corrections id] @@ -119,7 +124,7 @@ [:td [:a.btn.btn.flat {:on-click #(swap! core update :corrections dissoc id)} [:i.material-icons "delete"]]]] - ) + )) ]] ])}))) diff --git a/src/cljs/lernmeister/components/exercise_types/text_correction/views/show.cljs b/src/cljs/lernmeister/components/exercise_types/text_correction/views/show.cljs index 8253428..5b3b71e 100644 --- a/src/cljs/lernmeister/components/exercise_types/text_correction/views/show.cljs +++ b/src/cljs/lernmeister/components/exercise_types/text_correction/views/show.cljs @@ -6,11 +6,13 @@ [lernmeister.components.content-elements.exercise.show :as ce-ex] [lernmeister.components.content-elements.exercise.task-description :refer [default-task-description]] + [lernmeister.components.exercise-types.text-correction.common :refer [split-text]] [clojure.string :refer [split]])) (defn correctable-text [text & {:keys []}] (let [edit? (reagent/atom nil) - edit-text (reagent/atom nil)] + edit-text (reagent/atom nil) + component-id (gensym "correctable-text")] (fn [text & {:keys [on-select corrections on-delete]}] [:<> @@ -22,23 +24,24 @@ correction (get corrections fragment-id) edit-fragment? (= @edit? fragment-id)] (if-not edit-fragment? - ^{:key (str fragment-id "-" edit-fragment?)} + ^{:key (str component-id "-" fragment-id "-" edit-fragment?)} [:span.text-fragment {:id fragment-id :class (when correction "corrected") :on-click #(do (reset! edit? fragment-id) - (reset! edit-text (or correction + (reset! edit-text (or (:correct-word correction) text-fragment)))} - (or correction text-fragment) + (or (:correct-word correction) + text-fragment) ] - ^{:key (str fragment-id "-" edit-fragment?)} + ^{:key (str component-id "-" fragment-id "-" edit-fragment?)} [:div.input-field.inline {:style {:margin "0px"}} [:input.browser-default {:type :text - :value @edit-text - :on-change #(reset! edit-text (-> % .-target .-value)) - }] + :value @edit-text + :on-change #(reset! edit-text (-> % .-target .-value)) + :auto-focus true}] [:a.btn.btn-flat {:on-click #(do (on-delete fragment-id) @@ -53,10 +56,8 @@ [:i.material-icons.center "save"]] ] - ))) - (-> text - (split #"(\ |\. |\,)") - )) + ))) + (split-text text)) ) ]] ) @@ -78,7 +79,7 @@ [default-task-description (:task-description exercise)] [correctable-text (:correction-text exercise) :corrections answer - :on-select #(on-change (assoc answer %1 %2)) + :on-select #(on-change (assoc answer %1 {:correct-word %2})) :on-delete #(on-change (dissoc answer %1))] (when result [:span.secondary-content [:b (str (:points result) "P")]])]])) -- GitLab