Fix fuzzyCompare

This commit is contained in:
Him188 2020-08-22 21:49:09 +08:00
parent faaf8d34f2
commit cdc9f8f613
2 changed files with 37 additions and 40 deletions

View File

@ -195,12 +195,15 @@ public object ExistMemberArgumentParser : InternalCommandArgumentParserExtension
- `botId.group.memberId`
- `botId.group.memberCard` (模糊搜索, 寻找最优匹配)
- `~` (指代指令调用人自己. 仅聊天环境下)
- `$` (随机成员)
当只登录了一个 [Bot] , 无需上述 `botId` 参数即可
""".trimIndent()
public override fun parse(raw: String, sender: CommandSender): Member {
if (raw == "~") return (sender as? MemberCommandSender)?.user ?: illegalArgument("当前语境下无法推断目标群员")
if (raw == "~") return (sender as? MemberCommandSender)?.user ?: illegalArgument("当前语境下无法推断自身作为群员")
if (raw == "\$") return (sender as? MemberCommandSender)?.group?.members?.randomOrNull()
?: illegalArgument("当前语境下无法推断随机群员")
val components = raw.split(".")
@ -221,7 +224,12 @@ public object ExistMemberArgumentParser : InternalCommandArgumentParserExtension
public override fun parse(raw: SingleMessage, sender: CommandSender): Member {
return if (raw is At) {
checkArgument(sender is MemberCommandSender)
sender.group.members[raw.target]
val bot = sender.inferBotOrFail()
val group = sender.inferGroupOrFail()
if (raw.target == bot.id) {
return group.botAsMember
}
group[raw.target]
} else {
parse(raw.content, sender)
}
@ -247,10 +255,12 @@ internal interface InternalCommandArgumentParserExtensions<T : Any> : CommandArg
fun Bot.findMemberOrFail(id: String): Friend =
getFriendOrNull(id.parseToLongOrFail()) ?: illegalArgument("无法找到群员: $this")
fun Group.findMemberOrFail(idOrCard: String): Member =
idOrCard.toLongOrNull()?.let { getOrNull(it) }
fun Group.findMemberOrFail(idOrCard: String): Member {
if (idOrCard == "\$") return members.randomOrNull() ?: illegalArgument("当前语境下无法推断随机群员")
return idOrCard.toLongOrNull()?.let { getOrNull(it) }
?: fuzzySearchMember(idOrCard)
?: illegalArgument("无法找到目标群员 $idOrCard")
}
fun CommandSender.inferBotOrFail(): Bot = (this as? BotAwareCommandSender)?.bot ?: illegalArgument("当前语境下无法推断目标群员")

View File

@ -14,6 +14,7 @@ import net.mamoe.mirai.console.command.description.CommandArgumentParserExceptio
import net.mamoe.mirai.contact.Group
import net.mamoe.mirai.contact.Member
import net.mamoe.mirai.contact.nameCardOrNick
import kotlin.math.max
internal infix fun Array<String>.matchesBeginning(list: List<Any>): Boolean {
@ -31,53 +32,39 @@ internal infix fun Array<out String>.intersectsIgnoringCase(other: Array<out Str
return false
}
internal fun String.fuzzyCompare(target: String): Double {
var step = 0
internal fun String.fuzzyMatchWith(target: String): Double {
if (this == target) {
return 1.0
}
if (target.length > this.length) {
return 0.0
}
for (i in this.indices) {
if (target.length == i) {
step--
} else {
if (this[i] != target[i]) {
break
}
step++
var match = 0
for (i in 0..(max(this.lastIndex, target.lastIndex))) {
val t = target.getOrNull(match)
if (t == this.getOrNull(i) && t != null) {
match++
}
}
if (step == this.length - 1) {
return 1.0
}
return step.toDouble() / this.length
return match.toDouble() / (max(this.lastIndex, target.lastIndex) + 1)
}
/**
* 模糊搜索一个List中index最接近target的东西
*/
internal inline fun <T : Any> Collection<T>.fuzzySearch(
target: String,
index: (T) -> String
crossinline index: (T) -> String
): T? {
var potential: T? = null
var rate = 0.0
this.forEach {
val thisIndex = index(it)
if (thisIndex == target) {
return it
}
with(thisIndex.fuzzyCompare(target)) {
if (this > rate) {
rate = this
potential = it
}
var maxElement: T? = null
var max = 0.0
for (t in this) {
val r = index(t).fuzzyMatchWith(target)
if (r > max) {
maxElement = t
max = r
}
}
return potential
if (max >= 0.7) {
return maxElement
}
return null
}
/**
@ -93,7 +80,7 @@ internal inline fun <T : Any> Collection<T>.fuzzySearchOnly(
var rate = 0.0
var collide = 0
this.forEach {
with(index(it).fuzzyCompare(target)) {
with(index(it).fuzzyMatchWith(target)) {
if (this > rate) {
rate = this
potential = it