AtCoderProblems icon indicating copy to clipboard operation
AtCoderProblems copied to clipboard

writerがコンテスト中に参加者よりも早くACし、かつ、その提出を公開するとFirst ACと認識される

Open kenkoooo opened this issue 4 years ago • 9 comments

現状の実装では、各問題について、コンテスト開始時刻以降にACした提出のうち最もidが小さい提出を First ACの提出として扱っています。

これはwriterはwriter解をコンテスト中には提出しないということを前提としていますが、実際にはwriterがコンテスト中に提出することもあり、本来First ACであるにもかかわらずFirst ACとして扱われない提出があります。

First AC として扱われるべき提出 https://atcoder.jp/contests/abc196/submissions/21061490

誤って First AC として扱われている writer 解 https://atcoder.jp/contests/abc196/submissions/21059851

この問題を解決する方法として次のような選択肢が考えられます。

  1. 各コンテストごとにwriter情報を保持し、集計の際にwriterのコンテスト中のACを除外する。
    • AtCoderの告知ページで公開されているwriter情報を収集する必要があり、面倒。
    • tester情報は公開されないので、同じような行動のtesterがいた場合にどうしようもない。
  2. 各コンテストごとに順位表の情報を保持し、集計の際にコンテスト中の提出で順位表に載っていないユーザーのものを除外する。
    • 順位表はJSONで取れるので良さそう。

kenkoooo avatar Mar 28 '21 05:03 kenkoooo

興味あるので、やり方見てます。 JSONから参加者のリストを列挙して、SQLのINで絞り込む感じですね。

fukatani avatar May 06 '21 06:05 fukatani

各コンテストの順位表のjsonを落として保存する仕組みを整えるのが最初のステップになりそうです。保存はS3にするとすると、以下のようになりそうです。

  1. ~~SQL~~ contests.json からコンテスト一覧を取得する。
  2. S3からダウンロード済みコンテスト一覧を取得する。
  3. 差分からダウンロードしていないコンテスト一覧を作り、ダウンロードする。

kenkoooo avatar May 06 '21 06:05 kenkoooo

助言ありがとうございます! 毎回jsonをダウンロードする感じで作ってしまうところでした。

lamda-functions/time-estimator/function.pyが参考にできそうなのでこれを読みつつ考えてみます。

fukatani avatar May 06 '21 15:05 fukatani

続きがやれてなくてすいません。そろそろ手を付けようと思いますが、もし急ぎだったら他の人が引き受けてもかまいません。

fukatani avatar Jun 06 '21 11:06 fukatani

続きがやれてなくてすいません。そろそろ手を付けようと思いますが、もし急ぎだったら他の人が引き受けてもかまいません。

全然大丈夫です!やれたらやる(全くやらなくてもOK)くらいの気持ちでやっていきましょう!

kenkoooo avatar Jun 06 '21 15:06 kenkoooo

ありがとうございます。

素人質問なのですが、

                (
                    SELECT MIN(submissions.id) FROM submissions
                    LEFT JOIN contests ON contests.id=contest_id
                    WHERE result='AC'
                    AND contests.start_epoch_second < submissions.epoch_second
                    AND (problem_id, submissions.{column}) IN
                    (
                        SELECT problem_id, MIN(submissions.{column}) FROM submissions
                        LEFT JOIN contests ON contests.id=contest_id
                        WHERE result='AC'
                        AND contests.start_epoch_second < submissions.epoch_second
                        GROUP BY problem_id
                    )
                    GROUP BY problem_id
                )

                    WHERE result='AC'
                    AND contests.start_epoch_second < submissions.epoch_second

あたりに、submissions.user_name IN {コンテストの参加者}の条件を入れればいいと思うんですけど、 コンテストごとに参加者を列挙するやり方がわかっておりません :cactus:

コンテスト参加者のテーブルがあるなら、SELECTを使って列挙できそうですけど、テーブルを作るべきなんでしょうか? jsonからrustの中でコンテスト -> 参加者の文字列みたいなのを取得するところはできるんですけど、それをSQLにうまく持っていく方法がわからずです。

fukatani avatar Jun 07 '21 15:06 fukatani

SQL クエリを合わせるのは結構難しい気がしています。例えば WHERE submissions.user_id IN ({参加者のユーザーIDのリスト}) などとすることで可能ではありますが、クエリが長大になりますし現実的ではありません。

update_submissions_of_problems()batch_update から呼び出されていますが、batch_update は AC した提出を全てもっています。ここで提出をフィルターして計算し、update_submissions_of_problems() を使わずに新しい関数を作ってSQLに書き込んでいくことになるかと思います。

kenkoooo avatar Jun 08 '21 04:06 kenkoooo

https://atcoder.jp/contests/abc196/submissions/21059851 ってnot foundになってますね。 今、submission crawlerを回してbatch_updateすると、https://atcoder.jp/contests/abc196/submissions/21061490 がFirst AC扱いになります。

fukatani avatar Jun 12 '21 04:06 fukatani

https://atcoder.jp/contests/abc196/submissions/21059851 ってnot foundになってますね。 今、submission crawlerを回してbatch_updateすると、https://atcoder.jp/contests/abc196/submissions/21061490 がFirst AC扱いになります。

kortonさんが気を遣って非公開にしたっぽいですね

kenkoooo avatar Jun 12 '21 04:06 kenkoooo