From 70c64a9251366b9b76146f180337e7246fd84af6 Mon Sep 17 00:00:00 2001 From: Eugene Date: Sun, 9 Aug 2026 18:23:35 +0300 Subject: [PATCH] use fuzzykot library --- apps/vbox/backend/build.gradle.kts | 1 + .../vbox/backend/data/FuzzySearchFilter.kt | 20 ++++--------------- gradle/libs.versions.toml | 2 ++ 3 files changed, 7 insertions(+), 16 deletions(-) diff --git a/apps/vbox/backend/build.gradle.kts b/apps/vbox/backend/build.gradle.kts index a8777f5..1be004d 100644 --- a/apps/vbox/backend/build.gradle.kts +++ b/apps/vbox/backend/build.gradle.kts @@ -35,6 +35,7 @@ dependencies { implementation(libs.ktor.server.websockets.jvm) implementation(libs.ktor.server.cors) + implementation(libs.fuzzykot) implementation(libs.androidx.datastore.preferences.core) implementation(libs.kxml2) implementation(libs.jsoup) diff --git a/apps/vbox/backend/src/main/kotlin/ru/shadowsparky/vbox/backend/data/FuzzySearchFilter.kt b/apps/vbox/backend/src/main/kotlin/ru/shadowsparky/vbox/backend/data/FuzzySearchFilter.kt index f057ee3..c1410c9 100644 --- a/apps/vbox/backend/src/main/kotlin/ru/shadowsparky/vbox/backend/data/FuzzySearchFilter.kt +++ b/apps/vbox/backend/src/main/kotlin/ru/shadowsparky/vbox/backend/data/FuzzySearchFilter.kt @@ -1,5 +1,6 @@ package ru.shadowsparky.vbox.backend.data +import com.github.terrakok.fuzzykot.Levenshtein import org.koin.core.annotation.Single import ru.shadowsparky.vbox.shared.domain.model.VideoItem @@ -12,9 +13,9 @@ class FuzzyMovieSearchFilter { return original.map { movie -> val titleNormalized = movie.title.normalize() if (titleNormalized.contains(query)) { - return@map Pair(movie, 1.0) + return@map Pair(movie, 100) } - val score = titleNormalized.fuzzySimilarity(query) + val score = Levenshtein.tokenSortRatio(titleNormalized, query) Pair(movie, score) }.filter { it.second >= THRESHOLD }.sortedByDescending { it.second }.map { it.first } } @@ -47,20 +48,7 @@ class FuzzyMovieSearchFilter { } } - private fun String.fuzzySimilarity(other: String): Double { - if (this == other) return 1.0 - if (this.isBlank() || other.isBlank()) return 0.0 - val s1Pairs = this.windowed(2) - val s2Pairs = other.windowed(2).toMutableList() - if (s1Pairs.isEmpty() || s2Pairs.isEmpty()) return 0.0 - var matches = 0 - for (pair in s1Pairs) { - if (s2Pairs.remove(pair)) { matches++ } - } - return (2.0 * matches) / (s1Pairs.size + other.windowed(2).size) - } - private companion object { - const val THRESHOLD: Double = 0.45 + const val THRESHOLD = 55 } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 81e31d7..eaf7118 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -8,6 +8,7 @@ compose-material-version = "1.11.0-alpha03" compose-version = "1.11.1" desugar_jdk_libs = "2.1.5" foundation = "1.11.1" +fuzzykot = "1.0.0" haze = "1.7.2" java-jwt = "4.6.0" kotlin-version = "2.4.10" @@ -66,6 +67,7 @@ androidx-sqlite = { module = "androidx.sqlite:sqlite", version.ref = "sqlite" } androidx-work-runtime-ktx = { module = "androidx.work:work-runtime-ktx", version.ref = "workRuntimeKtx" } coil-compose = { module = "io.coil-kt.coil3:coil-compose", version.ref = "coil-compose" } com-android-application-gradle-plugin = { module = "com.android.application:com.android.application.gradle.plugin", version.ref = "agp" } +fuzzykot = { module = "com.github.terrakok:fuzzykot", version.ref = "fuzzykot" } haze = { module = "dev.chrisbanes.haze:haze", version.ref = "haze" } haze-materials = { module = "dev.chrisbanes.haze:haze-materials", version.ref = "haze" } java-jwt = { module = "com.auth0:java-jwt", version.ref = "java-jwt" }