@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.
Files changed (35) hide show
  1. package/dist/cjs/models/Marksheet.d.ts +9 -1
  2. package/dist/cjs/models/Marksheet.js +7 -1
  3. package/dist/cjs/models/Question.d.ts +2 -2
  4. package/dist/cjs/resolvers/fragments/marksheet.js +4 -0
  5. package/dist/cjs/resolvers/fragments/record.d.ts +0 -1
  6. package/dist/cjs/resolvers/fragments/record.js +14 -19
  7. package/dist/cjs/resolvers/mutation/restricted/marksheet.d.ts +2 -0
  8. package/dist/cjs/resolvers/mutation/restricted/marksheet.js +17 -5
  9. package/dist/cjs/resolvers/mutation/restricted/mockTest.d.ts +3 -0
  10. package/dist/cjs/resolvers/query/admin/record.js +2 -2
  11. package/dist/cjs/resolvers/query/restricted/analytics.js +2 -0
  12. package/dist/cjs/resolvers/subscription/marksheet.d.ts +6 -4
  13. package/dist/cjs/resolvers/subscription/marksheet.js +2 -0
  14. package/dist/cjs/utils/evaluateMark.d.ts +14 -0
  15. package/dist/cjs/utils/evaluateMark.js +310 -0
  16. package/dist/cjs/utils/index.d.ts +1 -0
  17. package/dist/cjs/utils/index.js +1 -0
  18. package/dist/mjs/models/Marksheet.d.ts +9 -1
  19. package/dist/mjs/models/Marksheet.js +6 -0
  20. package/dist/mjs/models/Question.d.ts +2 -2
  21. package/dist/mjs/resolvers/fragments/marksheet.js +4 -0
  22. package/dist/mjs/resolvers/fragments/record.d.ts +0 -1
  23. package/dist/mjs/resolvers/fragments/record.js +13 -18
  24. package/dist/mjs/resolvers/mutation/restricted/marksheet.d.ts +2 -0
  25. package/dist/mjs/resolvers/mutation/restricted/marksheet.js +17 -5
  26. package/dist/mjs/resolvers/mutation/restricted/mockTest.d.ts +3 -0
  27. package/dist/mjs/resolvers/query/admin/record.js +2 -2
  28. package/dist/mjs/resolvers/query/restricted/analytics.js +2 -0
  29. package/dist/mjs/resolvers/subscription/marksheet.d.ts +6 -4
  30. package/dist/mjs/resolvers/subscription/marksheet.js +2 -0
  31. package/dist/mjs/utils/evaluateMark.d.ts +14 -0
  32. package/dist/mjs/utils/evaluateMark.js +306 -0
  33. package/dist/mjs/utils/index.d.ts +1 -0
  34. package/dist/mjs/utils/index.js +1 -0
  35. 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[]] | IPrescribeMark[] | [string, string][] | [string, string, string] | string[] | [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: IPrescribeMark[];
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
- ${JOB_RECORD_METRICS_SUMMARY_FRAGMENT}
80
- ${JOB_RECORD_CHOICE_SUMMARY_FRAGMENT}
81
- fragment JobRecordStatistics on JobRecord {
82
- metricsSummary {
83
- ...JobRecordMetricsSummary
84
- }
85
- choiceSummary {
86
- ...JobRecordChoiceSummary
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 marksheet = input[i];
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: marksheet.markId,
99
+ id: inputData.markId,
96
100
  __typename: 'MarksheetMark',
97
101
  }),
98
102
  data: {
99
- timeTaken: marksheet.timeTaken || 0,
100
- mark: marksheet.mark,
101
- questionChoiceId: marksheet.choiceId,
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!, $filter: JobRecordsFilterInput!) {
5
+ query GetJobRecords($jobId: ID!) {
6
6
  admin {
7
- getJobRecords(jobId: $jobId, filter: $filter) {
7
+ getJobRecords(jobId: $jobId) {
8
8
  ...JobRecord
9
9
  }
10
10
  }
@@ -76,6 +76,8 @@ export const UCAT_THEME_ANALYTICS = gql `
76
76
  correct
77
77
  incorrect
78
78
  marks {
79
+ id
80
+ index
79
81
  questionId
80
82
  updatedAt
81
83
  mark
@@ -1,4 +1,4 @@
1
- import { EMarksheetAction, EMarksheetState, Id, IMarksheetMarkJSONB, IUser } from '../../models';
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?: IMarksheetMarkJSONB;
61
+ mark?: IMarksheetMark['mark'];
62
62
  isAnswered?: boolean;
63
- timeTaken?: number;
63
+ score?: IMarksheetMark['score'];
64
+ result?: IMarksheetMark['result'];
65
+ timeTaken?: IMarksheetMark['timeTaken'];
64
66
  updatedAt?: Date;
65
67
  user: IUser;
66
- striked?: number[];
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";
@@ -76,6 +76,8 @@ export const ON_MARKSHEET_MARK_CHANGE = gql `
76
76
  displayName
77
77
  }
78
78
  striked
79
+ score
80
+ result
79
81
  }
80
82
  }
81
83
  `;
@@ -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
+ }
@@ -1,4 +1,5 @@
1
1
  export * from './commonFunctions';
2
+ export * from './evaluateMark';
2
3
  export * from './lightgallery';
3
4
  export * from './object';
4
5
  export * from './offlineLink';
@@ -1,4 +1,5 @@
1
1
  export * from './commonFunctions';
2
+ export * from './evaluateMark';
2
3
  export * from './lightgallery';
3
4
  export * from './object';
4
5
  export * from './offlineLink';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quesmed/types",
3
- "version": "2.6.209",
3
+ "version": "2.6.211",
4
4
  "description": "Typescript types for Quesmed",
5
5
  "keywords": [
6
6
  "quesmed",