From 79557b170a4cc3835de62e71a54e144f1146bfbf Mon Sep 17 00:00:00 2001 From: "nise.moe" Date: Sat, 24 Feb 2024 18:59:55 +0100 Subject: [PATCH] Cleaning up advanced search --- .../nise/controller/SearchController.kt | 158 ++++++++++-------- .../src/app/search/search.component.ts | 7 +- .../src/corelib/service/user.service.ts | 11 +- 3 files changed, 93 insertions(+), 83 deletions(-) diff --git a/nise-backend/src/main/kotlin/com/nisemoe/nise/controller/SearchController.kt b/nise-backend/src/main/kotlin/com/nisemoe/nise/controller/SearchController.kt index 139876e..042a059 100644 --- a/nise-backend/src/main/kotlin/com/nisemoe/nise/controller/SearchController.kt +++ b/nise-backend/src/main/kotlin/com/nisemoe/nise/controller/SearchController.kt @@ -5,19 +5,10 @@ import com.nisemoe.generated.tables.references.SCORES import com.nisemoe.generated.tables.references.USERS import com.nisemoe.nise.Format import com.nisemoe.nise.service.AuthService -import org.jooq.Condition -import org.jooq.DSLContext -import org.jooq.Field -import org.jooq.OrderField -import org.jooq.Record -import org.jooq.Result +import org.jooq.* import org.jooq.impl.DSL import org.springframework.http.ResponseEntity -import org.springframework.web.bind.annotation.GetMapping -import org.springframework.web.bind.annotation.PostMapping -import org.springframework.web.bind.annotation.RequestBody -import org.springframework.web.bind.annotation.RequestHeader -import org.springframework.web.bind.annotation.RestController +import org.springframework.web.bind.annotation.* import kotlin.math.roundToInt @RestController @@ -144,6 +135,18 @@ class SearchController( val type: String ) + data class InternalSchemaField( + val name: String, + val shortName: String, + val category: Category, + val type: Type, + val active: Boolean, + val description: String, + + val isPrivileged: Boolean = false, + val databaseField: Field<*>? = null + ) + data class SchemaField( val name: String, val shortName: String, @@ -169,68 +172,89 @@ class SearchController( @GetMapping("search") fun getSearchSchema(): ResponseEntity { - val fields = listOf( + val internalFields = listOf( // User fields - SchemaField("user_id", "ID", Category.user, Type.number, false, "unique identifier for a user"), - SchemaField("user_username", "Username", Category.user, Type.string, true, "user's name"), - SchemaField("user_join_date", "Join Date", Category.user, Type.string, false, "when the user joined"), - SchemaField("user_country", "Country", Category.user, Type.flag, true, "user's country flag"), - SchemaField("user_country_rank", "Country Rank", Category.user, Type.number, false, "ranking within user's country"), - SchemaField("user_rank", "Rank", Category.user, Type.number, false, "global ranking"), - SchemaField("user_pp_raw", "User PP", Category.user, Type.number, false, "performance points"), - SchemaField("user_accuracy", "User Accuracy", Category.user, Type.number, false, "hit accuracy percentage"), - SchemaField("user_playcount", "Playcount", Category.user, Type.number, false, "total plays"), - SchemaField("user_total_score", "Total Score", Category.user, Type.number, false, "cumulative score"), - SchemaField("user_ranked_score", "Ranked Score", Category.user, Type.number, false, "score from ranked maps"), - SchemaField("user_seconds_played", "Play Time", Category.user, Type.number, false, "total play time in seconds"), - SchemaField("user_count_300", "300s", Category.user, Type.number, false, "number of 300 hits"), - SchemaField("user_count_100", "100s", Category.user, Type.number, false, "number of 100 hits"), - SchemaField("user_count_50", "50s", Category.user, Type.number, false, "number of 50 hits"), - SchemaField("user_count_miss", "Misses", Category.user, Type.number, false, "missed hits"), + InternalSchemaField("user_id", "ID", Category.user, Type.number, false, "unique identifier for a user"), + InternalSchemaField("user_username", "Username", Category.user, Type.string, true, "user's name"), + InternalSchemaField("user_join_date", "Join Date", Category.user, Type.string, false, "when the user joined"), + InternalSchemaField("user_country", "Country", Category.user, Type.flag, true, "user's country flag"), + InternalSchemaField("user_country_rank", "Country Rank", Category.user, Type.number, false, "ranking within user's country"), + InternalSchemaField("user_rank", "Rank", Category.user, Type.number, false, "global ranking"), + InternalSchemaField("user_pp_raw", "User PP", Category.user, Type.number, false, "performance points"), + InternalSchemaField("user_accuracy", "User Accuracy", Category.user, Type.number, false, "hit accuracy percentage"), + InternalSchemaField("user_playcount", "Playcount", Category.user, Type.number, false, "total plays"), + InternalSchemaField("user_total_score", "Total Score", Category.user, Type.number, false, "cumulative score"), + InternalSchemaField("user_ranked_score", "Ranked Score", Category.user, Type.number, false, "score from ranked maps"), + InternalSchemaField("user_seconds_played", "Play Time", Category.user, Type.number, false, "total play time in seconds"), + InternalSchemaField("user_count_300", "300s", Category.user, Type.number, false, "number of 300 hits"), + InternalSchemaField("user_count_100", "100s", Category.user, Type.number, false, "number of 100 hits"), + InternalSchemaField("user_count_50", "50s", Category.user, Type.number, false, "number of 50 hits"), + InternalSchemaField("user_count_miss", "Misses", Category.user, Type.number, false, "missed hits"), // Score fields - SchemaField("id", "ID", Category.score, Type.number, false, "unique identifier for a score"), - SchemaField("beatmap_id", "Beatmap ID", Category.score, Type.number, false, "identifies the beatmap"), - SchemaField("count_300", "300s", Category.score, Type.number, false, "number of 300 hits in score"), - SchemaField("count_100", "100s", Category.score, Type.number, false, "number of 100 hits in score"), - SchemaField("count_50", "50s", Category.score, Type.number, false, "number of 50 hits in score"), - SchemaField("count_miss", "Misses", Category.score, Type.number, false, "missed hits in score"), - SchemaField("date", "Date", Category.score, Type.string, true, "when score was achieved"), - SchemaField("max_combo", "Max Combo", Category.score, Type.number, false, "highest combo in score"), - SchemaField("mods", "Mods", Category.score, Type.number, false, "game modifiers used"), - SchemaField("perfect", "Perfect", Category.score, Type.boolean, false, "if score is a full combo"), - SchemaField("pp", "Score PP", Category.score, Type.number, true, "performance points for score"), - SchemaField("rank", "Rank", Category.score, Type.grade, false, "score grade"), - SchemaField("replay_id", "Replay ID", Category.score, Type.number, false, "identifier for replay"), - SchemaField("score", "Score", Category.score, Type.number, false, "score value"), - SchemaField("ur", "UR", Category.score, Type.number, false, "unstable rate"), - SchemaField("frametime", "Frame Time", Category.score, Type.number, false, "average frame time during play"), - SchemaField("edge_hits", "Edge Hits", Category.score, Type.number, false, "hits at the edge of hit window"), - SchemaField("snaps", "Snaps", Category.score, Type.number, false, "rapid cursor movements"), - SchemaField("adjusted_ur", "Adj. UR", Category.score, Type.number, true, "adjusted unstable rate"), - SchemaField("mean_error", "Mean Error", Category.score, Type.number, false, "average timing error"), - SchemaField("error_variance", "Error Var.", Category.score, Type.number, false, "variability of error in scores"), - SchemaField("error_standard_deviation", "Error SD", Category.score, Type.number, false, "standard deviation of error"), - SchemaField("minimum_error", "Min Error", Category.score, Type.number, false, "smallest error recorded"), - SchemaField("maximum_error", "Max Error", Category.score, Type.number, false, "largest error recorded"), - SchemaField("error_range", "Error Range", Category.score, Type.number, false, "range between min and max error"), - SchemaField("error_coefficient_of_variation", "Error CV", Category.score, Type.number, false, "relative variability of error"), - SchemaField("error_kurtosis", "Kurtosis", Category.score, Type.number, false, "peakedness of error distribution"), - SchemaField("error_skewness", "Skewness", Category.score, Type.number, false, "asymmetry of error distribution"), - SchemaField("keypresses_median_adjusted", "KP Median Adj.", Category.score, Type.number, false, "median of adjusted keypresses"), - SchemaField("keypresses_standard_deviation_adjusted", "KP std. Adj.", Category.score, Type.number, false, "std. dev of adjusted keypresses"), - SchemaField("sliderend_release_median_adjusted", "Sliderend Median Adj.", Category.score, Type.number, false, "median of adjusted sliderend releases"), - SchemaField("sliderend_release_standard_deviation_adjusted", "Sliderend std. Adj.", Category.score, Type.number, false, "std. dev of adjusted sliderend releases"), + InternalSchemaField("id", "ID", Category.score, Type.number, false, "unique identifier for a score"), + InternalSchemaField("beatmap_id", "Beatmap ID", Category.score, Type.number, false, "identifies the beatmap"), + InternalSchemaField("count_300", "300s", Category.score, Type.number, false, "number of 300 hits in score"), + InternalSchemaField("count_100", "100s", Category.score, Type.number, false, "number of 100 hits in score"), + InternalSchemaField("count_50", "50s", Category.score, Type.number, false, "number of 50 hits in score"), + InternalSchemaField("count_miss", "Misses", Category.score, Type.number, false, "missed hits in score"), + InternalSchemaField("date", "Date", Category.score, Type.string, true, "when score was achieved"), + InternalSchemaField("max_combo", "Max Combo", Category.score, Type.number, false, "highest combo in score"), + InternalSchemaField("mods", "Mods", Category.score, Type.number, false, "game modifiers used"), + InternalSchemaField("perfect", "Perfect", Category.score, Type.boolean, false, "if score is a full combo"), + InternalSchemaField("pp", "Score PP", Category.score, Type.number, true, "performance points for score"), + InternalSchemaField("rank", "Rank", Category.score, Type.grade, false, "score grade"), + InternalSchemaField("replay_id", "Replay ID", Category.score, Type.number, false, "identifier for replay"), + InternalSchemaField("score", "Score", Category.score, Type.number, false, "score value"), + InternalSchemaField("ur", "UR", Category.score, Type.number, false, "unstable rate"), + InternalSchemaField("frametime", "Frame Time", Category.score, Type.number, false, "average frame time during play"), + InternalSchemaField("edge_hits", "Edge Hits", Category.score, Type.number, false, "hits at the edge of hit window"), + InternalSchemaField("snaps", "Snaps", Category.score, Type.number, false, "rapid cursor movements"), + InternalSchemaField("adjusted_ur", "Adj. UR", Category.score, Type.number, true, "adjusted unstable rate"), + InternalSchemaField("mean_error", "Mean Error", Category.score, Type.number, false, "average timing error"), + InternalSchemaField("error_variance", "Error Var.", Category.score, Type.number, false, "variability of error in scores"), + InternalSchemaField("error_standard_deviation", "Error SD", Category.score, Type.number, false, "standard deviation of error"), + InternalSchemaField("minimum_error", "Min Error", Category.score, Type.number, false, "smallest error recorded"), + InternalSchemaField("maximum_error", "Max Error", Category.score, Type.number, false, "largest error recorded"), + InternalSchemaField("error_range", "Error Range", Category.score, Type.number, false, "range between min and max error"), + InternalSchemaField("error_coefficient_of_variation", "Error CV", Category.score, Type.number, false, "relative variability of error"), + InternalSchemaField("error_kurtosis", "Kurtosis", Category.score, Type.number, false, "peakedness of error distribution"), + InternalSchemaField("error_skewness", "Skewness", Category.score, Type.number, false, "asymmetry of error distribution"), + InternalSchemaField("keypresses_median_adjusted", "KP Median Adj.", Category.score, Type.number, false, "median of adjusted keypresses", isPrivileged = true), + InternalSchemaField("keypresses_standard_deviation_adjusted", "KP std. Adj.", Category.score, Type.number, false, "std. dev of adjusted keypresses", isPrivileged = true), + InternalSchemaField("sliderend_release_median_adjusted", "Sliderend Median Adj.", Category.score, Type.number, false, "median of adjusted sliderend releases", isPrivileged = true), + InternalSchemaField("sliderend_release_standard_deviation_adjusted", "Sliderend std. Adj.", Category.score, Type.number, false, "std. dev of adjusted sliderend releases", isPrivileged = true), // Beatmap fields - SchemaField("beatmap_artist", "Artist", Category.beatmap, Type.string, false, "artist of the beatmap"), - SchemaField("beatmap_beatmapset_id", "Set ID", Category.beatmap, Type.number, false, "id of the beatmap set"), - SchemaField("beatmap_creator", "Creator", Category.beatmap, Type.string, false, "creator of the beatmap"), - SchemaField("beatmap_source", "Source", Category.beatmap, Type.string, false, "source of the beatmap music"), - SchemaField("beatmap_star_rating", "Stars", Category.beatmap, Type.number, false, "(★) difficulty rating of the beatmap"), - SchemaField("beatmap_title", "Title", Category.beatmap, Type.string, false, "title of the beatmap"), - SchemaField("beatmap_version", "Version", Category.beatmap, Type.string, false, "version or difficulty name of the beatmap") + InternalSchemaField("beatmap_artist", "Artist", Category.beatmap, Type.string, false, "artist of the beatmap"), + InternalSchemaField("beatmap_beatmapset_id", "Set ID", Category.beatmap, Type.number, false, "id of the beatmap set"), + InternalSchemaField("beatmap_creator", "Creator", Category.beatmap, Type.string, false, "creator of the beatmap"), + InternalSchemaField("beatmap_source", "Source", Category.beatmap, Type.string, false, "source of the beatmap music"), + InternalSchemaField("beatmap_star_rating", "Stars", Category.beatmap, Type.number, false, "(★) difficulty rating of the beatmap"), + InternalSchemaField("beatmap_title", "Title", Category.beatmap, Type.string, false, "title of the beatmap"), + InternalSchemaField("beatmap_version", "Version", Category.beatmap, Type.string, false, "version or difficulty name of the beatmap") ) + + // Map to SchemaField + val isUserAdmin = authService.isAdmin() + val fields = internalFields + .filter { + return@filter !(it.isPrivileged && !isUserAdmin) + } + .map { + SchemaField( + name = it.name, + shortName = it.shortName, + category = it.category, + type = it.type, + active = it.active, + description = it.description + ) + } + + // Filter privileged fields + + val schema = SearchSchema(fields) return ResponseEntity.ok(schema) } diff --git a/nise-frontend/src/app/search/search.component.ts b/nise-frontend/src/app/search/search.component.ts index fad1ffc..f30add1 100644 --- a/nise-frontend/src/app/search/search.component.ts +++ b/nise-frontend/src/app/search/search.component.ts @@ -112,12 +112,7 @@ export class SearchComponent implements OnInit { queries: Query[] | null = null; ngOnInit(): void { - - this.localCacheService.fetchData( - "search-schema", - `${environment.apiUrl}/search`, - 60 - ).subscribe({ + this.httpClient.get(`${environment.apiUrl}/search`,).subscribe({ next: (response) => { this.fields = response.fields; this.loadPreviousFromLocalStorage(); diff --git a/nise-frontend/src/corelib/service/user.service.ts b/nise-frontend/src/corelib/service/user.service.ts index e6bf3f4..b8df8e5 100644 --- a/nise-frontend/src/corelib/service/user.service.ts +++ b/nise-frontend/src/corelib/service/user.service.ts @@ -15,7 +15,6 @@ export class UserService { currentUser: UserInfo | null = null; loginCallback: () => void = () => {}; - logoutCallback: () => void = () => {}; constructor(private httpClient: HttpClient) { this.currentUser = this.loadCurrentUserFromLocalStorage(); @@ -23,14 +22,6 @@ export class UserService { .catch(reason => console.debug(reason)); } - public doLogout(): void { - this.currentUser = null; - this.clearCurrentUserFromLocalStorage(); - this.updateUser().then( - () => this.logoutCallback() - ) - } - isUserLoggedIn(): boolean { return this.currentUser !== null; } @@ -74,7 +65,7 @@ export class UserService { } clearCurrentUserFromLocalStorage() { - localStorage.setItem('currentUser', ''); + localStorage.removeItem('currentUser'); document.cookie = 'SESSION=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;'; }