mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-10 18:40:15 +08:00
Fix fuzzyCompare
This commit is contained in:
parent
faaf8d34f2
commit
cdc9f8f613
@ -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("当前语境下无法推断目标群员")
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user