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する

def data_comparison() -> tuple[dict, cls.types.ComparisonDict]:
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]: 修正内容(結果)