Skip to content

Commit cb505cd

Browse files
1 parent 68b10f9 commit cb505cd

File tree

8 files changed

+206
-8
lines changed

8 files changed

+206
-8
lines changed

src/apps/statements/models/Result.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
import Extensions from './Extensions';
2+
import Score from './Score';
23

34
interface Result {
5+
readonly score?: Score;
6+
readonly success?: boolean;
7+
readonly completion?: boolean;
8+
readonly response?: string;
49
readonly duration?: string;
510
readonly extensions?: Extensions;
611
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
interface Score {
2+
/** Decimal number between -1 and 1, inclusive */
3+
readonly scaled: number;
4+
5+
/** Decimal number between min and max (if present, otherwise unrestricted), inclusive */
6+
readonly raw?: number;
7+
8+
/** Decimal number less than max (if present) */
9+
readonly min?: number;
10+
11+
/** Decimal number greater than min (if present) */
12+
readonly max?: number;
13+
}
14+
15+
export default Score;
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { get, has } from 'lodash';
2+
3+
import ActivityInteractionType from '../../../../models/ActivityInteractionType';
4+
import Statement from '../../../../models/Statement';
5+
6+
export const getMatchingQuestionsMetadata = (statement: Statement)
7+
: {readonly [key: string]: any} => {
8+
if (
9+
!(
10+
get(
11+
statement.object,
12+
['definition', 'interactionType'],
13+
) === ActivityInteractionType.MATCHING
14+
&& has(statement, ['result', 'response'])
15+
)
16+
) {
17+
return {};
18+
}
19+
20+
const matchingQuestionsString = get(statement, ['result', 'response']);
21+
const matchingQuestions = matchingQuestionsString
22+
.split('[,]')
23+
.map((mq: string) => mq.split('[.]'));
24+
25+
return { 'https://learninglocker&46;net/matching-response': matchingQuestions };
26+
};
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
11
import Statement from '../../../../models/Statement';
22
import { getBooleanMetadata } from './getBooleanMetadata';
33
import { getDurationMetadata } from './getDurationMetadata';
4+
import { getMatchingQuestionsMetadata } from './getMatchingQuestionsMetadata';
45
import { getSequencingMetadata } from './getSequencingMetadata';
56

67
export default (statement: Statement): { readonly [key: string]: any } => {
78
const durationMetadata = getDurationMetadata(statement);
89
const sequencingMetadata = getSequencingMetadata(statement);
10+
const matchingMetadata = getMatchingQuestionsMetadata(statement);
911
const booleanMetadata = getBooleanMetadata(statement);
1012

1113
return {
1214
...durationMetadata,
1315
...sequencingMetadata,
16+
...matchingMetadata,
1417
...booleanMetadata,
1518
};
1619
};
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import { merge } from 'lodash';
2+
import InteractionActivityDefinition from '../../../../../models/InteractionActivityDefinition';
3+
4+
import Statement from '../../../../../models/Statement';
5+
import SubStatementObject from '../../../../../models/SubStatementObject';
6+
import { statementDefaults } from './statements.fixture';
7+
8+
const singleMatchingQuestion: Statement = {
9+
...statementDefaults,
10+
...{
11+
result: {
12+
response: 'ben[.]3',
13+
},
14+
object: {
15+
id: 'http://www.example.com/tincan/activities/uyheHUJd76s/question4',
16+
objectType: 'Activity',
17+
definition: {
18+
name: { 'en-US': 'Question 4' },
19+
description: { 'en-US': 'Match these people to their kickball team:' },
20+
type: 'http://adlnet.gov/expapi/activities/cmi.interaction',
21+
interactionType: 'matching',
22+
correctResponsesPattern: [
23+
'ben[.]3[,]chris[.]2[,]troy[.]4[,]freddie[.]1',
24+
],
25+
source: [
26+
{
27+
id: 'ben',
28+
description: { 'en-US': 'Ben' },
29+
},
30+
{
31+
id: 'chris',
32+
description: { 'en-US': 'Chris' },
33+
},
34+
{
35+
id: 'troy',
36+
description: { 'en-US': 'Troy' },
37+
},
38+
{
39+
id: 'freddie',
40+
description: { 'en-US': 'Freddie' },
41+
},
42+
],
43+
target: [
44+
{
45+
id: '1',
46+
description: { 'en-US': 'SCORM Engine' },
47+
},
48+
{
49+
id: '2',
50+
description: { 'en-US': 'Pure-sewage' },
51+
},
52+
{
53+
id: '3',
54+
description: { 'en-US': 'Tin Can xAPI' },
55+
},
56+
{
57+
id: '4',
58+
description: { 'en-US': 'SCORM Cloud' },
59+
},
60+
],
61+
} as Partial<InteractionActivityDefinition>,
62+
} as SubStatementObject,
63+
} as Partial<Statement>,
64+
};
65+
66+
const multipleMatchingQuestions: Statement = merge(
67+
{},
68+
singleMatchingQuestion,
69+
{
70+
result: {
71+
response: 'ben[.]3[,]chris[.]2[,]troy[.]4[,]freddie[.]1',
72+
},
73+
} as Partial<Statement>,
74+
);
75+
76+
export {
77+
singleMatchingQuestion,
78+
multipleMatchingQuestions,
79+
};
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import * as assert from 'assert';
2+
3+
import { getMatchingQuestionsMetadata } from '../../../../service/storeStatements/queriables/getMetadataFromStatement/getMatchingQuestionsMetadata';
4+
import {
5+
multipleMatchingQuestions,
6+
singleMatchingQuestion,
7+
} from './fixtures/matching-interaction.fixture';
8+
9+
describe('Retrieve matching questions metadata from statement', () => {
10+
it('should return matching questions metadata from statement', () => {
11+
const expectedEmptyMetadata = {};
12+
13+
const actualEmptyMetadataFromEmptyResult = getMatchingQuestionsMetadata(
14+
{
15+
...singleMatchingQuestion,
16+
...{
17+
result: {},
18+
},
19+
},
20+
);
21+
22+
assert.deepEqual(actualEmptyMetadataFromEmptyResult, expectedEmptyMetadata);
23+
});
24+
25+
it('should return metadata from single matching question', () => {
26+
const actualSingleMatchingQuestionMetadata = getMatchingQuestionsMetadata(
27+
singleMatchingQuestion,
28+
);
29+
const expectedSingleMatchingQuestionMetadata = {
30+
'https://learninglocker&46;net/matching-response': [
31+
['ben', '3'],
32+
],
33+
};
34+
35+
assert.deepEqual(actualSingleMatchingQuestionMetadata, expectedSingleMatchingQuestionMetadata);
36+
});
37+
38+
it('should return metadata from multiple matching questions', () => {
39+
const actualMultipleMatchingQuestionsMetadata = getMatchingQuestionsMetadata(
40+
multipleMatchingQuestions,
41+
);
42+
const expectedMultipleMatchingQuestionsMetadata = {
43+
'https://learninglocker&46;net/matching-response': [
44+
['ben', '3'],
45+
['chris', '2'],
46+
['troy', '4'],
47+
['freddie', '1'],
48+
],
49+
};
50+
51+
assert
52+
.deepEqual(
53+
actualMultipleMatchingQuestionsMetadata,
54+
expectedMultipleMatchingQuestionsMetadata,
55+
);
56+
});
57+
});

src/apps/statements/tests/storingStatements/queriables/getMetadataFromStatement/getMetadataFromStatement.test.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { merge } from 'lodash';
33

44
import getMetadataFromStatement
55
from '../../../../service/storeStatements/queriables/getMetadataFromStatement';
6+
import { multipleMatchingQuestions } from './fixtures/matching-interaction.fixture';
67
import {
78
sequencingInteractionActivityStatement,
89
statementDefaults,
@@ -47,4 +48,18 @@ describe('Retrieve metadata from statement', () => {
4748

4849
assert.deepEqual(actualMetadata, expectedMetadata);
4950
});
51+
52+
it('should return matching questions metadata', () => {
53+
const actualMatchingQuestionsMetadata = getMetadataFromStatement(multipleMatchingQuestions);
54+
const expectedMatchingQuestionsMetadata = {
55+
'https://learninglocker&46;net/matching-response': [
56+
['ben', '3'],
57+
['chris', '2'],
58+
['troy', '4'],
59+
['freddie', '1'],
60+
],
61+
};
62+
63+
assert.deepEqual(actualMatchingQuestionsMetadata, expectedMatchingQuestionsMetadata);
64+
});
5065
});

yarn.lock

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,9 @@
3434
dependencies:
3535
"@babel/highlight" "^7.8.3"
3636

37-
"@babel/highlight@^7.8.3":
38-
version "7.8.3"
39-
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.8.3.tgz#28f173d04223eaaa59bc1d439a3836e6d1265797"
40-
integrity sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==
37+
"@babel/highlight@^7.8.0":
38+
version "7.8.0"
39+
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.8.0.tgz#4cc003dc10359919e2e3a1d9459150942913dd1a"
4140
dependencies:
4241
chalk "^2.0.0"
4342
esutils "^2.0.2"
@@ -3131,10 +3130,9 @@ [email protected]:
31313130
resolved "https://registry.yarnpkg.com/eyes/-/eyes-0.1.8.tgz#62cf120234c683785d902348a800ef3e0cc20bc0"
31323131
integrity sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=
31333132

3134-
fast-deep-equal@^3.1.1:
3135-
version "3.1.1"
3136-
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz#545145077c501491e33b15ec408c294376e94ae4"
3137-
integrity sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==
3133+
fast-deep-equal@^2.0.1:
3134+
version "2.0.1"
3135+
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49"
31383136

31393137
fast-glob@^3.0.3:
31403138
version "3.2.0"

0 commit comments

Comments
 (0)