render.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. const getSprite = (() => {
  2. const stripForm = ["flabebe", "floette", "florges", "vivillon", "basculin", "furfrou", "magearna"];
  3. return pokemon => {
  4. pokemon = pokemon
  5. .replace("-alola", "-alolan")
  6. .replace("-galar", "-galarian")
  7. .replace("darmanitan-galarian", "darmanitan-galarian-standard");
  8. if (stripForm.find(s => pokemon.includes(s))) {
  9. pokemon = pokemon.replace(/-.*$/, "");
  10. }
  11. return `https://img.pokemondb.net/sprites/sword-shield/icon/${pokemon}.png`;
  12. }
  13. })();
  14. const renderStatPair = (lbl, val, valueClass = "value") => `
  15. <span class="pkmn-tile_label">${lbl}</span>
  16. <span class="pkmn-tile_${valueClass}">${val}</span>
  17. `;
  18. const renderStatRow = lines => `
  19. <div class="pkmn-tile_row">
  20. ${lines.join("\n")}
  21. </div>
  22. `;
  23. const renderPokemonTileCluster = (area, totalSize, { mu, nu }, scores) => {
  24. const textColor = getContrastingTextColor(mu.hex);
  25. return `
  26. <div
  27. class="pkmn-tile_stats"
  28. style="grid-area: ${area}; color: ${textColor}; background-color: ${mu.hex};"
  29. >
  30. <div class="pkmn-tile_row" style="justify-content: center;">
  31. ${(100 * scores.size / totalSize).toFixed(2)}% ${mu.hex}
  32. </div>
  33. <div class="toggle-on">
  34. ${
  35. [ ["σ =", scores.sigma.toFixed(2)],
  36. ["δ =", scores.delta.toFixed(2)],
  37. ["M =", scores.manhattan.toFixed(2)],
  38. ["Ч =", scores.ch.toFixed(2)],
  39. ["Θ =", scores.bigTheta.toFixed(2) + "°"],
  40. ["θ =", scores.theta.toFixed(2) + "°"],
  41. ["ϕ =", scores.phi.toFixed(2) + "°"],
  42. ["ℓ =", scores.lightnessDiff.toFixed(2)],
  43. ]
  44. .map(([lbl, val]) => renderStatPair(lbl, val))
  45. .map(ls => renderStatRow([ls]))
  46. .join("\n")
  47. }
  48. <hr style="width: 80%; color: ${textColor}"/>
  49. ${
  50. [ ["μ =", `(${mu.vector[0].toFixed(2)},`],
  51. ["", mu.vector[1].toFixed(2) + ","],
  52. ["", mu.vector[2].toFixed(2) + ")"],
  53. ["I =", scores.inertia.toFixed(2)],
  54. ["ℒ =", scores.lightness.toFixed(2) + "°"],
  55. ["ν =", `(${nu[0].toFixed(2)},`],
  56. ["", nu[1].toFixed(2) + ","],
  57. ["", nu[2].toFixed(2) + ")"],
  58. ["V =", scores.muNuAngle.toFixed(2)],
  59. ["N =", scores.size],
  60. ]
  61. .map(([lbl, val]) => renderStatPair(lbl, val))
  62. .map(ls => renderStatRow([ls]))
  63. .join("\n")
  64. }
  65. </div>
  66. </div>
  67. `;
  68. };
  69. const clusterToggles = {};
  70. const renderPokemonTile = (kind, name, { total: { mu, nu, size }, clusters }, scores) => {
  71. const clusterToggleId = `${name}-${kind}-pkmn-expand-toggle`;
  72. const textColor = getContrastingTextColor(mu.hex);
  73. return `
  74. <div class="pkmn-tile toggle-box">
  75. <input
  76. autocomplete="off"
  77. type="checkbox"
  78. ${clusterToggles?.[clusterToggleId] ? "checked" : ""}
  79. id="${clusterToggleId}"
  80. onchange="clusterToggles['${clusterToggleId}'] = event.target.checked"
  81. class="toggle-button"
  82. role="button"
  83. >
  84. <label for="${clusterToggleId}" style="grid-area: togg; text-align: center; align-self: start;">
  85. <div class="toggle-off">►</div>
  86. <div class="toggle-on">▼</div>
  87. </label>
  88. <img style="grid-area: icon" src="${getSprite(name)}" />
  89. <span style="grid-area: name">
  90. ${name.split("-").map(part => part.charAt(0).toUpperCase() + part.substr(1)).join(" ")}
  91. </span>
  92. <div
  93. class="pkmn-tile_stats"
  94. style="grid-area: totl; color: ${textColor}; background-color: ${mu.hex};"
  95. >
  96. <div class="pkmn-tile_row" style="justify-content: center;">
  97. ${mu.hex}
  98. </div>
  99. <div class="toggle-on">
  100. ${ renderStatRow(
  101. [ ["σ =", scores.total.sigma.toFixed(2)],
  102. ["δ =", scores.total.delta.toFixed(2)],
  103. ["M =", scores.total.manhattan.toFixed(2)],
  104. ["Ч =", scores.total.ch.toFixed(2)],
  105. ].map(([lbl, val]) => renderStatPair(lbl, val))
  106. )}
  107. ${ renderStatRow(
  108. [ ["Θ =", scores.total.bigTheta.toFixed(2) + "°"],
  109. ["θ =", scores.total.theta.toFixed(2) + "°"],
  110. ["ϕ =", scores.total.phi.toFixed(2) + "°"],
  111. ["ℓ =", scores.total.lightnessDiff.toFixed(2)],
  112. ].map(([lbl, val]) => renderStatPair(lbl, val))
  113. )}
  114. <hr style="width: 80%; color: ${textColor}"/>
  115. ${ renderStatRow(
  116. [ ["μ =", `(${mu.vector.map(c => c.toFixed(2)).join(", ")})`, "vector"],
  117. ["I =", scores.total.inertia.toFixed(2)],
  118. ["ℒ =", scores.total.lightness.toFixed(2)],
  119. ].map(([lbl, val, cls]) => renderStatPair(lbl, val, cls))
  120. )}
  121. ${ renderStatRow(
  122. [ ["ν =", `(${nu.map(c => c.toFixed(2)).join(", ")})`, "vector"],
  123. ["V =", scores.total.muNuAngle.toFixed(2)],
  124. ["N =", size],
  125. ].map(([lbl, val, cls]) => renderStatPair(lbl, val, cls))
  126. )}
  127. </div>
  128. </div>
  129. ${clusters.map((c, i) => renderPokemonTileCluster(`cls${i+1}`, size, c, scores.clusters[i])).join("\n")}
  130. </div>
  131. `
  132. };