Skip to content

Commit

Permalink
Rework PP to use Phoenix score, rework all calculations, rework Ranking
Browse files Browse the repository at this point in the history
  • Loading branch information
grumd committed Nov 29, 2023
1 parent c131347 commit 37e997a
Show file tree
Hide file tree
Showing 30 changed files with 1,291 additions and 452 deletions.
27 changes: 27 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions packages/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
"lusca": "^1.7.0",
"morgan": "^1.10.0",
"mysql2": "^2.3.3",
"node-cron": "^3.0.3",
"nodemon": "^2.0.22",
"pm2": "^5.3.0",
"regression": "^2.0.1",
Expand All @@ -72,6 +73,7 @@
"@types/mocha": "^8.2.2",
"@types/morgan": "^1.9.2",
"@types/node": "^20.5.1",
"@types/node-cron": "^3.0.11",
"@types/regression": "^2.0.0",
"@types/supertest": "^2.0.11",
"@types/validatorjs": "^3.15.0",
Expand Down
3 changes: 2 additions & 1 deletion packages/api/src/constants/currentMix.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export const mix = 26; // XX
export const mix = 27; // phoenix
export const minMixToGetPp = 25; // prime2, xx, phoenix +
75 changes: 75 additions & 0 deletions packages/api/src/controllers/charts/difficultyInterpolation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { db } from 'db';
import type { Response, Request, NextFunction } from 'express';
import _ from 'lodash/fp';
import {
getInterpolatedDifficultyPerChartInstance,
updateChartsDifficulty,
} from 'services/charts/chartDifficultyInterpolation';

export const difficultyInterpolationController = async (
request: Request,
response: Response,
next: NextFunction
) => {
try {
const interpolatedDiffs = await getInterpolatedDifficultyPerChartInstance();

const chartLevels = (
await db
.selectFrom('chart_instances')
.leftJoin('tracks', 'chart_instances.track', 'tracks.id')
.select([
'chart_instances.id as chart_instance_id',
'chart_instances.shared_chart as shared_chart_id',
'chart_instances.level',
'chart_instances.mix',
'tracks.full_name',
'chart_instances.label',
])
.where('mix', '>=', 25)
.where('chart_instances.level', 'is not', null)
.execute()
)
.map((chart) => {
return {
...chart,
interpolated: interpolatedDiffs[chart.chart_instance_id]?.difficulty,
};
})
.filter((ch) => ch.interpolated && ch.level)
.sort((a, b) => {
return Math.abs(b.level! - b.interpolated) - Math.abs(a.level! - a.interpolated);
});

const bySharedChart = _.flow(
_.groupBy((ch: (typeof chartLevels)[number]) => ch.shared_chart_id),
(z) => _.toPairs(z),
_.map(([, charts]) => ({
charts,
amplitude: Math.max(
Math.max(...charts.map((c) => c.interpolated)) -
Math.min(...charts.map((c) => c.interpolated)),
Math.max(...charts.map((c) => (c.level ? Math.abs(c.level - c.interpolated) : 0)))
),
})),
_.orderBy('amplitude', 'desc')
)(chartLevels);

response.json(bySharedChart);
} catch (error) {
next(error);
}
};

export const updateChartsDifficultyController = async (
request: Request,
response: Response,
next: NextFunction
) => {
try {
await updateChartsDifficulty();
response.json({ success: true });
} catch (error) {
next(error);
}
};
18 changes: 18 additions & 0 deletions packages/api/src/controllers/charts/sharedChartPp.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import type { Response, Request, NextFunction } from 'express';
import _ from 'lodash/fp';
import { calculateResultsPp } from 'services/results/resultsPp';

export const sharedChartPpController = async (
request: Request,
response: Response,
next: NextFunction
) => {
try {
const resultPpMap = await calculateResultsPp({
sharedChartId: Number(request.params.sharedChartId),
});
response.json(Object.fromEntries(resultPpMap.entries()));
} catch (error) {
next(error);
}
};
4 changes: 2 additions & 2 deletions packages/api/src/controllers/players/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import _ from 'lodash/fp';
import type { Response, Request, NextFunction } from 'express';

import { getPlayers, getPlayersGradeStats } from 'services/players/players';
import { getPlayers, getPlayersStats } from 'services/players/players';

export const getPlayersAllController = async (
request: Request,
Expand All @@ -21,7 +21,7 @@ export const getPlayersStatsController = async (
next: NextFunction
) => {
try {
response.json(await getPlayersGradeStats());
response.json(await getPlayersStats());
} catch (error) {
next(error);
}
Expand Down
2 changes: 2 additions & 0 deletions packages/api/src/controllers/results/addResult.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ const ManualResult = z.object({
});

const mixIdByName = {
Phoenix: 27,
XX: 26,
Prime2: 25,
Prime: 24,
Expand Down Expand Up @@ -213,6 +214,7 @@ export const addResultController = async (

response.json({ success: true });
} catch (e) {
console.error(e);
next(e);
}
};
Expand Down
6 changes: 2 additions & 4 deletions packages/api/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
// require('tsconfig-paths/register');

import { app } from './app';
import './jobs';
import fs from 'fs';
import https from 'https';

import { app } from './app';

const port = process.env.APP_PORT || 5000;

if (!process.env.HTTPS_PUBLIC_CERT_PATH || !process.env.HTTPS_PRIVATE_KEY_PATH) {
Expand Down
12 changes: 12 additions & 0 deletions packages/api/src/jobs/chartDifficulty/chartDifficultyJob.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import createDebug from 'debug';
import cron from 'node-cron';
import { updateChartsDifficulty } from 'services/charts/chartDifficultyInterpolation';

const debug = createDebug('backend-ts:jobs:chart-difficulty');

// Every day at 4 AM
cron.schedule('0 4 * * *', async () => {
debug('Starting job: Recalculate chart difficulty and all pp');
await updateChartsDifficulty();
debug('Job finished: Recalculate chart difficulty and all pp');
});
1 change: 1 addition & 0 deletions packages/api/src/jobs/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import './chartDifficulty/chartDifficultyJob';
39 changes: 36 additions & 3 deletions packages/api/src/routes/charts.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,48 @@
import { Router } from 'express';

import {
difficultyInterpolationController,
updateChartsDifficultyController,
} from 'controllers/charts/difficultyInterpolation';
import { searchChartsController } from 'controllers/charts/search';
import { sharedChartPpController } from 'controllers/charts/sharedChartPp';
import { Router } from 'express';
import { validate } from 'utils';

const router = Router();

/**
* GET /charts/search
* GET /charts/interpolated-difficulty
* @summary Search charts with filters
* @tags charts
* @return {array<object>} 200 - success response - application/json
*/
router.get('/interpolated-difficulty', difficultyInterpolationController);

/**
* GET /charts/refresh-difficulty
* @summary Update charts difficulty and update all scores
* @tags charts
* @return {array<object>} 200 - success response - application/json
*/
router.get('/refresh-difficulty', updateChartsDifficultyController);

/**
* GET /charts/recalc-diff
* @summary Recalculate difficulty
* @tags charts
* @return {array<object>} 200 - success response - application/json
*/
router.get('/search', searchChartsController);

/**
* GET /charts/:sharedChartId/pp
* @summary Recalculate pp for chart
* @tags charts pp
* @return {array<object>} 200 - success response - application/json
*/
router.get(
'/:sharedChartId/pp',
validate({ params: { sharedChartId: 'required|integer' } }),
sharedChartPpController
);

export default router;
9 changes: 3 additions & 6 deletions packages/api/src/routes/results.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import { Router } from 'express';

import { addResultController } from 'controllers/results/addResult';
import { resultAddedEffectController } from 'controllers/results/resultAddedEffect';
import { screenshotController } from 'controllers/results/screenshot';
import { addResultController } from 'controllers/results/addResult';

import { validate } from 'utils';

import { Router } from 'express';
import { addResultsAuth } from 'middlewares/auth/auth';
import { validate } from 'utils';

const router = Router();

Expand Down
Loading

0 comments on commit 37e997a

Please sign in to comment.