Pre-compute skin museum sort order

This commit is contained in:
Jordan Eldredge 2022-10-23 13:43:04 -07:00
parent 9bda4b2738
commit eb0a1dc8fb
3 changed files with 84 additions and 57 deletions

View file

@ -332,6 +332,10 @@ program
.option("--refresh-content-hash", "Refresh content hash")
.option("--update-search-index", "Refresh content hash")
.option("--configure-r2-cors", "Configure CORS for r2")
.option(
"--compute-museum-order",
"Compute the order in which skins should be displayed in the museum"
)
.action(async (arg) => {
const {
uploadIaScreenshot,
@ -340,8 +344,13 @@ program
refreshContentHash,
updateSearchIndex,
configureR2Cors,
computeMuseumOrder,
} = arg;
console.log(arg);
if (computeMuseumOrder) {
const sql = fs.readFileSync("./museumOrder.sql", { encoding: "utf8" });
await knex.raw(sql);
console.log("Museum order updated.");
}
if (configureR2Cors) {
await S3.configureCors();
}

View file

@ -630,62 +630,14 @@ export async function getMuseumPage({
}): Promise<MuseumPage> {
const skins = await knex.raw(
`
-- A tweet score for each skin based on its tweets.
WITH skin_tweets as (
SELECT
skin_md5,
MAX(likes) as likes,
MAX(retweets) as retweets,
(IFNULL(likes, 0) + (IFNULL(retweets, 0) * 1.5)) AS tweet_score
FROM
tweets
GROUP BY
skin_md5
)
SELECT
skins.md5,
files.file_path,
skin_reviews.review = 'NSFW' AS nsfw
FROM
skins
LEFT JOIN museum_sort_overrides ON museum_sort_overrides.skin_md5 = skins.md5
LEFT JOIN skin_tweets ON skin_tweets.skin_md5 = skins.md5
LEFT JOIN skin_reviews ON skin_reviews.skin_md5 = skins.md5
LEFT JOIN files ON files.skin_md5 = skins.md5
LEFT JOIN refreshes ON refreshes.skin_md5 = skins.md5
WHERE
-- Only show classic skins
skin_type = 1
-- Hide skins that are dupes or we otherwise want to hide
AND (museum_sort_overrides.score IS NULL OR museum_sort_overrides.score > 0)
-- Hides skins that might not have a valid screenshot
AND refreshes.error IS NULL
GROUP BY
skins.md5
ORDER BY
-- The secret sauce of the Winamp Skin Museum.
-- We try to rank skins based on how interesting they are to a modern
-- audience by leveraging data accumulated by the @winampskins Twitter bot.
-- 1. Manaully currated skins (the default skin and classic ports of the default modern skins)
-- 2. All tweeted skins ranked by (likes + retweets * 1.5)
-- 3. All approved skins that have not yet been tweeted
-- 4. All unreviewed skins
-- 5. All rejected skins
-- 6. All NSFW skins
-- Show manually currated skins (default skins) first
museum_sort_overrides.score DESC,
-- Sort skins by their popularity on Twitter
tweet_score DESC,
-- Push NSFW skins to the bottom
skin_reviews.review = 'NSFW' ASC,
-- Skins that have been approved are better than others
skin_reviews.review = 'APPROVED' DESC,
-- Skins that have been rejected are worse than those that have not been reviewed
skin_reviews.review = 'REJECTED' ASC
LIMIT ? offset ?`,
SELECT
skins.md5,
(SELECT file_path from files WHERE files.skin_md5 = skins.md5 LIMIT 1) as file_path,
(skins.md5 IN (SELECT skin_reviews.skin_md5 from skin_reviews WHERE skin_reviews.review = 'NSFW')) as nsfw
FROM
museum_sort_order
LEFT JOIN skins ON skins.md5 = museum_sort_order.skin_md5
LIMIT ? OFFSET ?`,
[first, offset]
);

View file

@ -0,0 +1,66 @@
-- Precompute the sort order for the skin musuem.
BEGIN IMMEDIATE TRANSACTION;
CREATE TABLE IF NOT EXISTS museum_sort_order (skin_md5 TEXT references skins(md5));
DELETE FROM museum_sort_order;
INSERT INTO museum_sort_order (skin_md5)
-- A tweet score for each skin based on its tweets.
WITH skin_tweets as (
SELECT
skin_md5,
MAX(likes) as likes,
MAX(retweets) as retweets,
(IFNULL(likes, 0) + (IFNULL(retweets, 0) * 1.5)) AS tweet_score
FROM
tweets
GROUP BY
skin_md5
)
SELECT
skins.md5
-- files.file_path,
-- skin_reviews.review = 'NSFW' AS nsfw
FROM
skins
LEFT JOIN museum_sort_overrides ON museum_sort_overrides.skin_md5 = skins.md5
LEFT JOIN skin_tweets ON skin_tweets.skin_md5 = skins.md5
LEFT JOIN skin_reviews ON skin_reviews.skin_md5 = skins.md5
LEFT JOIN files ON files.skin_md5 = skins.md5
LEFT JOIN refreshes ON refreshes.skin_md5 = skins.md5
WHERE
-- Only show classic skins
skin_type = 1
-- Hide skins that are dupes or we otherwise want to hide
AND (museum_sort_overrides.score IS NULL OR museum_sort_overrides.score > 0)
-- Hides skins that might not have a valid screenshot
AND refreshes.error IS NULL
GROUP BY
skins.md5
ORDER BY
-- The secret sauce of the Winamp Skin Museum.
-- We try to rank skins based on how interesting they are to a modern
-- audience by leveraging data accumulated by the @winampskins Twitter bot.
-- 1. Manaully currated skins (the default skin and classic ports of the default modern skins)
-- 2. All tweeted skins ranked by (likes + retweets * 1.5)
-- 3. All approved skins that have not yet been tweeted
-- 4. All unreviewed skins
-- 5. All rejected skins
-- 6. All NSFW skins
-- Show manually currated skins (default skins) first
museum_sort_overrides.score DESC,
-- Sort skins by their popularity on Twitter
tweet_score DESC,
-- Push NSFW skins to the bottom
skin_reviews.review = 'NSFW' ASC,
-- Skins that have been approved are better than others
skin_reviews.review = 'APPROVED' DESC,
-- Skins that have been rejected are worse than those that have not been reviewed
skin_reviews.review = 'REJECTED' ASC;
COMMIT;