UNPKG

@basicsu/courses-mcp

Version:

Interactive programming courses from Basics - MCP server for Cursor

140 lines 6.56 kB
// Hierarchical Progress Calculation import { getCourseModules, getCourseLessons, getLessonSteps } from './database-helper.js'; import { createClient } from '@supabase/supabase-js'; const SUPABASE_URL = 'https://mqvlccclucfewgtmhyiv.supabase.co'; const SUPABASE_ANON_KEY = 'sb_publishable_MiRSlSxgvZ_D_VeB3-73Mw_gtReq_yT'; const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY); export async function calculateHierarchicalProgress(userProfileId, courseId, currentModuleId, currentLessonId, currentStepId) { // Get course structure const allModules = await getCourseModules(courseId); const currentModuleIndex = allModules.findIndex(m => m.id === currentModuleId); const currentModule = allModules[currentModuleIndex]; const allLessonsInModule = await getCourseLessons(currentModuleId); const currentLessonIndex = allLessonsInModule.findIndex(l => l.id === currentLessonId); const currentLesson = allLessonsInModule[currentLessonIndex]; const allStepsInLesson = await getLessonSteps(currentLessonId); const currentStepIndex = currentStepId ? allStepsInLesson.findIndex(s => s.id === currentStepId) : -1; const currentStep = currentStepId ? allStepsInLesson[currentStepIndex] : allStepsInLesson[0] || null; // Calculate total course structure let totalLessons = 0; let totalSteps = 0; for (const module of allModules) { const moduleLessons = await getCourseLessons(module.id); totalLessons += moduleLessons.length; for (const lesson of moduleLessons) { const lessonSteps = await getLessonSteps(lesson.id); totalSteps += lessonSteps.length; } } // Get user's completed steps from database (using profile ID directly) const { data: completedSteps } = await supabase .from('user_step_progress') .select('step_id') .eq('user_id', userProfileId); const completedStepIds = new Set((completedSteps || []).map(s => s.step_id)); // Calculate completed lessons and modules let completedLessons = 0; let completedModules = 0; let currentModuleCompletedLessons = 0; for (let i = 0; i < allModules.length; i++) { const module = allModules[i]; const moduleLessons = await getCourseLessons(module.id); let moduleCompletedLessons = 0; for (let j = 0; j < moduleLessons.length; j++) { const lesson = moduleLessons[j]; const lessonSteps = await getLessonSteps(lesson.id); if (lessonSteps.length === 0) { // No steps means lesson is incomplete (has no content) // Don't count as completed } else { // Count completed steps in this lesson const completedStepsInLesson = lessonSteps.filter(step => completedStepIds.has(step.id)).length; if (completedStepsInLesson === lessonSteps.length) { // All steps completed = lesson complete moduleCompletedLessons++; if (i < currentModuleIndex) completedLessons++; } else if (i === currentModuleIndex && j < currentLessonIndex) { // Previous lessons in current module should be complete if we're past them // But only if they have steps if (lessonSteps.length > 0) { moduleCompletedLessons++; } } } } if (i === currentModuleIndex) { currentModuleCompletedLessons = moduleCompletedLessons; } if (moduleCompletedLessons === moduleLessons.length && moduleLessons.length > 0) { completedModules++; } } // Calculate progress at each level const stepProgress = { completed: completedStepIds.size, total: totalSteps, percentage: totalSteps > 0 ? Math.round((completedStepIds.size / totalSteps) * 100) : 0 }; // Current lesson progress (steps within current lesson) const completedStepsInCurrentLesson = allStepsInLesson.filter(step => completedStepIds.has(step.id)).length; const currentLessonStepPercentage = allStepsInLesson.length > 0 ? Math.round((completedStepsInCurrentLesson / allStepsInLesson.length) * 100) : 100; const lessonProgress = { completed: completedLessons, total: totalLessons, percentage: totalLessons > 0 ? Math.round((completedLessons / totalLessons) * 100) : 0, currentLessonPercentage: currentLessonStepPercentage }; // Current module progress (lessons within current module + partial current lesson) const moduleProgressWithCurrent = currentModuleCompletedLessons + (currentLessonStepPercentage / 100); const currentModulePercentage = allLessonsInModule.length > 0 ? Math.round((moduleProgressWithCurrent / allLessonsInModule.length) * 100) : 0; const moduleProgress = { completed: completedModules, total: allModules.length, percentage: allModules.length > 0 ? Math.round((completedModules / allModules.length) * 100) : 0, currentModulePercentage }; // Overall course progress (hierarchical) - based on modules const courseProgressWithCurrent = completedModules + (currentModulePercentage / 100); const coursePercentage = allModules.length > 0 ? Math.round((courseProgressWithCurrent / allModules.length) * 100) : 0; const courseProgress = { completed: completedModules, total: allModules.length, percentage: coursePercentage }; return { currentModule: { id: currentModule.id, title: currentModule.title, index: currentModuleIndex, totalModules: allModules.length }, currentLesson: { id: currentLesson.id, title: currentLesson.title, index: currentLessonIndex, totalLessons: allLessonsInModule.length }, currentStep: currentStep ? { id: currentStep.id, title: currentStep.title, index: currentStepIndex, totalSteps: allStepsInLesson.length } : { id: null, title: 'No steps in this lesson', index: -1, totalSteps: allStepsInLesson.length }, stepProgress, lessonProgress, moduleProgress, courseProgress }; } //# sourceMappingURL=hierarchical-progress.js.map