refactor Outfit.js to split Pet to a separate type

yeah, I had unified Pet into Outfit, but now I think that was overly clever… 😅

Here, I define a new Pet type, and it has some of the fields of Outfit and the deprecated fields still.

I did this because I want petAppearance to work, for UC testing!
This commit is contained in:
Emi Matchu 2020-09-27 03:18:46 -07:00
parent 94f6363251
commit e57af14625
2 changed files with 61 additions and 24 deletions

View file

@ -324,7 +324,7 @@ const buildItemBodiesWithAppearanceDataLoader = (db) =>
return itemIds.map((itemId) => entities.filter((e) => e.itemId === itemId));
});
const buildPetTypeLoader = (db) =>
const buildPetTypeLoader = (db, loaders) =>
new DataLoader(async (petTypeIds) => {
const qs = petTypeIds.map((_) => "?").join(",");
const [rows, _] = await db.execute(
@ -334,6 +334,13 @@ const buildPetTypeLoader = (db) =>
const entities = rows.map(normalizeRow);
for (const petType of entities) {
loaders.petTypeBySpeciesAndColorLoader.prime(
{ speciesId: petType.speciesId, colorId: petType.colorId },
petType
);
}
return petTypeIds.map((petTypeId) =>
entities.find((e) => e.id === petTypeId)
);
@ -577,7 +584,7 @@ const buildCanonicalPetStateForBodyLoader = (db, loaders) =>
);
});
const buildPetStateByPetTypeAndAssetsLoader = (db) =>
const buildPetStateByPetTypeAndAssetsLoader = (db, loaders) =>
new DataLoader(
async (petTypeIdAndAssetIdsPairs) => {
const qs = petTypeIdAndAssetIdsPairs
@ -593,6 +600,10 @@ const buildPetStateByPetTypeAndAssetsLoader = (db) =>
const entities = rows.map(normalizeRow);
for (const petState of entities) {
loaders.petStateLoader.prime(petState.id, petState);
}
return petTypeIdAndAssetIdsPairs.map(({ petTypeId, swfAssetIds }) =>
entities.find(
(e) => e.petTypeId === petTypeId && e.swfAssetIds === swfAssetIds
@ -721,7 +732,7 @@ function buildLoaders(db) {
loaders.itemBodiesWithAppearanceDataLoader = buildItemBodiesWithAppearanceDataLoader(
db
);
loaders.petTypeLoader = buildPetTypeLoader(db);
loaders.petTypeLoader = buildPetTypeLoader(db, loaders);
loaders.petTypeBySpeciesAndColorLoader = buildPetTypeBySpeciesAndColorLoader(
db,
loaders
@ -744,7 +755,8 @@ function buildLoaders(db) {
loaders
);
loaders.petStateByPetTypeAndAssetsLoader = buildPetStateByPetTypeAndAssetsLoader(
db
db,
loaders
);
loaders.speciesLoader = buildSpeciesLoader(db);
loaders.speciesTranslationLoader = buildSpeciesTranslationLoader(db);

View file

@ -1,5 +1,6 @@
const fetch = require("node-fetch");
const { gql } = require("apollo-server");
const { getPoseFromPetState } = require("../util");
const typeDefs = gql`
type Outfit {
@ -8,6 +9,14 @@ const typeDefs = gql`
petAppearance: PetAppearance!
wornItems: [Item!]!
closetedItems: [Item!]!
}
# TODO: This maybe should move to a separate file?
type Pet {
id: ID!
name: String!
petAppearance: PetAppearance!
wornItems: [Item!]!
species: Species! # to be deprecated? can use petAppearance? 🤔
color: Color! # to be deprecated? can use petAppearance? 🤔
@ -17,7 +26,7 @@ const typeDefs = gql`
extend type Query {
outfit(id: ID!): Outfit
petOnNeopetsDotCom(petName: String!): Outfit
petOnNeopetsDotCom(petName: String!): Pet
}
`;
@ -44,6 +53,37 @@ const resolvers = {
.map((oir) => ({ id: oir.itemId }));
},
},
Pet: {
species: ({ customPetData }) => ({
id: customPetData.custom_pet.species_id,
}),
color: ({ customPetData }) => ({ id: customPetData.custom_pet.color_id }),
pose: ({ customPetData, petMetaData }) =>
getPoseFromPetData(petMetaData, customPetData),
petAppearance: async (
{ customPetData, petMetaData },
_,
{ petTypeBySpeciesAndColorLoader, petStatesForPetTypeLoader }
) => {
const petType = await petTypeBySpeciesAndColorLoader.load({
speciesId: customPetData.custom_pet.species_id,
colorId: customPetData.custom_pet.color_id,
});
const petStates = await petStatesForPetTypeLoader.load(petType.id);
const pose = getPoseFromPetData(petMetaData, customPetData);
const petState = petStates.find((ps) => getPoseFromPetState(ps) === pose);
return { id: petState.id };
},
wornItems: ({ customPetData }) =>
Object.values(customPetData.object_info_registry).map((o) => ({
id: o.obj_info_id,
name: o.name,
description: o.description,
thumbnailUrl: o.thumbnail_url,
rarityIndex: o.rarity_index,
})),
items: (...args) => resolvers.Pet.wornItems(...args),
},
Query: {
outfit: (_, { id }) => ({ id }),
petOnNeopetsDotCom: async (
@ -72,23 +112,7 @@ const resolvers = {
swfAssetByRemoteIdLoader,
});
const outfit = {
// TODO: This isn't a fully-working Outfit object. It works for the
// client as currently implemented, but we'll probably want to
// move the client and this onto our more generic fields!
species: { id: customPetData.custom_pet.species_id },
color: { id: customPetData.custom_pet.color_id },
pose: getPoseFromPetData(petMetaData, customPetData),
items: Object.values(customPetData.object_info_registry).map((o) => ({
id: o.obj_info_id,
name: o.name,
description: o.description,
thumbnailUrl: o.thumbnail_url,
rarityIndex: o.rarity_index,
})),
};
return outfit;
return { name, customPetData, petMetaData };
},
},
};
@ -129,10 +153,11 @@ async function loadCustomPetData(petName) {
}
function getPoseFromPetData(petMetaData, petCustomData) {
// TODO: Use custom data to decide if Unconverted.
const moodId = petMetaData.mood;
const genderId = petMetaData.gender;
if (String(moodId) === "1" && String(genderId) === "1") {
if (Object.keys(petCustomData.custom_pet.biology_by_zone).length === 1) {
return "UNCONVERTED";
} else if (String(moodId) === "1" && String(genderId) === "1") {
return "HAPPY_MASC";
} else if (String(moodId) === "1" && String(genderId) === "2") {
return "HAPPY_FEM";