|
@@ -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";
|
|
|
|