UNPKG

datapilot-cli

Version:

Enterprise-grade streaming multi-format data analysis with comprehensive statistical insights and intelligent relationship detection - supports CSV, JSON, Excel, TSV, Parquet - memory-efficient, cross-platform

674 lines (649 loc) 30.7 kB
"use strict"; /** * Section 5: Data Engineering & Structural Insights Formatter * Formats engineering analysis results into comprehensive markdown reports */ Object.defineProperty(exports, "__esModule", { value: true }); exports.Section5Formatter = void 0; class Section5Formatter { /** * Format Section 5 results into comprehensive markdown report */ static formatMarkdown(result) { const { engineeringAnalysis, warnings, performanceMetrics, metadata } = result; const sections = [ this.formatHeader(), this.formatExecutiveSummary(engineeringAnalysis, metadata), this.formatSchemaAnalysis(engineeringAnalysis.schemaAnalysis), this.formatStructuralIntegrity(engineeringAnalysis.structuralIntegrity), this.formatTransformationPipeline(engineeringAnalysis.transformationPipeline), this.formatScalabilityAssessment(engineeringAnalysis.scalabilityAssessment), this.formatDataGovernance(engineeringAnalysis.dataGovernance), this.formatMLReadiness(engineeringAnalysis.mlReadiness), this.formatKnowledgeBase(engineeringAnalysis.knowledgeBaseOutput), this.formatWarnings(warnings), this.formatPerformanceMetrics(performanceMetrics), ]; return sections.filter(Boolean).join('\n\n'); } static formatHeader() { return `# Section 5: Data Engineering & Structural Insights 🏛️🛠️ This section evaluates the dataset from a data engineering perspective, focusing on schema optimization, transformation pipelines, scalability considerations, and machine learning readiness. ---`; } static formatExecutiveSummary(_analysis, metadata) { return `## 5.1 Executive Summary **Analysis Overview:** - **Approach:** ${metadata.analysisApproach} - **Source Dataset Size:** ${metadata.sourceDatasetSize.toLocaleString()} rows - **Engineered Features:** ${metadata.engineeredFeatureCount} features designed - **ML Readiness Score:** ${metadata.mlReadinessScore}% **Key Engineering Insights:** - Schema optimization recommendations generated for improved performance - Comprehensive transformation pipeline designed for ML preparation - Data integrity analysis completed with structural recommendations - Scalability pathway identified for future growth`; } static formatSchemaAnalysis(schemaAnalysis) { const sections = [ '## 5.2 Schema Analysis & Optimization', '', '### 5.2.1 Current Schema Profile', this.formatCurrentSchema(schemaAnalysis.currentSchema), '', '### 5.2.2 Optimized Schema Recommendations', this.formatOptimizedSchema(schemaAnalysis.optimizedSchema), '', '### 5.2.3 Data Type Conversions', this.formatDataTypeConversions(schemaAnalysis.dataTypeConversions), '', '### 5.2.4 Character Encoding & Collation', this.formatEncodingRecommendations(schemaAnalysis.characterEncodingRecommendations), ]; if (schemaAnalysis.normalizationInsights.redundancyDetected.length > 0) { sections.push('', '### 5.2.5 Normalization Insights', this.formatNormalizationInsights(schemaAnalysis.normalizationInsights)); } return sections.join('\n'); } static formatCurrentSchema(currentSchema) { if (!currentSchema.columns || currentSchema.columns.length === 0) { return 'No current schema information available.'; } const headers = [ 'Column Name', 'Detected Type', 'Semantic Type', 'Nullability (%)', 'Uniqueness (%)', 'Sample Values', ]; const rows = currentSchema.columns.map((col) => [ col.originalName, col.detectedType, col.inferredSemanticType, `${col.nullabilityPercentage.toFixed(1)}%`, `${col.uniquenessPercentage.toFixed(1)}%`, col.sampleValues.slice(0, 2).join(', ') || 'N/A', ]); return (this.formatTable(headers, rows) + `\n\n**Dataset Metrics:** - **Estimated Rows:** ${currentSchema.estimatedRowCount.toLocaleString()} - **Estimated Size:** ${(currentSchema.estimatedSizeBytes / (1024 * 1024)).toFixed(1)} MB - **Detected Encoding:** ${currentSchema.detectedEncoding}`); } static formatOptimizedSchema(optimizedSchema) { let output = `**Target System:** ${optimizedSchema.targetSystem}\n\n`; if (optimizedSchema.columns && optimizedSchema.columns.length > 0) { output += '**Optimized Column Definitions:**\n\n'; const headers = [ 'Original Name', 'Optimized Name', 'Recommended Type', 'Constraints', 'Reasoning', ]; const rows = optimizedSchema.columns.map((col) => [ col.originalName, col.optimizedName, col.recommendedType, col.constraints.join(', ') || 'None', col.reasoning, ]); output += this.formatTable(headers, rows); } if (optimizedSchema.ddlStatement) { output += '\n\n**Generated DDL Statement:**\n\n```sql\n' + optimizedSchema.ddlStatement + '\n```'; } if (optimizedSchema.indexes && optimizedSchema.indexes.length > 0) { output += '\n\n**Recommended Indexes:**\n\n'; optimizedSchema.indexes.forEach((index, i) => { output += `${i + 1}. **${index.indexType.toUpperCase()} INDEX** on \`${index.columns.join(', ')}\`\n`; output += ` - **Purpose:** ${index.purpose}\n`; output += ` - **Expected Impact:** ${index.expectedImpact}\n\n`; }); } return output; } static formatDataTypeConversions(conversions) { if (!conversions || conversions.length === 0) { return 'No data type conversions required.'; } let output = 'The following data type conversions are recommended:\n\n'; conversions.forEach((conversion, i) => { output += `**${i + 1}. ${conversion.columnName}** (${conversion.currentType}${conversion.recommendedType})\n`; output += `- **Conversion Logic:** \`${conversion.conversionLogic}\`\n`; output += `- **Reasoning:** ${conversion.reasoning}\n`; output += `- **Risk Level:** ${conversion.riskLevel.toUpperCase()}\n`; output += `- **Example:** ${conversion.exampleTransformation}\n\n`; }); return output; } static formatEncodingRecommendations(encoding) { return `**Current Encoding:** ${encoding.detectedEncoding} **Recommended Encoding:** ${encoding.recommendedEncoding} **Collation Recommendation:** ${encoding.collationRecommendation} ${encoding.characterSetIssues.length > 0 ? `**Character Set Issues Detected:**\n${encoding.characterSetIssues.map((issue) => `- ${issue}`).join('\n')}` : '**No character set issues detected.**'}`; } static formatNormalizationInsights(insights) { let output = ''; if (insights.redundancyDetected.length > 0) { output += '**Redundancy Detected:**\n\n'; insights.redundancyDetected.forEach((redundancy, i) => { output += `${i + 1}. **${redundancy.redundancyType}**\n`; output += ` - **Affected Columns:** ${redundancy.affectedColumns.join(', ')}\n`; output += ` - **Description:** ${redundancy.description}\n`; output += ` - **Recommended Action:** ${redundancy.recommendedAction}\n\n`; }); } if (insights.normalizationOpportunities.length > 0) { output += '**Normalization Opportunities:**\n\n'; insights.normalizationOpportunities.forEach((opportunity, i) => { output += `${i + 1}. **${opportunity.opportunity}** (${opportunity.normalizedForm})\n`; output += ` - **Affected Columns:** ${opportunity.affectedColumns.join(', ')}\n`; output += ` - **Benefits:** ${opportunity.benefits.join(', ')}\n\n`; }); } return output || 'No normalization insights available.'; } static formatStructuralIntegrity(integrity) { const sections = [ '## 5.3 Structural Integrity Analysis', '', '### 5.3.1 Primary Key Candidates', this.formatPrimaryKeyCandidates(integrity.primaryKeyCandidates), '', '### 5.3.2 Foreign Key Relationships', this.formatForeignKeyRelationships(integrity.foreignKeyRelationships), '', '### 5.3.3 Data Integrity Score', this.formatDataIntegrityScore(integrity.dataIntegrityScore), ]; if (integrity.orphanedRecords && integrity.orphanedRecords.length > 0) { sections.push('', '### 5.3.4 Orphaned Records Analysis', this.formatOrphanedRecords(integrity.orphanedRecords)); } return sections.join('\n'); } static formatPrimaryKeyCandidates(candidates) { if (!candidates || candidates.length === 0) { return 'No strong primary key candidates identified.'; } let output = '**Primary Key Candidate Analysis:**\n\n'; const headers = [ 'Column Name', 'Uniqueness', 'Completeness', 'Stability', 'Confidence', 'Reasoning', ]; const rows = candidates.map((candidate) => [ candidate.columnName, `${candidate.uniqueness.toFixed(1)}%`, `${candidate.completeness.toFixed(1)}%`, `${candidate.stability.toFixed(1)}%`, candidate.confidence.toUpperCase(), candidate.reasoning, ]); output += this.formatTable(headers, rows); // Highlight top candidate if (candidates.length > 0) { const topCandidate = candidates[0]; output += `\n\n**Recommended Primary Key:** \`${topCandidate.columnName}\` (${topCandidate.confidence} confidence)`; } return output; } static formatForeignKeyRelationships(relationships) { if (!relationships || relationships.length === 0) { return 'No foreign key relationships inferred.'; } let output = '**Inferred Foreign Key Relationships:**\n\n'; relationships.forEach((rel, i) => { output += `**${i + 1}. ${rel.columnName}**\n`; output += `- **References:** ${rel.referencedTable}.${rel.referencedColumn}\n`; output += `- **Cardinality:** ${rel.cardinality}\n`; output += `- **Confidence:** ${rel.confidence.toUpperCase()}\n`; output += `- **Integrity Violations:** ${rel.integrityViolations}\n`; output += `- **Action:** ${rel.actionRecommendation}\n\n`; }); return output; } static formatDataIntegrityScore(score) { return `**Overall Data Integrity Score:** ${score.score}/100 (${score.interpretation}) **Contributing Factors:** ${score.factors .map((factor) => `- **${factor.factor}** (${factor.impact}, weight: ${factor.weight}): ${factor.description}`) .join('\n')}`; } static formatOrphanedRecords(orphanedRecords) { let output = '**Orphaned Records Detected:**\n\n'; orphanedRecords.forEach((record, i) => { output += `**${i + 1}. ${record.relationshipDescription}**\n`; output += `- **Orphaned Count:** ${record.orphanedCount} (${record.orphanedPercentage.toFixed(1)}%)\n`; output += `- **Impact:** ${record.impactAssessment}\n`; output += `- **Resolution:** ${record.resolutionStrategy}\n\n`; }); return output; } static formatTransformationPipeline(pipeline) { const sections = [ '## 5.4 Data Transformation Pipeline', '', '### 5.4.1 Column Standardization', this.formatColumnStandardization(pipeline.columnStandardization), '', '### 5.4.2 Missing Value Strategy', this.formatMissingValueStrategy(pipeline.missingValueStrategy), '', '### 5.4.3 Outlier Treatment', this.formatOutlierTreatment(pipeline.outlierTreatment), '', '### 5.4.4 Categorical Encoding', this.formatCategoricalEncoding(pipeline.categoricalEncoding), ]; if (pipeline.numericalTransformations.length > 0) { sections.push('', '### 5.4.5 Numerical Transformations', this.formatNumericalTransformations(pipeline.numericalTransformations)); } if (pipeline.dateTimeFeatureEngineering.length > 0) { sections.push('', '### 5.4.6 DateTime Feature Engineering', this.formatDateTimeEngineering(pipeline.dateTimeFeatureEngineering)); } if (pipeline.textProcessingPipeline.length > 0) { sections.push('', '### 5.4.7 Text Processing Pipeline', this.formatTextProcessing(pipeline.textProcessingPipeline)); } return sections.join('\n'); } static formatColumnStandardization(standardization) { if (!standardization || standardization.length === 0) { return 'No column standardization needed.'; } const headers = ['Original Name', 'Standardized Name', 'Convention', 'Reasoning']; const rows = standardization.map((std) => [ std.originalName, std.standardizedName, std.namingConvention, std.reasoning, ]); return this.formatTable(headers, rows); } static formatMissingValueStrategy(strategies) { if (!strategies || strategies.length === 0) { return 'No missing value handling required.'; } let output = '**Missing Value Handling Strategies:**\n\n'; strategies.forEach((strategy, i) => { output += `**${i + 1}. ${strategy.columnName}** (${strategy.strategy.toUpperCase()})\n`; output += `- **Parameters:** ${JSON.stringify(strategy.parameters)}\n`; output += `- **Flag Column:** \`${strategy.flagColumn}\`\n`; output += `- **Reasoning:** ${strategy.reasoning}\n`; output += `- **Impact:** ${strategy.impact}\n\n`; }); return output; } static formatOutlierTreatment(treatments) { if (!treatments || treatments.length === 0) { return 'No outlier treatment required.'; } let output = '**Outlier Treatment Strategies:**\n\n'; treatments.forEach((treatment, i) => { output += `**${i + 1}. ${treatment.columnName}** (${treatment.treatmentMethod.toUpperCase()})\n`; output += `- **Detection Method:** ${treatment.detectionMethod}\n`; output += `- **Parameters:** ${JSON.stringify(treatment.parameters)}\n`; output += `- **Flag Column:** \`${treatment.flagColumn}\`\n`; output += `- **Reasoning:** ${treatment.reasoning}\n`; output += `- **Expected Impact:** ${treatment.expectedImpact}\n\n`; }); return output; } static formatCategoricalEncoding(encodings) { if (!encodings || encodings.length === 0) { return 'No categorical encoding required.'; } let output = '**Categorical Encoding Strategies:**\n\n'; encodings.forEach((encoding, i) => { output += `**${i + 1}. ${encoding.columnName}** (${encoding.encodingMethod.toUpperCase()})\n`; output += `- **Parameters:** ${JSON.stringify(encoding.parameters)}\n`; output += `- **Resulting Columns:** ${encoding.resultingColumns.join(', ')}\n`; output += `- **Reasoning:** ${encoding.reasoning}\n`; if (encoding.considerations.length > 0) { output += `- **Considerations:** ${encoding.considerations.join(', ')}\n`; } output += '\n'; }); return output; } static formatNumericalTransformations(transformations) { let output = '**Numerical Transformation Strategies:**\n\n'; transformations.forEach((transform, i) => { output += `**${i + 1}. ${transform.columnName}**\n`; output += `- **Transformations:**\n`; transform.transformations.forEach((t) => { output += ` - ${t.transformation}: ${t.purpose} → \`${t.resultingColumnName}\`\n`; }); output += `- **Reasoning:** ${transform.reasoning}\n`; output += `- **ML Considerations:** ${transform.mlConsiderations.join(', ')}\n\n`; }); return output; } static formatDateTimeEngineering(engineering) { let output = '**DateTime Feature Engineering Strategies:**\n\n'; engineering.forEach((eng, i) => { output += `**${i + 1}. ${eng.columnName}**\n`; output += `- **Extracted Features:**\n`; eng.extractedFeatures.forEach((feature) => { output += ` - ${feature.featureName}: ${feature.purpose}\n`; }); if (eng.calculatedFeatures.length > 0) { output += `- **Calculated Features:**\n`; eng.calculatedFeatures.forEach((feature) => { output += ` - ${feature.featureName}: ${feature.purpose}\n`; }); } output += `- **Reasoning:** ${eng.reasoning}\n\n`; }); return output; } static formatTextProcessing(processing) { let output = '**Text Processing Pipeline:**\n\n'; processing.forEach((proc, i) => { output += `**${i + 1}. ${proc.columnName}**\n`; output += `- **Cleaning Steps:**\n`; proc.cleaningSteps.forEach((step) => { output += ` - ${step.step}: ${step.description}\n`; }); output += `- **Vectorization:** ${proc.vectorizationMethod.toUpperCase()}\n`; output += `- **Resulting Features:** ${proc.resultingFeatureCount}\n`; if (proc.considerations.length > 0) { output += `- **Considerations:** ${proc.considerations.join(', ')}\n`; } output += '\n'; }); return output; } static formatScalabilityAssessment(scalability) { return `## 5.5 Scalability Assessment ### 5.5.1 Current Metrics - **Disk Size:** ${scalability.currentMetrics.diskSizeMB} MB - **In-Memory Size:** ${scalability.currentMetrics.inMemorySizeMB} MB - **Row Count:** ${scalability.currentMetrics.rowCount.toLocaleString()} - **Column Count:** ${scalability.currentMetrics.columnCount} - **Estimated Growth Rate:** ${scalability.currentMetrics.estimatedGrowthRate}%/year ### 5.5.2 Scalability Analysis **Current Capability:** ${scalability.scalabilityAnalysis.currentCapability} ${this.formatTechnologyRecommendations(scalability.scalabilityAnalysis.technologyRecommendations)} ${this.formatPerformanceOptimizations(scalability.performanceOptimizations)}`; } static formatTechnologyRecommendations(recommendations) { if (!recommendations || recommendations.length === 0) { return ''; } let output = '**Technology Recommendations:**\n\n'; recommendations.forEach((rec, i) => { output += `**${i + 1}. ${rec.technology}** (${rec.implementationComplexity} complexity)\n`; output += `- **Use Case:** ${rec.useCase}\n`; output += `- **Benefits:** ${rec.benefits.join(', ')}\n`; output += `- **Considerations:** ${rec.considerations.join(', ')}\n\n`; }); return output; } static formatPerformanceOptimizations(optimizations) { if (!optimizations || optimizations.length === 0) { return ''; } let output = '**Performance Optimization Recommendations:**\n\n'; optimizations.forEach((opt, i) => { output += `**${i + 1}. ${opt.area}** (${opt.implementationEffort} effort)\n`; output += `- **Current Issue:** ${opt.currentIssue}\n`; output += `- **Recommendation:** ${opt.recommendation}\n`; output += `- **Expected Improvement:** ${opt.expectedImprovement}\n\n`; }); return output; } static formatDataGovernance(governance) { return `## 5.6 Data Governance Considerations ### 5.6.1 Data Sensitivity Classification ${this.formatSensitivityClassification(governance.sensitivityClassification)} ### 5.6.2 Data Freshness Analysis ${this.formatDataFreshnessAnalysis(governance.dataFreshnessAnalysis)} ### 5.6.3 Compliance Considerations ${this.formatComplianceConsiderations(governance.complianceConsiderations)}`; } static formatSensitivityClassification(classifications) { if (!classifications || classifications.length === 0) { return 'No sensitive data classifications identified.'; } const headers = ['Column', 'Sensitivity Level', 'Category', 'Protection Recommendations']; const rows = classifications.map((cls) => [ cls.columnName, cls.sensitivityLevel.toUpperCase(), cls.dataCategory, cls.protectionRecommendations.join(', '), ]); return this.formatTable(headers, rows); } static formatDataFreshnessAnalysis(freshness) { return `**Freshness Score:** ${freshness.freshnessScore}/100 **Last Update Detected:** ${freshness.lastUpdateDetected || 'Unknown'} **Update Frequency Estimate:** ${freshness.updateFrequencyEstimate} **Implications:** ${freshness.implications.map((imp) => `- ${imp}`).join('\n')} **Recommendations:** ${freshness.recommendations.map((rec) => `- ${rec}`).join('\n')}`; } static formatComplianceConsiderations(considerations) { if (!considerations || considerations.length === 0) { return 'No specific compliance regulations identified.'; } let output = ''; considerations.forEach((cons, i) => { output += `**${i + 1}. ${cons.regulation}**\n`; output += `- **Applicable Columns:** ${cons.applicableColumns.join(', ')}\n`; output += `- **Requirements:** ${cons.requirements.join(', ')}\n`; output += `- **Recommendations:** ${cons.recommendations.join(', ')}\n\n`; }); return output; } static formatMLReadiness(mlReadiness) { return `## 5.7 Machine Learning Readiness Assessment ### 5.7.1 Overall ML Readiness Score: ${mlReadiness.overallScore}/100 ### 5.7.2 Enhancing Factors ${this.formatMLEnhancingFactors(mlReadiness.enhancingFactors)} ### 5.7.3 Remaining Challenges ${this.formatMLChallenges(mlReadiness.remainingChallenges)} ### 5.7.4 Feature Preparation Matrix ${this.formatFeaturePreparationMatrix(mlReadiness.featurePreparationMatrix)} ### 5.7.5 Modeling Considerations ${this.formatModelingConsiderations(mlReadiness.modelingConsiderations)}`; } static formatMLEnhancingFactors(factors) { if (!factors || factors.length === 0) { return 'No specific enhancing factors identified.'; } let output = ''; factors.forEach((factor, i) => { output += `**${i + 1}. ${factor.factor}** (${factor.impact.toUpperCase()} impact)\n`; output += ` ${factor.description}\n\n`; }); return output; } static formatMLChallenges(challenges) { if (!challenges || challenges.length === 0) { return 'No major ML challenges identified.'; } let output = ''; challenges.forEach((challenge, i) => { output += `**${i + 1}. ${challenge.challenge}** (${challenge.severity.toUpperCase()} severity)\n`; output += `- **Impact:** ${challenge.impact}\n`; output += `- **Mitigation:** ${challenge.mitigationStrategy}\n`; output += `- **Estimated Effort:** ${challenge.estimatedEffort}\n\n`; }); return output; } static formatFeaturePreparationMatrix(matrix) { if (!matrix || matrix.length === 0) { return 'No feature preparation matrix available.'; } const headers = [ 'ML Feature Name', 'Original Column', 'Final Type', 'Key Issues', 'Engineering Steps', 'ML Feature Type', ]; const rows = matrix.slice(0, 20).map((entry) => [ // Limit to first 20 for readability entry.featureName, entry.originalColumn, entry.finalDataType, entry.keyIssues.join(', ') || 'None', entry.engineeringSteps.join(', ') || 'None', entry.finalMLFeatureType, ]); let output = this.formatTable(headers, rows); if (matrix.length > 20) { output += `\n\n*Note: Showing first 20 features. Total features: ${matrix.length}*`; } return output; } static formatModelingConsiderations(considerations) { if (!considerations || considerations.length === 0) { return 'No specific modeling considerations identified.'; } let output = ''; considerations.forEach((cons, i) => { output += `**${i + 1}. ${cons.aspect}**\n`; output += `- **Consideration:** ${cons.consideration}\n`; output += `- **Impact:** ${cons.impact}\n`; output += `- **Recommendations:** ${cons.recommendations.join(', ')}\n\n`; }); return output; } static formatKnowledgeBase(knowledgeBase) { return `## 5.8 Knowledge Base Output ### 5.8.1 Dataset Profile Summary ${this.formatDatasetProfile(knowledgeBase.datasetProfile)} ### 5.8.2 Schema Recommendations Summary ${this.formatSchemaRecommendationsSummary(knowledgeBase.schemaRecommendations)} ### 5.8.3 Key Transformations Summary ${this.formatKeyTransformationsSummary(knowledgeBase.keyTransformations)}`; } static formatDatasetProfile(profile) { return `**Dataset:** ${profile.fileName} **Analysis Date:** ${new Date(profile.analysisDate).toLocaleDateString()} **Total Rows:** ${profile.totalRows.toLocaleString()} **Original Columns:** ${profile.totalColumnsOriginal} **Engineered ML Features:** ${profile.totalColumnsEngineeredForML} **Technical Debt:** ${profile.estimatedTechnicalDebtHours} hours **ML Readiness Score:** ${profile.mlReadinessScore}/100`; } static formatSchemaRecommendationsSummary(recommendations) { if (!recommendations || recommendations.length === 0) { return 'No schema recommendations available.'; } const headers = [ 'Original Column', 'Target Column', 'Recommended Type', 'Constraints', 'Key Transformations', ]; const rows = recommendations .slice(0, 15) .map((rec) => [ rec.columnNameOriginal, rec.columnNameTarget, rec.recommendedType, rec.constraints.join(', ') || 'None', rec.transformations.join(', ') || 'None', ]); let output = this.formatTable(headers, rows); if (recommendations.length > 15) { output += `\n\n*Note: Showing first 15 recommendations. Total: ${recommendations.length}*`; } return output; } static formatKeyTransformationsSummary(transformations) { if (!transformations || transformations.length === 0) { return 'No key transformations identified.'; } let output = ''; transformations.forEach((transform, i) => { output += `**${i + 1}. ${transform.featureGroup}**\n`; output += `- **Steps:** ${transform.steps.join(', ')}\n`; output += `- **Impact:** ${transform.impact}\n\n`; }); return output; } static formatWarnings(warnings) { if (!warnings || warnings.length === 0) { return ''; } let output = '## ⚠️ Engineering Warnings\n\n'; const groupedWarnings = warnings.reduce((groups, warning) => { const category = warning.category; if (!groups[category]) groups[category] = []; groups[category].push(warning); return groups; }, {}); Object.entries(groupedWarnings).forEach(([category, categoryWarnings]) => { output += `### ${category.charAt(0).toUpperCase() + category.slice(1)} Warnings\n\n`; categoryWarnings.forEach((warning) => { const icon = warning.severity === 'critical' ? '🔴' : warning.severity === 'high' ? '🟠' : warning.severity === 'medium' ? '🟡' : '🔵'; output += `${icon} **${warning.severity.toUpperCase()}:** ${warning.message}\n`; output += ` - **Impact:** ${warning.impact}\n`; output += ` - **Suggestion:** ${warning.suggestion}\n\n`; }); }); return output; } static formatPerformanceMetrics(metrics) { return `## 📊 Engineering Analysis Performance **Analysis Completed in:** ${metrics.analysisTimeMs.toLocaleString()}ms **Transformations Evaluated:** ${metrics.transformationsEvaluated} **Schema Recommendations Generated:** ${metrics.schemaRecommendationsGenerated} **ML Features Designed:** ${metrics.mlFeaturesDesigned} ---`; } static formatTable(headers, rows) { if (!headers.length || !rows.length) return ''; const maxWidths = headers.map((header, i) => Math.max(header.length, ...rows.map((row) => (row[i] || '').toString().length))); const headerRow = '| ' + headers.map((header, i) => header.padEnd(maxWidths[i])).join(' | ') + ' |'; const separatorRow = '| ' + maxWidths.map((width) => '-'.repeat(width)).join(' | ') + ' |'; const dataRows = rows.map((row) => '| ' + row.map((cell, i) => (cell || '').toString().padEnd(maxWidths[i])).join(' | ') + ' |'); return [headerRow, separatorRow, ...dataRows].join('\n'); } } exports.Section5Formatter = Section5Formatter; //# sourceMappingURL=section5-formatter.js.map