CoolFace
Apppublic

HelloWorld97/layeredlearner-assignment-mastermind

sourceHugging Faceupdated 9mo agoView on Hugging Face
0likes
script.js871 linesDownload Raw Back to root
1// Main application script for LayeredLearner2 3// Storage key4const STORAGE_KEY = 'LayeredAssignmentTracker_v1';5 6// Initial sample data7const sampleData = {8    courses: [9        {10            id: 'course_1',11            name: 'Biology 11',12            units: ['unit_1', 'unit_2'],13            createdAt: Date.now() - 30 * 24 * 60 * 60 * 100014        },15        {16            id: 'course_2',17            name: 'Calculus 12',18            units: ['unit_3'],19            createdAt: Date.now() - 15 * 24 * 60 * 60 * 100020        }21    ],22    units: [23        {24            id: 'unit_1',25            courseId: 'course_1',26            name: 'Cell Biology',27            material: 'Cells are the basic unit of life. Topics include cell structure, organelles, membrane transport, and cellular processes like photosynthesis and respiration.',28            createdAt: Date.now() - 28 * 24 * 60 * 60 * 100029        },30        {31            id: 'unit_2',32            courseId: 'course_1',33            name: 'Genetics',34            material: 'Study of genes, heredity, and variation in living organisms. Covers DNA structure, replication, transcription, translation, and genetic disorders.',35            createdAt: Date.now() - 14 * 24 * 60 * 60 * 100036        },37        {38            id: 'unit_3',39            courseId: 'course_2',40            name: 'Differential Calculus',41            material: 'Introduction to derivatives, limits, and their applications. Topics include power rule, chain rule, product rule, and optimization problems.',42            createdAt: Date.now() - 10 * 24 * 60 * 60 * 100043        }44    ],45    assignments: [46        {47            id: 'assign_1',48            courseId: 'course_1',49            unitId: 'unit_1',50            name: 'Mitochondria Essay',51            type: 'written',52            status: 'in progress',53            link: '',54            ai: {55                assignmentStructure: null,56                draftRank: null,57                draftFeedback: null,58                practiceTest: null,59                summary: null,60                answerKey: null61            },62            draft: 'Mitochondria are often called the powerhouses of the cell...',63            final: '',64            grade: null,65            gradeFeedback: [],66            createdAt: Date.now() - 7 * 24 * 60 * 60 * 1000,67            updatedAt: Date.now() - 2 * 24 * 60 * 60 * 100068        },69        {70            id: 'assign_2',71            courseId: 'course_2',72            unitId: 'unit_3',73            name: 'Derivatives Quiz',74            type: 'quiz',75            status: 'not started',76            link: '',77            ai: {78                assignmentStructure: null,79                draftRank: null,80                draftFeedback: null,81                practiceTest: null,82                summary: null,83                answerKey: null84            },85            draft: '',86            final: '',87            grade: null,88            gradeFeedback: [],89            createdAt: Date.now() - 3 * 24 * 60 * 60 * 1000,90            updatedAt: Date.now() - 3 * 24 * 60 * 60 * 100091        }92    ],93    lastSavedAt: Date.now()94};95 96// Application state97let appState = {98    courses: [],99    units: [],100    assignments: [],101    filters: {102        course: null,103        unit: null,104        type: [],105        status: [],106        search: ''107    },108    sort: {109        field: 'updatedAt',110        direction: 'desc'111    }112};113 114// Initialize application115function initApp() {116    loadState();117    renderCourses();118    renderAssignments();119    updateStats();120    setupEventListeners();121    feather.replace();122}123 124// Storage functions125function loadState() {126    try {127        const saved = localStorage.getItem(STORAGE_KEY);128        if (saved) {129            const parsed = JSON.parse(saved);130            appState.courses = parsed.courses || [];131            appState.units = parsed.units || [];132            appState.assignments = parsed.assignments || [];133        } else {134            // Load sample data135            appState = { ...sampleData, filters: appState.filters, sort: appState.sort };136            saveState();137        }138    } catch (error) {139        console.error('Failed to load state:', error);140        showToast('Error loading data. Loading sample data.', 'error');141        appState = { ...sampleData, filters: appState.filters, sort: appState.sort };142    }143}144 145function saveState() {146    try {147        const stateToSave = {148            courses: appState.courses,149            units: appState.units,150            assignments: appState.assignments,151            lastSavedAt: Date.now()152        };153        localStorage.setItem(STORAGE_KEY, JSON.stringify(stateToSave));154    } catch (error) {155        console.error('Failed to save state:', error);156        showToast('Error saving data.', 'error');157    }158}159 160// Render functions161function renderCourses() {162    const container = document.getElementById('courses-list');163    if (!container) return;164 165    if (appState.courses.length === 0) {166        container.innerHTML = `167            <div class="text-center py-8 text-gray-500">168                <i data-feather="book" class="w-12 h-12 mx-auto mb-3 text-gray-300"></i>169                <p>No courses yet. Add your first course!</p>170            </div>171        `;172        return;173    }174 175    container.innerHTML = appState.courses.map(course => {176        const courseUnits = appState.units.filter(u => u.courseId === course.id);177        const courseAssignments = appState.assignments.filter(a => a.courseId === course.id);178        179        return `180            <div class="course-card p-4 rounded-lg border border-gray-200 hover:border-primary/50 transition-all-200 hover-card">181                <div class="flex justify-between items-start mb-2">182                    <h3 class="font-bold text-gray-800">${course.name}</h3>183                    <div class="flex gap-1">184                        <button class="edit-course-btn p-1 text-gray-400 hover:text-primary" data-id="${course.id}">185                            <i data-feather="edit-2" class="w-4 h-4"></i>186                        </button>187                        <button class="delete-course-btn p-1 text-gray-400 hover:text-red-500" data-id="${course.id}">188                            <i data-feather="trash-2" class="w-4 h-4"></i>189                        </button>190                    </div>191                </div>192                <div class="flex items-center gap-4 text-sm text-gray-600 mb-3">193                    <span class="flex items-center gap-1">194                        <i data-feather="layers" class="w-3 h-3"></i>195                        ${courseUnits.length} units196                    </span>197                    <span class="flex items-center gap-1">198                        <i data-feather="file-text" class="w-3 h-3"></i>199                        ${courseAssignments.length} assignments200                    </span>201                </div>202                <div class="space-y-1">203                    ${courseUnits.slice(0, 3).map(unit => `204                        <div class="text-sm text-gray-600 flex items-center gap-2">205                            <i data-feather="folder" class="w-3 h-3 text-gray-400"></i>206                            ${unit.name}207                        </div>208                    `).join('')}209                    ${courseUnits.length > 3 ? `210                        <div class="text-sm text-gray-500">211                            +${courseUnits.length - 3} more units212                        </div>213                    ` : ''}214                </div>215            </div>216        `;217    }).join('');218 219    feather.replace();220}221 222function renderAssignments() {223    const container = document.getElementById('assignments-table-body');224    const emptyState = document.getElementById('empty-state');225    226    if (!container) return;227 228    // Apply filters and sorting229    let filteredAssignments = [...appState.assignments];230    231    // Apply course filter232    if (appState.filters.course) {233        filteredAssignments = filteredAssignments.filter(a => a.courseId === appState.filters.course);234    }235    236    // Apply unit filter237    if (appState.filters.unit) {238        filteredAssignments = filteredAssignments.filter(a => a.unitId === appState.filters.unit);239    }240    241    // Apply type filter242    if (appState.filters.type.length > 0) {243        filteredAssignments = filteredAssignments.filter(a => appState.filters.type.includes(a.type));244    }245    246    // Apply status filter247    if (appState.filters.status.length > 0) {248        filteredAssignments = filteredAssignments.filter(a => appState.filters.status.includes(a.status));249    }250    251    // Apply search252    if (appState.filters.search) {253        const searchLower = appState.filters.search.toLowerCase();254        filteredAssignments = filteredAssignments.filter(a => {255            const course = appState.courses.find(c => c.id === a.courseId);256            const unit = appState.units.find(u => u.id === a.unitId);257            return (258                a.name.toLowerCase().includes(searchLower) ||259                (course && course.name.toLowerCase().includes(searchLower)) ||260                (unit && unit.name.toLowerCase().includes(searchLower))261            );262        });263    }264    265    // Apply sorting266    filteredAssignments.sort((a, b) => {267        let aVal, bVal;268        269        switch (appState.sort.field) {270            case 'course':271                aVal = appState.courses.find(c => c.id === a.courseId)?.name || '';272                bVal = appState.courses.find(c => c.id === b.courseId)?.name || '';273                break;274            case 'unit':275                aVal = appState.units.find(u => u.id === a.unitId)?.name || '';276                bVal = appState.units.find(u => u.id === b.unitId)?.name || '';277                break;278            default:279                aVal = a[appState.sort.field];280                bVal = b[appState.sort.field];281        }282        283        if (appState.sort.direction === 'asc') {284            return aVal > bVal ? 1 : -1;285        } else {286            return aVal < bVal ? 1 : -1;287        }288    });289 290    // Show/hide empty state291    if (filteredAssignments.length === 0) {292        container.innerHTML = '';293        if (emptyState) emptyState.classList.remove('hidden');294        return;295    }296    297    if (emptyState) emptyState.classList.add('hidden');298 299    // Render assignments300    container.innerHTML = filteredAssignments.map(assignment => {301        const course = appState.courses.find(c => c.id === assignment.courseId);302        const unit = appState.units.find(u => u.id === assignment.unitId);303        304        const statusClass = `status-${assignment.status.replace(/\s+/g, '-')}`;305        const typeClass = `type-${assignment.type}`;306        307        const statusText = assignment.status.split('_').map(word => 308            word.charAt(0).toUpperCase() + word.slice(1)309        ).join(' ');310        311        const typeText = assignment.type.split('_').map(word => 312            word.charAt(0).toUpperCase() + word.slice(1)313        ).join(' ');314        315        return `316            <tr class="border-b border-gray-100 table-row-hover" data-id="${assignment.id}">317                <td class="py-4 px-4">318                    <div class="font-medium text-gray-800">${course?.name || 'Unknown'}</div>319                </td>320                <td class="py-4 px-4">321                    <div class="text-gray-600">${unit?.name || 'No Unit'}</div>322                </td>323                <td class="py-4 px-4">324                    <div class="font-medium text-gray-800">${assignment.name}</div>325                    ${assignment.link ? `326                        <a href="${assignment.link}" target="_blank" class="text-xs text-primary hover:underline flex items-center gap-1">327                            <i data-feather="external-link" class="w-3 h-3"></i>328                            Open link329                        </a>330                    ` : ''}331                </td>332                <td class="py-4 px-4">333                    <span class="${typeClass} type-indicator">${typeText}</span>334                </td>335                <td class="py-4 px-4">336                    <span class="${statusClass} status-badge">${statusText}</span>337                </td>338                <td class="py-4 px-4">339                    <div class="flex gap-2">340                        <a href="assignment.html?id=${assignment.id}" class="p-2 text-gray-400 hover:text-primary rounded hover:bg-gray-100">341                            <i data-feather="eye" class="w-4 h-4"></i>342                        </a>343                        <button class="edit-assignment-btn p-2 text-gray-400 hover:text-secondary rounded hover:bg-gray-100" data-id="${assignment.id}">344                            <i data-feather="edit-2" class="w-4 h-4"></i>345                        </button>346                        <button class="delete-assignment-btn p-2 text-gray-400 hover:text-red-500 rounded hover:bg-gray-100" data-id="${assignment.id}">347                            <i data-feather="trash-2" class="w-4 h-4"></i>348                        </button>349                    </div>350                </td>351            </tr>352        `;353    }).join('');354 355    feather.replace();356}357 358function updateStats() {359    document.getElementById('total-courses').textContent = appState.courses.length;360    document.getElementById('total-assignments').textContent = appState.assignments.length;361    document.getElementById('in-progress').textContent = appState.assignments.filter(a => 362        a.status === 'in progress' || a.status === 'draft done'363    ).length;364    document.getElementById('completed').textContent = appState.assignments.filter(a => 365        a.status === 'submitted' || a.status === 'graded'366    ).length;367}368 369// Event listeners370function setupEventListeners() {371    // Add course button372    document.getElementById('add-course-btn')?.addEventListener('click', () => {373        showCourseModal();374    });375    376    // Add assignment button377    document.getElementById('add-assignment-btn')?.addEventListener('click', () => {378        showAssignmentModal();379    });380    381    // Empty state add button382    document.getElementById('empty-add-btn')?.addEventListener('click', () => {383        showAssignmentModal();384    });385    386    // Export data387    document.getElementById('export-data')?.addEventListener('click', exportData);388    389    // Import data390    document.getElementById('import-data')?.addEventListener('click', () => {391        document.getElementById('import-file')?.click();392    });393    394    // Reset sample data395    document.getElementById('reset-sample')?.addEventListener('click', resetSampleData);396    397    // File input for import398    const fileInput = document.createElement('input');399    fileInput.type = 'file';400    fileInput.accept = '.json';401    fileInput.id = 'import-file';402    fileInput.style.display = 'none';403    fileInput.addEventListener('change', importData);404    document.body.appendChild(fileInput);405    406    // Table sorting407    document.querySelectorAll('.sortable').forEach(th => {408        th.addEventListener('click', () => {409            const field = th.dataset.sort;410            if (appState.sort.field === field) {411                appState.sort.direction = appState.sort.direction === 'asc' ? 'desc' : 'asc';412            } else {413                appState.sort.field = field;414                appState.sort.direction = 'asc';415            }416            renderAssignments();417        });418    });419    420    // Delegated event listeners for dynamic content421    document.addEventListener('click', (e) => {422        // Edit course423        if (e.target.closest('.edit-course-btn')) {424            const btn = e.target.closest('.edit-course-btn');425            const courseId = btn.dataset.id;426            showCourseModal(courseId);427        }428        429        // Delete course430        if (e.target.closest('.delete-course-btn')) {431            const btn = e.target.closest('.delete-course-btn');432            const courseId = btn.dataset.id;433            deleteCourse(courseId);434        }435        436        // Edit assignment437        if (e.target.closest('.edit-assignment-btn')) {438            const btn = e.target.closest('.edit-assignment-btn');439            const assignmentId = btn.dataset.id;440            showAssignmentModal(assignmentId);441        }442        443        // Delete assignment444        if (e.target.closest('.delete-assignment-btn')) {445            const btn = e.target.closest('.delete-assignment-btn');446            const assignmentId = btn.dataset.id;447            deleteAssignment(assignmentId);448        }449        450        // Assignment row click (navigate to assignment page)451        if (e.target.closest('tr[data-id]') && !e.target.closest('button')) {452            const row = e.target.closest('tr[data-id]');453            const assignmentId = row.dataset.id;454            window.location.href = `assignment.html?id=${assignmentId}`;455        }456    });457}458 459// Modal functions460function showCourseModal(courseId = null) {461    const modal = document.createElement('custom-course-modal');462    modal.setAttribute('course-id', courseId || '');463    document.getElementById('modal-container').appendChild(modal);464}465 466function showAssignmentModal(assignmentId = null) {467    const modal = document.createElement('custom-assignment-modal');468    modal.setAttribute('assignment-id', assignmentId || '');469    document.getElementById('modal-container').appendChild(modal);470}471 472function showConfirmDialog(options) {473    const dialog = document.createElement('custom-confirm-dialog');474    dialog.setAttribute('title', options.title || 'Confirm Action');475    dialog.setAttribute('message', options.message || 'Are you sure?');476    dialog.setAttribute('confirm-text', options.confirmText || 'Confirm');477    dialog.setAttribute('cancel-text', options.cancelText || 'Cancel');478    479    dialog.addEventListener('confirm', () => {480        if (options.onConfirm) options.onConfirm();481        dialog.remove();482    });483    484    dialog.addEventListener('cancel', () => {485        if (options.onCancel) options.onCancel();486        dialog.remove();487    });488    489    document.getElementById('modal-container').appendChild(dialog);490}491 492// Data operations493function deleteCourse(courseId) {494    const course = appState.courses.find(c => c.id === courseId);495    if (!course) return;496    497    const courseAssignments = appState.assignments.filter(a => a.courseId === courseId);498    const courseUnits = appState.units.filter(u => u.courseId === courseId);499    500    showConfirmDialog({501        title: 'Delete Course',502        message: `This will delete "${course.name}" and all ${courseUnits.length} units and ${courseAssignments.length} assignments. Type DELETE to confirm.`,503        confirmText: 'Delete',504        cancelText: 'Cancel',505        onConfirm: () => {506            // Remove course507            appState.courses = appState.courses.filter(c => c.id !== courseId);508            509            // Remove associated units510            appState.units = appState.units.filter(u => u.courseId !== courseId);511            512            // Remove associated assignments513            appState.assignments = appState.assignments.filter(a => a.courseId !== courseId);514            515            saveState();516            renderCourses();517            renderAssignments();518            updateStats();519            showToast('Course deleted successfully', 'success');520        }521    });522}523 524function deleteAssignment(assignmentId) {525    const assignment = appState.assignments.find(a => a.id === assignmentId);526    if (!assignment) return;527    528    showConfirmDialog({529        title: 'Delete Assignment',530        message: `Delete "${assignment.name}"? This action cannot be undone.`,531        confirmText: 'Delete',532        cancelText: 'Cancel',533        onConfirm: () => {534            appState.assignments = appState.assignments.filter(a => a.id !== assignmentId);535            saveState();536            renderAssignments();537            updateStats();538            showToast('Assignment deleted', 'success');539        }540    });541}542 543// Import/Export functions544function exportData() {545    const data = {546        courses: appState.courses,547        units: appState.units,548        assignments: appState.assignments,549        exportedAt: Date.now()550    };551    552    const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' });553    const url = URL.createObjectURL(blob);554    const a = document.createElement('a');555    a.href = url;556    a.download = `layeredlearner-export-${new Date().toISOString().split('T')[0]}.json`;557    document.body.appendChild(a);558    a.click();559    document.body.removeChild(a);560    URL.revokeObjectURL(url);561    562    showToast('Data exported successfully', 'success');563}564 565function importData(event) {566    const file = event.target.files[0];567    if (!file) return;568    569    const reader = new FileReader();570    reader.onload = function(e) {571        try {572            const importedData = JSON.parse(e.target.result);573            574            showConfirmDialog({575                title: 'Import Data',576                message: 'This will replace all current data. Are you sure?',577                confirmText: 'Import',578                cancelText: 'Cancel',579                onConfirm: () => {580                    appState.courses = importedData.courses || [];581                    appState.units = importedData.units || [];582                    appState.assignments = importedData.assignments || [];583                    saveState();584                    renderCourses();585                    renderAssignments();586                    updateStats();587                    showToast('Data imported successfully', 'success');588                }589            });590        } catch (error) {591            showToast('Invalid data file', 'error');592        }593    };594    reader.readAsText(file);595    event.target.value = '';596}597 598function resetSampleData() {599    showConfirmDialog({600        title: 'Load Sample Data',601        message: 'This will replace all current data with sample data. Are you sure?',602        confirmText: 'Load Sample',603        cancelText: 'Cancel',604        onConfirm: () => {605            appState = { ...sampleData, filters: appState.filters, sort: appState.sort };606            saveState();607            renderCourses();608            renderAssignments();609            updateStats();610            showToast('Sample data loaded', 'success');611        }612    });613}614 615// Utility functions616function showToast(message, type = 'info') {617    // Remove existing toast618    const existingToast = document.querySelector('.toast');619    if (existingToast) existingToast.remove();620    621    // Create toast622    const toast = document.createElement('div');623    toast.className = `toast fixed bottom-4 right-4 px-4 py-3 rounded-lg shadow-hard z-50 animate-fade-in ${624        type === 'success' ? 'bg-green-500 text-white' :625        type === 'error' ? 'bg-red-500 text-white' :626        'bg-gray-800 text-white'627    }`;628    toast.textContent = message;629    630    // Add icon631    const icon = document.createElement('i');632    icon.setAttribute('data-feather', 633        type === 'success' ? 'check-circle' :634        type === 'error' ? 'alert-circle' :635        'info'636    );637    icon.className = 'inline w-4 h-4 mr-2';638    toast.prepend(icon);639    640    document.body.appendChild(toast);641    feather.replace();642    643    // Auto remove644    setTimeout(() => {645        toast.remove();646    }, 3000);647}648 649// Generate unique ID650function generateId(prefix) {651    return `${prefix}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;652}653 654// Filter functions (called from filter-bar component)655function updateFilters(newFilters) {656    appState.filters = { ...appState.filters, ...newFilters };657    renderAssignments();658}659 660function clearFilters() {661    appState.filters = {662        course: null,663        unit: null,664        type: [],665        status: [],666        search: ''667    };668    renderAssignments();669}670 671// Public API for components672window.appState = appState;673window.initApp = initApp;674window.saveState = saveState;675window.generateId = generateId;676window.showToast = showToast;677window.updateFilters = updateFilters;678window.clearFilters = clearFilters;679 680// Course and unit getters for components681window.getCourses = () => appState.courses;682window.getUnits = (courseId) => appState.units.filter(u => u.courseId === courseId);683window.getCourseById = (id) => appState.courses.find(c => c.id === id);684window.getUnitById = (id) => appState.units.find(u => u.id === id);685window.getAssignmentById = (id) => appState.assignments.find(a => a.id === id);686 687// Course operations for components688window.saveCourse = (courseData) => {689    if (courseData.id) {690        // Update existing course691        const index = appState.courses.findIndex(c => c.id === courseData.id);692        if (index !== -1) {693            appState.courses[index] = { ...appState.courses[index], ...courseData };694        }695    } else {696        // Create new course697        const newCourse = {698            id: generateId('course'),699            name: courseData.name,700            units: [],701            createdAt: Date.now()702        };703        appState.courses.push(newCourse);704    }705    saveState();706    renderCourses();707    renderAssignments();708    updateStats();709    showToast('Course saved successfully', 'success');710};711 712// Assignment operations for components713window.saveAssignment = (assignmentData) => {714    if (assignmentData.id) {715        // Update existing assignment716        const index = appState.assignments.findIndex(a => a.id === assignmentData.id);717        if (index !== -1) {718            appState.assignments[index] = { 719                ...appState.assignments[index], 720                ...assignmentData,721                updatedAt: Date.now()722            };723        }724    } else {725        // Create new assignment726        const newAssignment = {727            id: generateId('assign'),728            ...assignmentData,729            ai: {730                assignmentStructure: null,731                draftRank: null,732                draftFeedback: null,733                practiceTest: null,734                summary: null,735                answerKey: null736            },737            draft: '',738            final: '',739            grade: null,740            gradeFeedback: [],741            createdAt: Date.now(),742            updatedAt: Date.now()743        };744        appState.assignments.push(newAssignment);745    }746    saveState();747    renderAssignments();748    updateStats();749    showToast('Assignment saved successfully', 'success');750};751 752// Unit operations for components753window.saveUnit = (unitData) => {754    if (unitData.id) {755        // Update existing unit756        const index = appState.units.findIndex(u => u.id === unitData.id);757        if (index !== -1) {758            appState.units[index] = { ...appState.units[index], ...unitData };759        }760    } else {761        // Create new unit762        const newUnit = {763            id: generateId('unit'),764            ...unitData,765            createdAt: Date.now()766        };767        appState.units.push(newUnit);768        769        // Add unit to course's units array770        const courseIndex = appState.courses.findIndex(c => c.id === unitData.courseId);771        if (courseIndex !== -1) {772            if (!appState.courses[courseIndex].units.includes(newUnit.id)) {773                appState.courses[courseIndex].units.push(newUnit.id);774            }775        }776    }777    saveState();778    showToast('Unit saved successfully', 'success');779};780 781// AI simulation function (for demo purposes)782window.simulateAIResponse = (task, context) => {783    // Simulate API call delay784    return new Promise((resolve) => {785        setTimeout(() => {786            let response;787            788            switch (task) {789                case 'generate_structure':790                    response = {791                        outline: [792                            {793                                heading: "Introduction",794                                purpose: "Establish context and thesis",795                                bullet_points: [796                                    "Hook: Start with an engaging statement about mitochondria",797                                    "Background: Briefly explain mitochondrial function",798                                    "Thesis: State the main argument about mitochondrial importance"799                                ],800                                estimated_word_count: 150801                            },802                            {803                                heading: "Structure and Function",804                                purpose: "Describe mitochondrial anatomy and processes",805                                bullet_points: [806                                    "Describe double membrane structure",807                                    "Explain ATP production process",808                                    "Discuss role in cellular respiration"809                                ],810                                estimated_word_count: 250811                            },812                            {813                                heading: "Conclusion",814                                purpose: "Summarize key points and implications",815                                bullet_points: [816                                    "Restate thesis in new words",817                                    "Summarize main findings",818                                    "Discuss broader implications"819                                ],820                                estimated_word_count: 150821                            }822                        ],823                        notes: "Focus on clarity and scientific accuracy. Include at least 3 reputable sources."824                    };825                    break;826                    827                case 'rank_draft':828                    response = {829                        score: 78,830                        strengths: [831                            "Clear explanation of ATP production",832                            "Good use of scientific terminology",833                            "Logical structure and flow"834                        ],835                        improvements: [836                            "Add more specific examples of mitochondrial diseases",837                            "Expand on the evolutionary significance",838                            "Include recent research citations"839                        ],840                        suggestedSnippet: "Recent studies in mitochondrial biology have revealed fascinating insights into cellular aging processes, suggesting that mitochondrial efficiency directly correlates with overall cellular health and longevity."841                    };842                    break;843                    844                case 'generate_practice_test':845                    response = {846                        questions: [847                            {848                                q: "What is the primary function of mitochondria?",849                                type: "mcq",850                                choices: ["Protein synthesis", "ATP production", "DNA replication", "Waste removal"],851                                answer: "B",852                                explanation: "Mitochondria are often called the 'powerhouses of the cell' because they produce ATP through cellular respiration."853                            },854                            {855                                q: "Describe the structure of a mitochondrion.",856                                type: "short",857                                answer: "Double membrane organelle with inner membrane folds called cristae.",858                                explanation: "The double membrane creates compartments for different stages of cellular respiration."859                            }860                        ]861                    };862                    break;863                    864                default:865                    response = { message: "AI analysis complete" };866            }867            868            resolve(response);869        }, 1500); // Simulate 1.5 second delay870    });871};