Optimize pakubiiti player state
Add cleanup, if user identified with session token hasn't interacted with the game in 24h Store the the previously separate AlbumState inside PlayerState as well. This means it's better connected to the actual player and will also be cleaned up
This commit is contained in:
parent
94b659b1f0
commit
d882c670ed
5 changed files with 100 additions and 101 deletions
|
@ -1,45 +0,0 @@
|
|||
import type { AlbumSolveState } from '$lib/types';
|
||||
|
||||
class AlbumState {
|
||||
private albums: AlbumSolveState[] | undefined = undefined;
|
||||
|
||||
setAlbums(data: AlbumSolveState[]) {
|
||||
if (!data) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.albums = data;
|
||||
}
|
||||
|
||||
checkSolve(data: AlbumSolveState[]) {
|
||||
if (!data || !this.albums) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const solve of data) {
|
||||
const search = this.albums.filter((album) => album.name === solve.name);
|
||||
|
||||
if (!search) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const matching = search.at(0);
|
||||
|
||||
if (!matching) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (matching.image !== solve.image) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (matching.artists !== solve.artists) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export const albumState = new AlbumState();
|
|
@ -1,90 +1,139 @@
|
|||
import type { Player } from '$lib/types';
|
||||
import type { AlbumSolveState, Player } from '$lib/types';
|
||||
|
||||
export class PlayerState {
|
||||
players = $state<Player[]>([]);
|
||||
private lastAccessed: Map<string, number> = new Map();
|
||||
|
||||
newPlayer(id: string) {
|
||||
this.players.push({ id: id, stage: 0, highscore: 0, playing: true });
|
||||
constructor() {
|
||||
// Clean up expired sessions every hour
|
||||
setInterval(() => this.cleanup(), 1000 * 60 * 60);
|
||||
}
|
||||
|
||||
getStage(id: string) {
|
||||
const player = this.players.find((player) => player.id === id);
|
||||
private updateLastAccessed(id: string) {
|
||||
this.lastAccessed.set(id, Date.now());
|
||||
}
|
||||
|
||||
if (!player) {
|
||||
return undefined;
|
||||
private findPlayer(id: string): Player | undefined {
|
||||
this.updateLastAccessed(id);
|
||||
return this.players.find((player) => player.id === id);
|
||||
}
|
||||
|
||||
private checkSolution(solution: AlbumSolveState[], submission: AlbumSolveState[]) {
|
||||
if (!solution || !submission) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return player.stage;
|
||||
for (const solve of solution) {
|
||||
const search = submission.filter((album) => album.name === solve.name);
|
||||
|
||||
if (!search) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const matching = search.at(0);
|
||||
|
||||
if (!matching) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (matching.image !== solve.image) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (matching.artists !== solve.artists) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
newPlayer(id: string) {
|
||||
this.updateLastAccessed(id);
|
||||
this.players.push({ id: id, stage: 0, highscore: 0, playing: true, albums: [] });
|
||||
}
|
||||
|
||||
nextStage(id: string) {
|
||||
const player = this.players.find((player) => player.id === id);
|
||||
|
||||
if (!player) {
|
||||
return;
|
||||
const player = this.findPlayer(id);
|
||||
if (player) {
|
||||
player.stage += 1;
|
||||
}
|
||||
|
||||
player.stage += 1;
|
||||
}
|
||||
|
||||
restart(id: string) {
|
||||
const player = this.players.find((player) => player.id === id);
|
||||
|
||||
if (!player) {
|
||||
return;
|
||||
const player = this.findPlayer(id);
|
||||
if (player) {
|
||||
player.stage = 0;
|
||||
player.playing = true;
|
||||
}
|
||||
|
||||
player.stage = 0;
|
||||
player.playing = true;
|
||||
}
|
||||
|
||||
score(id: string, won: boolean) {
|
||||
const player = this.players.find((player) => player.id === id);
|
||||
score(id: string, submission: AlbumSolveState[]) {
|
||||
if (!submission) return false;
|
||||
|
||||
if (!player) {
|
||||
return;
|
||||
}
|
||||
const player = this.findPlayer(id);
|
||||
if (!player) return false;
|
||||
|
||||
if (won) {
|
||||
if (this.checkSolution(player.albums, submission)) {
|
||||
player.stage += 1;
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
player.playing = false;
|
||||
|
||||
if (player.stage > player.highscore) {
|
||||
player.highscore = player.stage;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
getHighscore(id: string) {
|
||||
const player = this.players.find((player) => player.id === id);
|
||||
const player = this.findPlayer(id);
|
||||
return player?.highscore;
|
||||
}
|
||||
|
||||
if (!player) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return player.highscore;
|
||||
getStage(id: string) {
|
||||
const player = this.findPlayer(id);
|
||||
return player?.stage;
|
||||
}
|
||||
|
||||
getPlaying(id: string) {
|
||||
const player = this.players.find((player) => player.id === id);
|
||||
|
||||
if (!player) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return player.playing;
|
||||
const player = this.findPlayer(id);
|
||||
return player?.playing;
|
||||
}
|
||||
|
||||
setPlaying(id: string, playing: boolean) {
|
||||
const player = this.players.find((player) => player.id === id);
|
||||
|
||||
if (!player) {
|
||||
return;
|
||||
const player = this.findPlayer(id);
|
||||
if (player) {
|
||||
player.playing = playing;
|
||||
}
|
||||
}
|
||||
|
||||
player.playing = playing;
|
||||
getAlbums(id: string) {
|
||||
const player = this.findPlayer(id);
|
||||
return player?.albums;
|
||||
}
|
||||
|
||||
setAlbums(id: string, albums: AlbumSolveState[]) {
|
||||
const player = this.findPlayer(id);
|
||||
if (player) {
|
||||
player.albums = albums;
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up players that haven't been accessed in 24 hours
|
||||
private cleanup(): void {
|
||||
const now = Date.now();
|
||||
const expiryTime = 24 * 60 * 60 * 1000; // 24 hours
|
||||
|
||||
this.players = this.players.filter((player) => {
|
||||
const lastAccess = this.lastAccessed.get(player.id);
|
||||
if (!lastAccess || now - lastAccess > expiryTime) {
|
||||
this.lastAccessed.delete(player.id);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@ export type Player = {
|
|||
stage: number;
|
||||
highscore: number;
|
||||
playing: boolean;
|
||||
albums: AlbumSolveState[];
|
||||
};
|
||||
|
||||
export interface TimeRemaining {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import type { AlbumSolveState } from '$lib/types';
|
||||
|
||||
import { error, json } from '@sveltejs/kit';
|
||||
import { albumState } from '$lib/server/pakubiiti/AlbumState.svelte';
|
||||
import { spotifyAPI } from '$lib/server/pakubiiti/Spotify.svelte';
|
||||
|
||||
const maxTries = 10;
|
||||
|
@ -30,12 +29,8 @@ export async function GET({ params }) {
|
|||
}
|
||||
|
||||
if (albums.length !== count) {
|
||||
albumState.setAlbums([]);
|
||||
|
||||
return error(500, "Couldn't get albums from Spotify.");
|
||||
}
|
||||
|
||||
albumState.setAlbums(albums);
|
||||
|
||||
return json({ albums: albums });
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ import type { AlbumSolveState } from '$lib/types';
|
|||
import { nanoid } from 'nanoid';
|
||||
import { shuffleArray } from '$lib/utils';
|
||||
|
||||
import { albumState } from '$lib/server/pakubiiti/AlbumState.svelte';
|
||||
import { playerState } from '$lib/server/pakubiiti/PlayerState.svelte';
|
||||
import { ratelimit } from '$lib/server/redis';
|
||||
|
||||
|
@ -92,6 +91,8 @@ export const load: PageServerLoad = async (event) => {
|
|||
value: album.artists
|
||||
}));
|
||||
|
||||
playerState.setAlbums(user, data.albums);
|
||||
|
||||
return {
|
||||
names: shuffleArray(albumNames),
|
||||
images: shuffleArray(albumImages),
|
||||
|
@ -133,9 +134,7 @@ export const actions = {
|
|||
state.push({ name: name, image: image, artists: artists });
|
||||
}
|
||||
|
||||
const solved = albumState.checkSolve(state);
|
||||
|
||||
playerState.score(user, solved);
|
||||
const solved = playerState.score(user, state);
|
||||
|
||||
return { solved: solved };
|
||||
},
|
||||
|
|
Loading…
Add table
Reference in a new issue