add and run prettier
This commit is contained in:
@ -1,16 +1,19 @@
|
||||
import {expose} from 'comlink'
|
||||
import initDb from '../db/db'
|
||||
import scoresRepository from '../db/repository/scores'
|
||||
import rankedsRepository from '../db/repository/rankeds'
|
||||
import eventBus from '../utils/broadcast-channel-pubsub'
|
||||
import {convertArrayToObjectByKey} from '../utils/js'
|
||||
import {diffColors} from '../utils/scoresaber/format'
|
||||
import {getAccFromScore} from '../utils/scoresaber/song'
|
||||
import {getTotalPpFromSortedPps, WEIGHT_COEFFICIENT} from '../utils/scoresaber/pp'
|
||||
import makePendingPromisePool from '../utils/pending-promises'
|
||||
import produce, {setAutoFreeze} from 'immer'
|
||||
import beatmapsEnhancer from '../stores/http/enhancers/common/beatmaps'
|
||||
import accEnhancer from '../stores/http/enhancers/scores/acc'
|
||||
import { expose } from "comlink";
|
||||
import initDb from "../db/db";
|
||||
import scoresRepository from "../db/repository/scores";
|
||||
import rankedsRepository from "../db/repository/rankeds";
|
||||
import eventBus from "../utils/broadcast-channel-pubsub";
|
||||
import { convertArrayToObjectByKey } from "../utils/js";
|
||||
import { diffColors } from "../utils/scoresaber/format";
|
||||
import { getAccFromScore } from "../utils/scoresaber/song";
|
||||
import {
|
||||
getTotalPpFromSortedPps,
|
||||
WEIGHT_COEFFICIENT,
|
||||
} from "../utils/scoresaber/pp";
|
||||
import makePendingPromisePool from "../utils/pending-promises";
|
||||
import produce, { setAutoFreeze } from "immer";
|
||||
import beatmapsEnhancer from "../stores/http/enhancers/common/beatmaps";
|
||||
import accEnhancer from "../stores/http/enhancers/scores/acc";
|
||||
|
||||
let db = null;
|
||||
|
||||
@ -18,14 +21,18 @@ let rankeds = null;
|
||||
|
||||
const resolvePromiseOrWaitForPending = makePendingPromisePool();
|
||||
|
||||
const getPlayerScores = async playerId => scoresRepository().getAllFromIndex('scores-playerId', playerId, true);
|
||||
const getPlayerScores = async (playerId) =>
|
||||
scoresRepository().getAllFromIndex("scores-playerId", playerId, true);
|
||||
const getRankedsFromDb = async (refreshCache = false) => {
|
||||
const dbRankeds = await rankedsRepository().getAll(refreshCache)
|
||||
const dbRankeds = await rankedsRepository().getAll(refreshCache);
|
||||
|
||||
return dbRankeds ? convertArrayToObjectByKey(dbRankeds, 'leaderboardId') : {}
|
||||
}
|
||||
return dbRankeds ? convertArrayToObjectByKey(dbRankeds, "leaderboardId") : {};
|
||||
};
|
||||
|
||||
const getRankeds = async (refreshCache = false) => resolvePromiseOrWaitForPending(`rankeds/${refreshCache}`, () => getRankedsFromDb())
|
||||
const getRankeds = async (refreshCache = false) =>
|
||||
resolvePromiseOrWaitForPending(`rankeds/${refreshCache}`, () =>
|
||||
getRankedsFromDb(),
|
||||
);
|
||||
|
||||
async function init() {
|
||||
if (db) return;
|
||||
@ -34,16 +41,16 @@ async function init() {
|
||||
|
||||
// setup immer.js
|
||||
// WORKAROUND for immer.js esm (see https://github.com/immerjs/immer/issues/557)
|
||||
self.process = {env: {NODE_ENV: "production"}};
|
||||
self.process = { env: { NODE_ENV: "production" } };
|
||||
setAutoFreeze(false);
|
||||
|
||||
rankeds = getRankeds();
|
||||
|
||||
eventBus.on('rankeds-changed', () => rankeds = getRankeds(true));
|
||||
eventBus.on("rankeds-changed", () => (rankeds = getRankeds(true)));
|
||||
}
|
||||
|
||||
const getRankedScores = async (playerId, withStars = false) => {
|
||||
const scores = await getPlayerScores(playerId)
|
||||
const scores = await getPlayerScores(playerId);
|
||||
|
||||
if (!scores || !scores.length) return null;
|
||||
|
||||
@ -53,86 +60,134 @@ const getRankedScores = async (playerId, withStars = false) => {
|
||||
}
|
||||
|
||||
return withStars
|
||||
? (await Promise.all(scores
|
||||
.filter(score => score?.score?.pp)
|
||||
.map(async score => {
|
||||
score = await produce(await produce(score, draft => beatmapsEnhancer(draft, true)), draft => accEnhancer(draft))
|
||||
? (
|
||||
await Promise.all(
|
||||
scores
|
||||
.filter((score) => score?.score?.pp)
|
||||
.map(async (score) => {
|
||||
score = await produce(
|
||||
await produce(score, (draft) => beatmapsEnhancer(draft, true)),
|
||||
(draft) => accEnhancer(draft),
|
||||
);
|
||||
|
||||
return {
|
||||
...score,
|
||||
stars: allRankeds[score?.leaderboardId]?.stars ?? null,
|
||||
}
|
||||
}))
|
||||
)
|
||||
.filter(s => s.stars)
|
||||
: scores.filter(score => score?.score?.pp);
|
||||
}
|
||||
return {
|
||||
...score,
|
||||
stars: allRankeds[score?.leaderboardId]?.stars ?? null,
|
||||
};
|
||||
}),
|
||||
)
|
||||
).filter((s) => s.stars)
|
||||
: scores.filter((score) => score?.score?.pp);
|
||||
};
|
||||
|
||||
const getPlayerRankedScoresWithStars = async playerId => getRankedScores(playerId, true)
|
||||
const getPlayerRankedScoresWithStars = async (playerId) =>
|
||||
getRankedScores(playerId, true);
|
||||
|
||||
const calcPlayerStats = async playerId => {
|
||||
const calcPlayerStats = async (playerId) => {
|
||||
await init();
|
||||
|
||||
const rankedScores = await getRankedScores(playerId);
|
||||
if (!rankedScores) return null;
|
||||
|
||||
const stats = rankedScores
|
||||
.filter(score => (score?.score?.score && score?.score?.maxScore) || score?.score?.acc)
|
||||
.reduce((cum, s) => {
|
||||
const leaderboardId = s?.leaderboard?.leaderboardId;
|
||||
const pp = s?.score?.pp;
|
||||
const score = s?.score?.unmodifiedScore ?? s?.score?.score ?? 0;
|
||||
const accFromScore = getAccFromScore({...s.score, leaderboardId});
|
||||
const scoreAcc = s?.score?.acc;
|
||||
.filter(
|
||||
(score) =>
|
||||
(score?.score?.score && score?.score?.maxScore) || score?.score?.acc,
|
||||
)
|
||||
.reduce(
|
||||
(cum, s) => {
|
||||
const leaderboardId = s?.leaderboard?.leaderboardId;
|
||||
const pp = s?.score?.pp;
|
||||
const score = s?.score?.unmodifiedScore ?? s?.score?.score ?? 0;
|
||||
const accFromScore = getAccFromScore({ ...s.score, leaderboardId });
|
||||
const scoreAcc = s?.score?.acc;
|
||||
|
||||
if (!accFromScore && !scoreAcc) return cum;
|
||||
if (!accFromScore && !scoreAcc) return cum;
|
||||
|
||||
let acc = accFromScore ? accFromScore : scoreAcc;
|
||||
if (!acc || isNaN(acc)) return cum;
|
||||
let acc = accFromScore ? accFromScore : scoreAcc;
|
||||
if (!acc || isNaN(acc)) return cum;
|
||||
|
||||
s.score.acc = acc;
|
||||
cum.totalScore += score;
|
||||
cum.totalAcc += acc;
|
||||
s.score.acc = acc;
|
||||
cum.totalScore += score;
|
||||
cum.totalAcc += acc;
|
||||
|
||||
if (cum.topAcc < acc) cum.topAcc = acc;
|
||||
if (cum.topPp < pp) cum.topPp = pp;
|
||||
if (cum.topAcc < acc) cum.topAcc = acc;
|
||||
if (cum.topPp < pp) cum.topPp = pp;
|
||||
|
||||
cum.badges.forEach(badge => {
|
||||
if ((!badge.min || badge.min <= acc) && (!badge.max || badge.max > acc)) badge.value++;
|
||||
})
|
||||
cum.badges.forEach((badge) => {
|
||||
if (
|
||||
(!badge.min || badge.min <= acc) &&
|
||||
(!badge.max || badge.max > acc)
|
||||
)
|
||||
badge.value++;
|
||||
});
|
||||
|
||||
return cum;
|
||||
}, {
|
||||
playerId,
|
||||
badges: [
|
||||
{label: 'SS+', min: 95, max: null, value: 0, bgColor: diffColors.expertPlus},
|
||||
{label: 'SS', min: 90, max: 95, value: 0, bgColor: diffColors.expert},
|
||||
{label: 'S+', min: 85, max: 90, value: 0, bgColor: diffColors.hard},
|
||||
{label: 'S', min: 80, max: 85, value: 0, bgColor: diffColors.normal},
|
||||
{label: 'A', min: null, max: 80, value: 0, bgColor: diffColors.easy},
|
||||
],
|
||||
topAcc: 0,
|
||||
topPp: 0,
|
||||
totalAcc: 0,
|
||||
totalScore: 0,
|
||||
avgAcc: 0,
|
||||
playCount: rankedScores.length,
|
||||
medianAcc: 0,
|
||||
stdDeviation: 0,
|
||||
})
|
||||
return cum;
|
||||
},
|
||||
{
|
||||
playerId,
|
||||
badges: [
|
||||
{
|
||||
label: "SS+",
|
||||
min: 95,
|
||||
max: null,
|
||||
value: 0,
|
||||
bgColor: diffColors.expertPlus,
|
||||
},
|
||||
{
|
||||
label: "SS",
|
||||
min: 90,
|
||||
max: 95,
|
||||
value: 0,
|
||||
bgColor: diffColors.expert,
|
||||
},
|
||||
{ label: "S+", min: 85, max: 90, value: 0, bgColor: diffColors.hard },
|
||||
{
|
||||
label: "S",
|
||||
min: 80,
|
||||
max: 85,
|
||||
value: 0,
|
||||
bgColor: diffColors.normal,
|
||||
},
|
||||
{
|
||||
label: "A",
|
||||
min: null,
|
||||
max: 80,
|
||||
value: 0,
|
||||
bgColor: diffColors.easy,
|
||||
},
|
||||
],
|
||||
topAcc: 0,
|
||||
topPp: 0,
|
||||
totalAcc: 0,
|
||||
totalScore: 0,
|
||||
avgAcc: 0,
|
||||
playCount: rankedScores.length,
|
||||
medianAcc: 0,
|
||||
stdDeviation: 0,
|
||||
},
|
||||
);
|
||||
|
||||
stats.medianAcc = rankedScores.length > 1
|
||||
? (rankedScores.sort((a, b) => a.score.acc - b.score.acc))[Math.ceil(rankedScores.length / 2)].score.acc
|
||||
: stats.totalAcc;
|
||||
stats.medianAcc =
|
||||
rankedScores.length > 1
|
||||
? rankedScores.sort((a, b) => a.score.acc - b.score.acc)[
|
||||
Math.ceil(rankedScores.length / 2)
|
||||
].score.acc
|
||||
: stats.totalAcc;
|
||||
stats.avgAcc = stats.totalAcc / rankedScores.length;
|
||||
stats.stdDeviation = Math.sqrt(rankedScores.reduce((sum, s) => sum + Math.pow(stats.avgAcc - s.score.acc, 2), 0) / rankedScores.length);
|
||||
stats.stdDeviation = Math.sqrt(
|
||||
rankedScores.reduce(
|
||||
(sum, s) => sum + Math.pow(stats.avgAcc - s.score.acc, 2),
|
||||
0,
|
||||
) / rankedScores.length,
|
||||
);
|
||||
|
||||
delete stats.totalAcc;
|
||||
|
||||
eventBus.publish('player-stats-calculated', stats);
|
||||
eventBus.publish("player-stats-calculated", stats);
|
||||
|
||||
return stats;
|
||||
}
|
||||
};
|
||||
|
||||
const calcPpBoundary = async (playerId, expectedPp = 1) => {
|
||||
const rankedScores = await getRankedScores(playerId);
|
||||
@ -144,10 +199,12 @@ const calcPpBoundary = async (playerId, expectedPp = 1) => {
|
||||
|
||||
// 0.965^idx * rawPpToFind = expected + oldBottomPp - newBottomPp;
|
||||
// rawPpToFind = (expected + oldBottomPp - newBottomPp) / 0.965^idx;
|
||||
return (expected + oldBottomPp - newBottomPp) / Math.pow(WEIGHT_COEFFICIENT, idx);
|
||||
}
|
||||
return (
|
||||
(expected + oldBottomPp - newBottomPp) / Math.pow(WEIGHT_COEFFICIENT, idx)
|
||||
);
|
||||
};
|
||||
|
||||
const rankedScorePps = rankedScores.map(s => s.pp).sort((a, b) => b - a);
|
||||
const rankedScorePps = rankedScores.map((s) => s.pp).sort((a, b) => b - a);
|
||||
|
||||
let idx = rankedScorePps.length - 1;
|
||||
|
||||
@ -160,9 +217,17 @@ const calcPpBoundary = async (playerId, expectedPp = 1) => {
|
||||
const diff = modifiedBottomPp - bottomPp;
|
||||
|
||||
if (diff > expectedPp) {
|
||||
const ppBoundary = calcRawPpAtIdx(rankedScorePps.slice(idx + 1), idx + 1, expectedPp);
|
||||
const ppBoundary = calcRawPpAtIdx(
|
||||
rankedScorePps.slice(idx + 1),
|
||||
idx + 1,
|
||||
expectedPp,
|
||||
);
|
||||
|
||||
eventBus.publish('player-pp-boundary-calculated', {playerId, expectedPp, ppBoundary});
|
||||
eventBus.publish("player-pp-boundary-calculated", {
|
||||
playerId,
|
||||
expectedPp,
|
||||
ppBoundary,
|
||||
});
|
||||
|
||||
return ppBoundary;
|
||||
}
|
||||
@ -172,16 +237,20 @@ const calcPpBoundary = async (playerId, expectedPp = 1) => {
|
||||
|
||||
const ppBoundary = calcRawPpAtIdx(rankedScorePps, 0, expectedPp);
|
||||
|
||||
eventBus.publish('player-pp-boundary-calculated', {playerId, expectedPp, ppBoundary});
|
||||
eventBus.publish("player-pp-boundary-calculated", {
|
||||
playerId,
|
||||
expectedPp,
|
||||
ppBoundary,
|
||||
});
|
||||
|
||||
return ppBoundary;
|
||||
}
|
||||
};
|
||||
|
||||
const worker = {
|
||||
init,
|
||||
calcPlayerStats,
|
||||
calcPpBoundary,
|
||||
getPlayerRankedScoresWithStars
|
||||
}
|
||||
getPlayerRankedScoresWithStars,
|
||||
};
|
||||
|
||||
expose(worker);
|
||||
expose(worker);
|
||||
|
Reference in New Issue
Block a user