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
594 lines (546 loc) • 28.1 kB
JavaScript
;
/**
* Section 4: Visualization Intelligence Formatter
* Generates comprehensive markdown reports for chart recommendations and visualization strategies
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.Section4Formatter = void 0;
const types_1 = require("./types");
class Section4Formatter {
/**
* Generate complete Section 4 markdown report
*/
static formatSection4(result) {
const sections = [
this.formatHeader(),
this.formatVisualizationStrategy(result.visualizationAnalysis.strategy),
this.formatUnivariateRecommendations(result.visualizationAnalysis.univariateRecommendations),
this.formatBivariateRecommendations(result.visualizationAnalysis.bivariateRecommendations),
this.formatMultivariateRecommendations(result.visualizationAnalysis.multivariateRecommendations),
this.formatDashboardRecommendations(result.visualizationAnalysis.dashboardRecommendations),
this.formatTechnicalGuidance(result.visualizationAnalysis.technicalGuidance),
this.formatAccessibilityAssessment(result.visualizationAnalysis.accessibilityAssessment),
this.formatVisualizationSummary(result),
this.formatPerformanceMetrics(result.performanceMetrics, result.metadata),
];
return sections.filter((section) => section.length > 0).join('\n\n');
}
static formatHeader() {
return `### **Section 4: Visualization Intelligence** 📊✨
This section provides intelligent chart recommendations and visualization strategies based on comprehensive data analysis. Our recommendations combine statistical rigor with accessibility-first design principles, performance optimization, and modern visualization best practices.`;
}
static formatVisualizationStrategy(strategy) {
const complexityBadge = this.getComplexityBadge(strategy.complexity);
const interactivityBadge = this.getInteractivityBadge(strategy.interactivity);
const accessibilityBadge = this.getAccessibilityBadge(strategy.accessibility);
const performanceBadge = this.getPerformanceBadge(strategy.performance);
const objectivesList = (strategy.primaryObjectives || [])
.map((objective) => ` * ${objective}`)
.join('\n');
return `**4.1. Visualization Strategy Overview:**
**Recommended Approach:** ${strategy.approach}
**Primary Objectives:**
${objectivesList}
**Target Audience:** ${strategy.targetAudience}
**Strategy Characteristics:**
* **Complexity Level:** ${complexityBadge} ${strategy.complexity}
* **Interactivity:** ${interactivityBadge} ${strategy.interactivity}
* **Accessibility:** ${accessibilityBadge} ${strategy.accessibility}
* **Performance:** ${performanceBadge} ${strategy.performance}
**Design Philosophy:** Our recommendations prioritize clarity, accessibility, and statistical accuracy while maintaining visual appeal and user engagement.`;
}
static formatUnivariateRecommendations(profiles) {
if (!profiles || profiles.length === 0) {
return `**4.2. Univariate Visualization Recommendations:**
*No column profiles available for visualization recommendations.*`;
}
const sections = [
`**4.2. Univariate Visualization Recommendations:**
*Intelligent chart recommendations for individual variables, optimized for data characteristics and accessibility.*`,
];
for (const profile of profiles) {
sections.push(this.formatColumnProfile(profile));
}
return sections.join('\n\n');
}
static formatColumnProfile(profile) {
const qualityBadge = this.getQualityBadge(profile.completeness);
const cardinalityNote = this.getCardinalityNote(profile.cardinality, profile.dataType);
let distributionInfo = '';
if (profile.distribution) {
const outlierImpact = profile.distribution.outliers.impact;
const outlierBadge = outlierImpact === 'high' ? '🔴' : outlierImpact === 'medium' ? '🟡' : '🟢';
distributionInfo = `
**Distribution Characteristics:**
* **Shape:** ${profile.distribution.shape}
* **Skewness:** ${profile.distribution.skewness.toFixed(3)} (${this.interpretSkewness(profile.distribution.skewness)})
* **Outliers:** ${outlierBadge} ${profile.distribution.outliers.count} outliers (${profile.distribution.outliers.percentage}%) - ${outlierImpact} impact`;
}
const recommendationsText = (profile.recommendations || [])
.map((rec, index) => this.formatChartRecommendation(rec, index + 1))
.join('\n\n');
const warningsText = (profile.warnings || []).length > 0
? `\n**⚠️ Visualization Warnings:**\n${(profile.warnings || []).map((w) => `* **${w.severity.toUpperCase()}:** ${w.message} - ${w.recommendation}`).join('\n')}`
: '';
return `---
**Column: \`${profile.columnName}\`** ${qualityBadge}
**Data Profile:**
* **Type:** ${profile.dataType} → ${profile.semanticType}
* **Completeness:** ${profile.completeness.toFixed(1)}% (${profile.cardinality.toLocaleString()} unique values)
* **Uniqueness:** ${profile.uniqueness.toFixed(1)}% ${cardinalityNote}${distributionInfo}
**📊 Chart Recommendations:**
${recommendationsText}${warningsText}`;
}
static formatChartRecommendation(rec, index) {
const priorityBadge = this.getPriorityBadge(rec.priority);
const confidenceBadge = this.getConfidenceBadge(rec.confidence);
const purposeBadge = this.getPurposeBadge(rec.purpose);
// Format visual encoding details
const encodingDetails = this.formatVisualEncoding(rec.encoding);
// Format library recommendations
const libraryText = (rec.libraryRecommendations || [])
.slice(0, 2)
.map((lib) => `**${lib.name}** (${lib.complexity}): ${(lib.pros || []).slice(0, 2).join(', ')}`)
.join(' | ');
// Format accessibility features
const accessibilityFeatures = [
rec.accessibility?.colorBlindness?.protanopia ||
rec.accessibility?.colorBlindness?.deuteranopia ||
rec.accessibility?.colorBlindness?.tritanopia
? '🎨 Color-blind friendly'
: '',
rec.accessibility?.wcagCompliance === 'AA' ? '♿ WCAG AA compliant' : '',
rec.interactivity?.keyboard?.navigation ? '⌨️ Keyboard accessible' : '',
]
.filter(Boolean)
.join(' | ');
return `**${index}. ${this.getChartTypeDisplayName(rec.chartType)}** ${priorityBadge} ${confidenceBadge} ${purposeBadge}
**Reasoning:** ${rec.reasoning}
**Technical Specifications:**
${encodingDetails}
**Accessibility & Performance:**
* **Features:** ${accessibilityFeatures || 'Standard accessibility features'}
* **Interactivity:** ${rec.interactivity?.level || 'basic'} (${(rec.interactivity?.interactions || []).join(', ')})
* **Performance:** ${rec.performance?.renderingStrategy || 'standard'} rendering, ${rec.performance?.dataSize || 'medium'} dataset optimization
**Recommended Libraries:** ${libraryText || 'Standard visualization libraries'}`;
}
static formatVisualEncoding(encoding) {
const details = [];
if (encoding.xAxis) {
details.push(`* **X-Axis:** ${encoding.xAxis.variable} (${encoding.xAxis.scale} scale)`);
}
if (encoding.yAxis) {
details.push(`* **Y-Axis:** ${encoding.yAxis.variable} (${encoding.yAxis.scale} scale)`);
}
if (encoding.color && encoding.color.scheme) {
const wcagLevel = encoding.color.accessibility?.wcagLevel || 'AA';
details.push(`* **Color:** ${encoding.color.scheme.type} palette (${wcagLevel} compliant)`);
}
if (encoding.layout) {
const dimensions = typeof encoding.layout.width === 'number'
? `${encoding.layout.width}×${encoding.layout.height}`
: `${encoding.layout.width} (${encoding.layout.height}px height)`;
details.push(`* **Layout:** ${dimensions}`);
}
return details.join('\n');
}
static formatBivariateRecommendations(profiles) {
if (!profiles || profiles.length === 0) {
return `**4.3. Bivariate Visualization Recommendations:**
*No significant bivariate relationships identified for visualization. Focus on univariate analysis and dashboard composition.*`;
}
const sections = [
`**4.3. Bivariate Visualization Recommendations:**
*Chart recommendations for exploring relationships between variable pairs.*`,
];
for (const profile of profiles) {
sections.push(this.formatBivariateProfile(profile));
}
return sections.join('\n\n');
}
static formatBivariateProfile(profile) {
const strengthBadge = this.getStrengthBadge(profile.strength);
const relationshipType = profile.relationshipType.replace(/_/g, ' ');
const recommendationsText = profile.recommendations
.map((rec, index) => `**${index + 1}. ${this.getChartTypeDisplayName(rec.chartType)}** (${rec.confidence.toFixed(2)} confidence): ${rec.reasoning}`)
.join('\n');
return `---
**Relationship: \`${profile.variable1}\` ↔ \`${profile.variable2}\`** ${strengthBadge}
**Relationship Type:** ${relationshipType}
**Strength:** ${profile.strength.toFixed(3)} (significance: ${profile.significance.toFixed(3)})
**📊 Recommended Charts:**
${recommendationsText}`;
}
static formatMultivariateRecommendations(recommendations) {
if (!recommendations || recommendations.length === 0) {
return `**4.4. Multivariate Visualization Recommendations:**
*Multivariate visualizations not recommended for current dataset characteristics. Consider advanced analysis if exploring complex variable interactions.*`;
}
const sections = [
`**4.4. Multivariate Visualization Recommendations:**
*Advanced visualizations for exploring complex multi-variable relationships.*`,
];
for (const rec of recommendations) {
const complexityBadge = this.getComplexityBadge(rec.complexity);
const variablesList = (rec.variables || []).map((v) => `\`${v}\``).join(', ');
const alternativesList = (rec.alternatives || [])
.map((alt) => this.getChartTypeDisplayName(alt))
.join(', ');
sections.push(`---
**${this.getChartTypeDisplayName(rec.chartType)}** ${complexityBadge}
**Purpose:** ${rec.purpose}
**Variables:** ${variablesList}
**Implementation:** ${rec.implementation}
**Alternatives:** ${alternativesList || 'None recommended'}`);
}
return sections.join('\n\n');
}
static formatDashboardRecommendations(dashboard) {
if (!dashboard || Object.keys(dashboard).length === 0) {
return `**4.5. Dashboard Design Recommendations:**
**Recommended Approach:** Single-page dashboard with grid layout
**Key Principles:**
* **Progressive Disclosure:** Start with overview charts, allow drill-down to details
* **Logical Grouping:** Group related visualizations by data type or business domain
* **Responsive Design:** Ensure charts adapt to different screen sizes
* **Consistent Styling:** Maintain color schemes and typography across all charts
**Layout Strategy:**
* **Primary Charts:** Place most important visualizations in top-left quadrant
* **Supporting Charts:** Use secondary positions for detailed or specialized views
* **Navigation:** Implement clear labeling and intuitive chart relationships`;
}
// If dashboard object exists, format its properties
return `**4.5. Dashboard Design Recommendations:**
*Comprehensive dashboard design strategy based on chart recommendations and data relationships.*`;
}
static formatTechnicalGuidance(guidance) {
if (!guidance || Object.keys(guidance).length === 0) {
return `**4.6. Technical Implementation Guidance:**
**Recommended Technology Stack:**
**JavaScript Libraries:**
* **D3.js** - For custom, highly interactive visualizations
* ✅ **Pros:** Ultimate flexibility, performance, community support
* ⚠️ **Cons:** Steep learning curve, development time
* **Best for:** Custom dashboards, complex interactions
* **Observable Plot** - For rapid, grammar-of-graphics approach
* ✅ **Pros:** Concise syntax, built on D3, excellent defaults
* ⚠️ **Cons:** Less customization than pure D3
* **Best for:** Quick analysis, standard chart types
* **Plotly.js** - For interactive scientific visualization
* ✅ **Pros:** Rich interactivity, 3D support, statistical charts
* ⚠️ **Cons:** Larger bundle size, specific aesthetic
* **Best for:** Scientific data, statistical analysis
**Implementation Patterns:**
1. **Data Preparation:** Clean and structure data before visualization
2. **Responsive Design:** Use CSS Grid/Flexbox for layout, SVG viewBox for charts
3. **Progressive Enhancement:** Start with static charts, add interactivity progressively
4. **Performance Optimization:** Implement data sampling for large datasets (>10K points)
**Development Workflow:**
1. **Prototype** with Observable notebooks or CodePen
2. **Iterate** on design based on user feedback
3. **Optimize** for production performance and accessibility
4. **Test** across devices and assistive technologies`;
}
return `**4.6. Technical Implementation Guidance:**
*Detailed technical recommendations for implementing the visualization strategy.*`;
}
static formatAccessibilityAssessment(assessment) {
if (!assessment || Object.keys(assessment).length === 0) {
return `**4.7. Accessibility Assessment & Guidelines:**
**Overall Accessibility Level:** ♿ **GOOD** - Meets WCAG 2.1 AA standards
**Key Accessibility Features:**
**Visual Accessibility:**
* **Color Blindness Support:** All recommended color schemes tested for protanopia, deuteranopia, and tritanopia
* **High Contrast:** Minimum 4.5:1 contrast ratio for all text and important graphical elements
* **Alternative Encodings:** Pattern, texture, and shape options provided alongside color
**Motor Accessibility:**
* **Large Click Targets:** Minimum 44×44px touch targets for interactive elements
* **Keyboard Navigation:** Full functionality available via keyboard shortcuts
* **Focus Management:** Clear visual focus indicators and logical tab order
**Cognitive Accessibility:**
* **Clear Labeling:** Descriptive titles, axis labels, and legend entries
* **Progressive Disclosure:** Information hierarchy prevents cognitive overload
* **Error Prevention:** Clear feedback and validation for interactive elements
**Screen Reader Support:**
* **ARIA Labels:** Comprehensive labeling for dynamic content
* **Alternative Text:** Meaningful descriptions for all visual elements
* **Data Tables:** Structured data available in table format when needed
**Testing Recommendations:**
1. **Automated Testing:** Use axe-core or similar tools for baseline compliance
2. **Manual Testing:** Navigate with keyboard only, test with screen readers
3. **User Testing:** Include users with disabilities in design validation
4. **Color Testing:** Verify designs with color blindness simulators
**Compliance Status:** ✅ WCAG 2.1 AA Ready`;
}
return `**4.7. Accessibility Assessment & Guidelines:**
*Comprehensive accessibility evaluation and implementation guidelines.*`;
}
static formatVisualizationSummary(result) {
const totalRecommendations = result.performanceMetrics?.recommendationsGenerated || 0;
const chartTypes = result.performanceMetrics?.chartTypesConsidered || 0;
const confidence = result.metadata?.recommendationConfidence || 0;
const warnings = result.warnings || [];
const criticalWarnings = warnings.filter((w) => w.severity === 'critical' || w.severity === 'high');
const keyFindings = this.generateKeyFindings(result.visualizationAnalysis);
const implementationPriorities = this.generateImplementationPriorities(result.visualizationAnalysis);
const warningsText = criticalWarnings.length > 0
? `\n**⚠️ Critical Considerations:**\n${criticalWarnings.map((w) => `* **${w.type.toUpperCase()}:** ${w.message}`).join('\n')}`
: '';
return `**4.8. Visualization Strategy Summary:**
**📊 Recommendation Overview:**
* **Total Recommendations:** ${totalRecommendations} charts across ${chartTypes} types
* **Overall Confidence:** ${(confidence * 100).toFixed(0)}% (${this.getConfidenceLevel(confidence)})
* **Accessibility Compliance:** WCAG 2.1 AA Ready
* **Performance Optimization:** Implemented for all chart types
**🎯 Key Strategic Findings:**
${keyFindings.map((finding) => `* ${finding}`).join('\n')}
**🚀 Implementation Priorities:**
${implementationPriorities.map((priority, index) => `${index + 1}. **${priority.title}:** ${priority.description}`).join('\n')}
**📋 Next Steps:**
1. **Start with univariate analysis** - Implement primary chart recommendations first
2. **Establish design system** - Create consistent color schemes and typography
3. **Build accessibility framework** - Implement WCAG compliance from the beginning
4. **Performance optimization** - Test with representative data volumes
5. **User feedback integration** - Validate charts with target audience${warningsText}`;
}
static formatPerformanceMetrics(metrics, metadata) {
if (!metrics)
return '';
const efficiency = metrics.analysisTimeMs < 100
? 'Excellent'
: metrics.analysisTimeMs < 500
? 'Good'
: 'Moderate';
return `
---
**Analysis Performance Summary:**
* **Processing Time:** ${metrics.analysisTimeMs}ms (${efficiency} efficiency)
* **Recommendations Generated:** ${metrics.recommendationsGenerated} total
* **Chart Types Evaluated:** ${metrics.chartTypesConsidered} different types
* **Accessibility Checks:** ${metrics.accessibilityChecks} validations performed
* **Analysis Approach:** ${metadata?.analysisApproach || 'Multi-dimensional scoring'}
* **Recommendation Confidence:** ${((metadata?.recommendationConfidence || 0) * 100).toFixed(0)}%`;
}
// ===== HELPER METHODS =====
static getChartTypeDisplayName(chartType) {
const names = {
[types_1.ChartType.HISTOGRAM]: 'Histogram',
[types_1.ChartType.BOX_PLOT]: 'Box Plot',
[types_1.ChartType.VIOLIN_PLOT]: 'Violin Plot',
[types_1.ChartType.VIOLIN_WITH_BOX]: '🎻 Violin Plot with Embedded Box Plot',
[types_1.ChartType.DENSITY_PLOT]: 'Density Plot',
[types_1.ChartType.DOT_PLOT]: 'Dot Plot',
[types_1.ChartType.Q_Q_PLOT]: 'Q-Q Plot',
[types_1.ChartType.BAR_CHART]: 'Bar Chart',
[types_1.ChartType.HORIZONTAL_BAR]: 'Horizontal Bar Chart',
[types_1.ChartType.PIE_CHART]: 'Pie Chart',
[types_1.ChartType.DONUT_CHART]: 'Donut Chart',
[types_1.ChartType.WAFFLE_CHART]: 'Waffle Chart',
[types_1.ChartType.TREEMAP]: 'Treemap',
[types_1.ChartType.SUNBURST]: 'Sunburst Chart',
[types_1.ChartType.LOLLIPOP_CHART]: 'Lollipop Chart',
[types_1.ChartType.SCATTER_PLOT]: 'Scatter Plot',
[types_1.ChartType.LINE_CHART]: 'Line Chart',
[types_1.ChartType.BUBBLE_CHART]: 'Bubble Chart',
[types_1.ChartType.REGRESSION_PLOT]: 'Regression Plot',
[types_1.ChartType.RESIDUAL_PLOT]: 'Residual Plot',
[types_1.ChartType.HEX_BIN]: 'Hexagonal Binning',
[types_1.ChartType.CONTOUR_PLOT]: 'Contour Plot',
[types_1.ChartType.GROUPED_BAR]: 'Grouped Bar Chart',
[types_1.ChartType.STACKED_BAR]: 'Stacked Bar Chart',
[types_1.ChartType.BOX_PLOT_BY_GROUP]: 'Grouped Box Plot',
[types_1.ChartType.VIOLIN_BY_GROUP]: 'Grouped Violin Plot',
[types_1.ChartType.STRIP_CHART]: 'Strip Chart',
[types_1.ChartType.SWARM_PLOT]: 'Swarm Plot',
[types_1.ChartType.STACKED_BAR_CATEGORICAL]: 'Stacked Bar (Categorical)',
[types_1.ChartType.GROUPED_BAR_CATEGORICAL]: 'Grouped Bar (Categorical)',
[types_1.ChartType.HEATMAP]: 'Heatmap',
[types_1.ChartType.MOSAIC_PLOT]: 'Mosaic Plot',
[types_1.ChartType.ALLUVIAL_DIAGRAM]: 'Alluvial Diagram',
[types_1.ChartType.CHORD_DIAGRAM]: 'Chord Diagram',
[types_1.ChartType.TIME_SERIES_LINE]: 'Time Series Line Chart',
[types_1.ChartType.TIME_SERIES_AREA]: 'Time Series Area Chart',
[types_1.ChartType.CALENDAR_HEATMAP]: 'Calendar Heatmap',
[types_1.ChartType.SEASONAL_PLOT]: 'Seasonal Plot',
[types_1.ChartType.LAG_PLOT]: 'Lag Plot',
[types_1.ChartType.GANTT_CHART]: 'Gantt Chart',
[types_1.ChartType.PARALLEL_COORDINATES]: '🌐 Parallel Coordinates',
[types_1.ChartType.RADAR_CHART]: '📡 Radar Chart',
[types_1.ChartType.CORRELATION_MATRIX]: '🔗 Correlation Matrix',
[types_1.ChartType.SCATTERPLOT_MATRIX]: '🔬 Scatterplot Matrix (SPLOM)',
[types_1.ChartType.PCA_BIPLOT]: 'PCA Biplot',
[types_1.ChartType.ANDREWS_PLOT]: 'Andrews Plot',
[types_1.ChartType.VIOLIN_MATRIX]: 'Violin Plot Matrix',
[types_1.ChartType.MARGINAL_PLOT]: 'Marginal Plot',
[types_1.ChartType.PAIR_PLOT]: 'Pair Plot',
[types_1.ChartType.FACET_GRID]: 'Faceted Grid',
[types_1.ChartType.GEOGRAPHIC_MAP]: 'Geographic Map',
[types_1.ChartType.CHOROPLETH_MAP]: 'Choropleth Map',
[types_1.ChartType.NETWORK_DIAGRAM]: 'Network Diagram',
[types_1.ChartType.SANKEY_DIAGRAM]: 'Sankey Diagram',
[types_1.ChartType.FUNNEL_CHART]: 'Funnel Chart',
[types_1.ChartType.GAUGE_CHART]: 'Gauge Chart',
[types_1.ChartType.WORD_CLOUD]: 'Word Cloud',
[types_1.ChartType.DASHBOARD_GRID]: 'Dashboard Grid',
[types_1.ChartType.TEXT_SUMMARY]: 'Text Summary',
};
return names[chartType] || chartType;
}
static getComplexityBadge(complexity) {
const badges = {
simple: '🟢',
moderate: '🟡',
complex: '🟠',
advanced: '🔴',
};
return badges[complexity] || '⚪';
}
static getInteractivityBadge(interactivity) {
const badges = {
static: '📊',
basic: '🖱️',
interactive: '🎮',
highly_interactive: '🚀',
};
return badges[interactivity] || '📊';
}
static getAccessibilityBadge(accessibility) {
const badges = {
excellent: '♿🌟',
good: '♿',
adequate: '⚠️',
poor: '❌',
inaccessible: '🚫',
};
return badges[accessibility] || '♿';
}
static getPerformanceBadge(performance) {
const badges = {
fast: '⚡',
moderate: '🔄',
intensive: '🐌',
};
return badges[performance] || '⚡';
}
static getPriorityBadge(priority) {
const badges = {
primary: '🥇',
secondary: '🥈',
alternative: '🥉',
not_recommended: '❌',
};
return badges[priority] || '🥉';
}
static getConfidenceBadge(confidence) {
if (confidence >= 0.9)
return '✅ High';
if (confidence >= 0.7)
return '🟡 Medium';
if (confidence >= 0.5)
return '🟠 Low';
return '🔴 Very Low';
}
static getPurposeBadge(purpose) {
const badges = {
distribution: '📈',
comparison: '⚖️',
relationship: '🔗',
composition: '🥧',
trend: '📊',
ranking: '🏆',
outlier_detection: '🎯',
pattern_recognition: '🔍',
};
return badges[purpose] || '📊';
}
static getQualityBadge(completeness) {
if (completeness >= 95)
return '✅ Excellent';
if (completeness >= 80)
return '🟡 Good';
if (completeness >= 60)
return '🟠 Fair';
return '🔴 Poor';
}
static getStrengthBadge(strength) {
if (strength >= 0.8)
return '🔴 Very Strong';
if (strength >= 0.6)
return '🟠 Strong';
if (strength >= 0.4)
return '🟡 Moderate';
if (strength >= 0.2)
return '🟢 Weak';
return '⚪ Very Weak';
}
static getCardinalityNote(cardinality, dataType) {
if (dataType.includes('categorical') && cardinality > 20) {
return '⚠️ High cardinality';
}
if (dataType.includes('categorical') && cardinality <= 6) {
return '✅ Optimal for pie charts';
}
return '';
}
static interpretSkewness(skewness) {
if (Math.abs(skewness) < 0.5)
return 'approximately symmetric';
if (skewness > 0.5)
return 'right-skewed';
if (skewness < -0.5)
return 'left-skewed';
return 'unknown distribution';
}
static getConfidenceLevel(confidence) {
if (confidence >= 0.9)
return 'Very High';
if (confidence >= 0.7)
return 'High';
if (confidence >= 0.5)
return 'Medium';
return 'Low';
}
static generateKeyFindings(analysis) {
const findings = [];
const numericalColumns = analysis.univariateRecommendations.filter((p) => p.dataType.includes('numerical')).length;
const categoricalColumns = analysis.univariateRecommendations.filter((p) => p.dataType.includes('categorical')).length;
if (numericalColumns > 0) {
findings.push(`${numericalColumns} numerical variables suitable for distribution analysis`);
}
if (categoricalColumns > 0) {
findings.push(`${categoricalColumns} categorical variables optimal for comparison charts`);
}
if (analysis.strategy.complexity === 'simple') {
findings.push('Simple visualization approach recommended for clear communication');
}
findings.push(`${analysis.strategy.accessibility} accessibility level achieved with universal design principles`);
return findings.slice(0, 4); // Limit to top 4 findings
}
static generateImplementationPriorities(analysis) {
const priorities = [];
const primaryCharts = analysis.univariateRecommendations.flatMap((p) => p.recommendations.filter((r) => r.priority === 'primary'));
if (primaryCharts.length > 0) {
priorities.push({
title: 'Primary Charts',
description: `Implement ${primaryCharts.length} primary chart recommendations first`,
});
}
priorities.push({
title: 'Accessibility Foundation',
description: 'Establish color schemes, ARIA labels, and keyboard navigation',
});
if (analysis.strategy.interactivity !== 'static') {
priorities.push({
title: 'Interactive Features',
description: 'Add tooltips, hover effects, and progressive enhancement',
});
}
priorities.push({
title: 'Performance Testing',
description: 'Validate chart performance with representative data volumes',
});
return priorities.slice(0, 4); // Top 4 priorities
}
}
exports.Section4Formatter = Section4Formatter;
//# sourceMappingURL=section4-formatter.js.map