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