fix: concurrency noi tu
This commit is contained in:
+51
-43
@@ -5,6 +5,7 @@ from core.bot import bot
|
|||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
from typing import Dict, Set, Optional
|
from typing import Dict, Set, Optional
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
import threading
|
||||||
|
|
||||||
# Lazy load repository để tránh lỗi database connection
|
# Lazy load repository để tránh lỗi database connection
|
||||||
noi_tu_repo = None
|
noi_tu_repo = None
|
||||||
@@ -34,6 +35,7 @@ class NoiTuGame:
|
|||||||
self.timer_message = None # Tin nhắn hiển thị thời gian
|
self.timer_message = None # Tin nhắn hiển thị thời gian
|
||||||
self.timer_task = None # Task cập nhật thời gian
|
self.timer_task = None # Task cập nhật thời gian
|
||||||
self.start_time = None # Thời gian bắt đầu game
|
self.start_time = None # Thời gian bắt đầu game
|
||||||
|
self.lock = threading.Lock()
|
||||||
|
|
||||||
# Khởi tạo game state
|
# Khởi tạo game state
|
||||||
game = NoiTuGame()
|
game = NoiTuGame()
|
||||||
@@ -52,6 +54,9 @@ def get_first_word(word: str) -> str:
|
|||||||
def get_last_word(word: str) -> str:
|
def get_last_word(word: str) -> str:
|
||||||
return word.strip().split()[-1] if word else ''
|
return word.strip().split()[-1] if word else ''
|
||||||
|
|
||||||
|
def is_valid(prev, next: str) -> bool:
|
||||||
|
return get_last_word(prev) == get_first_word(next)
|
||||||
|
|
||||||
def format_time_remaining(seconds: int) -> str:
|
def format_time_remaining(seconds: int) -> str:
|
||||||
"""Format thời gian còn lại"""
|
"""Format thời gian còn lại"""
|
||||||
if seconds <= 0:
|
if seconds <= 0:
|
||||||
@@ -324,6 +329,8 @@ async def handle_game_message(message):
|
|||||||
|
|
||||||
# Kiểm tra xem tin nhắn có phải là từ không
|
# Kiểm tra xem tin nhắn có phải là từ không
|
||||||
word = message.content.strip().lower()
|
word = message.content.strip().lower()
|
||||||
|
if len(word.split()) != 2:
|
||||||
|
return
|
||||||
|
|
||||||
# Kiểm tra từ có hợp lệ không
|
# Kiểm tra từ có hợp lệ không
|
||||||
if not await get_noi_tu_repo().is_valid_word(word):
|
if not await get_noi_tu_repo().is_valid_word(word):
|
||||||
@@ -331,14 +338,11 @@ async def handle_game_message(message):
|
|||||||
|
|
||||||
# Kiểm tra người vừa trả lời có trả lời tiếp không
|
# Kiểm tra người vừa trả lời có trả lời tiếp không
|
||||||
if game.last_player_id == message.author.id:
|
if game.last_player_id == message.author.id:
|
||||||
await message.add_reaction('❌')
|
# ignore
|
||||||
await message.channel.send(f"❌ **{message.author.display_name}**, hãy để người khác trả lời!")
|
# await message.add_reaction('❌')
|
||||||
|
# await message.channel.send(f"❌ **{message.author.display_name}**, hãy để người khác trả lời!")
|
||||||
return
|
return
|
||||||
|
|
||||||
# Kiểm tra từ có tồn tại trong DB không
|
|
||||||
if not await get_noi_tu_repo().is_exist(word):
|
|
||||||
await message.add_reaction('❌')
|
|
||||||
return
|
|
||||||
|
|
||||||
# Kiểm tra từ đã được sử dụng chưa
|
# Kiểm tra từ đã được sử dụng chưa
|
||||||
if word in game.used_words:
|
if word in game.used_words:
|
||||||
@@ -348,42 +352,46 @@ async def handle_game_message(message):
|
|||||||
|
|
||||||
# Kiểm tra quy tắc nối từ ghép
|
# Kiểm tra quy tắc nối từ ghép
|
||||||
if game.current_word:
|
if game.current_word:
|
||||||
last = get_last_word(game.current_word)
|
if not is_valid(game.current_word, word):
|
||||||
first = get_first_word(word)
|
|
||||||
if first != last:
|
|
||||||
await message.add_reaction('❌')
|
|
||||||
await message.channel.send(f"❌ Từ mới phải bắt đầu bằng từ: '{last.upper()}'!")
|
|
||||||
return
|
return
|
||||||
|
|
||||||
# Từ hợp lệ
|
# Kiểm tra từ có tồn tại trong DB không
|
||||||
await message.add_reaction('✅')
|
if not await get_noi_tu_repo().is_exist(word):
|
||||||
|
await message.add_reaction('❌')
|
||||||
# Cập nhật game state
|
return
|
||||||
game.current_word = word
|
|
||||||
game.used_words.add(word)
|
with game.lock:
|
||||||
game.last_player_id = message.author.id
|
if not is_valid(game.current_word, word):
|
||||||
game.last_player_name = message.author.display_name # Lưu tên người chơi
|
return
|
||||||
game.last_message_time = datetime.now()
|
# Từ hợp lệ
|
||||||
|
await message.add_reaction('✅')
|
||||||
# Reset timeout
|
|
||||||
if game.timeout_task:
|
# Cập nhật game state
|
||||||
game.timeout_task.cancel()
|
game.current_word = word
|
||||||
game.timeout_task = asyncio.create_task(game_timeout())
|
game.used_words.add(word)
|
||||||
|
game.last_player_id = message.author.id
|
||||||
# Dừng timer task cũ nếu có
|
game.last_player_name = message.author.display_name # Lưu tên người chơi
|
||||||
if game.timer_task:
|
game.last_message_time = datetime.now()
|
||||||
game.timer_task.cancel()
|
|
||||||
|
# Reset timeout
|
||||||
# Thông báo từ tiếp theo
|
if game.timeout_task:
|
||||||
next_hint = get_last_word(word).upper()
|
game.timeout_task.cancel()
|
||||||
embed = discord.Embed(
|
game.timeout_task = asyncio.create_task(game_timeout())
|
||||||
title="⏰ Còn lại: 30 giây",
|
|
||||||
color=discord.Color.blue()
|
# Dừng timer task cũ nếu có
|
||||||
)
|
if game.timer_task:
|
||||||
|
game.timer_task.cancel()
|
||||||
# Gửi tin nhắn mới và lưu reference
|
|
||||||
game.timer_message = await message.channel.send(embed=embed)
|
# Thông báo từ tiếp theo
|
||||||
|
next_hint = get_last_word(word).upper()
|
||||||
# Bắt đầu task cập nhật thời gian
|
embed = discord.Embed(
|
||||||
game.timer_task = asyncio.create_task(update_timer_message())
|
title="⏰ Còn lại: 30 giây",
|
||||||
|
color=discord.Color.blue()
|
||||||
|
)
|
||||||
|
|
||||||
|
# Gửi tin nhắn mới và lưu reference
|
||||||
|
game.timer_message = await message.channel.send(embed=embed)
|
||||||
|
|
||||||
|
# Bắt đầu task cập nhật thời gian
|
||||||
|
game.timer_task = asyncio.create_task(update_timer_message())
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user