libs.commands.registry.team
libs/registry/team.py
1""" 2libs/registry/team.py 3""" 4 5import logging 6from typing import TYPE_CHECKING, TypedDict, cast 7 8import libs.global_value as g 9from libs.bootstrap import initialization 10from libs.bootstrap.section import BaseSection 11from libs.domain import modify 12from libs.types import CommandType 13from libs.utils import dbutil, formatter, textutil, validator 14 15if TYPE_CHECKING: 16 from configparser import ConfigParser, SectionProxy 17 18 from libs.bootstrap.app_config import AppConfig 19 20 21class TeamDataDict(TypedDict): 22 """チーム情報格納辞書""" 23 24 id: int 25 """チームID""" 26 team: str 27 """チーム名""" 28 members: list[str] 29 """所属メンバーリスト""" 30 31 32class TeamSection(BaseSection): 33 """teamセクション処理""" 34 35 default_commandword: str 36 """コマンドワードデフォルト値""" 37 commandword: list[str] 38 """呼び出しキーワード""" 39 command_suffix: list[str] 40 """コマンド接尾辞(登録キーワード+接尾辞を呼び出しキーワードとして扱う)""" 41 42 section: str 43 main_parser: "ConfigParser" 44 45 info: list[TeamDataDict] 46 """チーム情報(キャッシュデータ)""" 47 registration_limit: int 48 """登録チーム上限数""" 49 character_limit: int 50 """チーム名に使用できる文字数""" 51 member_limit: int 52 """チームに所属できるメンバー上限""" 53 friendly_fire: bool 54 """チームメイトが同卓しているゲームを集計対象に含めるか""" 55 56 def __init__(self, outer: "AppConfig") -> None: 57 self.default_commandword = "チーム一覧" 58 self.section = str(CommandType.TEAM_LIST) 59 self.main_parser = outer.main_parser 60 self._reset() 61 62 def _reset(self) -> None: 63 self.info = [] 64 self.commandword = [] 65 self.command_suffix = [] 66 self.registration_limit = int(255) 67 self.character_limit = int(16) 68 self.member_limit = int(16) 69 self.friendly_fire = bool(True) 70 71 def config_load(self, section_proxy: "SectionProxy") -> None: 72 """ 73 設定値取り込み 74 75 Args: 76 section_proxy (SectionProxy): 読み込み先(パーサー + セクション名) 77 78 """ 79 self._reset() 80 self.initialization(section_proxy) 81 82 # 呼び出しキーワード取り込み 83 self.commandword = self.getlist("commandword", fallback=self.default_commandword) 84 85 logging.trace("%s: %s", self.section, self) # type: ignore 86 87 def member(self, team: str) -> list[str]: 88 """ 89 指定チームの所属メンバーをリストで返す 90 91 Args: 92 team (str): 対象チーム名 93 94 Returns: 95 list[str]: 所属メンバーリスト 96 97 """ 98 for x in self.info: 99 if x.get("team") == team: 100 return x.get("members") 101 return [] 102 103 def which(self, name: str) -> str | None: 104 """ 105 指定メンバーの所属チームを返す 106 107 Args: 108 name (str): 対象メンバー名 109 110 Returns: 111 Union[str, None]: 112 - str: 所属しているチーム名 113 - None: 未所属 114 115 """ 116 for team in self.lists: 117 if name in self.member(team): 118 return team 119 120 return None 121 122 @property 123 def lists(self) -> list[str]: 124 """ 125 チーム名一覧をリストで返す 126 127 Returns: 128 list[str]: チーム名一覧 129 130 """ 131 return [x.get("team") for x in self.info] 132 133 @property 134 def get_info(self) -> list[TeamDataDict]: 135 """ 136 全チーム情報取得 137 138 Returns: 139 list[TeamDataDict]: チーム情報 140 141 """ 142 ret = g.params.read_data("TEAM_INFO").to_dict(orient="records") 143 for row in ret: 144 row.update(members=str(row["members"]).split(",")) 145 146 return cast(list[TeamDataDict], ret) 147 148 149def create(argument: list[str]) -> str: 150 """ 151 チーム作成 152 153 Args: 154 argument (list[str]): 作成するチーム名 155 156 Returns: 157 str: 処理結果 158 159 """ 160 ret = False 161 msg = "使い方が間違っています。" 162 163 if len(argument) == 1: # 新規追加 164 team_name = textutil.str_conv(argument[0], textutil.ConversionType.HtoZ) 165 if len(g.cfg.team.lists) > g.cfg.team.registration_limit: 166 msg = "登録上限を超えています。" 167 else: # 登録処理 168 ret, msg = validator.check_namepattern(team_name, "team") 169 if ret: 170 resultdb = dbutil.connection(g.cfg.setting.database_file) 171 resultdb.execute( 172 "insert into team(name) values (?)", 173 (team_name,), 174 ) 175 resultdb.commit() 176 resultdb.close() 177 g.cfg.team.info = g.cfg.team.get_info 178 msg = f"チーム「{team_name}」を登録しました。" 179 logging.info("add new team: %s", team_name) 180 181 return msg 182 183 184def delete(argument: list[str]) -> str: 185 """ 186 チーム削除 187 188 Args: 189 argument (list[str]): 削除するチーム名 190 191 Returns: 192 str: 処理結果 193 194 """ 195 msg = "使い方が間違っています。" 196 197 if len(argument) == 1: # 新規追加 198 team_name = textutil.str_conv(argument[0], textutil.ConversionType.HtoZ) 199 if team_name not in g.cfg.team.lists: # 未登録チームチェック 200 msg = f"チーム「{team_name}」は登録されていません。" 201 else: 202 msg = modify.db_backup() 203 team_id = [x["id"] for x in g.cfg.team.info if x["team"] == team_name][0] 204 resultdb = dbutil.connection(g.cfg.setting.database_file) 205 resultdb.execute("delete from team where id = ?", (team_id,)) 206 resultdb.execute( 207 "update member set team_id = null where team_id = ?", 208 (team_id,), 209 ) 210 resultdb.commit() 211 resultdb.close() 212 g.cfg.team.info = g.cfg.team.get_info 213 msg += f"\nチーム「{team_name}」を削除しました。" 214 logging.info("team delete: %s", team_name) 215 216 return msg 217 218 219def append(argument: list[str]) -> str: 220 """ 221 チーム所属 222 223 Args: 224 argument (list[str]): 登録情報 225 - argument[0]: 所属させるチーム名 226 - argument[1]: 所属するメンバー名 227 228 Returns: 229 str: 処理結果 230 231 """ 232 msg = "使い方が間違っています。" 233 234 if len(argument) == 1: # 新規作成 235 msg = create(argument) 236 237 if len(argument) == 2: # チーム所属 238 g.params.unregistered_replace = False 239 240 team_name = textutil.str_conv(argument[0], textutil.ConversionType.HtoZ) 241 player_name = formatter.name_replace(argument[1]) 242 registration_flg = True 243 team_id = None 244 245 if team_name not in g.cfg.team.lists: # 未登録チームチェック 246 msg = f"チーム「{team_name}」はまだ登録されていません。" 247 registration_flg = False 248 else: 249 team_id = [x["id"] for x in g.cfg.team.info if x["team"] == team_name][0] 250 251 if player_name not in g.cfg.member.lists: # 未登録プレイヤーチェック 252 msg = f"「{player_name}」はレギュラーメンバーではありません。" 253 registration_flg = False 254 255 # 登録上限を超えていないか? 256 # select count() from member where team_id=? group by team_id; 257 # rows = resultdb.execute("select count() from team where name=?", (team_name,)) 258 # count = rows.fetchone()[0] 259 # if count > g.cfg.team.member_limit: 260 # msg = f"登録上限を超えています。" 261 # registration_flg = False 262 263 if registration_flg and team_id: # 登録処理 264 resultdb = dbutil.connection(g.cfg.setting.database_file) 265 resultdb.execute( 266 "update member set team_id = ? where name = ?", 267 (team_id, player_name), 268 ) 269 resultdb.commit() 270 resultdb.close() 271 g.cfg.team.info = g.cfg.team.get_info 272 msg = f"チーム「{team_name}」に「{player_name}」を所属させました。" 273 logging.info("team participation: %s -> %s", team_name, player_name) 274 275 return msg 276 277 278def remove(argument: list[str]) -> str: 279 """ 280 チームから除名 281 282 Args: 283 argument (list[str]): 登録情報 284 - argument[0]: 対象チーム名 285 - argument[1]: チームから離脱するメンバー名 286 287 Returns: 288 str: 処理結果 289 290 """ 291 msg = "使い方が間違っています。" 292 293 resultdb = dbutil.connection(g.cfg.setting.database_file) 294 295 if len(argument) == 1: 296 msg = delete(argument) 297 298 if len(argument) == 2: # チーム名指 299 g.params.unregistered_replace = False 300 team_name = textutil.str_conv(argument[0], textutil.ConversionType.HtoZ) 301 player_name = formatter.name_replace(argument[1]) 302 303 registration_flg = True 304 team_id = None 305 306 if team_name not in g.cfg.team.lists: # 未登録チームチェック 307 msg = f"チーム「{team_name}」は登録されていません。" 308 registration_flg = False 309 else: 310 team_id = [x["id"] for x in g.cfg.team.info if x["team"] == team_name][0] 311 312 if player_name not in g.cfg.member.lists: # 未登録プレイヤーチェック 313 msg = f"「{player_name}」はレギュラーメンバーではありません。" 314 registration_flg = False 315 316 if registration_flg and team_id: # 登録処理 317 resultdb = dbutil.connection(g.cfg.setting.database_file) 318 resultdb.execute( 319 "update member set team_id = null where name = ?", 320 (player_name,), 321 ) 322 resultdb.commit() 323 resultdb.close() 324 g.cfg.team.info = g.cfg.team.get_info 325 msg = f"チーム「{team_name}」から「{player_name}」を離脱させました。" 326 logging.info("team breakaway: %s -> %s", team_name, player_name) 327 328 return msg 329 330 331def clear() -> str: 332 """ 333 全チーム削除 334 335 Returns: 336 str: 処理結果 337 338 """ 339 msg = modify.db_backup() 340 341 resultdb = dbutil.connection(g.cfg.setting.database_file) 342 resultdb.execute("update member set team_id = null;") 343 resultdb.execute("drop table team;") 344 resultdb.execute("delete from sqlite_sequence where name = 'team';") 345 resultdb.commit() 346 resultdb.close() 347 348 initialization.setup_resultdb(g.cfg.setting.database_file) 349 g.cfg.member.info = g.cfg.member.get_info 350 g.cfg.team.info = g.cfg.team.get_info 351 352 return msg
class
TeamDataDict(typing.TypedDict):
22class TeamDataDict(TypedDict): 23 """チーム情報格納辞書""" 24 25 id: int 26 """チームID""" 27 team: str 28 """チーム名""" 29 members: list[str] 30 """所属メンバーリスト"""
チーム情報格納辞書
33class TeamSection(BaseSection): 34 """teamセクション処理""" 35 36 default_commandword: str 37 """コマンドワードデフォルト値""" 38 commandword: list[str] 39 """呼び出しキーワード""" 40 command_suffix: list[str] 41 """コマンド接尾辞(登録キーワード+接尾辞を呼び出しキーワードとして扱う)""" 42 43 section: str 44 main_parser: "ConfigParser" 45 46 info: list[TeamDataDict] 47 """チーム情報(キャッシュデータ)""" 48 registration_limit: int 49 """登録チーム上限数""" 50 character_limit: int 51 """チーム名に使用できる文字数""" 52 member_limit: int 53 """チームに所属できるメンバー上限""" 54 friendly_fire: bool 55 """チームメイトが同卓しているゲームを集計対象に含めるか""" 56 57 def __init__(self, outer: "AppConfig") -> None: 58 self.default_commandword = "チーム一覧" 59 self.section = str(CommandType.TEAM_LIST) 60 self.main_parser = outer.main_parser 61 self._reset() 62 63 def _reset(self) -> None: 64 self.info = [] 65 self.commandword = [] 66 self.command_suffix = [] 67 self.registration_limit = int(255) 68 self.character_limit = int(16) 69 self.member_limit = int(16) 70 self.friendly_fire = bool(True) 71 72 def config_load(self, section_proxy: "SectionProxy") -> None: 73 """ 74 設定値取り込み 75 76 Args: 77 section_proxy (SectionProxy): 読み込み先(パーサー + セクション名) 78 79 """ 80 self._reset() 81 self.initialization(section_proxy) 82 83 # 呼び出しキーワード取り込み 84 self.commandword = self.getlist("commandword", fallback=self.default_commandword) 85 86 logging.trace("%s: %s", self.section, self) # type: ignore 87 88 def member(self, team: str) -> list[str]: 89 """ 90 指定チームの所属メンバーをリストで返す 91 92 Args: 93 team (str): 対象チーム名 94 95 Returns: 96 list[str]: 所属メンバーリスト 97 98 """ 99 for x in self.info: 100 if x.get("team") == team: 101 return x.get("members") 102 return [] 103 104 def which(self, name: str) -> str | None: 105 """ 106 指定メンバーの所属チームを返す 107 108 Args: 109 name (str): 対象メンバー名 110 111 Returns: 112 Union[str, None]: 113 - str: 所属しているチーム名 114 - None: 未所属 115 116 """ 117 for team in self.lists: 118 if name in self.member(team): 119 return team 120 121 return None 122 123 @property 124 def lists(self) -> list[str]: 125 """ 126 チーム名一覧をリストで返す 127 128 Returns: 129 list[str]: チーム名一覧 130 131 """ 132 return [x.get("team") for x in self.info] 133 134 @property 135 def get_info(self) -> list[TeamDataDict]: 136 """ 137 全チーム情報取得 138 139 Returns: 140 list[TeamDataDict]: チーム情報 141 142 """ 143 ret = g.params.read_data("TEAM_INFO").to_dict(orient="records") 144 for row in ret: 145 row.update(members=str(row["members"]).split(",")) 146 147 return cast(list[TeamDataDict], ret)
teamセクション処理
TeamSection(outer: libs.bootstrap.app_config.AppConfig)
def
config_load(self, section_proxy: configparser.SectionProxy) -> None:
72 def config_load(self, section_proxy: "SectionProxy") -> None: 73 """ 74 設定値取り込み 75 76 Args: 77 section_proxy (SectionProxy): 読み込み先(パーサー + セクション名) 78 79 """ 80 self._reset() 81 self.initialization(section_proxy) 82 83 # 呼び出しキーワード取り込み 84 self.commandword = self.getlist("commandword", fallback=self.default_commandword) 85 86 logging.trace("%s: %s", self.section, self) # type: ignore
設定値取り込み
Arguments:
- section_proxy (SectionProxy): 読み込み先(パーサー + セクション名)
def
member(self, team: str) -> list[str]:
88 def member(self, team: str) -> list[str]: 89 """ 90 指定チームの所属メンバーをリストで返す 91 92 Args: 93 team (str): 対象チーム名 94 95 Returns: 96 list[str]: 所属メンバーリスト 97 98 """ 99 for x in self.info: 100 if x.get("team") == team: 101 return x.get("members") 102 return []
指定チームの所属メンバーをリストで返す
Arguments:
- team (str): 対象チーム名
Returns:
list[str]: 所属メンバーリスト
def
which(self, name: str) -> str | None:
104 def which(self, name: str) -> str | None: 105 """ 106 指定メンバーの所属チームを返す 107 108 Args: 109 name (str): 対象メンバー名 110 111 Returns: 112 Union[str, None]: 113 - str: 所属しているチーム名 114 - None: 未所属 115 116 """ 117 for team in self.lists: 118 if name in self.member(team): 119 return team 120 121 return None
指定メンバーの所属チームを返す
Arguments:
- name (str): 対象メンバー名
Returns:
Union[str, None]:
- str: 所属しているチーム名
- None: 未所属
lists: list[str]
123 @property 124 def lists(self) -> list[str]: 125 """ 126 チーム名一覧をリストで返す 127 128 Returns: 129 list[str]: チーム名一覧 130 131 """ 132 return [x.get("team") for x in self.info]
チーム名一覧をリストで返す
Returns:
list[str]: チーム名一覧
get_info: list[TeamDataDict]
134 @property 135 def get_info(self) -> list[TeamDataDict]: 136 """ 137 全チーム情報取得 138 139 Returns: 140 list[TeamDataDict]: チーム情報 141 142 """ 143 ret = g.params.read_data("TEAM_INFO").to_dict(orient="records") 144 for row in ret: 145 row.update(members=str(row["members"]).split(",")) 146 147 return cast(list[TeamDataDict], ret)
全チーム情報取得
Returns:
list[TeamDataDict]: チーム情報
def
create(argument: list[str]) -> str:
150def create(argument: list[str]) -> str: 151 """ 152 チーム作成 153 154 Args: 155 argument (list[str]): 作成するチーム名 156 157 Returns: 158 str: 処理結果 159 160 """ 161 ret = False 162 msg = "使い方が間違っています。" 163 164 if len(argument) == 1: # 新規追加 165 team_name = textutil.str_conv(argument[0], textutil.ConversionType.HtoZ) 166 if len(g.cfg.team.lists) > g.cfg.team.registration_limit: 167 msg = "登録上限を超えています。" 168 else: # 登録処理 169 ret, msg = validator.check_namepattern(team_name, "team") 170 if ret: 171 resultdb = dbutil.connection(g.cfg.setting.database_file) 172 resultdb.execute( 173 "insert into team(name) values (?)", 174 (team_name,), 175 ) 176 resultdb.commit() 177 resultdb.close() 178 g.cfg.team.info = g.cfg.team.get_info 179 msg = f"チーム「{team_name}」を登録しました。" 180 logging.info("add new team: %s", team_name) 181 182 return msg
チーム作成
Arguments:
- argument (list[str]): 作成するチーム名
Returns:
str: 処理結果
def
delete(argument: list[str]) -> str:
185def delete(argument: list[str]) -> str: 186 """ 187 チーム削除 188 189 Args: 190 argument (list[str]): 削除するチーム名 191 192 Returns: 193 str: 処理結果 194 195 """ 196 msg = "使い方が間違っています。" 197 198 if len(argument) == 1: # 新規追加 199 team_name = textutil.str_conv(argument[0], textutil.ConversionType.HtoZ) 200 if team_name not in g.cfg.team.lists: # 未登録チームチェック 201 msg = f"チーム「{team_name}」は登録されていません。" 202 else: 203 msg = modify.db_backup() 204 team_id = [x["id"] for x in g.cfg.team.info if x["team"] == team_name][0] 205 resultdb = dbutil.connection(g.cfg.setting.database_file) 206 resultdb.execute("delete from team where id = ?", (team_id,)) 207 resultdb.execute( 208 "update member set team_id = null where team_id = ?", 209 (team_id,), 210 ) 211 resultdb.commit() 212 resultdb.close() 213 g.cfg.team.info = g.cfg.team.get_info 214 msg += f"\nチーム「{team_name}」を削除しました。" 215 logging.info("team delete: %s", team_name) 216 217 return msg
チーム削除
Arguments:
- argument (list[str]): 削除するチーム名
Returns:
str: 処理結果
def
append(argument: list[str]) -> str:
220def append(argument: list[str]) -> str: 221 """ 222 チーム所属 223 224 Args: 225 argument (list[str]): 登録情報 226 - argument[0]: 所属させるチーム名 227 - argument[1]: 所属するメンバー名 228 229 Returns: 230 str: 処理結果 231 232 """ 233 msg = "使い方が間違っています。" 234 235 if len(argument) == 1: # 新規作成 236 msg = create(argument) 237 238 if len(argument) == 2: # チーム所属 239 g.params.unregistered_replace = False 240 241 team_name = textutil.str_conv(argument[0], textutil.ConversionType.HtoZ) 242 player_name = formatter.name_replace(argument[1]) 243 registration_flg = True 244 team_id = None 245 246 if team_name not in g.cfg.team.lists: # 未登録チームチェック 247 msg = f"チーム「{team_name}」はまだ登録されていません。" 248 registration_flg = False 249 else: 250 team_id = [x["id"] for x in g.cfg.team.info if x["team"] == team_name][0] 251 252 if player_name not in g.cfg.member.lists: # 未登録プレイヤーチェック 253 msg = f"「{player_name}」はレギュラーメンバーではありません。" 254 registration_flg = False 255 256 # 登録上限を超えていないか? 257 # select count() from member where team_id=? group by team_id; 258 # rows = resultdb.execute("select count() from team where name=?", (team_name,)) 259 # count = rows.fetchone()[0] 260 # if count > g.cfg.team.member_limit: 261 # msg = f"登録上限を超えています。" 262 # registration_flg = False 263 264 if registration_flg and team_id: # 登録処理 265 resultdb = dbutil.connection(g.cfg.setting.database_file) 266 resultdb.execute( 267 "update member set team_id = ? where name = ?", 268 (team_id, player_name), 269 ) 270 resultdb.commit() 271 resultdb.close() 272 g.cfg.team.info = g.cfg.team.get_info 273 msg = f"チーム「{team_name}」に「{player_name}」を所属させました。" 274 logging.info("team participation: %s -> %s", team_name, player_name) 275 276 return msg
チーム所属
Arguments:
- argument (list[str]): 登録情報
- argument[0]: 所属させるチーム名
- argument[1]: 所属するメンバー名
Returns:
str: 処理結果
def
remove(argument: list[str]) -> str:
279def remove(argument: list[str]) -> str: 280 """ 281 チームから除名 282 283 Args: 284 argument (list[str]): 登録情報 285 - argument[0]: 対象チーム名 286 - argument[1]: チームから離脱するメンバー名 287 288 Returns: 289 str: 処理結果 290 291 """ 292 msg = "使い方が間違っています。" 293 294 resultdb = dbutil.connection(g.cfg.setting.database_file) 295 296 if len(argument) == 1: 297 msg = delete(argument) 298 299 if len(argument) == 2: # チーム名指 300 g.params.unregistered_replace = False 301 team_name = textutil.str_conv(argument[0], textutil.ConversionType.HtoZ) 302 player_name = formatter.name_replace(argument[1]) 303 304 registration_flg = True 305 team_id = None 306 307 if team_name not in g.cfg.team.lists: # 未登録チームチェック 308 msg = f"チーム「{team_name}」は登録されていません。" 309 registration_flg = False 310 else: 311 team_id = [x["id"] for x in g.cfg.team.info if x["team"] == team_name][0] 312 313 if player_name not in g.cfg.member.lists: # 未登録プレイヤーチェック 314 msg = f"「{player_name}」はレギュラーメンバーではありません。" 315 registration_flg = False 316 317 if registration_flg and team_id: # 登録処理 318 resultdb = dbutil.connection(g.cfg.setting.database_file) 319 resultdb.execute( 320 "update member set team_id = null where name = ?", 321 (player_name,), 322 ) 323 resultdb.commit() 324 resultdb.close() 325 g.cfg.team.info = g.cfg.team.get_info 326 msg = f"チーム「{team_name}」から「{player_name}」を離脱させました。" 327 logging.info("team breakaway: %s -> %s", team_name, player_name) 328 329 return msg
チームから除名
Arguments:
- argument (list[str]): 登録情報
- argument[0]: 対象チーム名
- argument[1]: チームから離脱するメンバー名
Returns:
str: 処理結果
def
clear() -> str:
332def clear() -> str: 333 """ 334 全チーム削除 335 336 Returns: 337 str: 処理結果 338 339 """ 340 msg = modify.db_backup() 341 342 resultdb = dbutil.connection(g.cfg.setting.database_file) 343 resultdb.execute("update member set team_id = null;") 344 resultdb.execute("drop table team;") 345 resultdb.execute("delete from sqlite_sequence where name = 'team';") 346 resultdb.commit() 347 resultdb.close() 348 349 initialization.setup_resultdb(g.cfg.setting.database_file) 350 g.cfg.member.info = g.cfg.member.get_info 351 g.cfg.team.info = g.cfg.team.get_info 352 353 return msg
全チーム削除
Returns:
str: 処理結果