cache scoresaber leaderboards
This commit is contained in:
@ -1,29 +0,0 @@
|
||||
import Leaderboard from "../leaderboard";
|
||||
import { LeaderboardStatus } from "../leaderboard-status";
|
||||
|
||||
export default interface ScoreSaberLeaderboard extends Leaderboard {
|
||||
/**
|
||||
* The star count for the leaderboard.
|
||||
*/
|
||||
readonly stars: number;
|
||||
|
||||
/**
|
||||
* The total amount of plays.
|
||||
*/
|
||||
readonly plays: number;
|
||||
|
||||
/**
|
||||
* The amount of plays today.
|
||||
*/
|
||||
readonly dailyPlays: number;
|
||||
|
||||
/**
|
||||
* Whether this leaderboard is qualified to be ranked.
|
||||
*/
|
||||
readonly qualified: boolean;
|
||||
|
||||
/**
|
||||
* The status of the map.
|
||||
*/
|
||||
readonly status: LeaderboardStatus;
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
import { MapDifficulty } from "../score/map-difficulty";
|
||||
import { MapCharacteristic } from "../types/map-characteristic";
|
||||
|
||||
export default interface LeaderboardDifficulty {
|
||||
/**
|
||||
* The id of the leaderboard.
|
||||
*/
|
||||
leaderboardId: number;
|
||||
|
||||
/**
|
||||
* The difficulty of the leaderboard.
|
||||
*/
|
||||
difficulty: MapDifficulty;
|
||||
|
||||
/**
|
||||
* The characteristic of the leaderboard.
|
||||
*/
|
||||
characteristic: MapCharacteristic;
|
||||
|
||||
/**
|
||||
* The raw difficulty of the leaderboard.
|
||||
*/
|
||||
difficultyRaw: string;
|
||||
}
|
@ -1,75 +0,0 @@
|
||||
import LeaderboardDifficulty from "./leaderboard-difficulty";
|
||||
|
||||
export default interface Leaderboard {
|
||||
/**
|
||||
* The id of the leaderboard.
|
||||
* @private
|
||||
*/
|
||||
readonly id: number;
|
||||
|
||||
/**
|
||||
* The hash of the song this leaderboard is for.
|
||||
* @private
|
||||
*/
|
||||
readonly songHash: string;
|
||||
|
||||
/**
|
||||
* The name of the song this leaderboard is for.
|
||||
* @private
|
||||
*/
|
||||
readonly songName: string;
|
||||
|
||||
/**
|
||||
* The sub name of the leaderboard.
|
||||
* @private
|
||||
*/
|
||||
readonly songSubName: string;
|
||||
|
||||
/**
|
||||
* The author of the song this leaderboard is for.
|
||||
* @private
|
||||
*/
|
||||
readonly songAuthorName: string;
|
||||
|
||||
/**
|
||||
* The author of the level this leaderboard is for.
|
||||
* @private
|
||||
*/
|
||||
readonly levelAuthorName: string;
|
||||
|
||||
/**
|
||||
* The difficulty of the leaderboard.
|
||||
* @private
|
||||
*/
|
||||
readonly difficulty: LeaderboardDifficulty;
|
||||
|
||||
/**
|
||||
* The difficulties of the leaderboard.
|
||||
* @private
|
||||
*/
|
||||
readonly difficulties: LeaderboardDifficulty[];
|
||||
|
||||
/**
|
||||
* The maximum score of the leaderboard.
|
||||
* @private
|
||||
*/
|
||||
readonly maxScore: number;
|
||||
|
||||
/**
|
||||
* Whether the leaderboard is ranked.
|
||||
* @private
|
||||
*/
|
||||
readonly ranked: boolean;
|
||||
|
||||
/**
|
||||
* The link to the song art.
|
||||
* @private
|
||||
*/
|
||||
readonly songArt: string;
|
||||
|
||||
/**
|
||||
* The date the leaderboard was created.
|
||||
* @private
|
||||
*/
|
||||
readonly timestamp: Date;
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
import Leaderboard from "../leaderboard";
|
||||
import { type LeaderboardStatus } from "../leaderboard-status";
|
||||
import { getModelForClass, modelOptions, Prop, ReturnModelType, Severity } from "@typegoose/typegoose";
|
||||
import { Document } from "mongoose";
|
||||
|
||||
@modelOptions({
|
||||
options: { allowMixed: Severity.ALLOW },
|
||||
schemaOptions: {
|
||||
collection: "scoresaber-leaderboards",
|
||||
toObject: {
|
||||
virtuals: true,
|
||||
transform: function (_, ret) {
|
||||
ret.id = ret._id;
|
||||
delete ret._id;
|
||||
delete ret.__v;
|
||||
return ret;
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
export default class ScoreSaberLeaderboard extends Leaderboard {
|
||||
/**
|
||||
* The star count for the leaderboard.
|
||||
*/
|
||||
@Prop({ required: true })
|
||||
readonly stars!: number;
|
||||
|
||||
/**
|
||||
* The total amount of plays.
|
||||
*/
|
||||
@Prop({ required: true })
|
||||
readonly plays!: number;
|
||||
|
||||
/**
|
||||
* The amount of plays today.
|
||||
*/
|
||||
@Prop({ required: true })
|
||||
readonly dailyPlays!: number;
|
||||
|
||||
/**
|
||||
* Whether this leaderboard is qualified to be ranked.
|
||||
*/
|
||||
@Prop({ required: true })
|
||||
readonly qualified!: boolean;
|
||||
|
||||
/**
|
||||
* The status of the map.
|
||||
*/
|
||||
@Prop({ required: true })
|
||||
readonly status!: LeaderboardStatus;
|
||||
}
|
||||
|
||||
export type ScoreSaberLeaderboardDocument = ScoreSaberLeaderboard & Document;
|
||||
export const ScoreSaberLeaderboardModel: ReturnModelType<typeof ScoreSaberLeaderboard> =
|
||||
getModelForClass(ScoreSaberLeaderboard);
|
@ -0,0 +1,29 @@
|
||||
import { type MapDifficulty } from "../../score/map-difficulty";
|
||||
import { type MapCharacteristic } from "../../types/map-characteristic";
|
||||
import { Prop } from "@typegoose/typegoose";
|
||||
|
||||
export default class LeaderboardDifficulty {
|
||||
/**
|
||||
* The id of the leaderboard.
|
||||
*/
|
||||
@Prop({ required: true })
|
||||
leaderboardId!: number;
|
||||
|
||||
/**
|
||||
* The difficulty of the leaderboard.
|
||||
*/
|
||||
@Prop({ required: true })
|
||||
difficulty!: MapDifficulty;
|
||||
|
||||
/**
|
||||
* The characteristic of the leaderboard.
|
||||
*/
|
||||
@Prop({ required: true })
|
||||
characteristic!: MapCharacteristic;
|
||||
|
||||
/**
|
||||
* The raw difficulty of the leaderboard.
|
||||
*/
|
||||
@Prop({ required: true })
|
||||
difficultyRaw!: string;
|
||||
}
|
112
projects/common/src/model/leaderboard/leaderboard.ts
Normal file
112
projects/common/src/model/leaderboard/leaderboard.ts
Normal file
@ -0,0 +1,112 @@
|
||||
import LeaderboardDifficulty from "./leaderboard-difficulty";
|
||||
import { Prop } from "@typegoose/typegoose";
|
||||
|
||||
export default class Leaderboard {
|
||||
/**
|
||||
* The id of the leaderboard.
|
||||
* @private
|
||||
*/
|
||||
@Prop({ required: true })
|
||||
private readonly _id!: number;
|
||||
|
||||
/**
|
||||
* The hash of the song this leaderboard is for.
|
||||
* @private
|
||||
*/
|
||||
@Prop({ required: true })
|
||||
readonly songHash!: string;
|
||||
|
||||
/**
|
||||
* The name of the song this leaderboard is for.
|
||||
* @private
|
||||
*/
|
||||
@Prop({ required: true })
|
||||
readonly songName!: string;
|
||||
|
||||
/**
|
||||
* The sub name of the leaderboard.
|
||||
* @private
|
||||
*/
|
||||
@Prop({ required: true })
|
||||
readonly songSubName!: string;
|
||||
|
||||
/**
|
||||
* The author of the song this leaderboard is for.
|
||||
* @private
|
||||
*/
|
||||
@Prop({ required: true })
|
||||
readonly songAuthorName!: string;
|
||||
|
||||
/**
|
||||
* The author of the level this leaderboard is for.
|
||||
* @private
|
||||
*/
|
||||
@Prop({ required: true })
|
||||
readonly levelAuthorName!: string;
|
||||
|
||||
/**
|
||||
* The difficulty of the leaderboard.
|
||||
* @private
|
||||
*/
|
||||
@Prop({ required: true, _id: false, type: () => LeaderboardDifficulty })
|
||||
readonly difficulty!: LeaderboardDifficulty;
|
||||
|
||||
/**
|
||||
* The difficulties of the leaderboard.
|
||||
* @private
|
||||
*/
|
||||
@Prop({ required: true, _id: false, type: () => [LeaderboardDifficulty] })
|
||||
readonly difficulties!: LeaderboardDifficulty[];
|
||||
|
||||
/**
|
||||
* The maximum score of the leaderboard.
|
||||
* @private
|
||||
*/
|
||||
@Prop({ required: true })
|
||||
readonly maxScore!: number;
|
||||
|
||||
/**
|
||||
* Whether the leaderboard is ranked.
|
||||
* @private
|
||||
*/
|
||||
@Prop({ required: true })
|
||||
readonly ranked!: boolean;
|
||||
|
||||
/**
|
||||
* The link to the song art.
|
||||
* @private
|
||||
*/
|
||||
@Prop({ required: true })
|
||||
readonly songArt!: string;
|
||||
|
||||
/**
|
||||
* The date the leaderboard was created.
|
||||
* @private
|
||||
*/
|
||||
@Prop({ required: true })
|
||||
readonly timestamp!: Date;
|
||||
|
||||
/**
|
||||
* The date the leaderboard was last refreshed.
|
||||
* @private
|
||||
*/
|
||||
@Prop({ required: true })
|
||||
lastRefreshed?: Date;
|
||||
|
||||
/**
|
||||
* Should the map data be refreshed?
|
||||
*
|
||||
* @returns true if the map data should be refreshed
|
||||
*/
|
||||
public shouldRefresh(): boolean {
|
||||
if (!this.lastRefreshed) {
|
||||
return true;
|
||||
}
|
||||
const now = new Date();
|
||||
return now.getTime() - this.lastRefreshed.getTime() > 1000 * 60 * 60 * 24; // 1 day
|
||||
}
|
||||
|
||||
get id(): number {
|
||||
return this._id;
|
||||
}
|
||||
}
|
@ -44,7 +44,7 @@ export class ScoreSaberScoreInternal extends Score {
|
||||
* @private
|
||||
*/
|
||||
@Prop({ required: true })
|
||||
public readonly pp!: number;
|
||||
public pp!: number;
|
||||
|
||||
/**
|
||||
* The weight of the score, or undefined if not ranked.
|
||||
|
@ -1,9 +1,9 @@
|
||||
import ScoreSaberLeaderboard from "./leaderboard/impl/scoresaber-leaderboard";
|
||||
import ScoreSaberLeaderboard from "./model/leaderboard/impl/scoresaber-leaderboard";
|
||||
import ScoreSaberLeaderboardToken from "./types/token/scoresaber/score-saber-leaderboard-token";
|
||||
import LeaderboardDifficulty from "./leaderboard/leaderboard-difficulty";
|
||||
import LeaderboardDifficulty from "./model/leaderboard/leaderboard-difficulty";
|
||||
import { getDifficultyFromScoreSaberDifficulty } from "./utils/scoresaber-utils";
|
||||
import { MapCharacteristic } from "./types/map-characteristic";
|
||||
import { LeaderboardStatus } from "./leaderboard/leaderboard-status";
|
||||
import { LeaderboardStatus } from "./model/leaderboard/leaderboard-status";
|
||||
import { formatDateMinimal, getDaysAgoDate, getMidnightAlignedDate, parseDate } from "./utils/time-utils";
|
||||
import ScoreSaberPlayerToken from "./types/token/scoresaber/score-saber-player-token";
|
||||
import ScoreSaberPlayer, { ScoreSaberBadge, ScoreSaberBio } from "./player/impl/scoresaber-player";
|
||||
|
@ -18,4 +18,9 @@ export type AppStatistics = {
|
||||
* The amount of cached BeatSaver maps.
|
||||
*/
|
||||
cachedBeatSaverMaps: number;
|
||||
|
||||
/**
|
||||
* The amount of cached ScoreSaber leaderboards.
|
||||
*/
|
||||
cachedScoreSaberLeaderboards: number;
|
||||
};
|
||||
|
@ -7,7 +7,7 @@ import LeaderboardScoresResponse from "../response/leaderboard-scores-response";
|
||||
import { Page } from "../pagination";
|
||||
import { ScoreSaberScore } from "src/model/score/impl/scoresaber-score";
|
||||
import { PlayerScore } from "../score/player-score";
|
||||
import ScoreSaberLeaderboard from "../leaderboard/impl/scoresaber-leaderboard";
|
||||
import ScoreSaberLeaderboard from "../model/leaderboard/impl/scoresaber-leaderboard";
|
||||
|
||||
/**
|
||||
* Fetches the player's scores
|
||||
|
Reference in New Issue
Block a user