Compare commits

...

3 Commits

Author SHA1 Message Date
875e0efc2f Merge branch 'master' of ssh://gitea.service.jazzwhom.top:2221/mttu-developers/konabot
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
2025-10-23 22:12:41 +08:00
4f43312663 升级 ptimeparse 2025-10-23 22:12:34 +08:00
b2f4768573 优化判定与计分规则
All checks were successful
continuous-integration/drone/push Build is passing
2025-10-21 23:52:05 +08:00
3 changed files with 47 additions and 20 deletions

View File

@ -68,17 +68,19 @@ class TryStopState(Enum):
class TryVerifyState(Enum):
VERIFIED = 0
NOT_IDIOM = 1
WRONG_FIRST_CHAR = 2
VERIFIED_BUT_NO_NEXT = 3
VERIFIED_GAME_END = 4
VERIFIED_AND_REAL = 1
NOT_IDIOM = 2
WRONG_FIRST_CHAR = 3
VERIFIED_BUT_NO_NEXT = 4
VERIFIED_GAME_END = 5
class IdiomGame:
ALL_WORDS = [] # 所有四字词语
ALL_IDIOMS = [] # 所有成语
INSTANCE_LIST: dict[str, "IdiomGame"] = {} # 群号对应的游戏实例
IDIOM_FIRST_CHAR = {} # 成语首字字典
IDIOM_FIRST_CHAR = {} # 所有成语包括词语的首字字典
AVALIABLE_IDIOM_FIRST_CHAR = {} # 真正有效的成语首字字典
__inited = False
@ -181,7 +183,7 @@ class IdiomGame:
"""
判断是否有成语可以接
"""
return last_char in IdiomGame.IDIOM_FIRST_CHAR
return last_char in IdiomGame.AVALIABLE_IDIOM_FIRST_CHAR
def _verify_idiom(self, idiom: str, user_id: str) -> TryVerifyState:
# 新成语的首字应与上一条成语的尾字相同
@ -193,6 +195,8 @@ class IdiomGame:
self.last_idiom = idiom
self.last_char = idiom[-1]
self.add_score(user_id, 1)
if idiom in IdiomGame.ALL_IDIOMS:
self.add_score(user_id, 4) # 再加 4 分
self.remain_rounds -= 1
if self.remain_rounds <= 0:
self.now_playing = False
@ -201,6 +205,8 @@ class IdiomGame:
# 没有成语可以接了,自动跳过
self._skip_idiom_async()
return TryVerifyState.VERIFIED_BUT_NO_NEXT
if idiom in IdiomGame.ALL_IDIOMS:
return TryVerifyState.VERIFIED_AND_REAL # 真实成语
return TryVerifyState.VERIFIED
def get_user_score(self, user_id: str) -> float:
@ -223,6 +229,13 @@ class IdiomGame:
def get_last_char(self) -> str:
return self.last_char
@classmethod
def random_idiom_starting_with(cls, first_char: str) -> Optional[str]:
cls.init_lexicon()
if first_char not in cls.IDIOM_FIRST_CHAR:
return None
return secrets.choice(cls.IDIOM_FIRST_CHAR[first_char])
@classmethod
def init_lexicon(cls):
@ -288,6 +301,12 @@ class IdiomGame:
cls.IDIOM_FIRST_CHAR[idiom[0]] = []
cls.IDIOM_FIRST_CHAR[idiom[0]].append(idiom)
# 根据真正的成语大表,划分出有效成语首字字典
for idiom in cls.ALL_IDIOMS:
if idiom[0] not in cls.AVALIABLE_IDIOM_FIRST_CHAR:
cls.AVALIABLE_IDIOM_FIRST_CHAR[idiom[0]] = []
cls.AVALIABLE_IDIOM_FIRST_CHAR[idiom[0]].append(idiom)
evt = on_alconna(
Alconna(
@ -421,7 +440,8 @@ async def _(target: DepLongTaskTarget):
instance = IdiomGame.INSTANCE_LIST.get(group_id)
if not instance or not instance.get_playing_state():
return
await evt.send(await UniMessage().text("你们太菜了全部扣100分").export())
avaliable_idiom = IdiomGame.random_idiom_starting_with(instance.get_last_char())
await evt.send(await UniMessage().text(f"你们太菜了全部扣100分明明还可以接「{avaliable_idiom}」的!").export())
idiom = await instance.skip_idiom(-100)
await evt.send(
await UniMessage().text(f"重新开始,下一个成语是「{idiom}").export()
@ -458,16 +478,24 @@ async def _(event: BaseEvent, msg: UniMsg, target: DepLongTaskTarget):
await evt.send(
await UniMessage()
.at(user_id)
.text("接不上!这个不一样!你被扣了 0.1 分!")
.text(" 接不上!这个不一样!你被扣了 0.1 分!")
.export()
)
return
await evt.send(
await UniMessage()
.at(user_id)
.text(f"接对了!你有 {instance.get_user_score(user_id)} 分!")
.export()
)
if state == TryVerifyState.VERIFIED:
await evt.send(
await UniMessage()
.at(user_id)
.text(f" 接上了,喜提 1 分!你有 {instance.get_user_score(user_id)} 分!")
.export()
)
elif state == TryVerifyState.VERIFIED_AND_REAL:
await evt.send(
await UniMessage()
.at(user_id)
.text(f" 接上了,这是个真实成语,喜提 5 分!你有 {instance.get_user_score(user_id)} 分!")
.export()
)
if state == TryVerifyState.VERIFIED_GAME_END:
await evt.send(await UniMessage().text("全部回合结束!").export())
await end_game(event, group_id)

8
poetry.lock generated
View File

@ -2402,14 +2402,14 @@ reference = "mirrors"
[[package]]
name = "ptimeparse"
version = "0.2.0"
version = "0.2.1"
description = "一个用于解析中文的时间表达的库"
optional = false
python-versions = ">=3.9"
groups = ["main"]
files = [
{file = "ptimeparse-0.2.0-py3-none-any.whl", hash = "sha256:57055f8fd99fb69e19deac3b8a5c7ac91af86c7ac09781632e9abf318df0d6d2"},
{file = "ptimeparse-0.2.0.tar.gz", hash = "sha256:867c265f2e157fe4d793d20fe9c449b8ede5c855f336d7e6b2eb78551e622766"},
{file = "ptimeparse-0.2.1-py3-none-any.whl", hash = "sha256:cf1115784d5d983da2d5b7af327108bf04c218c795d63291e71f76d7c6ffd2d4"},
{file = "ptimeparse-0.2.1.tar.gz", hash = "sha256:9b640e0a315d19b1e3821a290d236a051d8320348970ce3a835ed675bd2d832f"},
]
[package.source]
@ -3807,4 +3807,4 @@ reference = "mirrors"
[metadata]
lock-version = "2.1"
python-versions = ">=3.12,<4.0"
content-hash = "02530953efe65da1a788845cd43f8856be62db5bfb59de691cad813f57bab25e"
content-hash = "78a299c64ba07999fae807300b10a1c622d45b8b387aded5a34d17cf5550e777"

View File

@ -20,10 +20,10 @@ dependencies = [
"imagetext-py (>=2.2.0,<3.0.0)",
"opencv-python-headless (>=4.12.0.88,<5.0.0.0)",
"returns (>=0.26.0,<0.27.0)",
"ptimeparse (>=0.1.1,<1.0.0)",
"skia-python (>=138.0,<139.0)",
"nonebot-plugin-analysis-bilibili (>=2.8.1,<3.0.0)",
"qrcode (>=8.2,<9.0)",
"ptimeparse (>=0.2.1,<0.3.0)",
]
[build-system]
@ -41,4 +41,3 @@ url = "https://pypi.tuna.tsinghua.edu.cn/simple/"
priority = "primary"
[tool.poetry.dependencies]
ptimeparse = { source = "pt-gitea-pypi" }