libs.data.comparison
lib/data/comparison.py
1""" 2lib/data/comparison.py 3""" 4 5import logging 6from typing import cast 7 8import libs.global_value as g 9from cls.score import GameResult 10from cls.timekit import ExtendedDatetime as ExtDt 11from cls.types import ComparisonDict, RemarkDict, SlackSearchData 12from libs.data import lookup, modify 13from libs.functions import search, slack_api 14from libs.utils import dictutil 15 16SlackSearchDict = dict[str, SlackSearchData] 17DBSearchDict = dict[str, GameResult] 18 19 20def main() -> None: 21 """データ突合の実施、その結果をslackにpostする""" 22 # チェックコマンドを拾ったイベントの情報を保持(結果の返し先) 23 command_ch = g.msg.channel_id 24 command_ts = g.msg.event_ts 25 26 # データ突合 27 count, msg = data_comparison() 28 logging.notice("count=%s", count) # type: ignore 29 30 # 突合結果 31 after = ExtDt(days=-g.cfg.search.after).format("ymd") 32 before = ExtDt().format("ymd") 33 34 ret = f"*【データ突合】* ({after} - {before})\n" 35 if count["pending"]: 36 ret += f"* 保留:{count["pending"]}件\n" 37 for x in msg["pending"]: 38 ret += f"\t\t{ExtDt(float(x)).format("ymdhms")}\n" 39 ret += f"* 不一致:{count["mismatch"]}件\n{msg["mismatch"]}" 40 ret += f"* 取りこぼし:{count["missing"]}件\n{msg["missing"]}" 41 ret += f"* 削除漏れ:{count["delete"]}件\n{msg["delete"]}" 42 ret += f"* メモ更新:{count["remark_mod"]}件\n{msg["remark_mod"]}" 43 ret += f"* メモ削除:{count["remark_del"]}件\n{msg["remark_del"]}" 44 if count["invalid_score"] > 0: 45 ret += "\n*【素点合計不一致】*\n" 46 ret += msg["invalid_score"] 47 48 g.msg.channel_id = command_ch 49 slack_api.post_message(ret, command_ts) 50 51 52def data_comparison() -> tuple[dict, ComparisonDict]: 53 """データ突合処理 54 55 Returns: 56 tuple[dict,dict]: 57 - dict: 処理された更新/追加/削除の件数 58 - ComparisonDict: slackに返すメッセージ 59 """ 60 61 count: dict = {} 62 msg: dict = {} 63 64 # slackログからゲーム結果を取得 65 slack_score = search.for_slack_score() 66 slack_remarks = search.for_slack_remarks() 67 for _, val in slack_remarks.items(): # スレッド元のスコアデータを追加 68 if (thread_ts := val.get("thread_ts")): 69 val["score"] = slack_score[thread_ts].get("score", GameResult()) 70 71 if slack_score: 72 first_ts = float(min(slack_score)) 73 else: 74 first_ts = float(ExtDt(days=-g.cfg.search.after).format("ts")) 75 76 # データベースからゲーム結果を取得 77 db_score = search.for_db_score(first_ts) 78 db_remarks = search.for_db_remarks(first_ts) 79 80 # --- スコア突合 81 ret_count, ret_msg = check_omission(slack_score, db_score) 82 count = dictutil.merge_dicts(count, ret_count) 83 msg = dictutil.merge_dicts(msg, ret_msg) 84 85 # --- 素点合計の再チェック(修正可能なslack側のみチェック) 86 ret_count, ret_msg = check_total_score(slack_score) 87 count = dictutil.merge_dicts(count, ret_count) 88 msg = dictutil.merge_dicts(msg, ret_msg) 89 90 # --- メモ突合 91 ret_count, ret_msg = check_remarks(slack_remarks, db_remarks) 92 count = dictutil.merge_dicts(count, ret_count) 93 msg = dictutil.merge_dicts(msg, ret_msg) 94 95 count.update(pending=len(msg["pending"])) 96 97 return (count, cast(ComparisonDict, msg)) 98 99 100def check_omission(slack_data: SlackSearchDict, db_data: DBSearchDict) -> tuple[dict, ComparisonDict]: 101 """スコア取りこぼしチェック 102 103 Args: 104 slack_data (SlackSearchDict): slack検索結果 105 db_data (DBSearchDict): DB登録状況 106 107 Returns: 108 tuple[dict, ComparisonDict]: 修正内容(結果) 109 """ 110 111 now_ts = float(ExtDt().format("ts")) 112 count: dict[str, int] = {"mismatch": 0, "missing": 0, "delete": 0} 113 msg: ComparisonDict = {"mismatch": "", "missing": "", "delete": "", "pending": []} 114 115 for key, val in slack_data.items(): 116 # 保留チェック 117 if val["edited_ts"]: 118 check_ts = float(max(val["edited_ts"])) + g.cfg.search.wait 119 else: 120 check_ts = float(key) + g.cfg.search.wait 121 122 if check_ts > now_ts: 123 msg["pending"].append(str(key)) 124 logging.info("pending(slack -> DB): %s", ExtDt(float(key)).format("ymdhms")) 125 continue 126 127 # "score"が取得できていない場合は処理をスキップ 128 if (slack_score := val.get("score", GameResult())): 129 continue 130 131 # 情報更新 132 g.msg.channel_id = val.get("channel_id", "") 133 g.msg.user_id = val.get("user_id", "") 134 g.msg.event_ts = key 135 g.msg.check_updatable() 136 137 reactions_data = [] 138 reactions_data.append(val.get("reaction_ok")) 139 reactions_data.append(val.get("reaction_ng")) 140 141 if key in db_data: # slack -> DB チェック 142 db_score = db_data[key] 143 if not g.cfg.setting.thread_report: # スレッド内報告が禁止されているパターン 144 if val.get("in_thread"): 145 count["delete"] += 1 146 logging.notice("delete: %s (In-thread report)", slack_score) # type: ignore 147 msg["delete"] += f"\t{ExtDt(float(key)).format("ymdhms")} {slack_score.to_text()}\n" 148 modify.db_delete(key) 149 150 # リアクションの削除 151 if key in val.get("reaction_ok", []): 152 slack_api.call_reactions_remove(g.cfg.setting.reaction_ok, ts=key) 153 if key in val.get("reaction_ng", []): 154 slack_api.call_reactions_remove(g.cfg.setting.reaction_ng, ts=key) 155 continue 156 157 if slack_score.to_dict() == db_score.to_dict(): # スコア比較 158 logging.info("score check pass: %s %s", ExtDt(float(key)).format("ymdhms"), db_score.to_text()) 159 continue 160 161 # 更新 162 if db_score.rule_version == g.cfg.mahjong.rule_version: 163 count["mismatch"] += 1 164 logging.notice("mismatch: %s", ExtDt(float(key)).format("ymdhms")) # type: ignore 165 logging.info(" * slack: %s", db_score.to_text()) 166 logging.info(" * db: %s", slack_score.to_text()) 167 msg["mismatch"] += f"\t{ExtDt(float(key)).format("ymdhms")}\n" 168 msg["mismatch"] += f"\t\t修正前:{db_score.to_text()}\n" 169 msg["mismatch"] += f"\t\t修正後:{slack_score.to_text()}\n" 170 modify.db_update(slack_score, reactions_data) 171 else: 172 logging.info("score check skip: %s %s", ExtDt(float(key)).format("ymdhms"), db_score.to_text()) 173 continue 174 175 # 追加 176 if not g.cfg.setting.thread_report and val.get("in_thread"): 177 logging.notice("skip: %s (In-thread report)", slack_score) # type: ignore 178 continue 179 180 count["missing"] += 1 181 logging.notice("missing: %s (%s)", slack_score.ts, ExtDt(float(slack_score.ts)).format("ymdhms")) # type: ignore 182 msg["missing"] += f"\t{ExtDt(float(key)).format("ymdhms")} {slack_score.to_text()}\n" 183 modify.db_insert(slack_score, reactions_data) 184 185 for key in db_data: # DB -> slack チェック 186 # 保留チェック 187 if float(key) + g.cfg.search.wait > now_ts: 188 msg["pending"].append(str(key)) 189 logging.info("pending(DB -> slack): %s", ExtDt(float(key)).format("ymdhms")) 190 continue 191 192 # 登録済みデータは処理をスキップ 193 if key in slack_data: 194 continue 195 196 # 削除 197 count["delete"] += 1 198 logging.notice("delete: %s (Only database)", db_data[key]) # type: ignore 199 msg["delete"] += f"\t{ExtDt(float(key)).format("ymdhms")} {db_data[key].to_text()}\n" 200 g.msg.updatable = True 201 modify.db_delete(key) 202 203 # メッセージが残っているならリアクションを外す 204 if not g.msg.channel_id: 205 g.msg.channel_id = lookup.api.get_channel_id() 206 for icon in lookup.api.reactions_status(ts=key): 207 slack_api.call_reactions_remove(icon, ts=key) 208 209 return (count, msg) 210 211 212def check_remarks(slack_data: SlackSearchDict, db_data: list) -> tuple[dict, ComparisonDict]: 213 """メモの取りこぼしチェック 214 215 Args: 216 slack_data (SlackSearchDict): slack検索結果 217 db_data (list): DB登録状況 218 219 Returns: 220 tuple[dict, ComparisonDict]: 修正内容(結果) 221 """ 222 223 now_ts = float(ExtDt().format("ts")) 224 count: dict[str, int] = {"remark_mod": 0, "remark_del": 0} 225 msg: ComparisonDict = {"remark_mod": "", "remark_del": "", "pending": []} 226 227 # 比較用リスト生成 228 slack_remarks: list[RemarkDict] = [] 229 for val in slack_data.values(): 230 if (remark_list := val.get("remarks", [])): 231 for name, matter in remark_list: 232 if name in val.get("score", GameResult()).to_list() and val.get("in_thread"): 233 slack_remarks.append({ 234 "thread_ts": str(val.get("thread_ts", "")), 235 "event_ts": str(val.get("event_ts", "")), 236 "name": name, 237 "matter": matter, 238 }) 239 240 # slack -> DB チェック 241 for remark in slack_remarks: 242 # 保留チェック 243 if float(remark["event_ts"]) + g.cfg.search.wait > now_ts: 244 msg["pending"].append(remark["event_ts"]) 245 logging.info("pending(slack -> DB): %s", ExtDt(float(remark["event_ts"])).format("ymdhms")) 246 continue 247 248 if remark in db_data: 249 logging.info("remark pass(slack -> DB): %s", remark) 250 else: 251 count["remark_mod"] += 1 252 modify.remarks_delete(remark["event_ts"]) 253 modify.remarks_append(cast(dict, remark)) 254 logging.notice("modification(data mismatch): %s", remark) # type: ignore 255 256 # DB -> slack チェック 257 for remark in db_data: 258 if remark in slack_remarks: 259 logging.info("remark pass(DB -> slack): %s", remark) 260 else: 261 count["remark_del"] += 1 262 modify.remarks_delete_compar(remark) 263 logging.notice("delete(missed deletion): %s", remark) # type: ignore 264 265 return (count, msg) 266 267 268def check_total_score(slack_data: SlackSearchDict) -> tuple[dict, ComparisonDict]: 269 """素点合計の再チェック 270 271 Args: 272 slack_data (SlackSearchDict): slack検索結果 273 274 Returns: 275 tuple[dict, ComparisonDict]: 修正内容(結果) 276 """ 277 278 now_ts = float(ExtDt().format("ts")) 279 count: dict[str, int] = {"invalid_score": 0} 280 msg: ComparisonDict = {"invalid_score": "", "pending": []} 281 282 for key, val in slack_data.items(): 283 # 保留チェック 284 if val["edited_ts"]: 285 check_ts = float(max(val["edited_ts"])) + g.cfg.search.wait 286 else: 287 check_ts = float(key) + g.cfg.search.wait 288 289 if check_ts > now_ts: 290 msg["pending"].append(str(key)) 291 logging.info("pending(slack -> DB): %s", ExtDt(float(key)).format("ymdhms")) 292 continue 293 294 # "score"が取得できていない場合は処理をスキップ 295 if (score_data := val.get("score", GameResult())): 296 continue 297 298 # 判定条件外のデータはスキップ 299 if not g.cfg.setting.thread_report and val.get("in_thread", False): 300 continue 301 if score_data.rule_version != g.cfg.mahjong.rule_version: 302 continue 303 304 score_data.calc() 305 reaction_ok = val.get("reaction_ok") 306 reaction_ng = val.get("reaction_ng") 307 308 if score_data.deposit != 0: # 素点合計と配給原点が不一致 309 count["invalid_score"] += 1 310 logging.notice("invalid score: %s deposit=%s", key, score_data.deposit) # type: ignore 311 msg["invalid_score"] += f"\t{ExtDt(float(key)).format("ymdhms")} [供託:{score_data.deposit}]{score_data.to_text()}\n" 312 if reaction_ok is not None and key in reaction_ok: 313 slack_api.call_reactions_remove(g.cfg.setting.reaction_ok, ts=key) 314 if reaction_ng is not None and key not in reaction_ng: 315 slack_api.call_reactions_add(g.cfg.setting.reaction_ng, ts=key) 316 else: 317 if reaction_ng is not None and key in reaction_ng: 318 slack_api.call_reactions_remove(g.cfg.setting.reaction_ng, ts=key) 319 if reaction_ok is not None and key not in reaction_ok: 320 slack_api.call_reactions_add(g.cfg.setting.reaction_ok, ts=key) 321 322 return (count, msg)
SlackSearchDict =
dict[str, cls.types.SlackSearchData]
DBSearchDict =
dict[str, cls.score.GameResult]
def
main() -> None:
21def main() -> None: 22 """データ突合の実施、その結果をslackにpostする""" 23 # チェックコマンドを拾ったイベントの情報を保持(結果の返し先) 24 command_ch = g.msg.channel_id 25 command_ts = g.msg.event_ts 26 27 # データ突合 28 count, msg = data_comparison() 29 logging.notice("count=%s", count) # type: ignore 30 31 # 突合結果 32 after = ExtDt(days=-g.cfg.search.after).format("ymd") 33 before = ExtDt().format("ymd") 34 35 ret = f"*【データ突合】* ({after} - {before})\n" 36 if count["pending"]: 37 ret += f"* 保留:{count["pending"]}件\n" 38 for x in msg["pending"]: 39 ret += f"\t\t{ExtDt(float(x)).format("ymdhms")}\n" 40 ret += f"* 不一致:{count["mismatch"]}件\n{msg["mismatch"]}" 41 ret += f"* 取りこぼし:{count["missing"]}件\n{msg["missing"]}" 42 ret += f"* 削除漏れ:{count["delete"]}件\n{msg["delete"]}" 43 ret += f"* メモ更新:{count["remark_mod"]}件\n{msg["remark_mod"]}" 44 ret += f"* メモ削除:{count["remark_del"]}件\n{msg["remark_del"]}" 45 if count["invalid_score"] > 0: 46 ret += "\n*【素点合計不一致】*\n" 47 ret += msg["invalid_score"] 48 49 g.msg.channel_id = command_ch 50 slack_api.post_message(ret, command_ts)
データ突合の実施、その結果をslackにpostする
53def data_comparison() -> tuple[dict, ComparisonDict]: 54 """データ突合処理 55 56 Returns: 57 tuple[dict,dict]: 58 - dict: 処理された更新/追加/削除の件数 59 - ComparisonDict: slackに返すメッセージ 60 """ 61 62 count: dict = {} 63 msg: dict = {} 64 65 # slackログからゲーム結果を取得 66 slack_score = search.for_slack_score() 67 slack_remarks = search.for_slack_remarks() 68 for _, val in slack_remarks.items(): # スレッド元のスコアデータを追加 69 if (thread_ts := val.get("thread_ts")): 70 val["score"] = slack_score[thread_ts].get("score", GameResult()) 71 72 if slack_score: 73 first_ts = float(min(slack_score)) 74 else: 75 first_ts = float(ExtDt(days=-g.cfg.search.after).format("ts")) 76 77 # データベースからゲーム結果を取得 78 db_score = search.for_db_score(first_ts) 79 db_remarks = search.for_db_remarks(first_ts) 80 81 # --- スコア突合 82 ret_count, ret_msg = check_omission(slack_score, db_score) 83 count = dictutil.merge_dicts(count, ret_count) 84 msg = dictutil.merge_dicts(msg, ret_msg) 85 86 # --- 素点合計の再チェック(修正可能なslack側のみチェック) 87 ret_count, ret_msg = check_total_score(slack_score) 88 count = dictutil.merge_dicts(count, ret_count) 89 msg = dictutil.merge_dicts(msg, ret_msg) 90 91 # --- メモ突合 92 ret_count, ret_msg = check_remarks(slack_remarks, db_remarks) 93 count = dictutil.merge_dicts(count, ret_count) 94 msg = dictutil.merge_dicts(msg, ret_msg) 95 96 count.update(pending=len(msg["pending"])) 97 98 return (count, cast(ComparisonDict, msg))
データ突合処理
Returns:
tuple[dict,dict]:
- dict: 処理された更新/追加/削除の件数
- ComparisonDict: slackに返すメッセージ
def
check_omission( slack_data: dict[str, cls.types.SlackSearchData], db_data: dict[str, cls.score.GameResult]) -> tuple[dict, cls.types.ComparisonDict]:
101def check_omission(slack_data: SlackSearchDict, db_data: DBSearchDict) -> tuple[dict, ComparisonDict]: 102 """スコア取りこぼしチェック 103 104 Args: 105 slack_data (SlackSearchDict): slack検索結果 106 db_data (DBSearchDict): DB登録状況 107 108 Returns: 109 tuple[dict, ComparisonDict]: 修正内容(結果) 110 """ 111 112 now_ts = float(ExtDt().format("ts")) 113 count: dict[str, int] = {"mismatch": 0, "missing": 0, "delete": 0} 114 msg: ComparisonDict = {"mismatch": "", "missing": "", "delete": "", "pending": []} 115 116 for key, val in slack_data.items(): 117 # 保留チェック 118 if val["edited_ts"]: 119 check_ts = float(max(val["edited_ts"])) + g.cfg.search.wait 120 else: 121 check_ts = float(key) + g.cfg.search.wait 122 123 if check_ts > now_ts: 124 msg["pending"].append(str(key)) 125 logging.info("pending(slack -> DB): %s", ExtDt(float(key)).format("ymdhms")) 126 continue 127 128 # "score"が取得できていない場合は処理をスキップ 129 if (slack_score := val.get("score", GameResult())): 130 continue 131 132 # 情報更新 133 g.msg.channel_id = val.get("channel_id", "") 134 g.msg.user_id = val.get("user_id", "") 135 g.msg.event_ts = key 136 g.msg.check_updatable() 137 138 reactions_data = [] 139 reactions_data.append(val.get("reaction_ok")) 140 reactions_data.append(val.get("reaction_ng")) 141 142 if key in db_data: # slack -> DB チェック 143 db_score = db_data[key] 144 if not g.cfg.setting.thread_report: # スレッド内報告が禁止されているパターン 145 if val.get("in_thread"): 146 count["delete"] += 1 147 logging.notice("delete: %s (In-thread report)", slack_score) # type: ignore 148 msg["delete"] += f"\t{ExtDt(float(key)).format("ymdhms")} {slack_score.to_text()}\n" 149 modify.db_delete(key) 150 151 # リアクションの削除 152 if key in val.get("reaction_ok", []): 153 slack_api.call_reactions_remove(g.cfg.setting.reaction_ok, ts=key) 154 if key in val.get("reaction_ng", []): 155 slack_api.call_reactions_remove(g.cfg.setting.reaction_ng, ts=key) 156 continue 157 158 if slack_score.to_dict() == db_score.to_dict(): # スコア比較 159 logging.info("score check pass: %s %s", ExtDt(float(key)).format("ymdhms"), db_score.to_text()) 160 continue 161 162 # 更新 163 if db_score.rule_version == g.cfg.mahjong.rule_version: 164 count["mismatch"] += 1 165 logging.notice("mismatch: %s", ExtDt(float(key)).format("ymdhms")) # type: ignore 166 logging.info(" * slack: %s", db_score.to_text()) 167 logging.info(" * db: %s", slack_score.to_text()) 168 msg["mismatch"] += f"\t{ExtDt(float(key)).format("ymdhms")}\n" 169 msg["mismatch"] += f"\t\t修正前:{db_score.to_text()}\n" 170 msg["mismatch"] += f"\t\t修正後:{slack_score.to_text()}\n" 171 modify.db_update(slack_score, reactions_data) 172 else: 173 logging.info("score check skip: %s %s", ExtDt(float(key)).format("ymdhms"), db_score.to_text()) 174 continue 175 176 # 追加 177 if not g.cfg.setting.thread_report and val.get("in_thread"): 178 logging.notice("skip: %s (In-thread report)", slack_score) # type: ignore 179 continue 180 181 count["missing"] += 1 182 logging.notice("missing: %s (%s)", slack_score.ts, ExtDt(float(slack_score.ts)).format("ymdhms")) # type: ignore 183 msg["missing"] += f"\t{ExtDt(float(key)).format("ymdhms")} {slack_score.to_text()}\n" 184 modify.db_insert(slack_score, reactions_data) 185 186 for key in db_data: # DB -> slack チェック 187 # 保留チェック 188 if float(key) + g.cfg.search.wait > now_ts: 189 msg["pending"].append(str(key)) 190 logging.info("pending(DB -> slack): %s", ExtDt(float(key)).format("ymdhms")) 191 continue 192 193 # 登録済みデータは処理をスキップ 194 if key in slack_data: 195 continue 196 197 # 削除 198 count["delete"] += 1 199 logging.notice("delete: %s (Only database)", db_data[key]) # type: ignore 200 msg["delete"] += f"\t{ExtDt(float(key)).format("ymdhms")} {db_data[key].to_text()}\n" 201 g.msg.updatable = True 202 modify.db_delete(key) 203 204 # メッセージが残っているならリアクションを外す 205 if not g.msg.channel_id: 206 g.msg.channel_id = lookup.api.get_channel_id() 207 for icon in lookup.api.reactions_status(ts=key): 208 slack_api.call_reactions_remove(icon, ts=key) 209 210 return (count, msg)
スコア取りこぼしチェック
Arguments:
- slack_data (SlackSearchDict): slack検索結果
- db_data (DBSearchDict): DB登録状況
Returns:
tuple[dict, ComparisonDict]: 修正内容(結果)
def
check_remarks( slack_data: dict[str, cls.types.SlackSearchData], db_data: list) -> tuple[dict, cls.types.ComparisonDict]:
213def check_remarks(slack_data: SlackSearchDict, db_data: list) -> tuple[dict, ComparisonDict]: 214 """メモの取りこぼしチェック 215 216 Args: 217 slack_data (SlackSearchDict): slack検索結果 218 db_data (list): DB登録状況 219 220 Returns: 221 tuple[dict, ComparisonDict]: 修正内容(結果) 222 """ 223 224 now_ts = float(ExtDt().format("ts")) 225 count: dict[str, int] = {"remark_mod": 0, "remark_del": 0} 226 msg: ComparisonDict = {"remark_mod": "", "remark_del": "", "pending": []} 227 228 # 比較用リスト生成 229 slack_remarks: list[RemarkDict] = [] 230 for val in slack_data.values(): 231 if (remark_list := val.get("remarks", [])): 232 for name, matter in remark_list: 233 if name in val.get("score", GameResult()).to_list() and val.get("in_thread"): 234 slack_remarks.append({ 235 "thread_ts": str(val.get("thread_ts", "")), 236 "event_ts": str(val.get("event_ts", "")), 237 "name": name, 238 "matter": matter, 239 }) 240 241 # slack -> DB チェック 242 for remark in slack_remarks: 243 # 保留チェック 244 if float(remark["event_ts"]) + g.cfg.search.wait > now_ts: 245 msg["pending"].append(remark["event_ts"]) 246 logging.info("pending(slack -> DB): %s", ExtDt(float(remark["event_ts"])).format("ymdhms")) 247 continue 248 249 if remark in db_data: 250 logging.info("remark pass(slack -> DB): %s", remark) 251 else: 252 count["remark_mod"] += 1 253 modify.remarks_delete(remark["event_ts"]) 254 modify.remarks_append(cast(dict, remark)) 255 logging.notice("modification(data mismatch): %s", remark) # type: ignore 256 257 # DB -> slack チェック 258 for remark in db_data: 259 if remark in slack_remarks: 260 logging.info("remark pass(DB -> slack): %s", remark) 261 else: 262 count["remark_del"] += 1 263 modify.remarks_delete_compar(remark) 264 logging.notice("delete(missed deletion): %s", remark) # type: ignore 265 266 return (count, msg)
メモの取りこぼしチェック
Arguments:
- slack_data (SlackSearchDict): slack検索結果
- db_data (list): DB登録状況
Returns:
tuple[dict, ComparisonDict]: 修正内容(結果)
def
check_total_score( slack_data: dict[str, cls.types.SlackSearchData]) -> tuple[dict, cls.types.ComparisonDict]:
269def check_total_score(slack_data: SlackSearchDict) -> tuple[dict, ComparisonDict]: 270 """素点合計の再チェック 271 272 Args: 273 slack_data (SlackSearchDict): slack検索結果 274 275 Returns: 276 tuple[dict, ComparisonDict]: 修正内容(結果) 277 """ 278 279 now_ts = float(ExtDt().format("ts")) 280 count: dict[str, int] = {"invalid_score": 0} 281 msg: ComparisonDict = {"invalid_score": "", "pending": []} 282 283 for key, val in slack_data.items(): 284 # 保留チェック 285 if val["edited_ts"]: 286 check_ts = float(max(val["edited_ts"])) + g.cfg.search.wait 287 else: 288 check_ts = float(key) + g.cfg.search.wait 289 290 if check_ts > now_ts: 291 msg["pending"].append(str(key)) 292 logging.info("pending(slack -> DB): %s", ExtDt(float(key)).format("ymdhms")) 293 continue 294 295 # "score"が取得できていない場合は処理をスキップ 296 if (score_data := val.get("score", GameResult())): 297 continue 298 299 # 判定条件外のデータはスキップ 300 if not g.cfg.setting.thread_report and val.get("in_thread", False): 301 continue 302 if score_data.rule_version != g.cfg.mahjong.rule_version: 303 continue 304 305 score_data.calc() 306 reaction_ok = val.get("reaction_ok") 307 reaction_ng = val.get("reaction_ng") 308 309 if score_data.deposit != 0: # 素点合計と配給原点が不一致 310 count["invalid_score"] += 1 311 logging.notice("invalid score: %s deposit=%s", key, score_data.deposit) # type: ignore 312 msg["invalid_score"] += f"\t{ExtDt(float(key)).format("ymdhms")} [供託:{score_data.deposit}]{score_data.to_text()}\n" 313 if reaction_ok is not None and key in reaction_ok: 314 slack_api.call_reactions_remove(g.cfg.setting.reaction_ok, ts=key) 315 if reaction_ng is not None and key not in reaction_ng: 316 slack_api.call_reactions_add(g.cfg.setting.reaction_ng, ts=key) 317 else: 318 if reaction_ng is not None and key in reaction_ng: 319 slack_api.call_reactions_remove(g.cfg.setting.reaction_ng, ts=key) 320 if reaction_ok is not None and key not in reaction_ok: 321 slack_api.call_reactions_add(g.cfg.setting.reaction_ok, ts=key) 322 323 return (count, msg)
素点合計の再チェック
Arguments:
- slack_data (SlackSearchDict): slack検索結果
Returns:
tuple[dict, ComparisonDict]: 修正内容(結果)