mirror of
https://github.com/ershisan99/www.git
synced 2025-12-17 21:09:22 +00:00
79 lines
2.0 KiB
TypeScript
79 lines
2.0 KiB
TypeScript
import { redis } from '../redis'
|
|
import { neatqueue_service } from './neatqueue.service'
|
|
|
|
export class LeaderboardService {
|
|
private getZSetKey(channel_id: string) {
|
|
return `zset:leaderboard:${channel_id}`
|
|
}
|
|
|
|
private getRawKey(channel_id: string) {
|
|
return `raw:leaderboard:${channel_id}`
|
|
}
|
|
|
|
private getUserKey(user_id: string, channel_id: string) {
|
|
return `user:${user_id}:${channel_id}`
|
|
}
|
|
|
|
async refreshLeaderboard(channel_id: string) {
|
|
try {
|
|
const fresh = await neatqueue_service.get_leaderboard(channel_id)
|
|
const zsetKey = this.getZSetKey(channel_id)
|
|
const rawKey = this.getRawKey(channel_id)
|
|
|
|
const pipeline = redis.pipeline()
|
|
pipeline.setex(rawKey, 180, JSON.stringify(fresh))
|
|
pipeline.del(zsetKey)
|
|
|
|
for (const entry of fresh) {
|
|
pipeline.zadd(zsetKey, entry.mmr, entry.id)
|
|
pipeline.hset(this.getUserKey(entry.id, channel_id), {
|
|
...entry,
|
|
channel_id,
|
|
})
|
|
}
|
|
|
|
pipeline.expire(zsetKey, 180)
|
|
await pipeline.exec()
|
|
|
|
return fresh
|
|
} catch (error) {
|
|
console.error('Error refreshing leaderboard:', error)
|
|
throw error
|
|
}
|
|
}
|
|
|
|
async getLeaderboard(channel_id: string) {
|
|
try {
|
|
const cached = await redis.get(this.getRawKey(channel_id))
|
|
if (cached) return JSON.parse(cached)
|
|
|
|
return await this.refreshLeaderboard(channel_id)
|
|
} catch (error) {
|
|
console.error('Error getting leaderboard:', error)
|
|
throw error
|
|
}
|
|
}
|
|
|
|
async getUserRank(channel_id: string, user_id: string) {
|
|
try {
|
|
const zsetKey = this.getZSetKey(channel_id)
|
|
const rank = await redis.zrevrank(zsetKey, user_id)
|
|
|
|
if (rank === null) return null
|
|
|
|
const userData = await redis.hgetall(this.getUserKey(user_id, channel_id))
|
|
if (!userData) return null
|
|
|
|
return {
|
|
rank: rank + 1,
|
|
...userData,
|
|
mmr: Number(userData.mmr),
|
|
streak: userData.streak,
|
|
}
|
|
} catch (error) {
|
|
console.error('Error getting user rank:', error)
|
|
throw error
|
|
}
|
|
}
|
|
}
|