cache scoresaber leaderboards
This commit is contained in:
@ -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;
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
/**
|
||||
* The status of the leaderboard.
|
||||
*/
|
||||
export type LeaderboardStatus = "Unranked" | "Ranked" | "Qualified";
|
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;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user