nise/nise-frontend/src/app/view-suspicious-scores/view-suspicious-scores.component.ts

194 lines
5.6 KiB
TypeScript
Raw Normal View History

2024-02-14 16:43:11 +00:00
import {Component, OnDestroy, OnInit} from '@angular/core';
import {environment} from "../../environments/environment";
import {SuspiciousScore} from "../replays";
import {Observable, Subscription, timer} from 'rxjs';
import {LocalCacheService} from "../../corelib/service/local-cache.service";
import {ActivatedRoute, Router, RouterLink} from "@angular/router";
2024-02-14 16:43:11 +00:00
import {FilterManagerService} from "../filter-manager.service";
import {FormsModule} from "@angular/forms";
import {DecimalPipe, NgForOf, NgIf, NgOptimizedImage} from "@angular/common";
2024-02-14 16:43:11 +00:00
export interface SuspiciousScoresFilter {
sorting?: string;
minPP?: number;
maxPP?: number;
minUR?: number;
maxUR?: number;
searchUsername?: string;
searchBeatmap?: string;
}
@Component({
selector: 'app-view-suspicious-scores',
standalone: true,
2024-02-14 16:43:11 +00:00
templateUrl: './view-suspicious-scores.component.html',
imports: [
FormsModule,
RouterLink,
NgForOf,
DecimalPipe,
NgOptimizedImage,
NgIf
],
2024-02-14 16:43:11 +00:00
styleUrls: ['./view-suspicious-scores.component.css']
})
export class ViewSuspiciousScoresComponent implements OnInit, OnDestroy {
filterManager = new FilterManagerService<SuspiciousScoresFilter>("suspiciousScoreFilters");
isUrlFilters = false;
originalScores: SuspiciousScore[] = [];
filteredScores: SuspiciousScore[] = [];
currentPage = 1;
itemsPerPage = 150;
autoUpdateInterval: number = 3600000;
isLoading: boolean = true;
private updateSubscription: Subscription | null = null;
constructor(
private localCacheService: LocalCacheService,
private router: Router,
private activatedRoute: ActivatedRoute
) {
}
ngOnInit(): void {
this.activatedRoute.params.subscribe(params => {
let filters = params['f'];
if (filters) {
this.filterManager.setFiltersFromUrl(filters);
this.isUrlFilters = true;
} else {
this.filterManager.setFiltersFromLocal();
}
});
this.startAutoUpdateTimer();
}
getTotalPages(): number {
return Math.ceil(this.filteredScores.length / this.itemsPerPage);
}
getCurrentPage(): SuspiciousScore[] {
const start = (this.currentPage - 1) * this.itemsPerPage;
const end = start + this.itemsPerPage;
return this.filteredScores.slice(start, end);
}
getFiltersUrl(): void {
let targetUrl = '/sus/' + this.filterManager.getFiltersUrl();
this.router.navigate([targetUrl]).then(() => {
navigator.clipboard.writeText(targetUrl).then(() => {
console.debug('Loaded filters!')
});
});
}
ngOnDestroy(): void {
if (this.updateSubscription) {
this.updateSubscription.unsubscribe();
}
}
startAutoUpdateTimer(): void {
this.updateSubscription = timer(0, this.autoUpdateInterval).subscribe(() => {
this.isLoading = true;
this.getSuspiciousScores().subscribe(scores => {
this.originalScores = scores;
this.filterScores();
this.isLoading = false;
});
});
}
resetValues(): void {
this.filterManager.resetValues();
this.filterScores();
this.router.navigate(['/sus']).then(() => {
this.isUrlFilters = false;
});
}
getSuspiciousScores(): Observable<SuspiciousScore[]> {
this.currentPage = 1;
return this.localCacheService.fetchData<SuspiciousScore[]>(
'suspiciousScores',
`${environment.apiUrl}/suspicious-scores`,
15
);
}
filterScores(): void {
// Access the filters from the filterManager
const filters = this.filterManager.filters;
// Trim and convert to lowercase for case-insensitive comparison
const searchUsername = filters.searchUsername?.trim().toLowerCase();
const searchBeatmap = filters.searchBeatmap?.trim().toLowerCase();
this.filteredScores = this.originalScores.filter((score) => {
// Apply username filter if specified, case-insensitive
const usernameMatch = searchUsername ?
score.username.toLowerCase().includes(searchUsername) :
true;
// Apply beatmap filter if specified, case-insensitive
const beatmapMatch = searchBeatmap ?
score.beatmap_title.toLowerCase().includes(searchBeatmap) :
true;
// Apply PP filter if specified
const ppMatch = (filters.minPP == null || score.pp >= filters.minPP) &&
(filters.maxPP == null || score.pp <= filters.maxPP);
// Apply UR filter if specified
const urMatch = (filters.minUR == null || score.ur >= filters.minUR) &&
(filters.maxUR == null || score.ur <= filters.maxUR);
return usernameMatch && beatmapMatch && ppMatch && urMatch;
});
// Presumably persists the current state of filters for future sessions
this.filterManager.persistToLocalStorage();
if(this.filterManager.filters.sorting) {
let field = this.filterManager.filters.sorting.split("-")[0];
let order = this.filterManager.filters.sorting.split("-")[1];
//@ts-ignore
this.sortScores(field, order);
}
}
sortScores(field: 'pp' | 'ur' | 'beatmap_star_rating' | 'date', order: 'asc' | 'desc'): void {
if(this.isUrlFilters && this.filterManager.filters.sorting != `${field}-${order}`) {
return;
}
this.filterManager.filters.sorting = `${field}-${order}`
this.filterManager.persistToLocalStorage();
this.currentPage = 1;
this.filteredScores.sort((a: SuspiciousScore, b: SuspiciousScore): number => {
let compareValue = 0;
if (field === 'pp' || field === 'ur' || field === 'beatmap_star_rating') {
compareValue = a[field] - b[field];
} else if (field === 'date') {
compareValue = a[field] < b[field] ? -1 : a[field] > b[field] ? 1 : 0;
}
return order === 'asc' ? compareValue : -compareValue;
});
}
}