Pārlūkot izejas kodu

Inline some of the math that was only used in one place

Kirk Trombley 3 gadi atpakaļ
vecāks
revīzija
6fd245d0c6
6 mainītis faili ar 27 papildinājumiem un 32 dzēšanām
  1. 8 9
      web/convert.js
  2. 1 1
      web/listeners.js
  3. 6 13
      web/math.js
  4. 6 3
      web/metrics.js
  5. 2 2
      web/render.js
  6. 4 4
      web/score.js

+ 8 - 9
web/convert.js

@@ -4,10 +4,6 @@ const jab2hue = ([, a, b]) => rad2deg * Math.atan2(b, a);
 const rgb2hue = rgb => d3.hsl(d3.rgb(...rgb)).h || 0;
 const jab2lit = ([j]) => j;
 const rgb2lit = rgb => d3.hsl(d3.rgb(...rgb)).l || 0;
-const hex2rgb = hex => {
-  const { r, g, b } = d3.color(hex);
-  return [r, g, b];
-};
 
 const buildVectorData = (vector, toHue, toLightness, toHex) => {
   const sqMag = vectorDot(vector, vector);
@@ -19,11 +15,14 @@ const buildVectorData = (vector, toHue, toLightness, toHex) => {
   return { vector, sqMag, mag, unit, hue, lightness, hex };
 };
 
-const buildClusterData = (size, inertia, mu1, mu2, mu3, nu1, nu2, nu3, toHue, toLightness, toHex) => ({
-  size, inertia,
-  mu: buildVectorData([mu1, mu2, mu3], toHue, toLightness, toHex),
-  nu: [nu1, nu2, nu3],
-});
+const buildClusterData = (size, inertia, mu1, mu2, mu3, nu1, nu2, nu3, toHue, toLightness, toHex) => {
+  const mu = buildVectorData([mu1, mu2, mu3], toHue, toLightness, toHex);
+  const nu = [nu1, nu2, nu3];
+  return {
+    size, inertia, mu, nu,
+    muNuAngle: rad2deg * Math.acos(vectorDot(mu.unit, nu) / vectorMag(nu)),
+  };
+};
 
 const buildPokemonData = ([name, size, ...values]) => ({
   name,

+ 1 - 1
web/listeners.js

@@ -126,7 +126,7 @@ const onColorChanged = (state, newValue) => {
 
   const rootElem = document.querySelector(":root");
   rootElem.style.setProperty("--background", state.target.rgb.hex);
-  rootElem.style.setProperty("--highlight", getContrastingTextColor(state.target.rgb.vector));
+  rootElem.style.setProperty("--highlight", getContrastingTextColor(state.target.rgb.hex));
 
   rescoreAll(state.target);
   onControlsChanged(state);

+ 6 - 13
web/math.js

@@ -1,19 +1,12 @@
 // Vector Math
 const vectorDot = (u, v) => u.map((x, i) => x * v[i]).reduce((x, y) => x + y);
-const vectorSqMag = v => vectorDot(v, v);
-const vectorMag = v => Math.sqrt(vectorSqMag(v));
-const vectorSqDist = (u, v) => vectorSqMag(u.map((x, i) => x - v[i]));
-const vectorDist = (u, v) => Math.sqrt(vectorSqDist(u, v));
-const vectorNorm = v => { const n = vectorMag(v); return [ n, v.map(c => c / n) ]; };
+const vectorMag = v => Math.sqrt(vectorDot(v, v));
 
 // Angle Math
-const angleDiff = (a, b) => { const raw = Math.abs(a - b); return raw < 180 ? raw : (360 - raw); };
 const rad2deg = 180 / Math.PI;
 
-// Arg Compare
-const argComp = comp => ra => ra.map((x, i) => [x, i]).reduce((a, b) => comp(a[0], b[0]) > 0 ? b : a)[1];
-const argMin = argComp((a, b) => a - b);
-const argMax = argComp((a, b) => b - a);
-
-// Luminance
-const getContrastingTextColor = rgb => vectorDot(rgb, [0.3, 0.6, 0.1]) >= 128 ? "#222" : "#ddd";
+// Contrast
+const getContrastingTextColor = hex => {
+  const { r, g, b } = d3.color(hex);
+  return vectorDot([r, g, b], [0.3, 0.6, 0.1]) >= 128 ? "#222" : "#ddd";
+};

+ 6 - 3
web/metrics.js

@@ -29,7 +29,10 @@ const metrics = {
     displayBody: (p, space) => String.raw`
       \angle \left(\text{oproj}_{\vec{${space === "jab" ? "J" : "L"}}}{\vec{q}}, \text{oproj}_{\vec{${space === "jab" ? "J" : "L"}}}{\vec{\mu}\left(${p}\right)} \right)
     `,
-    evaluate: (data, target) => angleDiff(data.mu.hue, target.hue),
+    evaluate: (data, target) => { 
+      const raw = Math.abs(data.mu.hue - target.hue); 
+      return Math.min(raw, 360 - raw);
+    },
   },
   delta: { // euclidean
     option: "Euclidean Distance (δ)",
@@ -37,7 +40,7 @@ const metrics = {
     displayBody: p => String.raw`
       \left|\left| \vec{q} - \vec{\mu}\left(${p}\right) \right|\right|
     `,
-    evaluate: (data, target) => vectorDist(data.mu.vector, target.vector),
+    evaluate: (data, target) => vectorMag(data.mu.vector.map((x, i) => x - target.vector[i])),
   },
   manhattan: { // manhattan distance
     option: "Manhattan Distance (M)",
@@ -83,7 +86,7 @@ const metrics = {
     option: "Mu-Nu Angle (V)",
     displayName: "V",
     displayBody: p => String.raw`\angle \left( \vec{\mu}\left(${p}\right), \vec{\nu}\left(${p}\right) \right)`,
-    evaluate: data => rad2deg * Math.acos(vectorDot(data.mu.unit, data.nu) / vectorMag(data.nu)),
+    evaluate: data => data.muNuAngle,
   },
   size: {
     option: "Size (N)",

+ 2 - 2
web/render.js

@@ -13,7 +13,7 @@ const getSprite = (() => {
 })();
 
 const renderPokemonTileCluster = (area, totalSize, { mu, nu }, scores) => {
-  const textColor = getContrastingTextColor(hex2rgb(mu.hex));
+  const textColor = getContrastingTextColor(mu.hex);
   return String.raw`
   <div
     class="pkmn-tile_stats"
@@ -105,7 +105,7 @@ const clusterToggles = {};
 
 const renderPokemonTile = (kind, name, { total: { mu, nu, size }, clusters }, scores) => {
   const clusterToggleId = `${name}-${kind}-pkmn-expand-toggle`;
-  const textColor = getContrastingTextColor(hex2rgb(mu.hex));
+  const textColor = getContrastingTextColor(mu.hex);
 
   return String.raw`
     <div class="pkmn-tile toggle-box">

+ 4 - 4
web/score.js

@@ -18,10 +18,10 @@ const rescoreAll = target => pokemonData.forEach(pkmn => rescore(target, pkmn));
 const getBestClusterIndex = (pkmn, space, { sortMetric, scaleOption, sortOrder }) => {
   // get the scales
   const scales = scaleOption(pkmn[space]);
-  // and multiply with the intended metric, and find the best value
-  return argComp(sortOrder)(
-    currentScores[pkmn.name][space].clusters.map((c, i) => c[sortMetric] * scales[i])
-  );
+  // and multiply with the intended metric, and find the index of the best value
+  return currentScores[pkmn.name][space].clusters
+    .map((c, i) => [c[sortMetric] * scales[i], i])
+    .reduce((a, b) => sortOrder(a[0], b[0]) > 0 ? b : a)[1];
 }
 
 const getBest = (number, space, clusterSettings, { sortMetric, scaleOption, sortOrder }) => {