Jelajahi Sumber

Moving all the marker logic to a separate file to clean up RoundSummary

Kirk Trombley 5 tahun lalu
induk
melakukan
051862870e

+ 11 - 88
client/src/components/screens/RoundSummary/RoundSummary.jsx

@@ -6,7 +6,8 @@ import usePlayerScores from "../../../hooks/usePlayerScores";
 import useRoundInfo from "../../../hooks/useRoundInfo";
 import DelayedButton from "../../util/DelayedButton";
 import Button from "../../util/Button";
-/* global google */
+import usePlayerColors from "./usePlayerColors";
+import { makeQuestionMarker, makeFlagMarker, makeLine } from "./markers";
 
 
 const Container = styled.div`
@@ -43,83 +44,6 @@ const NextButton = styled(DelayedButton)`
   padding: 1em;
 `
 
-const flagIcon = {
-  path: "M466.515 66.928C487.731 57.074 512 72.551 512 95.944v243.1c0 10.526-5.161 20.407-13.843 26.358-35.837 24.564-74.335 40.858-122.505 40.858-67.373 0-111.63-34.783-165.217-34.783-50.853 0-86.124 10.058-114.435 22.122V488c0 13.255-10.745 24-24 24H56c-13.255 0-24-10.745-24-24V101.945C17.497 91.825 8 75.026 8 56 8 24.296 34.345-1.254 66.338.048c28.468 1.158 51.779 23.968 53.551 52.404.52 8.342-.81 16.31-3.586 23.562C137.039 68.384 159.393 64 184.348 64c67.373 0 111.63 34.783 165.217 34.783 40.496 0 82.612-15.906 116.95-31.855zM96 134.63v70.49c29-10.67 51.18-17.83 73.6-20.91v-71.57c-23.5 2.17-40.44 9.79-73.6 21.99zm220.8 9.19c-26.417-4.672-49.886-13.979-73.6-21.34v67.42c24.175 6.706 47.566 16.444 73.6 22.31v-68.39zm-147.2 40.39v70.04c32.796-2.978 53.91-.635 73.6 3.8V189.9c-25.247-7.035-46.581-9.423-73.6-5.69zm73.6 142.23c26.338 4.652 49.732 13.927 73.6 21.34v-67.41c-24.277-6.746-47.54-16.45-73.6-22.32v68.39zM96 342.1c23.62-8.39 47.79-13.84 73.6-16.56v-71.29c-26.11 2.35-47.36 8.04-73.6 17.36v70.49zm368-221.6c-21.3 8.85-46.59 17.64-73.6 22.47v71.91c27.31-4.36 50.03-14.1 73.6-23.89V120.5zm0 209.96v-70.49c-22.19 14.2-48.78 22.61-73.6 26.02v71.58c25.07-2.38 48.49-11.04 73.6-27.11zM316.8 212.21v68.16c25.664 7.134 46.616 9.342 73.6 5.62v-71.11c-25.999 4.187-49.943 2.676-73.6-2.67z",
-  fillOpacity: 1.0,
-  fillColor: "#000000",
-  scale: 0.075,
-  anchor: new google.maps.Point(16, 512),
-};
-
-const questionSymbol = color => ({
-  path: "M29.898 26.5722l-4.3921 0c-0.0118,-0.635 -0.0177,-1.0172 -0.0177,-1.1583 0,-1.4229 0.2352,-2.5929 0.7056,-3.5102 0.4704,-0.9231 1.417,-1.952 2.8281,-3.1044 1.4111,-1.1465 2.2578,-1.8991 2.5282,-2.2578 0.4292,-0.5585 0.6409,-1.1818 0.6409,-1.8579 0,-0.9408 -0.3763,-1.7463 -1.1289,-2.4224 -0.7526,-0.6703 -1.7639,-1.0054 -3.0397,-1.0054 -1.2289,0 -2.2578,0.3527 -3.0868,1.0524 -0.8232,0.6997 -1.3935,1.7698 -1.7051,3.2044l-4.4391 -0.5527c0.1234,-2.0578 0.9995,-3.8041 2.6223,-5.2387 1.6286,-1.4346 3.757,-2.152 6.4029,-2.152 2.7752,0 4.9859,0.7291 6.6322,2.1814 1.6404,1.4522 2.4635,3.1397 2.4635,5.0741 0,1.0642 -0.3057,2.0755 -0.9054,3.028 -0.6056,0.9525 -1.8933,2.2519 -3.8688,3.8923 -1.0231,0.8525 -1.6581,1.5346 -1.905,2.052 -0.2469,0.5174 -0.3587,1.4405 -0.3351,2.7752zm-4.3921 6.5087l0 -4.8389 4.8389 0 0 4.8389 -4.8389 0z",
-  fillOpacity: 1.0,
-  fillColor: color,
-  scale: 1,
-  anchor: new google.maps.Point(32, 40),
-})
-
-const lineSettings = color => ({
-  strokeColor: color,
-  strokeOpacity: 0,
-  icons: [{
-    icon: {
-      path: 'M 0,-1 0,1',
-      strokeOpacity: 1,
-      scale: 4
-    },
-    offset: '0',
-    repeat: '20px'
-  }],
-});
-
-const makeMarker = (map, position, title, icon) => {
-  const marker = new google.maps.Marker({
-    clickable: true,
-    map,
-    position,
-    title,
-    icon,
-  });
-
-  const { lat, lng } = position;
-  marker.addListener("click", () => {
-    window.open(`https://www.google.com/maps?hl=en&q=+${lat},+${lng}`, "_blank");
-  });
-
-  return marker;
-}
-
-// logic adapted from How to Generate Random Colors Programmatically by Martin Ankerl
-// https://martin.ankerl.com/2009/12/09/how-to-create-random-colors-programmatically/
-const goldenRatioConj = 0.618033988749895;
-let h = 0;
-const nextColor = () => {
-  h += goldenRatioConj;
-  h %= 1;
-  const h6 = h * 6;
-  const h_i = Math.floor(h6);
-  const f = 0.45 * (h6 - h_i);
-  const q = 0.9 - f;
-  const t = f + 0.45;
-  return "#" + ([
-    [0.9, t, 0.45],
-    [q, 0.9, 0.45],
-    [0.45, 0.9, t],
-    [0.45, q, 0.9],
-    [t, 0.45, 0.9],
-    [0.9, 0.45, q],
-  ])[h_i].map(component => {
-    const converted = Math.floor(component * 256).toString(16);
-    if (converted.length === 1) {
-      return "0" + converted;
-    }
-    return converted;
-  }).reduce((x, y) => x + y);
-}
-
-const playerColors = {};
-
 export default () => {
   // get the info about the last round
   const { roundNum, targetPoint } = useLastRound();
@@ -130,7 +54,7 @@ export default () => {
 
   // set up the flag at the target point
   useEffect(() => {
-    const targetMarker = makeMarker(mapRef.current, targetPoint, "Goal", flagIcon);
+    const targetMarker = makeFlagMarker(mapRef.current, targetPoint, "Goal", "#000000");
     return () => targetMarker.setMap(null);
   }, [mapRef, targetPoint]);
 
@@ -140,27 +64,26 @@ export default () => {
   // live update the player scores
   const players = usePlayerScores()
     ?.filter(({ guesses }) => guesses[roundNum] && guesses[roundNum].score !== null);
+
+  // set up the marker colors
+  const playerColors = usePlayerColors(players?.map(({ name }) => name))
+
   useEffect(() => {
     if (!players) return;
     const drawings = [];
     players.forEach(({ name, guesses }) => {
       const { lat, lng, score } = guesses[roundNum]
-      const color = playerName === name ? "#000000" : playerColors[name] ?? nextColor();
-      playerColors[name] = color;
+      const color = playerName === name ? "#000000" : playerColors[name];
       const selectedPoint = { lat, lng };
 
-      const marker = makeMarker(mapRef.current, selectedPoint, `${name} - ${score} Points`, questionSymbol(color))
+      const marker = makeQuestionMarker(mapRef.current, selectedPoint, `${name} - ${score} Points`, color);
       drawings.push(marker);
 
-      const line = new google.maps.Polyline({
-        path: [ selectedPoint, targetPoint ],
-        map: mapRef.current,
-        ...lineSettings(color),
-      });
+      const line = makeLine(selectedPoint, targetPoint, mapRef.current, color);
       drawings.push(line);
     });
     return () => drawings.forEach((drawing) => drawing.setMap(null));
-  }, [players, mapRef, targetPoint, roundNum, playerName]);
+  }, [players, mapRef, targetPoint, roundNum, playerName, playerColors]);
 
   // whether or not the game is done
   const [gameFinished] = useRoundInfo()

+ 54 - 0
client/src/components/screens/RoundSummary/markers.js

@@ -0,0 +1,54 @@
+/* global google */
+
+const flagIcon = fillColor => ({
+  path: "M466.515 66.928C487.731 57.074 512 72.551 512 95.944v243.1c0 10.526-5.161 20.407-13.843 26.358-35.837 24.564-74.335 40.858-122.505 40.858-67.373 0-111.63-34.783-165.217-34.783-50.853 0-86.124 10.058-114.435 22.122V488c0 13.255-10.745 24-24 24H56c-13.255 0-24-10.745-24-24V101.945C17.497 91.825 8 75.026 8 56 8 24.296 34.345-1.254 66.338.048c28.468 1.158 51.779 23.968 53.551 52.404.52 8.342-.81 16.31-3.586 23.562C137.039 68.384 159.393 64 184.348 64c67.373 0 111.63 34.783 165.217 34.783 40.496 0 82.612-15.906 116.95-31.855zM96 134.63v70.49c29-10.67 51.18-17.83 73.6-20.91v-71.57c-23.5 2.17-40.44 9.79-73.6 21.99zm220.8 9.19c-26.417-4.672-49.886-13.979-73.6-21.34v67.42c24.175 6.706 47.566 16.444 73.6 22.31v-68.39zm-147.2 40.39v70.04c32.796-2.978 53.91-.635 73.6 3.8V189.9c-25.247-7.035-46.581-9.423-73.6-5.69zm73.6 142.23c26.338 4.652 49.732 13.927 73.6 21.34v-67.41c-24.277-6.746-47.54-16.45-73.6-22.32v68.39zM96 342.1c23.62-8.39 47.79-13.84 73.6-16.56v-71.29c-26.11 2.35-47.36 8.04-73.6 17.36v70.49zm368-221.6c-21.3 8.85-46.59 17.64-73.6 22.47v71.91c27.31-4.36 50.03-14.1 73.6-23.89V120.5zm0 209.96v-70.49c-22.19 14.2-48.78 22.61-73.6 26.02v71.58c25.07-2.38 48.49-11.04 73.6-27.11zM316.8 212.21v68.16c25.664 7.134 46.616 9.342 73.6 5.62v-71.11c-25.999 4.187-49.943 2.676-73.6-2.67z",
+  fillOpacity: 1.0,
+  fillColor,
+  scale: 0.075,
+  anchor: new google.maps.Point(16, 512),
+});
+
+const questionSymbol = fillColor => ({
+  path: "M29.898 26.5722l-4.3921 0c-0.0118,-0.635 -0.0177,-1.0172 -0.0177,-1.1583 0,-1.4229 0.2352,-2.5929 0.7056,-3.5102 0.4704,-0.9231 1.417,-1.952 2.8281,-3.1044 1.4111,-1.1465 2.2578,-1.8991 2.5282,-2.2578 0.4292,-0.5585 0.6409,-1.1818 0.6409,-1.8579 0,-0.9408 -0.3763,-1.7463 -1.1289,-2.4224 -0.7526,-0.6703 -1.7639,-1.0054 -3.0397,-1.0054 -1.2289,0 -2.2578,0.3527 -3.0868,1.0524 -0.8232,0.6997 -1.3935,1.7698 -1.7051,3.2044l-4.4391 -0.5527c0.1234,-2.0578 0.9995,-3.8041 2.6223,-5.2387 1.6286,-1.4346 3.757,-2.152 6.4029,-2.152 2.7752,0 4.9859,0.7291 6.6322,2.1814 1.6404,1.4522 2.4635,3.1397 2.4635,5.0741 0,1.0642 -0.3057,2.0755 -0.9054,3.028 -0.6056,0.9525 -1.8933,2.2519 -3.8688,3.8923 -1.0231,0.8525 -1.6581,1.5346 -1.905,2.052 -0.2469,0.5174 -0.3587,1.4405 -0.3351,2.7752zm-4.3921 6.5087l0 -4.8389 4.8389 0 0 4.8389 -4.8389 0z",
+  fillOpacity: 1.0,
+  fillColor,
+  scale: 1,
+  anchor: new google.maps.Point(32, 40),
+});
+
+const makeMarker = (map, position, title, icon) => {
+  const marker = new google.maps.Marker({
+    clickable: true,
+    map,
+    position,
+    title,
+    icon,
+  });
+
+  const { lat, lng } = position;
+  marker.addListener("click", () => {
+    window.open(`https://www.google.com/maps?hl=en&q=+${lat},+${lng}`, "_blank");
+  });
+
+  return marker;
+};
+
+export const makeFlagMarker = (map, position, title, color) => makeMarker(map, position, title, flagIcon(color));
+
+export const makeQuestionMarker = (map, position, title, color) => makeMarker(map, position, title, questionSymbol(color));
+
+export const makeLine = (p1, p2, map, strokeColor) => new google.maps.Polyline({
+  path: [ p1, p2 ],
+  map,
+  strokeColor,
+  strokeOpacity: 0,
+  icons: [{
+    icon: {
+      path: 'M 0,-1 0,1',
+      strokeOpacity: 1,
+      scale: 4
+    },
+    offset: '0',
+    repeat: '20px'
+  }],
+});

+ 49 - 0
client/src/components/screens/RoundSummary/usePlayerColors.jsx

@@ -0,0 +1,49 @@
+import { useRef } from "react";
+
+// logic adapted from How to Generate Random Colors Programmatically by Martin Ankerl
+// https://martin.ankerl.com/2009/12/09/how-to-create-random-colors-programmatically/
+const goldenRatioConj = 0.618033988749895;
+
+const getColorGenerator = () => {
+  let h = 0;
+  const nextColor = () => {
+    h += goldenRatioConj;
+    h %= 1;
+    const h6 = h * 6;
+    const h_i = Math.floor(h6);
+    const f = 0.45 * (h6 - h_i);
+    const q = 0.9 - f;
+    const t = f + 0.45;
+    return "#" + ([
+      [0.9, t, 0.45],
+      [q, 0.9, 0.45],
+      [0.45, 0.9, t],
+      [0.45, q, 0.9],
+      [t, 0.45, 0.9],
+      [0.9, 0.45, q],
+    ])[h_i].map(component => {
+      const converted = Math.floor(component * 256).toString(16);
+      if (converted.length === 1) {
+        return "0" + converted;
+      }
+      return converted;
+    }).reduce((x, y) => x + y);
+  };
+
+  return nextColor
+};
+
+const usePlayerColors = (players) => {
+  const playerColors = useRef({});
+  const nextColor = useRef(getColorGenerator());
+
+  if (players) {
+    players
+      .filter(name => !playerColors.current[name])
+      .forEach(name => { playerColors.current[name] = nextColor.current() });
+  }
+
+  return playerColors.current;
+};
+
+export default usePlayerColors;