@openstax/ts-utils 1.38.0-beta → 1.38.1

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.
@@ -3,5 +3,5 @@ import type { JWK } from 'node-jose';
3
3
  export type JwksFetcher = (uri: string) => Promise<{
4
4
  keys: JWK.RawKey[];
5
5
  }>;
6
- export declare const getJwksClient: (iss: string, fetcher?: JwksFetcher) => JwksClient;
6
+ export declare const getJwksClient: (jwksUri: string, fetcher?: JwksFetcher) => JwksClient;
7
7
  export declare const getJwksKey: (iss: string, kid?: string, fetcher?: JwksFetcher) => Promise<import("jwks-rsa").SigningKey>;
@@ -3,11 +3,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getJwksKey = exports.getJwksClient = void 0;
4
4
  const jwks_rsa_1 = require("jwks-rsa");
5
5
  const helpers_1 = require("./helpers");
6
- exports.getJwksClient = (0, helpers_1.memoize)((iss, fetcher) => {
7
- const jwksUri = new URL('/.well-known/jwks.json', iss).toString();
6
+ exports.getJwksClient = (0, helpers_1.memoize)((jwksUri, fetcher) => {
8
7
  return new jwks_rsa_1.JwksClient({ jwksUri, fetcher });
9
8
  });
10
9
  exports.getJwksKey = (0, helpers_1.memoize)(async (iss, kid, fetcher) => {
11
- const client = (0, exports.getJwksClient)(iss, fetcher);
10
+ const jwksUri = new URL('/.well-known/jwks.json', iss).toString();
11
+ const client = (0, exports.getJwksClient)(jwksUri, fetcher);
12
12
  return client.getSigningKey(kid);
13
13
  });
@@ -14,16 +14,21 @@ export type ActivityState = {
14
14
  mostRecentWithCompleted?: AttemptEntry;
15
15
  };
16
16
  export declare const matchAttempt: (statement: UXapiStatement) => boolean;
17
- export declare const matchAttemptCompleted: (attempt: UXapiStatement) => (statement: UXapiStatement) => boolean;
18
- export declare const matchAttemptScored: (attempt: UXapiStatement) => (statement: UXapiStatement) => boolean;
17
+ export declare const matchAttemptCompleted: (attempt: UXapiStatement) => (statement: UXapiStatement) => boolean | "";
18
+ export declare const matchAttemptScored: (attempt: UXapiStatement) => (statement: UXapiStatement) => boolean | "";
19
19
  export declare const resolveAttempts: (statements: UXapiStatement[], options?: {
20
20
  activityIRI?: string;
21
21
  parentActivityAttempt?: string;
22
22
  }) => UXapiStatement[];
23
23
  export declare const resolveCompletedForAttempt: (statements: UXapiStatement[], attempt: UXapiStatement, activityIRI?: string) => UXapiStatement | undefined;
24
24
  export declare const resolveScoredForAttempt: (statements: UXapiStatement[], attempt: UXapiStatement, activityIRI?: string) => UXapiStatement | undefined;
25
- export declare const oldestStatement: (statements: UXapiStatement[]) => UXapiStatement | undefined;
26
- export declare const mostRecentStatement: (statements: UXapiStatement[]) => UXapiStatement | undefined;
25
+ export declare const getStatementTimeString: (statement: UXapiStatement) => string;
26
+ export declare const getStatementTime: (statement: UXapiStatement) => Date;
27
+ export declare const oldestStatement: (items: UXapiStatement[]) => UXapiStatement | undefined;
28
+ export declare const mostRecentStatement: (items: UXapiStatement[]) => UXapiStatement | undefined;
29
+ export declare const oldestEntry: (items: AttemptEntry[]) => AttemptEntry | undefined;
30
+ export declare const mostRecentEntry: (items: AttemptEntry[]) => AttemptEntry | undefined;
31
+ export declare const bestEntry: (items: AttemptEntry[]) => AttemptEntry | undefined;
27
32
  export declare const resolveAttemptInfo: (statements: UXapiStatement[], options?: {
28
33
  activityIRI?: string;
29
34
  currentAttempt?: string;
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.putScoredStatement = exports.createScoredStatement = exports.putCompletedPendingScoringStatement = exports.createCompletedPendingScoringStatement = exports.putCompletedStatement = exports.createCompletedStatement = exports.putAttemptActivityStatement = exports.createAttemptActivityStatement = exports.putAttemptStatement = exports.createAttemptStatement = exports.createStatement = exports.loadActivityAttemptInfo = exports.loadStatementsForActivityAndFirstChildren = exports.resolveAttemptInfo = exports.mostRecentStatement = exports.oldestStatement = exports.resolveScoredForAttempt = exports.resolveCompletedForAttempt = exports.resolveAttempts = exports.matchAttemptScored = exports.matchAttemptCompleted = exports.matchAttempt = exports.EXT_PENDING_SCORING = void 0;
6
+ exports.putScoredStatement = exports.createScoredStatement = exports.putCompletedPendingScoringStatement = exports.createCompletedPendingScoringStatement = exports.putCompletedStatement = exports.createCompletedStatement = exports.putAttemptActivityStatement = exports.createAttemptActivityStatement = exports.putAttemptStatement = exports.createAttemptStatement = exports.createStatement = exports.loadActivityAttemptInfo = exports.loadStatementsForActivityAndFirstChildren = exports.resolveAttemptInfo = exports.bestEntry = exports.mostRecentEntry = exports.oldestEntry = exports.mostRecentStatement = exports.oldestStatement = exports.getStatementTime = exports.getStatementTimeString = exports.resolveScoredForAttempt = exports.resolveCompletedForAttempt = exports.resolveAttempts = exports.matchAttemptScored = exports.matchAttemptCompleted = exports.matchAttempt = exports.EXT_PENDING_SCORING = void 0;
7
7
  /*
8
8
  * the structure of xapi statements for handling multiple attempts of an activity
9
9
  * including the option of a parent activity/attempt such that a new attempt
@@ -28,7 +28,7 @@ const matchAttempt = (statement) => statement.verb.id === Verb.Attempted;
28
28
  exports.matchAttempt = matchAttempt;
29
29
  const matchAttemptCompleted = (attempt) => (statement) => {
30
30
  var _a, _b;
31
- return statement.verb.id === Verb.Completed
31
+ return statement.verb.id === Verb.Completed && attempt.id
32
32
  && statement.context !== undefined
33
33
  && ((_a = statement.context.statement) === null || _a === void 0 ? void 0 : _a.id) === attempt.id
34
34
  && statement.context.registration === ((_b = attempt.context) === null || _b === void 0 ? void 0 : _b.registration);
@@ -36,7 +36,7 @@ const matchAttemptCompleted = (attempt) => (statement) => {
36
36
  exports.matchAttemptCompleted = matchAttemptCompleted;
37
37
  const matchAttemptScored = (attempt) => (statement) => {
38
38
  var _a, _b;
39
- return statement.verb.id === Verb.Scored
39
+ return statement.verb.id === Verb.Scored && attempt.id
40
40
  && statement.context !== undefined
41
41
  && ((_a = statement.context.statement) === null || _a === void 0 ? void 0 : _a.id) === attempt.id
42
42
  && statement.context.registration === ((_b = attempt.context) === null || _b === void 0 ? void 0 : _b.registration);
@@ -53,104 +53,89 @@ const resolveCompletedForAttempt = (statements, attempt, activityIRI) => stateme
53
53
  && (!activityIRI || statement.object.id === activityIRI));
54
54
  exports.resolveCompletedForAttempt = resolveCompletedForAttempt;
55
55
  const resolveScoredForAttempt = (statements, attempt, activityIRI) => {
56
- // Prefer the most recent Scored
57
- const scored = (0, exports.mostRecentStatement)(statements.filter(s => (0, exports.matchAttemptScored)(attempt)(s) && (!activityIRI || s.object.id === activityIRI)));
58
- if (scored)
59
- return scored;
60
- // if no scored found, return most recent Completed with a score for the attempt.
61
- const completedWithScore = (0, exports.mostRecentStatement)(statements.filter(s => (0, exports.matchAttemptCompleted)(attempt)(s) &&
62
- (!activityIRI || s.object.id === activityIRI) && s.result &&
63
- s.result.score &&
64
- (s.result.score.scaled !== undefined)));
65
- return completedWithScore;
56
+ // scored or completed statements that contain a score in their
57
+ // result are 'scoring statements' for our purposes.
58
+ const scoringStatements = statements.filter(s => {
59
+ var _a;
60
+ return ((0, exports.matchAttemptScored)(attempt)(s) || (0, exports.matchAttemptCompleted)(attempt)(s))
61
+ && ((_a = s.result) === null || _a === void 0 ? void 0 : _a.score)
62
+ && (!activityIRI || s.object.id === activityIRI);
63
+ });
64
+ return (0, exports.mostRecentStatement)(scoringStatements);
66
65
  };
67
66
  exports.resolveScoredForAttempt = resolveScoredForAttempt;
68
- const oldestStatement = (statements) => statements.reduce((result, statement) => result && (0, isBefore_1.default)((0, parseISO_1.default)('stored' in result && result.stored ? result.stored : result.timestamp), (0, parseISO_1.default)(statement.timestamp)) ? result : statement, statements[0]);
69
- exports.oldestStatement = oldestStatement;
70
- const mostRecentStatement = (statements) => statements.reduce((result, statement) => result && (0, isAfter_1.default)((0, parseISO_1.default)('stored' in result && result.stored ? result.stored : result.timestamp), (0, parseISO_1.default)(statement.timestamp)) ? result : statement, statements[0]);
71
- exports.mostRecentStatement = mostRecentStatement;
67
+ const resolveAttemptEntries = (statements, attempts, activityIRI) => attempts.reduce((acc, attempt) => {
68
+ const completed = (0, exports.resolveCompletedForAttempt)(statements, attempt, activityIRI);
69
+ const scored = (0, exports.resolveScoredForAttempt)(statements, attempt, activityIRI);
70
+ acc.push({ attempt, completed, scored });
71
+ return acc;
72
+ }, []);
73
+ const getStatementTimeString = (statement) => 'stored' in statement && statement.stored ? statement.stored : statement.timestamp;
74
+ exports.getStatementTimeString = getStatementTimeString;
75
+ const getStatementTime = (statement) => (0, parseISO_1.default)((0, exports.getStatementTimeString)(statement));
76
+ exports.getStatementTime = getStatementTime;
77
+ const findByComparator = (comparator, extractor) => (items) => {
78
+ return items.reduce((best, item) => {
79
+ if (!best)
80
+ return item;
81
+ return comparator(extractor(best), extractor(item)) ? best : item;
82
+ }, undefined);
83
+ };
84
+ exports.oldestStatement = findByComparator(isBefore_1.default, exports.getStatementTime);
85
+ exports.mostRecentStatement = findByComparator(isAfter_1.default, exports.getStatementTime);
86
+ exports.oldestEntry = findByComparator(isBefore_1.default, (entry) => (0, exports.getStatementTime)(entry.attempt));
87
+ exports.mostRecentEntry = findByComparator(isAfter_1.default, (entry) => (0, exports.getStatementTime)(entry.attempt));
88
+ const scaledScoreForEntry = (entry) => {
89
+ var _a;
90
+ const scoringStatement = entry.scored;
91
+ const score = (_a = scoringStatement === null || scoringStatement === void 0 ? void 0 : scoringStatement.result) === null || _a === void 0 ? void 0 : _a.score;
92
+ if (!score)
93
+ return { score: undefined, entry };
94
+ // Prefer scaled, otherwise normalize raw/max if available
95
+ if (score.scaled !== undefined)
96
+ return { score: score.scaled, entry };
97
+ if (score.raw !== undefined && score.max !== undefined && score.max !== 0) {
98
+ return { score: score.raw / score.max, entry };
99
+ }
100
+ return { score: undefined, entry };
101
+ };
102
+ /*
103
+ * the 'best' entry is the one with the highest scaled score.
104
+ * if two entries have no score, the most recent is considered best.
105
+ */
106
+ exports.bestEntry = findByComparator((a, b) => {
107
+ // if neither has a score, use the most recent
108
+ if (a.score === undefined && b.score === undefined) {
109
+ return (0, isAfter_1.default)((0, exports.getStatementTime)(a.entry.attempt), (0, exports.getStatementTime)(b.entry.attempt));
110
+ }
111
+ if (a.score === undefined)
112
+ return false;
113
+ if (b.score === undefined)
114
+ return true;
115
+ return a.score > b.score;
116
+ }, scaledScoreForEntry);
72
117
  const resolveAttemptInfo = (statements, options) => {
73
118
  // TODO optimize. i'm 100% that this could all be done in one iteration but i'm not messing around with that for now.
74
119
  const attempts = (0, exports.resolveAttempts)(statements, options);
75
- /* attempts that have a completed statement */
76
- const resolveAttemptsWithCompleted = (statements, attempts, activityIRI) => attempts.reduce((acc, attempt) => {
77
- const completed = (0, exports.resolveCompletedForAttempt)(statements, attempt, activityIRI);
78
- if (completed)
79
- acc.push({ attempt, completed });
80
- return acc;
81
- }, []);
82
- const completedPairs = resolveAttemptsWithCompleted(statements, attempts, options === null || options === void 0 ? void 0 : options.activityIRI);
83
- const completedAttempts = completedPairs.length;
84
- /* the last attempt sorted by timestamp */
85
- const currentAttempt = (options === null || options === void 0 ? void 0 : options.currentAttempt)
86
- ? attempts.find(attempt => attempt.id === options.currentAttempt)
87
- : (options === null || options === void 0 ? void 0 : options.currentPreference) === 'oldest'
88
- ? (0, exports.oldestStatement)(attempts)
89
- : (0, exports.mostRecentStatement)(attempts);
90
- const current = currentAttempt
91
- ? {
92
- attempt: currentAttempt,
93
- completed: (0, exports.resolveCompletedForAttempt)(statements, currentAttempt, options === null || options === void 0 ? void 0 : options.activityIRI),
94
- scored: (0, exports.resolveScoredForAttempt)(statements, currentAttempt, options === null || options === void 0 ? void 0 : options.activityIRI),
95
- }
96
- : undefined;
97
- const currentAttemptStatements = currentAttempt
120
+ const attemptEntries = resolveAttemptEntries(statements, attempts, options === null || options === void 0 ? void 0 : options.activityIRI);
121
+ const completedEntries = attemptEntries.filter((entry) => !!entry.completed);
122
+ const current = (options === null || options === void 0 ? void 0 : options.currentAttempt)
123
+ ? attemptEntries.find(({ attempt }) => attempt.id === options.currentAttempt)
124
+ : (options === null || options === void 0 ? void 0 : options.currentPreference) === 'oldest' /* the attempt sorted by timestamp */
125
+ ? (0, exports.oldestEntry)(attemptEntries)
126
+ : (0, exports.mostRecentEntry)(attemptEntries);
127
+ const currentAttemptStatements = current
98
128
  ? statements.filter(statement => {
99
129
  var _a;
100
130
  return (!(options === null || options === void 0 ? void 0 : options.activityIRI) || statement.object.id === options.activityIRI) &&
101
- ((_a = statement.context) === null || _a === void 0 ? void 0 : _a.registration) === currentAttempt.id;
131
+ ((_a = statement.context) === null || _a === void 0 ? void 0 : _a.registration) === current.attempt.id;
102
132
  })
103
133
  : [];
104
- const mostRecentPair = completedPairs.reduce((cur, pair) => {
105
- if (!cur)
106
- return pair;
107
- return (0, isAfter_1.default)((0, parseISO_1.default)(cur.attempt.timestamp), (0, parseISO_1.default)(pair.attempt.timestamp)) ? cur : pair;
108
- }, undefined);
109
- const mostRecentWithCompleted = mostRecentPair
110
- ? {
111
- attempt: mostRecentPair.attempt,
112
- completed: (0, exports.resolveCompletedForAttempt)(statements, mostRecentPair.attempt, options === null || options === void 0 ? void 0 : options.activityIRI),
113
- scored: (0, exports.resolveScoredForAttempt)(statements, mostRecentPair.attempt, options === null || options === void 0 ? void 0 : options.activityIRI),
114
- }
115
- : undefined;
116
- const scaledForAttempt = (attempt) => {
117
- var _a;
118
- // resolveScoredForAttempt may return a Scored, or fallback to a Completed that has a score
119
- const picked = (0, exports.resolveScoredForAttempt)(statements, attempt, options === null || options === void 0 ? void 0 : options.activityIRI);
120
- const score = (_a = picked === null || picked === void 0 ? void 0 : picked.result) === null || _a === void 0 ? void 0 : _a.score;
121
- if (!score)
122
- return undefined;
123
- // Prefer scaled, otherwise normalize raw/max if available
124
- if (score.scaled !== undefined)
125
- return score.scaled;
126
- if (score.raw !== undefined && score.max !== undefined && score.max !== 0) {
127
- return score.raw / score.max;
128
- }
129
- return undefined;
130
- };
131
- let bestAttempt = completedPairs.reduce((best, { attempt }) => {
132
- const bScaled = best !== undefined ? scaledForAttempt(best) : undefined;
133
- const aScaled = scaledForAttempt(attempt);
134
- if (bScaled === undefined)
135
- return aScaled === undefined ? best : attempt;
136
- if (aScaled === undefined)
137
- return best;
138
- return aScaled > bScaled ? attempt : best;
139
- }, undefined);
140
- // Fallback if no attempt had a score, use newest completed as best
141
- if (!bestAttempt && mostRecentPair) {
142
- bestAttempt = mostRecentPair.attempt;
143
- }
144
- const best = bestAttempt
145
- ? {
146
- attempt: bestAttempt,
147
- completed: (0, exports.resolveCompletedForAttempt)(statements, bestAttempt, options && options.activityIRI),
148
- scored: (0, exports.resolveScoredForAttempt)(statements, bestAttempt, options && options.activityIRI),
149
- }
150
- : undefined;
134
+ const mostRecentWithCompleted = (0, exports.mostRecentEntry)(completedEntries);
135
+ const best = (0, exports.bestEntry)(completedEntries);
151
136
  return {
152
137
  attempts: attempts.length,
153
- completedAttempts,
138
+ completedAttempts: completedEntries.length,
154
139
  currentAttemptStatements,
155
140
  current,
156
141
  best,
@@ -1,6 +1,6 @@
1
1
  import { AccountsGateway, MappedUserInfo } from '../accountsGateway';
2
2
  import { AuthProvider } from '../authProvider';
3
- import { ActivityState } from './attempt-utils';
3
+ import { ActivityState, AttemptEntry } from './attempt-utils';
4
4
  import { LrsGateway } from '.';
5
5
  export interface Grade {
6
6
  activityProgress: 'Initialized' | 'Started' | 'inProgress' | 'Submitted' | 'Completed';
@@ -23,15 +23,8 @@ export declare const getRegistrationAttemptInfo: (lrs: LrsGateway, registration:
23
23
  }) => Promise<{
24
24
  [key: string]: ActivityState;
25
25
  }>;
26
- export declare const getScoreGrade: (score: {
27
- scaled?: number;
28
- raw?: number;
29
- min?: number;
30
- max?: number;
31
- }, options: {
26
+ export declare const getScoreGrade: (entry: Partial<AttemptEntry>, options: {
32
27
  maxScore?: number;
33
- startedAt?: string;
34
- submittedAt?: string;
35
28
  userId?: string;
36
29
  }) => Grade;
37
30
  export type Progress = {
@@ -30,28 +30,28 @@ exports.getRegistrationAttemptInfo = getRegistrationAttemptInfo;
30
30
  // lti: http://www.imsglobal.org/spec/lti-ags/v2p0#score-publish-service
31
31
  // ltijs: https://cvmcosta.me/ltijs/#/grading
32
32
  // Note: "min" is currently completely ignored
33
- const getScoreGrade = (score, options) => {
34
- const { raw, scaled, max } = score;
35
- const { maxScore, startedAt, submittedAt, userId } = options;
33
+ const getScoreGrade = (entry, options) => {
34
+ var _a, _b, _c, _d, _e;
35
+ const { raw, scaled, max } = ((_b = (_a = entry.scored) === null || _a === void 0 ? void 0 : _a.result) === null || _b === void 0 ? void 0 : _b.score) || {};
36
+ const { maxScore, userId } = options;
36
37
  const scoreMaximum = maxScore !== null && maxScore !== void 0 ? maxScore : 100;
37
38
  const scoreGiven = raw && max
38
39
  ? scoreMaximum / max * raw
39
40
  : scaled
40
41
  ? scaled * scoreMaximum
41
42
  : 0;
42
- const submission = {};
43
- if (startedAt) {
44
- submission.startedAt = startedAt;
45
- }
46
- if (submittedAt) {
47
- submission.submittedAt = submittedAt;
48
- }
43
+ const submission = {
44
+ startedAt: entry.attempt ? (0, attempt_utils_1.getStatementTimeString)(entry.attempt) : undefined,
45
+ submittedAt: entry.completed ? (0, attempt_utils_1.getStatementTimeString)(entry.completed) : undefined,
46
+ };
47
+ const pendingManual = entry.scored === undefined
48
+ && ((_e = (_d = (_c = entry.completed) === null || _c === void 0 ? void 0 : _c.result) === null || _d === void 0 ? void 0 : _d.extensions) === null || _e === void 0 ? void 0 : _e[attempt_utils_1.EXT_PENDING_SCORING]) === 'true';
49
49
  return {
50
50
  userId,
51
- activityProgress: submittedAt ? 'Completed' : 'Started',
51
+ activityProgress: entry.completed ? 'Completed' : 'Started',
52
52
  // canvas assumes that anything that isn't 'FullyGraded' requires manual grading and displays a "needs grading" icon.
53
53
  // if you warp your mind you can consider the portion of the assignment which is completed to be fully graded.
54
- gradingProgress: 'FullyGraded',
54
+ gradingProgress: pendingManual ? 'PendingManual' : 'FullyGraded',
55
55
  scoreMaximum,
56
56
  scoreGiven: (0, __1.roundToPrecision)(scoreGiven, -2),
57
57
  submission,
@@ -59,32 +59,19 @@ const getScoreGrade = (score, options) => {
59
59
  };
60
60
  exports.getScoreGrade = getScoreGrade;
61
61
  // These methods assign 0's to incomplete activities
62
- const pickAttemptAndCompletedOrScored = (state, gradePreference) => {
63
- var _a;
64
- const entry = (gradePreference === 'best' ? state.best : state.current);
65
- return {
66
- attempt: entry === null || entry === void 0 ? void 0 : entry.attempt,
67
- completedOrScored: (_a = entry === null || entry === void 0 ? void 0 : entry.scored) !== null && _a !== void 0 ? _a : entry === null || entry === void 0 ? void 0 : entry.completed,
68
- completed: entry === null || entry === void 0 ? void 0 : entry.completed,
69
- };
62
+ const getGradingAttemptEntry = (state, gradePreference) => {
63
+ return (gradePreference === 'best' ? state.best : state.current) || {};
70
64
  };
71
65
  const getCompletedActivityStateGradeAndProgress = ({ name, scoreMaximum, state, userId, gradePreference = 'current' }) => {
72
- var _a, _b, _c;
73
- const { attempt, completedOrScored, completed } = pickAttemptAndCompletedOrScored(state, gradePreference);
74
- const grade = (0, exports.getScoreGrade)(((_a = completedOrScored === null || completedOrScored === void 0 ? void 0 : completedOrScored.result) === null || _a === void 0 ? void 0 : _a.score) || {}, {
66
+ const entry = getGradingAttemptEntry(state, gradePreference);
67
+ const grade = (0, exports.getScoreGrade)(entry, {
75
68
  maxScore: scoreMaximum,
76
- startedAt: attempt === null || attempt === void 0 ? void 0 : attempt.timestamp,
77
- submittedAt: completed === null || completed === void 0 ? void 0 : completed.timestamp,
78
69
  userId,
79
70
  });
80
- // If this Completed is explicitly "pending scoring", surface that in the grade.
81
- if (((_c = (_b = completedOrScored === null || completedOrScored === void 0 ? void 0 : completedOrScored.result) === null || _b === void 0 ? void 0 : _b.extensions) === null || _c === void 0 ? void 0 : _c[attempt_utils_1.EXT_PENDING_SCORING]) === 'true') {
82
- grade.gradingProgress = 'PendingManual';
83
- }
84
71
  return {
85
72
  grade,
86
73
  progress: {
87
- scaled: completedOrScored ? 1 : 0,
74
+ scaled: entry.completed ? 1 : 0,
88
75
  },
89
76
  name,
90
77
  };
@@ -98,7 +85,7 @@ const getCompletedUserInfosGradeAndProgress = (infos, scoreMaximum, gradePrefere
98
85
  }));
99
86
  exports.getCompletedUserInfosGradeAndProgress = getCompletedUserInfosGradeAndProgress;
100
87
  const getCurrentGrade = async (services, registration, options) => {
101
- var _a;
88
+ var _a, _b;
102
89
  const user = await services.ltiAuthProvider.getUser();
103
90
  if (!user) {
104
91
  return null;
@@ -116,7 +103,7 @@ const getCurrentGrade = async (services, registration, options) => {
116
103
  gradePreference,
117
104
  });
118
105
  }
119
- if (userInfo.current && userInfo.current.completed || !incompleteAttemptCallback) {
106
+ if (((_b = userInfo.current) === null || _b === void 0 ? void 0 : _b.completed) || !incompleteAttemptCallback) {
120
107
  return getCompletedActivityStateGradeAndProgress({
121
108
  name,
122
109
  scoreMaximum,
@@ -138,8 +125,8 @@ const getAssignmentGrades = async (services, assignmentIRI, registration, option
138
125
  }
139
126
  // Partition based on whether the chosen preference has a completed attempt
140
127
  const [incompleteInfo, completedInfo] = (0, partition_1.default)((info) => {
141
- const { completedOrScored } = pickAttemptAndCompletedOrScored(info.data, gradePreference);
142
- return completedOrScored === undefined;
128
+ const { completed } = getGradingAttemptEntry(info.data, gradePreference);
129
+ return completed === undefined;
143
130
  })(mappedInfo);
144
131
  return (0, exports.getCompletedUserInfosGradeAndProgress)(completedInfo, scoreMaximum, gradePreference).concat(await incompleteAttemptsCallback(incompleteInfo));
145
132
  };