Minor matching algorithm improvement

Add "Clear DB" button to UI
This commit is contained in:
grimsi
2025-03-31 09:39:53 +02:00
parent c3f696ea90
commit bcade0e4f1
4 changed files with 38 additions and 4 deletions
@@ -16,6 +16,17 @@ export default function TestView() {
}); });
} }
function removeGames() {
LibraryEndpoint.removeGames().then(() => {
setGame(undefined);
addToast({
title: "Success",
description: "Games removed",
color: "success"
})
});
}
return ( return (
<div className="grow justify-center mt-12"> <div className="grow justify-center mt-12">
<div className="flex flex-col items-center gap-6"> <div className="flex flex-col items-center gap-6">
@@ -46,6 +57,7 @@ export default function TestView() {
<div className="flex flex-row gap-4 items-center"> <div className="flex flex-row gap-4 items-center">
<Input label="Game title" onValueChange={setGameTitle}/> <Input label="Game title" onValueChange={setGameTitle}/>
<Button onPress={getGame} size="lg">Match</Button> <Button onPress={getGame} size="lg">Match</Button>
<Button onPress={removeGames} size="lg">Clear DB</Button>
</div> </div>
{game && <GameOverviewCard game={game}></GameOverviewCard>} {game && <GameOverviewCard game={game}></GameOverviewCard>}
{game && <>{JSON.stringify(game, null, 2)}</>} {game && <>{JSON.stringify(game, null, 2)}</>}
@@ -51,5 +51,14 @@ class Utils {
} }
} }
/**
* Converts a map with nullable values to a map with non-nullable values by filtering out null values
*/
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
fun <K, V> Map<K, V?>.filterValuesNotNull() = filterValues { it != null } as Map<K, V> fun <K, V> Map<K, V?>.filterValuesNotNull() = filterValues { it != null } as Map<K, V>
/**
* Converts a string to an alphanumeric string by removing all non-alphanumeric characters (except whitespaces)
* and converting it to lowercase
*/
fun String.alphaNumeric() = filter { it.isLetterOrDigit() || it.isWhitespace() }.lowercase()
@@ -1,5 +1,6 @@
package de.grimsi.gameyfin.games package de.grimsi.gameyfin.games
import de.grimsi.gameyfin.core.alphaNumeric
import de.grimsi.gameyfin.core.filterValuesNotNull import de.grimsi.gameyfin.core.filterValuesNotNull
import de.grimsi.gameyfin.core.plugins.management.PluginManagementEntry import de.grimsi.gameyfin.core.plugins.management.PluginManagementEntry
import de.grimsi.gameyfin.core.plugins.management.PluginManagementService import de.grimsi.gameyfin.core.plugins.management.PluginManagementService
@@ -83,6 +84,10 @@ class GameService(
gameRepository.delete(game) gameRepository.delete(game)
} }
fun deleteAll() {
gameRepository.deleteAll()
}
private fun getById(id: Long): Game { private fun getById(id: Long): Game {
return gameRepository.findByIdOrNull(id) ?: throw IllegalArgumentException("Game with id $id not found") return gameRepository.findByIdOrNull(id) ?: throw IllegalArgumentException("Game with id $id not found")
} }
@@ -110,7 +115,8 @@ class GameService(
} }
/** /**
* Determines the closest matching title from the results and filters out any other results * Determines the closest matching title from the results
* Filters the results to only include the best matching title (using an alphanumeric comparison)
*/ */
private fun filterResults( private fun filterResults(
originalQuery: String, originalQuery: String,
@@ -121,7 +127,7 @@ class GameService(
log.info { "Best matching title: '$bestMatchingTitle' for '$originalQuery' determined from $availableTitles" } log.info { "Best matching title: '$bestMatchingTitle' for '$originalQuery' determined from $availableTitles" }
return results.filter { it.value.title == bestMatchingTitle } return results.filter { it.value.title.alphaNumeric() == bestMatchingTitle.alphaNumeric() }
} }
/** /**
@@ -2,12 +2,14 @@ package de.grimsi.gameyfin.libraries
import com.vaadin.hilla.Endpoint import com.vaadin.hilla.Endpoint
import de.grimsi.gameyfin.core.Role import de.grimsi.gameyfin.core.Role
import de.grimsi.gameyfin.games.GameService
import de.grimsi.gameyfin.games.dto.GameDto import de.grimsi.gameyfin.games.dto.GameDto
import jakarta.annotation.security.RolesAllowed import jakarta.annotation.security.RolesAllowed
@Endpoint @Endpoint
class LibraryEndpoint( class LibraryEndpoint(
private val libraryService: LibraryService private val libraryService: LibraryService,
private val gameService: GameService
) { ) {
@RolesAllowed(Role.Names.ADMIN) @RolesAllowed(Role.Names.ADMIN)
fun getAllLibraries(): Collection<LibraryDto> { fun getAllLibraries(): Collection<LibraryDto> {
@@ -23,4 +25,9 @@ class LibraryEndpoint(
fun test(testString: String): GameDto { fun test(testString: String): GameDto {
return libraryService.test(testString) return libraryService.test(testString)
} }
@RolesAllowed(Role.Names.ADMIN)
fun removeGames() {
return gameService.deleteAll()
}
} }