| |
| const appData = { |
| "lifecycleStages": [ |
| { |
| "id": 1, |
| "name": "Problem Formulation", |
| "icon": "π‘", |
| "description": "Transform real-world problems into data-driven questions", |
| "example": "Healthcare: Predicting patient recovery time based on medical history", |
| "keyPoints": ["Define business objectives", "Identify success metrics", "Translate to ML problem", "Set constraints and requirements"], |
| "status": "completed" |
| }, |
| { |
| "id": 2, |
| "name": "Data Collection", |
| "icon": "π", |
| "description": "Gather relevant data from reliable sources", |
| "sources": ["Clinical databases", "IoT sensors", "Public datasets", "APIs"], |
| "compliance": {"HIPAA": true, "GDPR": true, "SOX": false}, |
| "status": "completed" |
| }, |
| { |
| "id": 3, |
| "name": "Data Preprocessing", |
| "icon": "π§", |
| "description": "Clean and standardize data for analysis", |
| "metrics": {"missingValues": 12, "normalization": "StandardScaler", "categoricalEncoding": "OneHot", "outliers": 8}, |
| "status": "in-progress" |
| }, |
| { |
| "id": 4, |
| "name": "Modeling", |
| "icon": "π€", |
| "description": "Select and apply appropriate algorithms", |
| "modelTypes": ["Classification", "Regression", "Clustering"], |
| "algorithms": ["Random Forest", "Logistic Regression", "SVM", "Neural Networks"], |
| "status": "pending" |
| }, |
| { |
| "id": 5, |
| "name": "Evaluation", |
| "icon": "π", |
| "description": "Assess model performance and reliability", |
| "metrics": {"accuracy": 0.94, "precision": 0.91, "recall": 0.89, "f1Score": 0.90}, |
| "status": "pending" |
| }, |
| { |
| "id": 6, |
| "name": "Deployment", |
| "icon": "π", |
| "description": "Deploy model to production environment", |
| "pipeline": {"docker": true, "kubernetes": true, "cicd": "Jenkins", "api": "REST"}, |
| "status": "pending" |
| }, |
| { |
| "id": 7, |
| "name": "Monitoring & Maintenance", |
| "icon": "π", |
| "description": "Monitor performance and maintain model accuracy", |
| "alerts": {"dataDrift": false, "accuracyDecay": 2.1, "retrainingDue": "2025-07-15"}, |
| "status": "pending" |
| } |
| ], |
| "industries": [ |
| {"name": "Healthcare", "examples": ["Patient recovery prediction", "Disease diagnosis", "Drug discovery"]}, |
| {"name": "Retail", "examples": ["Customer segmentation", "Demand forecasting", "Price optimization"]}, |
| {"name": "Finance", "examples": ["Fraud detection", "Credit scoring", "Algorithmic trading"]}, |
| {"name": "Manufacturing", "examples": ["Predictive maintenance", "Quality control", "Supply chain optimization"]}, |
| {"name": "Education", "examples": ["Student performance prediction", "Personalized learning", "Dropout prevention"]} |
| ], |
| "modelTypes": [ |
| {"name": "Logistic Regression", "type": "Classification", "accuracy": 0.85}, |
| {"name": "Random Forest", "type": "Classification", "accuracy": 0.92}, |
| {"name": "SVM", "type": "Classification", "accuracy": 0.88}, |
| {"name": "Neural Networks", "type": "Classification", "accuracy": 0.94}, |
| {"name": "Linear Regression", "type": "Regression", "rmse": 0.23}, |
| {"name": "K-Means", "type": "Clustering", "silhouette": 0.67} |
| ], |
| "complianceRequirements": { |
| "Healthcare": ["HIPAA", "FDA", "HITECH"], |
| "Finance": ["SOX", "GDPR", "PCI-DSS"], |
| "Retail": ["GDPR", "CCPA"], |
| "Manufacturing": ["ISO 27001", "GDPR"], |
| "Education": ["FERPA", "COPPA"] |
| } |
| }; |
|
|
| |
| let currentStage = null; |
| let currentFilters = { |
| industry: '', |
| model: '', |
| version: '' |
| }; |
| let evaluationChart = null; |
|
|
| |
| document.addEventListener('DOMContentLoaded', function() { |
| initializeTimeline(); |
| initializeFilters(); |
| updateProgressSummary(); |
| }); |
|
|
| |
| function initializeTimeline() { |
| const timelineStages = document.getElementById('timelineStages'); |
| |
| appData.lifecycleStages.forEach((stage, index) => { |
| const stageElement = createTimelineStage(stage, index); |
| timelineStages.appendChild(stageElement); |
| }); |
| } |
|
|
| |
| function createTimelineStage(stage, index) { |
| const stageDiv = document.createElement('div'); |
| stageDiv.className = `timeline-stage timeline-stage--${index % 2 === 0 ? 'left' : 'right'} timeline-stage--${stage.status}`; |
| stageDiv.setAttribute('data-stage-id', stage.id); |
| |
| stageDiv.innerHTML = ` |
| <div class="timeline-stage__card"> |
| <h3 class="timeline-stage__title">${stage.name}</h3> |
| <p class="timeline-stage__description">${stage.description}</p> |
| <span class="timeline-stage__status status--${stage.status}">${stage.status.replace('-', ' ')}</span> |
| </div> |
| <div class="timeline-stage__node">${stage.icon}</div> |
| `; |
| |
| stageDiv.addEventListener('click', () => selectStage(stage.id)); |
| |
| return stageDiv; |
| } |
|
|
| |
| function initializeFilters() { |
| const industryFilter = document.getElementById('industryFilter'); |
| const modelFilter = document.getElementById('modelFilter'); |
| const versionFilter = document.getElementById('versionFilter'); |
| |
| industryFilter.addEventListener('change', (e) => { |
| currentFilters.industry = e.target.value; |
| applyFilters(); |
| }); |
| |
| modelFilter.addEventListener('change', (e) => { |
| currentFilters.model = e.target.value; |
| applyFilters(); |
| }); |
| |
| versionFilter.addEventListener('change', (e) => { |
| currentFilters.version = e.target.value; |
| applyFilters(); |
| }); |
| } |
|
|
| |
| function applyFilters() { |
| |
| console.log('Filters applied:', currentFilters); |
| } |
|
|
| |
| function selectStage(stageId) { |
| |
| document.querySelectorAll('.timeline-stage').forEach(stage => { |
| stage.classList.remove('timeline-stage--active'); |
| }); |
| |
| |
| const selectedStage = document.querySelector(`[data-stage-id="${stageId}"]`); |
| if (selectedStage) { |
| selectedStage.classList.add('timeline-stage--active'); |
| } |
| |
| |
| const stage = appData.lifecycleStages.find(s => s.id === stageId); |
| if (stage) { |
| currentStage = stage; |
| showStageDetails(stage); |
| } |
| } |
|
|
| |
| function showStageDetails(stage) { |
| const stageDetail = document.getElementById('stageDetail'); |
| |
| let content = ` |
| <div class="stage-content"> |
| <div class="stage-header"> |
| <div class="stage-icon">${stage.icon}</div> |
| <div> |
| <h2 class="stage-title">${stage.name}</h2> |
| <p class="stage-description">${stage.description}</p> |
| </div> |
| </div> |
| <div class="stage-sections"> |
| `; |
| |
| |
| switch(stage.id) { |
| case 1: |
| content += ` |
| <div class="stage-section"> |
| <h4>Real-world Example</h4> |
| <p>${stage.example}</p> |
| </div> |
| <div class="stage-section"> |
| <h4>Key Activities</h4> |
| <ul class="key-points"> |
| ${stage.keyPoints.map(point => `<li>${point}</li>`).join('')} |
| </ul> |
| </div> |
| `; |
| break; |
| |
| case 2: |
| content += ` |
| <div class="stage-section"> |
| <h4>Data Sources</h4> |
| <ul class="key-points"> |
| ${stage.sources.map(source => `<li>${source}</li>`).join('')} |
| </ul> |
| </div> |
| <div class="stage-section"> |
| <h4>Compliance Status</h4> |
| <div class="compliance-badges"> |
| ${Object.entries(stage.compliance).map(([key, value]) => |
| `<span class="compliance-badge compliance-badge--${value ? 'active' : 'inactive'}">${key}</span>` |
| ).join('')} |
| </div> |
| </div> |
| `; |
| break; |
| |
| case 3: |
| content += ` |
| <div class="stage-section"> |
| <h4>Data Quality Metrics</h4> |
| <div class="metrics-grid"> |
| <div class="metric-item"> |
| <span class="metric-label">Missing Values</span> |
| <span class="metric-value">${stage.metrics.missingValues}%</span> |
| </div> |
| <div class="metric-item"> |
| <span class="metric-label">Normalization</span> |
| <span class="metric-value">${stage.metrics.normalization}</span> |
| </div> |
| <div class="metric-item"> |
| <span class="metric-label">Categorical Encoding</span> |
| <span class="metric-value">${stage.metrics.categoricalEncoding}</span> |
| </div> |
| <div class="metric-item"> |
| <span class="metric-label">Outliers Detected</span> |
| <span class="metric-value">${stage.metrics.outliers}</span> |
| </div> |
| </div> |
| </div> |
| `; |
| break; |
| |
| case 4: |
| content += ` |
| <div class="stage-section"> |
| <h4>Select Model Type</h4> |
| <div class="model-selector"> |
| ${stage.modelTypes.map(type => |
| `<div class="model-option" data-model-type="${type}">${type}</div>` |
| ).join('')} |
| </div> |
| <div id="modelOutput" class="mt-8"></div> |
| </div> |
| `; |
| break; |
| |
| case 5: |
| content += ` |
| <div class="stage-section"> |
| <h4>Performance Metrics</h4> |
| <div class="metrics-grid"> |
| <div class="metric-item"> |
| <span class="metric-label">Accuracy</span> |
| <span class="metric-value">${(stage.metrics.accuracy * 100).toFixed(1)}%</span> |
| </div> |
| <div class="metric-item"> |
| <span class="metric-label">Precision</span> |
| <span class="metric-value">${(stage.metrics.precision * 100).toFixed(1)}%</span> |
| </div> |
| <div class="metric-item"> |
| <span class="metric-label">Recall</span> |
| <span class="metric-value">${(stage.metrics.recall * 100).toFixed(1)}%</span> |
| </div> |
| <div class="metric-item"> |
| <span class="metric-label">F1-Score</span> |
| <span class="metric-value">${(stage.metrics.f1Score * 100).toFixed(1)}%</span> |
| </div> |
| </div> |
| <div class="chart-container"> |
| <canvas id="evaluationChart"></canvas> |
| </div> |
| </div> |
| `; |
| break; |
| |
| case 6: |
| content += ` |
| <div class="stage-section"> |
| <h4>Infrastructure Status</h4> |
| <div class="metrics-grid"> |
| <div class="metric-item"> |
| <span class="metric-label">Docker</span> |
| <span class="metric-value">${stage.pipeline.docker ? 'β Ready' : 'β Not Ready'}</span> |
| </div> |
| <div class="metric-item"> |
| <span class="metric-label">Kubernetes</span> |
| <span class="metric-value">${stage.pipeline.kubernetes ? 'β Ready' : 'β Not Ready'}</span> |
| </div> |
| <div class="metric-item"> |
| <span class="metric-label">CI/CD</span> |
| <span class="metric-value">${stage.pipeline.cicd}</span> |
| </div> |
| <div class="metric-item"> |
| <span class="metric-label">API Type</span> |
| <span class="metric-value">${stage.pipeline.api}</span> |
| </div> |
| </div> |
| </div> |
| `; |
| break; |
| |
| case 7: |
| content += ` |
| <div class="stage-section"> |
| <h4>System Health</h4> |
| <div class="alert alert--${stage.alerts.dataDrift ? 'warning' : 'success'}"> |
| <strong>Data Drift:</strong> ${stage.alerts.dataDrift ? 'Detected - Review required' : 'No drift detected'} |
| </div> |
| <div class="alert alert--warning"> |
| <strong>Accuracy Decay:</strong> ${stage.alerts.accuracyDecay}% decline detected |
| </div> |
| <div class="alert alert--info"> |
| <strong>Next Retraining:</strong> Scheduled for ${stage.alerts.retrainingDue} |
| </div> |
| </div> |
| `; |
| break; |
| } |
| |
| content += ` |
| </div> |
| </div> |
| `; |
| |
| stageDetail.innerHTML = content; |
| |
| |
| if (stage.id === 4) { |
| setupModelSelector(); |
| } else if (stage.id === 5) { |
| setTimeout(() => createEvaluationChart(stage.metrics), 100); |
| } |
| } |
|
|
| |
| function setupModelSelector() { |
| document.querySelectorAll('.model-option').forEach(option => { |
| option.addEventListener('click', function() { |
| |
| document.querySelectorAll('.model-option').forEach(opt => { |
| opt.classList.remove('model-option--selected'); |
| }); |
| |
| |
| this.classList.add('model-option--selected'); |
| |
| |
| const modelType = this.getAttribute('data-model-type'); |
| showModelOutput(modelType); |
| }); |
| }); |
| } |
|
|
| |
| function showModelOutput(modelType) { |
| const outputDiv = document.getElementById('modelOutput'); |
| const relevantModels = appData.modelTypes.filter(model => model.type === modelType); |
| |
| let output = ` |
| <h5>Available ${modelType} Models:</h5> |
| <div class="model-selector"> |
| `; |
| |
| relevantModels.forEach(model => { |
| const metric = model.accuracy ? `Accuracy: ${(model.accuracy * 100).toFixed(1)}%` : |
| model.rmse ? `RMSE: ${model.rmse}` : |
| `Silhouette Score: ${model.silhouette}`; |
| |
| output += ` |
| <div class="model-option"> |
| <strong>${model.name}</strong><br> |
| <small>${metric}</small> |
| </div> |
| `; |
| }); |
| |
| output += '</div>'; |
| outputDiv.innerHTML = output; |
| } |
|
|
| |
| function createEvaluationChart(metrics) { |
| const ctx = document.getElementById('evaluationChart'); |
| if (!ctx) return; |
| |
| |
| if (evaluationChart) { |
| evaluationChart.destroy(); |
| } |
| |
| evaluationChart = new Chart(ctx, { |
| type: 'bar', |
| data: { |
| labels: ['Accuracy', 'Precision', 'Recall', 'F1-Score'], |
| datasets: [{ |
| label: 'Performance Metrics', |
| data: [metrics.accuracy, metrics.precision, metrics.recall, metrics.f1Score], |
| backgroundColor: ['#1FB8CD', '#FFC185', '#B4413C', '#5D878F'], |
| borderColor: ['#1FB8CD', '#FFC185', '#B4413C', '#5D878F'], |
| borderWidth: 2, |
| borderRadius: 8 |
| }] |
| }, |
| options: { |
| responsive: true, |
| maintainAspectRatio: false, |
| plugins: { |
| legend: { |
| display: false |
| }, |
| tooltip: { |
| callbacks: { |
| label: function(context) { |
| return `${context.label}: ${(context.parsed.y * 100).toFixed(1)}%`; |
| } |
| } |
| } |
| }, |
| scales: { |
| y: { |
| beginAtZero: true, |
| max: 1, |
| ticks: { |
| callback: function(value) { |
| return (value * 100).toFixed(0) + '%'; |
| } |
| } |
| } |
| } |
| } |
| }); |
| } |
|
|
| |
| function updateProgressSummary() { |
| const completed = appData.lifecycleStages.filter(stage => stage.status === 'completed').length; |
| const inProgress = appData.lifecycleStages.filter(stage => stage.status === 'in-progress').length; |
| const pending = appData.lifecycleStages.filter(stage => stage.status === 'pending').length; |
| |
| document.getElementById('completedCount').textContent = completed; |
| document.getElementById('inProgressCount').textContent = inProgress; |
| document.getElementById('pendingCount').textContent = pending; |
| } |