LETS GO BABY
This commit is contained in:
126
projects/backend/src/service/player.service.ts
Normal file
126
projects/backend/src/service/player.service.ts
Normal file
@ -0,0 +1,126 @@
|
||||
import { PlayerDocument, PlayerModel } from "../model/player";
|
||||
import { NotFoundError } from "../error/not-found-error";
|
||||
import { cron } from "@elysiajs/cron";
|
||||
import { app } from "../index";
|
||||
import { getDaysAgoDate, getMidnightAlignedDate } from "@ssr/common/utils/time-utils";
|
||||
import { scoresaberService } from "@ssr/common/service/impl/scoresaber";
|
||||
import ScoreSaberPlayerToken from "@ssr/common/types/token/scoresaber/score-saber-player-token";
|
||||
|
||||
export class PlayerService {
|
||||
/**
|
||||
* Initialize the cron jobs
|
||||
*/
|
||||
public static initCronjobs() {
|
||||
app.use(
|
||||
cron({
|
||||
name: "player-statistics-tracker-cron",
|
||||
pattern: "0 1 * * *", // Every day at 00:01 (midnight)
|
||||
run: async () => {
|
||||
const players: PlayerDocument[] = await PlayerModel.find({});
|
||||
for (const player of players) {
|
||||
await PlayerService.trackScoreSaberPlayer(getMidnightAlignedDate(new Date()), player);
|
||||
}
|
||||
},
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a player from the database.
|
||||
*
|
||||
* @param id the player to fetch
|
||||
* @param create if true, create the player if it doesn't exist
|
||||
* @returns the player
|
||||
* @throws NotFoundError if the player is not found
|
||||
*/
|
||||
public static async getPlayer(id: string, create: boolean = false): Promise<PlayerDocument> {
|
||||
console.log(`Fetching player "${id}"...`);
|
||||
let player: PlayerDocument | null = await PlayerModel.findById(id);
|
||||
if (player === null && !create) {
|
||||
console.log(`Player "${id}" not found.`);
|
||||
throw new NotFoundError(`Player "${id}" not found`);
|
||||
}
|
||||
if (player === null) {
|
||||
const playerToken = await scoresaberService.lookupPlayer(id);
|
||||
if (playerToken === undefined) {
|
||||
throw new NotFoundError(`Player "${id}" not found`);
|
||||
}
|
||||
|
||||
console.log(`Creating player "${id}"...`);
|
||||
player = (await PlayerModel.create({ _id: id })) as any;
|
||||
if (player === null) {
|
||||
throw new NotFoundError(`Player "${id}" not found`);
|
||||
}
|
||||
await this.seedPlayerHistory(player, playerToken);
|
||||
console.log(`Created player "${id}".`);
|
||||
} else {
|
||||
console.log(`Found player "${id}".`);
|
||||
}
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Seeds the player's history using data from
|
||||
* the ScoreSaber API.
|
||||
*
|
||||
* @param player the player to seed
|
||||
* @param playerToken the SoreSaber player token
|
||||
*/
|
||||
public static async seedPlayerHistory(player: PlayerDocument, playerToken: ScoreSaberPlayerToken): Promise<void> {
|
||||
// Loop through rankHistory in reverse, from current day backwards
|
||||
const playerRankHistory = playerToken.histories.split(",").map((value: string) => {
|
||||
return parseInt(value);
|
||||
});
|
||||
playerRankHistory.push(playerToken.rank);
|
||||
|
||||
let daysAgo = 1; // Start from yesterday
|
||||
for (let i = playerRankHistory.length - daysAgo - 1; i >= 0; i--) {
|
||||
const rank = playerRankHistory[i];
|
||||
const date = getMidnightAlignedDate(getDaysAgoDate(daysAgo));
|
||||
player.setStatisticHistory(date, {
|
||||
rank: rank,
|
||||
});
|
||||
daysAgo += 1; // Increment daysAgo for each earlier rank
|
||||
}
|
||||
await player.save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tracks a players statistics
|
||||
*
|
||||
* @param dateToday the date to track
|
||||
* @param foundPlayer the player to track
|
||||
*/
|
||||
public static async trackScoreSaberPlayer(dateToday: Date, foundPlayer: PlayerDocument) {
|
||||
const player = await scoresaberService.lookupPlayer(foundPlayer.id);
|
||||
if (player == undefined) {
|
||||
console.log(`Player "${foundPlayer.id}" not found on ScoreSaber`);
|
||||
return;
|
||||
}
|
||||
if (player.inactive) {
|
||||
console.log(`Player "${foundPlayer.id}" is inactive on ScoreSaber`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Seed the history with ScoreSaber data if no history exists
|
||||
if (foundPlayer.getDaysTracked() === 0) {
|
||||
await this.seedPlayerHistory(foundPlayer, player);
|
||||
}
|
||||
|
||||
// Update current day's statistics
|
||||
let history = foundPlayer.getHistoryByDate(dateToday);
|
||||
if (history == undefined) {
|
||||
history = {}; // Initialize if history is not found
|
||||
}
|
||||
// Set the history data
|
||||
history.pp = player.pp;
|
||||
history.countryRank = player.countryRank;
|
||||
history.rank = player.rank;
|
||||
foundPlayer.setStatisticHistory(dateToday, history);
|
||||
foundPlayer.sortStatisticHistory();
|
||||
foundPlayer.lastTracked = new Date();
|
||||
await foundPlayer.save();
|
||||
|
||||
console.log(`Tracked player "${foundPlayer.id}"!`);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user