|
7 | 7 | MailToIRIRegEx |
8 | 8 | UuidRegEx |
9 | 9 | TimestampRegEx |
| 10 | + TimestampRegEx200 |
10 | 11 | xAPIVersionRegEx |
| 12 | + xAPIVersionRegEx200 |
11 | 13 | DurationRegEx |
| 14 | + DurationRegEx200 |
12 | 15 | Sha1RegEx |
13 | 16 | Sha2RegEx]] |
14 | 17 | [clojure.spec.alpha :as s #?@(:cljs [:include-macros true])] |
|
22 | 25 | "When true, coerce 0.95 context activities to conform." |
23 | 26 | true) |
24 | 27 |
|
| 28 | +(def ^:dynamic *xapi-version* |
| 29 | + "xAPI Statement Version to Conform" |
| 30 | + "1.0.3") |
| 31 | + |
25 | 32 | ;; Utils |
26 | 33 |
|
27 | 34 | (def double-conformer |
|
234 | 241 | [timestamp] |
235 | 242 | (letfn [(parse-int [s] #?(:clj (Integer/parseInt s) :cljs (js/parseInt s)))] |
236 | 243 | (let [[ts year month day _hour _min _sec _sec-frac _offset] |
237 | | - (re-matches TimestampRegEx timestamp) |
| 244 | + (re-matches |
| 245 | + (case *xapi-version* |
| 246 | + "1.0.3" TimestampRegEx |
| 247 | + "2.0.0" TimestampRegEx200) |
| 248 | + timestamp) |
238 | 249 | month-int (when month (parse-int month)) |
239 | 250 | year-int (when year (parse-int year)) |
240 | 251 | day-int (when day (parse-int day))] |
|
269 | 280 | (s/def ::duration |
270 | 281 | (s/with-gen |
271 | 282 | (s/and string? |
272 | | - (partial re-matches DurationRegEx)) |
| 283 | + #(re-matches |
| 284 | + (case *xapi-version* |
| 285 | + "1.0.3" DurationRegEx |
| 286 | + "2.0.0" DurationRegEx200) |
| 287 | + %)) |
273 | 288 | #(sgen/fmap (fn [[h m s]] |
274 | 289 | (#?(:clj format |
275 | 290 | :cljs gstring/format) "PT%dH%sM%dS" h m s)) |
|
280 | 295 | (s/def ::version |
281 | 296 | (s/with-gen |
282 | 297 | (s/and string? |
283 | | - (partial re-matches xAPIVersionRegEx)) |
284 | | - #(sgen/fmap (fn [i] |
285 | | - (#?(:clj format |
286 | | - :cljs gstring/format) "1.0.%d" i)) |
287 | | - (sgen/int)))) |
| 298 | + #(re-matches |
| 299 | + (case *xapi-version* |
| 300 | + "1.0.3" xAPIVersionRegEx |
| 301 | + "2.0.0" xAPIVersionRegEx200) |
| 302 | + %)) |
| 303 | + #(sgen/return *xapi-version*))) |
288 | 304 |
|
289 | 305 | (s/def ::sha2 |
290 | 306 | (s/with-gen |
|
815 | 831 | (-> scores |
816 | 832 | (assoc :score/min raw) |
817 | 833 | (assoc :score/raw min)) |
818 | | - |
| 834 | + |
819 | 835 | (and min max (< max min)) |
820 | 836 | (-> scores |
821 | 837 | (assoc :score/min max) |
822 | 838 | (assoc :score/max min)) |
823 | | - |
| 839 | + |
824 | 840 | (and raw max (< max raw)) |
825 | 841 | (-> scores |
826 | 842 | (assoc :score/raw max) |
827 | 843 | (assoc :score/max raw)) |
828 | | - |
| 844 | + |
829 | 845 | :else |
830 | 846 | scores)) |
831 | 847 |
|
|
973 | 989 | (s/def :context/extensions |
974 | 990 | ::extensions) |
975 | 991 |
|
976 | | -(s/def ::context |
977 | | - (conform-ns "context" |
| 992 | +;; 2.0.x compat |
| 993 | + |
| 994 | +;; contextAgents |
| 995 | +(s/def :contextAgent/objectType #{"contextAgent"}) |
| 996 | +(s/def :contextAgent/agent ::agent) |
| 997 | +(s/def :contextAgent/relevantTypes |
| 998 | + (s/every ::iri |
| 999 | + :into [] |
| 1000 | + :min-count 1)) |
| 1001 | + |
| 1002 | +(s/def ::context-agent |
| 1003 | + (conform-ns "contextAgent" |
| 1004 | + (s/and |
| 1005 | + (s/keys :req [:contextAgent/objectType |
| 1006 | + :contextAgent/agent] |
| 1007 | + :opt [:contextAgent/relevantTypes]) |
| 1008 | + (restrict-keys :contextAgent/objectType |
| 1009 | + :contextAgent/agent |
| 1010 | + :contextAgent/relevantTypes)))) |
| 1011 | +(s/def :context/contextAgents |
| 1012 | + (s/every ::context-agent |
| 1013 | + :into [])) |
| 1014 | + |
| 1015 | +;; contextGroups |
| 1016 | + |
| 1017 | +(s/def :contextGroup/objectType #{"contextGroup"}) |
| 1018 | +(s/def :contextGroup/group ::group) |
| 1019 | +(s/def :contextGroup/relevantTypes |
| 1020 | + (s/every ::iri |
| 1021 | + :into [] |
| 1022 | + :min-count 1)) |
| 1023 | + |
| 1024 | +(s/def ::context-group |
| 1025 | + (conform-ns "contextGroup" |
978 | 1026 | (s/and |
979 | | - (s/keys :opt [:context/registration |
980 | | - :context/instructor |
981 | | - :context/team |
982 | | - :context/contextActivities |
983 | | - :context/revision |
984 | | - :context/platform |
985 | | - :context/language |
986 | | - :context/statement |
987 | | - :context/extensions]) |
988 | | - (restrict-keys :context/registration |
989 | | - :context/instructor |
990 | | - :context/team |
991 | | - :context/contextActivities |
992 | | - :context/revision |
993 | | - :context/platform |
994 | | - :context/language |
995 | | - :context/statement |
996 | | - :context/extensions)))) |
| 1027 | + (s/keys :req [:contextGroup/objectType |
| 1028 | + :contextGroup/group] |
| 1029 | + :opt [:contextGroup/relevantTypes]) |
| 1030 | + (restrict-keys :contextGroup/objectType |
| 1031 | + :contextGroup/group |
| 1032 | + :contextGroup/relevantTypes)))) |
| 1033 | +(s/def :context/contextGroups |
| 1034 | + (s/every ::context-group |
| 1035 | + :into [])) |
| 1036 | + |
| 1037 | +;; multispec for dynamic params |
| 1038 | +(defmulti context-version (fn [_] *xapi-version*)) |
| 1039 | + |
| 1040 | +(defmethod context-version "1.0.3" [_] |
| 1041 | + (conform-ns |
| 1042 | + "context" |
| 1043 | + (s/and |
| 1044 | + (s/keys :opt [:context/registration |
| 1045 | + :context/instructor |
| 1046 | + :context/team |
| 1047 | + :context/contextActivities |
| 1048 | + :context/revision |
| 1049 | + :context/platform |
| 1050 | + :context/language |
| 1051 | + :context/statement |
| 1052 | + :context/extensions]) |
| 1053 | + (restrict-keys :context/registration |
| 1054 | + :context/instructor |
| 1055 | + :context/team |
| 1056 | + :context/contextActivities |
| 1057 | + :context/revision |
| 1058 | + :context/platform |
| 1059 | + :context/language |
| 1060 | + :context/statement |
| 1061 | + :context/extensions)))) |
| 1062 | + |
| 1063 | +(defmethod context-version "2.0.0" [_] |
| 1064 | + (conform-ns |
| 1065 | + "context" |
| 1066 | + (s/and |
| 1067 | + (s/keys :opt [:context/registration |
| 1068 | + :context/instructor |
| 1069 | + :context/team |
| 1070 | + :context/contextActivities |
| 1071 | + :context/revision |
| 1072 | + :context/platform |
| 1073 | + :context/language |
| 1074 | + :context/statement |
| 1075 | + :context/extensions |
| 1076 | + :context/contextAgents |
| 1077 | + :context/contextGroups]) |
| 1078 | + (restrict-keys :context/registration |
| 1079 | + :context/instructor |
| 1080 | + :context/team |
| 1081 | + :context/contextActivities |
| 1082 | + :context/revision |
| 1083 | + :context/platform |
| 1084 | + :context/language |
| 1085 | + :context/statement |
| 1086 | + :context/extensions |
| 1087 | + :context/contextAgents |
| 1088 | + :context/contextGroups)))) |
| 1089 | + |
| 1090 | +(s/def ::context |
| 1091 | + (s/multi-spec context-version (fn [gen-val _] |
| 1092 | + gen-val) )) |
997 | 1093 |
|
998 | 1094 | ;; Attachments |
999 | 1095 |
|
|
1326 | 1422 | (some-> s :statement/object :statement-ref/objectType) |
1327 | 1423 | true))))) |
1328 | 1424 |
|
| 1425 | +(defn unique-statement-ids? |
| 1426 | + "Spec predicate to ensure that the IDs of a list of statements are unique." |
| 1427 | + [statements] |
| 1428 | + (let [ids (keep #(get % "id") statements)] |
| 1429 | + (or |
| 1430 | + (empty? ids) |
| 1431 | + (reduce distinct? ids) |
| 1432 | + ::s/invalid))) |
| 1433 | + |
1329 | 1434 | (s/def ::statements |
1330 | | - (s/coll-of ::statement :into [])) |
| 1435 | + (s/and |
| 1436 | + (s/coll-of ::statement :into []) |
| 1437 | + unique-statement-ids?)) |
1331 | 1438 |
|
1332 | 1439 | (s/def ::lrs-statements |
1333 | 1440 | (s/coll-of ::lrs-statement :into [])) |
0 commit comments