update for python 3.10
This commit is contained in:
parent
533ad72741
commit
99f7055178
2 changed files with 39 additions and 44 deletions
2
cards.py
2
cards.py
|
@ -371,7 +371,7 @@ def reveal(update, context):
|
||||||
and type((btn := kbd[0][0])) is InlineKeyboardButton and (data := btn.callback_data)
|
and type((btn := kbd[0][0])) is InlineKeyboardButton and (data := btn.callback_data)
|
||||||
data = data.split(' ')
|
data = data.split(' ')
|
||||||
data = [int(i) for i in data]
|
data = [int(i) for i in data]
|
||||||
(bhash, _, _) = data
|
(bhash, _, _, _) = data
|
||||||
except:
|
except:
|
||||||
msg.reply_text('不是一条有效的消息')
|
msg.reply_text('不是一条有效的消息')
|
||||||
return
|
return
|
||||||
|
|
81
tgmsbot.py
81
tgmsbot.py
|
@ -3,12 +3,12 @@
|
||||||
from mscore import Board, check_params
|
from mscore import Board, check_params
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
from telegram import InlineKeyboardMarkup, InlineKeyboardButton
|
from telegram import InlineKeyboardMarkup, InlineKeyboardButton
|
||||||
from telegram.ext import Updater, CommandHandler, CallbackQueryHandler, run_async
|
from telegram.ext import Updater, CommandHandler, CallbackQueryHandler
|
||||||
from telegram.error import TimedOut as TimedOutError, RetryAfter as RetryAfterError
|
from telegram.error import TimedOut as TimedOutError, RetryAfter as RetryAfterError
|
||||||
from numpy import array_equal
|
from numpy import array_equal
|
||||||
from random import randint, choice, randrange
|
from random import randint, choice, randrange
|
||||||
from math import log
|
from math import log
|
||||||
from threading import Lock
|
from threading import Lock, Thread
|
||||||
import time
|
import time
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import pickle
|
import pickle
|
||||||
|
@ -48,7 +48,7 @@ NUM_CELL_ORD = ord("\uff11") - 1
|
||||||
|
|
||||||
WIN_TEXT_TEMPLATE = "哇所有奇怪的地方都被你打开啦…好羞羞\n" \
|
WIN_TEXT_TEMPLATE = "哇所有奇怪的地方都被你打开啦…好羞羞\n" \
|
||||||
"地图:Op {s_op} / Is {s_is} / 3bv {s_3bv}\n操作总数 {ops_count}\n" \
|
"地图:Op {s_op} / Is {s_is} / 3bv {s_3bv}\n操作总数 {ops_count}\n" \
|
||||||
"统计:\n{ops_list}\n{last_player} 你要对人家负责哟/// ///\n\n" \
|
"统计:\n{ops_list}\n\n{last_player} 你要对人家负责哟/// ///\n\n" \
|
||||||
"用时{time}秒,超时{timeouts}次\n\n" \
|
"用时{time}秒,超时{timeouts}次\n\n" \
|
||||||
"{last_player} {reward}\n\n" \
|
"{last_player} {reward}\n\n" \
|
||||||
"/mine 开始新游戏"
|
"/mine 开始新游戏"
|
||||||
|
@ -58,11 +58,17 @@ STEP_TEXT_TEMPLATE = "{last_player} 踩到了地雷!\n" \
|
||||||
"雷区生命值:({remain}/{ttl})"
|
"雷区生命值:({remain}/{ttl})"
|
||||||
LOSE_TEXT_TEMPLATE = "一道火光之后,你就在天上飞了呢…好奇怪喵\n" \
|
LOSE_TEXT_TEMPLATE = "一道火光之后,你就在天上飞了呢…好奇怪喵\n" \
|
||||||
"地图:Op {s_op} / Is {s_is} / 3bv {s_3bv}\n操作总数 {ops_count}\n" \
|
"地图:Op {s_op} / Is {s_is} / 3bv {s_3bv}\n操作总数 {ops_count}\n" \
|
||||||
"统计:\n{ops_list}\n{last_player} 是我们中出的叛徒!\n\n" \
|
"统计:\n{ops_list}\n\n{last_player} 是我们中出的叛徒!\n\n" \
|
||||||
"用时{time}秒,超时{timeouts}次\n\n" \
|
"用时{time}秒,超时{timeouts}次\n\n" \
|
||||||
"{last_player} {reward}\n\n" \
|
"{last_player} {reward}\n\n" \
|
||||||
"/mine 开始新游戏"
|
"/mine 开始新游戏"
|
||||||
|
|
||||||
|
def run_async(func):
|
||||||
|
def wrapped(*args, **kwargs):
|
||||||
|
tr = Thread(target=func, args=args, kwargs=kwargs, daemon=True)
|
||||||
|
tr.start()
|
||||||
|
return tr
|
||||||
|
return wrapped
|
||||||
|
|
||||||
def display_username(user, atuser=True, shorten=False, markdown=True):
|
def display_username(user, atuser=True, shorten=False, markdown=True):
|
||||||
"""
|
"""
|
||||||
|
@ -81,7 +87,7 @@ def display_username(user, atuser=True, shorten=False, markdown=True):
|
||||||
name += " ({})".format(user.username)
|
name += " ({})".format(user.username)
|
||||||
return name
|
return name
|
||||||
|
|
||||||
class Saved_Game:
|
class Game:
|
||||||
def __init__(self, board, group, creator, lives=1):
|
def __init__(self, board, group, creator, lives=1):
|
||||||
self.board = board
|
self.board = board
|
||||||
self.group = group
|
self.group = group
|
||||||
|
@ -99,13 +105,19 @@ class Saved_Game:
|
||||||
self.timeouts = 0
|
self.timeouts = 0
|
||||||
self.lives = lives
|
self.lives = lives
|
||||||
self.ttl_lives = lives
|
self.ttl_lives = lives
|
||||||
|
self.lock = Lock()
|
||||||
|
def __getstate__(self):
|
||||||
|
""" https://docs.python.org/3/library/pickle.html#handling-stateful-objects """
|
||||||
|
state = self.__dict__.copy()
|
||||||
|
del state['lock']
|
||||||
|
return state
|
||||||
|
def __setstate__(self, state):
|
||||||
|
self.__dict__.update(state)
|
||||||
|
self.lock = Lock()
|
||||||
def save_action(self, user, spot):
|
def save_action(self, user, spot):
|
||||||
'''spot is supposed to be a tuple'''
|
'''spot is supposed to be a tuple'''
|
||||||
self.last_player = user
|
self.last_player = user
|
||||||
if self.__actions.get(user, None):
|
self.__actions.setdefault(user, list()).append(spot)
|
||||||
self.__actions[user].append(spot)
|
|
||||||
else:
|
|
||||||
self.__actions[user] = [spot,]
|
|
||||||
def actions_sum(self):
|
def actions_sum(self):
|
||||||
mysum = 0
|
mysum = 0
|
||||||
for user in self.__actions:
|
for user in self.__actions:
|
||||||
|
@ -117,44 +129,24 @@ class Saved_Game:
|
||||||
return display_username(self.last_player)
|
return display_username(self.last_player)
|
||||||
def get_actions(self):
|
def get_actions(self):
|
||||||
'''Convert actions into text'''
|
'''Convert actions into text'''
|
||||||
msg = ""
|
msg_l = list()
|
||||||
for user in self.__actions:
|
for user in self.__actions:
|
||||||
count = len(self.__actions.get(user, list()))
|
count = len(self.__actions.get(user, list()))
|
||||||
msg = "{}{} - {}项操作\n".format(msg, display_username(user), count)
|
msg_l.append(f"{display_username(user)} - {count}项操作")
|
||||||
return msg
|
return "\n".join(msg_l)
|
||||||
|
|
||||||
class Game:
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
if 'unpickle' in args:
|
|
||||||
assert len(args) == 2 and args[0] == 'unpickle'
|
|
||||||
self.__sg = args[1]
|
|
||||||
else:
|
|
||||||
self.__sg = Saved_Game(*args, **kwargs)
|
|
||||||
self.lock = Lock()
|
|
||||||
def pickle(self):
|
|
||||||
return self.__sg
|
|
||||||
def __getattr__(self, name):
|
|
||||||
return getattr(self.__sg, name)
|
|
||||||
def __setattr__(self, name, val):
|
|
||||||
if name in ('_Game__sg', 'lock'):
|
|
||||||
self.__dict__[name] = val
|
|
||||||
else:
|
|
||||||
return setattr(self.__sg, name, val)
|
|
||||||
|
|
||||||
class GameManager:
|
class GameManager:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
self.__savelock = Lock()
|
||||||
self.__games = dict()
|
self.__games = dict()
|
||||||
self.__pf = Path(PICKLE_FILE)
|
self.__pf = Path(PICKLE_FILE)
|
||||||
if self.__pf.exists():
|
if self.__pf.exists():
|
||||||
try:
|
try:
|
||||||
with open(self.__pf, 'rb') as fhandle:
|
with open(self.__pf, 'rb') as fhandle:
|
||||||
saved_games = pickle.load(fhandle, fix_imports=True, errors="strict")
|
self.__games = pickle.load(fhandle, fix_imports=True, errors="strict")
|
||||||
self.__games = {bhash: Game('unpickle', saved_games[bhash]) for bhash in saved_games}
|
except Exception:
|
||||||
except Exception as err:
|
logger.exception('Unable to load pickle file')
|
||||||
logger.error(f'Unable to load pickle file, {type(err).__name__}: {err}')
|
|
||||||
assert type(self.__games) is dict
|
assert type(self.__games) is dict
|
||||||
for board_hash in self.__games:
|
|
||||||
self.__games[board_hash].lock = Lock()
|
|
||||||
def append(self, board, board_hash, group_id, creator_id):
|
def append(self, board, board_hash, group_id, creator_id):
|
||||||
lives = int(board.mines/3)
|
lives = int(board.mines/3)
|
||||||
if lives <= 0:
|
if lives <= 0:
|
||||||
|
@ -187,15 +179,18 @@ class GameManager:
|
||||||
def count(self):
|
def count(self):
|
||||||
return len(self.__games)
|
return len(self.__games)
|
||||||
@run_async
|
@run_async
|
||||||
def save_async(self):
|
def save_async(self, timeout=1):
|
||||||
self.save()
|
self.save(timeout=timeout)
|
||||||
def save(self):
|
def save(self, timeout=-1):
|
||||||
|
if not self.__savelock.acquire(timeout=timeout):
|
||||||
|
return
|
||||||
try:
|
try:
|
||||||
games_without_locks = {bhash: self.__games[bhash].pickle() for bhash in self.__games}
|
|
||||||
with open(self.__pf, 'wb') as fhandle:
|
with open(self.__pf, 'wb') as fhandle:
|
||||||
pickle.dump(games_without_locks, fhandle, fix_imports=True)
|
pickle.dump(self.__games, fhandle, fix_imports=True)
|
||||||
except Exception as err:
|
except Exception:
|
||||||
logger.error(f'Unable to save pickle file, {type(err).__name__}: {err}')
|
logger.exception('Unable to save pickle file')
|
||||||
|
finally:
|
||||||
|
self.__savelock.release()
|
||||||
def do_garbage_collection(self, context):
|
def do_garbage_collection(self, context):
|
||||||
g_checked: int = 0
|
g_checked: int = 0
|
||||||
g_freed: int = 0
|
g_freed: int = 0
|
||||||
|
|
Loading…
Reference in a new issue