libs.types
libs/types.py
1""" 2libs/types.py 3""" 4 5from dataclasses import asdict, dataclass, field 6from enum import Enum, StrEnum, auto 7from typing import TYPE_CHECKING, Any, Literal, Optional, TypeAlias, TypedDict, Union 8 9if TYPE_CHECKING: 10 from pathlib import Path 11 12 import pandas as pd 13 14 15MessageType: TypeAlias = Union[None, str, "Path", "pd.DataFrame"] 16"""メッセージ型 17- *None*: 空データ(なにもしない) 18- *str*: 文字列型データ(そのまま表示) 19- *Path*: ファイルパス(アップロード処理) 20- *DataFrame*: 表データ 21""" 22 23 24class MessageStatus(StrEnum): 25 """メッセージステータス""" 26 27 APPEND = "message_append" 28 """新規ポストイベント""" 29 CHANGED = "message_changed" 30 """編集イベント""" 31 DELETED = "message_deleted" 32 """削除イベント""" 33 DO_NOTHING = "do_nothing" 34 """何もしなくてよいイベント""" 35 UNDETERMINED = "undetermined" 36 """未定義状態""" 37 38 39class ActionStatus(StrEnum): 40 """DBに対する操作""" 41 42 CHANGE = "change" 43 """insert/updateが実行された""" 44 DELETE = "delete" 45 """deleteが実行された""" 46 NOTHING = "nothing" 47 """何もしてない""" 48 49 50class ChannelType(StrEnum): 51 """チャンネルタイプ""" 52 53 CHANNEL = "normal" 54 """通常チャンネル""" 55 PRIVATE = "private" 56 """プライベートチャンネル""" 57 DIRECT_MESSAGE = "direct_message" 58 """ダイレクトメッセージ""" 59 HOME_APP = "home_app" 60 """Slackのホームアプリ""" 61 SEARCH = "search_api" 62 """検索API""" 63 UNDETERMINED = "undetermined" 64 """未定義状態""" 65 66 67class CommandType(StrEnum): 68 """実行(する/した)サブコマンド兼設定ファイルセクション名""" 69 70 RESULTS = "results" 71 """成績サマリ""" 72 GRAPH = "graph" 73 """グラフ生成""" 74 RANKING = "ranking" 75 """ランキング""" 76 RATING = "rating" 77 """レーティング""" 78 REPORT = "report" 79 """レポート""" 80 MEMBER_LIST = "member" 81 """メンバー一覧""" 82 TEAM_LIST = "team" 83 """チーム一覧""" 84 HELP = "help" 85 """ヘルプ""" 86 COMPARISON = "comparison" 87 """突合処理""" 88 UNKNOWN = "unknown" 89 """未定義""" 90 91 92class ServiceType(StrEnum): 93 """連携先サービス""" 94 95 SLACK = "slack" 96 """slack""" 97 DISCORD = "discord" 98 """discord""" 99 WEB = "web" 100 """web ui""" 101 STANDARD_IO = "standard_io" 102 """standard_io""" 103 UNKNOWN = "unknown" 104 """unknown""" 105 106 107@dataclass 108class StyleOptions: 109 """表示オプション""" 110 111 class RenameType(Enum): 112 """リネームタイプ""" 113 114 NONE = auto() 115 """変換しない""" 116 NORMAL = auto() 117 """通常変換""" 118 SHORT = auto() 119 """短縮変換""" 120 121 class DataKind(Enum): 122 """保存されているデータの種類""" 123 124 GENERAL = auto() 125 """通常データ""" 126 POINTS_TOTAL = auto() 127 """成績サマリ(通算ポイント)""" 128 POINTS_DIFF = auto() 129 """成績サマリ(ポイント差分)""" 130 DETAILED_COMPARISON = auto() 131 """成績詳細比較""" 132 SEAT_DATA = auto() 133 """座席データ""" 134 RECORD_DATA = auto() 135 """戦績データ(簡易版)""" 136 RECORD_DATA_ALL = auto() 137 """戦績データ(詳細版)""" 138 RANKING = auto() 139 """ランキングデータ""" 140 RATING = auto() 141 """レーティングデータ""" 142 143 # メモ 144 REMARKS_REGULATION = auto() 145 """メモ(卓外清算)""" 146 REMARKS_YAKUMAN = auto() 147 """メモ(役満和了)""" 148 REMARKS_OTHER = auto() 149 """メモ(その他)""" 150 151 title: str = "" 152 """出力タイトル""" 153 sub_title: bool = False 154 """サブタイトル化""" 155 format_type: Literal["default", "csv", "txt"] = "default" 156 """出力フォーマット""" 157 158 base_name: str = "" 159 """ファイル出力時のファイル名""" 160 161 codeblock: bool = False 162 """MessageTypeがstr型ならcodeblock化 163 - *True*: codeblock化 164 - *False*: 何もしない 165 """ 166 show_index: bool = False 167 """MessageTypeがDataFrame型なら表にIndexに含める 168 - *True*: Indexを含める 169 - *False*: Indexを含めない 170 """ 171 use_comment: bool = False 172 """ファイルアップロード時のinitial_commentを有効にする 173 - *True*: initial_commentを使う 174 - *False*: initial_commentを使わない 175 """ 176 header_hidden: bool = False 177 """ヘッダ文を非表示にする 178 - *True*: 非表示 179 - *False*: 表示 180 """ 181 key_title: bool = True 182 """小見出しに辞書のキーを使う 183 - *True*: 表示 184 - *False*: 非表示 185 """ 186 summarize: bool = True 187 """MessageTypeがstr型のとき後続の要素を集約する 188 - *True*: 可能な限り複数の要素をひとつにまとめる 189 - *False*: 要素単位でデータを処理する 190 """ 191 indent: int = 0 192 """出力時に付与するインデント数(TAB)""" 193 keep_blank: bool = False 194 """空行の削除 195 - *True*: 削除しない 196 - *False*: 削除する 197 """ 198 keep_indent: bool = False 199 """保存されているメッセージのdedentの取り扱い 200 - *True*: 維持する 201 - *False*: 削除する 202 """ 203 transpose: bool = False 204 """MessageTypeがDataFrameのとき表の縦横を変換する""" 205 rename_type: RenameType = field(default=RenameType.NORMAL) 206 """カラム名変換パラメータ""" 207 data_kind: DataKind = field(default=DataKind.GENERAL) 208 """データ種別""" 209 210 @property 211 def print_title(self) -> str: 212 """ 213 タイトル表示 214 215 Returns: 216 str: タイトル文字列 217 218 """ 219 ret: str = "" 220 221 if self.title: 222 tab = "\t" * (self.indent - 1) 223 if self.sub_title: 224 ret = f"{tab}{self.title}:" 225 else: 226 ret = f"{tab}【{self.title}】" 227 228 return ret 229 230 @property 231 def filename(self) -> str: 232 """出力ファイル名""" 233 if self.format_type == "default": 234 return "" 235 return f"{self.base_name}.{self.format_type}" 236 237 @property 238 def asdict(self) -> dict[str, Any]: 239 """辞書変換""" 240 return asdict(self) 241 242 243class MessageTypeDict(TypedDict): 244 """メッセージ格納辞書""" 245 246 data: MessageType 247 """内容""" 248 options: StyleOptions 249 """表示オプション""" 250 251 252class ScoreDict(TypedDict, total=False): 253 """スコアデータ格納用辞書""" 254 255 ts: str 256 """ゲーム終了時間""" 257 258 p1_name: str 259 """東家:プレイヤー名""" 260 p1_str: str 261 """東家:入力された素点情報(文字列)""" 262 p1_rpoint: int 263 """東家:素点(入力文字列評価後)""" 264 p1_point: float 265 """東家:獲得ポイント""" 266 p1_rank: int 267 """東家:獲得順位""" 268 269 p2_name: str 270 """南家:プレイヤー名""" 271 p2_str: str 272 """南家:入力された素点情報(文字列)""" 273 p2_rpoint: int 274 """南家:素点(入力文字列評価後)""" 275 p2_point: float 276 """東家:獲得ポイント""" 277 p2_rank: int 278 """南家:獲得順位""" 279 280 p3_name: str 281 """西家:プレイヤー名""" 282 p3_str: str 283 """西家:入力された素点情報(文字列)""" 284 p3_rpoint: int 285 """西家:素点(入力文字列評価後)""" 286 p3_point: float 287 """西家:獲得ポイント""" 288 p3_rank: int 289 """西家:獲得順位""" 290 291 p4_name: str 292 """北家:プレイヤー名""" 293 p4_str: str 294 """北家:入力された素点情報(文字列)""" 295 p4_rpoint: int 296 """北家:素点(入力文字列評価後)""" 297 p4_point: float 298 """北家:獲得ポイント""" 299 p4_rank: int 300 """北家:獲得順位""" 301 302 deposit: int 303 """配給原点合計 - 素点合計""" 304 comment: Optional[str] 305 """ゲームコメント""" 306 rule_version: str 307 """ルール識別子""" 308 source: Optional[str] 309 """データ入力元識別子""" 310 mode: Literal[3, 4] 311 """集計モード""" 312 313 314class RemarkDict(TypedDict, total=False): 315 """メモ格納用辞書""" 316 317 thread_ts: str 318 """ゲーム終了時間""" 319 event_ts: str 320 """メモ記録時間""" 321 name: str 322 """記録対象プレイヤー名""" 323 matter: str 324 """記録内容""" 325 source: str 326 """データ入力元識別子""" 327 328 329class RankTableDict(TypedDict): 330 """昇段ポイント計算テーブル用辞書""" 331 332 grade: str 333 """段位名称""" 334 point: list[int] 335 """初期ポイントと昇段に必要なポイント""" 336 acquisition: list[int] 337 """獲得ポイント(順位)""" 338 demote: bool 339 """降格フラグ 340 - *True*: 降格する(省略時デフォルト) 341 - *False*: 降格しない 342 """ 343 344 345class GradeTableDict(TypedDict, total=False): 346 """段位テーブル用辞書""" 347 348 name: str 349 """識別名""" 350 addition_expression: str 351 """素点評価式(昇段ポイントに加算)""" 352 table: list[RankTableDict] 353 """昇段ポイント計算テーブル"""
MessageType: TypeAlias =
None | str | ForwardRef('Path') | ForwardRef('pd.DataFrame')
メッセージ型
- None: 空データ(なにもしない)
- str: 文字列型データ(そのまま表示)
- Path: ファイルパス(アップロード処理)
- DataFrame: 表データ
class
MessageStatus(enum.StrEnum):
25class MessageStatus(StrEnum): 26 """メッセージステータス""" 27 28 APPEND = "message_append" 29 """新規ポストイベント""" 30 CHANGED = "message_changed" 31 """編集イベント""" 32 DELETED = "message_deleted" 33 """削除イベント""" 34 DO_NOTHING = "do_nothing" 35 """何もしなくてよいイベント""" 36 UNDETERMINED = "undetermined" 37 """未定義状態"""
メッセージステータス
class
ActionStatus(enum.StrEnum):
40class ActionStatus(StrEnum): 41 """DBに対する操作""" 42 43 CHANGE = "change" 44 """insert/updateが実行された""" 45 DELETE = "delete" 46 """deleteが実行された""" 47 NOTHING = "nothing" 48 """何もしてない"""
DBに対する操作
class
ChannelType(enum.StrEnum):
51class ChannelType(StrEnum): 52 """チャンネルタイプ""" 53 54 CHANNEL = "normal" 55 """通常チャンネル""" 56 PRIVATE = "private" 57 """プライベートチャンネル""" 58 DIRECT_MESSAGE = "direct_message" 59 """ダイレクトメッセージ""" 60 HOME_APP = "home_app" 61 """Slackのホームアプリ""" 62 SEARCH = "search_api" 63 """検索API""" 64 UNDETERMINED = "undetermined" 65 """未定義状態"""
チャンネルタイプ
class
CommandType(enum.StrEnum):
68class CommandType(StrEnum): 69 """実行(する/した)サブコマンド兼設定ファイルセクション名""" 70 71 RESULTS = "results" 72 """成績サマリ""" 73 GRAPH = "graph" 74 """グラフ生成""" 75 RANKING = "ranking" 76 """ランキング""" 77 RATING = "rating" 78 """レーティング""" 79 REPORT = "report" 80 """レポート""" 81 MEMBER_LIST = "member" 82 """メンバー一覧""" 83 TEAM_LIST = "team" 84 """チーム一覧""" 85 HELP = "help" 86 """ヘルプ""" 87 COMPARISON = "comparison" 88 """突合処理""" 89 UNKNOWN = "unknown" 90 """未定義"""
実行(する/した)サブコマンド兼設定ファイルセクション名
class
ServiceType(enum.StrEnum):
93class ServiceType(StrEnum): 94 """連携先サービス""" 95 96 SLACK = "slack" 97 """slack""" 98 DISCORD = "discord" 99 """discord""" 100 WEB = "web" 101 """web ui""" 102 STANDARD_IO = "standard_io" 103 """standard_io""" 104 UNKNOWN = "unknown" 105 """unknown"""
連携先サービス
@dataclass
class
StyleOptions:
108@dataclass 109class StyleOptions: 110 """表示オプション""" 111 112 class RenameType(Enum): 113 """リネームタイプ""" 114 115 NONE = auto() 116 """変換しない""" 117 NORMAL = auto() 118 """通常変換""" 119 SHORT = auto() 120 """短縮変換""" 121 122 class DataKind(Enum): 123 """保存されているデータの種類""" 124 125 GENERAL = auto() 126 """通常データ""" 127 POINTS_TOTAL = auto() 128 """成績サマリ(通算ポイント)""" 129 POINTS_DIFF = auto() 130 """成績サマリ(ポイント差分)""" 131 DETAILED_COMPARISON = auto() 132 """成績詳細比較""" 133 SEAT_DATA = auto() 134 """座席データ""" 135 RECORD_DATA = auto() 136 """戦績データ(簡易版)""" 137 RECORD_DATA_ALL = auto() 138 """戦績データ(詳細版)""" 139 RANKING = auto() 140 """ランキングデータ""" 141 RATING = auto() 142 """レーティングデータ""" 143 144 # メモ 145 REMARKS_REGULATION = auto() 146 """メモ(卓外清算)""" 147 REMARKS_YAKUMAN = auto() 148 """メモ(役満和了)""" 149 REMARKS_OTHER = auto() 150 """メモ(その他)""" 151 152 title: str = "" 153 """出力タイトル""" 154 sub_title: bool = False 155 """サブタイトル化""" 156 format_type: Literal["default", "csv", "txt"] = "default" 157 """出力フォーマット""" 158 159 base_name: str = "" 160 """ファイル出力時のファイル名""" 161 162 codeblock: bool = False 163 """MessageTypeがstr型ならcodeblock化 164 - *True*: codeblock化 165 - *False*: 何もしない 166 """ 167 show_index: bool = False 168 """MessageTypeがDataFrame型なら表にIndexに含める 169 - *True*: Indexを含める 170 - *False*: Indexを含めない 171 """ 172 use_comment: bool = False 173 """ファイルアップロード時のinitial_commentを有効にする 174 - *True*: initial_commentを使う 175 - *False*: initial_commentを使わない 176 """ 177 header_hidden: bool = False 178 """ヘッダ文を非表示にする 179 - *True*: 非表示 180 - *False*: 表示 181 """ 182 key_title: bool = True 183 """小見出しに辞書のキーを使う 184 - *True*: 表示 185 - *False*: 非表示 186 """ 187 summarize: bool = True 188 """MessageTypeがstr型のとき後続の要素を集約する 189 - *True*: 可能な限り複数の要素をひとつにまとめる 190 - *False*: 要素単位でデータを処理する 191 """ 192 indent: int = 0 193 """出力時に付与するインデント数(TAB)""" 194 keep_blank: bool = False 195 """空行の削除 196 - *True*: 削除しない 197 - *False*: 削除する 198 """ 199 keep_indent: bool = False 200 """保存されているメッセージのdedentの取り扱い 201 - *True*: 維持する 202 - *False*: 削除する 203 """ 204 transpose: bool = False 205 """MessageTypeがDataFrameのとき表の縦横を変換する""" 206 rename_type: RenameType = field(default=RenameType.NORMAL) 207 """カラム名変換パラメータ""" 208 data_kind: DataKind = field(default=DataKind.GENERAL) 209 """データ種別""" 210 211 @property 212 def print_title(self) -> str: 213 """ 214 タイトル表示 215 216 Returns: 217 str: タイトル文字列 218 219 """ 220 ret: str = "" 221 222 if self.title: 223 tab = "\t" * (self.indent - 1) 224 if self.sub_title: 225 ret = f"{tab}{self.title}:" 226 else: 227 ret = f"{tab}【{self.title}】" 228 229 return ret 230 231 @property 232 def filename(self) -> str: 233 """出力ファイル名""" 234 if self.format_type == "default": 235 return "" 236 return f"{self.base_name}.{self.format_type}" 237 238 @property 239 def asdict(self) -> dict[str, Any]: 240 """辞書変換""" 241 return asdict(self)
表示オプション
StyleOptions( title: str = '', sub_title: bool = False, format_type: Literal['default', 'csv', 'txt'] = 'default', base_name: str = '', codeblock: bool = False, show_index: bool = False, use_comment: bool = False, header_hidden: bool = False, key_title: bool = True, summarize: bool = True, indent: int = 0, keep_blank: bool = False, keep_indent: bool = False, transpose: bool = False, rename_type: StyleOptions.RenameType = <RenameType.NORMAL: 2>, data_kind: StyleOptions.DataKind = <DataKind.GENERAL: 1>)
use_comment: bool =
False
ファイルアップロード時のinitial_commentを有効にする
- True: initial_commentを使う
- False: initial_commentを使わない
print_title: str
211 @property 212 def print_title(self) -> str: 213 """ 214 タイトル表示 215 216 Returns: 217 str: タイトル文字列 218 219 """ 220 ret: str = "" 221 222 if self.title: 223 tab = "\t" * (self.indent - 1) 224 if self.sub_title: 225 ret = f"{tab}{self.title}:" 226 else: 227 ret = f"{tab}【{self.title}】" 228 229 return ret
タイトル表示
Returns:
str: タイトル文字列
class
StyleOptions.RenameType(enum.Enum):
112 class RenameType(Enum): 113 """リネームタイプ""" 114 115 NONE = auto() 116 """変換しない""" 117 NORMAL = auto() 118 """通常変換""" 119 SHORT = auto() 120 """短縮変換"""
リネームタイプ
class
StyleOptions.DataKind(enum.Enum):
122 class DataKind(Enum): 123 """保存されているデータの種類""" 124 125 GENERAL = auto() 126 """通常データ""" 127 POINTS_TOTAL = auto() 128 """成績サマリ(通算ポイント)""" 129 POINTS_DIFF = auto() 130 """成績サマリ(ポイント差分)""" 131 DETAILED_COMPARISON = auto() 132 """成績詳細比較""" 133 SEAT_DATA = auto() 134 """座席データ""" 135 RECORD_DATA = auto() 136 """戦績データ(簡易版)""" 137 RECORD_DATA_ALL = auto() 138 """戦績データ(詳細版)""" 139 RANKING = auto() 140 """ランキングデータ""" 141 RATING = auto() 142 """レーティングデータ""" 143 144 # メモ 145 REMARKS_REGULATION = auto() 146 """メモ(卓外清算)""" 147 REMARKS_YAKUMAN = auto() 148 """メモ(役満和了)""" 149 REMARKS_OTHER = auto() 150 """メモ(その他)"""
保存されているデータの種類
class
MessageTypeDict(typing.TypedDict):
244class MessageTypeDict(TypedDict): 245 """メッセージ格納辞書""" 246 247 data: MessageType 248 """内容""" 249 options: StyleOptions 250 """表示オプション"""
メッセージ格納辞書
class
ScoreDict(typing.TypedDict):
253class ScoreDict(TypedDict, total=False): 254 """スコアデータ格納用辞書""" 255 256 ts: str 257 """ゲーム終了時間""" 258 259 p1_name: str 260 """東家:プレイヤー名""" 261 p1_str: str 262 """東家:入力された素点情報(文字列)""" 263 p1_rpoint: int 264 """東家:素点(入力文字列評価後)""" 265 p1_point: float 266 """東家:獲得ポイント""" 267 p1_rank: int 268 """東家:獲得順位""" 269 270 p2_name: str 271 """南家:プレイヤー名""" 272 p2_str: str 273 """南家:入力された素点情報(文字列)""" 274 p2_rpoint: int 275 """南家:素点(入力文字列評価後)""" 276 p2_point: float 277 """東家:獲得ポイント""" 278 p2_rank: int 279 """南家:獲得順位""" 280 281 p3_name: str 282 """西家:プレイヤー名""" 283 p3_str: str 284 """西家:入力された素点情報(文字列)""" 285 p3_rpoint: int 286 """西家:素点(入力文字列評価後)""" 287 p3_point: float 288 """西家:獲得ポイント""" 289 p3_rank: int 290 """西家:獲得順位""" 291 292 p4_name: str 293 """北家:プレイヤー名""" 294 p4_str: str 295 """北家:入力された素点情報(文字列)""" 296 p4_rpoint: int 297 """北家:素点(入力文字列評価後)""" 298 p4_point: float 299 """北家:獲得ポイント""" 300 p4_rank: int 301 """北家:獲得順位""" 302 303 deposit: int 304 """配給原点合計 - 素点合計""" 305 comment: Optional[str] 306 """ゲームコメント""" 307 rule_version: str 308 """ルール識別子""" 309 source: Optional[str] 310 """データ入力元識別子""" 311 mode: Literal[3, 4] 312 """集計モード"""
スコアデータ格納用辞書
class
RemarkDict(typing.TypedDict):
315class RemarkDict(TypedDict, total=False): 316 """メモ格納用辞書""" 317 318 thread_ts: str 319 """ゲーム終了時間""" 320 event_ts: str 321 """メモ記録時間""" 322 name: str 323 """記録対象プレイヤー名""" 324 matter: str 325 """記録内容""" 326 source: str 327 """データ入力元識別子"""
メモ格納用辞書
class
RankTableDict(typing.TypedDict):
330class RankTableDict(TypedDict): 331 """昇段ポイント計算テーブル用辞書""" 332 333 grade: str 334 """段位名称""" 335 point: list[int] 336 """初期ポイントと昇段に必要なポイント""" 337 acquisition: list[int] 338 """獲得ポイント(順位)""" 339 demote: bool 340 """降格フラグ 341 - *True*: 降格する(省略時デフォルト) 342 - *False*: 降格しない 343 """
昇段ポイント計算テーブル用辞書
class
GradeTableDict(typing.TypedDict):
346class GradeTableDict(TypedDict, total=False): 347 """段位テーブル用辞書""" 348 349 name: str 350 """識別名""" 351 addition_expression: str 352 """素点評価式(昇段ポイントに加算)""" 353 table: list[RankTableDict] 354 """昇段ポイント計算テーブル"""
段位テーブル用辞書