update filter alghoritm
This commit is contained in:
+12
-33
@@ -2,7 +2,6 @@ package ru.shadowsparky.vbox.backend.data
|
|||||||
|
|
||||||
import org.koin.core.annotation.Single
|
import org.koin.core.annotation.Single
|
||||||
import ru.shadowsparky.vbox.shared.domain.model.VideoItem
|
import ru.shadowsparky.vbox.shared.domain.model.VideoItem
|
||||||
import kotlin.math.max
|
|
||||||
|
|
||||||
@Single
|
@Single
|
||||||
class FuzzyMovieSearchFilter {
|
class FuzzyMovieSearchFilter {
|
||||||
@@ -15,20 +14,9 @@ class FuzzyMovieSearchFilter {
|
|||||||
if (titleNormalized.contains(query)) {
|
if (titleNormalized.contains(query)) {
|
||||||
return@map Pair(movie, 1.0)
|
return@map Pair(movie, 1.0)
|
||||||
}
|
}
|
||||||
val queryWords = query.split(" ")
|
val score = titleNormalized.fuzzySimilarity(query)
|
||||||
val titleWords = titleNormalized.split(" ")
|
Pair(movie, score)
|
||||||
var maxScore = 0.0
|
}.filter { it.second >= THRESHOLD }.sortedByDescending { it.second }.map { it.first }
|
||||||
for (qWord in queryWords) {
|
|
||||||
for (tWord in titleWords) {
|
|
||||||
val score = tWord.fuzzySimilarity(qWord)
|
|
||||||
if (score > maxScore) maxScore = score
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Pair(movie, maxScore)
|
|
||||||
}
|
|
||||||
.filter { it.second >= THRESHOLD }
|
|
||||||
.sortedByDescending { it.second }
|
|
||||||
.map { it.first }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun String.normalize(): String {
|
private fun String.normalize(): String {
|
||||||
@@ -61,27 +49,18 @@ class FuzzyMovieSearchFilter {
|
|||||||
|
|
||||||
private fun String.fuzzySimilarity(other: String): Double {
|
private fun String.fuzzySimilarity(other: String): Double {
|
||||||
if (this == other) return 1.0
|
if (this == other) return 1.0
|
||||||
if (this.isEmpty() || other.isEmpty()) return 0.0
|
if (this.isBlank() || other.isBlank()) return 0.0
|
||||||
val s1 = this
|
val s1Pairs = this.windowed(2)
|
||||||
val dp = IntArray(other.length + 1) { it }
|
val s2Pairs = other.windowed(2).toMutableList()
|
||||||
for (i in 1..s1.length) {
|
if (s1Pairs.isEmpty() || s2Pairs.isEmpty()) return 0.0
|
||||||
var prev = dp[0]
|
var matches = 0
|
||||||
dp[0] = i
|
for (pair in s1Pairs) {
|
||||||
for (j in 1..other.length) {
|
if (s2Pairs.remove(pair)) { matches++ }
|
||||||
val temp = dp[j]
|
|
||||||
if (s1[i - 1] == other[j - 1]) {
|
|
||||||
dp[j] = prev
|
|
||||||
} else {
|
|
||||||
dp[j] = minOf(dp[j - 1], dp[j], prev) + 1
|
|
||||||
}
|
|
||||||
prev = temp
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
val maxLen = max(s1.length, other.length)
|
return (2.0 * matches) / (s1Pairs.size + other.windowed(2).size)
|
||||||
return (maxLen - dp[other.length]).toDouble() / maxLen
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private companion object {
|
private companion object {
|
||||||
const val THRESHOLD: Double = 0.5
|
const val THRESHOLD: Double = 0.45
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -26,7 +26,7 @@ class SessionVideoApi(
|
|||||||
private val linksMutex = Mutex()
|
private val linksMutex = Mutex()
|
||||||
|
|
||||||
override suspend fun fetchNewVideos(query: String?): VideosResponse {
|
override suspend fun fetchNewVideos(query: String?): VideosResponse {
|
||||||
val cacheKey = query.orEmpty()
|
val cacheKey = query?.trim().orEmpty()
|
||||||
videosCache.getValid(cacheKey)?.let { return it }
|
videosCache.getValid(cacheKey)?.let { return it }
|
||||||
return videosMutex.withLock {
|
return videosMutex.withLock {
|
||||||
videosCache.getValid(cacheKey) ?: run {
|
videosCache.getValid(cacheKey) ?: run {
|
||||||
|
|||||||
Reference in New Issue
Block a user