aboutsummaryrefslogtreecommitdiff
path: root/src/database.ts
diff options
context:
space:
mode:
authormat <27899617+mat-1@users.noreply.github.com>2021-02-28 15:20:44 -0600
committermat <27899617+mat-1@users.noreply.github.com>2021-02-28 15:20:44 -0600
commitd9a7e35f7635c48a928ce362654da094b69c042c (patch)
treeb61b1933722fbf2430dc36dd212d532df5ddb36b /src/database.ts
parent7b1d1cb2c7f1f5a98d4be54396d228ef02028679 (diff)
downloadskyblock-api-d9a7e35f7635c48a928ce362654da094b69c042c.tar.gz
skyblock-api-d9a7e35f7635c48a928ce362654da094b69c042c.tar.bz2
skyblock-api-d9a7e35f7635c48a928ce362654da094b69c042c.zip
instantly update leaderboard when profile is viewed
Diffstat (limited to 'src/database.ts')
-rw-r--r--src/database.ts77
1 files changed, 56 insertions, 21 deletions
diff --git a/src/database.ts b/src/database.ts
index ac0265d..d1ad8e6 100644
--- a/src/database.ts
+++ b/src/database.ts
@@ -9,6 +9,7 @@ import NodeCache from 'node-cache'
import { CleanMember } from './cleaners/skyblock/member'
import { CleanPlayer } from './cleaners/player'
import { shuffle } from './util'
+import { CleanFullProfile } from './cleaners/skyblock/profile'
// don't update the user for 3 minutes
const recentlyUpdated = new NodeCache({
@@ -28,7 +29,8 @@ interface LeaderboardItem {
value: number
}
-const cachedLeaderboards: Map<string, any> = new Map()
+const cachedRawLeaderboards: Map<string, DatabaseLeaderboardItem[]> = new Map()
+const cachedLeaderboards: Map<string, LeaderboardItem[]> = new Map()
const leaderboardMax = 100
@@ -89,9 +91,9 @@ async function fetchAllMemberLeaderboardAttributes(): Promise<string[]> {
]
}
-export async function fetchMemberLeaderboard(name: string) {
- if (cachedLeaderboards.has(name))
- return cachedLeaderboards.get(name)
+async function fetchMemberLeaderboardRaw(name: string): Promise<DatabaseLeaderboardItem[]> {
+ if (cachedRawLeaderboards.has(name))
+ return cachedRawLeaderboards.get(name)
// typescript forces us to make a new variable and set it this way because it gives an error otherwise
const query = {}
query[`stats.${name}`] = { '$exists': true }
@@ -99,8 +101,16 @@ export async function fetchMemberLeaderboard(name: string) {
const sortQuery: any = {}
sortQuery[`stats.${name}`] = -1
-
const leaderboardRaw = await memberLeaderboardsCollection.find(query).sort(sortQuery).limit(leaderboardMax).toArray()
+ cachedRawLeaderboards.set(name, leaderboardRaw)
+ return leaderboardRaw
+}
+
+export async function fetchMemberLeaderboard(name: string) {
+ if (cachedLeaderboards.has(name))
+ return cachedLeaderboards.get(name)
+
+ const leaderboardRaw = await fetchMemberLeaderboardRaw(name)
const fetchLeaderboardPlayer = async(item: DatabaseLeaderboardItem): Promise<LeaderboardItem> => {
return {
player: await cached.fetchPlayer(item.uuid),
@@ -117,51 +127,75 @@ export async function fetchMemberLeaderboard(name: string) {
}
async function getMemberLeaderboardRequirement(name: string): Promise<number> {
- const leaderboard = await fetchMemberLeaderboard(name)
+ const leaderboard = await fetchMemberLeaderboardRaw(name)
// if there's more than 100 items, return the 100th. if there's less, return null
if (leaderboard.length >= leaderboardMax)
- return leaderboard[leaderboardMax - 1].value
+ return leaderboard[leaderboardMax - 1].stats[name]
else
return null
}
/** Get the attributes for the member, but only ones that would put them on the top 100 for leaderboards */
-async function getApplicableAttributes(member) {
+async function getApplicableAttributes(member): Promise<{ [key: string]: number }> {
const leaderboardAttributes = getMemberLeaderboardAttributes(member)
- const applicableAttributes = []
+ const applicableAttributes = {}
for (const [ attributeName, attributeValue ] of Object.entries(leaderboardAttributes)) {
const requirement = await getMemberLeaderboardRequirement(attributeName)
if (!requirement || attributeValue > requirement)
applicableAttributes[attributeName] = attributeValue
}
+ return applicableAttributes
}
/** Update the member's leaderboard data on the server if applicable */
-export async function updateDatabaseMember(member: CleanMember) {
+export async function updateDatabaseMember(member: CleanMember, profile: CleanFullProfile) {
if (!client) return // the db client hasn't been initialized
// the member's been updated too recently, just return
- if (recentlyUpdated.get(member.uuid))
+ if (recentlyUpdated.get(profile.uuid + member.uuid))
return
// store the member in recentlyUpdated so it cant update for 3 more minutes
- recentlyUpdated.set(member.uuid, true)
+ recentlyUpdated.set(profile.uuid + member.uuid, true)
await constants.addStats(Object.keys(member.rawHypixelStats))
await constants.addCollections(member.collections.map(value => value.name))
-
const leaderboardAttributes = await getApplicableAttributes(member)
await memberLeaderboardsCollection.updateOne(
+ { uuid: member.uuid },
{
- uuid: member.uuid
- }, {
'$set': {
- 'stats': leaderboardAttributes,
- 'last_updated': new Date()
+ stats: leaderboardAttributes,
+ last_updated: new Date()
}
- }, {
- upsert: true
- }
+ },
+ { upsert: true }
)
+
+ for (const [ attributeName, attributeValue ] of Object.entries(leaderboardAttributes)) {
+ const existingLeaderboard = await fetchMemberLeaderboard(attributeName)
+ const existingRawLeaderboard = await fetchMemberLeaderboardRaw(attributeName)
+ const newLeaderboard = existingLeaderboard
+ // remove the player from the leaderboard, if they're there
+ .filter(value => value.player.uuid !== member.uuid)
+ .concat([{
+ player: await cached.fetchPlayer(member.uuid),
+ value: attributeValue
+ }])
+ .sort((a, b) => b.value - a.value)
+ .slice(0, 100)
+ const newRawLeaderboard = existingRawLeaderboard
+ // remove the player from the leaderboard, if they're there
+ .filter(value => value.uuid !== member.uuid)
+ .concat([{
+ last_updated: new Date(),
+ stats: leaderboardAttributes,
+ uuid: member.uuid
+ }])
+ .sort((a, b) => b.stats[attributeName] - a.stats[attributeName])
+ .slice(0, 100)
+ cachedLeaderboards.set(attributeName, newLeaderboard)
+ cachedRawLeaderboards.set(attributeName, newRawLeaderboard)
+ }
}
@@ -193,4 +227,5 @@ async function removeBadMemberLeaderboardAttributes() {
connect()
- .then(removeBadMemberLeaderboardAttributes) \ No newline at end of file
+ .then(removeBadMemberLeaderboardAttributes)
+