diff --git a/src/app/HomePage.js b/src/app/HomePage.js
index 59c442d..0a26efb 100644
--- a/src/app/HomePage.js
+++ b/src/app/HomePage.js
@@ -128,8 +128,7 @@ function SubmitPetForm() {
name: petName,
species: species.id,
color: color.id,
- emotion: "HAPPY", // TODO: Ask PetService
- genderPresentation: "FEMININE", // TODO: Ask PetService
+ pose: "HAPPY_FEM", // TODO: Ask PetService
});
for (const item of items) {
params.append("objects[]", item.id);
diff --git a/src/app/PosePicker.js b/src/app/PosePicker.js
index aafaa07..f00664b 100644
--- a/src/app/PosePicker.js
+++ b/src/app/PosePicker.js
@@ -32,7 +32,7 @@ function PosePicker({
}) {
const theme = useTheme();
const checkedInputRef = React.useRef();
- const { loading, error, poses } = usePoses(outfitState);
+ const { loading, error, poseInfos } = usePoses(outfitState);
if (loading) {
return null;
@@ -45,19 +45,15 @@ function PosePicker({
}
// If there's only one pose anyway, don't bother showing a picker!
- const numAvailablePoses = Object.values(poses).filter((p) => p.isAvailable)
- .length;
+ const numAvailablePoses = Object.values(poseInfos).filter(
+ (p) => p.isAvailable
+ ).length;
if (numAvailablePoses <= 1) {
return null;
}
const onChange = (e) => {
- const [emotion, genderPresentation] = e.target.value.split("-");
- dispatchToOutfit({
- type: "setPose",
- emotion,
- genderPresentation,
- });
+ dispatchToOutfit({ type: "setPose", pose: e.target.value });
};
return (
@@ -99,13 +95,13 @@ function PosePicker({
isOpen && "is-open"
)}
>
- {outfitState.emotion === "HAPPY" && (
+ {getEmotion(outfitState.pose) === "HAPPY" && (
)}
- {outfitState.emotion === "SAD" && (
+ {getEmotion(outfitState.pose) === "SAD" && (
)}
- {outfitState.emotion === "SICK" && (
+ {getEmotion(outfitState.pose) === "SICK" && (
)}
@@ -133,24 +129,30 @@ function PosePicker({
-
|
-
|
-
|
@@ -159,24 +161,30 @@ function PosePicker({
-
|
-
|
-
|
@@ -213,14 +221,14 @@ const GENDER_PRESENTATION_STRINGS = {
FEMININE: "Feminine",
};
-function PoseButton({ pose, onChange, inputRef }) {
+function PoseOption({ poseInfo, onChange, inputRef }) {
const theme = useTheme();
const genderPresentationStr =
- GENDER_PRESENTATION_STRINGS[pose.genderPresentation];
- const emotionStr = EMOTION_STRINGS[pose.emotion];
+ GENDER_PRESENTATION_STRINGS[poseInfo.genderPresentation];
+ const emotionStr = EMOTION_STRINGS[poseInfo.emotion];
let label = `${emotionStr} and ${genderPresentationStr}`;
- if (!pose.isAvailable) {
+ if (!poseInfo.isAvailable) {
label += ` (not modeled yet)`;
}
@@ -239,9 +247,9 @@ function PoseButton({ pose, onChange, inputRef }) {
type="radio"
aria-label={label}
name="pose"
- value={`${pose.emotion}-${pose.genderPresentation}`}
- checked={pose.isSelected}
- disabled={!pose.isAvailable}
+ value={poseInfo.pose}
+ checked={poseInfo.isSelected}
+ disabled={!poseInfo.isAvailable}
onChange={onChange}
ref={inputRef || null}
/>
@@ -253,11 +261,11 @@ function PoseButton({ pose, onChange, inputRef }) {
width="50px"
height="50px"
title={
- pose.isAvailable
+ poseInfo.isAvailable
? // A lil debug output, so that we can quickly identify glitched
// PetStates and manually mark them as glitched!
window.location.hostname.includes("localhost") &&
- `#${pose.petStateId}`
+ `#${poseInfo.petStateId}`
: "Not modeled yet"
}
position="relative"
@@ -298,18 +306,18 @@ function PoseButton({ pose, onChange, inputRef }) {
border-width: 3px;
}
`,
- !pose.isAvailable && "not-available"
+ !poseInfo.isAvailable && "not-available"
)}
/>
- {pose.isAvailable ? (
+ {poseInfo.isAvailable ? (
-
+
) : (
@@ -342,8 +350,7 @@ function usePoses(outfitState) {
id
petStateId
bodyId
- genderPresentation
- emotion
+ pose
approximateThumbnailUrl
...PetAppearanceForOutfitPreview
}
@@ -354,28 +361,39 @@ function usePoses(outfitState) {
);
const petAppearances = data?.petAppearances || [];
- const buildPose = (e, gp) => {
- const appearance = petAppearances.find(
- (pa) => pa.emotion === e && pa.genderPresentation === gp
- );
+ const buildPoseInfo = (pose) => {
+ const appearance = petAppearances.find((pa) => pa.pose === pose);
return {
...appearance,
isAvailable: Boolean(appearance),
- isSelected:
- outfitState.emotion === e && outfitState.genderPresentation === gp,
+ isSelected: outfitState.pose === pose,
};
};
- const poses = {
- happyMasc: buildPose("HAPPY", "MASCULINE"),
- sadMasc: buildPose("SAD", "MASCULINE"),
- sickMasc: buildPose("SICK", "MASCULINE"),
- happyFem: buildPose("HAPPY", "FEMININE"),
- sadFem: buildPose("SAD", "FEMININE"),
- sickFem: buildPose("SICK", "FEMININE"),
+ const poseInfos = {
+ happyMasc: buildPoseInfo("HAPPY_MASC"),
+ sadMasc: buildPoseInfo("SAD_MASC"),
+ sickMasc: buildPoseInfo("SICK_MASC"),
+ happyFem: buildPoseInfo("HAPPY_FEM"),
+ sadFem: buildPoseInfo("SAD_FEM"),
+ sickFem: buildPoseInfo("SICK_FEM"),
};
- return { loading, error, poses };
+ return { loading, error, poseInfos };
+}
+
+function getEmotion(pose) {
+ if (["HAPPY_MASC", "HAPPY_FEM"].includes(pose)) {
+ return "HAPPY";
+ } else if (["SAD_MASC", "SAD_FEM"].includes(pose)) {
+ return "SAD";
+ } else if (["SICK_MASC", "SICK_FEM"].includes(pose)) {
+ return "SICK";
+ } else if (["UNCONVERTED", "UNKNOWN"].includes(pose)) {
+ return null;
+ } else {
+ throw new Error(`unrecognized pose ${JSON.stringify(pose)}`);
+ }
}
const transformsByBodyId = {
diff --git a/src/app/apolloClient.js b/src/app/apolloClient.js
index 0f4e7d0..c270e8b 100644
--- a/src/app/apolloClient.js
+++ b/src/app/apolloClient.js
@@ -16,8 +16,8 @@ const cacheRedirects = {
// way, when you switch pet poses, Apollo knows it already has the
// appearance data and doesn't need to ask the server again!
petAppearance: (_, args, { getCacheKey }) => {
- const { speciesId, colorId, emotion, genderPresentation } = args;
- const id = `${speciesId}-${colorId}-${emotion}-${genderPresentation}`;
+ const { speciesId, colorId, pose } = args;
+ const id = `${speciesId}-${colorId}-${pose}`;
return getCacheKey({ __typename: "PetAppearance", id });
},
},
diff --git a/src/app/useOutfitAppearance.js b/src/app/useOutfitAppearance.js
index 93250cf..0e7aa3a 100644
--- a/src/app/useOutfitAppearance.js
+++ b/src/app/useOutfitAppearance.js
@@ -6,13 +6,7 @@ import { useQuery } from "@apollo/react-hooks";
* visibleLayers for rendering.
*/
export default function useOutfitAppearance(outfitState) {
- const {
- wornItemIds,
- speciesId,
- colorId,
- emotion,
- genderPresentation,
- } = outfitState;
+ const { wornItemIds, speciesId, colorId, pose } = outfitState;
const { loading, error, data } = useQuery(
gql`
@@ -20,15 +14,9 @@ export default function useOutfitAppearance(outfitState) {
$wornItemIds: [ID!]!
$speciesId: ID!
$colorId: ID!
- $emotion: Emotion!
- $genderPresentation: GenderPresentation!
+ $pose: Pose!
) {
- petAppearance(
- speciesId: $speciesId
- colorId: $colorId
- emotion: $emotion
- genderPresentation: $genderPresentation
- ) {
+ petAppearance(speciesId: $speciesId, colorId: $colorId, pose: $pose) {
...PetAppearanceForOutfitPreview
}
@@ -47,8 +35,7 @@ export default function useOutfitAppearance(outfitState) {
wornItemIds,
speciesId,
colorId,
- emotion,
- genderPresentation,
+ pose,
},
}
);
diff --git a/src/app/useOutfitState.js b/src/app/useOutfitState.js
index 8618d85..45bc358 100644
--- a/src/app/useOutfitState.js
+++ b/src/app/useOutfitState.js
@@ -15,7 +15,7 @@ function useOutfitState() {
initialState
);
- const { name, speciesId, colorId, emotion, genderPresentation } = state;
+ const { name, speciesId, colorId, pose } = state;
// It's more convenient to manage these as a Set in state, but most callers
// will find it more convenient to access them as arrays! e.g. for `.map()`
@@ -84,8 +84,7 @@ function useOutfitState() {
allItemIds,
speciesId,
colorId,
- emotion,
- genderPresentation,
+ pose,
url,
};
@@ -159,28 +158,21 @@ const outfitStateReducer = (apolloClient) => (baseState, action) => {
closetedItemIds.delete(itemId);
});
case "setPose":
- return produce(baseState, (state) => {
- const { emotion, genderPresentation } = action;
- state.emotion = emotion;
- state.genderPresentation = genderPresentation;
- });
+ return { ...baseState, pose: action.pose };
case "reset":
return produce(baseState, (state) => {
const {
name,
speciesId,
colorId,
- emotion,
- genderPresentation,
+ pose,
wornItemIds,
closetedItemIds,
} = action;
state.name = name;
state.speciesId = speciesId ? String(speciesId) : baseState.speciesId;
state.colorId = colorId ? String(colorId) : baseState.colorId;
- state.emotion = emotion || baseState.emotion;
- state.genderPresentation =
- genderPresentation || baseState.genderPresentation;
+ state.pose = pose || baseState.pose;
state.wornItemIds = wornItemIds
? new Set(wornItemIds.map(String))
: baseState.wornItemIds;
@@ -199,8 +191,7 @@ function parseOutfitUrl() {
name: urlParams.get("name"),
speciesId: urlParams.get("species"),
colorId: urlParams.get("color"),
- emotion: urlParams.get("emotion") || "HAPPY",
- genderPresentation: urlParams.get("genderPresentation") || "FEMININE",
+ pose: urlParams.get("pose") || "HAPPY_FEM",
wornItemIds: new Set(urlParams.getAll("objects[]")),
closetedItemIds: new Set(urlParams.getAll("closet[]")),
};
@@ -335,8 +326,7 @@ function buildOutfitUrl(state) {
name,
speciesId,
colorId,
- emotion,
- genderPresentation,
+ pose,
wornItemIds,
closetedItemIds,
} = state;
@@ -345,8 +335,7 @@ function buildOutfitUrl(state) {
name: name || "",
species: speciesId,
color: colorId,
- emotion,
- genderPresentation,
+ pose,
});
for (const itemId of wornItemIds) {
params.append("objects[]", itemId);
diff --git a/src/server/__snapshots__/getValidPetPoses.test.js.snap b/src/server/__snapshots__/getValidPetPoses.test.js.snap
index 60229d1..4efa998 100644
Binary files a/src/server/__snapshots__/getValidPetPoses.test.js.snap and b/src/server/__snapshots__/getValidPetPoses.test.js.snap differ
diff --git a/src/server/getValidPetPoses.js b/src/server/getValidPetPoses.js
index c1b97b7..0cd3972 100644
--- a/src/server/getValidPetPoses.js
+++ b/src/server/getValidPetPoses.js
@@ -1,25 +1,25 @@
import connectToDb from "./db";
-import { getPose } from "./util";
+import { getPoseFromPetState, normalizeRow } from "./util";
export default async function getValidPetPoses() {
const db = await connectToDb();
const numSpeciesPromise = getNumSpecies(db);
const numColorsPromise = getNumColors(db);
- const poseTuplesPromise = getPoseTuples(db);
+ const distinctPetStatesPromise = getDistinctPetStates(db);
- const [numSpecies, numColors, poseTuples] = await Promise.all([
+ const [numSpecies, numColors, distinctPetStates] = await Promise.all([
numSpeciesPromise,
numColorsPromise,
- poseTuplesPromise,
+ distinctPetStatesPromise,
]);
const poseStrs = new Set();
- for (const poseTuple of poseTuples) {
- const { species_id, color_id, mood_id, female, unconverted } = poseTuple;
- const pose = getPose(mood_id, female, unconverted);
- const poseStr = `${species_id}-${color_id}-${pose}`;
+ for (const petState of distinctPetStates) {
+ const { speciesId, colorId } = petState;
+ const pose = getPoseFromPetState(petState);
+ const poseStr = `${speciesId}-${colorId}-${pose}`;
poseStrs.add(poseStr);
}
@@ -77,11 +77,11 @@ async function getNumColors(db) {
return rows[0]["count(*)"];
}
-async function getPoseTuples(db) {
+async function getDistinctPetStates(db) {
const [rows, _] = await db.query(`
SELECT DISTINCT species_id, color_id, mood_id, female, unconverted
FROM pet_states
INNER JOIN pet_types ON pet_types.id = pet_states.pet_type_id
WHERE glitched IS false AND color_id >= 1`);
- return rows;
+ return rows.map(normalizeRow);
}
diff --git a/src/server/getValidPetPoses.test.js b/src/server/getValidPetPoses.test.js
index 18ee109..e142ef9 100644
--- a/src/server/getValidPetPoses.test.js
+++ b/src/server/getValidPetPoses.test.js
@@ -3,6 +3,15 @@ import getValidPetPoses from "./getValidPetPoses";
describe("getValidPetPoses", () => {
it("gets them and writes them to a buffer", async () => {
const buffer = await getValidPetPoses();
- expect(buffer.toString()).toMatchSnapshot();
+ expect(asBinaryString(buffer)).toMatchSnapshot();
});
});
+
+function asBinaryString(buffer) {
+ let str = "";
+ for (let i = 0; i < buffer.length; i++) {
+ const byte = buffer.readUInt8(i);
+ str += byte.toString(2).padStart(8, "0") + "\n";
+ }
+ return str;
+}
diff --git a/src/server/index.js b/src/server/index.js
index 6c54348..4570a84 100644
--- a/src/server/index.js
+++ b/src/server/index.js
@@ -3,7 +3,12 @@ const { gql } = require("apollo-server");
const connectToDb = require("./db");
const buildLoaders = require("./loaders");
const neopets = require("./neopets");
-const { capitalize, getEmotion, getGenderPresentation } = require("./util");
+const {
+ capitalize,
+ getPoseFromPetState,
+ getEmotion,
+ getGenderPresentation,
+} = require("./util");
const typeDefs = gql`
enum LayerImageSize {
@@ -12,6 +17,20 @@ const typeDefs = gql`
SIZE_150
}
+ """
+ The poses a PetAppearance can take!
+ """
+ enum Pose {
+ HAPPY_MASC
+ SAD_MASC
+ SICK_MASC
+ HAPPY_FEM
+ SAD_FEM
+ SICK_FEM
+ UNCONVERTED
+ UNKNOWN # for when we have the data, but we don't know what it is
+ }
+
"""
A pet's gender presentation: masculine or feminine.
@@ -50,8 +69,9 @@ const typeDefs = gql`
id: ID!
petStateId: ID!
bodyId: ID!
- genderPresentation: GenderPresentation
- emotion: Emotion
+ pose: Pose!
+ genderPresentation: GenderPresentation # deprecated
+ emotion: Emotion # deprecated
approximateThumbnailUrl: String!
layers: [AppearanceLayer!]!
}
@@ -120,12 +140,7 @@ const typeDefs = gql`
offset: Int
limit: Int
): ItemSearchResult!
- petAppearance(
- speciesId: ID!
- colorId: ID!
- emotion: Emotion!
- genderPresentation: GenderPresentation!
- ): PetAppearance
+ petAppearance(speciesId: ID!, colorId: ID!, pose: Pose!): PetAppearance
petAppearances(speciesId: ID!, colorId: ID!): [PetAppearance!]!
petOnNeopetsDotCom(petName: String!): Outfit
@@ -177,15 +192,15 @@ const resolvers = {
PetAppearance: {
id: ({ petType, petState }) => {
const { speciesId, colorId } = petType;
- const emotion = getEmotion(petState.moodId);
- const genderPresentation = getGenderPresentation(petState.female);
- return `${speciesId}-${colorId}-${emotion}-${genderPresentation}`;
+ const pose = getPoseFromPetState(petState);
+ return `${speciesId}-${colorId}-${pose}`;
},
petStateId: ({ petState }) => petState.id,
bodyId: ({ petType }) => petType.bodyId,
+ pose: ({ petState }) => getPoseFromPetState(petState),
genderPresentation: ({ petState }) =>
- getGenderPresentation(petState.female),
- emotion: ({ petState }) => getEmotion(petState.moodId),
+ getGenderPresentation(getPoseFromPetState(petState)),
+ emotion: ({ petState }) => getEmotion(getPoseFromPetState(petState)),
approximateThumbnailUrl: ({ petType, petState }) => {
return `http://pets.neopets.com/cp/${petType.basicImageHash}/${petState.moodId}/1.png`;
},
@@ -309,7 +324,7 @@ const resolvers = {
},
petAppearance: async (
_,
- { speciesId, colorId, emotion, genderPresentation },
+ { speciesId, colorId, pose },
{ petTypeLoader, petStateLoader }
) => {
const petType = await petTypeLoader.load({
@@ -319,11 +334,7 @@ const resolvers = {
const petStates = await petStateLoader.load(petType.id);
// TODO: This could be optimized into the query condition 🤔
- const petState = petStates.find(
- (ps) =>
- getEmotion(ps.moodId) === emotion &&
- getGenderPresentation(ps.female) === genderPresentation
- );
+ const petState = petStates.find((ps) => getPoseFromPetState(ps) === pose);
if (!petState) {
return null;
}
diff --git a/src/server/loaders.js b/src/server/loaders.js
index 15bd4c6..68c6919 100644
--- a/src/server/loaders.js
+++ b/src/server/loaders.js
@@ -1,4 +1,5 @@
const DataLoader = require("dataloader");
+const { normalizeRow } = require("./util");
const loadAllColors = (db) => async () => {
const [rows, _] = await db.execute(`SELECT * FROM colors WHERE prank = 0`);
@@ -277,18 +278,6 @@ const buildZoneTranslationLoader = (db) =>
);
});
-function normalizeRow(row) {
- const normalizedRow = {};
- for (let [key, value] of Object.entries(row)) {
- key = key.replace(/_([a-z])/gi, (m) => m[1].toUpperCase());
- if ((key === "id" || key.endsWith("Id")) && typeof value === "number") {
- value = String(value);
- }
- normalizedRow[key] = value;
- }
- return normalizedRow;
-}
-
function buildLoaders(db) {
return {
loadAllColors: loadAllColors(db),
diff --git a/src/server/query-tests/PetAppearance.test.js b/src/server/query-tests/PetAppearance.test.js
index c4bc806..71a15ce 100644
--- a/src/server/query-tests/PetAppearance.test.js
+++ b/src/server/query-tests/PetAppearance.test.js
@@ -6,12 +6,7 @@ describe("PetAppearance", () => {
const res = await query({
query: gql`
query {
- petAppearance(
- speciesId: "54"
- colorId: "75"
- emotion: HAPPY
- genderPresentation: FEMININE
- ) {
+ petAppearance(speciesId: "54", colorId: "75", pose: HAPPY_FEM) {
layers {
id
imageUrl(size: SIZE_600)
@@ -77,6 +72,7 @@ describe("PetAppearance", () => {
id
bodyId
petStateId
+ pose
genderPresentation
emotion
approximateThumbnailUrl
diff --git a/src/server/query-tests/__snapshots__/PetAppearance.test.js.snap b/src/server/query-tests/__snapshots__/PetAppearance.test.js.snap
index 5d48a66..58ca2eb 100644
--- a/src/server/query-tests/__snapshots__/PetAppearance.test.js.snap
+++ b/src/server/query-tests/__snapshots__/PetAppearance.test.js.snap
@@ -64,8 +64,8 @@ Object {
"approximateThumbnailUrl": "http://pets.neopets.com/cp/vghhzlgf/1/1.png",
"bodyId": "180",
"emotion": "HAPPY",
- "genderPresentation": "FEMININE",
- "id": "54-75-HAPPY-FEMININE",
+ "genderPresentation": "MASCULINE",
+ "id": "54-75-HAPPY_FEM",
"layers": Array [
Object {
"id": "5995",
@@ -111,13 +111,14 @@ Object {
},
],
"petStateId": "17723",
+ "pose": "HAPPY_FEM",
},
Object {
"approximateThumbnailUrl": "http://pets.neopets.com/cp/vghhzlgf/1/1.png",
"bodyId": "180",
"emotion": "HAPPY",
"genderPresentation": "MASCULINE",
- "id": "54-75-HAPPY-MASCULINE",
+ "id": "54-75-HAPPY_MASC",
"layers": Array [
Object {
"id": "5995",
@@ -163,13 +164,14 @@ Object {
},
],
"petStateId": "17742",
+ "pose": "HAPPY_MASC",
},
Object {
"approximateThumbnailUrl": "http://pets.neopets.com/cp/vghhzlgf/4/1.png",
"bodyId": "180",
"emotion": "SICK",
- "genderPresentation": "FEMININE",
- "id": "54-75-SICK-FEMININE",
+ "genderPresentation": "MASCULINE",
+ "id": "54-75-SICK_FEM",
"layers": Array [
Object {
"id": "5995",
@@ -215,13 +217,14 @@ Object {
},
],
"petStateId": "10014",
+ "pose": "SICK_FEM",
},
Object {
"approximateThumbnailUrl": "http://pets.neopets.com/cp/vghhzlgf/4/1.png",
"bodyId": "180",
"emotion": "SICK",
"genderPresentation": "MASCULINE",
- "id": "54-75-SICK-MASCULINE",
+ "id": "54-75-SICK_MASC",
"layers": Array [
Object {
"id": "5995",
@@ -267,13 +270,14 @@ Object {
},
],
"petStateId": "11089",
+ "pose": "SICK_MASC",
},
Object {
"approximateThumbnailUrl": "http://pets.neopets.com/cp/vghhzlgf/2/1.png",
"bodyId": "180",
"emotion": "SAD",
- "genderPresentation": "FEMININE",
- "id": "54-75-SAD-FEMININE",
+ "genderPresentation": "MASCULINE",
+ "id": "54-75-SAD_FEM",
"layers": Array [
Object {
"id": "5995",
@@ -319,13 +323,14 @@ Object {
},
],
"petStateId": "5991",
+ "pose": "SAD_FEM",
},
Object {
"approximateThumbnailUrl": "http://pets.neopets.com/cp/vghhzlgf/2/1.png",
"bodyId": "180",
"emotion": "SAD",
"genderPresentation": "MASCULINE",
- "id": "54-75-SAD-MASCULINE",
+ "id": "54-75-SAD_MASC",
"layers": Array [
Object {
"id": "5995",
@@ -371,13 +376,14 @@ Object {
},
],
"petStateId": "436",
+ "pose": "SAD_MASC",
},
Object {
"approximateThumbnailUrl": "http://pets.neopets.com/cp/vghhzlgf/null/1.png",
"bodyId": "180",
"emotion": null,
"genderPresentation": null,
- "id": "54-75-null-null",
+ "id": "54-75-UNKNOWN",
"layers": Array [
Object {
"id": "5995",
@@ -430,13 +436,14 @@ Object {
},
],
"petStateId": "2",
+ "pose": "UNKNOWN",
},
Object {
"approximateThumbnailUrl": "http://pets.neopets.com/cp/vghhzlgf/null/1.png",
"bodyId": "180",
"emotion": null,
"genderPresentation": null,
- "id": "54-75-null-null",
+ "id": "54-75-UNKNOWN",
"layers": Array [
Object {
"id": "5995",
@@ -489,6 +496,7 @@ Object {
},
],
"petStateId": "4751",
+ "pose": "UNKNOWN",
},
],
}
diff --git a/src/server/util.js b/src/server/util.js
index 7220935..aa746c1 100644
--- a/src/server/util.js
+++ b/src/server/util.js
@@ -2,55 +2,77 @@ function capitalize(str) {
return str[0].toUpperCase() + str.slice(1);
}
-function getEmotion(moodId) {
- if (String(moodId) === "1") {
+function getEmotion(pose) {
+ if (["HAPPY_MASC", "HAPPY_FEM"].includes(pose)) {
return "HAPPY";
- } else if (String(moodId) === "2") {
+ } else if (["SAD_MASC", "SAD_FEM"].includes(pose)) {
return "SAD";
- } else if (String(moodId) === "4") {
+ } else if (["SICK_MASC", "SICK_FEM"].includes(pose)) {
return "SICK";
- } else if (moodId === null) {
+ } else if (["UNCONVERTED", "UNKNOWN"].includes(pose)) {
return null;
} else {
- throw new Error(`unrecognized moodId ${JSON.stringify(moodId)}`);
+ throw new Error(`unrecognized pose ${JSON.stringify(pose)}`);
}
}
-function getGenderPresentation(modelPetWasFemale) {
- if (String(modelPetWasFemale) === "1") {
- return "FEMININE";
- } else if (String(modelPetWasFemale) === "0") {
+function getGenderPresentation(pose) {
+ if (["HAPPY_MASC", "SAD_MASC", "SICK_MASC"].includes(pose)) {
return "MASCULINE";
- } else {
+ } else if (["HAPPY_FEM", "SAD_FEM", "SICK_FEM"].includes(pose)) {
+ return "MASCULINE";
+ } else if (["UNCONVERTED", "UNKNOWN"].includes(pose)) {
return null;
+ } else {
+ throw new Error(`unrecognized pose ${JSON.stringify(pose)}`);
}
}
-function getPose(moodId, modelPetWasFemale, isUnconverted) {
- if (isUnconverted) {
+function getPoseFromPetState(petState) {
+ const { moodId, female, unconverted } = petState;
+
+ if (unconverted) {
return "UNCONVERTED";
- } else if (moodId == null || modelPetWasFemale == null) {
+ } else if (moodId == null || female == null) {
return "UNKNOWN";
- } else if (String(moodId) === "1" && String(modelPetWasFemale) === "0") {
+ } else if (String(moodId) === "1" && String(female) === "0") {
return "HAPPY_MASC";
- } else if (String(moodId) === "1" && String(modelPetWasFemale) === "1") {
+ } else if (String(moodId) === "1" && String(female) === "1") {
return "HAPPY_FEM";
- } else if (String(moodId) === "2" && String(modelPetWasFemale) === "0") {
+ } else if (String(moodId) === "2" && String(female) === "0") {
return "SAD_MASC";
- } else if (String(moodId) === "2" && String(modelPetWasFemale) === "1") {
+ } else if (String(moodId) === "2" && String(female) === "1") {
return "SAD_FEM";
- } else if (String(moodId) === "4" && String(modelPetWasFemale) === "0") {
+ } else if (String(moodId) === "4" && String(female) === "0") {
return "SICK_MASC";
- } else if (String(moodId) === "4" && String(modelPetWasFemale) === "1") {
+ } else if (String(moodId) === "4" && String(female) === "1") {
return "SICK_FEM";
} else {
throw new Error(
`could not identify pose: ` +
`moodId=${moodId}, ` +
- `modelPetWasFemale=${modelPetWasFemale}, ` +
- `isUnconverted=${isUnconverted}`
+ `female=${female}, ` +
+ `unconverted=${unconverted}`
);
}
}
-module.exports = { capitalize, getEmotion, getGenderPresentation, getPose };
+function normalizeRow(row) {
+ const normalizedRow = {};
+ for (let [key, value] of Object.entries(row)) {
+ key = key.replace(/_([a-z])/gi, (m) => m[1].toUpperCase());
+ if ((key === "id" || key.endsWith("Id")) && typeof value === "number") {
+ value = String(value);
+ }
+ normalizedRow[key] = value;
+ }
+ return normalizedRow;
+}
+
+module.exports = {
+ capitalize,
+ getEmotion,
+ getGenderPresentation,
+ getPoseFromPetState,
+ normalizeRow,
+};