@pie-element/placement-ordering 12.0.1 → 12.0.2-esm.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/configure/package.json +5 -5
- package/esm/configure.css +847 -0
- package/esm/configure.js +1623 -16923
- package/esm/configure.js.map +1 -1
- package/esm/controller.css +847 -0
- package/esm/controller.js +132 -180
- package/esm/controller.js.map +1 -1
- package/esm/element.css +847 -0
- package/esm/element.js +433 -7567
- package/esm/element.js.map +1 -1
- package/package.json +5 -5
package/esm/controller.js
CHANGED
|
@@ -6,55 +6,22 @@ import isEqual from 'lodash/isEqual';
|
|
|
6
6
|
import isEmpty from 'lodash/isEmpty';
|
|
7
7
|
import Translator from '@pie-lib/translator';
|
|
8
8
|
|
|
9
|
-
function
|
|
10
|
-
|
|
11
|
-
var
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
if (info.done) {
|
|
19
|
-
resolve(value);
|
|
20
|
-
} else {
|
|
21
|
-
Promise.resolve(value).then(_next, _throw);
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
function _asyncToGenerator(fn) {
|
|
26
|
-
return function () {
|
|
27
|
-
var self = this,
|
|
28
|
-
args = arguments;
|
|
29
|
-
return new Promise(function (resolve, reject) {
|
|
30
|
-
var gen = fn.apply(self, args);
|
|
31
|
-
|
|
32
|
-
function _next(value) {
|
|
33
|
-
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
function _throw(err) {
|
|
37
|
-
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
|
|
9
|
+
function _extends() {
|
|
10
|
+
_extends = Object.assign || function (target) {
|
|
11
|
+
for (var i = 1; i < arguments.length; i++) {
|
|
12
|
+
var source = arguments[i];
|
|
13
|
+
|
|
14
|
+
for (var key in source) {
|
|
15
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
16
|
+
target[key] = source[key];
|
|
17
|
+
}
|
|
38
18
|
}
|
|
19
|
+
}
|
|
39
20
|
|
|
40
|
-
|
|
41
|
-
});
|
|
21
|
+
return target;
|
|
42
22
|
};
|
|
43
|
-
}
|
|
44
23
|
|
|
45
|
-
|
|
46
|
-
if (key in obj) {
|
|
47
|
-
Object.defineProperty(obj, key, {
|
|
48
|
-
value: value,
|
|
49
|
-
enumerable: true,
|
|
50
|
-
configurable: true,
|
|
51
|
-
writable: true
|
|
52
|
-
});
|
|
53
|
-
} else {
|
|
54
|
-
obj[key] = value;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
return obj;
|
|
24
|
+
return _extends.apply(this, arguments);
|
|
58
25
|
}
|
|
59
26
|
|
|
60
27
|
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
|
|
@@ -619,13 +586,10 @@ var combinatorics = {exports: {}};
|
|
|
619
586
|
}));
|
|
620
587
|
}(combinatorics));
|
|
621
588
|
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
var illegalArgumentError = answer => new Error("Cant score answer: ".concat(answer, " it has duplicates and allowDuplicates is false"));
|
|
627
|
-
var pairwiseCombinationScore = (correct, answer, opts) => {
|
|
628
|
-
opts = _objectSpread$1({
|
|
589
|
+
const log$1 = debug('pie-elements:placement-ordering:controller');
|
|
590
|
+
const illegalArgumentError = answer => new Error(`Cant score answer: ${answer} it has duplicates and allowDuplicates is false`);
|
|
591
|
+
const pairwiseCombinationScore = (correct, answer, opts) => {
|
|
592
|
+
opts = _extends({
|
|
629
593
|
allowDuplicates: false,
|
|
630
594
|
orderMustBeComplete: false
|
|
631
595
|
}, opts);
|
|
@@ -661,15 +625,15 @@ var pairwiseCombinationScore = (correct, answer, opts) => {
|
|
|
661
625
|
return 0;
|
|
662
626
|
}
|
|
663
627
|
|
|
664
|
-
|
|
665
|
-
|
|
628
|
+
const correctCombo = combinatorics.exports.combination(correct, 2).toArray();
|
|
629
|
+
const answerCombo = combinatorics.exports.combination(answer, 2).toArray();
|
|
666
630
|
|
|
667
|
-
|
|
631
|
+
const diff = _.differenceWith(answerCombo, correctCombo, _.isEqual);
|
|
668
632
|
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
633
|
+
const comboLengthDiff = correctCombo.length - answerCombo.length;
|
|
634
|
+
const total = correctCombo.length;
|
|
635
|
+
const actual = total - diff.length - comboLengthDiff;
|
|
636
|
+
const n = (actual / total).toFixed(2);
|
|
673
637
|
return parseFloat(n);
|
|
674
638
|
};
|
|
675
639
|
/**
|
|
@@ -677,14 +641,14 @@ var pairwiseCombinationScore = (correct, answer, opts) => {
|
|
|
677
641
|
* correct response.
|
|
678
642
|
*/
|
|
679
643
|
|
|
680
|
-
|
|
644
|
+
const flattenCorrect = question => question.correctResponse ? question.correctResponse.map(r => r && r.id ? r.id : r) : [];
|
|
681
645
|
/**
|
|
682
646
|
* Returns all correct responses for this question
|
|
683
647
|
* @param question - array
|
|
684
648
|
*/
|
|
685
649
|
|
|
686
|
-
|
|
687
|
-
|
|
650
|
+
const getAllCorrectResponses = question => {
|
|
651
|
+
const alternates = (question.alternateResponses || []).map(alternate => {
|
|
688
652
|
if (Array.isArray(alternate)) {
|
|
689
653
|
return alternate;
|
|
690
654
|
}
|
|
@@ -700,8 +664,8 @@ var getAllCorrectResponses = question => {
|
|
|
700
664
|
* for all correct) will be used.
|
|
701
665
|
*/
|
|
702
666
|
|
|
703
|
-
|
|
704
|
-
|
|
667
|
+
const score = (question, session) => {
|
|
668
|
+
const {
|
|
705
669
|
value
|
|
706
670
|
} = session || {};
|
|
707
671
|
|
|
@@ -709,16 +673,16 @@ var score = (question, session) => {
|
|
|
709
673
|
return 0;
|
|
710
674
|
}
|
|
711
675
|
|
|
712
|
-
|
|
713
|
-
|
|
676
|
+
const allCorrectResponse = getAllCorrectResponses(question);
|
|
677
|
+
const allowDuplicates = (question.configure && question.configure.removeTilesAfterPlacing) !== false;
|
|
714
678
|
/**
|
|
715
679
|
* We require this to be the case - locking
|
|
716
680
|
*/
|
|
717
681
|
//const orderMustBeComplete = true;
|
|
718
682
|
|
|
719
|
-
|
|
683
|
+
let bestScore = 0;
|
|
720
684
|
allCorrectResponse.forEach(cr => {
|
|
721
|
-
|
|
685
|
+
const currentScore = pairwiseCombinationScore(cr, value, {
|
|
722
686
|
allowDuplicates
|
|
723
687
|
});
|
|
724
688
|
|
|
@@ -752,14 +716,11 @@ var defaults = {
|
|
|
752
716
|
toolbarEditorPosition: 'bottom'
|
|
753
717
|
};
|
|
754
718
|
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
758
|
-
var log = debug('@pie-element:placement-ordering:controller');
|
|
759
|
-
var {
|
|
719
|
+
const log = debug('@pie-element:placement-ordering:controller');
|
|
720
|
+
const {
|
|
760
721
|
translator
|
|
761
722
|
} = Translator;
|
|
762
|
-
|
|
723
|
+
const questionError = () => new Error('Question is missing required array: correctResponse');
|
|
763
724
|
function outcome(question, session, env) {
|
|
764
725
|
return new Promise((resolve, reject) => {
|
|
765
726
|
if (!session || _.isEmpty(session)) {
|
|
@@ -773,8 +734,8 @@ function outcome(question, session, env) {
|
|
|
773
734
|
reject(questionError());
|
|
774
735
|
} else {
|
|
775
736
|
try {
|
|
776
|
-
|
|
777
|
-
|
|
737
|
+
const s = score(question, session);
|
|
738
|
+
const finalScore = partialScoring.enabled(question, env || {}) ? s : s === 1 ? 1 : 0;
|
|
778
739
|
resolve({
|
|
779
740
|
score: finalScore
|
|
780
741
|
});
|
|
@@ -784,13 +745,12 @@ function outcome(question, session, env) {
|
|
|
784
745
|
}
|
|
785
746
|
});
|
|
786
747
|
}
|
|
787
|
-
function createDefaultModel() {
|
|
788
|
-
var model = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
748
|
+
function createDefaultModel(model = {}) {
|
|
789
749
|
return new Promise(resolve => {
|
|
790
|
-
resolve(
|
|
750
|
+
resolve(_extends({}, defaults, model));
|
|
791
751
|
});
|
|
792
752
|
}
|
|
793
|
-
|
|
753
|
+
const normalize = question => _extends({}, defaults, {
|
|
794
754
|
rationaleEnabled: true,
|
|
795
755
|
feedbackEnabled: false,
|
|
796
756
|
promptEnabled: true,
|
|
@@ -805,107 +765,101 @@ var normalize = question => _objectSpread(_objectSpread({}, defaults), {}, {
|
|
|
805
765
|
*/
|
|
806
766
|
|
|
807
767
|
function model(question, session, env) {
|
|
808
|
-
return new Promise(
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
var base = {};
|
|
768
|
+
return new Promise(async resolve => {
|
|
769
|
+
const normalizedQuestion = normalize(question);
|
|
770
|
+
const base = {};
|
|
812
771
|
|
|
813
|
-
|
|
814
|
-
|
|
772
|
+
if (question.alternateResponses && _.every(question.alternateResponses, _.isArray)) {
|
|
773
|
+
log('Deprecated structure of alternateResponses is in use'); // eslint-disable-next-line no-console
|
|
815
774
|
|
|
816
|
-
|
|
817
|
-
|
|
775
|
+
console.error('Deprecated structure of alternateResponses is in use');
|
|
776
|
+
}
|
|
818
777
|
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
if (!base.note) {
|
|
841
|
-
base.note = translator.t('common:commonCorrectAnswerWithAlternates', {
|
|
842
|
-
lng: normalizedQuestion.language
|
|
843
|
-
});
|
|
844
|
-
}
|
|
778
|
+
base.env = env;
|
|
779
|
+
base.extraCSSRules = normalizedQuestion.extraCSSRules;
|
|
780
|
+
base.outcomes = [];
|
|
781
|
+
base.completeLength = (normalizedQuestion.correctResponse || []).length;
|
|
782
|
+
base.choices = (normalizedQuestion.choices || []).filter(choice => choice.label);
|
|
783
|
+
base.note = normalizedQuestion.note;
|
|
784
|
+
base.showNote = normalizedQuestion.alternateResponses && normalizedQuestion.alternateResponses.length > 0;
|
|
785
|
+
base.language = normalizedQuestion.language;
|
|
786
|
+
log('[model] removing tileSize for the moment.');
|
|
787
|
+
base.prompt = normalizedQuestion.promptEnabled ? normalizedQuestion.prompt : null;
|
|
788
|
+
base.config = {
|
|
789
|
+
orientation: normalizedQuestion.orientation || 'vertical',
|
|
790
|
+
includeTargets: normalizedQuestion.placementArea,
|
|
791
|
+
choiceLabelEnabled: normalizedQuestion.choiceLabelEnabled,
|
|
792
|
+
targetLabel: normalizedQuestion.targetLabel,
|
|
793
|
+
choiceLabel: normalizedQuestion.choiceLabel,
|
|
794
|
+
showOrdering: normalizedQuestion.numberedGuides,
|
|
795
|
+
allowSameChoiceInTargets: !normalizedQuestion.removeTilesAfterPlacing
|
|
796
|
+
};
|
|
797
|
+
base.disabled = env.mode !== 'gather';
|
|
845
798
|
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
}
|
|
850
|
-
|
|
851
|
-
base.teacherInstructions = null;
|
|
852
|
-
}
|
|
799
|
+
if (!base.note) {
|
|
800
|
+
base.note = translator.t('common:commonCorrectAnswerWithAlternates', {
|
|
801
|
+
lng: normalizedQuestion.language
|
|
802
|
+
});
|
|
803
|
+
}
|
|
853
804
|
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
arr: [],
|
|
870
|
-
score: 0
|
|
871
|
-
});
|
|
872
|
-
base.outcomes = _.map(value, (c, idx) => {
|
|
805
|
+
if (env.role === 'instructor' && (env.mode === 'view' || env.mode === 'evaluate')) {
|
|
806
|
+
base.rationale = normalizedQuestion.rationaleEnabled ? normalizedQuestion.rationale : null;
|
|
807
|
+
base.teacherInstructions = normalizedQuestion.teacherInstructionsEnabled ? normalizedQuestion.teacherInstructions : null;
|
|
808
|
+
} else {
|
|
809
|
+
base.rationale = null;
|
|
810
|
+
base.teacherInstructions = null;
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
if (env.mode === 'evaluate') {
|
|
814
|
+
const value = session && session.value || [];
|
|
815
|
+
const allCorrectResponses = getAllCorrectResponses(normalizedQuestion);
|
|
816
|
+
const bestSetOfResponses = allCorrectResponses.reduce((info, cr) => {
|
|
817
|
+
const currentScore = _.reduce(value, (acc, c, idx) => acc + (Array.isArray(cr) && cr[idx] === c ? 1 : 0), 0);
|
|
818
|
+
|
|
819
|
+
if (currentScore > info.score) {
|
|
873
820
|
return {
|
|
874
|
-
|
|
875
|
-
|
|
821
|
+
arr: cr,
|
|
822
|
+
score: currentScore
|
|
876
823
|
};
|
|
877
|
-
}
|
|
878
|
-
var isResponseCorrect = allCorrectResponses.some(response => _.isEqual(response, value));
|
|
879
|
-
var responseScore = score(question, session);
|
|
880
|
-
var isCorrect = responseScore === 1;
|
|
881
|
-
var isPartialCorrect = !isCorrect && partialScoring.enabled(normalizedQuestion, env || {}) && responseScore !== 0;
|
|
882
|
-
base.correctness = isCorrect ? 'correct' : isPartialCorrect ? 'partial' : 'incorrect';
|
|
824
|
+
}
|
|
883
825
|
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
826
|
+
return info;
|
|
827
|
+
}, {
|
|
828
|
+
arr: [],
|
|
829
|
+
score: 0
|
|
830
|
+
});
|
|
831
|
+
base.outcomes = _.map(value, (c, idx) => {
|
|
832
|
+
return {
|
|
833
|
+
id: c,
|
|
834
|
+
outcome: bestSetOfResponses.arr[idx] === c ? 'correct' : 'incorrect'
|
|
835
|
+
};
|
|
836
|
+
});
|
|
837
|
+
const isResponseCorrect = allCorrectResponses.some(response => _.isEqual(response, value));
|
|
838
|
+
const responseScore = score(question, session);
|
|
839
|
+
const isCorrect = responseScore === 1;
|
|
840
|
+
const isPartialCorrect = !isCorrect && partialScoring.enabled(normalizedQuestion, env || {}) && responseScore !== 0;
|
|
841
|
+
base.correctness = isCorrect ? 'correct' : isPartialCorrect ? 'partial' : 'incorrect';
|
|
887
842
|
|
|
843
|
+
if (!isResponseCorrect) {
|
|
844
|
+
base.correctResponse = flattenCorrect(normalizedQuestion);
|
|
845
|
+
} // requirement made in PD-2182
|
|
888
846
|
|
|
889
|
-
if (!normalizedQuestion.feedback) {
|
|
890
|
-
normalizedQuestion.feedbackEnabled = false;
|
|
891
|
-
}
|
|
892
847
|
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
base.feedback = feedback;
|
|
896
|
-
resolve(base);
|
|
897
|
-
});
|
|
898
|
-
} else {
|
|
899
|
-
resolve(base);
|
|
848
|
+
if (!normalizedQuestion.feedback) {
|
|
849
|
+
normalizedQuestion.feedbackEnabled = false;
|
|
900
850
|
}
|
|
901
|
-
});
|
|
902
851
|
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
852
|
+
const fb = normalizedQuestion.feedbackEnabled ? getFeedbackForCorrectness(base.correctness, normalizedQuestion.feedback) : Promise.resolve(undefined);
|
|
853
|
+
fb.then(feedback => {
|
|
854
|
+
base.feedback = feedback;
|
|
855
|
+
resolve(base);
|
|
856
|
+
});
|
|
857
|
+
} else {
|
|
858
|
+
resolve(base);
|
|
859
|
+
}
|
|
860
|
+
});
|
|
907
861
|
}
|
|
908
|
-
|
|
862
|
+
const createCorrectResponseSession = (question, env) => {
|
|
909
863
|
return new Promise(resolve => {
|
|
910
864
|
if (env.mode !== 'evaluate' && env.role === 'instructor') {
|
|
911
865
|
resolve({
|
|
@@ -919,27 +873,25 @@ var createCorrectResponseSession = (question, env) => {
|
|
|
919
873
|
}; // remove all html tags
|
|
920
874
|
|
|
921
875
|
|
|
922
|
-
|
|
876
|
+
const getContent = html => (html || '').replace(/(<(?!img|iframe|source)([^>]+)>)/gi, '');
|
|
923
877
|
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
var config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
927
|
-
var {
|
|
878
|
+
const validate = (model = {}, config = {}) => {
|
|
879
|
+
const {
|
|
928
880
|
choices,
|
|
929
881
|
correctResponse
|
|
930
882
|
} = model;
|
|
931
|
-
|
|
883
|
+
const errors = {};
|
|
932
884
|
['teacherInstructions', 'prompt', 'rationale'].forEach(field => {
|
|
933
885
|
var _config$field;
|
|
934
886
|
|
|
935
|
-
if ((_config$field = config[field])
|
|
887
|
+
if ((_config$field = config[field]) != null && _config$field.required && !getContent(model[field])) {
|
|
936
888
|
errors[field] = 'This field is required.';
|
|
937
889
|
}
|
|
938
890
|
});
|
|
939
|
-
|
|
940
|
-
|
|
891
|
+
const reversedChoices = [...(choices || [])].reverse();
|
|
892
|
+
const choicesErrors = {};
|
|
941
893
|
reversedChoices.forEach((choice, index) => {
|
|
942
|
-
|
|
894
|
+
const {
|
|
943
895
|
id,
|
|
944
896
|
label
|
|
945
897
|
} = choice;
|
|
@@ -947,15 +899,15 @@ var validate = function validate() {
|
|
|
947
899
|
if (!getContent(label)) {
|
|
948
900
|
choicesErrors[id] = 'Content should not be empty.';
|
|
949
901
|
} else {
|
|
950
|
-
|
|
902
|
+
const identicalAnswer = reversedChoices.slice(index + 1).some(c => c.label === label);
|
|
951
903
|
|
|
952
904
|
if (identicalAnswer) {
|
|
953
905
|
choicesErrors[id] = 'Content should be unique.';
|
|
954
906
|
}
|
|
955
907
|
}
|
|
956
908
|
});
|
|
957
|
-
|
|
958
|
-
|
|
909
|
+
const choicesIds = (choices || []).map(choice => choice.id);
|
|
910
|
+
const correctResponseIds = (correctResponse || []).map(response => response.id || response);
|
|
959
911
|
|
|
960
912
|
if (isEqual(choicesIds, correctResponseIds)) {
|
|
961
913
|
errors.orderError = 'The correct ordering should not be identical to the initial ordering.';
|