libs.commands.results.versus
libs/commands/results/versus.py
1""" 2libs/commands/results/versus.py 3""" 4 5import textwrap 6 7import pandas as pd 8 9import libs.global_value as g 10from libs.data import loader 11from libs.functions import message 12from libs.utils import formatter 13 14 15def aggregation() -> tuple[str, dict, dict]: 16 """直接対戦結果を集計して返す 17 18 Returns: 19 tuple[str, dict, dict] 20 - str: ヘッダ情報 21 - dict: 集計データ 22 - dict: 生成ファイル情報 23 """ 24 25 # 検索動作を合わせる 26 g.params.update(guest_skip=g.params.get("guest_skip2")) 27 28 # --- データ収集 29 df_vs = loader.read_data("summary/versus_matrix.sql") 30 df_game = loader.read_data("summary/details.sql").fillna(value="") 31 df_data = pd.DataFrame(columns=df_game.columns) # ファイル出力用 32 33 my_name = formatter.name_replace(g.params["player_name"], add_mark=True) 34 vs_list = [formatter.name_replace(x, add_mark=True) for x in g.params["competition_list"].values()] 35 36 # --- 匿名化 37 if g.params.get("anonymous"): 38 mapping_dict = formatter.anonymous_mapping([my_name] + vs_list) 39 my_name = mapping_dict[my_name] 40 vs_list = [mapping_dict[name] for name in vs_list] 41 df_vs["my_name"] = df_vs["my_name"].replace(mapping_dict) 42 df_vs["vs_name"] = df_vs["vs_name"].replace(mapping_dict) 43 44 # --- 表示内容 45 if g.params.get("all_player"): 46 vs = "全員" 47 else: 48 vs = ",".join(vs_list) 49 50 msg1 = tmpl_header(my_name, vs) 51 msg2: dict = {} # 対戦結果格納用 52 53 tmp_msg: dict = {} 54 drop_name: list = [] # 対戦記録なしプレイヤー 55 if len(df_vs) == 0: # 検索結果なし 56 msg2[""] = "対戦記録が見つかりません。\n" 57 return (msg1, msg2, {}) 58 59 for vs_name in vs_list: 60 tmp_msg[vs_name] = {} 61 if vs_name in vs_list: 62 data = df_vs.query("my_name == @my_name and vs_name == @vs_name") 63 if data.empty: 64 drop_name.append(vs_name) 65 tmp_msg[vs_name]["info"] = f"*【{my_name} vs {vs_name}】*\n\t対戦記録はありません。" 66 continue 67 68 tmp_msg[vs_name]["info"] = tmpl_vs_table(data.to_dict(orient="records")[0]) 69 70 # ゲーム結果 71 if g.params.get("game_results"): 72 count = 0 73 my_score = df_game.query("name == @my_name") 74 vs_score = df_game.query("name == @vs_name") 75 my_playtime = my_score["playtime"].to_list() 76 vs_playtime = vs_score["playtime"].to_list() 77 78 for playtime in sorted(set(my_playtime + vs_playtime)): 79 if playtime in my_playtime and playtime in vs_playtime: 80 current_game = df_game.query("playtime == @playtime") 81 df_data = current_game if df_data.empty else pd.concat([df_data, current_game]) 82 count += 1 83 else: # 対戦記録なし 84 tmp_msg[vs_name]["info"] = f"*【{my_name} vs {vs_name}】*\n\t対戦相手が見つかりません。\n\n" 85 86 # --- データ整列&まとめ 87 for key, val in tmp_msg.items(): 88 if key in drop_name and len(vs_list) > 5 and not g.params.get("all_player"): 89 continue 90 msg2[f"{key}_info"] = val.pop("info") + "\n" 91 if val: 92 for x in val: 93 msg2[f"{key}_{x}"] = textwrap.indent(val[x], "\t") + "\n" 94 95 # --- ファイル出力 96 if len(df_data) != 0: 97 df_data["座席"] = df_data["seat"].apply(lambda x: ["東家", "南家", "西家", "北家"][x - 1]) 98 df_data["rpoint"] = df_data["rpoint"] * 100 99 df_data = formatter.df_rename( 100 df_data.filter(items=["playtime", "座席", "name", "rank", "rpoint", "point", "grandslam"]).drop_duplicates(), 101 short=False 102 ) 103 104 namelist = list(g.params["competition_list"].values()) # pylint: disable=unused-variable # noqa: F841 105 df_vs["対戦相手"] = df_vs["vs_name"].apply(lambda x: str(x).strip()) 106 df_vs["my_rpoint_avg"] = (df_vs["my_rpoint_avg"] * 100).astype("int") 107 df_vs["vs_rpoint_avg"] = (df_vs["vs_rpoint_avg"] * 100).astype("int") 108 df_vs = formatter.df_rename(df_vs) 109 df_vs2 = df_vs.query("vs_name == @namelist").filter( 110 items=[ 111 "対戦相手", "対戦結果", "勝率", 112 "獲得ポイント(自分)", "平均ポイント(自分)", "平均素点(自分)", "順位分布(自分)", "平均順位(自分)", 113 "獲得ポイント(相手)", "平均ポイント(相手)", "平均素点(相手)", "順位分布(相手)", "平均順位(相手)", 114 ] 115 ).drop_duplicates() 116 117 match str(g.params.get("format", "default")).lower(): 118 case "csv": 119 file_list = { 120 "対戦結果": formatter.save_output(df_data, "csv", "result.csv"), 121 "成績": formatter.save_output(df_vs2, "csv", "versus.csv"), 122 } 123 case "text" | "txt": 124 file_list = { 125 "対戦結果": formatter.save_output(df_data, "txt", "result.txt"), 126 "成績": formatter.save_output(df_vs2, "txt", "versus.txt"), 127 } 128 case _: 129 file_list = {} 130 131 return (msg1, msg2, file_list) 132 133 134def tmpl_header(my_name: str, vs_name: str) -> str: 135 """ヘッダテンプレート 136 137 Args: 138 my_name (str): 自分の名前 139 vs_name (str): 相手の名前 140 141 Returns: 142 str: 出力データ 143 """ 144 ret = textwrap.dedent( 145 f"""\ 146 *【直接対戦結果】* 147 \tプレイヤー名:{my_name} 148 \t対戦相手:{vs_name} 149 \t{message.item_search_range()} 150 \t{message.remarks(True)} 151 """ 152 ).strip() 153 154 return message.del_blank_line(ret) 155 156 157def tmpl_vs_table(data: dict) -> str: 158 """直接対決結果表示テンプレート 159 160 Args: 161 data (dict): 結果データ 162 163 Returns: 164 str: 出力データ 165 """ 166 167 ret = f"*【{data["my_name"].strip()} vs {data["vs_name"].strip()}】*\n" 168 ret += textwrap.indent( 169 "".join([ 170 textwrap.dedent( 171 f"""\ 172 対戦数:{data["game"]} 戦 {data["win"]} 勝 {data["lose"]} 敗 ({data["win%"]:.2f}%) 173 平均素点差:{(data["my_rpoint_avg"] - data["vs_rpoint_avg"]) * 100:+.0f} 点 174 獲得ポイント合計(自分):{data["my_point_sum"]:+.1f}pt 175 獲得ポイント合計(相手):{data["vs_point_sum"]:+.1f}pt 176 """.replace("-", "▲") 177 ), 178 textwrap.dedent( 179 f"""\ 180 順位分布(自分):{data["my_1st"]}-{data["my_2nd"]}-{data["my_3rd"]}-{data["my_4th"]} ({data["my_rank_avg"]:1.2f}) 181 順位分布(相手):{data["vs_1st"]}-{data["vs_2nd"]}-{data["vs_3rd"]}-{data["vs_4th"]} ({data["vs_rank_avg"]:1.2f}) 182 """ 183 ) 184 ]), 185 "\t" 186 ) 187 188 return ret.strip() + "\n"
def
aggregation() -> tuple[str, dict, dict]:
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 g.params.update(guest_skip=g.params.get("guest_skip2")) 28 29 # --- データ収集 30 df_vs = loader.read_data("summary/versus_matrix.sql") 31 df_game = loader.read_data("summary/details.sql").fillna(value="") 32 df_data = pd.DataFrame(columns=df_game.columns) # ファイル出力用 33 34 my_name = formatter.name_replace(g.params["player_name"], add_mark=True) 35 vs_list = [formatter.name_replace(x, add_mark=True) for x in g.params["competition_list"].values()] 36 37 # --- 匿名化 38 if g.params.get("anonymous"): 39 mapping_dict = formatter.anonymous_mapping([my_name] + vs_list) 40 my_name = mapping_dict[my_name] 41 vs_list = [mapping_dict[name] for name in vs_list] 42 df_vs["my_name"] = df_vs["my_name"].replace(mapping_dict) 43 df_vs["vs_name"] = df_vs["vs_name"].replace(mapping_dict) 44 45 # --- 表示内容 46 if g.params.get("all_player"): 47 vs = "全員" 48 else: 49 vs = ",".join(vs_list) 50 51 msg1 = tmpl_header(my_name, vs) 52 msg2: dict = {} # 対戦結果格納用 53 54 tmp_msg: dict = {} 55 drop_name: list = [] # 対戦記録なしプレイヤー 56 if len(df_vs) == 0: # 検索結果なし 57 msg2[""] = "対戦記録が見つかりません。\n" 58 return (msg1, msg2, {}) 59 60 for vs_name in vs_list: 61 tmp_msg[vs_name] = {} 62 if vs_name in vs_list: 63 data = df_vs.query("my_name == @my_name and vs_name == @vs_name") 64 if data.empty: 65 drop_name.append(vs_name) 66 tmp_msg[vs_name]["info"] = f"*【{my_name} vs {vs_name}】*\n\t対戦記録はありません。" 67 continue 68 69 tmp_msg[vs_name]["info"] = tmpl_vs_table(data.to_dict(orient="records")[0]) 70 71 # ゲーム結果 72 if g.params.get("game_results"): 73 count = 0 74 my_score = df_game.query("name == @my_name") 75 vs_score = df_game.query("name == @vs_name") 76 my_playtime = my_score["playtime"].to_list() 77 vs_playtime = vs_score["playtime"].to_list() 78 79 for playtime in sorted(set(my_playtime + vs_playtime)): 80 if playtime in my_playtime and playtime in vs_playtime: 81 current_game = df_game.query("playtime == @playtime") 82 df_data = current_game if df_data.empty else pd.concat([df_data, current_game]) 83 count += 1 84 else: # 対戦記録なし 85 tmp_msg[vs_name]["info"] = f"*【{my_name} vs {vs_name}】*\n\t対戦相手が見つかりません。\n\n" 86 87 # --- データ整列&まとめ 88 for key, val in tmp_msg.items(): 89 if key in drop_name and len(vs_list) > 5 and not g.params.get("all_player"): 90 continue 91 msg2[f"{key}_info"] = val.pop("info") + "\n" 92 if val: 93 for x in val: 94 msg2[f"{key}_{x}"] = textwrap.indent(val[x], "\t") + "\n" 95 96 # --- ファイル出力 97 if len(df_data) != 0: 98 df_data["座席"] = df_data["seat"].apply(lambda x: ["東家", "南家", "西家", "北家"][x - 1]) 99 df_data["rpoint"] = df_data["rpoint"] * 100 100 df_data = formatter.df_rename( 101 df_data.filter(items=["playtime", "座席", "name", "rank", "rpoint", "point", "grandslam"]).drop_duplicates(), 102 short=False 103 ) 104 105 namelist = list(g.params["competition_list"].values()) # pylint: disable=unused-variable # noqa: F841 106 df_vs["対戦相手"] = df_vs["vs_name"].apply(lambda x: str(x).strip()) 107 df_vs["my_rpoint_avg"] = (df_vs["my_rpoint_avg"] * 100).astype("int") 108 df_vs["vs_rpoint_avg"] = (df_vs["vs_rpoint_avg"] * 100).astype("int") 109 df_vs = formatter.df_rename(df_vs) 110 df_vs2 = df_vs.query("vs_name == @namelist").filter( 111 items=[ 112 "対戦相手", "対戦結果", "勝率", 113 "獲得ポイント(自分)", "平均ポイント(自分)", "平均素点(自分)", "順位分布(自分)", "平均順位(自分)", 114 "獲得ポイント(相手)", "平均ポイント(相手)", "平均素点(相手)", "順位分布(相手)", "平均順位(相手)", 115 ] 116 ).drop_duplicates() 117 118 match str(g.params.get("format", "default")).lower(): 119 case "csv": 120 file_list = { 121 "対戦結果": formatter.save_output(df_data, "csv", "result.csv"), 122 "成績": formatter.save_output(df_vs2, "csv", "versus.csv"), 123 } 124 case "text" | "txt": 125 file_list = { 126 "対戦結果": formatter.save_output(df_data, "txt", "result.txt"), 127 "成績": formatter.save_output(df_vs2, "txt", "versus.txt"), 128 } 129 case _: 130 file_list = {} 131 132 return (msg1, msg2, file_list)
直接対戦結果を集計して返す
Returns:
tuple[str, dict, dict]
- str: ヘッダ情報
- dict: 集計データ
- dict: 生成ファイル情報
def
tmpl_header(my_name: str, vs_name: str) -> str:
135def tmpl_header(my_name: str, vs_name: str) -> str: 136 """ヘッダテンプレート 137 138 Args: 139 my_name (str): 自分の名前 140 vs_name (str): 相手の名前 141 142 Returns: 143 str: 出力データ 144 """ 145 ret = textwrap.dedent( 146 f"""\ 147 *【直接対戦結果】* 148 \tプレイヤー名:{my_name} 149 \t対戦相手:{vs_name} 150 \t{message.item_search_range()} 151 \t{message.remarks(True)} 152 """ 153 ).strip() 154 155 return message.del_blank_line(ret)
ヘッダテンプレート
Arguments:
- my_name (str): 自分の名前
- vs_name (str): 相手の名前
Returns:
str: 出力データ
def
tmpl_vs_table(data: dict) -> str:
158def tmpl_vs_table(data: dict) -> str: 159 """直接対決結果表示テンプレート 160 161 Args: 162 data (dict): 結果データ 163 164 Returns: 165 str: 出力データ 166 """ 167 168 ret = f"*【{data["my_name"].strip()} vs {data["vs_name"].strip()}】*\n" 169 ret += textwrap.indent( 170 "".join([ 171 textwrap.dedent( 172 f"""\ 173 対戦数:{data["game"]} 戦 {data["win"]} 勝 {data["lose"]} 敗 ({data["win%"]:.2f}%) 174 平均素点差:{(data["my_rpoint_avg"] - data["vs_rpoint_avg"]) * 100:+.0f} 点 175 獲得ポイント合計(自分):{data["my_point_sum"]:+.1f}pt 176 獲得ポイント合計(相手):{data["vs_point_sum"]:+.1f}pt 177 """.replace("-", "▲") 178 ), 179 textwrap.dedent( 180 f"""\ 181 順位分布(自分):{data["my_1st"]}-{data["my_2nd"]}-{data["my_3rd"]}-{data["my_4th"]} ({data["my_rank_avg"]:1.2f}) 182 順位分布(相手):{data["vs_1st"]}-{data["vs_2nd"]}-{data["vs_3rd"]}-{data["vs_4th"]} ({data["vs_rank_avg"]:1.2f}) 183 """ 184 ) 185 ]), 186 "\t" 187 ) 188 189 return ret.strip() + "\n"
直接対決結果表示テンプレート
Arguments:
- data (dict): 結果データ
Returns:
str: 出力データ