From eb0a1dc8fb6f0e350f0982be98b2ad83397cb690 Mon Sep 17 00:00:00 2001 From: Jordan Eldredge Date: Sun, 23 Oct 2022 13:43:04 -0700 Subject: [PATCH] Pre-compute skin museum sort order --- packages/skin-database/cli.ts | 11 ++++- packages/skin-database/data/skins.ts | 64 ++++--------------------- packages/skin-database/museumOrder.sql | 66 ++++++++++++++++++++++++++ 3 files changed, 84 insertions(+), 57 deletions(-) create mode 100644 packages/skin-database/museumOrder.sql diff --git a/packages/skin-database/cli.ts b/packages/skin-database/cli.ts index 39fa126f..cdc7e101 100755 --- a/packages/skin-database/cli.ts +++ b/packages/skin-database/cli.ts @@ -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(); } diff --git a/packages/skin-database/data/skins.ts b/packages/skin-database/data/skins.ts index 604a4ede..b89a2f1a 100644 --- a/packages/skin-database/data/skins.ts +++ b/packages/skin-database/data/skins.ts @@ -630,62 +630,14 @@ export async function getMuseumPage({ }): Promise { 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] ); diff --git a/packages/skin-database/museumOrder.sql b/packages/skin-database/museumOrder.sql new file mode 100644 index 00000000..f2314751 --- /dev/null +++ b/packages/skin-database/museumOrder.sql @@ -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; \ No newline at end of file