use compressed validPetPoses to save network

it also has valid emotion/gp data in there too, which we'll use later!
This commit is contained in:
Matt Dunn-Rankin 2020-05-03 01:52:39 -07:00
parent 04a851a138
commit 1bf33c14db
7 changed files with 70 additions and 44 deletions

View file

@ -26,7 +26,8 @@
"react-dom": "^16.13.1", "react-dom": "^16.13.1",
"react-helmet": "^6.0.0", "react-helmet": "^6.0.0",
"react-scripts": "3.4.1", "react-scripts": "3.4.1",
"react-transition-group": "^4.3.0" "react-transition-group": "^4.3.0",
"use-http": "^1.0.10"
}, },
"scripts": { "scripts": {
"start": "react-scripts start", "start": "react-scripts start",

View file

@ -1,5 +1,6 @@
import React from "react"; import React from "react";
import gql from "graphql-tag"; import gql from "graphql-tag";
import useFetch from "use-http";
import { useQuery } from "@apollo/react-hooks"; import { useQuery } from "@apollo/react-hooks";
import { Box, Flex, Select, Text, useToast } from "@chakra-ui/core"; import { Box, Flex, Select, Text, useToast } from "@chakra-ui/core";
@ -13,7 +14,7 @@ import { Delay } from "./util";
*/ */
function SpeciesColorPicker({ outfitState, dispatchToOutfit }) { function SpeciesColorPicker({ outfitState, dispatchToOutfit }) {
const toast = useToast(); const toast = useToast();
const { loading, error, data } = useQuery(gql` const { loading: loadingMeta, error: errorMeta, data: meta } = useQuery(gql`
query { query {
allSpecies { allSpecies {
id id
@ -24,35 +25,24 @@ function SpeciesColorPicker({ outfitState, dispatchToOutfit }) {
id id
name name
} }
allValidSpeciesColorPairs {
species {
id
}
color {
id
}
}
} }
`); `);
const {
const allColors = (data && [...data.allColors]) || []; loading: loadingValids,
allColors.sort((a, b) => a.name.localeCompare(b.name)); error: errorValids,
const allSpecies = (data && [...data.allSpecies]) || []; data: validsBuffer,
allSpecies.sort((a, b) => a.name.localeCompare(b.name)); } = useFetch("/api/validPetPoses", { responseType: "arrayBuffer" }, []);
const valids = React.useMemo(
// Build a large Set where we can quickly look up species/color pairs! () => validsBuffer && new DataView(validsBuffer),
const allValidSpeciesColorPairs = React.useMemo( [validsBuffer]
() =>
new Set(
((data && data.allValidSpeciesColorPairs) || []).map(
(p) => `${p.species.id},${p.color.id}`
)
),
[data]
); );
if (loading) { const allColors = (meta && [...meta.allColors]) || [];
allColors.sort((a, b) => a.name.localeCompare(b.name));
const allSpecies = (meta && [...meta.allSpecies]) || [];
allSpecies.sort((a, b) => a.name.localeCompare(b.name));
if (loadingMeta || loadingValids) {
return ( return (
<Delay ms={5000}> <Delay ms={5000}>
<Text color="gray.50" textShadow="md"> <Text color="gray.50" textShadow="md">
@ -62,7 +52,7 @@ function SpeciesColorPicker({ outfitState, dispatchToOutfit }) {
); );
} }
if (error) { if (errorMeta || errorValids) {
return ( return (
<Text color="gray.50" textShadow="md"> <Text color="gray.50" textShadow="md">
Error loading species/color data. Error loading species/color data.
@ -75,8 +65,7 @@ function SpeciesColorPicker({ outfitState, dispatchToOutfit }) {
const onChangeColor = (e) => { const onChangeColor = (e) => {
const speciesId = outfitState.speciesId; const speciesId = outfitState.speciesId;
const colorId = e.target.value; const colorId = e.target.value;
const pair = `${speciesId},${colorId}`; if (pairIsValid(valids, meta, speciesId, colorId)) {
if (allValidSpeciesColorPairs.has(pair)) {
dispatchToOutfit({ type: "changeColor", colorId: e.target.value }); dispatchToOutfit({ type: "changeColor", colorId: e.target.value });
} else { } else {
const species = allSpecies.find((s) => s.id === speciesId); const species = allSpecies.find((s) => s.id === speciesId);
@ -93,14 +82,14 @@ function SpeciesColorPicker({ outfitState, dispatchToOutfit }) {
const onChangeSpecies = (e) => { const onChangeSpecies = (e) => {
const colorId = outfitState.colorId; const colorId = outfitState.colorId;
const speciesId = e.target.value; const speciesId = e.target.value;
const pair = `${speciesId},${colorId}`; if (pairIsValid(valids, meta, speciesId, colorId)) {
if (allValidSpeciesColorPairs.has(pair)) {
dispatchToOutfit({ type: "changeSpecies", speciesId: e.target.value }); dispatchToOutfit({ type: "changeSpecies", speciesId: e.target.value });
} else { } else {
const species = allSpecies.find((s) => s.id === speciesId); const species = allSpecies.find((s) => s.id === speciesId);
const color = allColors.find((c) => c.id === colorId); const color = allColors.find((c) => c.id === colorId);
toast({ toast({
title: `We haven't seen a ${color.name} ${species.name} before! 😓`, title: `We haven't seen a ${color.name} ${species.name} before! 😓`,
status: "warning",
}); });
} }
}; };
@ -144,4 +133,14 @@ function SpeciesColorPicker({ outfitState, dispatchToOutfit }) {
); );
} }
function pairIsValid(valids, meta, speciesId, colorId) {
// Reading a bit table, owo!
const speciesIndex = speciesId - 1;
const colorIndex = colorId - 1;
const numColors = meta.allColors.length;
const pairByteIndex = speciesIndex * numColors + colorIndex;
const pairByte = valids.getUint8(pairByteIndex);
return pairByte !== 0;
}
export default SpeciesColorPicker; export default SpeciesColorPicker;

View file

@ -33,7 +33,10 @@ export default async function getValidPetPoses() {
const buffer = Buffer.alloc(numPairs); const buffer = Buffer.alloc(numPairs);
for (let speciesId = 1; speciesId <= numSpecies; speciesId++) { for (let speciesId = 1; speciesId <= numSpecies; speciesId++) {
const speciesIndex = speciesId - 1;
for (let colorId = 1; colorId <= numColors; colorId++) { for (let colorId = 1; colorId <= numColors; colorId++) {
const colorIndex = colorId - 1;
let byte = 0; let byte = 0;
byte += hasPose(speciesId, colorId, "HAPPY", "MASCULINE") ? 1 : 0; byte += hasPose(speciesId, colorId, "HAPPY", "MASCULINE") ? 1 : 0;
byte <<= 1; byte <<= 1;
@ -47,7 +50,7 @@ export default async function getValidPetPoses() {
byte <<= 1; byte <<= 1;
byte += hasPose(speciesId, colorId, "SICK", "FEMININE") ? 1 : 0; byte += hasPose(speciesId, colorId, "SICK", "FEMININE") ? 1 : 0;
buffer.writeUInt8(byte); buffer.writeUInt8(byte, speciesIndex * numColors + colorIndex);
} }
} }
@ -60,7 +63,9 @@ async function getNumSpecies(db) {
} }
async function getNumColors(db) { async function getNumColors(db) {
const [rows, _] = await db.query(`SELECT count(*) FROM colors`); const [rows, _] = await db.query(
`SELECT count(*) FROM colors WHERE prank = 0`
);
return rows[0]["count(*)"]; return rows[0]["count(*)"];
} }

View file

@ -101,8 +101,7 @@ const typeDefs = gql`
type Query { type Query {
allColors: [Color!]! allColors: [Color!]!
allSpecies: [Species!]! allSpecies: [Species!]!
allValidSpeciesColorPairs: [SpeciesColorPair!]! allValidSpeciesColorPairs: [SpeciesColorPair!]! # deprecated
items(ids: [ID!]!): [Item!]! items(ids: [ID!]!): [Item!]!
itemSearch(query: String!): ItemSearchResult! itemSearch(query: String!): ItemSearchResult!
itemSearchToFit( itemSearchToFit(

View file

@ -3,14 +3,13 @@ function capitalize(str) {
} }
function getEmotion(moodId) { function getEmotion(moodId) {
const moodIdStr = String(moodId); if (String(moodId) === "1") {
if (moodIdStr === "1") {
return "HAPPY"; return "HAPPY";
} else if (moodIdStr === "2") { } else if (String(moodId) === "2") {
return "SAD"; return "SAD";
} else if (moodIdStr === "4") { } else if (String(moodId) === "4") {
return "SICK"; return "SICK";
} else if (moodIdStr === null) { } else if (moodId === null) {
return null; return null;
} else { } else {
throw new Error(`unrecognized moodId ${JSON.stringify(moodId)}`); throw new Error(`unrecognized moodId ${JSON.stringify(moodId)}`);
@ -18,10 +17,9 @@ function getEmotion(moodId) {
} }
function getGenderPresentation(modelPetWasFemale) { function getGenderPresentation(modelPetWasFemale) {
const modelPetWasFemaleStr = String(modelPetWasFemale); if (String(modelPetWasFemale) === "1") {
if (modelPetWasFemaleStr === "1") {
return "FEMININE"; return "FEMININE";
} else if (modelPetWasFemaleStr === "0") { } else if (String(modelPetWasFemale) === "0") {
return "MASCULINE"; return "MASCULINE";
} else { } else {
return null; return null;

View file

@ -11427,6 +11427,11 @@ url@^0.11.0:
punycode "1.3.2" punycode "1.3.2"
querystring "0.2.0" querystring "0.2.0"
urs@^0.0.4:
version "0.0.4"
resolved "https://registry.yarnpkg.com/urs/-/urs-0.0.4.tgz#d559d660f2a468e0bb116e0b7b505af57cb59ae4"
integrity sha512-+QflFOKa9DmjWclPB2audGCV83uWUnTXHOxLPQyu7XXcaY9yQ4+Tb3UEm8m4N7abJ0kJUCUAQBpFlq6mx80j9g==
use-callback-ref@^1.2.1: use-callback-ref@^1.2.1:
version "1.2.3" version "1.2.3"
resolved "https://registry.yarnpkg.com/use-callback-ref/-/use-callback-ref-1.2.3.tgz#9f939dfb5740807bbf9dd79cdd4e99d27e827756" resolved "https://registry.yarnpkg.com/use-callback-ref/-/use-callback-ref-1.2.3.tgz#9f939dfb5740807bbf9dd79cdd4e99d27e827756"
@ -11440,6 +11445,15 @@ use-dark-mode@2.3.1:
"@use-it/event-listener" "^0.1.2" "@use-it/event-listener" "^0.1.2"
use-persisted-state "^0.3.0" use-persisted-state "^0.3.0"
use-http@^1.0.10:
version "1.0.10"
resolved "https://registry.yarnpkg.com/use-http/-/use-http-1.0.10.tgz#d04da86c65552237ee13ede6218a79693b7fb452"
integrity sha512-KSxibM4WoSxnp4B366zVPOEWFadBO84yYtNEMEevupW/6V+D/Gme1Agx0cWwN6AYarrupcUoGT8P8M97jo+pzg==
dependencies:
urs "^0.0.4"
use-ssr "^1.0.22"
utility-types "^3.10.0"
use-persisted-state@^0.3.0: use-persisted-state@^0.3.0:
version "0.3.0" version "0.3.0"
resolved "https://registry.yarnpkg.com/use-persisted-state/-/use-persisted-state-0.3.0.tgz#f8e3d2fd8eee67e0c86fd596c3ea3e8121c07402" resolved "https://registry.yarnpkg.com/use-persisted-state/-/use-persisted-state-0.3.0.tgz#f8e3d2fd8eee67e0c86fd596c3ea3e8121c07402"
@ -11455,6 +11469,11 @@ use-sidecar@^1.0.1:
detect-node "^2.0.4" detect-node "^2.0.4"
tslib "^1.9.3" tslib "^1.9.3"
use-ssr@^1.0.22:
version "1.0.23"
resolved "https://registry.yarnpkg.com/use-ssr/-/use-ssr-1.0.23.tgz#3bde1e10cd01b3b61ab6386d7cddb72e74828bf8"
integrity sha512-5bvlssgROgPgIrnILJe2mJch4e2Id0/bVm1SQzqvPvEAXmlsinCCVHWK3a2iHcPat7PkdJHBo0gmSmODIz6tNA==
use@^3.1.0: use@^3.1.0:
version "3.1.1" version "3.1.1"
resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f"
@ -11502,6 +11521,11 @@ utila@^0.4.0, utila@~0.4:
resolved "https://registry.yarnpkg.com/utila/-/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c" resolved "https://registry.yarnpkg.com/utila/-/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c"
integrity sha1-ihagXURWV6Oupe7MWxKk+lN5dyw= integrity sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=
utility-types@^3.10.0:
version "3.10.0"
resolved "https://registry.yarnpkg.com/utility-types/-/utility-types-3.10.0.tgz#ea4148f9a741015f05ed74fd615e1d20e6bed82b"
integrity sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg==
utils-merge@1.0.1: utils-merge@1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"