locate-the-news / frontend / src / utils / sentimentColors.js
sentimentColors.js
Raw
/**
 * Sentiment-based color mapping utilities
 * Maps sentiment scores (-1 to 1) to visual colors
 */

// Predefined color scales
export const SENTIMENT_COLORS = {
    NEGATIVE: '#ff3366',    // Red for negative/critical news
    NEUTRAL: '#00d9ff',     // Cyan for neutral news
    POSITIVE: '#00ff88'     // Green for positive news
};

/**
 * Convert sentiment score to RGB color
 * @param {number} score - Sentiment score from -1 (negative) to 1 (positive)
 * @returns {string} RGB color string
 */
export const sentimentToColor = (score) => {
    if (score === null || score === undefined) {
        return SENTIMENT_COLORS.NEUTRAL;
    }

    if (score < -0.3) {
        return SENTIMENT_COLORS.NEGATIVE;
    } else if (score > 0.3) {
        return SENTIMENT_COLORS.POSITIVE;
    } else {
        return SENTIMENT_COLORS.NEUTRAL;
    }
};

/**
 * Get gradient color for sentiment score
 * @param {number} score - Sentiment score from -1 to 1
 * @returns {string} Gradient CSS string
 */
export const sentimentToGradient = (score) => {
    const color = sentimentToColor(score);
    return `radial-gradient(circle, ${color}cc, ${color}66)`;
};

/**
 * Calculate sentiment intensity (for glow effect)
 * @param {number} score - Sentiment score
 * @returns {number} Intensity from 0 to 1
 */
export const sentimentIntensity = (score) => {
    return Math.abs(score || 0);
};

/**
 * Get cluster color based on sentiment ratio
 * @param {number} negativeRatio - Ratio of negative news (0 to 1)
 * @returns {string} RGB color string
 */
export const clusterSentimentColor = (negativeRatio) => {
    if (negativeRatio > 0.6) {
        return SENTIMENT_COLORS.NEGATIVE;
    } else if (negativeRatio < 0.3) {
        return SENTIMENT_COLORS.POSITIVE;
    } else {
        return SENTIMENT_COLORS.NEUTRAL;
    }
};

/**
 * Generate heatmap color based on crisis intensity
 * @param {number} intensity - Crisis intensity (0 to 1)
 * @returns {string} RGBA color string with opacity
 */
export const crisisHeatmapColor = (intensity) => {
    const red = Math.floor(255 * intensity);
    const green = Math.floor(255 * (1 - intensity));
    const blue = 102;
    const alpha = 0.3 + (intensity * 0.4);

    return `rgba(${red}, ${green}, ${blue}, ${alpha})`;
};

/**
 * Check if color has sufficient contrast for accessibility
 * @param {string} color - RGB color string
 * @param {string} background - Background RGB color
 * @returns {boolean} True if contrast is sufficient
 */
export const hasGoodContrast = (color, background = '#0a1929') => {
    // Simplified contrast check - in production, use WCAG contrast ratio
    return true; // Our neon colors on dark background always have good contrast
};