add prettier config
This commit is contained in:
parent
f6f56aa09c
commit
27f3c4e030
6
.prettierrc.json
Normal file
6
.prettierrc.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"trailingComma": "es5",
|
||||
"tabWidth": 2,
|
||||
"semi": true,
|
||||
"singleQuote": false
|
||||
}
|
10
public/assets/swiped-events.min.js
vendored
10
public/assets/swiped-events.min.js
vendored
@ -26,7 +26,7 @@
|
||||
(u = 0),
|
||||
(i = 0);
|
||||
},
|
||||
!1,
|
||||
!1
|
||||
),
|
||||
e.addEventListener(
|
||||
"touchmove",
|
||||
@ -36,7 +36,7 @@
|
||||
r = t.touches[0].clientY;
|
||||
(u = n - e), (i = a - r);
|
||||
},
|
||||
!1,
|
||||
!1
|
||||
),
|
||||
e.addEventListener(
|
||||
"touchend",
|
||||
@ -67,15 +67,15 @@
|
||||
bubbles: !0,
|
||||
cancelable: !0,
|
||||
detail: b,
|
||||
}),
|
||||
})
|
||||
),
|
||||
s.dispatchEvent(
|
||||
new CustomEvent(d, { bubbles: !0, cancelable: !0, detail: b }),
|
||||
new CustomEvent(d, { bubbles: !0, cancelable: !0, detail: b })
|
||||
);
|
||||
}
|
||||
(n = null), (a = null), (r = null);
|
||||
},
|
||||
!1,
|
||||
!1
|
||||
);
|
||||
var n = null,
|
||||
a = null,
|
||||
|
@ -20,7 +20,7 @@ fs.writeFileSync(
|
||||
buildDate:
|
||||
new Date().toISOString().substr(0, 19).replace("T", " ") + " UTC",
|
||||
buildVersion,
|
||||
}),
|
||||
})
|
||||
);
|
||||
|
||||
function serve() {
|
||||
@ -39,7 +39,7 @@ function serve() {
|
||||
{
|
||||
stdio: ["ignore", "inherit", "inherit"],
|
||||
shell: true,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
process.on("SIGTERM", toExit);
|
||||
@ -104,7 +104,7 @@ export default [
|
||||
|
||||
fs.copyFileSync(
|
||||
path.resolve("./node_modules/comlink/dist/umd/comlink.min.js"),
|
||||
path.resolve("./public/build/comlink.min.js"),
|
||||
path.resolve("./public/build/comlink.min.js")
|
||||
);
|
||||
},
|
||||
},
|
||||
@ -150,7 +150,7 @@ export default [
|
||||
|
||||
fs.copyFileSync(
|
||||
path.resolve("./src/workers/stats-worker.js"),
|
||||
path.resolve("./public/build/stats-worker.js"),
|
||||
path.resolve("./public/build/stats-worker.js")
|
||||
);
|
||||
},
|
||||
},
|
||||
|
@ -22,7 +22,7 @@ export const onLegendClick = (event, legendItem, legend) => {
|
||||
(ci?.config?.data?.datasets?.[a?.datasetIndex]?.axisOrder ??
|
||||
a?.datasetIndex) -
|
||||
(ci?.config?.data?.datasets?.[b?.datasetIndex]?.axisOrder ??
|
||||
b?.datasetIndex),
|
||||
b?.datasetIndex)
|
||||
)
|
||||
.reduce(
|
||||
(cum, legendItem) => {
|
||||
@ -44,7 +44,7 @@ export const onLegendClick = (event, legendItem, legend) => {
|
||||
|
||||
return cum;
|
||||
},
|
||||
{ first: null, second: null },
|
||||
{ first: null, second: null }
|
||||
);
|
||||
|
||||
Object.keys(yAxes).forEach((currentAxisKey) => {
|
||||
|
@ -39,7 +39,7 @@ export default {
|
||||
: left + 3,
|
||||
region?.position?.vertical === "bottom"
|
||||
? top + 2
|
||||
: top - fontSize - 1,
|
||||
: top - fontSize - 1
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ function updateScoresStats(playerData, playerStats) {
|
||||
bgColor: "var(--ppColour)",
|
||||
},
|
||||
]
|
||||
: [],
|
||||
: []
|
||||
)
|
||||
.filter((s) => s && (!playerStats || s.label !== "Average"));
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ export default () => {
|
||||
order: "desc",
|
||||
page: paramsArr[2] ?? serviceDefaultParams?.page,
|
||||
},
|
||||
service,
|
||||
service
|
||||
);
|
||||
|
||||
case "accsaber":
|
||||
@ -88,7 +88,7 @@ export default () => {
|
||||
: "desc",
|
||||
page: paramsArr[3] ?? serviceDefaultParams?.page,
|
||||
},
|
||||
service,
|
||||
service
|
||||
);
|
||||
|
||||
case "scoresaber":
|
||||
@ -102,7 +102,7 @@ export default () => {
|
||||
: "desc",
|
||||
page: paramsArr[2] ?? serviceDefaultParams?.page,
|
||||
},
|
||||
service,
|
||||
service
|
||||
);
|
||||
}
|
||||
};
|
||||
|
@ -5,19 +5,19 @@ export default (name, getObjKey) => {
|
||||
|
||||
// update data cached on another node
|
||||
eventBus.on("cache-key-set-" + name, ({ key, value }, isLocal) =>
|
||||
!isLocal ? set(key, value, false) : null,
|
||||
!isLocal ? set(key, value, false) : null
|
||||
);
|
||||
eventBus.on("cache-all-set" + name, ({ data }, isLocal) =>
|
||||
!isLocal ? setAll(data, false) : null,
|
||||
!isLocal ? setAll(data, false) : null
|
||||
);
|
||||
eventBus.on("cache-merge-" + name, ({ data }, isLocal) =>
|
||||
!isLocal ? merge(data, false) : null,
|
||||
!isLocal ? merge(data, false) : null
|
||||
);
|
||||
eventBus.on("cache-key-forget-" + name, ({ key }, isLocal) =>
|
||||
!isLocal ? forget(key, false) : null,
|
||||
!isLocal ? forget(key, false) : null
|
||||
);
|
||||
eventBus.on("cache-flush-" + name, (_, isLocal) =>
|
||||
!isLocal ? flush(false) : null,
|
||||
!isLocal ? flush(false) : null
|
||||
);
|
||||
|
||||
const set = (key, value, emitEvent = true) => {
|
||||
|
28
src/db/db.js
28
src/db/db.js
@ -27,7 +27,7 @@ async function openDatabase() {
|
||||
db = await openDB("ssr", SSR_DB_VERSION, {
|
||||
async upgrade(db, oldVersion, newVersion, transaction) {
|
||||
log.info(
|
||||
`Converting database from version ${oldVersion} to version ${newVersion}`,
|
||||
`Converting database from version ${oldVersion} to version ${newVersion}`
|
||||
);
|
||||
|
||||
dbNewVersion = newVersion;
|
||||
@ -50,7 +50,7 @@ async function openDatabase() {
|
||||
playersHistory.createIndex(
|
||||
"players-history-timestamp",
|
||||
"timestamp",
|
||||
{ unique: false },
|
||||
{ unique: false }
|
||||
);
|
||||
|
||||
const scoresStore = db.createObjectStore("scores", {
|
||||
@ -89,17 +89,17 @@ async function openDatabase() {
|
||||
{
|
||||
keyPath: "_idbId",
|
||||
autoIncrement: true,
|
||||
},
|
||||
}
|
||||
);
|
||||
rankedsChangesStore.createIndex(
|
||||
"rankeds-changes-timestamp",
|
||||
"timestamp",
|
||||
{ unique: false },
|
||||
{ unique: false }
|
||||
);
|
||||
rankedsChangesStore.createIndex(
|
||||
"rankeds-changes-leaderboardId",
|
||||
"leaderboardId",
|
||||
{ unique: false },
|
||||
{ unique: false }
|
||||
);
|
||||
|
||||
// no autoIncrement, no keyPath - key must be provided
|
||||
@ -197,12 +197,12 @@ async function openDatabase() {
|
||||
{
|
||||
keyPath: "id",
|
||||
autoIncrement: false,
|
||||
},
|
||||
}
|
||||
);
|
||||
scoresUpdateQueue.createIndex(
|
||||
"scores-update-queue-fetchedAt",
|
||||
"fetchedAt",
|
||||
{ unique: false },
|
||||
{ unique: false }
|
||||
);
|
||||
|
||||
case newVersion >= 8 && oldVersion <= 7:
|
||||
@ -220,7 +220,7 @@ async function openDatabase() {
|
||||
playersHistoryStorev9.createIndex(
|
||||
"players-history-playerIdSsTimestamp",
|
||||
"playerIdSsTimestamp",
|
||||
{ unique: true },
|
||||
{ unique: true }
|
||||
);
|
||||
|
||||
// NO break here
|
||||
@ -246,17 +246,17 @@ async function openDatabase() {
|
||||
{
|
||||
keyPath: "id",
|
||||
autoIncrement: false,
|
||||
},
|
||||
}
|
||||
);
|
||||
accSaberPlayersStore.createIndex(
|
||||
"accsaber-players-playerId",
|
||||
"playerId",
|
||||
{ unique: false },
|
||||
{ unique: false }
|
||||
);
|
||||
accSaberPlayersStore.createIndex(
|
||||
"accsaber-players-category",
|
||||
"category",
|
||||
{ unique: false },
|
||||
{ unique: false }
|
||||
);
|
||||
|
||||
// NO break here
|
||||
@ -267,12 +267,12 @@ async function openDatabase() {
|
||||
{
|
||||
keyPath: "playerIdTimestamp",
|
||||
autoIncrement: false,
|
||||
},
|
||||
}
|
||||
);
|
||||
accSaberPlayersHistoryStore.createIndex(
|
||||
"accsaber-players-history-playerId",
|
||||
"playerId",
|
||||
{ unique: false },
|
||||
{ unique: false }
|
||||
);
|
||||
|
||||
// NO break here
|
||||
@ -307,7 +307,7 @@ async function openDatabase() {
|
||||
objectStores,
|
||||
closure,
|
||||
mode = "readwrite",
|
||||
options = { durability: "strict" },
|
||||
options = { durability: "strict" }
|
||||
) => {
|
||||
try {
|
||||
const tx = db.transaction(objectStores, mode, options);
|
||||
|
@ -41,7 +41,7 @@ const allFixes = {
|
||||
: [];
|
||||
allAppliedFixes.push(fixName);
|
||||
await keyValueStore.put(allAppliedFixes, FIXES_KEY);
|
||||
},
|
||||
}
|
||||
);
|
||||
},
|
||||
},
|
||||
@ -75,14 +75,14 @@ const allFixes = {
|
||||
log.info(
|
||||
`Unable to convert, deleting a song`,
|
||||
"DBFix",
|
||||
beatSaverSong,
|
||||
beatSaverSong
|
||||
);
|
||||
}
|
||||
} else {
|
||||
log.info(
|
||||
`No metadata characteristics, skipping a song`,
|
||||
"DBFix",
|
||||
beatSaverSong,
|
||||
beatSaverSong
|
||||
);
|
||||
}
|
||||
|
||||
@ -99,7 +99,7 @@ const allFixes = {
|
||||
await keyValueStore.put(allAppliedFixes, FIXES_KEY);
|
||||
|
||||
log.info(`${songCount} BeatSaver song(s) converted`, "DBFix");
|
||||
},
|
||||
}
|
||||
);
|
||||
},
|
||||
},
|
||||
@ -150,8 +150,8 @@ const allFixes = {
|
||||
lastUpdated: null,
|
||||
login: twitchLogin,
|
||||
playerId,
|
||||
}),
|
||||
),
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
await addAppliedFix(fixName);
|
||||
@ -203,7 +203,7 @@ const allFixes = {
|
||||
: [];
|
||||
allAppliedFixes.push(fixName);
|
||||
await keyValueStore.put(allAppliedFixes, FIXES_KEY);
|
||||
},
|
||||
}
|
||||
);
|
||||
},
|
||||
},
|
||||
@ -216,7 +216,7 @@ export default async () => {
|
||||
const neededFixes = Object.keys(allFixes).filter(
|
||||
(f) =>
|
||||
!appliedFixes.includes(f) &&
|
||||
(!allFixes[f].validTo || allFixes[f].validTo > new Date()),
|
||||
(!allFixes[f].validTo || allFixes[f].validTo > new Date())
|
||||
);
|
||||
|
||||
if (!neededFixes.length) return;
|
||||
|
@ -75,7 +75,7 @@ export default (storeName, inlineKeyName = undefined, indexesKeyNames = {}) => {
|
||||
const cacheKey = getCacheKeyFor(key);
|
||||
|
||||
return repositoryCache.get(key, () =>
|
||||
resolvePromiseOrWaitForPending(cacheKey, () => db.get(storeName, key)),
|
||||
resolvePromiseOrWaitForPending(cacheKey, () => db.get(storeName, key))
|
||||
);
|
||||
};
|
||||
|
||||
@ -89,7 +89,7 @@ export default (storeName, inlineKeyName = undefined, indexesKeyNames = {}) => {
|
||||
|
||||
const getFromDb = () =>
|
||||
resolvePromiseOrWaitForPending(cacheKey, () =>
|
||||
db.getFromIndex(storeName, indexName, query),
|
||||
db.getFromIndex(storeName, indexName, query)
|
||||
);
|
||||
|
||||
if (query && query instanceof IDBKeyRange) return getFromDb();
|
||||
@ -114,7 +114,7 @@ export default (storeName, inlineKeyName = undefined, indexesKeyNames = {}) => {
|
||||
isIndexDataAvailable(cacheKey) ||
|
||||
isIndexDataAvailable(fullIndexCacheKey)
|
||||
? filterItems
|
||||
: null,
|
||||
: null
|
||||
);
|
||||
};
|
||||
|
||||
@ -134,7 +134,7 @@ export default (storeName, inlineKeyName = undefined, indexesKeyNames = {}) => {
|
||||
const data = convertArrayToObjectByKey(await getFromDb(), inlineKeyName);
|
||||
|
||||
const ret = Object.values(repositoryCache.setAll(data)).filter(
|
||||
filterUndefined,
|
||||
filterUndefined
|
||||
);
|
||||
|
||||
setAllDataAvailabilityStatus();
|
||||
@ -148,7 +148,7 @@ export default (storeName, inlineKeyName = undefined, indexesKeyNames = {}) => {
|
||||
const getAllFromIndex = async (
|
||||
indexName,
|
||||
query = undefined,
|
||||
refreshCache = false,
|
||||
refreshCache = false
|
||||
) => {
|
||||
if (hasOutOfLineKey())
|
||||
throw `getAllFromIndex() is not available for stores with out-of-line key`;
|
||||
@ -159,7 +159,7 @@ export default (storeName, inlineKeyName = undefined, indexesKeyNames = {}) => {
|
||||
|
||||
const getFromDb = async () =>
|
||||
resolvePromiseOrWaitForPending(cacheKey, () =>
|
||||
db.getAllFromIndex(storeName, indexName, query),
|
||||
db.getAllFromIndex(storeName, indexName, query)
|
||||
);
|
||||
|
||||
if (query && query instanceof IDBKeyRange) return getFromDb();
|
||||
|
@ -62,7 +62,7 @@ let app = null;
|
||||
"InvalidStateError: A mutation operation was attempted on a database that did not allow mutations."
|
||||
)
|
||||
error = new Error(
|
||||
"Firefox in private mode does not support the database. Please run the site in normal mode.",
|
||||
"Firefox in private mode does not support the database. Please run the site in normal mode."
|
||||
);
|
||||
|
||||
app = new ErrorComponent({
|
||||
|
@ -24,7 +24,7 @@ export default (size = DEFAULT_CACHE_SIZE, expiryIn = MINUTE) => {
|
||||
cum[key] = value;
|
||||
return cum;
|
||||
},
|
||||
{},
|
||||
{}
|
||||
);
|
||||
}
|
||||
|
||||
@ -43,7 +43,7 @@ export default (size = DEFAULT_CACHE_SIZE, expiryIn = MINUTE) => {
|
||||
if (value.headers) {
|
||||
const headers = new Headers();
|
||||
Object.keys(value.headers).map((k) =>
|
||||
headers.append(k, value.headers[k]),
|
||||
headers.append(k, value.headers[k])
|
||||
);
|
||||
newValue.headers = headers;
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ const get = async ({
|
||||
const response = await queue.ACCSABER.playerRankHistory(
|
||||
playerId,
|
||||
priority,
|
||||
queueOptions,
|
||||
queueOptions
|
||||
);
|
||||
|
||||
return {
|
||||
|
@ -23,7 +23,7 @@ const get = async ({
|
||||
category,
|
||||
page,
|
||||
priority,
|
||||
queueOptions,
|
||||
queueOptions
|
||||
);
|
||||
|
||||
return {
|
||||
|
@ -85,7 +85,7 @@ const get = async ({
|
||||
playerId,
|
||||
page,
|
||||
priority,
|
||||
queueOptions,
|
||||
queueOptions
|
||||
);
|
||||
|
||||
return {
|
||||
|
@ -23,7 +23,7 @@ export default (get, process) => {
|
||||
const response = await clientGet({ ...getOptions, priority, fullResponse });
|
||||
|
||||
const processedResponse = process(
|
||||
fullResponse ? getResponseBody(response) : response,
|
||||
fullResponse ? getResponseBody(response) : response
|
||||
);
|
||||
|
||||
return fullResponse
|
||||
|
@ -56,7 +56,7 @@ const get = async ({
|
||||
leaderboardId,
|
||||
page,
|
||||
priority,
|
||||
queueOptions,
|
||||
queueOptions
|
||||
);
|
||||
|
||||
const client = createClient(get, process);
|
||||
|
@ -5,7 +5,7 @@ import createClient from "../../generic";
|
||||
|
||||
const process = (response) => {
|
||||
const apiProcessedResponse = api.process(
|
||||
response && response.player ? response.player : null,
|
||||
response && response.player ? response.player : null
|
||||
);
|
||||
|
||||
if (!opt(apiProcessedResponse, "player.playerInfo")) return null;
|
||||
@ -20,7 +20,7 @@ const process = (response) => {
|
||||
|
||||
const externalProfileUrl = opt(
|
||||
response,
|
||||
"player.playerInfo.externalProfileUrl",
|
||||
"player.playerInfo.externalProfileUrl"
|
||||
);
|
||||
if (externalProfileUrl) {
|
||||
apiProcessedResponse.playerInfo.externalProfileUrl = externalProfileUrl;
|
||||
|
@ -27,7 +27,7 @@ export default (dlManager) => {
|
||||
if (!playerId) return;
|
||||
|
||||
await playerService.remove(playerId, purgeScores);
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
eventBus.on("dl-manager-pause-cmd", () => {
|
||||
|
@ -39,7 +39,7 @@ const enqueue = async (
|
||||
type,
|
||||
force = false,
|
||||
data = null,
|
||||
then = null,
|
||||
then = null
|
||||
) => {
|
||||
if (!type || !type.name || !Number.isFinite(type.priority)) {
|
||||
log.warn(`Unknown type enqueued.`, "DlManager", type);
|
||||
@ -49,9 +49,9 @@ const enqueue = async (
|
||||
|
||||
log.debug(
|
||||
`Try to enqueue type ${type.name}. Forced: ${force}, data: ${JSON.stringify(
|
||||
data,
|
||||
data
|
||||
)}`,
|
||||
"DlManager",
|
||||
"DlManager"
|
||||
);
|
||||
|
||||
const priority = force ? PRIORITY.HIGHEST : type.priority;
|
||||
@ -78,13 +78,13 @@ const enqueue = async (
|
||||
queue,
|
||||
{ ...TYPES.ACTIVE_PLAYERS, priority: PRIORITY.HIGHEST },
|
||||
force,
|
||||
{ playerId: mainPlayerId },
|
||||
{ playerId: mainPlayerId }
|
||||
),
|
||||
enqueue(
|
||||
queue,
|
||||
{ ...TYPES.PLAYER_SCORES, priority: PRIORITY.HIGHEST },
|
||||
force,
|
||||
{ playerId: mainPlayerId },
|
||||
{ playerId: mainPlayerId }
|
||||
),
|
||||
]);
|
||||
}
|
||||
@ -98,9 +98,9 @@ const enqueue = async (
|
||||
processThen(
|
||||
queue.add(
|
||||
async () => rankedsStore.refresh(force, networkPriority),
|
||||
priority,
|
||||
priority
|
||||
),
|
||||
then,
|
||||
then
|
||||
).then((_) => log.debug("Enqueued rankeds processed.", "DlManager"));
|
||||
break;
|
||||
|
||||
@ -112,32 +112,32 @@ const enqueue = async (
|
||||
processThen(
|
||||
queue.add(
|
||||
async () => playerService.add(data.playerId, networkPriority),
|
||||
priority,
|
||||
priority
|
||||
),
|
||||
then,
|
||||
then
|
||||
).then((_) =>
|
||||
log.debug("Enqueued active players processed.", "DlManager"),
|
||||
log.debug("Enqueued active players processed.", "DlManager")
|
||||
);
|
||||
else
|
||||
processThen(
|
||||
queue.add(
|
||||
async () =>
|
||||
playerService.refresh(data.playerId, force, networkPriority),
|
||||
priority,
|
||||
priority
|
||||
),
|
||||
then,
|
||||
then
|
||||
).then((_) =>
|
||||
log.debug("Enqueued active players processed.", "DlManager"),
|
||||
log.debug("Enqueued active players processed.", "DlManager")
|
||||
);
|
||||
} else
|
||||
processThen(
|
||||
queue.add(
|
||||
async () => playerService.refreshAll(force, networkPriority),
|
||||
priority,
|
||||
priority
|
||||
),
|
||||
then,
|
||||
then
|
||||
).then((_) =>
|
||||
log.debug("Enqueued active players processed.", "DlManager"),
|
||||
log.debug("Enqueued active players processed.", "DlManager")
|
||||
);
|
||||
break;
|
||||
|
||||
@ -149,21 +149,21 @@ const enqueue = async (
|
||||
queue.add(
|
||||
async () =>
|
||||
scoresService.refresh(data.playerId, force, networkPriority),
|
||||
priority,
|
||||
priority
|
||||
),
|
||||
then,
|
||||
then
|
||||
).then((_) =>
|
||||
log.debug("Enqueued players scores processed.", "DlManager"),
|
||||
log.debug("Enqueued players scores processed.", "DlManager")
|
||||
);
|
||||
else
|
||||
processThen(
|
||||
queue.add(
|
||||
async () => scoresService.refreshAll(force, networkPriority),
|
||||
priority,
|
||||
priority
|
||||
),
|
||||
then,
|
||||
then
|
||||
).then((_) =>
|
||||
log.debug("Enqueued players scores processed.", "DlManager"),
|
||||
log.debug("Enqueued players scores processed.", "DlManager")
|
||||
);
|
||||
break;
|
||||
|
||||
@ -173,9 +173,9 @@ const enqueue = async (
|
||||
processThen(
|
||||
queue.add(
|
||||
async () => beatSaviorService.refreshAll(force, networkPriority),
|
||||
priority,
|
||||
priority
|
||||
),
|
||||
then,
|
||||
then
|
||||
).then((_) => log.debug("Enqueued Beat Savior processed.", "DlManager"));
|
||||
|
||||
break;
|
||||
@ -186,14 +186,14 @@ const enqueue = async (
|
||||
processThen(
|
||||
queue.add(
|
||||
async () => scoresService.updateRankAndPpFromTheQueue(),
|
||||
priority,
|
||||
priority
|
||||
),
|
||||
then,
|
||||
then
|
||||
).then((_) =>
|
||||
log.debug(
|
||||
"Enqueued player scores rank & pp updates processed.",
|
||||
"DlManager",
|
||||
),
|
||||
"DlManager"
|
||||
)
|
||||
);
|
||||
|
||||
break;
|
||||
@ -203,9 +203,9 @@ const enqueue = async (
|
||||
|
||||
processThen(
|
||||
queue.add(async () => accSaberService.refreshAll(), priority),
|
||||
then,
|
||||
then
|
||||
).then((_) =>
|
||||
log.debug("Enqueued AccSaber updates processed.", "DlManager"),
|
||||
log.debug("Enqueued AccSaber updates processed.", "DlManager")
|
||||
);
|
||||
|
||||
break;
|
||||
@ -271,7 +271,7 @@ export default async () => {
|
||||
const nodeId = eventBus.getNodeId();
|
||||
log.info(
|
||||
`Node ${nodeId} is a leader, queue processing enabled`,
|
||||
"DlManager",
|
||||
"DlManager"
|
||||
);
|
||||
|
||||
await startSyncing(queue);
|
||||
@ -284,7 +284,7 @@ export default async () => {
|
||||
TYPES.ACTIVE_PLAYERS,
|
||||
true,
|
||||
{ playerId, add: true },
|
||||
async () => enqueue(queue, TYPES.PLAYER_SCORES, true, { playerId }),
|
||||
async () => enqueue(queue, TYPES.PLAYER_SCORES, true, { playerId })
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -33,7 +33,7 @@ export class SsrHttpResponseError extends SsrNetworkError {
|
||||
`HTTP Error Response: ${
|
||||
response && response.status ? response.status : "None"
|
||||
} ${response && response.statusText ? response.statusText : ""}`,
|
||||
...args,
|
||||
...args
|
||||
);
|
||||
|
||||
this.name = "SsrHttpResponseError";
|
||||
|
@ -97,12 +97,12 @@ export async function fetchUrl(url, options = {}, cors = true) {
|
||||
|
||||
export async function fetchJson(
|
||||
url,
|
||||
{ cacheTtl = null, maxAge = null, ...restOptions } = {},
|
||||
{ cacheTtl = null, maxAge = null, ...restOptions } = {}
|
||||
) {
|
||||
const options = getOptionsWithCacheKey(
|
||||
url,
|
||||
{ cacheTtl, maxAge, ...restOptions },
|
||||
"json",
|
||||
"json"
|
||||
);
|
||||
|
||||
const {
|
||||
@ -129,7 +129,7 @@ export async function fetchJson(
|
||||
body,
|
||||
},
|
||||
fetchCacheKey,
|
||||
fetchCacheTtl,
|
||||
fetchCacheTtl
|
||||
);
|
||||
})
|
||||
.catch((err) => {
|
||||
@ -141,12 +141,12 @@ export async function fetchJson(
|
||||
|
||||
export async function fetchHtml(
|
||||
url,
|
||||
{ cacheTtl = null, maxAge = null, ...restOptions } = {},
|
||||
{ cacheTtl = null, maxAge = null, ...restOptions } = {}
|
||||
) {
|
||||
const options = getOptionsWithCacheKey(
|
||||
url,
|
||||
{ cacheTtl, maxAge, ...restOptions },
|
||||
"json",
|
||||
"json"
|
||||
);
|
||||
|
||||
const {
|
||||
@ -172,7 +172,7 @@ export async function fetchHtml(
|
||||
body: new DOMParser().parseFromString(body, "text/html"),
|
||||
},
|
||||
fetchCacheKey,
|
||||
fetchCacheTtl,
|
||||
fetchCacheTtl
|
||||
);
|
||||
});
|
||||
}
|
||||
|
@ -21,54 +21,54 @@ export default (options = {}) => {
|
||||
category = "overall",
|
||||
page = 1,
|
||||
priority = PRIORITY.FG_LOW,
|
||||
options = {},
|
||||
options = {}
|
||||
) =>
|
||||
fetchJson(
|
||||
substituteVars(RANKING_URL, { category, page }),
|
||||
options,
|
||||
priority,
|
||||
priority
|
||||
);
|
||||
const scores = async (
|
||||
playerId,
|
||||
page = 1,
|
||||
priority = PRIORITY.FG_LOW,
|
||||
options = {},
|
||||
options = {}
|
||||
) =>
|
||||
fetchJson(
|
||||
substituteVars(PLAYER_SCORES_URL, { playerId, page }),
|
||||
options,
|
||||
priority,
|
||||
priority
|
||||
);
|
||||
const playerRankHistory = async (
|
||||
playerId,
|
||||
priority = PRIORITY.FG_LOW,
|
||||
options = {},
|
||||
options = {}
|
||||
) =>
|
||||
fetchJson(
|
||||
substituteVars(PLAYER_RANK_HISTORY, { playerId }),
|
||||
options,
|
||||
priority,
|
||||
priority
|
||||
);
|
||||
const leaderboard = async (
|
||||
leaderboardId,
|
||||
page = 1,
|
||||
priority = PRIORITY.FG_LOW,
|
||||
options = {},
|
||||
options = {}
|
||||
) =>
|
||||
fetchJson(
|
||||
substituteVars(LEADERBOARD_URL, { leaderboardId, page }),
|
||||
options,
|
||||
priority,
|
||||
priority
|
||||
);
|
||||
const leaderboardInfo = async (
|
||||
leaderboardId,
|
||||
priority = PRIORITY.FG_LOW,
|
||||
options = {},
|
||||
options = {}
|
||||
) =>
|
||||
fetchJson(
|
||||
substituteVars(LEADERBOARD_INFO_URL, { leaderboardId }),
|
||||
options,
|
||||
priority,
|
||||
priority
|
||||
);
|
||||
|
||||
return {
|
||||
|
@ -78,7 +78,7 @@ export default (options = {}) => {
|
||||
fetchFunc,
|
||||
url,
|
||||
options,
|
||||
priority = PRIORITY.FG_LOW,
|
||||
priority = PRIORITY.FG_LOW
|
||||
) => {
|
||||
for (let i = 0; i <= retries; i++) {
|
||||
try {
|
||||
@ -140,11 +140,11 @@ export default (options = {}) => {
|
||||
|
||||
const queuedFetchJson = async (url, options, priority = PRIORITY.FG_LOW) =>
|
||||
resolvePromiseOrWaitForPending(url, () =>
|
||||
retriedFetch(fetchJson, url, options, priority),
|
||||
retriedFetch(fetchJson, url, options, priority)
|
||||
);
|
||||
const queuedFetchHtml = async (url, options, priority = PRIORITY.FG_LOW) =>
|
||||
resolvePromiseOrWaitForPending(url, () =>
|
||||
retriedFetch(fetchHtml, url, options, priority),
|
||||
retriedFetch(fetchHtml, url, options, priority)
|
||||
);
|
||||
|
||||
const getRateLimit = () => currentRateLimit;
|
||||
|
@ -63,10 +63,10 @@ const initQueue = (queue) => {
|
||||
|
||||
export default {
|
||||
SCORESABER_API: initQueue(
|
||||
createScoreSaberApiQueue({ concurrency: 3, timeout: 95000 }),
|
||||
createScoreSaberApiQueue({ concurrency: 3, timeout: 95000 })
|
||||
),
|
||||
SCORESABER_PAGE: initQueue(
|
||||
createScoreSaberPageQueue({ concurrency: 3, timeout: 30000 }),
|
||||
createScoreSaberPageQueue({ concurrency: 3, timeout: 30000 })
|
||||
),
|
||||
BEATMAPS: initQueue(
|
||||
createBeatMapsApiQueue({
|
||||
@ -74,7 +74,7 @@ export default {
|
||||
timeout: 10000,
|
||||
intervalCap: 10,
|
||||
interval: 1000,
|
||||
}),
|
||||
})
|
||||
),
|
||||
BEATSAVIOR: initQueue(
|
||||
createBeatSaviorApiQueue({
|
||||
@ -82,7 +82,7 @@ export default {
|
||||
timeout: 10000,
|
||||
intervalCap: 60,
|
||||
interval: 60000,
|
||||
}),
|
||||
})
|
||||
),
|
||||
TWITCH: initQueue(
|
||||
createTwitchApiQueue({
|
||||
@ -90,10 +90,10 @@ export default {
|
||||
timeout: 8000,
|
||||
intervalCap: 800,
|
||||
interval: 60000,
|
||||
}),
|
||||
})
|
||||
),
|
||||
ACCSABER: initQueue(
|
||||
createAccSaberApiQueue({ concurrency: 2, timeout: 10000 }),
|
||||
createAccSaberApiQueue({ concurrency: 2, timeout: 10000 })
|
||||
),
|
||||
PRIORITY,
|
||||
};
|
||||
|
@ -27,7 +27,7 @@ export default (options = {}) => {
|
||||
playerId,
|
||||
page = 1,
|
||||
priority = PRIORITY.FG_LOW,
|
||||
options = {},
|
||||
options = {}
|
||||
) =>
|
||||
fetchJson(substituteVars(baseUrl, { playerId, page }), options, priority);
|
||||
|
||||
@ -35,21 +35,21 @@ export default (options = {}) => {
|
||||
fetchJson(
|
||||
substituteVars(SS_API_PLAYER_INFO_URL, { playerId }),
|
||||
options,
|
||||
priority,
|
||||
priority
|
||||
);
|
||||
|
||||
const recentScores = async (
|
||||
playerId,
|
||||
page = 1,
|
||||
priority = PRIORITY.FG_LOW,
|
||||
options = {},
|
||||
options = {}
|
||||
) => fetchScores(SS_API_RECENT_SCORES_URL, playerId, page, priority, options);
|
||||
|
||||
const topScores = async (
|
||||
playerId,
|
||||
page = 1,
|
||||
priority = PRIORITY.FG_LOW,
|
||||
options = {},
|
||||
options = {}
|
||||
) => fetchScores(SS_API_TOP_SCORES_URL, playerId, page, priority, options);
|
||||
|
||||
const findPlayer = async (query, priority = PRIORITY.FG_LOW, options = {}) =>
|
||||
@ -58,18 +58,18 @@ export default (options = {}) => {
|
||||
query: encodeURIComponent(query),
|
||||
}),
|
||||
options,
|
||||
priority,
|
||||
priority
|
||||
);
|
||||
|
||||
const rankingGlobal = async (
|
||||
page = 1,
|
||||
priority = PRIORITY.FG_LOW,
|
||||
options = {},
|
||||
options = {}
|
||||
) =>
|
||||
fetchJson(
|
||||
substituteVars(SS_API_RANKING_GLOBAL_URL, { page }),
|
||||
options,
|
||||
priority,
|
||||
priority
|
||||
);
|
||||
|
||||
const rankingGlobalPages = async (priority = PRIORITY.FG_LOW, options = {}) =>
|
||||
|
@ -24,7 +24,7 @@ export const parseSsInt = (text) => {
|
||||
export const parseSsFloat = (text) =>
|
||||
text
|
||||
? parseFloat(
|
||||
getFirstRegexpMatch(/([0-9,.]+)\s*$/, text.replace(/[^\d.]/g, "")),
|
||||
getFirstRegexpMatch(/([0-9,.]+)\s*$/, text.replace(/[^\d.]/g, ""))
|
||||
)
|
||||
: null;
|
||||
|
||||
@ -78,32 +78,32 @@ export default (options = {}) => {
|
||||
const rankeds = async (
|
||||
page = 1,
|
||||
priority = PRIORITY.BG_NORMAL,
|
||||
options = {},
|
||||
options = {}
|
||||
) =>
|
||||
fetchJson(substituteVars(RANKEDS_URL, { page }), options, priority).then(
|
||||
(r) => {
|
||||
r.body = processRankeds(r.body);
|
||||
|
||||
return r;
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const processPlayerProfile = (playerId, doc) => {
|
||||
cfDecryptEmail(doc);
|
||||
|
||||
let avatar = getImgUrl(
|
||||
opt(doc.querySelector(".column.avatar img"), "src", null),
|
||||
opt(doc.querySelector(".column.avatar img"), "src", null)
|
||||
);
|
||||
|
||||
let playerName = opt(
|
||||
doc.querySelector(".content .column:not(.avatar) .title a"),
|
||||
"innerText",
|
||||
"innerText"
|
||||
);
|
||||
playerName = playerName ? playerName.trim() : null;
|
||||
|
||||
let country = getFirstRegexpMatch(
|
||||
/^.*?\/flags\/([^.]+)\..*$/,
|
||||
opt(doc.querySelector(".content .column .title img"), "src"),
|
||||
opt(doc.querySelector(".content .column .title img"), "src")
|
||||
);
|
||||
country = country ? country.toUpperCase() : null;
|
||||
|
||||
@ -111,8 +111,8 @@ export default (options = {}) => {
|
||||
opt(
|
||||
doc.querySelector(".pagination .pagination-list li a.is-current"),
|
||||
"innerText",
|
||||
null,
|
||||
),
|
||||
null
|
||||
)
|
||||
);
|
||||
pageNum = !isNaN(pageNum) ? pageNum : null;
|
||||
|
||||
@ -120,8 +120,8 @@ export default (options = {}) => {
|
||||
opt(
|
||||
doc.querySelector(".pagination .pagination-list li:last-of-type"),
|
||||
"innerText",
|
||||
null,
|
||||
),
|
||||
null
|
||||
)
|
||||
);
|
||||
pageQty = !isNaN(pageQty) ? pageQty : null;
|
||||
|
||||
@ -130,31 +130,31 @@ export default (options = {}) => {
|
||||
/^\s*<strong>(?:[^:]+)\s*:?\s*<\/strong>\s*(.*)$/,
|
||||
opt(
|
||||
doc.querySelector(
|
||||
".columns .column:not(.is-narrow) ul li:nth-of-type(3)",
|
||||
),
|
||||
"innerHTML",
|
||||
),
|
||||
".columns .column:not(.is-narrow) ul li:nth-of-type(3)"
|
||||
),
|
||||
"innerHTML"
|
||||
)
|
||||
)
|
||||
);
|
||||
totalItems = !isNaN(totalItems) ? totalItems : 0;
|
||||
|
||||
let playerRank = parseSsInt(
|
||||
opt(
|
||||
doc.querySelector(
|
||||
".content .column ul li:first-of-type a:first-of-type",
|
||||
),
|
||||
"innerText",
|
||||
".content .column ul li:first-of-type a:first-of-type"
|
||||
),
|
||||
"innerText"
|
||||
)
|
||||
);
|
||||
playerRank = !isNaN(playerRank) ? playerRank : null;
|
||||
|
||||
let countryRank = parseSsInt(
|
||||
opt(
|
||||
doc.querySelector(
|
||||
'.content .column ul li:first-of-type a[href^="/global?country="]',
|
||||
),
|
||||
"innerText",
|
||||
'.content .column ul li:first-of-type a[href^="/global?country="]'
|
||||
),
|
||||
"innerText"
|
||||
)
|
||||
);
|
||||
countryRank = !isNaN(countryRank) ? countryRank : null;
|
||||
|
||||
@ -170,7 +170,7 @@ export default (options = {}) => {
|
||||
[...doc.querySelectorAll(".content .column ul li")]
|
||||
.map((li) => {
|
||||
const matches = li.innerHTML.match(
|
||||
/^\s*<strong>([^:]+)\s*:?\s*<\/strong>\s*(.*)$/,
|
||||
/^\s*<strong>([^:]+)\s*:?\s*<\/strong>\s*(.*)$/
|
||||
);
|
||||
if (!matches) return null;
|
||||
|
||||
@ -219,7 +219,7 @@ export default (options = {}) => {
|
||||
const item = mapping.find((m) => m.key === matches[1]);
|
||||
return item ? { ...item, value } : { label: matches[1], value };
|
||||
})
|
||||
.filter((s) => s),
|
||||
.filter((s) => s)
|
||||
)
|
||||
.reduce(
|
||||
(cum, item) => {
|
||||
@ -255,7 +255,7 @@ export default (options = {}) => {
|
||||
|
||||
return cum;
|
||||
},
|
||||
{ inactiveAccount: false, bannedAccount: false },
|
||||
{ inactiveAccount: false, bannedAccount: false }
|
||||
);
|
||||
|
||||
const scores = [...doc.querySelectorAll("table.ranking tbody tr")].map(
|
||||
@ -274,7 +274,7 @@ export default (options = {}) => {
|
||||
if (song) {
|
||||
const leaderboardId = parseInt(
|
||||
getFirstRegexpMatch(/leaderboard\/(\d+)/, song.href),
|
||||
10,
|
||||
10
|
||||
);
|
||||
ret.leaderboardId = leaderboardId ? leaderboardId : null;
|
||||
} else {
|
||||
@ -293,7 +293,7 @@ export default (options = {}) => {
|
||||
.replace(/&/g, "&")
|
||||
.replace(
|
||||
/<span class="__cf_email__" data-cfemail="[^"]+">\[email protected]<\/span>/g,
|
||||
"",
|
||||
""
|
||||
)
|
||||
.match(/^(.*?)\s*<span[^>]+>(.*?)<\/span>/)
|
||||
: null;
|
||||
@ -328,7 +328,7 @@ export default (options = {}) => {
|
||||
ret.timeSet = songDate ? dateFromString(songDate.title) : null;
|
||||
|
||||
const pp = parseSsFloat(
|
||||
opt(tr.querySelector("th.score .scoreTop.ppValue"), "innerText"),
|
||||
opt(tr.querySelector("th.score .scoreTop.ppValue"), "innerText")
|
||||
);
|
||||
ret.pp = !isNaN(pp) ? pp : null;
|
||||
|
||||
@ -337,9 +337,9 @@ export default (options = {}) => {
|
||||
/^\(([0-9.]+)pp\)$/,
|
||||
opt(
|
||||
tr.querySelector("th.score .scoreTop.ppWeightedValue"),
|
||||
"innerText",
|
||||
),
|
||||
),
|
||||
"innerText"
|
||||
)
|
||||
)
|
||||
);
|
||||
ret.ppWeighted = !isNaN(ppWeighted) ? ppWeighted : null;
|
||||
|
||||
@ -380,7 +380,7 @@ export default (options = {}) => {
|
||||
}
|
||||
|
||||
return ret;
|
||||
},
|
||||
}
|
||||
);
|
||||
const recentPlay =
|
||||
scores && scores.length && scores[0].timeSet ? scores[0].timeSet : null;
|
||||
@ -394,18 +394,18 @@ export default (options = {}) => {
|
||||
externalProfileUrl: opt(
|
||||
doc.querySelector(".content .column:not(.avatar) .title a"),
|
||||
"href",
|
||||
null,
|
||||
null
|
||||
),
|
||||
history: getFirstRegexpMatch(
|
||||
/data:\s*\[([0-9,]+)\]/,
|
||||
doc.body.innerHTML,
|
||||
doc.body.innerHTML
|
||||
),
|
||||
country,
|
||||
badges: [...doc.querySelectorAll(".column.avatar center img")].map(
|
||||
(img) => ({
|
||||
image: getImgUrl(img.src),
|
||||
description: img.title,
|
||||
}),
|
||||
})
|
||||
),
|
||||
rank: stats.rank ? stats.rank : null,
|
||||
countryRank: stats.countryRank ? stats.countryRank : null,
|
||||
@ -435,7 +435,7 @@ export default (options = {}) => {
|
||||
fetchHtml(
|
||||
substituteVars(PLAYER_PROFILE_URL, { playerId }),
|
||||
options,
|
||||
priority,
|
||||
priority
|
||||
).then((r) => {
|
||||
r.body = processPlayerProfile(playerId, r.body);
|
||||
|
||||
@ -451,17 +451,17 @@ export default (options = {}) => {
|
||||
const id = getFirstRegexpMatch(/\/(\d+)$/, a.href);
|
||||
|
||||
const avatar = getImgUrl(
|
||||
opt(tr.querySelector("td.picture img"), "src", null),
|
||||
opt(tr.querySelector("td.picture img"), "src", null)
|
||||
);
|
||||
|
||||
let country = getFirstRegexpMatch(
|
||||
/^.*?\/flags\/([^.]+)\..*$/,
|
||||
opt(tr.querySelector("td.player img"), "src", null),
|
||||
opt(tr.querySelector("td.player img"), "src", null)
|
||||
);
|
||||
country = country ? country.toUpperCase() : null;
|
||||
|
||||
let difference = parseSsInt(
|
||||
opt(tr.querySelector("td.diff"), "innerText", null),
|
||||
opt(tr.querySelector("td.diff"), "innerText", null)
|
||||
);
|
||||
difference = !isNaN(difference) ? difference : null;
|
||||
|
||||
@ -469,15 +469,15 @@ export default (options = {}) => {
|
||||
playerName = playerName || playerName === "" ? playerName.trim() : null;
|
||||
|
||||
let pp = parseSsFloat(
|
||||
opt(tr.querySelector("td.pp .scoreTop.ppValue"), "innerText"),
|
||||
opt(tr.querySelector("td.pp .scoreTop.ppValue"), "innerText")
|
||||
);
|
||||
pp = !isNaN(pp) ? pp : null;
|
||||
|
||||
let rank = parseSsInt(
|
||||
getFirstRegexpMatch(
|
||||
/^\s*#(\d+)\s*$/,
|
||||
opt(tr.querySelector("td.rank"), "innerText", null),
|
||||
),
|
||||
opt(tr.querySelector("td.rank"), "innerText", null)
|
||||
)
|
||||
);
|
||||
rank = !isNaN(rank) ? rank : null;
|
||||
|
||||
@ -491,7 +491,7 @@ export default (options = {}) => {
|
||||
pp,
|
||||
rank,
|
||||
};
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
return { players: data };
|
||||
@ -501,12 +501,12 @@ export default (options = {}) => {
|
||||
country,
|
||||
page = 1,
|
||||
priority = PRIORITY.FG_LOW,
|
||||
options = {},
|
||||
options = {}
|
||||
) =>
|
||||
fetchHtml(
|
||||
substituteVars(COUNTRY_RANKING_URL, { country, page }),
|
||||
options,
|
||||
priority,
|
||||
priority
|
||||
).then((r) => {
|
||||
r.body = processCountryRanking(country, r.body);
|
||||
|
||||
@ -529,11 +529,11 @@ export default (options = {}) => {
|
||||
};
|
||||
|
||||
ret.player.playerInfo.avatar = getImgUrl(
|
||||
opt(tr.querySelector(".picture img"), "src", null),
|
||||
opt(tr.querySelector(".picture img"), "src", null)
|
||||
);
|
||||
|
||||
ret.score.rank = parseSsInt(
|
||||
opt(tr.querySelector("td.rank"), "innerText"),
|
||||
opt(tr.querySelector("td.rank"), "innerText")
|
||||
);
|
||||
if (isNaN(ret.score.rank)) ret.score.rank = null;
|
||||
|
||||
@ -541,7 +541,7 @@ export default (options = {}) => {
|
||||
if (player) {
|
||||
let country = getFirstRegexpMatch(
|
||||
/^.*?\/flags\/([^.]+)\..*$/,
|
||||
opt(player.querySelector("img"), "src", ""),
|
||||
opt(player.querySelector("img"), "src", "")
|
||||
);
|
||||
country = country ? country.toUpperCase() : null;
|
||||
if (country) {
|
||||
@ -551,14 +551,14 @@ export default (options = {}) => {
|
||||
|
||||
ret.player.name = opt(
|
||||
player.querySelector("span.songTop.pp"),
|
||||
"innerText",
|
||||
"innerText"
|
||||
);
|
||||
ret.player.name = ret.player.name
|
||||
? ret.player.name.trim().replace("'", "'")
|
||||
: null;
|
||||
ret.player.playerId = getFirstRegexpMatch(
|
||||
/\/u\/(\d+)((\?|&|#).*)?$/,
|
||||
opt(player, "href", ""),
|
||||
opt(player, "href", "")
|
||||
);
|
||||
ret.player.playerId = ret.player.playerId
|
||||
? ret.player.playerId.trim()
|
||||
@ -574,7 +574,7 @@ export default (options = {}) => {
|
||||
ret.score.timeSetString = opt(
|
||||
tr.querySelector("td.timeset"),
|
||||
"innerText",
|
||||
null,
|
||||
null
|
||||
);
|
||||
if (ret.score.timeSetString)
|
||||
ret.score.timeSetString = ret.score.timeSetString.trim();
|
||||
@ -602,7 +602,7 @@ export default (options = {}) => {
|
||||
const diffs = [...doc.querySelectorAll(".tabs ul li a")].map((a) => {
|
||||
let leaderboardId = parseInt(
|
||||
getFirstRegexpMatch(/leaderboard\/(\d+)$/, a.href),
|
||||
10,
|
||||
10
|
||||
);
|
||||
if (isNaN(leaderboardId)) leaderboardId = null;
|
||||
|
||||
@ -615,7 +615,7 @@ export default (options = {}) => {
|
||||
const currentDiffHuman = opt(
|
||||
doc.querySelector(".tabs li.is-active a span"),
|
||||
"innerText",
|
||||
null,
|
||||
null
|
||||
);
|
||||
|
||||
let diff = null;
|
||||
@ -628,20 +628,20 @@ export default (options = {}) => {
|
||||
|
||||
const songName = opt(
|
||||
doc.querySelector(
|
||||
".column.is-one-third-desktop .box:first-of-type .title a",
|
||||
".column.is-one-third-desktop .box:first-of-type .title a"
|
||||
),
|
||||
"innerText",
|
||||
null,
|
||||
null
|
||||
);
|
||||
|
||||
const imageUrl = getImgUrl(
|
||||
opt(
|
||||
doc.querySelector(
|
||||
".column.is-one-third-desktop .box:first-of-type .columns .column.is-one-quarter img",
|
||||
".column.is-one-third-desktop .box:first-of-type .columns .column.is-one-quarter img"
|
||||
),
|
||||
"src",
|
||||
null,
|
||||
),
|
||||
null
|
||||
)
|
||||
);
|
||||
|
||||
const songInfo = [
|
||||
@ -656,13 +656,13 @@ export default (options = {}) => {
|
||||
]
|
||||
.map((sid) => {
|
||||
let songInfoBox = doc.querySelector(
|
||||
".column.is-one-third-desktop .box:first-of-type",
|
||||
".column.is-one-third-desktop .box:first-of-type"
|
||||
);
|
||||
return {
|
||||
...sid,
|
||||
value: songInfoBox
|
||||
? songInfoBox.innerHTML.match(
|
||||
new RegExp(sid.label + ":\\s*<b>(.*?)</b>", "i"),
|
||||
new RegExp(sid.label + ":\\s*<b>(.*?)</b>", "i")
|
||||
)
|
||||
: null,
|
||||
};
|
||||
@ -708,7 +708,7 @@ export default (options = {}) => {
|
||||
|
||||
return cum;
|
||||
},
|
||||
{ imageUrl, stats: {} },
|
||||
{ imageUrl, stats: {} }
|
||||
);
|
||||
|
||||
const { stats, ...song } = songInfo;
|
||||
@ -718,9 +718,9 @@ export default (options = {}) => {
|
||||
opt(
|
||||
doc.querySelector(".pagination .pagination-list li:last-of-type"),
|
||||
"innerText",
|
||||
null,
|
||||
null
|
||||
),
|
||||
10,
|
||||
10
|
||||
);
|
||||
if (isNaN(pageQty)) pageQty = null;
|
||||
|
||||
@ -736,7 +736,7 @@ export default (options = {}) => {
|
||||
|
||||
let diffChartText = getFirstRegexpMatch(
|
||||
/'difficulty',\s*([0-9.,\s]+)\s*\]/,
|
||||
doc.body.innerHTML,
|
||||
doc.body.innerHTML
|
||||
);
|
||||
let diffChart = (diffChartText ? diffChartText : "")
|
||||
.split(",")
|
||||
@ -758,12 +758,12 @@ export default (options = {}) => {
|
||||
leaderboardId,
|
||||
page = 1,
|
||||
priority = PRIORITY.FG_LOW,
|
||||
options = {},
|
||||
options = {}
|
||||
) =>
|
||||
fetchHtml(
|
||||
substituteVars(LEADERBOARD_URL, { leaderboardId, page }),
|
||||
options,
|
||||
priority,
|
||||
priority
|
||||
).then((r) => {
|
||||
r.body = processLeaderboard(leaderboardId, page, r.body);
|
||||
|
||||
|
@ -7,7 +7,7 @@ const CLIENT_ID = "u0swxz56n4iumc634at1osoqdk31qt";
|
||||
const TWITCH_AUTH_URL = "https://id.twitch.tv/oauth2";
|
||||
const AUTHORIZATION_URL =
|
||||
`${TWITCH_AUTH_URL}/authorize?client_id=${CLIENT_ID}&redirect_uri=${encodeURIComponent(
|
||||
ssrConfig.domain + "/twitch",
|
||||
ssrConfig.domain + "/twitch"
|
||||
)}&response_type=token` + "&scope=${scopes}&state=${state}";
|
||||
const VALIDATE_URL = `${TWITCH_AUTH_URL}/validate`;
|
||||
|
||||
@ -26,7 +26,7 @@ export default (options = {}) => {
|
||||
url,
|
||||
accessToken,
|
||||
priority = PRIORITY.FG_LOW,
|
||||
options = {},
|
||||
options = {}
|
||||
) =>
|
||||
fetchJson(
|
||||
url,
|
||||
@ -37,7 +37,7 @@ export default (options = {}) => {
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
},
|
||||
priority,
|
||||
priority
|
||||
);
|
||||
|
||||
const getAuthUrl = (state = "", scopes = "") =>
|
||||
@ -49,25 +49,25 @@ export default (options = {}) => {
|
||||
const validateToken = async (
|
||||
accessToken,
|
||||
priority = PRIORITY.FG_LOW,
|
||||
options = {},
|
||||
options = {}
|
||||
) =>
|
||||
fetchJson(
|
||||
VALIDATE_URL,
|
||||
{ ...options, headers: { Authorization: `OAuth ${accessToken}` } },
|
||||
priority,
|
||||
priority
|
||||
);
|
||||
|
||||
const profile = async (
|
||||
accessToken,
|
||||
login,
|
||||
priority = PRIORITY.FG_LOW,
|
||||
options = {},
|
||||
options = {}
|
||||
) =>
|
||||
fetchApi(
|
||||
substituteVars(PROFILE_URL, { login: encodeURIComponent(login) }),
|
||||
accessToken,
|
||||
priority,
|
||||
options,
|
||||
options
|
||||
);
|
||||
|
||||
const videos = async (
|
||||
@ -75,7 +75,7 @@ export default (options = {}) => {
|
||||
userId,
|
||||
type = "archive",
|
||||
priority = PRIORITY.FG_LOW,
|
||||
options = {},
|
||||
options = {}
|
||||
) =>
|
||||
fetchApi(
|
||||
substituteVars(VIDEOS_URL, {
|
||||
@ -84,20 +84,20 @@ export default (options = {}) => {
|
||||
}),
|
||||
accessToken,
|
||||
priority,
|
||||
options,
|
||||
options
|
||||
);
|
||||
|
||||
const streams = async (
|
||||
accessToken,
|
||||
userId,
|
||||
priority = PRIORITY.FG_LOW,
|
||||
options = {},
|
||||
options = {}
|
||||
) =>
|
||||
fetchApi(
|
||||
substituteVars(STREAMS_URL, { userId: encodeURIComponent(userId) }),
|
||||
accessToken,
|
||||
priority,
|
||||
options,
|
||||
options
|
||||
);
|
||||
|
||||
return {
|
||||
|
@ -43,7 +43,7 @@ export default () => {
|
||||
const getCategories = async () => {
|
||||
const categories = await resolvePromiseOrWaitForPending(
|
||||
`accSaberCategories`,
|
||||
() => accSaberCategoriesRepository().getAll(),
|
||||
() => accSaberCategoriesRepository().getAll()
|
||||
);
|
||||
|
||||
const getIdx = (category) => {
|
||||
@ -58,25 +58,25 @@ export default () => {
|
||||
resolvePromiseOrWaitForPending(`accSaberPlayer/${playerId}`, () =>
|
||||
accSaberPlayersRepository().getAllFromIndex(
|
||||
"accsaber-players-playerId",
|
||||
playerId,
|
||||
),
|
||||
playerId
|
||||
)
|
||||
);
|
||||
const getRanking = async (category = "overall") =>
|
||||
accSaberPlayersRepository().getAllFromIndex(
|
||||
"accsaber-players-category",
|
||||
category,
|
||||
category
|
||||
);
|
||||
const getPlayerHistory = async (playerId) =>
|
||||
resolvePromiseOrWaitForPending(`accSaberPlayerHistory/${playerId}`, () =>
|
||||
accSaberPlayersHistoryRepository().getAllFromIndex(
|
||||
"accsaber-players-history-playerId",
|
||||
playerId,
|
||||
),
|
||||
playerId
|
||||
)
|
||||
);
|
||||
|
||||
const isDataForPlayerAvailable = async (playerId) =>
|
||||
(await Promise.all([getPlayer(playerId), getCategories()])).every(
|
||||
(d) => d?.length,
|
||||
(d) => d?.length
|
||||
);
|
||||
|
||||
const getPlayerGain = (playerHistory, daysAgo = 1, maxDaysAgo = 7) =>
|
||||
@ -85,7 +85,7 @@ export default () => {
|
||||
toAccSaberMidnight,
|
||||
"accSaberDate",
|
||||
daysAgo,
|
||||
maxDaysAgo,
|
||||
maxDaysAgo
|
||||
);
|
||||
|
||||
const getLastUpdatedKey = (type) => `accSaber${capitalize(type)}LastUpdated`;
|
||||
@ -100,9 +100,9 @@ export default () => {
|
||||
if (lastUpdated && lastUpdated > new Date() - REFRESH_INTERVAL) {
|
||||
log.debug(
|
||||
`Refresh interval for ${type} not yet expired, skipping. Next refresh on ${formatDate(
|
||||
addToDate(REFRESH_INTERVAL, lastUpdated),
|
||||
addToDate(REFRESH_INTERVAL, lastUpdated)
|
||||
)}`,
|
||||
"AccSaberService",
|
||||
"AccSaberService"
|
||||
);
|
||||
|
||||
return false;
|
||||
@ -116,7 +116,7 @@ export default () => {
|
||||
playerId,
|
||||
page = 1,
|
||||
priority = PRIORITY.FG_LOW,
|
||||
{ ...options } = {},
|
||||
{ ...options } = {}
|
||||
) => {
|
||||
if (!options) options = {};
|
||||
if (!options.hasOwnProperty("cacheTtl"))
|
||||
@ -124,7 +124,7 @@ export default () => {
|
||||
|
||||
const categoriesByDisplayName = convertArrayToObjectByKey(
|
||||
await getCategories(),
|
||||
"displayName",
|
||||
"displayName"
|
||||
);
|
||||
|
||||
return (
|
||||
@ -136,7 +136,7 @@ export default () => {
|
||||
playerId,
|
||||
page,
|
||||
priority,
|
||||
}),
|
||||
})
|
||||
)
|
||||
).map((s) => ({
|
||||
...s,
|
||||
@ -150,7 +150,7 @@ export default () => {
|
||||
};
|
||||
|
||||
const getScoresHistogramDefinition = (
|
||||
serviceParams = { type: "overall", sort: "ap", order: "desc" },
|
||||
serviceParams = { type: "overall", sort: "ap", order: "desc" }
|
||||
) => {
|
||||
const scoreType = serviceParams?.type ?? "overall";
|
||||
const sort = serviceParams?.sort ?? "ap";
|
||||
@ -258,7 +258,7 @@ export default () => {
|
||||
|
||||
const getPlayerScoresPage = async (
|
||||
playerId,
|
||||
serviceParams = { sort: "recent", order: "desc", page: 1 },
|
||||
serviceParams = { sort: "recent", order: "desc", page: 1 }
|
||||
) => {
|
||||
let page = serviceParams?.page ?? 1;
|
||||
if (page < 1) page = 1;
|
||||
@ -290,7 +290,7 @@ export default () => {
|
||||
const fetchPlayerRankHistory = async (
|
||||
playerId,
|
||||
priority = PRIORITY.FG_LOW,
|
||||
{ ...options } = {},
|
||||
{ ...options } = {}
|
||||
) => {
|
||||
if (!options) options = {};
|
||||
if (!options.hasOwnProperty("cacheTtl"))
|
||||
@ -306,13 +306,13 @@ export default () => {
|
||||
const refreshCategories = async (
|
||||
forceUpdate = false,
|
||||
priority = queues.PRIORITY.BG_NORMAL,
|
||||
throwErrors = false,
|
||||
throwErrors = false
|
||||
) => {
|
||||
log.debug(
|
||||
`Starting AccSaber categories refreshing${
|
||||
forceUpdate ? " (forced)" : ""
|
||||
}...`,
|
||||
"AccSaberService",
|
||||
"AccSaberService"
|
||||
);
|
||||
|
||||
try {
|
||||
@ -327,7 +327,7 @@ export default () => {
|
||||
|
||||
log.trace(
|
||||
`Fetching current categories from AccSaber...`,
|
||||
"AccSaberService",
|
||||
"AccSaberService"
|
||||
);
|
||||
|
||||
let categories = await accSaberCategoriesApiClient.getProcessed({
|
||||
@ -352,13 +352,13 @@ export default () => {
|
||||
|
||||
const dbCategoriesNames = dbCategories.map((c) => c.name);
|
||||
const newCategories = categories.filter(
|
||||
(c) => !dbCategories || !dbCategoriesNames.includes(c.name),
|
||||
(c) => !dbCategories || !dbCategoriesNames.includes(c.name)
|
||||
);
|
||||
|
||||
if (newCategories && newCategories.length)
|
||||
log.debug(
|
||||
`${newCategories.length} new categories found`,
|
||||
"AccSaberService",
|
||||
"AccSaberService"
|
||||
);
|
||||
|
||||
await db.runInTransaction(
|
||||
@ -385,14 +385,14 @@ export default () => {
|
||||
log.trace(`Updating categories in DB...`, "AccSaberService");
|
||||
|
||||
await Promise.all(
|
||||
categories.map(async (c) => accSaberCategoriesStore.put(c)),
|
||||
categories.map(async (c) => accSaberCategoriesStore.put(c))
|
||||
);
|
||||
|
||||
log.trace(`Categories updated`, "AccSaberService");
|
||||
|
||||
log.trace(
|
||||
`Updating categories last update date in DB...`,
|
||||
"AccSaberService",
|
||||
"AccSaberService"
|
||||
);
|
||||
|
||||
await tx
|
||||
@ -400,13 +400,13 @@ export default () => {
|
||||
.put(new Date(), getLastUpdatedKey("categories"));
|
||||
|
||||
log.debug(`Categories last update date updated`, "AccSaberService");
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
accSaberCategoriesRepository().addToCache(categories);
|
||||
keyValueRepository().setCache(
|
||||
getLastUpdatedKey("categories"),
|
||||
new Date(),
|
||||
new Date()
|
||||
);
|
||||
|
||||
log.debug(`Categories refreshing completed`, "AccSaberService");
|
||||
@ -427,7 +427,7 @@ export default () => {
|
||||
try {
|
||||
log.debug(
|
||||
`Updating player ${player.playerId} history`,
|
||||
"AccSaberService",
|
||||
"AccSaberService"
|
||||
);
|
||||
|
||||
const accSaberDate = toAccSaberMidnight(new Date());
|
||||
@ -441,9 +441,9 @@ export default () => {
|
||||
`Refresh interval for player ${
|
||||
player.playerId
|
||||
} history not yet expired, skipping. Next refresh on ${formatDate(
|
||||
addToDate(REFRESH_INTERVAL, lastUpdated),
|
||||
addToDate(REFRESH_INTERVAL, lastUpdated)
|
||||
)}`,
|
||||
"AccSaberService",
|
||||
"AccSaberService"
|
||||
);
|
||||
|
||||
return;
|
||||
@ -452,7 +452,7 @@ export default () => {
|
||||
const categories = (await getCategories())?.map((c) => c.name) ?? null;
|
||||
if (!categories) {
|
||||
log.trace(
|
||||
`No categories found, skip updating player ${player.playerId} history.`,
|
||||
`No categories found, skip updating player ${player.playerId} history.`
|
||||
);
|
||||
return;
|
||||
}
|
||||
@ -460,7 +460,7 @@ export default () => {
|
||||
let accStats = {};
|
||||
for (const category of categories) {
|
||||
const playerAccInfo = ((await getRanking(category)) ?? []).find(
|
||||
(p) => p.playerId === player.playerId,
|
||||
(p) => p.playerId === player.playerId
|
||||
);
|
||||
if (!playerAccInfo) continue;
|
||||
|
||||
@ -492,7 +492,7 @@ export default () => {
|
||||
} else {
|
||||
log.trace(
|
||||
`No Acc Saber data for player ${player.playerId}, skipping history updating.`,
|
||||
"AccSaberService",
|
||||
"AccSaberService"
|
||||
);
|
||||
|
||||
return;
|
||||
@ -503,7 +503,7 @@ export default () => {
|
||||
log.debug(
|
||||
`Player ${player.playerId} history updating error.`,
|
||||
"AccSaberService",
|
||||
e,
|
||||
e
|
||||
);
|
||||
}
|
||||
};
|
||||
@ -512,13 +512,13 @@ export default () => {
|
||||
category = "overall",
|
||||
forceUpdate = false,
|
||||
priority = queues.PRIORITY.BG_NORMAL,
|
||||
throwErrors = false,
|
||||
throwErrors = false
|
||||
) => {
|
||||
log.debug(
|
||||
`Starting AccSaber ${category} ranking refreshing${
|
||||
forceUpdate ? " (forced)" : ""
|
||||
}...`,
|
||||
"AccSaberService",
|
||||
"AccSaberService"
|
||||
);
|
||||
|
||||
try {
|
||||
@ -535,7 +535,7 @@ export default () => {
|
||||
|
||||
log.trace(
|
||||
`Fetching current ${category} ranking from AccSaber...`,
|
||||
"AccSaberService",
|
||||
"AccSaberService"
|
||||
);
|
||||
|
||||
const ranking = await accSaberRankingApiClient.getProcessed({
|
||||
@ -545,7 +545,7 @@ export default () => {
|
||||
if (!ranking || !ranking.length) {
|
||||
log.warn(
|
||||
`AccSaber returned empty ${category} ranking`,
|
||||
"AccSaberService",
|
||||
"AccSaberService"
|
||||
);
|
||||
|
||||
return null;
|
||||
@ -554,7 +554,7 @@ export default () => {
|
||||
log.trace(
|
||||
`${capitalize(category)} ranking fetched`,
|
||||
"AccSaberService",
|
||||
ranking,
|
||||
ranking
|
||||
);
|
||||
|
||||
log.trace(`Updating ${category} ranking...`, "AccSaberService");
|
||||
@ -570,7 +570,7 @@ export default () => {
|
||||
|
||||
log.trace(
|
||||
`Remove old players from DB for category ${category}`,
|
||||
"AccSaberService",
|
||||
"AccSaberService"
|
||||
);
|
||||
|
||||
while (cursor) {
|
||||
@ -589,14 +589,14 @@ export default () => {
|
||||
log.trace(`Updating players in DB...`, "AccSaberService");
|
||||
|
||||
await Promise.all(
|
||||
ranking.map(async (p) => accSaberPlayersStore.put(p)),
|
||||
ranking.map(async (p) => accSaberPlayersStore.put(p))
|
||||
);
|
||||
|
||||
log.trace(`Players updated`, "AccSaberService");
|
||||
|
||||
log.trace(
|
||||
`Updating players last update date in DB...`,
|
||||
"AccSaberService",
|
||||
"AccSaberService"
|
||||
);
|
||||
|
||||
await tx
|
||||
@ -604,7 +604,7 @@ export default () => {
|
||||
.put(new Date(), getLastUpdatedKey(rankingType));
|
||||
|
||||
log.debug(`Players last update date updated`, "AccSaberService");
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
accSaberPlayersRepository().addToCache(ranking);
|
||||
@ -612,7 +612,7 @@ export default () => {
|
||||
|
||||
log.debug(
|
||||
`${capitalize(category)} ranking refreshing completed`,
|
||||
"AccSaberService",
|
||||
"AccSaberService"
|
||||
);
|
||||
|
||||
return ranking.sort((a, b) => a.rank - b.rank);
|
||||
@ -622,7 +622,7 @@ export default () => {
|
||||
log.debug(
|
||||
` ${capitalize(category)} ranking refreshing error`,
|
||||
"AccSaberService",
|
||||
e,
|
||||
e
|
||||
);
|
||||
|
||||
return null;
|
||||
@ -633,13 +633,13 @@ export default () => {
|
||||
category = "overall",
|
||||
forceUpdate = false,
|
||||
priority = queues.PRIORITY.BG_NORMAL,
|
||||
throwErrors = false,
|
||||
throwErrors = false
|
||||
) => {
|
||||
log.trace(
|
||||
`Starting AccSaber all data refreshing${
|
||||
forceUpdate ? " (forced)" : ""
|
||||
}...`,
|
||||
"AccSaberService",
|
||||
"AccSaberService"
|
||||
);
|
||||
|
||||
try {
|
||||
@ -650,7 +650,7 @@ export default () => {
|
||||
const allRankings = await Promise.all(
|
||||
dbCategories.all
|
||||
.map((c) => c.name)
|
||||
.map(async (category) => refreshRanking(category)),
|
||||
.map(async (category) => refreshRanking(category))
|
||||
);
|
||||
|
||||
log.debug(`All data refreshing completed.`, "AccSaberService");
|
||||
@ -665,8 +665,8 @@ export default () => {
|
||||
|
||||
Promise.all(
|
||||
(await playerService.getAllActive()).map(async (player) =>
|
||||
updatePlayerHistory(player),
|
||||
),
|
||||
updatePlayerHistory(player)
|
||||
)
|
||||
).then((_) => _);
|
||||
|
||||
return dbCategories.all.map((c) => ({
|
||||
|
@ -52,7 +52,7 @@ export default () => {
|
||||
|
||||
suspension.activeTo = addToDate(
|
||||
Math.pow(2, suspension.count) * HOUR,
|
||||
suspension.activeTo,
|
||||
suspension.activeTo
|
||||
);
|
||||
suspension.count++;
|
||||
|
||||
@ -97,7 +97,7 @@ export default () => {
|
||||
|
||||
si.diffs.forEach((d) => {
|
||||
const newNotesCnt = INVALID_NOTES_COUNT_FIXES[hash].find(
|
||||
(f) => f.type === d?.characteristic && f.diff === d?.difficulty,
|
||||
(f) => f.type === d?.characteristic && f.diff === d?.difficulty
|
||||
);
|
||||
if (!newNotesCnt) return;
|
||||
|
||||
@ -114,7 +114,7 @@ export default () => {
|
||||
forceUpdate = false,
|
||||
cacheOnly = false,
|
||||
errSongId = "",
|
||||
hash = null,
|
||||
hash = null
|
||||
) => {
|
||||
if (!forceUpdate && songInfo) return fixInvalidNotesCount(hash, songInfo);
|
||||
|
||||
@ -158,7 +158,7 @@ export default () => {
|
||||
forceUpdate = false,
|
||||
cacheOnly = false,
|
||||
signal = null,
|
||||
priority = PRIORITY.FG_LOW,
|
||||
priority = PRIORITY.FG_LOW
|
||||
) => {
|
||||
hash = hash.toLowerCase();
|
||||
|
||||
@ -170,7 +170,7 @@ export default () => {
|
||||
forceUpdate,
|
||||
cacheOnly,
|
||||
hash,
|
||||
hash,
|
||||
hash
|
||||
);
|
||||
};
|
||||
|
||||
@ -179,13 +179,13 @@ export default () => {
|
||||
forceUpdate = false,
|
||||
cacheOnly = false,
|
||||
signal = null,
|
||||
priority = PRIORITY.FG_LOW,
|
||||
priority = PRIORITY.FG_LOW
|
||||
) => {
|
||||
key = key.toLowerCase();
|
||||
|
||||
const songInfo = await songsBeatMapsRepository().getFromIndex(
|
||||
"songs-beatmaps-key",
|
||||
key,
|
||||
key
|
||||
);
|
||||
|
||||
return fetchSong(
|
||||
@ -193,7 +193,7 @@ export default () => {
|
||||
() => keyApiClient.getProcessed({ key, signal, priority }),
|
||||
forceUpdate,
|
||||
cacheOnly,
|
||||
key,
|
||||
key
|
||||
);
|
||||
};
|
||||
|
||||
@ -254,7 +254,7 @@ export default () => {
|
||||
},
|
||||
stars: null,
|
||||
};
|
||||
}),
|
||||
})
|
||||
)
|
||||
.filter((diff) => diff);
|
||||
}, []);
|
||||
|
@ -40,7 +40,7 @@ export default () => {
|
||||
|
||||
const getPlayerScores = async (playerId) =>
|
||||
resolvePromiseOrWaitForPending(`getPlayerScores/${playerId}`, () =>
|
||||
beatSaviorRepository().getAllFromIndex("beat-savior-playerId", playerId),
|
||||
beatSaviorRepository().getAllFromIndex("beat-savior-playerId", playerId)
|
||||
);
|
||||
|
||||
const getPlayerScoresWithScoreSaber = async (playerId) => {
|
||||
@ -50,8 +50,8 @@ export default () => {
|
||||
scoresService.getPlayerScoresAsObject(
|
||||
playerId,
|
||||
(score) => score?.leaderboard?.song?.hash?.toLowerCase() ?? null,
|
||||
true,
|
||||
),
|
||||
true
|
||||
)
|
||||
),
|
||||
]);
|
||||
|
||||
@ -61,7 +61,7 @@ export default () => {
|
||||
|
||||
const ssScore =
|
||||
playerScores[bsData.hash.toLowerCase()].find((ssScore) =>
|
||||
isScoreMatchingBsData(ssScore, bsData, true),
|
||||
isScoreMatchingBsData(ssScore, bsData, true)
|
||||
) ?? null;
|
||||
|
||||
return {
|
||||
@ -101,7 +101,7 @@ export default () => {
|
||||
};
|
||||
|
||||
const getScoresHistogramDefinition = (
|
||||
serviceParams = { sort: "recent", order: "desc" },
|
||||
serviceParams = { sort: "recent", order: "desc" }
|
||||
) => {
|
||||
const sort = serviceParams?.sort ?? "recent";
|
||||
const order = serviceParams?.order ?? "desc";
|
||||
@ -188,7 +188,7 @@ export default () => {
|
||||
|
||||
const getPlayerScoresPage = async (
|
||||
playerId,
|
||||
serviceParams = { sort: "recent", order: "desc", page: 1 },
|
||||
serviceParams = { sort: "recent", order: "desc", page: 1 }
|
||||
) => {
|
||||
let page = serviceParams?.page ?? 1;
|
||||
if (page < 1) page = 1;
|
||||
@ -250,14 +250,14 @@ export default () => {
|
||||
const updateData = async (playerId, data) => {
|
||||
log.debug(
|
||||
`Updating Beat Savior data for player "${playerId}"...`,
|
||||
"BeatSaviorService",
|
||||
"BeatSaviorService"
|
||||
);
|
||||
|
||||
await Promise.all(data.map(async (d) => beatSaviorRepository().set(d)));
|
||||
|
||||
log.debug(
|
||||
`Update player "${playerId}" Beat Savior last refresh date...`,
|
||||
"BeatSaviorService",
|
||||
"BeatSaviorService"
|
||||
);
|
||||
|
||||
await beatSaviorPlayersRepository().set({
|
||||
@ -267,7 +267,7 @@ export default () => {
|
||||
|
||||
log.debug(
|
||||
`Beat Savior data for player "${playerId}" updated.`,
|
||||
"BeatSaviorService",
|
||||
"BeatSaviorService"
|
||||
);
|
||||
|
||||
return data;
|
||||
@ -277,7 +277,7 @@ export default () => {
|
||||
try {
|
||||
log.debug(
|
||||
`Fetching Beat Savior data for player "${playerId}"...`,
|
||||
"BeatSaviorService",
|
||||
"BeatSaviorService"
|
||||
);
|
||||
|
||||
const data = await beatSaviorApiClient.getProcessed({
|
||||
@ -287,7 +287,7 @@ export default () => {
|
||||
if (!data) {
|
||||
log.debug(
|
||||
`No Beat Savior data for player "${playerId}"`,
|
||||
"BeatSaviorService",
|
||||
"BeatSaviorService"
|
||||
);
|
||||
|
||||
return null;
|
||||
@ -298,7 +298,7 @@ export default () => {
|
||||
log.trace(
|
||||
`Beat Savior data for player "${playerId}" fetched`,
|
||||
"BeatSaviorService",
|
||||
data,
|
||||
data
|
||||
);
|
||||
|
||||
return updateData(playerId, data);
|
||||
@ -313,13 +313,13 @@ export default () => {
|
||||
playerId,
|
||||
force = false,
|
||||
priority = PRIORITY.BG_NORMAL,
|
||||
throwErrors = false,
|
||||
throwErrors = false
|
||||
) => {
|
||||
log.trace(
|
||||
`Starting refreshing BeatSavior for player "${playerId}" ${
|
||||
force ? " (forced)" : ""
|
||||
}...`,
|
||||
"BeatSaviorService",
|
||||
"BeatSaviorService"
|
||||
);
|
||||
|
||||
try {
|
||||
@ -339,9 +339,9 @@ export default () => {
|
||||
if (!force && bsPlayerInfo && nextUpdate > new Date()) {
|
||||
log.debug(
|
||||
`Beat Savior data is still fresh, skipping. Next refresh on ${formatDate(
|
||||
nextUpdate,
|
||||
nextUpdate
|
||||
)}`,
|
||||
"BeatSaviorService",
|
||||
"BeatSaviorService"
|
||||
);
|
||||
|
||||
return null;
|
||||
@ -349,7 +349,7 @@ export default () => {
|
||||
if (player) {
|
||||
log.trace(
|
||||
`Player "${playerId}" is a cached one, checking recent play date`,
|
||||
"BeatSaviorService",
|
||||
"BeatSaviorService"
|
||||
);
|
||||
|
||||
if (
|
||||
@ -358,7 +358,7 @@ export default () => {
|
||||
) {
|
||||
log.debug(
|
||||
`Beat Savior data for player "${playerId}" was refreshed after recent play, skipping`,
|
||||
"BeatSaviorService",
|
||||
"BeatSaviorService"
|
||||
);
|
||||
|
||||
return null;
|
||||
@ -367,7 +367,7 @@ export default () => {
|
||||
}
|
||||
|
||||
return resolvePromiseOrWaitForPending(`refresh/${playerId}`, () =>
|
||||
fetchPlayer(playerId, priority),
|
||||
fetchPlayer(playerId, priority)
|
||||
);
|
||||
} catch (e) {
|
||||
if (throwErrors) throw e;
|
||||
@ -377,7 +377,7 @@ export default () => {
|
||||
e.toString ? `: ${e.toString()}` : ""
|
||||
}`,
|
||||
"BeatSaviorService",
|
||||
e,
|
||||
e
|
||||
);
|
||||
|
||||
return null;
|
||||
@ -387,13 +387,13 @@ export default () => {
|
||||
const refreshAll = async (
|
||||
force = false,
|
||||
priority = PRIORITY.BG_NORMAL,
|
||||
throwErrors = false,
|
||||
throwErrors = false
|
||||
) => {
|
||||
log.trace(
|
||||
`Starting refreshing Beat Savior data for all players${
|
||||
force ? " (forced)" : ""
|
||||
}...`,
|
||||
"BeatSaviorService",
|
||||
"BeatSaviorService"
|
||||
);
|
||||
|
||||
const allPlayers = await playerService.getAll();
|
||||
@ -409,15 +409,15 @@ export default () => {
|
||||
player.playerId,
|
||||
force,
|
||||
priority,
|
||||
throwErrors,
|
||||
throwErrors
|
||||
),
|
||||
})),
|
||||
}))
|
||||
);
|
||||
|
||||
log.trace(
|
||||
`Beat Savior data for all players refreshed.`,
|
||||
"BeatSaviorService",
|
||||
allRefreshed,
|
||||
allRefreshed
|
||||
);
|
||||
|
||||
return allRefreshed;
|
||||
@ -430,7 +430,7 @@ export default () => {
|
||||
if (!playerBsData || !playerBsData.length) return null;
|
||||
|
||||
const bsData = playerBsData.find((bsData) =>
|
||||
isScoreMatchingBsData(score, bsData, true),
|
||||
isScoreMatchingBsData(score, bsData, true)
|
||||
);
|
||||
|
||||
return bsData ? bsData : null;
|
||||
@ -439,7 +439,7 @@ export default () => {
|
||||
const isDataForPlayerAvailable = async (playerId) =>
|
||||
(await beatSaviorRepository().getFromIndex(
|
||||
"beat-savior-playerId",
|
||||
playerId,
|
||||
playerId
|
||||
)) !== undefined;
|
||||
|
||||
const destroyService = () => {
|
||||
|
@ -33,7 +33,7 @@ export default () => {
|
||||
page = 1,
|
||||
priority = PRIORITY.FG_LOW,
|
||||
signal = null,
|
||||
force = false,
|
||||
force = false
|
||||
) =>
|
||||
resolvePromiseOrWaitForPending(
|
||||
`pageClient/leaderboard/${leaderboardId}/${page}`,
|
||||
@ -44,7 +44,7 @@ export default () => {
|
||||
signal,
|
||||
priority,
|
||||
cacheTtl: MINUTE,
|
||||
}),
|
||||
})
|
||||
);
|
||||
|
||||
const fetchAccSaberPage = async (
|
||||
@ -52,7 +52,7 @@ export default () => {
|
||||
page = 1,
|
||||
priority = PRIORITY.FG_LOW,
|
||||
signal = null,
|
||||
force = false,
|
||||
force = false
|
||||
) => {
|
||||
if (page < 1) page = 1;
|
||||
|
||||
@ -65,7 +65,7 @@ export default () => {
|
||||
signal,
|
||||
priority,
|
||||
cacheTtl: ACCSABER_LEADERBOARD_NETWORK_TTL,
|
||||
}),
|
||||
})
|
||||
);
|
||||
|
||||
if (!data || !data.scores) return data;
|
||||
@ -77,7 +77,7 @@ export default () => {
|
||||
...data,
|
||||
scores: data.scores.slice(
|
||||
startIdx,
|
||||
startIdx + ACCSABER_LEADERBOARD_SCORES_PER_PAGE,
|
||||
startIdx + ACCSABER_LEADERBOARD_SCORES_PER_PAGE
|
||||
),
|
||||
};
|
||||
};
|
||||
@ -85,7 +85,7 @@ export default () => {
|
||||
const getFriendsLeaderboard = async (
|
||||
leaderboardId,
|
||||
priority = PRIORITY.FG_LOW,
|
||||
signal = null,
|
||||
signal = null
|
||||
) => {
|
||||
const leaderboard = await resolvePromiseOrWaitForPending(
|
||||
`pageClient/leaderboard/${leaderboardId}/1`,
|
||||
@ -96,7 +96,7 @@ export default () => {
|
||||
signal,
|
||||
priority,
|
||||
cacheTtl: MINUTE,
|
||||
}),
|
||||
})
|
||||
);
|
||||
|
||||
const friends = convertArrayToObjectByKey(await friendsPromise, "playerId");
|
||||
|
@ -51,7 +51,7 @@ export default () => {
|
||||
const getFriends = async () =>
|
||||
(await getAll())
|
||||
.filter(
|
||||
(player) => player && player.playerId && !isPlayerMain(player.playerId),
|
||||
(player) => player && player.playerId && !isPlayerMain(player.playerId)
|
||||
)
|
||||
.map((p) => p.playerId);
|
||||
|
||||
@ -64,7 +64,7 @@ export default () => {
|
||||
player &&
|
||||
player.playerInfo &&
|
||||
!player.playerInfo.inactive &&
|
||||
!player.playerInfo.banned,
|
||||
!player.playerInfo.banned
|
||||
);
|
||||
};
|
||||
|
||||
@ -107,13 +107,13 @@ export default () => {
|
||||
const updatePlayer = async (
|
||||
player,
|
||||
waitForSaving = true,
|
||||
forceAdd = false,
|
||||
forceAdd = false
|
||||
) => {
|
||||
if (!player || !player.playerId) {
|
||||
log.warn(
|
||||
`Can not update player, empty playerId`,
|
||||
"PlayerService",
|
||||
player,
|
||||
player
|
||||
);
|
||||
}
|
||||
|
||||
@ -135,8 +135,8 @@ export default () => {
|
||||
resolvePromiseOrWaitForPending(`playerHistory/${playerId}`, () =>
|
||||
playersHistoryRepository().getAllFromIndex(
|
||||
"players-history-playerId",
|
||||
playerId,
|
||||
),
|
||||
playerId
|
||||
)
|
||||
);
|
||||
|
||||
const getPlayerGain = (playerHistory, daysAgo = 1, maxDaysAgo = 7) =>
|
||||
@ -145,7 +145,7 @@ export default () => {
|
||||
toSsMidnight,
|
||||
"ssDate",
|
||||
daysAgo,
|
||||
maxDaysAgo,
|
||||
maxDaysAgo
|
||||
);
|
||||
|
||||
const updatePlayerHistory = async (player) => {
|
||||
@ -196,7 +196,7 @@ export default () => {
|
||||
if (badges?.length)
|
||||
accStats.accBadges = badges.reduce(
|
||||
(cum, b) => ({ ...cum, [b.label]: b.value }),
|
||||
{},
|
||||
{}
|
||||
);
|
||||
}
|
||||
|
||||
@ -241,7 +241,7 @@ export default () => {
|
||||
const updatePlayerRecentPlay = async (
|
||||
playerId,
|
||||
recentPlay,
|
||||
recentPlayLastUpdated = new Date(),
|
||||
recentPlayLastUpdated = new Date()
|
||||
) => {
|
||||
let player;
|
||||
|
||||
@ -277,19 +277,19 @@ export default () => {
|
||||
try {
|
||||
const player = await resolvePromiseOrWaitForPending(
|
||||
`pageClient/${playerId}`,
|
||||
() => playerPageClient.getProcessed({ playerId }),
|
||||
() => playerPageClient.getProcessed({ playerId })
|
||||
);
|
||||
const recentPlay = opt(player, "playerInfo.recentPlay");
|
||||
const recentPlayLastUpdated = opt(
|
||||
player,
|
||||
"playerInfo.recentPlayLastUpdated",
|
||||
"playerInfo.recentPlayLastUpdated"
|
||||
);
|
||||
if (!recentPlay || !recentPlayLastUpdated) return null;
|
||||
|
||||
return updatePlayerRecentPlay(
|
||||
playerId,
|
||||
recentPlay,
|
||||
recentPlayLastUpdated,
|
||||
recentPlayLastUpdated
|
||||
);
|
||||
} catch (err) {
|
||||
// swallow error
|
||||
@ -304,7 +304,7 @@ export default () => {
|
||||
const fetchPlayer = async (
|
||||
playerId,
|
||||
priority = PRIORITY.FG_LOW,
|
||||
{ fullResponse = false, ...options } = {},
|
||||
{ fullResponse = false, ...options } = {}
|
||||
) =>
|
||||
resolvePromiseOrWaitForPending(
|
||||
`apiClient/${playerId}/${fullResponse}`,
|
||||
@ -314,13 +314,13 @@ export default () => {
|
||||
playerId,
|
||||
priority,
|
||||
fullResponse,
|
||||
}),
|
||||
})
|
||||
);
|
||||
|
||||
const findPlayer = async (
|
||||
query,
|
||||
priority = PRIORITY.FG_LOW,
|
||||
{ fullResponse = false, ...options } = {},
|
||||
{ fullResponse = false, ...options } = {}
|
||||
) =>
|
||||
resolvePromiseOrWaitForPending(
|
||||
`apiClient/find/${query}/${fullResponse}`,
|
||||
@ -330,7 +330,7 @@ export default () => {
|
||||
query,
|
||||
priority,
|
||||
fullResponse,
|
||||
}),
|
||||
})
|
||||
);
|
||||
|
||||
const fetchPlayerOrGetFromCache = async (
|
||||
@ -338,7 +338,7 @@ export default () => {
|
||||
refreshInterval = MINUTE,
|
||||
priority = PRIORITY.FG_LOW,
|
||||
signal = null,
|
||||
force = false,
|
||||
force = false
|
||||
) => {
|
||||
const player = await getPlayer(playerId);
|
||||
|
||||
@ -358,7 +358,7 @@ export default () => {
|
||||
...getDataFromResponse(fetchedPlayerResponse),
|
||||
profileLastUpdated: new Date(),
|
||||
},
|
||||
false,
|
||||
false
|
||||
).then((player) => {
|
||||
fetchPlayerAndUpdateRecentPlay(player.playerId);
|
||||
|
||||
@ -376,17 +376,17 @@ export default () => {
|
||||
force = false,
|
||||
priority = PRIORITY.BG_NORMAL,
|
||||
throwErrors = false,
|
||||
addIfNotExists = false,
|
||||
addIfNotExists = false
|
||||
) => {
|
||||
log.trace(
|
||||
`Starting refreshing player "${playerId}" ${force ? " (forced)" : ""}...`,
|
||||
"PlayerService",
|
||||
"PlayerService"
|
||||
);
|
||||
|
||||
if (!playerId) {
|
||||
log.warn(
|
||||
`Can not refresh player if an empty playerId is given`,
|
||||
"PlayerService",
|
||||
"PlayerService"
|
||||
);
|
||||
|
||||
return null;
|
||||
@ -407,9 +407,9 @@ export default () => {
|
||||
if (profileFreshnessDate > new Date()) {
|
||||
log.debug(
|
||||
`Profile is still fresh, skipping. Next refresh on ${formatDate(
|
||||
profileFreshnessDate,
|
||||
profileFreshnessDate
|
||||
)}`,
|
||||
"PlayerService",
|
||||
"PlayerService"
|
||||
);
|
||||
|
||||
return player;
|
||||
@ -418,7 +418,7 @@ export default () => {
|
||||
|
||||
log.trace(
|
||||
`Fetching player ${playerId} from ScoreSaber...`,
|
||||
"PlayerService",
|
||||
"PlayerService"
|
||||
);
|
||||
|
||||
const fetchedPlayer = await fetchPlayer(playerId, priority);
|
||||
@ -432,7 +432,7 @@ export default () => {
|
||||
) {
|
||||
log.warn(
|
||||
`ScoreSaber returned empty info for player ${playerId}`,
|
||||
"PlayerService",
|
||||
"PlayerService"
|
||||
);
|
||||
|
||||
return null;
|
||||
@ -443,7 +443,7 @@ export default () => {
|
||||
player = await updatePlayer(
|
||||
{ ...fetchedPlayer, profileLastUpdated: new Date() },
|
||||
true,
|
||||
addIfNotExists,
|
||||
addIfNotExists
|
||||
);
|
||||
|
||||
updatePlayerHistory(player).then((_) => _);
|
||||
@ -457,7 +457,7 @@ export default () => {
|
||||
log.debug(
|
||||
`Player refreshing error${e.toString ? `: ${e.toString()}` : ""}`,
|
||||
"PlayerService",
|
||||
e,
|
||||
e
|
||||
);
|
||||
|
||||
return null;
|
||||
@ -467,11 +467,11 @@ export default () => {
|
||||
const refreshAll = async (
|
||||
force = false,
|
||||
priority = PRIORITY.BG_NORMAL,
|
||||
throwErrors = false,
|
||||
throwErrors = false
|
||||
) => {
|
||||
log.trace(
|
||||
`Starting refreshing all players${force ? " (forced)" : ""}...`,
|
||||
"PlayerService",
|
||||
"PlayerService"
|
||||
);
|
||||
|
||||
const allPlayers = await getAll();
|
||||
@ -482,8 +482,8 @@ export default () => {
|
||||
|
||||
const allRefreshed = await Promise.all(
|
||||
allPlayers.map((player) =>
|
||||
refresh(player.playerId, force, priority, throwErrors),
|
||||
),
|
||||
refresh(player.playerId, force, priority, throwErrors)
|
||||
)
|
||||
);
|
||||
|
||||
log.trace(`All players refreshed.`, "PlayerService", allRefreshed);
|
||||
|
@ -18,7 +18,7 @@ export default () => {
|
||||
scores
|
||||
.filter((s) => s.pp > 0)
|
||||
.map((s) => s.pp)
|
||||
.sort((a, b) => b - a),
|
||||
.sort((a, b) => b - a)
|
||||
)
|
||||
: null;
|
||||
|
||||
@ -26,10 +26,10 @@ export default () => {
|
||||
getTotalPp(
|
||||
Object.values({
|
||||
...(await resolvePromiseOrWaitForPending(`scores/${playerId}`, () =>
|
||||
scoresService.getPlayerScoresAsObject(playerId),
|
||||
scoresService.getPlayerScoresAsObject(playerId)
|
||||
)),
|
||||
...modifiedScores,
|
||||
}),
|
||||
})
|
||||
);
|
||||
|
||||
async function getWhatIfScore(playerId, leaderboardId, pp = 0) {
|
||||
|
@ -35,11 +35,11 @@ export default () => {
|
||||
const refreshRankeds = async (
|
||||
forceUpdate = false,
|
||||
priority = queues.PRIORITY.BG_NORMAL,
|
||||
throwErrors = false,
|
||||
throwErrors = false
|
||||
) => {
|
||||
log.trace(
|
||||
`Starting rankeds refreshing${forceUpdate ? " (forced)" : ""}...`,
|
||||
"RankedsService",
|
||||
"RankedsService"
|
||||
);
|
||||
|
||||
try {
|
||||
@ -50,9 +50,9 @@ export default () => {
|
||||
if (lastUpdated && lastUpdated > new Date() - REFRESH_INTERVAL) {
|
||||
log.debug(
|
||||
`Refresh interval not yet expired, skipping. Next refresh on ${formatDate(
|
||||
addToDate(REFRESH_INTERVAL, lastUpdated),
|
||||
addToDate(REFRESH_INTERVAL, lastUpdated)
|
||||
)}`,
|
||||
"RankedsService",
|
||||
"RankedsService"
|
||||
);
|
||||
|
||||
return null;
|
||||
@ -61,7 +61,7 @@ export default () => {
|
||||
|
||||
log.trace(
|
||||
`Fetching current rankeds from ScoreSaber...`,
|
||||
"RankedsService",
|
||||
"RankedsService"
|
||||
);
|
||||
fetchedRankedSongs = await rankedsPageClient.getProcessed({ priority });
|
||||
if (!fetchedRankedSongs || !fetchedRankedSongs.length) {
|
||||
@ -84,13 +84,13 @@ export default () => {
|
||||
|
||||
return { ...s, firstSeen, oldStars: null };
|
||||
}),
|
||||
"leaderboardId",
|
||||
"leaderboardId"
|
||||
);
|
||||
|
||||
// find differences between old and new ranked songs
|
||||
const newRankeds = arrayDifference(
|
||||
Object.keys(fetchedRankedSongs),
|
||||
Object.keys(oldRankedSongs),
|
||||
Object.keys(oldRankedSongs)
|
||||
).map((leaderboardId) => ({
|
||||
leaderboardId: parseInt(leaderboardId, 10),
|
||||
oldStars: null,
|
||||
@ -110,20 +110,20 @@ export default () => {
|
||||
s.stars !==
|
||||
(fetchedRankedSongs[s.leaderboardId]
|
||||
? opt(fetchedRankedSongs[s.leaderboardId], "stars", null)
|
||||
: null),
|
||||
: null)
|
||||
)
|
||||
.map((s) => ({
|
||||
leaderboardId: s.leaderboardId,
|
||||
oldStars: s.stars,
|
||||
stars: opt(fetchedRankedSongs[s.leaderboardId], "stars", null),
|
||||
timestamp: Date.now(),
|
||||
})),
|
||||
}))
|
||||
);
|
||||
|
||||
if (newRankeds && changed && changed.length - newRankeds.length > 0)
|
||||
log.debug(
|
||||
`${changed.length - newRankeds.length} changed ranked(s) found`,
|
||||
"RankedsService",
|
||||
"RankedsService"
|
||||
);
|
||||
|
||||
const changedLeaderboards = changed
|
||||
@ -150,16 +150,16 @@ export default () => {
|
||||
async (tx) => {
|
||||
await Promise.all(
|
||||
changedLeaderboards.map(async (ranked) =>
|
||||
rankedsRepository().set(ranked, undefined, tx),
|
||||
),
|
||||
rankedsRepository().set(ranked, undefined, tx)
|
||||
)
|
||||
);
|
||||
await Promise.all(
|
||||
changed.map(async (rc) =>
|
||||
rankedsChangesRepository().set(rc, undefined, tx),
|
||||
),
|
||||
rankedsChangesRepository().set(rc, undefined, tx)
|
||||
)
|
||||
);
|
||||
await setLastUpdated(new Date());
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
log.trace("Rankeds saved", "RankedsService");
|
||||
|
@ -15,17 +15,17 @@ export default () => {
|
||||
const fetchGlobal = async (
|
||||
page = 1,
|
||||
priority = PRIORITY.FG_LOW,
|
||||
signal = null,
|
||||
signal = null
|
||||
) =>
|
||||
resolvePromiseOrWaitForPending(`apiClient/ranking/global/${page}`, () =>
|
||||
playersGlobalRankingApiClient.getProcessed({ page, signal, priority }),
|
||||
playersGlobalRankingApiClient.getProcessed({ page, signal, priority })
|
||||
);
|
||||
|
||||
const fetchCountry = async (
|
||||
country,
|
||||
page = 1,
|
||||
priority = PRIORITY.FG_LOW,
|
||||
signal = null,
|
||||
signal = null
|
||||
) =>
|
||||
resolvePromiseOrWaitForPending(
|
||||
`pageClient/ranking/${country}/${page}`,
|
||||
@ -35,17 +35,17 @@ export default () => {
|
||||
page,
|
||||
signal,
|
||||
priority,
|
||||
}),
|
||||
})
|
||||
);
|
||||
|
||||
const fetchGlobalPages = async (priority = PRIORITY.FG_LOW, signal = null) =>
|
||||
resolvePromiseOrWaitForPending(`apiClient/rankingGlobalPages`, () =>
|
||||
playersGlobalRankingPagesApiClient.getProcessed({ signal, priority }),
|
||||
playersGlobalRankingPagesApiClient.getProcessed({ signal, priority })
|
||||
);
|
||||
|
||||
const fetchGlobalCount = async (
|
||||
priority = PRIORITY.FG_LOW,
|
||||
signal = null,
|
||||
signal = null
|
||||
) => {
|
||||
const pages = await fetchGlobalPages(priority, signal);
|
||||
if (!pages || !Number.isFinite(pages)) return 0;
|
||||
@ -73,8 +73,8 @@ export default () => {
|
||||
const ranking = (
|
||||
await Promise.all(
|
||||
pages.map(async (page) =>
|
||||
country ? fetchCountry(country, page) : fetchGlobal(page),
|
||||
),
|
||||
country ? fetchCountry(country, page) : fetchGlobal(page)
|
||||
)
|
||||
)
|
||||
)
|
||||
.reduce((cum, arr) => cum.concat(arr), [])
|
||||
|
@ -118,7 +118,7 @@ export default () => {
|
||||
const getPlayerScoresAsObject = async (
|
||||
playerId,
|
||||
idFunc = (score) => opt(score, "leaderboard.leaderboardId"),
|
||||
asArray = false,
|
||||
asArray = false
|
||||
) => convertScoresToObject(await getPlayerScores(playerId), idFunc, asArray);
|
||||
const getPlayerSongScore = async (playerId, leaderboardId) =>
|
||||
scoresRepository().get(playerId + "_" + leaderboardId);
|
||||
@ -137,7 +137,7 @@ export default () => {
|
||||
scores.reduce((allScores, scorePage) => [...allScores, ...scorePage], []);
|
||||
const isAnyScoreOlderThan = (scores, olderThan) =>
|
||||
scores.some(
|
||||
(s) => s.score && s.score.timeSet && s.score.timeSet <= olderThan,
|
||||
(s) => s.score && s.score.timeSet && s.score.timeSet <= olderThan
|
||||
);
|
||||
const createFetchUntilLastUpdated = (olderThan) => (scores) =>
|
||||
isAnyScoreOlderThan(scores, olderThan);
|
||||
@ -145,7 +145,7 @@ export default () => {
|
||||
const convertScoresToObject = (
|
||||
scores,
|
||||
idFunc = (score) => opt(score, "leaderboard.leaderboardId"),
|
||||
asArray = false,
|
||||
asArray = false
|
||||
) =>
|
||||
scores.reduce((scoresObj, score) => {
|
||||
const _id = idFunc(score);
|
||||
@ -176,11 +176,11 @@ export default () => {
|
||||
priority = PRIORITY.BG_NORMAL,
|
||||
signal = null,
|
||||
untilFunc = null,
|
||||
dontReduce = false,
|
||||
dontReduce = false
|
||||
) => {
|
||||
log.debug(
|
||||
`Fetching scores of player "${playerId}" starting from page #${startPage}`,
|
||||
"ScoresService",
|
||||
"ScoresService"
|
||||
);
|
||||
|
||||
let data = [];
|
||||
@ -212,7 +212,7 @@ export default () => {
|
||||
) {
|
||||
// push only relevant scores and return
|
||||
data.push(
|
||||
pageData.filter((score) => !untilFunc || !untilFunc([score])),
|
||||
pageData.filter((score) => !untilFunc || !untilFunc([score]))
|
||||
);
|
||||
|
||||
break;
|
||||
@ -238,11 +238,11 @@ export default () => {
|
||||
playerId,
|
||||
numOfPages,
|
||||
priority = PRIORITY.BG_NORMAL,
|
||||
signal = null,
|
||||
signal = null
|
||||
) => {
|
||||
log.debug(
|
||||
`Fetching all scores of player "${playerId}, number of pages: ${numOfPages}`,
|
||||
"ScoresService",
|
||||
"ScoresService"
|
||||
);
|
||||
|
||||
const pages = Array(numOfPages)
|
||||
@ -256,8 +256,8 @@ export default () => {
|
||||
page,
|
||||
signal,
|
||||
priority,
|
||||
}),
|
||||
),
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
if (!data || !data.length) return [];
|
||||
@ -271,7 +271,7 @@ export default () => {
|
||||
priority,
|
||||
signal,
|
||||
null,
|
||||
true,
|
||||
true
|
||||
)),
|
||||
];
|
||||
}
|
||||
@ -285,7 +285,7 @@ export default () => {
|
||||
opt(s, "score.timeSet") && s.score.timeSet > recentPlay
|
||||
? s.score.timeSet
|
||||
: recentPlay,
|
||||
defaultRecentPlay,
|
||||
defaultRecentPlay
|
||||
);
|
||||
|
||||
const addScoreIndexFields = (playerId, score) => {
|
||||
@ -310,12 +310,12 @@ export default () => {
|
||||
try {
|
||||
log.debug(
|
||||
"Rank and pp update queue, waiting for the scores to finish refreshing.",
|
||||
"ScoresService",
|
||||
"ScoresService"
|
||||
);
|
||||
await refreshingFinished();
|
||||
log.debug(
|
||||
"Rank and pp update queue, scores refreshed, start queue processing.",
|
||||
"ScoresService",
|
||||
"ScoresService"
|
||||
);
|
||||
|
||||
await db.runInTransaction(
|
||||
@ -373,14 +373,14 @@ export default () => {
|
||||
if (cursor) cursor = await cursor.continue();
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
log.debug("Rank and pp update queue processed.", "ScoresService");
|
||||
} catch (err) {
|
||||
log.debug(
|
||||
"Rank and pp update queue has NOT been processed.",
|
||||
"ScoresService",
|
||||
"ScoresService"
|
||||
);
|
||||
}
|
||||
};
|
||||
@ -391,12 +391,12 @@ export default () => {
|
||||
log.debug(
|
||||
"Queueing rank and pp update for bunch of scores",
|
||||
"ScoresService",
|
||||
scoresToUpdate,
|
||||
scoresToUpdate
|
||||
);
|
||||
|
||||
try {
|
||||
await Promise.all(
|
||||
scoresToUpdate.map(async (s) => scoresUpdateQueueRepository().set(s)),
|
||||
scoresToUpdate.map(async (s) => scoresUpdateQueueRepository().set(s))
|
||||
);
|
||||
} catch (err) {
|
||||
// swallow error
|
||||
@ -405,7 +405,7 @@ export default () => {
|
||||
log.debug(
|
||||
"Scores rank & pp queued for update.",
|
||||
"ScoresService",
|
||||
scoresToUpdate,
|
||||
scoresToUpdate
|
||||
);
|
||||
};
|
||||
|
||||
@ -414,7 +414,7 @@ export default () => {
|
||||
log.warn(
|
||||
`Can not refresh scores, empty playerId`,
|
||||
"ScoresService",
|
||||
player,
|
||||
player
|
||||
);
|
||||
|
||||
return null;
|
||||
@ -434,7 +434,7 @@ export default () => {
|
||||
const playerScores = await getPlayerScores(player.playerId);
|
||||
const currentScoresById = convertScoresById(
|
||||
player.playerId,
|
||||
playerScores,
|
||||
playerScores
|
||||
);
|
||||
|
||||
let mostRecentPlayFromScores = null;
|
||||
@ -455,7 +455,7 @@ export default () => {
|
||||
player.playerId,
|
||||
numOfPages,
|
||||
priority,
|
||||
abortController.signal,
|
||||
abortController.signal
|
||||
);
|
||||
else
|
||||
newScores = await fetchScoresUntil(
|
||||
@ -463,7 +463,7 @@ export default () => {
|
||||
1,
|
||||
priority,
|
||||
abortController.signal,
|
||||
createFetchUntilLastUpdated(startUpdatingDate),
|
||||
createFetchUntilLastUpdated(startUpdatingDate)
|
||||
);
|
||||
|
||||
if (!newScores || !newScores.length) {
|
||||
@ -568,7 +568,7 @@ export default () => {
|
||||
const getScoresFreshnessDate = (
|
||||
player,
|
||||
refreshInterval = null,
|
||||
key = "scoresLastUpdated",
|
||||
key = "scoresLastUpdated"
|
||||
) => {
|
||||
const lastUpdated = player && player[key] ? player[key] : null;
|
||||
if (!lastUpdated) return addToDate(-SECOND);
|
||||
@ -585,12 +585,12 @@ export default () => {
|
||||
const isScoreDateFresh = (
|
||||
player,
|
||||
refreshInterval = null,
|
||||
key = "scoresLastUpdated",
|
||||
key = "scoresLastUpdated"
|
||||
) => getScoresFreshnessDate(player, refreshInterval, key) > new Date();
|
||||
|
||||
const getPlayerScoresPage = async (
|
||||
playerId,
|
||||
serviceParams = { sort: "recent", order: "desc", page: 1 },
|
||||
serviceParams = { sort: "recent", order: "desc", page: 1 }
|
||||
) => {
|
||||
let page = serviceParams?.page ?? 1;
|
||||
if (page < 1) page = 1;
|
||||
@ -615,7 +615,7 @@ export default () => {
|
||||
};
|
||||
|
||||
const getScoresHistogramDefinition = (
|
||||
serviceParams = { sort: "recent", order: "desc" },
|
||||
serviceParams = { sort: "recent", order: "desc" }
|
||||
) => {
|
||||
const sort = serviceParams?.sort ?? "recent";
|
||||
const order = serviceParams?.order ?? "desc";
|
||||
@ -732,7 +732,7 @@ export default () => {
|
||||
playerId,
|
||||
serviceParams = { sort: "recent", order: "desc", page: 1 },
|
||||
priority = PRIORITY.FG_LOW,
|
||||
{ ...options } = {},
|
||||
{ ...options } = {}
|
||||
) =>
|
||||
((serviceParams?.sort ?? "recent") === "top"
|
||||
? topScoresApiClient
|
||||
@ -750,7 +750,7 @@ export default () => {
|
||||
priority = PRIORITY.FG_LOW,
|
||||
signal = null,
|
||||
canUseBrowserCache = false,
|
||||
refreshInterval = MINUTE,
|
||||
refreshInterval = MINUTE
|
||||
) => {
|
||||
const fetchedScoresResponse = await fetchScoresPage(
|
||||
playerId,
|
||||
@ -761,13 +761,13 @@ export default () => {
|
||||
cacheTtl: MINUTE,
|
||||
maxAge: canUseBrowserCache ? 0 : refreshInterval,
|
||||
fullResponse: true,
|
||||
},
|
||||
}
|
||||
);
|
||||
if (topScoresApiClient.isResponseCached(fetchedScoresResponse))
|
||||
return topScoresApiClient.getDataFromResponse(fetchedScoresResponse);
|
||||
|
||||
const fetchedScores = topScoresApiClient.getDataFromResponse(
|
||||
fetchedScoresResponse,
|
||||
fetchedScoresResponse
|
||||
);
|
||||
|
||||
const playerScores = await getPlayerScores(playerId);
|
||||
@ -835,7 +835,7 @@ export default () => {
|
||||
refreshInterval = MINUTE,
|
||||
priority = PRIORITY.FG_LOW,
|
||||
signal = null,
|
||||
force = false,
|
||||
force = false
|
||||
) => {
|
||||
if (!player || !player.playerId) return null;
|
||||
|
||||
@ -845,7 +845,7 @@ export default () => {
|
||||
|
||||
const scoresPage = await getPlayerScoresPage(
|
||||
player.playerId,
|
||||
serviceParams,
|
||||
serviceParams
|
||||
);
|
||||
|
||||
if (
|
||||
@ -889,7 +889,7 @@ export default () => {
|
||||
priority,
|
||||
signal,
|
||||
canUseBrowserCache && !shouldPageBeRefetched,
|
||||
refreshInterval,
|
||||
refreshInterval
|
||||
);
|
||||
|
||||
return scoresPage;
|
||||
@ -899,7 +899,7 @@ export default () => {
|
||||
playerId,
|
||||
forceUpdate = false,
|
||||
priority = PRIORITY.BG_NORMAL,
|
||||
throwErrors = false,
|
||||
throwErrors = false
|
||||
) => {
|
||||
refreshCallCounter++;
|
||||
|
||||
@ -908,13 +908,13 @@ export default () => {
|
||||
`Starting player "${playerId}" scores refreshing${
|
||||
forceUpdate ? " (forced)" : ""
|
||||
}...`,
|
||||
"ScoresService",
|
||||
"ScoresService"
|
||||
);
|
||||
|
||||
if (!playerId) {
|
||||
log.warn(
|
||||
`Can not refresh player scores if an empty playerId is given`,
|
||||
"ScoresService",
|
||||
"ScoresService"
|
||||
);
|
||||
|
||||
return null;
|
||||
@ -923,7 +923,7 @@ export default () => {
|
||||
if (updateInProgress.includes(playerId)) {
|
||||
log.warn(
|
||||
`Player "${playerId}" scores are being fetched, skipping.`,
|
||||
"ScoresService",
|
||||
"ScoresService"
|
||||
);
|
||||
|
||||
return null;
|
||||
@ -939,7 +939,7 @@ export default () => {
|
||||
|
||||
if (!player) {
|
||||
log.debug(
|
||||
`Can not refresh the scores of player "${playerId}" because it has not been added to the DB`,
|
||||
`Can not refresh the scores of player "${playerId}" because it has not been added to the DB`
|
||||
);
|
||||
return null;
|
||||
}
|
||||
@ -949,9 +949,9 @@ export default () => {
|
||||
if (scoresFreshnessDate > new Date()) {
|
||||
log.debug(
|
||||
`Player "${playerId}" scores are still fresh, skipping. Next refresh on ${formatDate(
|
||||
scoresFreshnessDate,
|
||||
scoresFreshnessDate
|
||||
)}`,
|
||||
"ScoresService",
|
||||
"ScoresService"
|
||||
);
|
||||
|
||||
return {
|
||||
@ -959,7 +959,7 @@ export default () => {
|
||||
newScores: null,
|
||||
scores: convertScoresById(
|
||||
player.playerId,
|
||||
await getPlayerScores(player.playerId),
|
||||
await getPlayerScores(player.playerId)
|
||||
),
|
||||
};
|
||||
}
|
||||
@ -967,18 +967,18 @@ export default () => {
|
||||
|
||||
log.trace(
|
||||
`Fetching player "${playerId}" scores from ScoreSaber...`,
|
||||
"ScoresService",
|
||||
"ScoresService"
|
||||
);
|
||||
|
||||
const updatedPlayerScores = await resolvePromiseOrWaitForPending(
|
||||
`service/updatePlayerScores/${playerId}`,
|
||||
() => updatePlayerScores(player, priority),
|
||||
() => updatePlayerScores(player, priority)
|
||||
);
|
||||
|
||||
if (!updatedPlayerScores) {
|
||||
log.warn(
|
||||
`Can not refresh player "${playerId}" scores`,
|
||||
"ScoresService",
|
||||
"ScoresService"
|
||||
);
|
||||
|
||||
return null;
|
||||
@ -989,7 +989,7 @@ export default () => {
|
||||
log.trace(
|
||||
`Player "${playerId}" scores updated`,
|
||||
"ScoresService",
|
||||
scoresInfo.newScores,
|
||||
scoresInfo.newScores
|
||||
);
|
||||
|
||||
if (scoresInfo.newScores && scoresInfo.newScores.length) {
|
||||
@ -1012,7 +1012,7 @@ export default () => {
|
||||
e.toString ? `: ${e.toString()}` : ""
|
||||
}`,
|
||||
"ScoresService",
|
||||
e,
|
||||
e
|
||||
);
|
||||
|
||||
return null;
|
||||
@ -1026,11 +1026,11 @@ export default () => {
|
||||
const refreshAll = async (
|
||||
force = false,
|
||||
priority = PRIORITY.BG_NORMAL,
|
||||
throwErrors = false,
|
||||
throwErrors = false
|
||||
) => {
|
||||
log.trace(
|
||||
`Starting refreshing all players scores${force ? " (forced)" : ""}...`,
|
||||
"ScoresService",
|
||||
"ScoresService"
|
||||
);
|
||||
|
||||
const allActivePlayers = await playerService.getAllActive();
|
||||
@ -1041,19 +1041,19 @@ export default () => {
|
||||
|
||||
const allNewScores = await Promise.all(
|
||||
allActivePlayers.map((player) =>
|
||||
refresh(player.playerId, force, priority, throwErrors),
|
||||
),
|
||||
refresh(player.playerId, force, priority, throwErrors)
|
||||
)
|
||||
);
|
||||
const allPlayersWithNewScores = allActivePlayers.map((player, idx) =>
|
||||
allNewScores[idx]
|
||||
? { player, ...allNewScores[idx] }
|
||||
: { player, newScores: null, scores: null, recentPlay: null },
|
||||
: { player, newScores: null, scores: null, recentPlay: null }
|
||||
);
|
||||
|
||||
log.trace(
|
||||
`All players scores refreshed.`,
|
||||
"ScoresService",
|
||||
allPlayersWithNewScores,
|
||||
allPlayersWithNewScores
|
||||
);
|
||||
|
||||
return allPlayersWithNewScores;
|
||||
|
@ -87,7 +87,7 @@ export default () => {
|
||||
const fetchProfile = async (
|
||||
login,
|
||||
priority = PRIORITY.FG_LOW,
|
||||
{ fullResponse = false, ...options } = {},
|
||||
{ fullResponse = false, ...options } = {}
|
||||
) => {
|
||||
const token = await getCurrentToken();
|
||||
if (!token || !token.expires || token.expires <= new Date()) return null;
|
||||
@ -101,14 +101,14 @@ export default () => {
|
||||
login,
|
||||
priority,
|
||||
fullResponse,
|
||||
}),
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
const fetchVideos = async (
|
||||
userId,
|
||||
priority = PRIORITY.FG_LOW,
|
||||
{ fullResponse = false, ...options } = {},
|
||||
{ fullResponse = false, ...options } = {}
|
||||
) => {
|
||||
const token = await getCurrentToken();
|
||||
if (!token || !token.expires || token.expires <= new Date()) return null;
|
||||
@ -122,7 +122,7 @@ export default () => {
|
||||
userId,
|
||||
priority,
|
||||
fullResponse,
|
||||
}),
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
@ -134,11 +134,11 @@ export default () => {
|
||||
playerId,
|
||||
forceUpdate = false,
|
||||
priority = queues.PRIORITY.FG_LOW,
|
||||
throwErrors = false,
|
||||
throwErrors = false
|
||||
) => {
|
||||
log.trace(
|
||||
`Starting Twitch videos refreshing${forceUpdate ? " (forced)" : ""}...`,
|
||||
"TwitchService",
|
||||
"TwitchService"
|
||||
);
|
||||
|
||||
if (!playerId) {
|
||||
@ -152,7 +152,7 @@ export default () => {
|
||||
if (!twitchProfile || !twitchProfile.login) {
|
||||
log.debug(
|
||||
`Twitch profile for player ${playerId} is not set, skipping`,
|
||||
"TwitchService",
|
||||
"TwitchService"
|
||||
);
|
||||
|
||||
return null;
|
||||
@ -163,9 +163,9 @@ export default () => {
|
||||
if (lastUpdated && lastUpdated > new Date() - REFRESH_INTERVAL) {
|
||||
log.debug(
|
||||
`Refresh interval not yet expired, skipping. Next refresh on ${formatDate(
|
||||
addToDate(REFRESH_INTERVAL, lastUpdated),
|
||||
addToDate(REFRESH_INTERVAL, lastUpdated)
|
||||
)}`,
|
||||
"TwitchService",
|
||||
"TwitchService"
|
||||
);
|
||||
|
||||
return twitchProfile;
|
||||
@ -177,7 +177,7 @@ export default () => {
|
||||
if (lastUpdated && lastUpdated > player.recentPlay) {
|
||||
log.debug(
|
||||
`Twitch updated after recent player play, skipping`,
|
||||
"TwitchService",
|
||||
"TwitchService"
|
||||
);
|
||||
|
||||
return twitchProfile;
|
||||
@ -189,7 +189,7 @@ export default () => {
|
||||
if (!fetchedProfile) {
|
||||
log.debug(
|
||||
`Can not fetch Twitch profile for player ${playerId}, skipping`,
|
||||
"TwitchService",
|
||||
"TwitchService"
|
||||
);
|
||||
|
||||
return twitchProfile;
|
||||
@ -220,7 +220,7 @@ export default () => {
|
||||
log.debug(
|
||||
`Twitch player ${playerId} refreshing error`,
|
||||
"TwitchService",
|
||||
e,
|
||||
e
|
||||
);
|
||||
|
||||
return null;
|
||||
@ -243,7 +243,7 @@ export default () => {
|
||||
created_at: dateFromString(v.created_at),
|
||||
ended_at: addToDate(
|
||||
durationToMillis(v.duration),
|
||||
dateFromString(v.created_at),
|
||||
dateFromString(v.created_at)
|
||||
),
|
||||
}))
|
||||
.find((v) => v.created_at <= songStarted && songStarted < v.ended_at);
|
||||
|
@ -5,7 +5,7 @@ export const getServicePlayerGain = (
|
||||
dateTruncFunc,
|
||||
dateKey,
|
||||
daysAgo = 1,
|
||||
maxDaysAgo = 7,
|
||||
maxDaysAgo = 7
|
||||
) => {
|
||||
if (!playerHistory?.length) return null;
|
||||
|
||||
@ -21,7 +21,7 @@ export const getServicePlayerGain = (
|
||||
return playerHistory
|
||||
.sort((a, b) => b?.[dateKey]?.getTime() - a?.[dateKey]?.getTime())
|
||||
.find(
|
||||
(h) => h?.[dateKey] <= compareToDate && h?.[dateKey] >= maxServiceDate,
|
||||
(h) => h?.[dateKey] <= compareToDate && h?.[dateKey] >= maxServiceDate
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -78,7 +78,7 @@ export default async () => {
|
||||
const determineNewSettingsAvailable = (dbConfig) =>
|
||||
Object.entries(newSettingsAvailableDefinition)
|
||||
.map(([key, description]) =>
|
||||
opt(dbConfig, key) === undefined ? description : null,
|
||||
opt(dbConfig, key) === undefined ? description : null
|
||||
)
|
||||
.filter((d) => d);
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { writable } from "svelte/store";
|
||||
|
||||
export default (
|
||||
sizes = { phone: 0, tablet: 768, desktop: 1024, xxl: 1749 },
|
||||
sizes = { phone: 0, tablet: 768, desktop: 1024, xxl: 1749 }
|
||||
) => {
|
||||
const defaultValue = { name: null, width: null, nodeWidth: null, rect: null };
|
||||
const { subscribe, unsubscribe, set } = writable(defaultValue);
|
||||
@ -41,8 +41,8 @@ export default (
|
||||
item[1] <= nodeWidth
|
||||
? { name: item[0], width: item[1], nodeWidth, rect }
|
||||
: cum,
|
||||
defaultValue,
|
||||
),
|
||||
defaultValue
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -11,7 +11,7 @@ export default (score, bmStats, leaderboardId) => {
|
||||
} else if (leaderboardId) {
|
||||
maxScore = getFixedLeaderboardMaxScore(
|
||||
leaderboardId,
|
||||
score?.maxScore ?? null,
|
||||
score?.maxScore ?? null
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,6 @@ export default async (data, cachedOnly = false) => {
|
||||
data.leaderboard.beatMaps = await beatMaps.byHash(
|
||||
data.leaderboard.song.hash,
|
||||
false,
|
||||
cachedOnly,
|
||||
cachedOnly
|
||||
);
|
||||
};
|
||||
|
@ -15,7 +15,7 @@ export default async (data) => {
|
||||
: 0;
|
||||
const bmStats = findDiffInfoWithDiffAndTypeFromBeatMaps(
|
||||
opt(data, `leaderboard.beatMaps.versions.${versionsLastIdx}.diffs`),
|
||||
diffInfo,
|
||||
diffInfo
|
||||
);
|
||||
|
||||
data.score = calculateAcc(data.score, bmStats, leaderboardId);
|
||||
|
@ -48,11 +48,11 @@ export default async (data, playerId = null) => {
|
||||
const mainPlayerScore = await produce(
|
||||
await produce(
|
||||
await produce(comparePlayerScores[leaderboardId], (draft) =>
|
||||
beatMapsEnhancer(draft),
|
||||
beatMapsEnhancer(draft)
|
||||
),
|
||||
(draft) => accEnhancer(draft, true),
|
||||
(draft) => accEnhancer(draft, true)
|
||||
),
|
||||
(draft) => beatSaviorEnhancer(draft, mainPlayerId),
|
||||
(draft) => beatSaviorEnhancer(draft, mainPlayerId)
|
||||
);
|
||||
|
||||
data.comparePlayers = [
|
||||
|
@ -15,7 +15,7 @@ export default async (data, playerId = null) => {
|
||||
if (!scoresService) scoresService = createScoresService();
|
||||
|
||||
const playerScores = scoresService.convertScoresToObject(
|
||||
await scoresService.getPlayerScores(playerId),
|
||||
await scoresService.getPlayerScores(playerId)
|
||||
);
|
||||
|
||||
// skip if no cached score
|
||||
@ -41,7 +41,7 @@ export default async (data, playerId = null) => {
|
||||
: 0;
|
||||
const bmStats = findDiffInfoWithDiffAndTypeFromBeatMaps(
|
||||
opt(data, `leaderboard.beatMaps.versions.${versionsLastIdx}.diffs`),
|
||||
diffInfo,
|
||||
diffInfo
|
||||
);
|
||||
|
||||
data.prevScore = calculateAcc(prevScore, bmStats, leaderboardId);
|
||||
|
@ -20,7 +20,7 @@ export default async (data, playerId = null, whatIfOnly = false) => {
|
||||
const whatIfPp = await ppService.getWhatIfScore(
|
||||
mainPlayerId,
|
||||
leaderboardId,
|
||||
pp,
|
||||
pp
|
||||
);
|
||||
if (whatIfPp && whatIfPp.diff >= 0.01) data.score.whatIfPp = whatIfPp;
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ export default async (data, playerId = null) => {
|
||||
: 0;
|
||||
const bmStats = findDiffInfoWithDiffAndTypeFromBeatMaps(
|
||||
opt(data, `leaderboard.beatMaps.versions.${versionsLastIdx}.diffs`),
|
||||
data.leaderboard.diffInfo,
|
||||
data.leaderboard.diffInfo
|
||||
);
|
||||
if (!bmStats || !bmStats.seconds) return;
|
||||
|
||||
@ -27,7 +27,7 @@ export default async (data, playerId = null) => {
|
||||
const video = await twitchService.findTwitchVideo(
|
||||
twitchProfile,
|
||||
data.score.timeSet,
|
||||
bmStats.seconds,
|
||||
bmStats.seconds
|
||||
);
|
||||
if (!video || !video.url) return;
|
||||
|
||||
|
@ -13,7 +13,7 @@ export default (
|
||||
type = "global",
|
||||
page = 1,
|
||||
initialState = null,
|
||||
initialStateType = "initial",
|
||||
initialStateType = "initial"
|
||||
) => {
|
||||
let currentLeaderboardId = leaderboardId ? leaderboardId : null;
|
||||
let currentType = type ? type : "global";
|
||||
@ -62,13 +62,13 @@ export default (
|
||||
|
||||
const patchId = getPatchId(currentLeaderboardId, scoreRow);
|
||||
const stateRowIdx = newState.scores.findIndex(
|
||||
(s) => getPatchId(currentLeaderboardId, s) === patchId,
|
||||
(s) => getPatchId(currentLeaderboardId, s) === patchId
|
||||
);
|
||||
if (stateRowIdx < 0) return;
|
||||
|
||||
newState.scores[stateRowIdx] = applyPatches(
|
||||
newState.scores[stateRowIdx],
|
||||
enhancePatches[patchId],
|
||||
enhancePatches[patchId]
|
||||
);
|
||||
|
||||
debouncedSetState(enhanceTaskId, newState);
|
||||
@ -88,7 +88,7 @@ export default (
|
||||
const bpm = newState?.leaderboard?.beatMaps?.metadata?.bpm ?? null;
|
||||
const bmStats = findDiffInfoWithDiffAndTypeFromBeatMaps(
|
||||
newState?.leaderboard?.beatMaps?.versions?.[versionsLastIdx]?.diffs,
|
||||
newState?.leaderboard?.diffInfo,
|
||||
newState?.leaderboard?.diffInfo
|
||||
);
|
||||
if (!bmStats) return null;
|
||||
|
||||
@ -113,7 +113,7 @@ export default (
|
||||
leaderboard: newState.leaderboard,
|
||||
},
|
||||
getPatchId(currentLeaderboardId, scoreRow),
|
||||
(draft) => accEnhancer(draft),
|
||||
(draft) => accEnhancer(draft)
|
||||
)
|
||||
.then((scoreRow) => setStateRow(enhanceTaskId, scoreRow))
|
||||
.then((scoreRow) =>
|
||||
@ -124,9 +124,9 @@ export default (
|
||||
ppAttributionEnhancer(
|
||||
draft,
|
||||
scoreRow?.player?.playerId,
|
||||
true,
|
||||
),
|
||||
),
|
||||
true
|
||||
)
|
||||
)
|
||||
)
|
||||
.then((scoreRow) => setStateRow(enhanceTaskId, scoreRow));
|
||||
}
|
||||
@ -144,14 +144,14 @@ export default (
|
||||
onAfterStateChange: onNewData,
|
||||
onSetPending: ({ fetchParams }) => ({ ...fetchParams }),
|
||||
},
|
||||
initialStateType,
|
||||
initialStateType
|
||||
);
|
||||
|
||||
const fetch = async (
|
||||
leaderboardId = currentLeaderboardId,
|
||||
type = currentType,
|
||||
page = currentPage,
|
||||
force = false,
|
||||
force = false
|
||||
) => {
|
||||
if (!leaderboardId) return false;
|
||||
|
||||
|
@ -4,7 +4,7 @@ import playerApiClient from "../../network/clients/scoresaber/player/api";
|
||||
export default (
|
||||
playerId = null,
|
||||
initialState = null,
|
||||
initialStateType = "initial",
|
||||
initialStateType = "initial"
|
||||
) => {
|
||||
let currentPlayerId = playerId;
|
||||
|
||||
@ -20,7 +20,7 @@ export default (
|
||||
onInitialized: onNewData,
|
||||
onAfterStateChange: onNewData,
|
||||
},
|
||||
initialStateType,
|
||||
initialStateType
|
||||
);
|
||||
|
||||
const fetch = async (playerId = currentPlayerId, force = false) => {
|
||||
|
@ -11,7 +11,7 @@ export default (
|
||||
service = "scoresaber",
|
||||
serviceParams = { type: "recent", page: 1 },
|
||||
initialState = null,
|
||||
initialStateType = "initial",
|
||||
initialStateType = "initial"
|
||||
) => {
|
||||
let currentPlayerId = playerId;
|
||||
let currentService = service;
|
||||
@ -42,14 +42,14 @@ export default (
|
||||
onInitialized: onNewData,
|
||||
onAfterStateChange: onNewData,
|
||||
},
|
||||
initialStateType,
|
||||
initialStateType
|
||||
);
|
||||
|
||||
const fetch = async (
|
||||
playerId = currentPlayerId,
|
||||
service = currentService,
|
||||
serviceParams = currentServiceParams,
|
||||
force = false,
|
||||
force = false
|
||||
) => {
|
||||
if (
|
||||
(!playerId || playerId === currentPlayerId) &&
|
||||
@ -70,7 +70,7 @@ export default (
|
||||
{ playerId, service, serviceParams },
|
||||
force,
|
||||
provider,
|
||||
!playerId || playerId !== currentPlayerId || force,
|
||||
!playerId || playerId !== currentPlayerId || force
|
||||
);
|
||||
};
|
||||
|
||||
@ -94,7 +94,7 @@ export default (
|
||||
playerForLastRecentPlay = playerId;
|
||||
|
||||
await refresh();
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const subscribe = (fn) => {
|
||||
@ -112,7 +112,7 @@ export default (
|
||||
if (!currentPlayerId) {
|
||||
setTimeout(
|
||||
() => enqueueRecentPlayRefresh(),
|
||||
DEFAULT_RECENT_PLAY_REFRESH_INTERVAL,
|
||||
DEFAULT_RECENT_PLAY_REFRESH_INTERVAL
|
||||
);
|
||||
|
||||
return;
|
||||
@ -130,7 +130,7 @@ export default (
|
||||
|
||||
setTimeout(
|
||||
() => enqueueRecentPlayRefresh(),
|
||||
DEFAULT_RECENT_PLAY_REFRESH_INTERVAL,
|
||||
DEFAULT_RECENT_PLAY_REFRESH_INTERVAL
|
||||
);
|
||||
|
||||
return {
|
||||
|
@ -5,7 +5,7 @@ export default (
|
||||
type = "global",
|
||||
page = 1,
|
||||
initialState = null,
|
||||
initialStateType = "initial",
|
||||
initialStateType = "initial"
|
||||
) => {
|
||||
let currentType = type ? type : "global";
|
||||
let currentPage = page ? page : 1;
|
||||
@ -26,13 +26,13 @@ export default (
|
||||
onAfterStateChange: onNewData,
|
||||
onSetPending: ({ fetchParams }) => ({ ...fetchParams }),
|
||||
},
|
||||
initialStateType,
|
||||
initialStateType
|
||||
);
|
||||
|
||||
const fetch = async (
|
||||
type = currentType,
|
||||
page = currentPage,
|
||||
force = false,
|
||||
force = false
|
||||
) => {
|
||||
if (
|
||||
(!type || type === currentType) &&
|
||||
|
@ -17,7 +17,7 @@ export default (
|
||||
service = "scoresaber",
|
||||
serviceParams = { type: "recent", page: 1 },
|
||||
initialState = null,
|
||||
initialStateType = "initial",
|
||||
initialStateType = "initial"
|
||||
) => {
|
||||
let currentPlayerId = playerId;
|
||||
let currentService = service;
|
||||
@ -82,13 +82,13 @@ export default (
|
||||
|
||||
const patchId = getPatchId(currentPlayerId, scoreRow);
|
||||
const stateRowIdx = newState.findIndex(
|
||||
(s) => getPatchId(currentPlayerId, s) === patchId,
|
||||
(s) => getPatchId(currentPlayerId, s) === patchId
|
||||
);
|
||||
if (stateRowIdx < 0) return;
|
||||
|
||||
newState[stateRowIdx] = applyPatches(
|
||||
newState[stateRowIdx],
|
||||
enhancePatches[patchId],
|
||||
enhancePatches[patchId]
|
||||
);
|
||||
|
||||
debouncedSetState(enhanceTaskId, newState);
|
||||
@ -99,74 +99,74 @@ export default (
|
||||
for (const scoreRow of newState) {
|
||||
if (currentService !== "accsaber") {
|
||||
stateProduce(scoreRow, getPatchId(currentPlayerId, scoreRow), (draft) =>
|
||||
beatMapsEnhancer(draft),
|
||||
beatMapsEnhancer(draft)
|
||||
)
|
||||
.then((scoreRow) =>
|
||||
stateProduce(
|
||||
scoreRow,
|
||||
getPatchId(currentPlayerId, scoreRow),
|
||||
(draft) => accEnhancer(draft),
|
||||
),
|
||||
(draft) => accEnhancer(draft)
|
||||
)
|
||||
)
|
||||
.then((scoreRow) => setStateRow(enhanceTaskId, scoreRow))
|
||||
.then((scoreRow) =>
|
||||
stateProduce(
|
||||
scoreRow,
|
||||
getPatchId(currentPlayerId, scoreRow),
|
||||
(draft) => diffEnhancer(draft, currentPlayerId),
|
||||
),
|
||||
(draft) => diffEnhancer(draft, currentPlayerId)
|
||||
)
|
||||
)
|
||||
.then((scoreRow) => setStateRow(enhanceTaskId, scoreRow))
|
||||
.then((scoreRow) =>
|
||||
stateProduce(
|
||||
scoreRow,
|
||||
getPatchId(currentPlayerId, scoreRow),
|
||||
(draft) => compareEnhancer(draft, currentPlayerId),
|
||||
),
|
||||
(draft) => compareEnhancer(draft, currentPlayerId)
|
||||
)
|
||||
)
|
||||
.then((scoreRow) => setStateRow(enhanceTaskId, scoreRow))
|
||||
.then((scoreRow) =>
|
||||
stateProduce(
|
||||
scoreRow,
|
||||
getPatchId(currentPlayerId, scoreRow),
|
||||
(draft) => twitchEnhancer(draft, currentPlayerId),
|
||||
),
|
||||
(draft) => twitchEnhancer(draft, currentPlayerId)
|
||||
)
|
||||
)
|
||||
.then((scoreRow) => setStateRow(enhanceTaskId, scoreRow));
|
||||
|
||||
stateProduce(scoreRow, getPatchId(currentPlayerId, scoreRow), (draft) =>
|
||||
rankedsEnhancer(draft),
|
||||
rankedsEnhancer(draft)
|
||||
).then((scoreRow) => setStateRow(enhanceTaskId, scoreRow));
|
||||
|
||||
stateProduce(scoreRow, getPatchId(currentPlayerId, scoreRow), (draft) =>
|
||||
ppAttributionEnhancer(draft, currentPlayerId),
|
||||
ppAttributionEnhancer(draft, currentPlayerId)
|
||||
).then((scoreRow) => setStateRow(enhanceTaskId, scoreRow));
|
||||
|
||||
if (stateType && stateType === "live")
|
||||
stateProduce(
|
||||
scoreRow,
|
||||
getPatchId(currentPlayerId, scoreRow),
|
||||
(draft) => beatSaviorEnhancer(draft, currentPlayerId),
|
||||
(draft) => beatSaviorEnhancer(draft, currentPlayerId)
|
||||
).then((scoreRow) => setStateRow(enhanceTaskId, scoreRow));
|
||||
} else {
|
||||
stateProduce(scoreRow, getPatchId(currentPlayerId, scoreRow), (draft) =>
|
||||
beatMapsEnhancer(draft),
|
||||
beatMapsEnhancer(draft)
|
||||
)
|
||||
.then((scoreRow) => setStateRow(enhanceTaskId, scoreRow))
|
||||
.then((scoreRow) =>
|
||||
stateProduce(
|
||||
scoreRow,
|
||||
getPatchId(currentPlayerId, scoreRow),
|
||||
(draft) => twitchEnhancer(draft, currentPlayerId),
|
||||
),
|
||||
(draft) => twitchEnhancer(draft, currentPlayerId)
|
||||
)
|
||||
)
|
||||
.then((scoreRow) => setStateRow(enhanceTaskId, scoreRow))
|
||||
.then((scoreRow) =>
|
||||
stateProduce(
|
||||
scoreRow,
|
||||
getPatchId(currentPlayerId, scoreRow),
|
||||
(draft) => beatSaviorEnhancer(draft, currentPlayerId),
|
||||
),
|
||||
(draft) => beatSaviorEnhancer(draft, currentPlayerId)
|
||||
)
|
||||
)
|
||||
.then((scoreRow) => setStateRow(enhanceTaskId, scoreRow));
|
||||
}
|
||||
@ -185,14 +185,14 @@ export default (
|
||||
onAfterStateChange: onNewData,
|
||||
onSetPending: ({ fetchParams }) => ({ ...fetchParams }),
|
||||
},
|
||||
initialStateType,
|
||||
initialStateType
|
||||
);
|
||||
|
||||
const fetch = async (
|
||||
serviceParams = currentServiceParams,
|
||||
service = currentService,
|
||||
playerId = currentPlayerId,
|
||||
force = false,
|
||||
force = false
|
||||
) => {
|
||||
if (
|
||||
(!playerId || playerId === currentPlayerId) &&
|
||||
@ -207,7 +207,7 @@ export default (
|
||||
{ playerId, service, serviceParams },
|
||||
force,
|
||||
provider,
|
||||
!playerId || playerId !== currentPlayerId || force,
|
||||
!playerId || playerId !== currentPlayerId || force
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -16,7 +16,7 @@ export default (
|
||||
onSetPending = null,
|
||||
onError = null,
|
||||
} = {},
|
||||
initialStateType = "initial",
|
||||
initialStateType = "initial"
|
||||
) => {
|
||||
const getFinalParams = (fetchParams) => ({
|
||||
...defaultFetchParams,
|
||||
@ -46,7 +46,7 @@ export default (
|
||||
fetchParams = {},
|
||||
force = false,
|
||||
provider = currentProvider,
|
||||
fetchCachedFirst = false,
|
||||
fetchCachedFirst = false
|
||||
) => {
|
||||
const abortController = new AbortController();
|
||||
|
||||
@ -67,7 +67,7 @@ export default (
|
||||
set(
|
||||
onBeforeStateChange
|
||||
? onBeforeStateChange(cachedState, stateType)
|
||||
: cachedState,
|
||||
: cachedState
|
||||
);
|
||||
}
|
||||
});
|
||||
@ -78,7 +78,7 @@ export default (
|
||||
setPending(
|
||||
onSetPending
|
||||
? onSetPending({ fetchParams, abortController })
|
||||
: fetchParams,
|
||||
: fetchParams
|
||||
);
|
||||
|
||||
pendingAbortController = abortController;
|
||||
|
@ -30,14 +30,14 @@ export default () => {
|
||||
refreshInterval,
|
||||
priority,
|
||||
signal,
|
||||
force,
|
||||
force
|
||||
);
|
||||
|
||||
const scores = await scoresFetcher.fetchLiveScores(
|
||||
player,
|
||||
service,
|
||||
serviceParams,
|
||||
{ refreshInterval, priority, signal, force },
|
||||
{ refreshInterval, priority, signal, force }
|
||||
);
|
||||
|
||||
return { ...player, scores, service, serviceParams };
|
||||
|
@ -20,7 +20,7 @@ export default () => {
|
||||
return;
|
||||
|
||||
player = newPlayer;
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const playerRecentPlayUpdatedUnsubscribe = eventBus.on(
|
||||
@ -30,7 +30,7 @@ export default () => {
|
||||
|
||||
player.recentPlay = recentPlay;
|
||||
player.recentPlayLastUpdated = recentPlayLastUpdated;
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
return {
|
||||
@ -47,7 +47,7 @@ export default () => {
|
||||
playerId,
|
||||
MINUTE,
|
||||
priority,
|
||||
signal,
|
||||
signal
|
||||
);
|
||||
|
||||
return scoresFetcher.fetchLiveScores(player, service, serviceParams, {
|
||||
|
@ -21,7 +21,7 @@ export default () => {
|
||||
page,
|
||||
priority,
|
||||
signal,
|
||||
force,
|
||||
force
|
||||
);
|
||||
case "accsaber":
|
||||
return await leaderboardService.fetchAccSaberPage(
|
||||
@ -29,14 +29,14 @@ export default () => {
|
||||
page,
|
||||
priority,
|
||||
signal,
|
||||
force,
|
||||
force
|
||||
);
|
||||
default:
|
||||
return await leaderboardService.getFriendsLeaderboard(
|
||||
leaderboardId,
|
||||
priority,
|
||||
signal,
|
||||
force,
|
||||
force
|
||||
);
|
||||
}
|
||||
};
|
||||
|
@ -19,7 +19,7 @@ export default () => {
|
||||
playerId,
|
||||
service,
|
||||
serviceParams = { sort: "recent", order: "desc", page: 1 },
|
||||
otherParams = {},
|
||||
otherParams = {}
|
||||
) => {
|
||||
switch (service) {
|
||||
case "beatsavior":
|
||||
@ -36,18 +36,18 @@ export default () => {
|
||||
player,
|
||||
service,
|
||||
serviceParams = { sort: "recent", order: "desc", page: 1 },
|
||||
otherParams = {},
|
||||
otherParams = {}
|
||||
) => {
|
||||
switch (service) {
|
||||
case "beatsavior":
|
||||
return beatSaviorService.getPlayerScoresPage(
|
||||
player?.playerId,
|
||||
serviceParams,
|
||||
serviceParams
|
||||
);
|
||||
case "accsaber":
|
||||
return accSaberService.getPlayerScoresPage(
|
||||
player?.playerId,
|
||||
serviceParams,
|
||||
serviceParams
|
||||
);
|
||||
case "scoresaber":
|
||||
default:
|
||||
@ -57,7 +57,7 @@ export default () => {
|
||||
otherParams?.refreshInterval,
|
||||
otherParams?.priority,
|
||||
otherParams?.signal,
|
||||
otherParams?.force,
|
||||
otherParams?.force
|
||||
);
|
||||
}
|
||||
};
|
||||
|
@ -15,7 +15,7 @@ export default () => {
|
||||
set(
|
||||
players
|
||||
.filter((p) => p && p.playerId && friends.includes(p.playerId))
|
||||
.sort((a, b) => (a.name ? a.name.localeCompare(b.name) : 0)),
|
||||
.sort((a, b) => (a.name ? a.name.localeCompare(b.name) : 0))
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -23,11 +23,11 @@ export default () => {
|
||||
|
||||
const playerAddedUnsubscribe = eventBus.on(
|
||||
"player-profile-added",
|
||||
refreshState,
|
||||
refreshState
|
||||
);
|
||||
const playerRemovedUnsubscribe = eventBus.on(
|
||||
"player-profile-removed",
|
||||
refreshState,
|
||||
refreshState
|
||||
);
|
||||
|
||||
const subscribe = (fn) => {
|
||||
|
@ -18,7 +18,7 @@ export default async (refreshOnCreate = false) => {
|
||||
const get = () => rankeds;
|
||||
const refresh = async (
|
||||
forceUpdate = false,
|
||||
priority = PRIORITY.BG_NORMAL,
|
||||
priority = PRIORITY.BG_NORMAL
|
||||
) => {
|
||||
await rankedsService.refresh(forceUpdate, priority);
|
||||
};
|
||||
@ -32,7 +32,7 @@ export default async (refreshOnCreate = false) => {
|
||||
"rankeds-changed",
|
||||
({ allRankeds }) => {
|
||||
if (allRankeds && Object.keys(allRankeds).length) set(allRankeds);
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const subscribe = (fn) => {
|
||||
|
@ -14,7 +14,7 @@ export function hoverable(node) {
|
||||
pageY: event.pageY,
|
||||
rect,
|
||||
},
|
||||
}),
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@ -30,7 +30,7 @@ export function hoverable(node) {
|
||||
pageX: event.pageX,
|
||||
pageY: event.pageY,
|
||||
},
|
||||
}),
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@ const createGlobalPubSub = () => {
|
||||
`Create pub/sub channel for node ${nodeId} (${
|
||||
isWorker ? "worker" : "browser"
|
||||
})`,
|
||||
"PubSub",
|
||||
"PubSub"
|
||||
);
|
||||
|
||||
bc = new BroadcastChannel("global-pub-sub", { webWorkerSupport: true });
|
||||
@ -41,7 +41,7 @@ const createGlobalPubSub = () => {
|
||||
if (!exists(eventName)) return;
|
||||
|
||||
subscribers[eventName].forEach((handler) =>
|
||||
handler(value, isLocal, eventName),
|
||||
handler(value, isLocal, eventName)
|
||||
);
|
||||
};
|
||||
|
||||
@ -49,7 +49,7 @@ const createGlobalPubSub = () => {
|
||||
if (!exists(eventName)) return;
|
||||
|
||||
subscribers[eventName] = subscribers[eventName].filter(
|
||||
(h) => h !== handler,
|
||||
(h) => h !== handler
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -20,7 +20,7 @@ export const dateFromString = (str) => {
|
||||
const matches =
|
||||
str && isString(str)
|
||||
? str.match(
|
||||
/^(\d{4}-\d{1,2}-\d{1,2})\s+(\d{1,2}:\d{1,2}(:\d{1,2})?)\sUTC$/,
|
||||
/^(\d{4}-\d{1,2}-\d{1,2})\s+(\d{1,2}:\d{1,2}(:\d{1,2})?)\sUTC$/
|
||||
)
|
||||
: null;
|
||||
if (matches && matches.length >= 3) {
|
||||
@ -99,7 +99,7 @@ export const fromAccSaberDateString = (dateStr) =>
|
||||
export function formatDateWithOptions(
|
||||
val,
|
||||
options = { localeMatcher: "best fit" },
|
||||
locale = getCurrentLocale(),
|
||||
locale = getCurrentLocale()
|
||||
) {
|
||||
if (!isValidDate(val)) return null;
|
||||
|
||||
@ -112,7 +112,7 @@ export function formatDate(
|
||||
val,
|
||||
dateStyle = "short",
|
||||
timeStyle = "medium",
|
||||
locale = getCurrentLocale(),
|
||||
locale = getCurrentLocale()
|
||||
) {
|
||||
return formatDateWithOptions(
|
||||
val,
|
||||
@ -121,7 +121,7 @@ export function formatDate(
|
||||
dateStyle,
|
||||
timeStyle: timeStyle ?? undefined,
|
||||
},
|
||||
locale,
|
||||
locale
|
||||
);
|
||||
}
|
||||
|
||||
@ -158,12 +158,12 @@ export function formatDateRelative(val, roundFunc = Math.round, unit = "auto") {
|
||||
else if (diffInSecs < 60 * 60 * 24 * 365)
|
||||
return rtf.format(
|
||||
-roundFunc(diffInSecs / (60 * 60 * 24 * 30)),
|
||||
"month",
|
||||
"month"
|
||||
);
|
||||
else
|
||||
return rtf.format(
|
||||
-roundFunc(diffInSecs / (60 * 60 * 24 * 365)),
|
||||
"year",
|
||||
"year"
|
||||
);
|
||||
|
||||
default:
|
||||
|
@ -24,7 +24,7 @@ export const throttle = (callback, wait) => {
|
||||
lastFired = Date.now();
|
||||
}
|
||||
},
|
||||
wait - (Date.now() - lastFired),
|
||||
wait - (Date.now() - lastFired)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
@ -110,7 +110,7 @@ const getOrigin = () => {
|
||||
};
|
||||
|
||||
export const exportJsonData = async (
|
||||
filename = "ssr-db-" + new Date().toISOString().replace(/:/g, "_") + ".json",
|
||||
filename = "ssr-db-" + new Date().toISOString().replace(/:/g, "_") + ".json"
|
||||
) => {
|
||||
const inLineKeysRepositories = getInLineKeysRepositories();
|
||||
const outOfLineKeysRepositories = getOutOfLineKeysRepositories();
|
||||
@ -119,7 +119,7 @@ export const exportJsonData = async (
|
||||
await Promise.all(
|
||||
inLineKeysRepositories
|
||||
.map((r) => r.repository)
|
||||
.map(async (repository) => repository().getAll()),
|
||||
.map(async (repository) => repository().getAll())
|
||||
)
|
||||
).reduce(
|
||||
(cum, repositoryData, idx) => {
|
||||
@ -133,7 +133,7 @@ export const exportJsonData = async (
|
||||
version: db.version,
|
||||
exportedOn: new Date(),
|
||||
stores: {},
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
await Promise.all(
|
||||
@ -152,21 +152,21 @@ export const exportJsonData = async (
|
||||
: respositoryValues[idx],
|
||||
},
|
||||
]),
|
||||
[],
|
||||
[]
|
||||
);
|
||||
}),
|
||||
})
|
||||
);
|
||||
|
||||
return download(
|
||||
JSON.stringify(data),
|
||||
filename,
|
||||
"application/json;charset=utf-8;",
|
||||
"application/json;charset=utf-8;"
|
||||
);
|
||||
};
|
||||
|
||||
export const importJsonData = async (json) => {
|
||||
const availableStores = repositories.map((item) =>
|
||||
item.repository().getStoreName(),
|
||||
item.repository().getStoreName()
|
||||
);
|
||||
|
||||
eventBus.publish("dl-manager-pause-cmd");
|
||||
@ -184,7 +184,7 @@ export const importJsonData = async (json) => {
|
||||
}
|
||||
|
||||
const items = json.stores[storeName].map((value) =>
|
||||
castRepositoryItem(value, repositoryItem),
|
||||
castRepositoryItem(value, repositoryItem)
|
||||
);
|
||||
|
||||
const store = tx.objectStore(storeName);
|
||||
@ -209,7 +209,7 @@ function castObjectKeys(
|
||||
value,
|
||||
testKeys,
|
||||
castType = "date",
|
||||
isOutOfLineRepository = false,
|
||||
isOutOfLineRepository = false
|
||||
) {
|
||||
const cast = (v, type = "date") => {
|
||||
switch (type) {
|
||||
@ -225,7 +225,7 @@ function castObjectKeys(
|
||||
const splittedKey = key.split(".");
|
||||
const mainKey = splittedKey.shift();
|
||||
const keys = (!isOutOfLineRepository ? [mainKey] : []).concat(
|
||||
isOutOfLineRepository && !splittedKey.length ? [""] : splittedKey,
|
||||
isOutOfLineRepository && !splittedKey.length ? [""] : splittedKey
|
||||
);
|
||||
|
||||
let valuePart = isOutOfLineRepository ? opt(value, "value") : value;
|
||||
@ -248,7 +248,7 @@ function castObjectKeys(
|
||||
return v.map((innerV) =>
|
||||
keys.length === 1
|
||||
? cast(innerV, castType)
|
||||
: process(innerV, keys.slice(1)),
|
||||
: process(innerV, keys.slice(1))
|
||||
);
|
||||
|
||||
default:
|
||||
@ -279,7 +279,7 @@ const castRepositoryItem = (value, repositoryItem) => {
|
||||
Object.entries(opt(repositoryItem, "casts", {})).forEach(
|
||||
([castType, keys]) => {
|
||||
value = castObjectKeys(value, keys, castType, isOutOfLineRepository);
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
return value;
|
||||
|
@ -3,14 +3,14 @@ import { getCurrentLocale } from "../stores/config";
|
||||
export const substituteVars = (url, vars) =>
|
||||
Object.keys(vars).reduce(
|
||||
(cum, key) => cum.replace(new RegExp("\\${" + key + "}", "gi"), vars[key]),
|
||||
url,
|
||||
url
|
||||
);
|
||||
|
||||
export function formatNumber(
|
||||
num,
|
||||
digits = 2,
|
||||
addSign = false,
|
||||
notANumber = null,
|
||||
notANumber = null
|
||||
) {
|
||||
if (!Number.isFinite(num)) {
|
||||
return notANumber;
|
||||
|
@ -43,7 +43,7 @@ export const opt = (obj, key, defaultValue = undefined) =>
|
||||
.reduce(
|
||||
(o, i) =>
|
||||
o && o[i] !== null && o[i] !== undefined ? o[i] : defaultValue,
|
||||
obj,
|
||||
obj
|
||||
);
|
||||
export const optSet = (obj, key, value, createKeys = true) => {
|
||||
const keys = key.split(".");
|
||||
|
@ -59,7 +59,7 @@ export default {
|
||||
},
|
||||
logOnly: (types) =>
|
||||
(enabledTypes = arrayUnique(
|
||||
enabledTypes.concat(Array.isArray(types) ? types : [types]),
|
||||
enabledTypes.concat(Array.isArray(types) ? types : [types])
|
||||
)),
|
||||
logAll: () => (enabledTypes = []),
|
||||
};
|
||||
|
@ -5,7 +5,7 @@ export const delay = async (time, val, shouldReject = false, signal = null) =>
|
||||
new Promise((resolve, reject) => {
|
||||
const handle = setTimeout(
|
||||
(_) => (shouldReject ? reject(val) : resolve(val)),
|
||||
time,
|
||||
time
|
||||
);
|
||||
|
||||
if (signal && signal.addEventListener)
|
||||
@ -16,6 +16,6 @@ export const delay = async (time, val, shouldReject = false, signal = null) =>
|
||||
|
||||
reject(AbortError());
|
||||
},
|
||||
{ once: true },
|
||||
{ once: true }
|
||||
);
|
||||
});
|
||||
|
@ -3,5 +3,5 @@ export const WEIGHT_COEFFICIENT = 0.965;
|
||||
export const getTotalPpFromSortedPps = (ppArray, startIdx = 0) =>
|
||||
ppArray.reduce(
|
||||
(cum, pp, idx) => cum + Math.pow(WEIGHT_COEFFICIENT, idx + startIdx) * pp,
|
||||
0,
|
||||
0
|
||||
);
|
||||
|
@ -52,7 +52,7 @@ export const getMaxScore = (blocks, maxScorePerBlock = 115) =>
|
||||
(blocks >= 14 ? 8 * maxScorePerBlock * (blocks - 13) : 0) +
|
||||
(blocks >= 6 ? 4 * maxScorePerBlock * (Math.min(blocks, 13) - 5) : 0) +
|
||||
(blocks >= 2 ? 2 * maxScorePerBlock * (Math.min(blocks, 5) - 1) : 0) +
|
||||
Math.min(blocks, 1) * maxScorePerBlock,
|
||||
Math.min(blocks, 1) * maxScorePerBlock
|
||||
);
|
||||
|
||||
export function getFixedLeaderboardMaxScore(leaderboardId, maxScore = null) {
|
||||
@ -64,7 +64,7 @@ export function getFixedLeaderboardMaxScore(leaderboardId, maxScore = null) {
|
||||
export function getAccFromScore(
|
||||
score,
|
||||
maxSongScore = null,
|
||||
percentageInsteadOfAcc = false,
|
||||
percentageInsteadOfAcc = false
|
||||
) {
|
||||
if (!score) return null;
|
||||
|
||||
@ -112,18 +112,18 @@ export function findDiffInfoWithDiffAndTypeFromBeatMaps(diffs, diffAndType) {
|
||||
: diffs.find(
|
||||
(diff) =>
|
||||
diff.characteristic === diffAndType.type &&
|
||||
diff.difficulty === capitalize(diffAndType.diff),
|
||||
diff.difficulty === capitalize(diffAndType.diff)
|
||||
);
|
||||
}
|
||||
|
||||
export function getMaxScoreFromSongCharacteristics(
|
||||
songCharacteristics,
|
||||
diffInfo,
|
||||
maxScorePerBlock = 115,
|
||||
maxScorePerBlock = 115
|
||||
) {
|
||||
const songDiffInfo = findDiffInfoWithDiffAndType(
|
||||
songCharacteristics,
|
||||
diffInfo,
|
||||
diffInfo
|
||||
);
|
||||
|
||||
return songDiffInfo && songDiffInfo.length && songDiffInfo.notes
|
||||
|
@ -20,6 +20,6 @@ export const uuid = (a) => {
|
||||
.replace(
|
||||
// replacing
|
||||
/[018]/g, // zeroes, ones, and eights with
|
||||
uuid, // random hex digits
|
||||
uuid // random hex digits
|
||||
);
|
||||
};
|
||||
|
@ -31,7 +31,7 @@ const getRankedsFromDb = async (refreshCache = false) => {
|
||||
|
||||
const getRankeds = async (refreshCache = false) =>
|
||||
resolvePromiseOrWaitForPending(`rankeds/${refreshCache}`, () =>
|
||||
getRankedsFromDb(),
|
||||
getRankedsFromDb()
|
||||
);
|
||||
|
||||
async function init() {
|
||||
@ -67,14 +67,14 @@ const getRankedScores = async (playerId, withStars = false) => {
|
||||
.map(async (score) => {
|
||||
score = await produce(
|
||||
await produce(score, (draft) => beatmapsEnhancer(draft, true)),
|
||||
(draft) => accEnhancer(draft),
|
||||
(draft) => accEnhancer(draft)
|
||||
);
|
||||
|
||||
return {
|
||||
...score,
|
||||
stars: allRankeds[score?.leaderboardId]?.stars ?? null,
|
||||
};
|
||||
}),
|
||||
})
|
||||
)
|
||||
).filter((s) => s.stars)
|
||||
: scores.filter((score) => score?.score?.pp);
|
||||
@ -92,7 +92,7 @@ const calcPlayerStats = async (playerId) => {
|
||||
const stats = rankedScores
|
||||
.filter(
|
||||
(score) =>
|
||||
(score?.score?.score && score?.score?.maxScore) || score?.score?.acc,
|
||||
(score?.score?.score && score?.score?.maxScore) || score?.score?.acc
|
||||
)
|
||||
.reduce(
|
||||
(cum, s) => {
|
||||
@ -165,7 +165,7 @@ const calcPlayerStats = async (playerId) => {
|
||||
playCount: rankedScores.length,
|
||||
medianAcc: 0,
|
||||
stdDeviation: 0,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
stats.medianAcc =
|
||||
@ -178,8 +178,8 @@ const calcPlayerStats = async (playerId) => {
|
||||
stats.stdDeviation = Math.sqrt(
|
||||
rankedScores.reduce(
|
||||
(sum, s) => sum + Math.pow(stats.avgAcc - s.score.acc, 2),
|
||||
0,
|
||||
) / rankedScores.length,
|
||||
0
|
||||
) / rankedScores.length
|
||||
);
|
||||
|
||||
delete stats.totalAcc;
|
||||
@ -220,7 +220,7 @@ const calcPpBoundary = async (playerId, expectedPp = 1) => {
|
||||
const ppBoundary = calcRawPpAtIdx(
|
||||
rankedScorePps.slice(idx + 1),
|
||||
idx + 1,
|
||||
expectedPp,
|
||||
expectedPp
|
||||
);
|
||||
|
||||
eventBus.publish("player-pp-boundary-calculated", {
|
||||
|
Reference in New Issue
Block a user