2021-04-23 12:31:41 -07:00
|
|
|
const beeline = require("honeycomb-beeline")({
|
|
|
|
writeKey: process.env["HONEYCOMB_WRITE_KEY"],
|
|
|
|
dataset:
|
|
|
|
process.env["NODE_ENV"] === "production"
|
|
|
|
? "Dress to Impress (2020)"
|
|
|
|
: "Dress to Impress (2020, dev)",
|
|
|
|
serviceName: "impress-2020-gql-server",
|
|
|
|
});
|
2023-08-20 15:40:21 -07:00
|
|
|
import { applyCORSHeaders } from "../../src/server/cors";
|
2021-11-01 22:25:43 -07:00
|
|
|
import connectToDb from "../../src/server/db";
|
|
|
|
import { getPoseFromPetState, normalizeRow } from "../../src/server/util";
|
2020-09-06 00:40:00 -07:00
|
|
|
|
|
|
|
export async function getValidPetPoses() {
|
|
|
|
const db = await connectToDb();
|
|
|
|
|
Fix Juppie Swirl bug in /api/validPetPoses
Oops, the new Juppie Swirl color has ID 114, and there's no released color #113 yet. But our `/api/validPetPoses` code, when deciding how large to make the byte array, uses the _number_ of colors in the database.
This meant that, when Juppie Swirl was released, there wasn't a 114th slot allocated, and the loop stopped at color ID #113—so the new Juppie Swirl color #114 wasn't included in the results. This made it impossible to select Juppie Swirl as a starting color. (You could, however, model a Juppie Swirl Chia, and the wardrobe would load it successfully; and you would see the color/species picker with the correct options selected, but in a red "invalid" state.)
Now, we instead use the largest ID in the database to determine the size of the array. This means Juppie Swirl is now included correctly!
There would be network perf implications if the color IDs were a sparser space, but it's dense enough to be totally fine in practice. (But let's not release an April Fools color #9999 or anything!)
2022-02-23 00:01:10 -08:00
|
|
|
const largestSpeciesIdPromise = getLargestSpeciesId(db);
|
|
|
|
const largestColorIdPromise = getLargestColorId(db);
|
2020-09-06 00:40:00 -07:00
|
|
|
const distinctPetStatesPromise = getDistinctPetStates(db);
|
|
|
|
|
2024-09-27 19:41:52 -07:00
|
|
|
const [largestSpeciesId, largestColorId, distinctPetStates] =
|
|
|
|
await Promise.all([
|
|
|
|
largestSpeciesIdPromise,
|
|
|
|
largestColorIdPromise,
|
|
|
|
distinctPetStatesPromise,
|
|
|
|
]);
|
2020-09-06 00:40:00 -07:00
|
|
|
|
|
|
|
const poseStrs = new Set();
|
|
|
|
for (const petState of distinctPetStates) {
|
|
|
|
const { speciesId, colorId } = petState;
|
|
|
|
const pose = getPoseFromPetState(petState);
|
|
|
|
const poseStr = `${speciesId}-${colorId}-${pose}`;
|
|
|
|
poseStrs.add(poseStr);
|
|
|
|
}
|
|
|
|
|
|
|
|
function hasPose(speciesId, colorId, pose) {
|
|
|
|
const poseStr = `${speciesId}-${colorId}-${pose}`;
|
|
|
|
return poseStrs.has(poseStr);
|
|
|
|
}
|
|
|
|
|
Fix Juppie Swirl bug in /api/validPetPoses
Oops, the new Juppie Swirl color has ID 114, and there's no released color #113 yet. But our `/api/validPetPoses` code, when deciding how large to make the byte array, uses the _number_ of colors in the database.
This meant that, when Juppie Swirl was released, there wasn't a 114th slot allocated, and the loop stopped at color ID #113—so the new Juppie Swirl color #114 wasn't included in the results. This made it impossible to select Juppie Swirl as a starting color. (You could, however, model a Juppie Swirl Chia, and the wardrobe would load it successfully; and you would see the color/species picker with the correct options selected, but in a red "invalid" state.)
Now, we instead use the largest ID in the database to determine the size of the array. This means Juppie Swirl is now included correctly!
There would be network perf implications if the color IDs were a sparser space, but it's dense enough to be totally fine in practice. (But let's not release an April Fools color #9999 or anything!)
2022-02-23 00:01:10 -08:00
|
|
|
// NOTE: We base the size of the array on the _largest_ color and species IDs
|
|
|
|
// in the database, not the _number_ of colors and species. This is
|
|
|
|
// because TNT sometimes skips IDs when working on multiple colors at
|
|
|
|
// once, so it's possible to have e.g. 113 released colors, but have
|
|
|
|
// the largest color ID be #114, because #113 was skipped. In that case,
|
|
|
|
// we leave an empty byte at skipped IDs, and that's okay because they
|
|
|
|
// don't skip a whole bunch of color IDs at once. (This would be a bad
|
|
|
|
// idea for network perf if e.g. TNT skipped to color #9999, because we
|
|
|
|
// would then leave a LOT of empty bytes in the array!)
|
|
|
|
const numPairs = largestSpeciesId * largestColorId;
|
2020-09-06 00:40:00 -07:00
|
|
|
const buffer = Buffer.alloc(numPairs + 2);
|
Fix Juppie Swirl bug in /api/validPetPoses
Oops, the new Juppie Swirl color has ID 114, and there's no released color #113 yet. But our `/api/validPetPoses` code, when deciding how large to make the byte array, uses the _number_ of colors in the database.
This meant that, when Juppie Swirl was released, there wasn't a 114th slot allocated, and the loop stopped at color ID #113—so the new Juppie Swirl color #114 wasn't included in the results. This made it impossible to select Juppie Swirl as a starting color. (You could, however, model a Juppie Swirl Chia, and the wardrobe would load it successfully; and you would see the color/species picker with the correct options selected, but in a red "invalid" state.)
Now, we instead use the largest ID in the database to determine the size of the array. This means Juppie Swirl is now included correctly!
There would be network perf implications if the color IDs were a sparser space, but it's dense enough to be totally fine in practice. (But let's not release an April Fools color #9999 or anything!)
2022-02-23 00:01:10 -08:00
|
|
|
buffer.writeUInt8(largestSpeciesId, 0);
|
|
|
|
buffer.writeUInt8(largestColorId, 1);
|
2020-09-06 00:40:00 -07:00
|
|
|
|
Fix Juppie Swirl bug in /api/validPetPoses
Oops, the new Juppie Swirl color has ID 114, and there's no released color #113 yet. But our `/api/validPetPoses` code, when deciding how large to make the byte array, uses the _number_ of colors in the database.
This meant that, when Juppie Swirl was released, there wasn't a 114th slot allocated, and the loop stopped at color ID #113—so the new Juppie Swirl color #114 wasn't included in the results. This made it impossible to select Juppie Swirl as a starting color. (You could, however, model a Juppie Swirl Chia, and the wardrobe would load it successfully; and you would see the color/species picker with the correct options selected, but in a red "invalid" state.)
Now, we instead use the largest ID in the database to determine the size of the array. This means Juppie Swirl is now included correctly!
There would be network perf implications if the color IDs were a sparser space, but it's dense enough to be totally fine in practice. (But let's not release an April Fools color #9999 or anything!)
2022-02-23 00:01:10 -08:00
|
|
|
for (let speciesId = 1; speciesId <= largestSpeciesId; speciesId++) {
|
2020-09-06 00:40:00 -07:00
|
|
|
const speciesIndex = speciesId - 1;
|
Fix Juppie Swirl bug in /api/validPetPoses
Oops, the new Juppie Swirl color has ID 114, and there's no released color #113 yet. But our `/api/validPetPoses` code, when deciding how large to make the byte array, uses the _number_ of colors in the database.
This meant that, when Juppie Swirl was released, there wasn't a 114th slot allocated, and the loop stopped at color ID #113—so the new Juppie Swirl color #114 wasn't included in the results. This made it impossible to select Juppie Swirl as a starting color. (You could, however, model a Juppie Swirl Chia, and the wardrobe would load it successfully; and you would see the color/species picker with the correct options selected, but in a red "invalid" state.)
Now, we instead use the largest ID in the database to determine the size of the array. This means Juppie Swirl is now included correctly!
There would be network perf implications if the color IDs were a sparser space, but it's dense enough to be totally fine in practice. (But let's not release an April Fools color #9999 or anything!)
2022-02-23 00:01:10 -08:00
|
|
|
for (let colorId = 1; colorId <= largestColorId; colorId++) {
|
2020-09-06 00:40:00 -07:00
|
|
|
const colorIndex = colorId - 1;
|
|
|
|
|
|
|
|
// We fill in the high bits first, and shift left as we go!
|
|
|
|
let byte = 0;
|
|
|
|
byte += hasPose(speciesId, colorId, "UNKNOWN") ? 1 : 0;
|
|
|
|
byte <<= 1;
|
|
|
|
byte += hasPose(speciesId, colorId, "UNCONVERTED") ? 1 : 0;
|
|
|
|
byte <<= 1;
|
|
|
|
byte += hasPose(speciesId, colorId, "SICK_FEM") ? 1 : 0;
|
|
|
|
byte <<= 1;
|
|
|
|
byte += hasPose(speciesId, colorId, "SAD_FEM") ? 1 : 0;
|
|
|
|
byte <<= 1;
|
|
|
|
byte += hasPose(speciesId, colorId, "HAPPY_FEM") ? 1 : 0;
|
|
|
|
byte <<= 1;
|
|
|
|
byte += hasPose(speciesId, colorId, "SICK_MASC") ? 1 : 0;
|
|
|
|
byte <<= 1;
|
|
|
|
byte += hasPose(speciesId, colorId, "SAD_MASC") ? 1 : 0;
|
|
|
|
byte <<= 1;
|
|
|
|
byte += hasPose(speciesId, colorId, "HAPPY_MASC") ? 1 : 0;
|
|
|
|
|
Fix Juppie Swirl bug in /api/validPetPoses
Oops, the new Juppie Swirl color has ID 114, and there's no released color #113 yet. But our `/api/validPetPoses` code, when deciding how large to make the byte array, uses the _number_ of colors in the database.
This meant that, when Juppie Swirl was released, there wasn't a 114th slot allocated, and the loop stopped at color ID #113—so the new Juppie Swirl color #114 wasn't included in the results. This made it impossible to select Juppie Swirl as a starting color. (You could, however, model a Juppie Swirl Chia, and the wardrobe would load it successfully; and you would see the color/species picker with the correct options selected, but in a red "invalid" state.)
Now, we instead use the largest ID in the database to determine the size of the array. This means Juppie Swirl is now included correctly!
There would be network perf implications if the color IDs were a sparser space, but it's dense enough to be totally fine in practice. (But let's not release an April Fools color #9999 or anything!)
2022-02-23 00:01:10 -08:00
|
|
|
buffer.writeUInt8(byte, speciesIndex * largestColorId + colorIndex + 2);
|
2020-09-06 00:40:00 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return buffer;
|
|
|
|
}
|
|
|
|
|
Fix Juppie Swirl bug in /api/validPetPoses
Oops, the new Juppie Swirl color has ID 114, and there's no released color #113 yet. But our `/api/validPetPoses` code, when deciding how large to make the byte array, uses the _number_ of colors in the database.
This meant that, when Juppie Swirl was released, there wasn't a 114th slot allocated, and the loop stopped at color ID #113—so the new Juppie Swirl color #114 wasn't included in the results. This made it impossible to select Juppie Swirl as a starting color. (You could, however, model a Juppie Swirl Chia, and the wardrobe would load it successfully; and you would see the color/species picker with the correct options selected, but in a red "invalid" state.)
Now, we instead use the largest ID in the database to determine the size of the array. This means Juppie Swirl is now included correctly!
There would be network perf implications if the color IDs were a sparser space, but it's dense enough to be totally fine in practice. (But let's not release an April Fools color #9999 or anything!)
2022-02-23 00:01:10 -08:00
|
|
|
async function getLargestSpeciesId(db) {
|
|
|
|
const [rows] = await db.query(`SELECT max(id) FROM species`);
|
|
|
|
return rows[0]["max(id)"];
|
2020-09-06 00:40:00 -07:00
|
|
|
}
|
|
|
|
|
Fix Juppie Swirl bug in /api/validPetPoses
Oops, the new Juppie Swirl color has ID 114, and there's no released color #113 yet. But our `/api/validPetPoses` code, when deciding how large to make the byte array, uses the _number_ of colors in the database.
This meant that, when Juppie Swirl was released, there wasn't a 114th slot allocated, and the loop stopped at color ID #113—so the new Juppie Swirl color #114 wasn't included in the results. This made it impossible to select Juppie Swirl as a starting color. (You could, however, model a Juppie Swirl Chia, and the wardrobe would load it successfully; and you would see the color/species picker with the correct options selected, but in a red "invalid" state.)
Now, we instead use the largest ID in the database to determine the size of the array. This means Juppie Swirl is now included correctly!
There would be network perf implications if the color IDs were a sparser space, but it's dense enough to be totally fine in practice. (But let's not release an April Fools color #9999 or anything!)
2022-02-23 00:01:10 -08:00
|
|
|
async function getLargestColorId(db) {
|
2024-09-27 19:41:52 -07:00
|
|
|
const [rows] = await db.query(`SELECT max(id) FROM colors`);
|
Fix Juppie Swirl bug in /api/validPetPoses
Oops, the new Juppie Swirl color has ID 114, and there's no released color #113 yet. But our `/api/validPetPoses` code, when deciding how large to make the byte array, uses the _number_ of colors in the database.
This meant that, when Juppie Swirl was released, there wasn't a 114th slot allocated, and the loop stopped at color ID #113—so the new Juppie Swirl color #114 wasn't included in the results. This made it impossible to select Juppie Swirl as a starting color. (You could, however, model a Juppie Swirl Chia, and the wardrobe would load it successfully; and you would see the color/species picker with the correct options selected, but in a red "invalid" state.)
Now, we instead use the largest ID in the database to determine the size of the array. This means Juppie Swirl is now included correctly!
There would be network perf implications if the color IDs were a sparser space, but it's dense enough to be totally fine in practice. (But let's not release an April Fools color #9999 or anything!)
2022-02-23 00:01:10 -08:00
|
|
|
return rows[0]["max(id)"];
|
2020-09-06 00:40:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
async function getDistinctPetStates(db) {
|
2021-05-13 01:13:21 -07:00
|
|
|
const [rows] = await db.query(`
|
2020-09-06 00:40:00 -07:00
|
|
|
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 color_id >= 1`);
|
|
|
|
return rows.map(normalizeRow);
|
|
|
|
}
|
2020-05-03 01:04:34 -07:00
|
|
|
|
2021-04-23 12:31:41 -07:00
|
|
|
async function handle(req, res) {
|
2023-08-20 15:40:21 -07:00
|
|
|
// Apply CORS headers, to allow Classic DTI to request this.
|
|
|
|
// If this is an OPTIONS request asking for CORS info, return an empty
|
|
|
|
// response with just the CORS headers applied.
|
|
|
|
applyCORSHeaders(req, res);
|
|
|
|
if (req.method === "OPTIONS") {
|
|
|
|
return res.status(204).end();
|
|
|
|
}
|
|
|
|
|
2020-05-03 01:04:34 -07:00
|
|
|
const buffer = await getValidPetPoses();
|
2020-05-03 02:13:46 -07:00
|
|
|
|
2021-05-13 01:05:34 -07:00
|
|
|
// Cache for 1 hour, and allow the CDN cache to serve copies up to an
|
|
|
|
// additional week older while re-fetching in the background.
|
|
|
|
res.setHeader("Cache-Control", "max-age=3600, stale-while-revalidate=604800");
|
2020-05-03 02:13:46 -07:00
|
|
|
|
2020-05-03 01:04:34 -07:00
|
|
|
res.status(200).send(buffer);
|
2021-04-23 12:31:41 -07:00
|
|
|
}
|
|
|
|
|
2021-05-13 01:13:21 -07:00
|
|
|
async function handleWithBeeline(req, res) {
|
2021-04-23 12:31:41 -07:00
|
|
|
beeline.withTrace(
|
|
|
|
{ name: "api/validPetPoses", operation_name: "api/validPetPoses" },
|
2024-09-27 19:41:52 -07:00
|
|
|
() => handle(req, res),
|
2021-04-23 12:31:41 -07:00
|
|
|
);
|
2021-05-13 01:13:21 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
export default handleWithBeeline;
|