Add ranked sorting for search results in Adv Mem Card

When searching through the advanced memory card, P2P entries are now sorted in
a ranking heuristic that puts the most "relevant" results up top. Entries are
scored based on the number of matching words w/ the search, followed by the
entry name's length (longer names go below shorter names).

Hopefully this addresses the problem of not getting what you searched for.
This commit is contained in:
Firenoo committed 2023-02-28 20:11:22 -08:00
1 parent ae0d50a7b1
commit be08ab0047
3 files changed
+35 -13

No files matched your search

@@ -321,8 +321,7 @@ class GuiAdvancedMemoryCard(msg: S2CListP2P) : GuiScreen(), TextureBound {
}else{
renameBar.textboxKeyTyped(char, key)
}
}else if (searchBar.isFocused && !(char == ' ' && searchBar.text.isEmpty())){
searchBar.textboxKeyTyped(char, key)
}else if (!(char.isWhitespace() && searchBar.text.isEmpty()) && searchBar.textboxKeyTyped(char, key)){
infos.refilter()
}
return super.keyTyped(char, key)
@@ -21,25 +21,33 @@ class InfoFilter {
* filter list.
*/
fun updateFilter(query: String) {
val tokens = query.split("\\s+".toRegex()) // split by whitespace
// I spent 10 minutes on this until I gave up... regex wtf
// https://stackoverflow.com/questions/366202/regex-for-splitting-a-string-using-space-when-not-surrounded-by-single-or-double
val regex = "[^\\s\"']+|\"([^\"]*)\"|'([^']*)'".toRegex()
val tokens = regex.findAll(query)
activeFilters.clear()
tokens.forEach {
when {
it.matches(Filter.INPUT.pattern) -> {
it.value.matches(Filter.INPUT.pattern) -> {
activeFilters.putIfAbsent(Filter.INPUT, null)
}
it.matches(Filter.OUTPUT.pattern) -> {
it.value.matches(Filter.OUTPUT.pattern) -> {
activeFilters.putIfAbsent(Filter.OUTPUT, null)
}
it.matches(Filter.BOUND.pattern) -> {
it.value.matches(Filter.BOUND.pattern) -> {
activeFilters.putIfAbsent(Filter.BOUND, null)
}
it.matches(Filter.UNBOUND.pattern) -> {
it.value.matches(Filter.UNBOUND.pattern) -> {
activeFilters.putIfAbsent(Filter.UNBOUND, null)
}
it.value.isBlank() -> {}
else -> {
activeFilters.putIfAbsent(Filter.NAME, mutableListOf())
activeFilters[Filter.NAME]!!.add(it)
when {
it.groups[1] != null -> activeFilters[Filter.NAME]!!.add(it.groups[1]!!.value)
it.groups[2] != null -> activeFilters[Filter.NAME]!!.add(it.groups[2]!!.value)
else -> activeFilters[Filter.NAME]!!.add(it.value)
}
}
}
}
@@ -68,7 +76,3 @@ enum class Filter(val pattern: Regex, val filter: (InfoWrapper, List<String>?) -
});
}
//fun parseQuery(search: String): InfoFilter {
//
//}
@@ -2,6 +2,7 @@ package com.projecturanus.betterp2p.client.gui
import com.projecturanus.betterp2p.network.NONE
import com.projecturanus.betterp2p.network.hashP2P
import kotlin.math.absoluteValue
import kotlin.reflect.KProperty0
/**
@@ -61,7 +62,7 @@ class InfoList (initList: Collection<InfoWrapper>,
} else if (it.frequency != 0.toLong() && it.frequency == selectedInfo?.frequency) {
-1 // Put same frequency in the front
} else {
// Frequencies from highest to lowest
// Frequencies from lowest to highest
it.frequency + Short.MAX_VALUE
}
}
@@ -82,6 +83,24 @@ class InfoList (initList: Collection<InfoWrapper>,
}
}
true
}.sortedBy {
when {
it.code == selectedEntry -> Long.MIN_VALUE + 1
it.frequency != 0L && it.frequency == selectedInfo?.frequency && !it.output -> Long.MIN_VALUE
it.frequency != 0.toLong() && it.frequency == selectedInfo?.frequency -> Long.MIN_VALUE + 2 // Put same frequency in the front
filter.activeFilters.containsKey(Filter.NAME) -> {
var hits = 0L
var name = it.name
for (f in filter.activeFilters[Filter.NAME]!!) {
if (name.contains(f, true)) {
hits += 1
name = name.replaceFirst(f, "", true)
}
}
-(hits * hits) + name.length
}
else -> it.frequency + Short.MAX_VALUE
}
}
// filtered = sorted.filter {
// it.frequency.toHexString().contains(searchStr.uppercase()) ||