mirror of
https://github.com/zkldi/Tachi.git
synced 2026-10-04 21:08:09 +03:00
feat: add sdvx PUC tierlists (#1375)
* add sdvx PUC tierlists * address review comments
This commit is contained in:
@@ -2,7 +2,7 @@ import { NumericSOV } from "util/sorts";
|
||||
import { ChangeOpacity } from "util/color-opacity";
|
||||
import { FormatMillions } from "util/misc";
|
||||
import { GPTClientImplementation } from "lib/types";
|
||||
import { COLOUR_SET, GPTStrings, SDVX_GRADES } from "tachi-common";
|
||||
import { COLOUR_SET, GPTStrings, SDVX_GRADES, SDVX_LAMPS } from "tachi-common";
|
||||
import MillionsScoreCell from "components/tables/cells/MillionsScoreCell";
|
||||
import SDVXJudgementCell from "components/tables/cells/SDVXJudgementCell";
|
||||
import SDVXLampCell from "components/tables/cells/SDVXLampCell";
|
||||
@@ -162,6 +162,18 @@ export const SDVX_IMPL: GPTClientImplementation<"sdvx:Single"> = {
|
||||
(c) => c.data.clearTier?.individualDifference,
|
||||
(s) => [s.scoreData.lamp, s.scoreData.lamp !== "FAILED"]
|
||||
),
|
||||
CreateRatingSys(
|
||||
"PUC Tierlist",
|
||||
"Tierlist ratings for PUC lamp",
|
||||
"lamp",
|
||||
(c) => c.data.pucTier?.value,
|
||||
(c) => c.data.pucTier?.text,
|
||||
(c) => c.data.pucTier?.individualDifference,
|
||||
(s) => [
|
||||
s.scoreData.lamp,
|
||||
s.scoreData.enumIndexes.lamp >= SDVX_LAMPS.PERFECT_ULTIMATE_CHAIN,
|
||||
]
|
||||
),
|
||||
CreateRatingSys(
|
||||
"S Tierlist",
|
||||
"Tierlist ratings for S grade",
|
||||
|
||||
@@ -187,6 +187,7 @@ export const SDVX_SINGLE_CONF = {
|
||||
chartData: z.strictObject({
|
||||
inGameID: zodNonNegativeInt,
|
||||
clearTier: zodTierlistData,
|
||||
pucTier: zodTierlistData,
|
||||
sTier: zodTierlistData,
|
||||
}),
|
||||
|
||||
|
||||
+14389
-2399
File diff suppressed because it is too large
Load Diff
@@ -8,9 +8,72 @@ import * as cheerio from "cheerio";
|
||||
type SDVXChart = ChartDocument<"sdvx:Single">;
|
||||
type SDVXSong = SongDocument<"sdvx">;
|
||||
|
||||
// Internal data for PUC tierlists are inconsistent
|
||||
const MANUAL_PUC_TIERS: { [level: number]: { [tier: string]: string } } = {
|
||||
16: {
|
||||
0: "16.?",
|
||||
1: "16.0",
|
||||
2: "16.1",
|
||||
3: "16.2",
|
||||
4: "16.3",
|
||||
5: "16.4",
|
||||
6: "16.5",
|
||||
7: "16.6",
|
||||
8: "16.7",
|
||||
9: "16.8",
|
||||
10: "16.9",
|
||||
11: "16.999",
|
||||
12: "16.?",
|
||||
},
|
||||
17: {
|
||||
10: "18.0",
|
||||
},
|
||||
19: {
|
||||
0: "19.13",
|
||||
1: "19.12",
|
||||
2: "19.11",
|
||||
3: "19.10",
|
||||
4: "19.9",
|
||||
5: "19.8",
|
||||
6: "19.7",
|
||||
7: "19.6",
|
||||
8: "19.5",
|
||||
9: "19.4",
|
||||
10: "19.3",
|
||||
11: "19.2",
|
||||
12: "19.1",
|
||||
13: "19.0",
|
||||
14: "19.?",
|
||||
},
|
||||
20: {
|
||||
0: "20.7",
|
||||
1: "20.6",
|
||||
2: "20.5",
|
||||
3: "20.4",
|
||||
4: "20.3",
|
||||
5: "20.2",
|
||||
6: "20.1",
|
||||
7: "20.0",
|
||||
8: "20.?",
|
||||
},
|
||||
};
|
||||
|
||||
// Used for tierlist value sorting
|
||||
const MANUAL_PUC_VALUES: { [tierText: string]: number } = {
|
||||
// ".?" values indicate individual difference and should appear at the bottom of their tierlists
|
||||
"16.?": 15.9,
|
||||
"19.?": 18.9,
|
||||
"20.?": 19.9,
|
||||
// To avoid these tiers getting grouped with 19.1
|
||||
"19.10": 20.0,
|
||||
19.11: 20.1,
|
||||
19.12: 20.2,
|
||||
19.13: 20.3,
|
||||
};
|
||||
|
||||
// Tier 0+ and Tier 0- for the Lvl 19/20 tierlist are internally named -1 and 0
|
||||
// respectively, so map them back to the display names
|
||||
const MANUAL_TIERS: { [level: number]: { [tier: string]: string } } = {
|
||||
const MANUAL_S_TIERS: { [level: number]: { [tier: string]: string } } = {
|
||||
19: {
|
||||
"-1": "0+",
|
||||
0: "0-",
|
||||
@@ -21,8 +84,14 @@ function normalizeStr(s: string) {
|
||||
return s.toLowerCase().replace(/ /g, "");
|
||||
}
|
||||
|
||||
async function scrape(charts: SDVXChart[], songs: SDVXSong[], level: number) {
|
||||
const html = await (await fetch(`https://sdvx.maya2silence.com/table/${level}`, {})).text();
|
||||
async function scrape(
|
||||
url: string,
|
||||
charts: SDVXChart[],
|
||||
songs: SDVXSong[],
|
||||
level: number,
|
||||
tierlistType: "S_RANK" | "PUC_LAMP"
|
||||
) {
|
||||
const html = await fetch(url).then((r: Response) => r.text());
|
||||
const $ = cheerio.load(html);
|
||||
|
||||
for (const tierBox of $(".tier_box")) {
|
||||
@@ -33,7 +102,10 @@ async function scrape(charts: SDVXChart[], songs: SDVXSong[], level: number) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const tierText = `Tier ${MANUAL_TIERS[level]?.[tier] ?? tier}`;
|
||||
const tierText =
|
||||
tierlistType === "S_RANK"
|
||||
? `T${MANUAL_S_TIERS[level]?.[tier] ?? tier}`
|
||||
: MANUAL_PUC_TIERS[level]?.[tier] ?? `${level}.${tier}`;
|
||||
|
||||
for (const chartData of $(tierBox).find(".chart_data")) {
|
||||
const title = chartData.attribs["data-title"] || "";
|
||||
@@ -59,27 +131,39 @@ async function scrape(charts: SDVXChart[], songs: SDVXSong[], level: number) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// e.g. Level 17 Tier 9 -> 17 + 1 - 9 / 10 = 17.1
|
||||
const value = level + 1 - parseInt(tier, 10) / 10;
|
||||
// S_RANK value is derived since the S tierlist groups charts under Tier 1, Tier 2, etc.
|
||||
// instead of 17.3, 17.4, etc. like the PUC tierlist
|
||||
// Example: Level 17 Tier 9 -> 17 + 1 - 9 / 10 = 17.1
|
||||
const value =
|
||||
tierlistType === "S_RANK"
|
||||
? level + 1 - parseInt(tier, 10) / 10
|
||||
: MANUAL_PUC_VALUES[tierText] ?? Number(tierText);
|
||||
const individualDifference = tierText.includes("?");
|
||||
const tierInfoKey: keyof SDVXChart["data"] =
|
||||
tierlistType === "S_RANK" ? "sTier" : "pucTier";
|
||||
|
||||
if (chart.data.sTier) {
|
||||
if (chart.data.sTier.text !== tierText) {
|
||||
if (chart.data[tierInfoKey]) {
|
||||
const tierInfo = chart.data[tierInfoKey]!;
|
||||
|
||||
if (
|
||||
tierInfo.text !== tierText ||
|
||||
tierInfo.value !== value ||
|
||||
tierInfo.individualDifference !== individualDifference
|
||||
) {
|
||||
console.log(
|
||||
`[${chart.data.sTier.text} -> ${tierText}]: ${title} - ${artist} [${diff}]`
|
||||
`[${chart.data[tierInfoKey]!.text} (${chart.data[tierInfoKey]!.value})
|
||||
} -> ${tierText} (${value})]: ${title} - ${artist} [${diff}]`
|
||||
);
|
||||
|
||||
chart.data.sTier.text = tierText;
|
||||
chart.data.sTier.value = value;
|
||||
}
|
||||
} else {
|
||||
console.log(`[${tierText}] ${title} - ${artist} [${diff}]`);
|
||||
|
||||
chart.data.sTier = {
|
||||
individualDifference: false,
|
||||
text: tierText,
|
||||
value,
|
||||
};
|
||||
console.log(`[${tierText} (${value})] ${title} - ${artist} [${diff}]`);
|
||||
}
|
||||
|
||||
chart.data[tierInfoKey] = {
|
||||
individualDifference,
|
||||
text: tierText,
|
||||
value,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -89,9 +173,27 @@ async function main() {
|
||||
const songs: SDVXSong[] = ReadCollection("songs-sdvx.json");
|
||||
|
||||
for (const level of [17, 18, 19]) {
|
||||
console.log(`\nScraping Level ${level}`);
|
||||
console.log(`\n[S Rank] Scraping Level ${level}`);
|
||||
|
||||
await scrape(charts, songs, level);
|
||||
await scrape(
|
||||
`https://sdvx.maya2silence.com/table/${level}`,
|
||||
charts,
|
||||
songs,
|
||||
level,
|
||||
"S_RANK"
|
||||
);
|
||||
}
|
||||
|
||||
for (const level of [16, 17, 18, 19, 20]) {
|
||||
console.log(`\n[PUC Lamp] Scraping Level ${level}`);
|
||||
|
||||
await scrape(
|
||||
`https://sdvx.maya2silence.com/table/${level}p`,
|
||||
charts,
|
||||
songs,
|
||||
level,
|
||||
"PUC_LAMP"
|
||||
);
|
||||
}
|
||||
|
||||
WriteCollection("charts-sdvx.json", charts);
|
||||
|
||||
Reference in New Issue
Block a user