libs.commands.results.summary
libs/commands/results/summary.py
1""" 2libs/commands/results/summary.py 3""" 4 5import re 6 7import pandas as pd 8 9import libs.global_value as g 10from cls.types import GameInfoDict 11from libs.data import aggregate, loader 12from libs.functions import message 13from libs.utils import formatter 14 15 16def aggregation() -> tuple[str, dict, dict]: 17 """各プレイヤーの通算ポイントを表示 18 19 Returns: 20 tuple[str, dict, dict] 21 - str: ヘッダ情報 22 - dict: 集計データ 23 - dict: 生成ファイル情報 24 """ 25 26 # --- データ収集 27 game_info: GameInfoDict = aggregate.game_info() 28 df_summary = aggregate.game_summary(drop_items=["rank_distr2"]) 29 df_game = loader.read_data("summary/details.sql") 30 df_grandslam = df_game.query("grandslam == grandslam") 31 32 if g.params.get("anonymous"): 33 col = "team" 34 if g.params.get("individual"): 35 col = "name" 36 mapping_dict = formatter.anonymous_mapping(df_game["name"].unique().tolist()) 37 df_game["name"] = df_game["name"].replace(mapping_dict) 38 df_summary[col] = df_summary[col].replace(mapping_dict) 39 df_grandslam["name"] = df_grandslam["name"].replace(mapping_dict) 40 41 df_summary = formatter.df_rename(df_summary) 42 43 # 表示 44 # --- 情報ヘッダ 45 add_text = "" 46 if g.params.get("individual"): # 個人集計 47 headline = "*【成績サマリ】*\n" 48 column_name = "名前" 49 else: # チーム集計 50 headline = "*【チーム成績サマリ】*\n" 51 column_name = "チーム" 52 53 if not g.cfg.mahjong.ignore_flying: 54 add_text = f" / トバされた人(延べ):{df_summary["トビ"].sum()} 人" 55 56 headline += message.header(game_info, add_text, 1) 57 58 if df_summary.empty: 59 return (headline, {}, {}) 60 61 # --- 集計結果 62 msg: dict = {} 63 msg_memo: str = memo_count(df_game) 64 65 if not g.params.get("score_comparisons"): # 通常表示 66 header_list: list = [column_name, "通算", "平均", "順位分布", "トビ"] 67 filter_list: list = [column_name, "ゲーム数", "通算", "平均", "差分", "1位", "2位", "3位", "4位", "平順", "トビ"] 68 if g.cfg.mahjong.ignore_flying: # トビカウントなし 69 header_list.remove("トビ") 70 filter_list.remove("トビ") 71 else: # 差分表示 72 df_grandslam = df_grandslam[:0] # 非表示のため破棄 73 msg_memo = "" # 非表示のため破棄 74 header_list = ["#", column_name, "通算", "順位差", "トップ差"] 75 filter_list = [column_name, "ゲーム数", "通算", "順位差", "トップ差"] 76 77 # --- メッセージ整形 78 step: int = 40 79 step_count: list = [] 80 print_df = df_summary.filter(items=header_list) 81 floatfmt = formatter.floatfmt_adjust(print_df) 82 last_line = len(print_df) 83 84 for i in range(int(last_line / step + 1)): # step行毎に分割 85 s_line = i * step 86 e_line = (i + 1) * step 87 88 if last_line - e_line < step / 2: # 最終ブロックがstep/2で収まるならまとめる 89 step_count.append((s_line, last_line)) 90 break 91 step_count.append((s_line, e_line)) 92 93 for s_line, e_line in step_count: 94 t = print_df[s_line:e_line].to_markdown( 95 index=False, 96 tablefmt="simple", 97 numalign="right", 98 maxheadercolwidths=8, 99 floatfmt=floatfmt, 100 ).replace(" nan", "******") 101 msg[s_line] = "```\n" + re.sub(r" -([0-9]+)", r" ▲\1", t) + "\n```\n" # マイナスを記号に置換 102 103 # メモ追加 104 if msg_memo: 105 msg["メモ"] = msg_memo 106 107 # --- ファイル出力 108 df_summary = df_summary.filter(items=filter_list).fillna("*****") 109 df_grandslam = df_grandslam.filter( 110 items=["playtime", "grandslam", "name"] 111 ).rename( 112 columns={ 113 "playtime": "日時", 114 "grandslam": "和了役", 115 "name": "和了者", 116 } 117 ) 118 119 prefix_summary = "summary" 120 prefix_yakuman = "yakuman" 121 if g.params.get("filename"): 122 prefix_summary = f"{g.params["filename"]}" 123 prefix_yakuman = f"{g.params["filename"]}_yakuman" 124 125 match g.params.get("format", "default").lower().lower(): 126 case "csv": 127 file_list = { 128 "集計結果": formatter.save_output(df_summary, "csv", f"{prefix_summary}.csv", headline), 129 "役満和了": formatter.save_output(df_grandslam, "csv", f"{prefix_yakuman}.csv", headline), 130 } 131 case "text" | "txt": 132 file_list = { 133 "集計結果": formatter.save_output(df_summary, "txt", f"{prefix_summary}.txt", headline), 134 "役満和了": formatter.save_output(df_grandslam, "txt", f"{prefix_yakuman}.txt", headline), 135 } 136 case _: 137 file_list = {} 138 139 return (headline, msg, file_list) 140 141 142def memo_count(df_game: pd.DataFrame) -> str: 143 """メモ集計 144 145 Args: 146 df_game (pd.DataFrame): ゲーム情報 147 148 Returns: 149 str: 集計結果 150 """ 151 152 # データ収集 153 df_grandslam = df_game.query("grandslam == grandslam") 154 match g.cfg.undefined_word: 155 case 1: 156 df_regulations = df_game.query("regulation == regulation and (type == 1 or type != type)") 157 df_wordcount = df_game.query("regulation == regulation and (type == 2 or type == type)") 158 case 2: 159 df_regulations = df_game.query("regulation == regulation and (type == 1 or type == type)") 160 df_wordcount = df_game.query("regulation == regulation and (type == 2 or type != type)") 161 case _: 162 df_regulations = df_game.query("regulation == regulation and type == 1") 163 df_wordcount = df_game.query("regulation == regulation and type == 2") 164 165 # メモ表示 166 memo_grandslam = "" 167 if not df_grandslam.empty: 168 for _, v in df_grandslam.iterrows(): 169 if not g.params.get("guest_skip") and v["name"] == g.cfg.member.guest_name: # ゲストなし 170 continue 171 memo_grandslam += f"\t{str(v["playtime"]).replace("-", "/")}:{v["grandslam"]} ({v["name"]})\n" 172 if memo_grandslam: 173 memo_grandslam = f"\n*【役満和了】*\n{memo_grandslam}" 174 175 memo_regulation = "" 176 if not df_regulations.empty: 177 for _, v in df_regulations.iterrows(): 178 if not g.params.get("guest_skip") and v["name"] == g.cfg.member.guest_name: # ゲストなし 179 continue 180 memo_regulation += f"\t{str(v["playtime"]).replace("-", "/")}:{v["regulation"]} {str(v["ex_point"]).replace("-", "▲")}pt({v["name"]})\n" 181 if memo_regulation: 182 memo_regulation = f"\n*【卓外ポイント】*\n{memo_regulation}" 183 184 memo_wordcount = "" 185 if not df_wordcount.empty: 186 for _, v in df_wordcount.iterrows(): 187 if not g.params.get("guest_skip") and v["name"] == g.cfg.member.guest_name: # ゲストなし 188 continue 189 memo_wordcount += f"\t{str(v["playtime"]).replace("-", "/")}:{v["regulation"]} ({v["name"]})\n" 190 if memo_wordcount: 191 memo_wordcount = f"\n*【その他】*\n{memo_wordcount}" 192 193 return (memo_grandslam + memo_regulation + memo_wordcount).strip()
def
aggregation() -> tuple[str, dict, dict]:
17def aggregation() -> tuple[str, dict, dict]: 18 """各プレイヤーの通算ポイントを表示 19 20 Returns: 21 tuple[str, dict, dict] 22 - str: ヘッダ情報 23 - dict: 集計データ 24 - dict: 生成ファイル情報 25 """ 26 27 # --- データ収集 28 game_info: GameInfoDict = aggregate.game_info() 29 df_summary = aggregate.game_summary(drop_items=["rank_distr2"]) 30 df_game = loader.read_data("summary/details.sql") 31 df_grandslam = df_game.query("grandslam == grandslam") 32 33 if g.params.get("anonymous"): 34 col = "team" 35 if g.params.get("individual"): 36 col = "name" 37 mapping_dict = formatter.anonymous_mapping(df_game["name"].unique().tolist()) 38 df_game["name"] = df_game["name"].replace(mapping_dict) 39 df_summary[col] = df_summary[col].replace(mapping_dict) 40 df_grandslam["name"] = df_grandslam["name"].replace(mapping_dict) 41 42 df_summary = formatter.df_rename(df_summary) 43 44 # 表示 45 # --- 情報ヘッダ 46 add_text = "" 47 if g.params.get("individual"): # 個人集計 48 headline = "*【成績サマリ】*\n" 49 column_name = "名前" 50 else: # チーム集計 51 headline = "*【チーム成績サマリ】*\n" 52 column_name = "チーム" 53 54 if not g.cfg.mahjong.ignore_flying: 55 add_text = f" / トバされた人(延べ):{df_summary["トビ"].sum()} 人" 56 57 headline += message.header(game_info, add_text, 1) 58 59 if df_summary.empty: 60 return (headline, {}, {}) 61 62 # --- 集計結果 63 msg: dict = {} 64 msg_memo: str = memo_count(df_game) 65 66 if not g.params.get("score_comparisons"): # 通常表示 67 header_list: list = [column_name, "通算", "平均", "順位分布", "トビ"] 68 filter_list: list = [column_name, "ゲーム数", "通算", "平均", "差分", "1位", "2位", "3位", "4位", "平順", "トビ"] 69 if g.cfg.mahjong.ignore_flying: # トビカウントなし 70 header_list.remove("トビ") 71 filter_list.remove("トビ") 72 else: # 差分表示 73 df_grandslam = df_grandslam[:0] # 非表示のため破棄 74 msg_memo = "" # 非表示のため破棄 75 header_list = ["#", column_name, "通算", "順位差", "トップ差"] 76 filter_list = [column_name, "ゲーム数", "通算", "順位差", "トップ差"] 77 78 # --- メッセージ整形 79 step: int = 40 80 step_count: list = [] 81 print_df = df_summary.filter(items=header_list) 82 floatfmt = formatter.floatfmt_adjust(print_df) 83 last_line = len(print_df) 84 85 for i in range(int(last_line / step + 1)): # step行毎に分割 86 s_line = i * step 87 e_line = (i + 1) * step 88 89 if last_line - e_line < step / 2: # 最終ブロックがstep/2で収まるならまとめる 90 step_count.append((s_line, last_line)) 91 break 92 step_count.append((s_line, e_line)) 93 94 for s_line, e_line in step_count: 95 t = print_df[s_line:e_line].to_markdown( 96 index=False, 97 tablefmt="simple", 98 numalign="right", 99 maxheadercolwidths=8, 100 floatfmt=floatfmt, 101 ).replace(" nan", "******") 102 msg[s_line] = "```\n" + re.sub(r" -([0-9]+)", r" ▲\1", t) + "\n```\n" # マイナスを記号に置換 103 104 # メモ追加 105 if msg_memo: 106 msg["メモ"] = msg_memo 107 108 # --- ファイル出力 109 df_summary = df_summary.filter(items=filter_list).fillna("*****") 110 df_grandslam = df_grandslam.filter( 111 items=["playtime", "grandslam", "name"] 112 ).rename( 113 columns={ 114 "playtime": "日時", 115 "grandslam": "和了役", 116 "name": "和了者", 117 } 118 ) 119 120 prefix_summary = "summary" 121 prefix_yakuman = "yakuman" 122 if g.params.get("filename"): 123 prefix_summary = f"{g.params["filename"]}" 124 prefix_yakuman = f"{g.params["filename"]}_yakuman" 125 126 match g.params.get("format", "default").lower().lower(): 127 case "csv": 128 file_list = { 129 "集計結果": formatter.save_output(df_summary, "csv", f"{prefix_summary}.csv", headline), 130 "役満和了": formatter.save_output(df_grandslam, "csv", f"{prefix_yakuman}.csv", headline), 131 } 132 case "text" | "txt": 133 file_list = { 134 "集計結果": formatter.save_output(df_summary, "txt", f"{prefix_summary}.txt", headline), 135 "役満和了": formatter.save_output(df_grandslam, "txt", f"{prefix_yakuman}.txt", headline), 136 } 137 case _: 138 file_list = {} 139 140 return (headline, msg, file_list)
各プレイヤーの通算ポイントを表示
Returns:
tuple[str, dict, dict]
- str: ヘッダ情報
- dict: 集計データ
- dict: 生成ファイル情報
def
memo_count(df_game: pandas.core.frame.DataFrame) -> str:
143def memo_count(df_game: pd.DataFrame) -> str: 144 """メモ集計 145 146 Args: 147 df_game (pd.DataFrame): ゲーム情報 148 149 Returns: 150 str: 集計結果 151 """ 152 153 # データ収集 154 df_grandslam = df_game.query("grandslam == grandslam") 155 match g.cfg.undefined_word: 156 case 1: 157 df_regulations = df_game.query("regulation == regulation and (type == 1 or type != type)") 158 df_wordcount = df_game.query("regulation == regulation and (type == 2 or type == type)") 159 case 2: 160 df_regulations = df_game.query("regulation == regulation and (type == 1 or type == type)") 161 df_wordcount = df_game.query("regulation == regulation and (type == 2 or type != type)") 162 case _: 163 df_regulations = df_game.query("regulation == regulation and type == 1") 164 df_wordcount = df_game.query("regulation == regulation and type == 2") 165 166 # メモ表示 167 memo_grandslam = "" 168 if not df_grandslam.empty: 169 for _, v in df_grandslam.iterrows(): 170 if not g.params.get("guest_skip") and v["name"] == g.cfg.member.guest_name: # ゲストなし 171 continue 172 memo_grandslam += f"\t{str(v["playtime"]).replace("-", "/")}:{v["grandslam"]} ({v["name"]})\n" 173 if memo_grandslam: 174 memo_grandslam = f"\n*【役満和了】*\n{memo_grandslam}" 175 176 memo_regulation = "" 177 if not df_regulations.empty: 178 for _, v in df_regulations.iterrows(): 179 if not g.params.get("guest_skip") and v["name"] == g.cfg.member.guest_name: # ゲストなし 180 continue 181 memo_regulation += f"\t{str(v["playtime"]).replace("-", "/")}:{v["regulation"]} {str(v["ex_point"]).replace("-", "▲")}pt({v["name"]})\n" 182 if memo_regulation: 183 memo_regulation = f"\n*【卓外ポイント】*\n{memo_regulation}" 184 185 memo_wordcount = "" 186 if not df_wordcount.empty: 187 for _, v in df_wordcount.iterrows(): 188 if not g.params.get("guest_skip") and v["name"] == g.cfg.member.guest_name: # ゲストなし 189 continue 190 memo_wordcount += f"\t{str(v["playtime"]).replace("-", "/")}:{v["regulation"]} ({v["name"]})\n" 191 if memo_wordcount: 192 memo_wordcount = f"\n*【その他】*\n{memo_wordcount}" 193 194 return (memo_grandslam + memo_regulation + memo_wordcount).strip()
メモ集計
Arguments:
- df_game (pd.DataFrame): ゲーム情報
Returns:
str: 集計結果