Bläddra i källkod

Clean up score logic, style template, add display

Kirk Trombley 2 år sedan
förälder
incheckning
dc5f02398d
2 ändrade filer med 181 tillägg och 18 borttagningar
  1. 104 18
      form.js
  2. 77 0
      styles.css

+ 104 - 18
form.js

@@ -35,6 +35,18 @@ const selectors = {
   get prevColors() {
     return document.getElementById("prev-colors");
   },
+  get metricFormTemplate() {
+    return document.getElementById("metric-form-template").content;
+  },
+  get scaleFormTemplate() {
+    return document.getElementById("scale-form-template").content;
+  },
+  get pokemonTemplate() {
+    return document.getElementById("pkmn-template").content;
+  },
+  get colorSearchResults() {
+    return document.getElementById("color-results");
+  },
   set background(hex) {
     document.querySelector(":root").style.setProperty("--background", hex);
   },
@@ -127,6 +139,8 @@ const calcScores = (data, target) => {
     inverseSize: data.inverseSize,
     proportion: data.proportion,
     inverseProportion: data.inverseProportion,
+
+    muHex: data.mu.hex,
   };
 };
 
@@ -149,6 +163,7 @@ const scaleOptions = {
 
 const currentScores = {};
 const currentBestClusterIndices = {};
+const currentSortValues = {};
 let sortedData = [];
 
 const updateScores = (rgb) => {
@@ -194,30 +209,29 @@ const updateSort = () => {
 
   // set up for actual sort
   const scaleOption = scaleOptions[selectors.scaleFactor];
-  let valueExtractor;
   switch (selectors.useClusters) {
     case "off":
-      valueExtractor = (name) =>
-        currentScores[name][selectors.colorSpace].total[selectors.sortMetric];
+      pokemonData.forEach(({ name }) => {
+        currentSortValues[name] =
+          currentScores[name][selectors.colorSpace].total[selectors.sortMetric];
+      });
       break;
     case "on":
-      valueExtractor = (name) => {
+      pokemonData.forEach(({ name }) => {
         const index = currentBestClusterIndices[name][selectors.colorSpace];
-        return (
+        currentSortValues[name] =
           scaleOption(currentScores[name][selectors.colorSpace])[index] *
-          currentScores[name][selectors.colorSpace].clusters[index][selectors.sortMetric]
-        );
-      };
+          currentScores[name][selectors.colorSpace].clusters[index][selectors.sortMetric];
+      });
       break;
     case "mult":
-      valueExtractor = (name) => {
+      pokemonData.forEach(({ name }) => {
         const index = currentBestClusterIndices[name][selectors.colorSpace];
-        return (
+        currentSortValues[name] =
           currentScores[name][selectors.colorSpace].total[selectors.sortMetric] *
           scaleOption(currentScores[name][selectors.colorSpace])[index] *
-          currentScores[name][selectors.colorSpace].clusters[index][selectors.sortMetric]
-        );
-      };
+          currentScores[name][selectors.colorSpace].clusters[index][selectors.sortMetric];
+      });
       break;
   }
 
@@ -225,19 +239,91 @@ const updateSort = () => {
   const sortOrder = sortOrders[selectors.sortOrder];
   sortedData = pokemonData
     .map(({ name }) => name)
-    .sort((a, b) => sortOrder(valueExtractor(a), valueExtractor(b)));
+    .sort((a, b) => sortOrder(currentSortValues[a], currentSortValues[b]));
 
   // and desplay results
   showResults();
 };
 
+const getSprite = (() => {
+  const stripForm = [
+    "flabebe",
+    "floette",
+    "florges",
+    "vivillon",
+    "basculin",
+    "furfrou",
+    "magearna",
+    "alcremie",
+  ];
+  return (pokemon) => {
+    pokemon = pokemon
+      .replace("-alola", "-alolan")
+      .replace("-galar", "-galarian")
+      .replace("-phony", "") // sinistea and polteageist
+      .replace("darmanitan-galarian", "darmanitan-galarian-standard");
+    if (stripForm.find((s) => pokemon.includes(s))) {
+      pokemon = pokemon.replace(/-.*$/, "");
+    }
+    return `https://img.pokemondb.net/sprites/sword-shield/icon/${pokemon}.png`;
+  };
+})();
+
+const makePokemonTile = (name) => {
+  const clone = selectors.pokemonTemplate.cloneNode(true);
+
+  const img = clone.querySelector("img");
+  img.src = getSprite(name);
+  img.alt = name;
+
+  clone.querySelector(".pkmn-name").innerText = name
+    .split("-")
+    .map((part) => part.charAt(0).toUpperCase() + part.substr(1))
+    .join(" ");
+
+  clone.querySelector(".pkmn-score").innerText = currentSortValues[name];
+
+  const { total, clusters } = currentScores[name][selectors.colorSpace];
+
+  const mu = clone.querySelector(".pkmn-total");
+  mu.innerText = total.muHex;
+  mu.style = `
+    color: ${getContrastingTextColor(total.muHex)}; 
+    background-color: ${total.muHex};
+  `;
+
+  clusters.forEach((cls, i) => {
+    const clsDiv = clone.querySelector(`.pkmn-cls${i + 1}`);
+    clsDiv.firstChild.innerText = (cls.proportion * 100).toFixed(2) + "%";
+    clsDiv.lastChild.innerText = cls.muHex;
+    clsDiv.style = `
+      color: ${getContrastingTextColor(cls.muHex)}; 
+      background-color: ${cls.muHex};
+    `;
+  });
+
+  if (selectors.useClusters === "off") {
+    clone.querySelector(".pkmn").classList.add("pkmn-total-selected");
+  } else {
+    clone
+      .querySelector(".pkmn")
+      .classList.add(
+        `pkmn-cls${currentBestClusterIndices[name][selectors.colorSpace] + 1}-selected`
+      );
+  }
+
+  return clone;
+};
+
 const showResults = () => {
-  // TODO
-  console.log(sortedData.slice(0, selectors.resultsToDisplay));
+  selectors.colorSearchResults.innerHTML = "";
+  sortedData.slice(0, selectors.resultsToDisplay).forEach((name) => {
+    selectors.colorSearchResults.appendChild(makePokemonTile(name));
+  });
 };
 
 window.addEventListener("load", () => {
-  const metricTemplate = document.getElementById("metric-form-template").content;
+  const metricTemplate = selectors.metricFormTemplate;
 
   selectors.sortControl.metric.appendChild(metricTemplate.cloneNode(true));
   selectors.sortControl.metricKind.value = "whole";
@@ -250,7 +336,7 @@ window.addEventListener("load", () => {
   selectors.clusterControl.statistic.value = "importance";
   onMetricChange(selectors.clusterControl, true);
 
-  const scaleTemplate = document.getElementById("scale-form-template").content;
+  const scaleTemplate = selectors.scaleFormTemplate;
   selectors.sortControl.rescaleSection.appendChild(scaleTemplate.cloneNode(true));
   selectors.sortControl.rescaleFactor.value = "inverse";
 

+ 77 - 0
styles.css

@@ -15,3 +15,80 @@ body {
 select:disabled {
   display: none;
 }
+
+.pkmn {
+  margin: 0.25rem;
+  padding: 0.25rem;
+  display: grid;
+  gap: 0.25rem;
+  grid-template-columns: 64px 1fr 14ch;
+  grid-template-rows: repeat(4, 1fr);
+  grid-template-areas:
+    "img name  cls1"
+    "img score cls2"
+    "... total cls3"
+    "... total cls4";
+  align-items: center;
+  border: 1px solid var(--highlight);
+}
+
+.pkmn > img {
+  grid-area: img;
+  justify-self: center;
+}
+
+.pkmn > .pkmn-name {
+  grid-area: name;
+  font-weight: 800;
+}
+
+.pkmn > .pkmn-total {
+  grid-area: total;
+  height: 100%;
+  display: inline-flex;
+  align-items: center;
+}
+
+.pkmn > .pkmn-score {
+  grid-area: score;
+  padding-left: 4ch;
+}
+
+.pkmn > .pkmn-cls {
+  font-weight: 600;
+  font-size: 0.75rem;
+  padding: 0.125rem;
+  display: flex;
+  justify-content: space-between;
+}
+
+.pkmn > :is(.pkmn-total, .pkmn-cls)::before {
+  display: inline-block;
+  content: "";
+  width: 1ch;
+  margin-right: 4px;
+}
+
+.pkmn-total-selected > .pkmn-total::before,
+.pkmn-cls1-selected > .pkmn-cls1::before,
+.pkmn-cls2-selected > .pkmn-cls2::before,
+.pkmn-cls3-selected > .pkmn-cls3::before,
+.pkmn-cls4-selected > .pkmn-cls4::before {
+  content: "▸";
+}
+
+.pkmn > .pkmn-cls1 {
+  grid-area: cls1;
+}
+
+.pkmn > .pkmn-cls2 {
+  grid-area: cls2;
+}
+
+.pkmn > .pkmn-cls3 {
+  grid-area: cls3;
+}
+
+.pkmn > .pkmn-cls4 {
+  grid-area: cls4;
+}