Add rate limit

This commit is contained in:
2025-03-04 00:45:22 +08:00
parent 05c115e3e8
commit 67f9d1ca75
2 changed files with 64 additions and 23 deletions

View File

@ -9,14 +9,14 @@ import net.mamoe.mirai.event.events.GroupMessageEvent
import net.mamoe.mirai.event.subscribeGroupMessages import net.mamoe.mirai.event.subscribeGroupMessages
import net.mamoe.mirai.utils.info import net.mamoe.mirai.utils.info
import java.text.DecimalFormat import java.text.DecimalFormat
import java.time.Duration import java.time.*
import java.time.LocalDateTime import kotlin.math.max
object PluginMain : KotlinPlugin( object PluginMain : KotlinPlugin(
JvmPluginDescription( JvmPluginDescription(
id = "top.jie65535.j24", id = "top.jie65535.j24",
name = "J 24点游戏", name = "J 24点游戏",
version = "0.1.3" version = "1.0.0"
) { ) {
author("jie65535") author("jie65535")
info("24点游戏") info("24点游戏")
@ -27,12 +27,26 @@ object PluginMain : KotlinPlugin(
private val df = DecimalFormat("0.00") private val df = DecimalFormat("0.00")
private const val prefix = "=" private const val prefix = "="
private const val maxRound = 10
class GroupState(
var lastGameTimes: Int = 1,
/**
* 游戏计时器
* 为了防止频繁刷屏记录开始时间一定间隔后才可再次触发
*/
var lastStartedAt: LocalDateTime = LocalDateTime.MIN,
/**
* 排行榜计时器
* 为了防止频繁刷屏记录出榜时间一定间隔后才可再次触发
*/
var lastRankedAt: LocalDateTime = LocalDateTime.MIN
)
private val gameStats = mutableMapOf<Long, GroupState>()
/**
* 排行榜计时器
* 为了防止频繁刷屏记录出榜时间一定间隔后才可再次触发
*/
private val rankTimes = mutableMapOf<Long, LocalDateTime>()
override fun onEnable() { override fun onEnable() {
logger.info { "Plugin loaded" } logger.info { "Plugin loaded" }
@ -45,19 +59,30 @@ object PluginMain : KotlinPlugin(
.subscribeGroupMessages { .subscribeGroupMessages {
"24点" reply { "24点" reply {
var game = games[group.id] var game = games[group.id]
if (game == null || game.time.plusMinutes(1) < LocalDateTime.now()) { val state = gameStats.getOrPut(group.id) { GroupState() }
if (state.lastStartedAt.plusMinutes(10).isBefore(LocalDateTime.now())) {
state.lastStartedAt = LocalDateTime.now()
state.lastGameTimes = 0
}
if (state.lastGameTimes >= maxRound) {
"您参与的太过频繁了,为避免影响他人聊天体验,请稍后再试~"
} else if (game == null || game.time.plusMinutes(1) < LocalDateTime.now()) {
game = Point24() game = Point24()
games[group.id] = game games[group.id] = game
"请用 $game 组成结果为24的算式以'$prefix'开头验证" state.lastGameTimes++
"{${state.lastGameTimes}/$maxRound} 请用 $game 组成结果为24的算式以'$prefix'开头验证"
} else Unit } else Unit
} }
"24点榜" reply { "24点榜" reply aaa@{
val g = PluginData.stats[group.id] val g = PluginData.stats[group.id] ?: return@aaa Unit
val state = gameStats.getOrPut(group.id) { GroupState() }
// 一小时内仅可查询一次 // 一小时内仅可查询一次
if (g != null && rankTimes[group.id]?.plusHours(1)?.isBefore(LocalDateTime.now()) != false) { if (state.lastRankedAt.plusHours(1).isBefore(LocalDateTime.now())) {
// 记录查询时间 // 记录查询时间
rankTimes[group.id] = LocalDateTime.now() state.lastRankedAt = LocalDateTime.now()
// 拼接排行榜 // 拼接排行榜
val sb = StringBuilder() val sb = StringBuilder()
sb.appendLine("[均时榜]") sb.appendLine("[均时榜]")
@ -80,11 +105,14 @@ object PluginMain : KotlinPlugin(
val game = games[group.id] val game = games[group.id]
if (game != null) { if (game != null) {
try { try {
val now = LocalDateTime.now()
val result = game.evaluate(message.contentToString().removePrefix(prefix).trim()) val result = game.evaluate(message.contentToString().removePrefix(prefix).trim())
if (result == 24.0) { if (result == 24.0) {
val newGame = Point24() val duration = Duration.between(game.time, now)
games[group.id] = newGame // Instant.ofEpochSecond(
val duration = Duration.between(game.time, LocalDateTime.now()) // this.time.toLong())
// .atZone(ZoneId.systemDefault())
// .toLocalDateTime())
// 群 // 群
var g = PluginData.stats[group.id] var g = PluginData.stats[group.id]
@ -105,18 +133,30 @@ object PluginMain : KotlinPlugin(
if (stat.minTime > t) { if (stat.minTime > t) {
stat.minTime = t stat.minTime = t
} }
// 仅统计百秒内的平均值 // 仅统计一定时间内的均值
if (t < 100) { val resultText = if (t < 60) {
// 计数增加 // 计数增加
stat.count += 1 stat.count += 1
// 更新均值 // 更新均值
stat.avgTime += (t - stat.avgTime) / stat.count stat.avgTime += (t - stat.avgTime) / max(20, stat.count)
"答对了!用时:${df.format(t)}s 平均:${df.format(stat.avgTime)}s 最快:${df.format(stat.minTime)}s\n" + "答对了!用时:${df.format(t)}s 平均:${df.format(stat.avgTime)}s 最快:${df.format(stat.minTime)}s\n"
"下一题:$newGame"
} else { } else {
"答对了!下一题:$newGame" "回答正确!"
} }
val state = gameStats[group.id]!!
val nextTip = if (state.lastGameTimes >= maxRound) {
games.remove(group.id)
"本轮游戏已经结束,感谢参与,请稍作休息~"
} else {
state.lastGameTimes++
val newGame = Point24()
games[group.id] = newGame
"{${state.lastGameTimes}/$maxRound}下一题:$newGame"
}
resultText + nextTip
} else { } else {
"答错了,计算结果为 $result" "答错了,计算结果为 $result"
} }

View File

@ -71,6 +71,7 @@ class Point24 {
val expr = expression val expr = expression
.replace('', '(') .replace('', '(')
.replace('', ')') .replace('', ')')
.replace('X', '*')
.replace('x', '*') .replace('x', '*')
.replace('×', '*') .replace('×', '*')
.replace('÷', '/') .replace('÷', '/')