mirror of
https://github.com/zkldi/Tachi.git
synced 2026-10-11 16:58:25 +03:00
Merge pull request #604 from TNG-dev/zkldi/issue-598
This commit is contained in:
Vendored
+1
@@ -46,6 +46,7 @@
|
||||
"bms",
|
||||
"chunithm",
|
||||
"usc",
|
||||
"wacca",
|
||||
],
|
||||
IMPORT_TYPES: [
|
||||
"file/eamusement-iidx-csv",
|
||||
|
||||
+1
-1
@@ -83,7 +83,7 @@
|
||||
"rimraf": "3.0.2",
|
||||
"safe-json-stringify": "1.2.0",
|
||||
"seq-logging": "^1.1.1",
|
||||
"tachi-common": "0.3.24",
|
||||
"tachi-common": "0.4.1",
|
||||
"ts-node": "10.0.0",
|
||||
"typescript": "4.3.4",
|
||||
"winston": "3.3.3",
|
||||
|
||||
Generated
+4
-4
@@ -63,7 +63,7 @@ specifiers:
|
||||
safe-json-stringify: 1.2.0
|
||||
seq-logging: ^1.1.1
|
||||
supertest: 6.1.3
|
||||
tachi-common: 0.3.24
|
||||
tachi-common: 0.4.1
|
||||
tap: 15.0.9
|
||||
ts-node: 10.0.0
|
||||
tsconfig-paths: 3.10.1
|
||||
@@ -107,7 +107,7 @@ dependencies:
|
||||
rimraf: 3.0.2
|
||||
safe-json-stringify: 1.2.0
|
||||
seq-logging: 1.1.1
|
||||
tachi-common: 0.3.24
|
||||
tachi-common: 0.4.1
|
||||
ts-node: 10.0.0_83f53b0a0c5616d3fa00ed4e30b9ce1b
|
||||
typescript: 4.3.4
|
||||
winston: 3.3.3
|
||||
@@ -5387,8 +5387,8 @@ packages:
|
||||
strip-ansi: 6.0.0
|
||||
dev: true
|
||||
|
||||
/tachi-common/0.3.24:
|
||||
resolution: {integrity: sha512-nTfVZeRXqOyVF5viHACawbbrERzwyY88wBxNuhpZVvSL4jTjFy7dSRf/7LnJVDC1XizhUBKfYMlOBXOUXTIzzg==}
|
||||
/tachi-common/0.4.1:
|
||||
resolution: {integrity: sha512-AREsya2jvgpBq036I17XUeR/jF+lKKJ+CeKCtzKLGE1j8GgyHH6HAy6zP5Vzw6eXRXknubCgr/xFbq+LDqWPmw==}
|
||||
dependencies:
|
||||
monk: 7.3.4
|
||||
transitivePeerDependencies:
|
||||
|
||||
Vendored
+2
@@ -122,6 +122,7 @@ const songs = {
|
||||
popn: monkDB.get<SongDocument>(`songs-popn`),
|
||||
sdvx: monkDB.get<SongDocument>(`songs-sdvx`),
|
||||
usc: monkDB.get<SongDocument>(`songs-usc`),
|
||||
wacca: monkDB.get<SongDocument>(`songs-wacca`),
|
||||
};
|
||||
|
||||
const charts = {
|
||||
@@ -136,6 +137,7 @@ const charts = {
|
||||
popn: monkDB.get<ChartDocument>(`charts-popn`),
|
||||
sdvx: monkDB.get<ChartDocument>(`charts-sdvx`),
|
||||
usc: monkDB.get<ChartDocument>(`charts-usc`),
|
||||
wacca: monkDB.get<ChartDocument>(`charts-wacca`),
|
||||
};
|
||||
|
||||
const db = {
|
||||
|
||||
Vendored
+11
@@ -767,6 +767,12 @@ export const DatabaseSchemas: Record<Databases, ValidatorFunction> = {
|
||||
displayVersion: "string",
|
||||
})
|
||||
),
|
||||
"songs-wacca": prSchemaify(
|
||||
PR_SongDocument({
|
||||
genre: "string",
|
||||
displayVersion: "?string",
|
||||
})
|
||||
),
|
||||
"charts-iidx": (self) => {
|
||||
const playtype = getPlaytype("iidx", self);
|
||||
|
||||
@@ -849,6 +855,11 @@ export const DatabaseSchemas: Record<Databases, ValidatorFunction> = {
|
||||
})
|
||||
)(self);
|
||||
},
|
||||
"charts-wacca": prSchemaify(
|
||||
PR_ChartDocument("wacca", "Single", {
|
||||
releaseVersion: p.isIn("wacca", "s", "lily", "lily-r", "reverse"),
|
||||
})
|
||||
),
|
||||
goals: prSchemaify({
|
||||
game: p.isIn(games),
|
||||
playtype: isValidPlaytype,
|
||||
|
||||
@@ -172,3 +172,15 @@ export enum CHUNITHM_COLOURS {
|
||||
PLATINUM,
|
||||
RAINBOW,
|
||||
}
|
||||
|
||||
export enum WACCA_COLOURS {
|
||||
ASH,
|
||||
NAVY,
|
||||
YELLOW,
|
||||
RED,
|
||||
PURPLE,
|
||||
BLUE,
|
||||
SILVER,
|
||||
GOLD,
|
||||
RAINBOW,
|
||||
}
|
||||
|
||||
@@ -3,13 +3,13 @@ import { KtLogger } from "lib/logger/logger";
|
||||
import {
|
||||
ChartDocument,
|
||||
Game,
|
||||
GetGamePTConfig,
|
||||
Grades,
|
||||
IDStrings,
|
||||
IIDX_LAMPS,
|
||||
Lamps,
|
||||
Playtypes,
|
||||
ScoreDocument,
|
||||
GetGamePTConfig,
|
||||
IIDX_LAMPS,
|
||||
} from "tachi-common";
|
||||
import { HasOwnProperty } from "utils/misc";
|
||||
import { DryScore } from "../common/types";
|
||||
@@ -93,6 +93,9 @@ const CalculatedDataFunctions: CalculatedDataFunctions = {
|
||||
Controller: CalculateDataSDVXorUSC,
|
||||
Keyboard: CalculateDataSDVXorUSC,
|
||||
},
|
||||
wacca: {
|
||||
Single: CalculateDataWACCA,
|
||||
},
|
||||
};
|
||||
|
||||
// Creates Game-Specific calculatedData for the provided game & playtype.
|
||||
@@ -323,3 +326,37 @@ export function CalculateDataBMS7K(
|
||||
// jubility: 0, // @todo #163 Jubeat Jubility
|
||||
// };
|
||||
// }
|
||||
|
||||
function CalculateDataWACCA(
|
||||
dryScore: DryScore,
|
||||
chart: ChartDocument,
|
||||
logger: KtLogger
|
||||
): CalculatedData<"wacca:Single"> {
|
||||
let scoreCoef = 1;
|
||||
|
||||
// See https://github.com/TNG-dev/tachi-server/issues/598.
|
||||
// This is genuinely how the game works.
|
||||
if (scoreCoef >= 990_000) {
|
||||
scoreCoef = 4;
|
||||
} else if (scoreCoef >= 980_000) {
|
||||
scoreCoef = 3.75;
|
||||
} else if (scoreCoef >= 970_000) {
|
||||
scoreCoef = 3.5;
|
||||
} else if (scoreCoef >= 960_000) {
|
||||
scoreCoef = 3.25;
|
||||
} else if (scoreCoef >= 950_000) {
|
||||
scoreCoef = 3;
|
||||
} else if (scoreCoef >= 940_000) {
|
||||
scoreCoef = 2.75;
|
||||
} else if (scoreCoef >= 920_000) {
|
||||
scoreCoef = 2.5;
|
||||
} else if (scoreCoef >= 900_000) {
|
||||
scoreCoef = 2;
|
||||
} else if (scoreCoef >= 850_000) {
|
||||
scoreCoef = 1.5;
|
||||
}
|
||||
|
||||
// That's... it??
|
||||
// How discrete. How boring!
|
||||
return { rate: scoreCoef * chart.levelNum };
|
||||
}
|
||||
|
||||
@@ -127,6 +127,11 @@ const CalculatedDataFunctions: CalculatedDataFunctions = {
|
||||
};
|
||||
},
|
||||
},
|
||||
wacca: {
|
||||
Single: (scd) => ({
|
||||
naiveRate: AvgBest10Map(scd, "rate"),
|
||||
}),
|
||||
},
|
||||
};
|
||||
|
||||
export function CreateSessionCalcData(
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
import { CHUNITHM_COLOURS, GitadoraColours, SDVXVFClasses } from "lib/constants/classes";
|
||||
import {
|
||||
CHUNITHM_COLOURS,
|
||||
GitadoraColours,
|
||||
SDVXVFClasses,
|
||||
WACCA_COLOURS,
|
||||
} from "lib/constants/classes";
|
||||
import { KtLogger } from "lib/logger/logger";
|
||||
import { Game, integer, Playtypes, ScoreCalculatedDataLookup } from "tachi-common";
|
||||
import { GameClasses } from "tachi-common/js/game-classes";
|
||||
@@ -94,6 +99,39 @@ export function GitadoraSkillToColour(sk: number) {
|
||||
return GitadoraColours.WHITE;
|
||||
}
|
||||
|
||||
export function CalculateWACCAColour(
|
||||
game: Game,
|
||||
playtype: Playtypes[Game],
|
||||
userID: integer,
|
||||
ratings: Record<string, number>
|
||||
) {
|
||||
const colour = WACCARateToColour(ratings.naiveRate);
|
||||
|
||||
return { colour };
|
||||
}
|
||||
|
||||
function WACCARateToColour(rate: number) {
|
||||
if (rate >= 2500) {
|
||||
return WACCA_COLOURS.RAINBOW;
|
||||
} else if (rate >= 2200) {
|
||||
return WACCA_COLOURS.GOLD;
|
||||
} else if (rate >= 1900) {
|
||||
return WACCA_COLOURS.SILVER;
|
||||
} else if (rate >= 1600) {
|
||||
return WACCA_COLOURS.BLUE;
|
||||
} else if (rate >= 1300) {
|
||||
return WACCA_COLOURS.PURPLE;
|
||||
} else if (rate >= 1000) {
|
||||
return WACCA_COLOURS.RED;
|
||||
} else if (rate >= 600) {
|
||||
return WACCA_COLOURS.YELLOW;
|
||||
} else if (rate >= 300) {
|
||||
return WACCA_COLOURS.NAVY;
|
||||
}
|
||||
|
||||
return WACCA_COLOURS.ASH;
|
||||
}
|
||||
|
||||
export function CalculateChunithmColour(
|
||||
game: Game,
|
||||
playtype: Playtypes[Game],
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
CalculateChunithmColour,
|
||||
CalculateGitadoraColour,
|
||||
CalculateSDVXClass,
|
||||
CalculateWACCAColour,
|
||||
} from "./builtin-class-handlers";
|
||||
import { ClassHandler, ScoreClasses } from "./types";
|
||||
|
||||
@@ -50,6 +51,9 @@ const STATIC_CLASS_HANDLERS: ClassHandlerMap = {
|
||||
Single: CalculateSDVXClass,
|
||||
},
|
||||
usc: null,
|
||||
wacca: {
|
||||
Single: CalculateWACCAColour,
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -132,6 +132,12 @@ const RatingFunctions: RatingFunctions = {
|
||||
ktRating: await LazyMeanN("ktRating", 20)(g, p, u),
|
||||
}),
|
||||
},
|
||||
wacca: {
|
||||
Single: async (g, p, u, l) => ({
|
||||
naiveRate: await LazySumN("rate", 50)(g, p, u),
|
||||
rate: await CalculateWACCARate(g, p, u, l),
|
||||
}),
|
||||
},
|
||||
// jubeat: {
|
||||
// Single: async (g, p, u, l) => ({
|
||||
// jubility: await CalculateJubility(g, p, u, l),
|
||||
@@ -149,6 +155,71 @@ export function CalculateRatings(
|
||||
return RatingFunctions[game][playtype](game, playtype, userID, logger);
|
||||
}
|
||||
|
||||
// Wacca has a funny algorithm for rate involving gitadora-style latest chart bonuses,
|
||||
async function CalculateWACCARate(
|
||||
game: Game,
|
||||
playtype: Playtypes[Game],
|
||||
userID: integer,
|
||||
logger: KtLogger
|
||||
) {
|
||||
const hotChartIDs = (
|
||||
await db.charts.wacca.find(
|
||||
{ "data.releaseVersion": "reverse" },
|
||||
{ projection: { chartID: 1 } }
|
||||
)
|
||||
).map((e) => e.chartID);
|
||||
|
||||
const coldChartIDs = (
|
||||
await db.charts.wacca.find(
|
||||
{ "data.releaseVersion": { $ne: "reverse" } },
|
||||
{ projection: { chartID: 1 } }
|
||||
)
|
||||
).map((e) => e.chartID);
|
||||
|
||||
const best15Hot = await db["personal-bests"].find(
|
||||
{
|
||||
game,
|
||||
playtype,
|
||||
userID,
|
||||
chartID: { $in: hotChartIDs },
|
||||
"calculatedData.rate": { $type: "number" },
|
||||
},
|
||||
{
|
||||
sort: {
|
||||
"calculatedData.rate": -1,
|
||||
},
|
||||
limit: 15,
|
||||
projection: {
|
||||
"calculatedData.rate": 1,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const best35Cold = await db["personal-bests"].find(
|
||||
{
|
||||
game,
|
||||
playtype,
|
||||
userID,
|
||||
chartID: { $in: coldChartIDs },
|
||||
"calculatedData.rate": { $type: "number" },
|
||||
},
|
||||
{
|
||||
sort: {
|
||||
"calculatedData.rate": -1,
|
||||
},
|
||||
limit: 35,
|
||||
projection: {
|
||||
"calculatedData.rate": 1,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
return (
|
||||
best15Hot.reduce((a, r) => a + r.calculatedData.rate!, 0) +
|
||||
best35Cold.reduce((a, r) => a + r.calculatedData.rate!, 0)
|
||||
);
|
||||
}
|
||||
|
||||
async function CalculateGitadoraSkill(
|
||||
game: Game,
|
||||
playtype: Playtypes[Game],
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
[]
|
||||
@@ -0,0 +1 @@
|
||||
[]
|
||||
Reference in New Issue
Block a user