import {Injectable} from '@angular/core'; import {GamesApi} from "../api/GamesApi"; import {HttpClient} from "@angular/common/http"; import {distinct, map, Observable} from "rxjs"; import {DetectedGameDto} from "../models/dtos/DetectedGameDto"; import {GameOverviewDto} from "../models/dtos/GameOverviewDto"; import {GenreDto} from "../models/dtos/GenreDto"; import {ThemeDto} from "../models/dtos/ThemeDto"; import {CompanyDto} from "../models/dtos/CompanyDto"; import {PlayerPerspectiveDto} from "../models/dtos/PlayerPerspectiveDto"; @Injectable({ providedIn: 'root' }) export class GamesService implements GamesApi { private readonly apiPath = '/games'; private cache: Map = new Map(); constructor(private http: HttpClient) { } getAllGames(forceReloadFromServer: boolean = false): Observable { if (this.cache.size === 0 || forceReloadFromServer) { let gamesObservable: Observable = this.http.get(this.apiPath).pipe(map(games => games.sort((g1, g2) => g1.title.localeCompare(g2.title)))); gamesObservable.subscribe(g => this.cacheGames(g)); return gamesObservable; } return new Observable(subscriber => { subscriber.next(Array.from(this.cache.values())); subscriber.complete(); }); } getGame(slug: string): Observable { if (this.cache.has(slug)) { return new Observable(subscriber => { subscriber.next(this.cache.get(slug)); subscriber.complete(); }); } return this.http.get(`${this.apiPath}/game/${slug}`); } // TODO: This method of removing duplicates is most certainly an anti-pattern in RxJS // TODO: However, I did not get the 'distinct()' pipe to work properly, so I have to take another look in the future getAvailableGenres(): Observable { return this.getAllGames().pipe( map( games => { let availableGenresMap: Map = new Map; games.map(game => game.genres === undefined ? [] : game.genres).flat().forEach(genre => availableGenresMap.set(genre.slug, genre)); return Array.from(availableGenresMap.values()).sort((g1, g2) => g1.name.localeCompare(g2.name)); } ) ); } // TODO: This method of removing duplicates is most certainly an anti-pattern in RxJS // TODO: However, I did not get the 'distinct()' pipe to work properly, so I have to take another look in the future getAvailableThemes(): Observable { return this.getAllGames().pipe( map( games => { let availableThemesMap: Map = new Map; games.map(game => game.themes === undefined ? [] : game.themes).flat().forEach(theme => availableThemesMap.set(theme.slug, theme)); return Array.from(availableThemesMap.values()).sort((t1, t2) => t1.name.localeCompare(t2.name)); } ) ); } // TODO: This method of removing duplicates is most certainly an anti-pattern in RxJS // TODO: However, I did not get the 'distinct()' pipe to work properly, so I have to take another look in the future getAvailablePlayerPerspectives(): Observable { return this.getAllGames().pipe( map( games => { let availablePlayerPerspectivesMap: Map = new Map; games.map(game => game.playerPerspectives === undefined ? [] : game.playerPerspectives).flat().forEach(playerPerspective => availablePlayerPerspectivesMap.set(playerPerspective.slug, playerPerspective)); return Array.from(availablePlayerPerspectivesMap.values()).sort((t1, t2) => t1.name.localeCompare(t2.name)); } ) ); } downloadGame(slug: String): void { window.open(`v1${this.apiPath}/game/${slug}/download`, '_top'); } refreshGame(slug: String): Observable { return this.http.get(`${this.apiPath}/game/${slug}/refresh`); } getGameOverviews(): Observable { return this.http.get(`${this.apiPath}/game-overviews`); } getAllGameMappings(): Observable> { return this.http.get>(`${this.apiPath}/game-mappings`); } removeGameFromCache(slug: string): void { this.cache.delete(slug); } private cacheGames(gameList: DetectedGameDto[]): void { this.cache.clear(); gameList.forEach(game => this.cache.set(game.slug, game)); } }