All files / web/src/components/toys/number-line/primes primeColors.ts

52.38% Statements 33/63
100% Branches 0/0
0% Functions 0/5
52.38% Lines 33/63

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 641x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x         1x 1x 1x 1x                 1x 1x 1x 1x 1x 1x 1x             1x 1x 1x 1x 1x             1x 1x 1x 1x 1x              
import { getPrimeOrdinal } from './sieve'
 
/**
 * Golden angle in degrees (~137.508).
 * Successive multiples produce maximally-spaced hues around the color wheel.
 */
const GOLDEN_ANGLE = 137.50776405003785
 
/**
 * Get the hue (0-360) for a given prime based on its ordinal index.
 * Uses golden-angle spacing for maximum perceptual distance between adjacent primes.
 */
function primeHue(prime: number): number {
  const ordinal = getPrimeOrdinal(prime)
  return (ordinal * GOLDEN_ANGLE) % 360
}
 
/**
 * Convert HSL to RGB values (each 0-255).
 */
function hslToRgb(h: number, s: number, l: number): [number, number, number] {
  const a = s * Math.min(l, 1 - l)
  const f = (n: number) => {
    const k = (n + h / 30) % 12
    return l - a * Math.max(-1, Math.min(k - 3, 9 - k, 1))
  }
  return [Math.round(f(0) * 255), Math.round(f(8) * 255), Math.round(f(4) * 255)]
}
 
/**
 * Get an RGBA color string for a prime's color.
 * Theme-aware: dark mode uses lighter/more saturated colors,
 * light mode uses deeper/muted colors.
 */
export function primeColorRgba(prime: number, alpha: number, isDark: boolean): string {
  const hue = primeHue(prime)
  const sat = isDark ? 0.7 : 0.65
  const lum = isDark ? 0.55 : 0.45
  const [r, g, b] = hslToRgb(hue, sat, lum)
  return `rgba(${r}, ${g}, ${b}, ${alpha})`
}
 
/**
 * Get an RGB color string (no alpha) for a prime's color.
 */
export function primeColorRgb(prime: number, isDark: boolean): string {
  const hue = primeHue(prime)
  const sat = isDark ? 0.7 : 0.65
  const lum = isDark ? 0.55 : 0.45
  const [r, g, b] = hslToRgb(hue, sat, lum)
  return `rgb(${r}, ${g}, ${b})`
}
 
/**
 * Get the CSS hex color for a prime (for use in DOM elements like tooltip spans).
 */
export function primeColorHex(prime: number, isDark: boolean): string {
  const hue = primeHue(prime)
  const sat = isDark ? 0.7 : 0.65
  const lum = isDark ? 0.55 : 0.45
  const [r, g, b] = hslToRgb(hue, sat, lum)
  return `#${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b.toString(16).padStart(2, '0')}`
}