convert.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. const jab2hex = jab => d3.jab(...jab).formatHex();
  2. const rgb2hex = rgb => d3.rgb(...rgb).formatHex();
  3. const jab2hue = jab => d3.jch(d3.jab(...jab)).h || 0;
  4. const rgb2hue = rgb => d3.hsl(d3.rgb(...rgb)).h || 0;
  5. const jab2lit = ([j]) => j / 100;
  6. const rgb2lit = rgb => d3.hsl(d3.rgb(...rgb)).l || 0;
  7. const jab2chroma = jab => d3.jch(d3.jab(...jab)).C / 100;
  8. const rgb2chroma = rgb => d3.jch(d3.rgb(...rgb)).C / 100;
  9. const buildVectorData = (vector, toHue, toLightness, toChroma, toHex) => {
  10. const sqMag = vectorDot(vector, vector);
  11. const mag = Math.sqrt(sqMag);
  12. const unit = vector.map(c => c / mag);
  13. const hue = toHue(vector);
  14. const lightness = toLightness(vector);
  15. const chroma = toChroma(vector);
  16. const hex = toHex(vector);
  17. return { vector, sqMag, mag, unit, hue, lightness, chroma, hex };
  18. };
  19. const calcImportance = (chroma, lightness, proportion) => (
  20. chroma
  21. + Math.tanh(100 * (chroma - 0.25)) // penalty for being <25%
  22. + Math.tanh(100 * (chroma - 0.40)) // penalty for being <40%
  23. + lightness
  24. + Math.tanh(100 * (lightness - 0.50)) // penalty for being <50%
  25. + proportion
  26. + Math.tanh(100 * (proportion - 0.05)) // penalty for being <5%
  27. + Math.tanh(100 * (proportion - 0.10)) // penalty for being <15%
  28. + Math.tanh(100 * (proportion - 0.15)) // penalty for being <15%
  29. + Math.tanh(100 * (proportion - 0.25)) // penalty for being <25%
  30. + Math.tanh(100 * (proportion - 0.80)) // penalty for being <50%
  31. );
  32. const buildClusterData = (size, inertia, mu1, mu2, mu3, nu1, nu2, nu3, totalSize, toHue, toLightness, toChroma, toHex) => {
  33. const mu = buildVectorData([mu1, mu2, mu3], toHue, toLightness, toChroma, toHex);
  34. const nu = [nu1, nu2, nu3];
  35. const muNuAngle = rad2deg * Math.acos(vectorDot(mu.unit, nu) / vectorMag(nu));
  36. const proportion = size / totalSize;
  37. const importance = calcImportance(mu.chroma, mu.lightness, proportion);
  38. return {
  39. size, inertia, mu, nu,
  40. muNuAngle, proportion, importance,
  41. };
  42. };
  43. const buildPokemonData = ([name, size, ...values]) => ({
  44. name,
  45. jab: {
  46. total: buildClusterData(size, ...values.slice(0, 7), size, jab2hue, jab2lit, jab2chroma, jab2hex),
  47. clusters: [
  48. buildClusterData(...values.slice(7, 15), size, jab2hue, jab2lit, jab2chroma, jab2hex),
  49. buildClusterData(...values.slice(15, 23), size, jab2hue, jab2lit, jab2chroma, jab2hex),
  50. buildClusterData(...values.slice(23, 31), size, jab2hue, jab2lit, jab2chroma, jab2hex),
  51. buildClusterData(...values.slice(31, 39), size, jab2hue, jab2lit, jab2chroma, jab2hex),
  52. ].filter(c => c.size !== 0),
  53. },
  54. rgb: {
  55. total: buildClusterData(size, ...values.slice(39, 46), size, rgb2hue, rgb2lit, rgb2chroma, rgb2hex),
  56. clusters: [
  57. buildClusterData(...values.slice(46, 54), size, rgb2hue, rgb2lit, rgb2chroma, rgb2hex),
  58. buildClusterData(...values.slice(54, 62), size, rgb2hue, rgb2lit, rgb2chroma, rgb2hex),
  59. buildClusterData(...values.slice(62, 70), size, rgb2hue, rgb2lit, rgb2chroma, rgb2hex),
  60. buildClusterData(...values.slice(70, 78), size, rgb2hue, rgb2lit, rgb2chroma, rgb2hex),
  61. ].filter(c => c.size !== 0),
  62. },
  63. });
  64. const pokemonData = databaseV3.map(row => buildPokemonData(row));