@quesmed/types 2.6.209 → 2.6.211
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/cjs/models/Marksheet.d.ts +9 -1
- package/dist/cjs/models/Marksheet.js +7 -1
- package/dist/cjs/models/Question.d.ts +2 -2
- package/dist/cjs/resolvers/fragments/marksheet.js +4 -0
- package/dist/cjs/resolvers/fragments/record.d.ts +0 -1
- package/dist/cjs/resolvers/fragments/record.js +14 -19
- package/dist/cjs/resolvers/mutation/restricted/marksheet.d.ts +2 -0
- package/dist/cjs/resolvers/mutation/restricted/marksheet.js +17 -5
- package/dist/cjs/resolvers/mutation/restricted/mockTest.d.ts +3 -0
- package/dist/cjs/resolvers/query/admin/record.js +2 -2
- package/dist/cjs/resolvers/query/restricted/analytics.js +2 -0
- package/dist/cjs/resolvers/subscription/marksheet.d.ts +6 -4
- package/dist/cjs/resolvers/subscription/marksheet.js +2 -0
- package/dist/cjs/utils/evaluateMark.d.ts +14 -0
- package/dist/cjs/utils/evaluateMark.js +310 -0
- package/dist/cjs/utils/index.d.ts +1 -0
- package/dist/cjs/utils/index.js +1 -0
- package/dist/mjs/models/Marksheet.d.ts +9 -1
- package/dist/mjs/models/Marksheet.js +6 -0
- package/dist/mjs/models/Question.d.ts +2 -2
- package/dist/mjs/resolvers/fragments/marksheet.js +4 -0
- package/dist/mjs/resolvers/fragments/record.d.ts +0 -1
- package/dist/mjs/resolvers/fragments/record.js +13 -18
- package/dist/mjs/resolvers/mutation/restricted/marksheet.d.ts +2 -0
- package/dist/mjs/resolvers/mutation/restricted/marksheet.js +17 -5
- package/dist/mjs/resolvers/mutation/restricted/mockTest.d.ts +3 -0
- package/dist/mjs/resolvers/query/admin/record.js +2 -2
- package/dist/mjs/resolvers/query/restricted/analytics.js +2 -0
- package/dist/mjs/resolvers/subscription/marksheet.d.ts +6 -4
- package/dist/mjs/resolvers/subscription/marksheet.js +2 -0
- package/dist/mjs/utils/evaluateMark.d.ts +14 -0
- package/dist/mjs/utils/evaluateMark.js +306 -0
- package/dist/mjs/utils/index.d.ts +1 -0
- package/dist/mjs/utils/index.js +1 -0
- package/package.json +1 -1
|
@@ -76,6 +76,7 @@ export interface IMarksheet {
|
|
|
76
76
|
isTestMarksheet: boolean;
|
|
77
77
|
correct?: number;
|
|
78
78
|
incorrect?: number;
|
|
79
|
+
partial?: number;
|
|
79
80
|
totalQuestions?: number;
|
|
80
81
|
sessionId: string;
|
|
81
82
|
passingMark: number;
|
|
@@ -93,7 +94,12 @@ export interface IMarksheet {
|
|
|
93
94
|
builderConfig?: IBuildConfigData;
|
|
94
95
|
entitlementId: EProductType | EEntitlementType;
|
|
95
96
|
}
|
|
96
|
-
export type IMarksheetMarkJSONB = string | [string] | [IQuestionQAAnswer] | [string[], string[]] | [IPrescribeMark] | null;
|
|
97
|
+
export type IMarksheetMarkJSONB = string | [string] | string[] | [IQuestionQAAnswer] | [string[], string[]] | [IPrescribeMark] | [string, string, string] | [string, string] | [string, string][] | null;
|
|
98
|
+
export declare enum EMarkResult {
|
|
99
|
+
Incorrect = 0,
|
|
100
|
+
Correct = 1,
|
|
101
|
+
Partial = 2
|
|
102
|
+
}
|
|
97
103
|
export interface IMarksheetMark {
|
|
98
104
|
id: Id;
|
|
99
105
|
createdAt: number | Date;
|
|
@@ -110,6 +116,8 @@ export interface IMarksheetMark {
|
|
|
110
116
|
marksheet?: IMarksheet;
|
|
111
117
|
isAnswered: boolean;
|
|
112
118
|
striked: number[];
|
|
119
|
+
score: number;
|
|
120
|
+
result: EMarkResult;
|
|
113
121
|
}
|
|
114
122
|
export interface IPreBuildMarksheetRef {
|
|
115
123
|
createdAt: number | Date;
|
|
@@ -47,3 +47,9 @@ export var EMarksheetAction;
|
|
|
47
47
|
EMarksheetAction[EMarksheetAction["ANSWER_SELECTED"] = 15] = "ANSWER_SELECTED";
|
|
48
48
|
EMarksheetAction[EMarksheetAction["MARK_CHECK_UNCHECK"] = 16] = "MARK_CHECK_UNCHECK";
|
|
49
49
|
})(EMarksheetAction || (EMarksheetAction = {}));
|
|
50
|
+
export var EMarkResult;
|
|
51
|
+
(function (EMarkResult) {
|
|
52
|
+
EMarkResult[EMarkResult["Incorrect"] = 0] = "Incorrect";
|
|
53
|
+
EMarkResult[EMarkResult["Correct"] = 1] = "Correct";
|
|
54
|
+
EMarkResult[EMarkResult["Partial"] = 2] = "Partial";
|
|
55
|
+
})(EMarkResult || (EMarkResult = {}));
|
|
@@ -77,7 +77,7 @@ export interface IQuestionCommentLike {
|
|
|
77
77
|
comment: IQuestionComment;
|
|
78
78
|
likeTrueDislikeFalse: boolean;
|
|
79
79
|
}
|
|
80
|
-
export type IQuestionAnswer = string | [string] | [IQuestionQAAnswer] | [string[], string[]] |
|
|
80
|
+
export type IQuestionAnswer = string | [string] | [IQuestionQAAnswer] | [string[], string[]] | IPrescribeAnswer[] | [string, string][] | [string, string, string] | string[] | [string, string];
|
|
81
81
|
export type IQuestionAll = IQuestion | IQuestionSBA | IQuestionQA | IQuestionMultiQ | IQuestionPrescribe | IQuestionEMQ | IQuestionSelect3 | IQuestionRanking | IQuestionSjtTwoAnswer;
|
|
82
82
|
export interface IQuestion {
|
|
83
83
|
id: Id;
|
|
@@ -207,7 +207,7 @@ export interface IQuestionSjtTwoAnswer extends IQuestion {
|
|
|
207
207
|
sjtTwoAnswer: [string, string];
|
|
208
208
|
}
|
|
209
209
|
export interface IQuestionPrescribe extends IQuestion {
|
|
210
|
-
answer:
|
|
210
|
+
answer: IPrescribeAnswer[];
|
|
211
211
|
prescribeAnswer: IPrescribeAnswer[];
|
|
212
212
|
}
|
|
213
213
|
export type IPrescribeAnswerData = {
|
|
@@ -12,6 +12,8 @@ export const MARKSHEET_MARK_FIELDS = gql `
|
|
|
12
12
|
isAnswered
|
|
13
13
|
striked
|
|
14
14
|
mark
|
|
15
|
+
result
|
|
16
|
+
score
|
|
15
17
|
questionId
|
|
16
18
|
question {
|
|
17
19
|
...QuestionFields
|
|
@@ -141,5 +143,7 @@ export const NEW_MARK_FIELDS = gql `
|
|
|
141
143
|
questionChoiceId
|
|
142
144
|
mark
|
|
143
145
|
isAnswered
|
|
146
|
+
result
|
|
147
|
+
score
|
|
144
148
|
}
|
|
145
149
|
`;
|
|
@@ -3,7 +3,6 @@ export declare const JOB_REMARK_FRAGMENT: import("@apollo/client").DocumentNode;
|
|
|
3
3
|
export declare const JOB_ASSET_FRAGMENT: import("@apollo/client").DocumentNode;
|
|
4
4
|
export declare const JOB_RECORD_METRICS_SUMMARY_FRAGMENT: import("@apollo/client").DocumentNode;
|
|
5
5
|
export declare const JOB_RECORD_CHOICE_SUMMARY_FRAGMENT: import("@apollo/client").DocumentNode;
|
|
6
|
-
export declare const JOB_RECORD_STATISTICS_FRAGMENT: import("@apollo/client").DocumentNode;
|
|
7
6
|
export declare const JOB_RECORD_QUESTION_FRAGMENT: import("@apollo/client").DocumentNode;
|
|
8
7
|
export declare const JOB_RECORD_CHAPTER_FRAGMENT: import("@apollo/client").DocumentNode;
|
|
9
8
|
export declare const JOB_RECORD_STATION_FRAGMENT: import("@apollo/client").DocumentNode;
|
|
@@ -60,10 +60,6 @@ export const JOB_RECORD_METRICS_SUMMARY_FRAGMENT = gql `
|
|
|
60
60
|
correct
|
|
61
61
|
incorrect
|
|
62
62
|
percentage
|
|
63
|
-
commentCount
|
|
64
|
-
likes
|
|
65
|
-
dislikes
|
|
66
|
-
public
|
|
67
63
|
}
|
|
68
64
|
`;
|
|
69
65
|
export const JOB_RECORD_CHOICE_SUMMARY_FRAGMENT = gql `
|
|
@@ -75,18 +71,18 @@ export const JOB_RECORD_CHOICE_SUMMARY_FRAGMENT = gql `
|
|
|
75
71
|
questionId
|
|
76
72
|
}
|
|
77
73
|
`;
|
|
78
|
-
export const JOB_RECORD_STATISTICS_FRAGMENT = gql
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
`;
|
|
74
|
+
// export const JOB_RECORD_STATISTICS_FRAGMENT = gql`
|
|
75
|
+
// ${JOB_RECORD_METRICS_SUMMARY_FRAGMENT}
|
|
76
|
+
// ${JOB_RECORD_CHOICE_SUMMARY_FRAGMENT}
|
|
77
|
+
// fragment JobRecordStatistics on JobRecord {
|
|
78
|
+
// metricsSummary {
|
|
79
|
+
// ...JobRecordMetricsSummary
|
|
80
|
+
// }
|
|
81
|
+
// choiceSummary {
|
|
82
|
+
// ...JobRecordChoiceSummary
|
|
83
|
+
// }
|
|
84
|
+
// }
|
|
85
|
+
// `;
|
|
90
86
|
export const JOB_RECORD_QUESTION_FRAGMENT = gql `
|
|
91
87
|
fragment JobRecordQuestion on JobRecordQuestion {
|
|
92
88
|
question
|
|
@@ -167,7 +163,6 @@ export const JOB_RECORD_FRAGMENT = gql `
|
|
|
167
163
|
${JOB_RECORD_CHAPTER_FRAGMENT}
|
|
168
164
|
${JOB_RECORD_STATION_FRAGMENT}
|
|
169
165
|
${JOB_RECORD_MOCK_TEST_FRAGMENT}
|
|
170
|
-
${JOB_RECORD_STATISTICS_FRAGMENT}
|
|
171
166
|
${JOB_ASSET_FRAGMENT}
|
|
172
167
|
fragment JobRecord on JobRecord {
|
|
173
168
|
id
|
|
@@ -205,6 +200,6 @@ export const JOB_RECORD_FRAGMENT = gql `
|
|
|
205
200
|
updatedAt
|
|
206
201
|
publishedAt
|
|
207
202
|
...JobRecordStatus
|
|
208
|
-
...JobRecordStatistics
|
|
203
|
+
# ...JobRecordStatistics
|
|
209
204
|
}
|
|
210
205
|
`;
|
|
@@ -190,6 +190,7 @@ export declare const optimisticModifyMarksheetBuilderConfig: (marksheetId: numbe
|
|
|
190
190
|
isTestMarksheet: boolean;
|
|
191
191
|
correct?: number | undefined;
|
|
192
192
|
incorrect?: number | undefined;
|
|
193
|
+
partial?: number | undefined;
|
|
193
194
|
totalQuestions?: number | undefined;
|
|
194
195
|
sessionId: string;
|
|
195
196
|
passingMark: number;
|
|
@@ -283,6 +284,7 @@ export declare const optimisticEndMarksheet: (marksheet: IMarksheet) => {
|
|
|
283
284
|
isTestMarksheet: boolean;
|
|
284
285
|
correct?: number | undefined;
|
|
285
286
|
incorrect?: number | undefined;
|
|
287
|
+
partial?: number | undefined;
|
|
286
288
|
totalQuestions?: number | undefined;
|
|
287
289
|
sessionId: string;
|
|
288
290
|
passingMark: number;
|
|
@@ -67,6 +67,8 @@ export const SAVE_MARKSHEET = gql `
|
|
|
67
67
|
state
|
|
68
68
|
marks {
|
|
69
69
|
isAnswered
|
|
70
|
+
result
|
|
71
|
+
score
|
|
70
72
|
id
|
|
71
73
|
marksheetId
|
|
72
74
|
questionChoiceId
|
|
@@ -89,17 +91,21 @@ export const updateMarksheets = (cache, result, options) => {
|
|
|
89
91
|
try {
|
|
90
92
|
const { input } = variables;
|
|
91
93
|
for (let i = 0; i < input.length; i++) {
|
|
92
|
-
const
|
|
94
|
+
const inputData = input[i];
|
|
95
|
+
const savedMarks = saveMarksheets.find((m) => m.id === inputData.marksheetId)?.marks;
|
|
96
|
+
const savedData = savedMarks?.find((m) => m.id === inputData.markId);
|
|
93
97
|
cache.writeFragment({
|
|
94
98
|
id: cache.identify({
|
|
95
|
-
id:
|
|
99
|
+
id: inputData.markId,
|
|
96
100
|
__typename: 'MarksheetMark',
|
|
97
101
|
}),
|
|
98
102
|
data: {
|
|
99
|
-
timeTaken:
|
|
100
|
-
mark:
|
|
101
|
-
questionChoiceId:
|
|
103
|
+
timeTaken: savedData?.timeTaken || 0,
|
|
104
|
+
mark: savedData?.mark,
|
|
105
|
+
questionChoiceId: savedData?.questionChoiceId,
|
|
102
106
|
isAnswered: true,
|
|
107
|
+
result: savedData?.result,
|
|
108
|
+
score: savedData?.score,
|
|
103
109
|
},
|
|
104
110
|
fragment: NEW_MARK_FIELDS,
|
|
105
111
|
});
|
|
@@ -119,6 +125,8 @@ export const optimisticSaveMarksheets = (marksheet, marksheetInput, questionInde
|
|
|
119
125
|
questionChoiceId: choiceId ?? null,
|
|
120
126
|
isAnswered: true,
|
|
121
127
|
mark: mark || null,
|
|
128
|
+
result: 0,
|
|
129
|
+
score: 0,
|
|
122
130
|
};
|
|
123
131
|
const updatedMarks = [
|
|
124
132
|
...marks.slice(0, questionIndex),
|
|
@@ -335,6 +343,8 @@ export const MODIFY_MARKSHEET_MARK = gql `
|
|
|
335
343
|
questionChoiceId
|
|
336
344
|
timeTaken
|
|
337
345
|
mark
|
|
346
|
+
result
|
|
347
|
+
score
|
|
338
348
|
isAnswered
|
|
339
349
|
striked
|
|
340
350
|
}
|
|
@@ -441,6 +451,8 @@ export const TOGGLE_STRIKE_OPTIONS = gql `
|
|
|
441
451
|
index
|
|
442
452
|
isAnswered
|
|
443
453
|
mark
|
|
454
|
+
result
|
|
455
|
+
score
|
|
444
456
|
marksheetId
|
|
445
457
|
question {
|
|
446
458
|
id
|
|
@@ -29,6 +29,8 @@ export declare const optimisticToggleFlaggedQuestion: (mark: IMarksheetMark, fla
|
|
|
29
29
|
marksheet?: IMarksheet | undefined;
|
|
30
30
|
isAnswered: boolean;
|
|
31
31
|
striked: number[];
|
|
32
|
+
score: number;
|
|
33
|
+
result: import("../../../models").EMarkResult;
|
|
32
34
|
};
|
|
33
35
|
};
|
|
34
36
|
};
|
|
@@ -64,6 +66,7 @@ export declare const optimisticEndMockTest: (marksheet: IMarksheet) => {
|
|
|
64
66
|
isTestMarksheet: boolean;
|
|
65
67
|
correct?: number | undefined;
|
|
66
68
|
incorrect?: number | undefined;
|
|
69
|
+
partial?: number | undefined;
|
|
67
70
|
totalQuestions?: number | undefined;
|
|
68
71
|
sessionId: string;
|
|
69
72
|
passingMark: number;
|
|
@@ -2,9 +2,9 @@ import { gql } from '@apollo/client';
|
|
|
2
2
|
import { JOB_RECORD_FRAGMENT } from '../../fragments';
|
|
3
3
|
export const GET_JOB_RECORDS = gql `
|
|
4
4
|
${JOB_RECORD_FRAGMENT}
|
|
5
|
-
query GetJobRecords($jobId: ID
|
|
5
|
+
query GetJobRecords($jobId: ID!) {
|
|
6
6
|
admin {
|
|
7
|
-
getJobRecords(jobId: $jobId
|
|
7
|
+
getJobRecords(jobId: $jobId) {
|
|
8
8
|
...JobRecord
|
|
9
9
|
}
|
|
10
10
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EMarksheetAction, EMarksheetState, Id,
|
|
1
|
+
import { EMarksheetAction, EMarksheetState, Id, IMarksheetMark, IUser } from '../../models';
|
|
2
2
|
import { IBuildConfigData, IPreBuildMarksheet } from '../mutation/restricted';
|
|
3
3
|
import { RootData } from '../types';
|
|
4
4
|
export interface IMarksheetGroupMember {
|
|
@@ -58,12 +58,14 @@ export interface IMarksheetMarkData {
|
|
|
58
58
|
newMarkId?: Id;
|
|
59
59
|
markIndex?: number;
|
|
60
60
|
questionChoiceId?: Id;
|
|
61
|
-
mark?:
|
|
61
|
+
mark?: IMarksheetMark['mark'];
|
|
62
62
|
isAnswered?: boolean;
|
|
63
|
-
|
|
63
|
+
score?: IMarksheetMark['score'];
|
|
64
|
+
result?: IMarksheetMark['result'];
|
|
65
|
+
timeTaken?: IMarksheetMark['timeTaken'];
|
|
64
66
|
updatedAt?: Date;
|
|
65
67
|
user: IUser;
|
|
66
|
-
striked?:
|
|
68
|
+
striked?: IMarksheetMark['striked'];
|
|
67
69
|
}
|
|
68
70
|
export type IOnMarksheetMarkChangeData = RootData<IMarksheetMarkData, 'onMarksheetMarkChange'>;
|
|
69
71
|
export declare const ON_MARKSHEET_MARK_CHANGE_KEY = "ON_MARKSHEET_CHANGE_KEY";
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { EMarkResult, EPsaSectionType, EQuestionType, IMarksheetMarkJSONB, IQuestionAnswer } from '../models';
|
|
2
|
+
export interface IEvaluateMarkData {
|
|
3
|
+
score: number;
|
|
4
|
+
result: EMarkResult;
|
|
5
|
+
}
|
|
6
|
+
export declare function evaluateMark({ mark, answer, questionTypeId, psaSectionId, choices, }: {
|
|
7
|
+
mark: IMarksheetMarkJSONB;
|
|
8
|
+
answer: IQuestionAnswer;
|
|
9
|
+
questionTypeId: EQuestionType;
|
|
10
|
+
psaSectionId: EPsaSectionType | null;
|
|
11
|
+
choices?: Array<{
|
|
12
|
+
label: string;
|
|
13
|
+
}>;
|
|
14
|
+
}): IEvaluateMarkData;
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
import { EMarkResult, EQuestionType, } from '../models';
|
|
2
|
+
import { compareObjects } from './object';
|
|
3
|
+
function isPrescribeAnswer(data) {
|
|
4
|
+
return Object(data).hasOwnProperty('dose');
|
|
5
|
+
}
|
|
6
|
+
function mapPrescribeMarkToAnswer(obj) {
|
|
7
|
+
if (isPrescribeAnswer(obj)) {
|
|
8
|
+
return {
|
|
9
|
+
drugId: obj.drug.value,
|
|
10
|
+
doseId: obj.dose.value,
|
|
11
|
+
durationId: obj.duration.value,
|
|
12
|
+
frequencyId: obj.frequency.value,
|
|
13
|
+
routeId: obj.route.value,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
return {
|
|
17
|
+
drugId: obj.drugId,
|
|
18
|
+
doseId: obj.doseId,
|
|
19
|
+
durationId: obj.durationId,
|
|
20
|
+
frequencyId: obj.frequencyId,
|
|
21
|
+
routeId: obj.routeId,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function createHashMap(arr) {
|
|
25
|
+
const map = new Map();
|
|
26
|
+
for (const innerArr of arr) {
|
|
27
|
+
const sortedInnerArr = innerArr.slice().sort();
|
|
28
|
+
const key = sortedInnerArr.join('|');
|
|
29
|
+
map.set(key, (map.get(key) || 0) + 1);
|
|
30
|
+
}
|
|
31
|
+
return map;
|
|
32
|
+
}
|
|
33
|
+
function deepParse(data) {
|
|
34
|
+
let parsed = data;
|
|
35
|
+
while (typeof parsed === 'string') {
|
|
36
|
+
try {
|
|
37
|
+
parsed = JSON.parse(parsed);
|
|
38
|
+
}
|
|
39
|
+
catch (e) {
|
|
40
|
+
break;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return parsed;
|
|
44
|
+
}
|
|
45
|
+
export function evaluateMark({ mark, answer, questionTypeId, psaSectionId, choices, }) {
|
|
46
|
+
const data = {
|
|
47
|
+
score: 0,
|
|
48
|
+
result: EMarkResult.Incorrect,
|
|
49
|
+
};
|
|
50
|
+
if (!mark || !answer) {
|
|
51
|
+
return data;
|
|
52
|
+
}
|
|
53
|
+
try {
|
|
54
|
+
const flatAnswer = answer[0];
|
|
55
|
+
const jsonAnswer = deepParse(mark);
|
|
56
|
+
const flatAttempt = jsonAnswer[0];
|
|
57
|
+
switch (questionTypeId) {
|
|
58
|
+
case EQuestionType.SINGLE_BEST_ANSWER:
|
|
59
|
+
case EQuestionType.SBA_WITH_MULTIPLE_CHOICES:
|
|
60
|
+
case EQuestionType.VERBAL_VERACITY:
|
|
61
|
+
case EQuestionType.VERBAL_READING_COMPREHENSION:
|
|
62
|
+
case EQuestionType.DECISION_MAKING_SBA:
|
|
63
|
+
case EQuestionType.QUANTITATIVE_REASONING_SBA: {
|
|
64
|
+
if (flatAnswer === flatAttempt) {
|
|
65
|
+
data.score = psaSectionId ? 2 : 1;
|
|
66
|
+
data.result = EMarkResult.Correct;
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
data.score = 0;
|
|
70
|
+
data.result = EMarkResult.Incorrect;
|
|
71
|
+
}
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
case EQuestionType.QUESTION_ANSWER: {
|
|
75
|
+
const normalizedAnswer = flatAnswer.dose
|
|
76
|
+
.toLowerCase()
|
|
77
|
+
.replace(/\s/g, '');
|
|
78
|
+
const normalizedAttempt = flatAttempt
|
|
79
|
+
? flatAttempt.toLowerCase().replace(/\s/g, '')
|
|
80
|
+
: '';
|
|
81
|
+
if (normalizedAnswer === normalizedAttempt) {
|
|
82
|
+
// for psa section, we give 2 marks for correct answer
|
|
83
|
+
data.score = psaSectionId ? 2 : 1;
|
|
84
|
+
data.result = EMarkResult.Correct;
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
data.score = 0;
|
|
88
|
+
data.result = EMarkResult.Incorrect;
|
|
89
|
+
}
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
case EQuestionType.MULTIPLE_ANSWERS: {
|
|
93
|
+
const [answerA, answerB] = answer.map((x) => x.sort());
|
|
94
|
+
let [attemptA, attemptB] = [[], []];
|
|
95
|
+
if (Array.isArray(jsonAnswer) &&
|
|
96
|
+
jsonAnswer.length === 2 &&
|
|
97
|
+
Array.isArray(jsonAnswer[0]) &&
|
|
98
|
+
Array.isArray(jsonAnswer[1])) {
|
|
99
|
+
[attemptA, attemptB] = jsonAnswer.map((x) => x.sort());
|
|
100
|
+
}
|
|
101
|
+
const isAMatch = answerA.length === attemptA.length &&
|
|
102
|
+
attemptA.every((x, i) => x === answerA[i]);
|
|
103
|
+
const isBMatch = answerB.length === attemptB.length &&
|
|
104
|
+
attemptB.every((x, i) => x === answerB[i]);
|
|
105
|
+
if (isAMatch && isBMatch) {
|
|
106
|
+
data.score = 4;
|
|
107
|
+
data.result = EMarkResult.Correct;
|
|
108
|
+
}
|
|
109
|
+
else if (isAMatch || isBMatch) {
|
|
110
|
+
data.score = 2;
|
|
111
|
+
data.result = EMarkResult.Partial;
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
data.score = 0;
|
|
115
|
+
data.result = EMarkResult.Incorrect;
|
|
116
|
+
}
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
case EQuestionType.DECISION_MAKING_YES_NO: {
|
|
120
|
+
const [answerA, answerB] = answer.map((x) => [...x].sort());
|
|
121
|
+
let [attemptA, attemptB] = [[], []];
|
|
122
|
+
if (Array.isArray(jsonAnswer) &&
|
|
123
|
+
jsonAnswer.length === 2 &&
|
|
124
|
+
Array.isArray(jsonAnswer[0]) &&
|
|
125
|
+
Array.isArray(jsonAnswer[1])) {
|
|
126
|
+
[attemptA, attemptB] = jsonAnswer.map((x) => [...x].sort());
|
|
127
|
+
}
|
|
128
|
+
// Count correct matches
|
|
129
|
+
let correctCount = 0;
|
|
130
|
+
// Count matches in A
|
|
131
|
+
correctCount += attemptA.filter((x) => answerA.includes(x)).length;
|
|
132
|
+
// Count matches in B
|
|
133
|
+
correctCount += attemptB.filter((x) => answerB.includes(x)).length;
|
|
134
|
+
const totalStatements = answerA.length + answerB.length;
|
|
135
|
+
if (correctCount === totalStatements) {
|
|
136
|
+
// 5 / 5
|
|
137
|
+
data.score = 2;
|
|
138
|
+
data.result = EMarkResult.Correct;
|
|
139
|
+
}
|
|
140
|
+
else if (correctCount === totalStatements - 1) {
|
|
141
|
+
// 4 / 5
|
|
142
|
+
data.score = 1;
|
|
143
|
+
data.result = EMarkResult.Partial;
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
// 3 or fewer
|
|
147
|
+
data.score = 0;
|
|
148
|
+
data.result = EMarkResult.Incorrect;
|
|
149
|
+
}
|
|
150
|
+
break;
|
|
151
|
+
}
|
|
152
|
+
case EQuestionType.PRESCRIPTION_ANSWER: {
|
|
153
|
+
let foundCorrect = false;
|
|
154
|
+
if (typeof flatAttempt === 'object' &&
|
|
155
|
+
Object.keys(flatAttempt).length > 0) {
|
|
156
|
+
const answers = answer.map(mapPrescribeMarkToAnswer);
|
|
157
|
+
const attempt = mapPrescribeMarkToAnswer(flatAttempt);
|
|
158
|
+
foundCorrect = answers.some((ans) => compareObjects(ans, attempt));
|
|
159
|
+
}
|
|
160
|
+
if (foundCorrect) {
|
|
161
|
+
data.score = 1;
|
|
162
|
+
data.result = EMarkResult.Correct;
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
data.score = 0;
|
|
166
|
+
data.result = EMarkResult.Incorrect;
|
|
167
|
+
}
|
|
168
|
+
break;
|
|
169
|
+
}
|
|
170
|
+
case EQuestionType.EXTENDED_MATCHING_ANSWER: {
|
|
171
|
+
const extendedAnswer = answer;
|
|
172
|
+
const attempt = jsonAnswer;
|
|
173
|
+
if (extendedAnswer.length !== attempt.length) {
|
|
174
|
+
data.score = 0;
|
|
175
|
+
data.result = EMarkResult.Incorrect;
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
const map1 = createHashMap(extendedAnswer);
|
|
179
|
+
const map2 = createHashMap(attempt);
|
|
180
|
+
let isCorrect = true;
|
|
181
|
+
for (const [key, value] of map1) {
|
|
182
|
+
if (map2.get(key) !== value) {
|
|
183
|
+
isCorrect = false;
|
|
184
|
+
break;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
if (isCorrect) {
|
|
188
|
+
data.score = 1;
|
|
189
|
+
data.result = EMarkResult.Correct;
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
data.score = 0;
|
|
193
|
+
data.result = EMarkResult.Incorrect;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
break;
|
|
197
|
+
}
|
|
198
|
+
case EQuestionType.SELECT_THREE_ANSWER: {
|
|
199
|
+
const threeAnswer = answer;
|
|
200
|
+
const attempt = jsonAnswer;
|
|
201
|
+
if (threeAnswer.length !== 3) {
|
|
202
|
+
data.score = 0;
|
|
203
|
+
data.result = EMarkResult.Incorrect;
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
const answerSet = new Set(threeAnswer);
|
|
207
|
+
let isCorrect = true;
|
|
208
|
+
for (const attemptLabel of attempt) {
|
|
209
|
+
if (!answerSet.has(attemptLabel)) {
|
|
210
|
+
isCorrect = false;
|
|
211
|
+
break;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
if (isCorrect) {
|
|
215
|
+
data.score = 1;
|
|
216
|
+
data.result = EMarkResult.Correct;
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
data.score = 0;
|
|
220
|
+
data.result = EMarkResult.Incorrect;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
break;
|
|
224
|
+
}
|
|
225
|
+
case EQuestionType.RANKING_ANSWER: {
|
|
226
|
+
// Duplicate logic to Extended Matching, but they have different scoring systems
|
|
227
|
+
// which we may add at a later point
|
|
228
|
+
const rankAnswer = answer;
|
|
229
|
+
const attempt = jsonAnswer;
|
|
230
|
+
if (rankAnswer.length !== attempt.length) {
|
|
231
|
+
data.score = 0;
|
|
232
|
+
data.result = EMarkResult.Incorrect;
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
let isCorrect = true;
|
|
236
|
+
for (let i = 0; i < rankAnswer.length; i++) {
|
|
237
|
+
if (rankAnswer[i] !== attempt[i]) {
|
|
238
|
+
isCorrect = false;
|
|
239
|
+
break;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
if (isCorrect) {
|
|
243
|
+
data.score = 1;
|
|
244
|
+
data.result = EMarkResult.Correct;
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
data.score = 0;
|
|
248
|
+
data.result = EMarkResult.Incorrect;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
break;
|
|
252
|
+
}
|
|
253
|
+
case EQuestionType.SJT_TWO_ANSWERS: {
|
|
254
|
+
const twoAnswer = answer;
|
|
255
|
+
const attempt = jsonAnswer;
|
|
256
|
+
if (twoAnswer.length === 2 &&
|
|
257
|
+
attempt.length === 2 &&
|
|
258
|
+
twoAnswer.join(',') === attempt.join(',')) {
|
|
259
|
+
data.score = 1;
|
|
260
|
+
data.result = EMarkResult.Correct;
|
|
261
|
+
}
|
|
262
|
+
else {
|
|
263
|
+
data.score = 0;
|
|
264
|
+
data.result = EMarkResult.Incorrect;
|
|
265
|
+
}
|
|
266
|
+
break;
|
|
267
|
+
}
|
|
268
|
+
case EQuestionType.SJT_SINGLE_CHOICE: {
|
|
269
|
+
const answer = flatAnswer;
|
|
270
|
+
const attempt = flatAttempt;
|
|
271
|
+
if (!choices) {
|
|
272
|
+
data.score = 0;
|
|
273
|
+
data.result = EMarkResult.Incorrect;
|
|
274
|
+
break;
|
|
275
|
+
}
|
|
276
|
+
const options = choices.map((o) => o.label);
|
|
277
|
+
const answerIndex = options.indexOf(answer);
|
|
278
|
+
const attemptIndex = options.indexOf(attempt);
|
|
279
|
+
if (answerIndex === -1 || attemptIndex === -1) {
|
|
280
|
+
data.score = 0;
|
|
281
|
+
data.result = EMarkResult.Incorrect;
|
|
282
|
+
}
|
|
283
|
+
else {
|
|
284
|
+
const distance = Math.abs(answerIndex - attemptIndex);
|
|
285
|
+
if (distance === 0) {
|
|
286
|
+
data.score = 1;
|
|
287
|
+
data.result = EMarkResult.Correct;
|
|
288
|
+
}
|
|
289
|
+
else if (distance === 1) {
|
|
290
|
+
data.score = 0.5;
|
|
291
|
+
data.result = EMarkResult.Partial;
|
|
292
|
+
}
|
|
293
|
+
else {
|
|
294
|
+
data.score = 0;
|
|
295
|
+
data.result = EMarkResult.Incorrect;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
break;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
catch (e) {
|
|
303
|
+
console.error(e);
|
|
304
|
+
}
|
|
305
|
+
return data;
|
|
306
|
+
}
|
package/dist/mjs/utils/index.js
CHANGED