(sessions, levels, levelStatusMap, classroom, courseId)
| 21 | * @returns {string} - Next level's original id. |
| 22 | */ |
| 23 | export const findNextLevelsBySession = (sessions, levels, levelStatusMap, classroom, courseId) => { |
| 24 | if (!levelStatusMap) { |
| 25 | levelStatusMap = getLevelStatusMap(sessions) |
| 26 | } |
| 27 | const nextLevelOriginals = new Set() // next level = started levels + incomplete unlocked levels + not-started first levels |
| 28 | |
| 29 | let levelDataMap = {} |
| 30 | if (_.isArray(levels)) { |
| 31 | levelDataMap = getLevelDataMap(levels) |
| 32 | } else { |
| 33 | levelDataMap = levels || {} |
| 34 | } |
| 35 | for (const [levelOriginal, level] of Object.entries(levelDataMap)) { |
| 36 | if (classroom && classroom.isStudentOnSkippedLevel(me.get('_id'), courseId, levelOriginal)) { |
| 37 | continue |
| 38 | } |
| 39 | |
| 40 | const levelStatus = levelStatusMap[levelOriginal] |
| 41 | const isLevelStarted = typeof levelStatus === 'string' && levelStatus === 'started' |
| 42 | const isLevelCompleted = typeof levelStatus === 'string' && levelStatus === 'complete' |
| 43 | const hasCompletedStages = typeof levelStatus === 'number' && levelStatus > 0 |
| 44 | |
| 45 | if (isLevelStarted) { |
| 46 | nextLevelOriginals.add(levelOriginal) |
| 47 | } else if (isLevelCompleted || hasCompletedStages) { |
| 48 | let unlockedLevel = {} |
| 49 | if (level.isPlayedInStages) { |
| 50 | const stageCompleted = levelStatusMap[levelOriginal] |
| 51 | unlockedLevel = getNextLevelForLevel(level, stageCompleted) || {} |
| 52 | } else { |
| 53 | unlockedLevel = getNextLevelForLevel(level) || {} |
| 54 | } |
| 55 | |
| 56 | if (unlockedLevel.original && classroom && classroom.isStudentOnSkippedLevel(me.get('_id'), courseId, unlockedLevel.original)) { |
| 57 | unlockedLevel = {} |
| 58 | } |
| 59 | |
| 60 | const unlockedLevelStatus = levelStatusMap[unlockedLevel.original] |
| 61 | const unlockedLevelCompleted = (typeof unlockedLevelStatus === 'string' && unlockedLevelStatus === 'complete') || |
| 62 | (typeof unlockedLevelStatus === 'number' && unlockedLevelStatus >= unlockedLevel.nextLevelStage) |
| 63 | if (!unlockedLevelCompleted && unlockedLevel.original) { // add incomplete unlocks |
| 64 | nextLevelOriginals.add(unlockedLevel.original) |
| 65 | } |
| 66 | } else if (level.first) { |
| 67 | nextLevelOriginals.add(levelOriginal) |
| 68 | } |
| 69 | } |
| 70 | return [...nextLevelOriginals][0] // assuming there can only be one next level for the given levels and their sessions |
| 71 | } |
| 72 | |
| 73 | /** |
| 74 | * Returns the options to be used with ajv for json schema validation (used for draft-07 as of now) |
no test coverage detected