@pocketprep/ui-kit 3.5.30 → 3.7.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/dist/@pocketprep/ui-kit.css +1 -1
- package/dist/@pocketprep/ui-kit.js +12594 -11931
- package/dist/@pocketprep/ui-kit.js.map +1 -1
- package/dist/@pocketprep/ui-kit.umd.cjs +12 -11
- package/dist/@pocketprep/ui-kit.umd.cjs.map +1 -1
- package/lib/components/Forms/Radio.vue +1 -8
- package/lib/components/Quiz/Question/BuildListChoicesContainer.vue +714 -0
- package/lib/components/Quiz/Question/ChoicesContainer.vue +1 -9
- package/lib/components/Quiz/Question/MPMCChoicesContainer.vue +472 -0
- package/lib/components/Quiz/Question/MPMCRadioGroup.vue +169 -0
- package/lib/components/Quiz/Question/MobileMatrixChoicesContainer.vue +1 -9
- package/lib/components/Quiz/Question/MobileMatrixRadioGroup.vue +1 -9
- package/lib/components/Quiz/Question/StatsSummary.vue +22 -6
- package/lib/components/Quiz/Question/Summary.vue +31 -5
- package/lib/components/Quiz/Question/composables.ts +18 -1
- package/lib/components/Quiz/Question/injectionSymbols.ts +15 -0
- package/lib/components/Quiz/Question.vue +394 -24
- package/lib/components/Quiz/question.d.ts +7 -0
- package/lib/utils.ts +8 -0
- package/package.json +2 -2
|
@@ -33,6 +33,8 @@
|
|
|
33
33
|
'uikit-question__main--mcr': isMCR,
|
|
34
34
|
'uikit-question__main--mcr-review-mode': isMCR && reviewMode,
|
|
35
35
|
'uikit-question__main--matrix-question-review-mode': isMatrixQuestion && reviewMode,
|
|
36
|
+
'uikit-question__main--mpmc-question-review-mode': isMPMCQuestion && reviewMode,
|
|
37
|
+
'uikit-question__main--build-list-question-review-mode': isBuildListQuestion && reviewMode,
|
|
36
38
|
}"
|
|
37
39
|
>
|
|
38
40
|
<div v-if="!showPassageAndImage && !showExplanation && !showPaywall">
|
|
@@ -100,7 +102,7 @@
|
|
|
100
102
|
@upgradeClicked="emitUpgrade"
|
|
101
103
|
/>
|
|
102
104
|
<div
|
|
103
|
-
v-if="(showAnswers || showMatrixAnswers) && isTeachReview && isUnanswered"
|
|
105
|
+
v-if="(showAnswers || showMatrixAnswers || showMPMCAnswers) && isTeachReview && isUnanswered"
|
|
104
106
|
v-dark="isDarkMode"
|
|
105
107
|
class="uikit-question__unanswered-teach-review-label"
|
|
106
108
|
>
|
|
@@ -117,9 +119,11 @@
|
|
|
117
119
|
'uikit-question__choices--incorrect':
|
|
118
120
|
showAnswers && (isMCR || isUnanswered) && !isCorrect && !isTeachReview,
|
|
119
121
|
'uikit-question__choices--matrix': isMatrixQuestion,
|
|
122
|
+
'uikit-question__choices--mpmc': isMPMCQuestion,
|
|
120
123
|
'uikit-question__choices--unanswered': showAnswers && !isMCR && isUnanswered && !isCorrect,
|
|
121
124
|
'uikit-question__choices--show-stats': globalMetrics,
|
|
122
|
-
'uikit-question__choices--no-actions':
|
|
125
|
+
'uikit-question__choices--no-actions':
|
|
126
|
+
!(isMCR || isUnanswered || isMatrixQuestion || isBuildListQuestion || isMPMCQuestion)
|
|
123
127
|
&& !globalMetrics
|
|
124
128
|
&& (
|
|
125
129
|
reviewMode
|
|
@@ -136,7 +140,16 @@
|
|
|
136
140
|
"
|
|
137
141
|
>
|
|
138
142
|
<div
|
|
139
|
-
v-if="
|
|
143
|
+
v-if="
|
|
144
|
+
showAnswers
|
|
145
|
+
&& !isMCR
|
|
146
|
+
&& !isMatrixQuestion
|
|
147
|
+
&& !isMPMCQuestion
|
|
148
|
+
&& !isBuildListQuestion
|
|
149
|
+
&& isUnanswered
|
|
150
|
+
&& !isCorrect
|
|
151
|
+
&& !isTeachReview
|
|
152
|
+
"
|
|
140
153
|
v-dark="isDarkMode"
|
|
141
154
|
class="uikit-question__unanswered-label"
|
|
142
155
|
>
|
|
@@ -148,7 +161,11 @@
|
|
|
148
161
|
/>
|
|
149
162
|
</div>
|
|
150
163
|
<ChoicesContainer
|
|
151
|
-
v-if="
|
|
164
|
+
v-if="
|
|
165
|
+
question.type !== 'Matrix Checkbox'
|
|
166
|
+
&& question.type !== 'Matrix Radio Button'
|
|
167
|
+
&& question.type !== 'Multi-Part Multiple Choice'
|
|
168
|
+
&& question.type !== 'Build List'"
|
|
152
169
|
ref="uikit-question__choices-container"
|
|
153
170
|
@emitChoiceMouseOver="choiceMouseOver"
|
|
154
171
|
@emitChoiceMouseLeave="choiceMouseLeave"
|
|
@@ -243,9 +260,34 @@
|
|
|
243
260
|
<slot name="explanationBottomExperiment" />
|
|
244
261
|
</template>
|
|
245
262
|
</MobileMatrixChoicesContainer>
|
|
263
|
+
<MPMCChoicesContainer
|
|
264
|
+
v-if="question.type === 'Multi-Part Multiple Choice'"
|
|
265
|
+
class="uikit-question__mpmc-choices-container"
|
|
266
|
+
v-breakpoint="breakpointsWithEl"
|
|
267
|
+
@emitSelectedMPMCChoice="selectMPMCChoice"
|
|
268
|
+
>
|
|
269
|
+
<template #explanationBottomExperiment>
|
|
270
|
+
<slot name="explanationBottomExperiment" />
|
|
271
|
+
</template>
|
|
272
|
+
</MPMCChoicesContainer>
|
|
273
|
+
<BuildListChoicesContainer
|
|
274
|
+
v-if="question.type === 'Build List'"
|
|
275
|
+
class="uikit-question__build-list-choices-container"
|
|
276
|
+
v-breakpoint="breakpointsWithEl"
|
|
277
|
+
@reorderBuildList="handleBuildListReorder"
|
|
278
|
+
>
|
|
279
|
+
<template #explanationBottomExperiment>
|
|
280
|
+
<slot name="explanationBottomExperiment" />
|
|
281
|
+
</template>
|
|
282
|
+
</BuildListChoicesContainer>
|
|
246
283
|
</div>
|
|
247
284
|
<Summary
|
|
248
|
-
v-if="
|
|
285
|
+
v-if="
|
|
286
|
+
((isMCR && showAnswers)
|
|
287
|
+
|| (isMatrixQuestion && showMatrixAnswers))
|
|
288
|
+
|| (isMPMCQuestion && showMPMCAnswers)
|
|
289
|
+
|| (isBuildListQuestion && showBuildListOrder)
|
|
290
|
+
&& !showPaywall"
|
|
249
291
|
ref="uikit-question__summary"
|
|
250
292
|
class="uikit-question__summary"
|
|
251
293
|
@click="keywordClick"
|
|
@@ -294,7 +336,14 @@
|
|
|
294
336
|
>
|
|
295
337
|
<slot name="action">
|
|
296
338
|
<PocketButton
|
|
297
|
-
v-if="
|
|
339
|
+
v-if="
|
|
340
|
+
!showAnswers
|
|
341
|
+
&& !hideAnswer
|
|
342
|
+
&& (showCheckAnswer || isMCR)
|
|
343
|
+
&& !isMatrixQuestion
|
|
344
|
+
&& !isBuildListQuestion
|
|
345
|
+
&& !isMPMCQuestion
|
|
346
|
+
"
|
|
298
347
|
:disabled="!selectedChoices.length"
|
|
299
348
|
:is-dark-mode="isDarkMode"
|
|
300
349
|
@click="clickCheckAnswer"
|
|
@@ -310,14 +359,41 @@
|
|
|
310
359
|
Check Answer
|
|
311
360
|
</PocketButton>
|
|
312
361
|
<PocketButton
|
|
313
|
-
v-else-if="
|
|
362
|
+
v-else-if="isBuildListQuestion && !showBuildListOrder && !hideAnswer"
|
|
363
|
+
:is-dark-mode="isDarkMode"
|
|
364
|
+
:disabled="!selectedBuildListChoiceOrder.length"
|
|
365
|
+
@click="clickCheckBuildListOrder"
|
|
366
|
+
>
|
|
367
|
+
Check Answer
|
|
368
|
+
</PocketButton>
|
|
369
|
+
<PocketButton
|
|
370
|
+
v-else-if="isMPMCQuestion && !showMPMCAnswers && !hideAnswer"
|
|
371
|
+
:disabled="!isMPMCQuestionAnswered"
|
|
372
|
+
:is-dark-mode="isDarkMode"
|
|
373
|
+
@click="clickCheckMPMCAnswer"
|
|
374
|
+
>
|
|
375
|
+
Check Answer
|
|
376
|
+
</PocketButton>
|
|
377
|
+
|
|
378
|
+
<PocketButton
|
|
379
|
+
v-else-if="(
|
|
380
|
+
showAnswers
|
|
381
|
+
|| showMatrixAnswers
|
|
382
|
+
|| showBuildListOrder
|
|
383
|
+
|| showMPMCAnswers
|
|
384
|
+
|| hideAnswer)
|
|
385
|
+
&& (questionNumber >= quizLength)
|
|
386
|
+
"
|
|
314
387
|
:is-dark-mode="isDarkMode"
|
|
315
388
|
@click="emitSubmitQuiz"
|
|
316
389
|
>
|
|
317
390
|
Submit Quiz
|
|
318
391
|
</PocketButton>
|
|
319
392
|
<PocketButton
|
|
320
|
-
v-else-if="
|
|
393
|
+
v-else-if="
|
|
394
|
+
(showAnswers || showMatrixAnswers || showBuildListOrder || showMPMCAnswers || hideAnswer )
|
|
395
|
+
&& showNextQuestion
|
|
396
|
+
"
|
|
321
397
|
:is-dark-mode="isDarkMode"
|
|
322
398
|
@click="emitNextQuestion"
|
|
323
399
|
>
|
|
@@ -341,6 +417,7 @@
|
|
|
341
417
|
:class="{
|
|
342
418
|
'uikit-question__right-side--explanation': showExplanation && !showPaywall,
|
|
343
419
|
'uikit-question__right-side--matrix-question-review-mode': isMatrixQuestion && reviewMode,
|
|
420
|
+
'uikit-question__right-side--mpmc-question-review-mode': isMPMCQuestion && reviewMode,
|
|
344
421
|
}"
|
|
345
422
|
>
|
|
346
423
|
<PassageAndImage
|
|
@@ -382,6 +459,8 @@ import Explanation from '../Quiz/Question/Explanation.vue'
|
|
|
382
459
|
import PassageAndImage from '../Quiz/Question/PassageAndImage.vue'
|
|
383
460
|
import MatrixChoicesContainer from '../Quiz/Question/MatrixChoicesContainer.vue'
|
|
384
461
|
import MobileMatrixChoicesContainer from '../Quiz/Question/MobileMatrixChoicesContainer.vue'
|
|
462
|
+
import MPMCChoicesContainer from '../Quiz/Question/MPMCChoicesContainer.vue'
|
|
463
|
+
import BuildListChoicesContainer from './Question/BuildListChoicesContainer.vue'
|
|
385
464
|
import type { Study } from '@pocketprep/types'
|
|
386
465
|
import { highlightKeywordsInText, studyModes } from '../../utils'
|
|
387
466
|
import type {
|
|
@@ -389,9 +468,12 @@ import type {
|
|
|
389
468
|
TQuizMode,
|
|
390
469
|
TChoiceKey,
|
|
391
470
|
TMatrixChoiceKey,
|
|
471
|
+
TBuildListChoiceKey,
|
|
392
472
|
TChoice,
|
|
473
|
+
TBuildListChoice,
|
|
393
474
|
TChoiceScores,
|
|
394
475
|
TMatrixChoiceScores,
|
|
476
|
+
TBuildListChoiceScores,
|
|
395
477
|
TViewNames,
|
|
396
478
|
IScenarioSerial,
|
|
397
479
|
} from './question'
|
|
@@ -411,6 +493,8 @@ const props = withDefaults(defineProps<{
|
|
|
411
493
|
reviewMode?: boolean
|
|
412
494
|
previousChoices?: TChoiceKey[] | null
|
|
413
495
|
previousMatrixChoices?: TMatrixChoiceKey[] | null
|
|
496
|
+
previousMultiPartMultipleChoiceChoices?: TChoiceKey[] | null
|
|
497
|
+
previousBuildListChoices?: TBuildListChoiceKey[] | null
|
|
414
498
|
globalMetrics?: Study.Class.GlobalQuestionMetricJSON | null
|
|
415
499
|
showNames?: TViewNames | null
|
|
416
500
|
allowKeyboardShortcuts?: boolean
|
|
@@ -435,6 +519,8 @@ const props = withDefaults(defineProps<{
|
|
|
435
519
|
reviewMode: false,
|
|
436
520
|
previousChoices: null,
|
|
437
521
|
previousMatrixChoices: null,
|
|
522
|
+
previousMultiPartMultipleChoiceChoices: null,
|
|
523
|
+
previousBuildListChoices: null,
|
|
438
524
|
globalMetrics: null,
|
|
439
525
|
showNames: null,
|
|
440
526
|
allowKeyboardShortcuts: true,
|
|
@@ -488,8 +574,12 @@ const focusChoiceKey = ref<TChoiceKey | null>(null)
|
|
|
488
574
|
const choiceStrikes = ref<TChoiceKey[]>([])
|
|
489
575
|
const selectedChoices = ref<TChoiceKey[]>([])
|
|
490
576
|
const selectedMatrixChoices = ref<TMatrixChoiceKey[]>([])
|
|
577
|
+
const selectedMPMCChoices = ref<TChoiceKey[]>([])
|
|
578
|
+
const selectedBuildListChoiceOrder = ref<TBuildListChoiceKey[]>([])
|
|
491
579
|
const showAnswers = ref(false)
|
|
492
580
|
const showMatrixAnswers = ref(false)
|
|
581
|
+
const showMPMCAnswers = ref(false)
|
|
582
|
+
const showBuildListOrder = ref(false)
|
|
493
583
|
const showExplanation = ref(false)
|
|
494
584
|
const showPassageImageLongAlt = ref(false)
|
|
495
585
|
const showExplanationImageLongAlt = ref(false)
|
|
@@ -517,6 +607,7 @@ const questionSummaryRef = useTemplateRef<{
|
|
|
517
607
|
mcrLongAltEl?: HTMLElement
|
|
518
608
|
summaryMCRExplanationEl?: HTMLElement
|
|
519
609
|
summaryMatrixExplanationEl?: HTMLElement
|
|
610
|
+
summaryBuildListExplanationEl?: HTMLElement
|
|
520
611
|
}>('uikit-question__summary')
|
|
521
612
|
const questionExplanationRef = useTemplateRef<{
|
|
522
613
|
explanationTitleEl?: HTMLElement
|
|
@@ -561,6 +652,14 @@ const isMatrixQuestion = computed(() => {
|
|
|
561
652
|
return props.question.type === 'Matrix Checkbox' || props.question.type === 'Matrix Radio Button'
|
|
562
653
|
})
|
|
563
654
|
|
|
655
|
+
const isMPMCQuestion = computed(() => {
|
|
656
|
+
return props.question.type === 'Multi-Part Multiple Choice'
|
|
657
|
+
})
|
|
658
|
+
|
|
659
|
+
const isBuildListQuestion = computed(() => {
|
|
660
|
+
return props.question.type === 'Build List'
|
|
661
|
+
})
|
|
662
|
+
|
|
564
663
|
const questionScenario = computed(() => {
|
|
565
664
|
return props.question.questionScenario as Study.Class.QuestionScenarioJSON | undefined
|
|
566
665
|
})
|
|
@@ -648,6 +747,16 @@ const matrixAnswerKeys = computed<TMatrixChoiceKey[]>(() => {
|
|
|
648
747
|
return [] as TMatrixChoiceKey[]
|
|
649
748
|
})
|
|
650
749
|
|
|
750
|
+
const correctOrderBuildListAnswerKeys = computed((): TBuildListChoiceKey[] => {
|
|
751
|
+
const buildListChoices = props.question.choices.map(choice => choice.id) as TBuildListChoiceKey[]
|
|
752
|
+
return buildListChoices
|
|
753
|
+
.sort((a, b) => {
|
|
754
|
+
const aNum = Number(a.substring(1))
|
|
755
|
+
const bNum = Number(b.substring(1))
|
|
756
|
+
return aNum - bNum
|
|
757
|
+
})
|
|
758
|
+
})
|
|
759
|
+
|
|
651
760
|
const distractors = computed((): TChoice[] => {
|
|
652
761
|
return props.question.choices.filter(choice => !choice.isCorrect).map((choice, index) => ({
|
|
653
762
|
text: choice.text,
|
|
@@ -666,6 +775,32 @@ const choices = computed(() => {
|
|
|
666
775
|
])
|
|
667
776
|
})
|
|
668
777
|
|
|
778
|
+
const buildListChoices = computed(() => {
|
|
779
|
+
const blChoices = props.question.choices.map(choice => {
|
|
780
|
+
return {
|
|
781
|
+
text: choice.text,
|
|
782
|
+
key: choice.id as TBuildListChoiceKey,
|
|
783
|
+
}
|
|
784
|
+
})
|
|
785
|
+
|
|
786
|
+
const shuffledChoices = shuffleBuildListChoices([ ...blChoices ])
|
|
787
|
+
|
|
788
|
+
// Check if the shuffled array is in correct order
|
|
789
|
+
const isInCorrectOrder = shuffledChoices.every((choice, index) => {
|
|
790
|
+
const expectedNumber = index + 1
|
|
791
|
+
const actualNumber = Number(choice.key.substring(1))
|
|
792
|
+
return actualNumber === expectedNumber
|
|
793
|
+
})
|
|
794
|
+
|
|
795
|
+
// If it is in the correct order, then we need to switch the first and second element
|
|
796
|
+
if (isInCorrectOrder && shuffledChoices.length >= 2) {
|
|
797
|
+
const [ first, second, ...rest ] = shuffledChoices
|
|
798
|
+
return [ second, first, ...rest ] as TBuildListChoice[]
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
return shuffledChoices
|
|
802
|
+
})
|
|
803
|
+
|
|
669
804
|
const isCorrect = computed(() => {
|
|
670
805
|
// In order to be correct, user must have selected all the answers and none of the distractors
|
|
671
806
|
return showAnswers.value
|
|
@@ -679,6 +814,20 @@ const isMatrixQuestionCorrect = computed(() => {
|
|
|
679
814
|
&& !selectedMatrixChoices.value.join(' ').includes('d')
|
|
680
815
|
})
|
|
681
816
|
|
|
817
|
+
const isMPMCQuestionCorrect = computed(() => {
|
|
818
|
+
return showMPMCAnswers.value
|
|
819
|
+
&& selectedMPMCChoices.value.length === answerKeys.value.length
|
|
820
|
+
&& !selectedMPMCChoices.value.join(' ').includes('d')
|
|
821
|
+
})
|
|
822
|
+
|
|
823
|
+
const isBuildListOrderCorrect = computed(() => {
|
|
824
|
+
return showBuildListOrder.value
|
|
825
|
+
&& correctOrderBuildListAnswerKeys.value.length === selectedBuildListChoiceOrder.value.length
|
|
826
|
+
&& correctOrderBuildListAnswerKeys.value.every(
|
|
827
|
+
(item, index) => item === selectedBuildListChoiceOrder.value[index]
|
|
828
|
+
)
|
|
829
|
+
})
|
|
830
|
+
|
|
682
831
|
const choiceScores = computed((): TChoiceScores => {
|
|
683
832
|
const metrics = globalMetrics.value
|
|
684
833
|
const scores: TChoiceScores = {
|
|
@@ -718,7 +867,49 @@ const matrixChoiceScores = computed((): TMatrixChoiceScores => {
|
|
|
718
867
|
const scores: TMatrixChoiceScores = {
|
|
719
868
|
totalAnswered: selectedMatrixChoices.value.length &&
|
|
720
869
|
showMatrixAnswers && !props.reviewMode ? 1 : 0,
|
|
721
|
-
answeredCorrectly:
|
|
870
|
+
answeredCorrectly: isMatrixQuestionCorrect.value && !props.reviewMode ? 1 : 0,
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
if (!metrics) {
|
|
874
|
+
return scores
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
scores.totalAnswered += (
|
|
878
|
+
(metrics.answeredCorrectlyCount || 0)
|
|
879
|
+
+ (metrics.answeredIncorrectlyCount || 0)
|
|
880
|
+
)
|
|
881
|
+
scores.answeredCorrectly += (metrics.answeredCorrectlyCount || 0)
|
|
882
|
+
return scores
|
|
883
|
+
})
|
|
884
|
+
|
|
885
|
+
const mpmcChoiceScores = computed((): TChoiceScores => {
|
|
886
|
+
const metrics = props.globalMetrics
|
|
887
|
+
|
|
888
|
+
const scores: TChoiceScores = {
|
|
889
|
+
totalAnswered: selectedMPMCChoices.value.length &&
|
|
890
|
+
showMPMCAnswers && !props.reviewMode ? 1 : 0,
|
|
891
|
+
answeredCorrectly: isMPMCQuestionCorrect.value && !props.reviewMode ? 1 : 0,
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
if (!metrics) {
|
|
895
|
+
return scores
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
scores.totalAnswered += (
|
|
899
|
+
(metrics.answeredCorrectlyCount || 0)
|
|
900
|
+
+ (metrics.answeredIncorrectlyCount || 0)
|
|
901
|
+
)
|
|
902
|
+
scores.answeredCorrectly += (metrics.answeredCorrectlyCount || 0)
|
|
903
|
+
return scores
|
|
904
|
+
})
|
|
905
|
+
|
|
906
|
+
const buildListChoiceScores = computed((): TBuildListChoiceScores => {
|
|
907
|
+
const metrics = props.globalMetrics
|
|
908
|
+
|
|
909
|
+
const scores: TBuildListChoiceScores = {
|
|
910
|
+
totalAnswered: selectedBuildListChoiceOrder.value.length &&
|
|
911
|
+
showBuildListOrder && !props.reviewMode ? 1 : 0,
|
|
912
|
+
answeredCorrectly: isBuildListOrderCorrect.value && !props.reviewMode ? 1 : 0,
|
|
722
913
|
}
|
|
723
914
|
|
|
724
915
|
if (!metrics) {
|
|
@@ -754,12 +945,38 @@ const isMatrixQuestionAnswered = computed(() => {
|
|
|
754
945
|
return false
|
|
755
946
|
})
|
|
756
947
|
|
|
948
|
+
const isMPMCQuestionAnswered = computed(() => {
|
|
949
|
+
const mpmcLabels = question.value.mpmcLabels
|
|
950
|
+
const mpmcChoices = question.value.choices
|
|
951
|
+
const selectedMPMCLabelIndexes: number[] = []
|
|
952
|
+
|
|
953
|
+
selectedMPMCChoices.value.forEach(choice => {
|
|
954
|
+
const mpmcChoiceObj = mpmcChoices.find(c => c.id === choice)
|
|
955
|
+
if (
|
|
956
|
+
mpmcChoiceObj?.labelIndex !== undefined
|
|
957
|
+
&& !selectedMPMCLabelIndexes.includes(mpmcChoiceObj?.labelIndex)
|
|
958
|
+
) {
|
|
959
|
+
selectedMPMCLabelIndexes.push(mpmcChoiceObj?.labelIndex)
|
|
960
|
+
}
|
|
961
|
+
})
|
|
962
|
+
|
|
963
|
+
return mpmcLabels?.length === selectedMPMCLabelIndexes.length
|
|
964
|
+
})
|
|
965
|
+
|
|
757
966
|
const isUnanswered = computed(() => {
|
|
758
|
-
if (
|
|
759
|
-
return
|
|
967
|
+
if (isBuildListQuestion.value) {
|
|
968
|
+
return selectedBuildListChoiceOrder.value.length === 0
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
if (isMPMCQuestion.value) {
|
|
972
|
+
return !isMPMCQuestionAnswered.value
|
|
760
973
|
}
|
|
761
974
|
|
|
762
|
-
|
|
975
|
+
if (isMatrixQuestion.value) {
|
|
976
|
+
return !isMatrixQuestionAnswered.value
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
return selectedChoices.value.length === 0
|
|
763
980
|
})
|
|
764
981
|
|
|
765
982
|
const prompt = computed(() => {
|
|
@@ -854,20 +1071,28 @@ const keywordClick = (event: MouseEvent) => {
|
|
|
854
1071
|
}
|
|
855
1072
|
|
|
856
1073
|
const startReviewMode = () => {
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
1074
|
+
showExplanation.value = props.defaultShowExplanation === null ? true : props.defaultShowExplanation
|
|
1075
|
+
|
|
1076
|
+
if (isBuildListQuestion.value) {
|
|
1077
|
+
showBuildListOrder.value = true
|
|
1078
|
+
selectedBuildListChoiceOrder.value = correctOrderBuildListAnswerKeys.value
|
|
1079
|
+
} else if (isMPMCQuestion.value) {
|
|
1080
|
+
showMPMCAnswers.value = true
|
|
1081
|
+
selectedMPMCChoices.value = answerKeys.value
|
|
1082
|
+
} else if (isMatrixQuestion.value) {
|
|
862
1083
|
showMatrixAnswers.value = true
|
|
863
|
-
showExplanation.value = props.defaultShowExplanation === null ? true : props.defaultShowExplanation
|
|
864
1084
|
selectedMatrixChoices.value = matrixAnswerKeys.value
|
|
1085
|
+
} else {
|
|
1086
|
+
showAnswers.value = true
|
|
1087
|
+
selectedChoices.value = answerKeys.value
|
|
865
1088
|
}
|
|
866
1089
|
}
|
|
867
1090
|
|
|
868
1091
|
const stopReviewMode = () => {
|
|
869
1092
|
showAnswers.value = false
|
|
870
1093
|
showMatrixAnswers.value = false
|
|
1094
|
+
showMPMCAnswers.value = false
|
|
1095
|
+
showBuildListOrder.value = false
|
|
871
1096
|
showExplanation.value = false
|
|
872
1097
|
selectedChoices.value = []
|
|
873
1098
|
selectedMatrixChoices.value = []
|
|
@@ -881,8 +1106,16 @@ const updateSelectedMatrixChoices = (matrixChoices: TMatrixChoiceKey[]) => {
|
|
|
881
1106
|
selectedMatrixChoices.value = [ ...matrixChoices ]
|
|
882
1107
|
}
|
|
883
1108
|
|
|
1109
|
+
const updateSelectedMPMCChoices = (updatedChoices: TChoiceKey[]) => {
|
|
1110
|
+
selectedMPMCChoices.value = [ ...updatedChoices ]
|
|
1111
|
+
}
|
|
1112
|
+
|
|
1113
|
+
const updateSelectedBuildListChoiceOrder = (buildListChoiceOrder: TBuildListChoiceKey[]) => {
|
|
1114
|
+
selectedBuildListChoiceOrder.value = [ ...buildListChoiceOrder ]
|
|
1115
|
+
}
|
|
1116
|
+
|
|
884
1117
|
// deterministic shuffling of choices so they don't change order everytime you reload the component
|
|
885
|
-
const shuffleChoices = (choicesToShuffle: TChoice[]): TChoice[]
|
|
1118
|
+
const shuffleChoices = (choicesToShuffle: TChoice[]): TChoice[]=> {
|
|
886
1119
|
const sortedChoices = choicesToShuffle.sort((a, b) => {
|
|
887
1120
|
const hashChar = (char: string, num: number) => ((num << 5) - num) + char.charCodeAt(0)
|
|
888
1121
|
|
|
@@ -906,6 +1139,30 @@ const shuffleChoices = (choicesToShuffle: TChoice[]): TChoice[] => {
|
|
|
906
1139
|
: sortedChoices
|
|
907
1140
|
}
|
|
908
1141
|
|
|
1142
|
+
const shuffleBuildListChoices = (choicesToShuffle: TBuildListChoice[]): TBuildListChoice[]=> {
|
|
1143
|
+
const sortedChoices = choicesToShuffle.sort((a, b) => {
|
|
1144
|
+
const hashChar = (char: string, num: number) => ((num << 5) - num) + char.charCodeAt(0)
|
|
1145
|
+
|
|
1146
|
+
const aHash = a.text?.split('')
|
|
1147
|
+
.reduce((acc: number, char: string) => hashChar(char, acc) & hashChar(char, acc), 0)
|
|
1148
|
+
const bHash = b.text?.split('')
|
|
1149
|
+
.reduce((acc: number, char: string) => hashChar(char, acc) & hashChar(char, acc), 0)
|
|
1150
|
+
|
|
1151
|
+
return (aHash || 0) - (bHash || 0)
|
|
1152
|
+
})
|
|
1153
|
+
|
|
1154
|
+
return props.answerSeed
|
|
1155
|
+
? props.answerSeed.reduce<TBuildListChoice[]>((acc, i) => {
|
|
1156
|
+
const sortedChoice = sortedChoices[i]
|
|
1157
|
+
if (sortedChoice) {
|
|
1158
|
+
acc.push(sortedChoice)
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
return acc
|
|
1162
|
+
}, [])
|
|
1163
|
+
: sortedChoices
|
|
1164
|
+
}
|
|
1165
|
+
|
|
909
1166
|
const choiceFocusOut = (event: FocusEvent) => {
|
|
910
1167
|
const relatedTarget = event.relatedTarget
|
|
911
1168
|
if (
|
|
@@ -1050,6 +1307,21 @@ const selectMatrixChoice = (matrixChoiceKeys: TMatrixChoiceKey[]) => {
|
|
|
1050
1307
|
selectedMatrixChoices.value = matrixChoiceKeys
|
|
1051
1308
|
}
|
|
1052
1309
|
|
|
1310
|
+
const selectMPMCChoice = (mpmcChoiceKeys: TChoiceKey[]) => {
|
|
1311
|
+
if (showMPMCAnswers.value) {
|
|
1312
|
+
return
|
|
1313
|
+
}
|
|
1314
|
+
selectedMPMCChoices.value = mpmcChoiceKeys
|
|
1315
|
+
}
|
|
1316
|
+
|
|
1317
|
+
const handleBuildListReorder = (reorderedChoices: TBuildListChoice[]) => {
|
|
1318
|
+
if (showBuildListOrder.value) {
|
|
1319
|
+
return
|
|
1320
|
+
}
|
|
1321
|
+
|
|
1322
|
+
selectedBuildListChoiceOrder.value = reorderedChoices.map(choice => choice.key)
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1053
1325
|
const togglePassageImageLongAlt = () => {
|
|
1054
1326
|
showPassageImageLongAlt.value = !showPassageImageLongAlt.value
|
|
1055
1327
|
|
|
@@ -1151,6 +1423,41 @@ const clickCheckMatrixAnswer = () => {
|
|
|
1151
1423
|
}
|
|
1152
1424
|
}
|
|
1153
1425
|
|
|
1426
|
+
const clickCheckMPMCAnswer = () => {
|
|
1427
|
+
if (!props.hideAnswer) {
|
|
1428
|
+
showMPMCAnswers.value = true
|
|
1429
|
+
|
|
1430
|
+
emitCheckAnswer({
|
|
1431
|
+
isCorrect: isMPMCQuestionCorrect.value,
|
|
1432
|
+
selectedChoices: selectedMPMCChoices.value,
|
|
1433
|
+
questionSerial: props.question.serial,
|
|
1434
|
+
})
|
|
1435
|
+
|
|
1436
|
+
const summaryMatrixExplanationEl = questionSummaryRef?.value?.summaryMatrixExplanationEl
|
|
1437
|
+
if (summaryMatrixExplanationEl) {
|
|
1438
|
+
summaryMatrixExplanationEl?.focus()
|
|
1439
|
+
}
|
|
1440
|
+
}
|
|
1441
|
+
}
|
|
1442
|
+
|
|
1443
|
+
const clickCheckBuildListOrder = () => {
|
|
1444
|
+
if (!props.hideAnswer) {
|
|
1445
|
+
showBuildListOrder.value = true
|
|
1446
|
+
|
|
1447
|
+
emitCheckAnswer({
|
|
1448
|
+
isCorrect: isBuildListOrderCorrect.value,
|
|
1449
|
+
selectedChoices: selectedBuildListChoiceOrder.value,
|
|
1450
|
+
questionSerial: props.question.serial,
|
|
1451
|
+
})
|
|
1452
|
+
|
|
1453
|
+
const summaryBuildListExplanationEl = questionSummaryRef?.value?.summaryBuildListExplanationEl
|
|
1454
|
+
|
|
1455
|
+
if (summaryBuildListExplanationEl) {
|
|
1456
|
+
summaryBuildListExplanationEl?.focus()
|
|
1457
|
+
}
|
|
1458
|
+
}
|
|
1459
|
+
}
|
|
1460
|
+
|
|
1154
1461
|
watch(reviewMode, () => {
|
|
1155
1462
|
if (reviewMode.value) {
|
|
1156
1463
|
startReviewMode()
|
|
@@ -1171,6 +1478,21 @@ watch(() => props.previousMatrixChoices, (previousMatrixChoices: TMatrixChoiceKe
|
|
|
1171
1478
|
}
|
|
1172
1479
|
}, { deep: true })
|
|
1173
1480
|
|
|
1481
|
+
watch(() =>
|
|
1482
|
+
props.previousMultiPartMultipleChoiceChoices,
|
|
1483
|
+
(previousMultiPartMultipleChoiceChoices: TChoiceKey[] | undefined | null
|
|
1484
|
+
) => {
|
|
1485
|
+
if (previousMultiPartMultipleChoiceChoices) {
|
|
1486
|
+
updateSelectedMPMCChoices(previousMultiPartMultipleChoiceChoices)
|
|
1487
|
+
}
|
|
1488
|
+
}, { deep: true })
|
|
1489
|
+
|
|
1490
|
+
watch(() => props.previousBuildListChoices, (previousBuildListChoices: TBuildListChoiceKey[] | undefined | null) => {
|
|
1491
|
+
if (previousBuildListChoices) {
|
|
1492
|
+
updateSelectedBuildListChoiceOrder(previousBuildListChoices)
|
|
1493
|
+
}
|
|
1494
|
+
}, { deep: true })
|
|
1495
|
+
|
|
1174
1496
|
watch(selectedChoices, () => {
|
|
1175
1497
|
emitSelectedChoices({
|
|
1176
1498
|
isCorrect: selectedChoices.value.length === answerKeys.value.length
|
|
@@ -1189,6 +1511,25 @@ watch(selectedMatrixChoices, () => {
|
|
|
1189
1511
|
} as Study.Cloud.IQuizAnswer)
|
|
1190
1512
|
}, { deep: true })
|
|
1191
1513
|
|
|
1514
|
+
watch(selectedBuildListChoiceOrder, () => {
|
|
1515
|
+
emitSelectedChoices({
|
|
1516
|
+
isCorrect: correctOrderBuildListAnswerKeys.value.length === selectedBuildListChoiceOrder.value.length
|
|
1517
|
+
&& correctOrderBuildListAnswerKeys.value.every(
|
|
1518
|
+
(item, index) => item === selectedBuildListChoiceOrder.value[index]),
|
|
1519
|
+
selectedChoices: selectedBuildListChoiceOrder.value,
|
|
1520
|
+
questionSerial: props.question.serial,
|
|
1521
|
+
} as Study.Cloud.IQuizAnswer)
|
|
1522
|
+
}, { deep: true })
|
|
1523
|
+
|
|
1524
|
+
watch(selectedMPMCChoices, () => {
|
|
1525
|
+
emitSelectedChoices({
|
|
1526
|
+
isCorrect: selectedMPMCChoices.value.length === answerKeys.value.length
|
|
1527
|
+
&& !selectedMPMCChoices.value.join(' ').includes('d'),
|
|
1528
|
+
selectedChoices: selectedMPMCChoices.value,
|
|
1529
|
+
questionSerial: props.question.serial,
|
|
1530
|
+
} as Study.Cloud.IQuizAnswer)
|
|
1531
|
+
}, { deep: true })
|
|
1532
|
+
|
|
1192
1533
|
watch(showExplanation, () => {
|
|
1193
1534
|
emitUpdateShowExplanation()
|
|
1194
1535
|
})
|
|
@@ -1229,7 +1570,7 @@ if (props.reviewMode) {
|
|
|
1229
1570
|
startReviewMode()
|
|
1230
1571
|
}
|
|
1231
1572
|
|
|
1232
|
-
if (!isMatrixQuestion.value && props.previousChoices) {
|
|
1573
|
+
if (!isMatrixQuestion.value && !isMPMCQuestion.value && !isBuildListQuestion.value && props.previousChoices) {
|
|
1233
1574
|
updateSelectedChoices(props.previousChoices)
|
|
1234
1575
|
}
|
|
1235
1576
|
|
|
@@ -1237,12 +1578,22 @@ if (isMatrixQuestion.value && props.previousMatrixChoices) {
|
|
|
1237
1578
|
updateSelectedMatrixChoices(props.previousMatrixChoices)
|
|
1238
1579
|
}
|
|
1239
1580
|
|
|
1581
|
+
if (isBuildListQuestion.value && props.previousBuildListChoices) {
|
|
1582
|
+
updateSelectedBuildListChoiceOrder(props.previousBuildListChoices)
|
|
1583
|
+
}
|
|
1584
|
+
|
|
1585
|
+
if (isMPMCQuestion.value && props.previousMultiPartMultipleChoiceChoices) {
|
|
1586
|
+
updateSelectedMPMCChoices(props.previousMultiPartMultipleChoiceChoices)
|
|
1587
|
+
}
|
|
1588
|
+
|
|
1240
1589
|
onMounted(() => {
|
|
1241
1590
|
questionEl.value = props.containerEl || questionRef.value
|
|
1242
1591
|
|
|
1243
1592
|
if (props.initialShowAnswers) {
|
|
1244
1593
|
showAnswers.value = props.initialShowAnswers
|
|
1245
1594
|
showMatrixAnswers.value = props.initialShowAnswers
|
|
1595
|
+
showMPMCAnswers.value = props.initialShowAnswers
|
|
1596
|
+
showBuildListOrder.value = props.initialShowAnswers
|
|
1246
1597
|
}
|
|
1247
1598
|
|
|
1248
1599
|
if (props.allowKeyboardShortcuts) {
|
|
@@ -1269,6 +1620,7 @@ onBeforeUnmount(() => {
|
|
|
1269
1620
|
// Provide question context once, instead of passing as props to every child
|
|
1270
1621
|
provide(InjectionKeys.questionKey, question)
|
|
1271
1622
|
provide(InjectionKeys.choicesKey, choices)
|
|
1623
|
+
provide(InjectionKeys.buildListChoicesKey, buildListChoices)
|
|
1272
1624
|
provide(InjectionKeys.questionElKey, questionEl)
|
|
1273
1625
|
provide(InjectionKeys.breakpointsWithElKey, breakpointsWithEl)
|
|
1274
1626
|
provide(InjectionKeys.quizLengthKey, quizLength)
|
|
@@ -1279,6 +1631,8 @@ provide(InjectionKeys.isCorrectKey, isCorrect)
|
|
|
1279
1631
|
provide(InjectionKeys.contextIconTypeKey, contextIconType)
|
|
1280
1632
|
provide(InjectionKeys.showAnswersKey, showAnswers)
|
|
1281
1633
|
provide(InjectionKeys.showMatrixAnswersKey, showMatrixAnswers)
|
|
1634
|
+
provide(InjectionKeys.showMPMCAnswersKey, showMPMCAnswers)
|
|
1635
|
+
provide(InjectionKeys.showBuildListOrderKey, showBuildListOrder)
|
|
1282
1636
|
provide(InjectionKeys.imageUrlPrefixKey, imageUrlPrefix)
|
|
1283
1637
|
provide(InjectionKeys.passageImageUrlKey, passageImageUrl)
|
|
1284
1638
|
provide(InjectionKeys.passageImageAltKey, passageImageAlt)
|
|
@@ -1307,10 +1661,18 @@ provide(InjectionKeys.keywordDefinitionsKey, keywordDefinitions)
|
|
|
1307
1661
|
provide(InjectionKeys.showPaywallKey, showPaywall)
|
|
1308
1662
|
provide(InjectionKeys.showPassageAndImageKey, showPassageAndImage)
|
|
1309
1663
|
provide(InjectionKeys.isMatrixQuestionKey, isMatrixQuestion)
|
|
1664
|
+
provide(InjectionKeys.isMPMCQuestionKey, isMPMCQuestion)
|
|
1310
1665
|
provide(InjectionKeys.matrixChoiceScoresKey, matrixChoiceScores)
|
|
1666
|
+
provide(InjectionKeys.mpmcChoiceScoresKey, mpmcChoiceScores)
|
|
1311
1667
|
provide(InjectionKeys.isMatrixQuestionCorrectKey, isMatrixQuestionCorrect)
|
|
1668
|
+
provide(InjectionKeys.isMPMCQuestionCorrectKey, isMPMCQuestionCorrect)
|
|
1312
1669
|
provide(InjectionKeys.matrixAnswerKeysKey, matrixAnswerKeys)
|
|
1313
1670
|
provide(InjectionKeys.selectedMatrixChoicesKey, selectedMatrixChoices)
|
|
1671
|
+
provide(InjectionKeys.selectedMPMCChoicesKey, selectedMPMCChoices)
|
|
1672
|
+
provide(InjectionKeys.isBuildListQuestionKey, isBuildListQuestion)
|
|
1673
|
+
provide(InjectionKeys.buildListChoiceScoresKey, buildListChoiceScores)
|
|
1674
|
+
provide(InjectionKeys.isBuildListOrderCorrectKey, isBuildListOrderCorrect)
|
|
1675
|
+
provide(InjectionKeys.selectedBuildListChoiceOrderKey, selectedBuildListChoiceOrder)
|
|
1314
1676
|
provide(InjectionKeys.isTeachGroupReviewKey, isTeachGroupReview)
|
|
1315
1677
|
</script>
|
|
1316
1678
|
|
|
@@ -1392,16 +1754,19 @@ provide(InjectionKeys.isTeachGroupReviewKey, isTeachGroupReview)
|
|
|
1392
1754
|
padding: 0 17px;
|
|
1393
1755
|
}
|
|
1394
1756
|
|
|
1395
|
-
&--matrix-question-review-mode#{&}--tablet-landscape:not(&--tablet-portrait)
|
|
1757
|
+
&--matrix-question-review-mode#{&}--tablet-landscape:not(&--tablet-portrait),
|
|
1758
|
+
&--mpmc-question-review-mode#{&}--tablet-landscape:not(&--tablet-portrait) {
|
|
1396
1759
|
width: 100%;
|
|
1397
1760
|
padding-right: 42px;
|
|
1398
1761
|
}
|
|
1399
1762
|
|
|
1400
|
-
&--matrix-question-review-mode#{&}--mobile
|
|
1763
|
+
&--matrix-question-review-mode#{&}--mobile,
|
|
1764
|
+
&--mpmc-question-review-mode#{&}--mobile {
|
|
1401
1765
|
overflow-y: scroll;
|
|
1402
1766
|
}
|
|
1403
1767
|
|
|
1404
|
-
&--mcr-review-mode#{&}--mobile
|
|
1768
|
+
&--mcr-review-mode#{&}--mobile,
|
|
1769
|
+
&--build-list-question-review-mode#{&}--mobile {
|
|
1405
1770
|
overflow-y: scroll;
|
|
1406
1771
|
width: 100%;
|
|
1407
1772
|
padding-right: 17px;
|
|
@@ -1421,7 +1786,8 @@ provide(InjectionKeys.isTeachGroupReviewKey, isTeachGroupReview)
|
|
|
1421
1786
|
display: none;
|
|
1422
1787
|
}
|
|
1423
1788
|
|
|
1424
|
-
&--matrix-question-review-mode#{&}--tablet-landscape
|
|
1789
|
+
&--matrix-question-review-mode#{&}--tablet-landscape,
|
|
1790
|
+
&--mpmc-question-review-mode#{&}--tablet-landscape {
|
|
1425
1791
|
display: none;
|
|
1426
1792
|
}
|
|
1427
1793
|
|
|
@@ -1727,6 +2093,10 @@ provide(InjectionKeys.isTeachGroupReviewKey, isTeachGroupReview)
|
|
|
1727
2093
|
&--matrix {
|
|
1728
2094
|
max-width: 518px;
|
|
1729
2095
|
}
|
|
2096
|
+
|
|
2097
|
+
&--mpmc {
|
|
2098
|
+
max-width: 518px;
|
|
2099
|
+
}
|
|
1730
2100
|
}
|
|
1731
2101
|
|
|
1732
2102
|
&__unanswered-label {
|