1日2本のバチャを手動で立てているのはアホすぎたので、心がぶっ壊れたのを機にやってみた(人生 いろいろ〜)
- はじめに…大感謝 KowerKoint さん
- 私の事前知識
- ABCなにかとは
- やりたいこと
- やったこと
- 変更した箇所
- こんな感じで立てられるようになったよ!
- 今後どうにかしたいこと
- やってみて思ったこと
はじめに…大感謝 KowerKoint さん
AtCoder Problems Contest Builder という、バチャを立てている人間にとって、喉から手が出るほど欲しかったツール…。
こちらのステキツール、ツールの素敵さだけでなく、なんとまあコードの読みやすいこと読みやすいこと。
そして「動いたあやったあ!」とツイートした瞬間「わからないことあったら聞いてくださいね」とリプをくださる菩薩的人間性。
All perfect…足を向けて眠れません。本当に、だいだいだいかんしゃ!です!
こちらのステキツールを、ABCなにか仕様に変更する過程が、今回の記事内容です。
私の事前知識
- Pythonで競プロをやっている(底を擦ってる茶)
- 競プロ以外だと、テキストファイルに出力するやり方は知っている
- Web知識は人並みくらい
以上!!!!!
ABCなにかとは
元々、私が個人的に精進するために立て始めた、35分のバチャ(バーチャルコンテスト)です。
- 平日14:00〜14:35、21:00〜21:35で開催
- コンセプトは「早解き力を鍛える!35分でA〜D問題まで辿り着けるようになろう(できたら解けるようになろう)」
- 毎晩21時の頭を冴えさせるために、平日に立てている
短い時間でしっかり集中できること、何が出てくるかわからないガチャ感、懐かしい回に出会った時の望郷感(?)、〜緑レートまでは本来の目的で、青以上は1st RTA狙いで…など、いろいろな方にお楽しみいただけています。うれしい
やりたいこと
- diff範囲指定など、使わない機能を横に置く
- ARC / AGCなにかを追加にあたり、ABC, ARC, AGCそれぞれのコンテスト指定範囲から乱数を生成
- ABCはA〜D, ARCはA〜C, AGCはA〜Bの問題をセット
- 生成したURLを、告知botツイート用にテキストファイルへ出力
やったこと
トークンってどうすりゃ手に入れられるんだ?を調べる
AtCoder Problems Contest Builder の README.mdに記載のある
の意味や、やり方が、永遠にわからなくて挫けそうになったんだぜ?
が、すでに崩れ落ちているむりおでんことわたくし(2023/05/27(土)現在)は、一味違うんだぜ?なので、得意のググり力でたどり着いた答えが chrome拡張機能のEditThisCookie でした。
拡張機能を起動して出てくるこいつをゲット!コピペだあ!!
無事にトークンとやらをゲットしました(まだふんわりとしかわかってない)
コードを読み、わからない部分を整理してママに聞く
業プロ的Pythonを読むのはまだ2回めなので、目が枯れるまで読みながら、コメントアウトをつけていく。
その後、いつもお世話になっているママことimaimaiさん、開発ができすぎてもう何がすごいのかよくわからないすごさ。あ、生み出しているからママなのか…?!?!
前回の大宴会スクレイピングに引き続き、助けを乞いました…いつもありがとう
ここからはぜひ、AtCoder Problems Contest Builder の main.py も開きながら読んでいただけると、よさそうです。
質問したことは以下です。
やりたいこと
- ランダムに数字を生成して、abc{}a,〜dを追加した問題名で、問題セットを作りたい
わかった
- problem_jsonで持ってきてる問題セットは、keyが問題名になっている
わからない
- 54行目〜、きっと問題を設定している部分のfor文がまだ読解できてない…そこをどうにかすればできる…?
- 83行目のtokenに直接書き込んでも良いのか…?
- 全体的に、実験の仕方がわからない
いやあ。なんて素晴らしい質問の仕方なんだ。自画自賛するしかない。しない選択肢がない。
返答していただいた内容は
- 54行目からは、config.pyで設定した内容から、問題の候補を絞っている
- config.pyのproblem_infosの各オブジェクトに、問題名を設定するkeyを追加し、それをもとに問題を絞れそう
- tokenは、他者に公開しない(githubなどに上げない)のであれば、直接書き込んでOK
- 実験は、89行目以降のrequests.post以降をコメントアウトし、所々でprintデバックでOK
とのことで、満を持し、いじいじしはじめる
変更した箇所
config.py
ABC, ARC or AGCを1日2回開催するデータをセットするために、配列自体を増殖
diff設定などは適当にし、残しておきました(結果的に、のちほどmain.pyのfor文の中で設定しちゃったため)
いつか綺麗にしてあげたい…
# コンテストセット一覧 # abc用 contest_sets_abc = [ { 'name': '☀️🍰ABCなにか(Dまで)!', 'title': '☀️🍰ABCなにか(Dまで)!', 'memo': 'だれでも参加してください!早解き練習にどうぞ / ABCD問題を35分間走るバチャ / ABC126〜最新-10までのなにかがランダムで出現 / 通知bot https://twitter.com/abc_nanica', 'everyday_start_time': '14:00', 'duration_second': 2100, 'penalty_second': 300, 'problem_infos': [ { 'difficulty_range': (0, 1500), 'point': 1, 'include_experimental': True, 'duplicate_remove_days': 60, } ] }, { 'name': '🌙🍰ABCなにか(Dまで)!', 'title': '🌙🍰ABCなにか(Dまで)!', 'memo': 'だれでも参加してください!早解き練習にどうぞ / ABCD問題を35分間走るバチャ / ABC126〜最新-10までのなにかがランダムで出現 / 通知bot https://twitter.com/abc_nanica', 'everyday_start_time': '21:00', 'duration_second': 2100, 'penalty_second': 300, 'problem_infos': [ { 'difficulty_range': (0, 1500), 'point': 1, 'include_experimental': True, 'duplicate_remove_days': 60 } ] } ] # arc用 contest_sets_arc = [ { 'name': '☀️🍘ARCなにか(Cまで)!', 'title': '☀️🍘ARCなにか(Cまで)!', 'memo': 'だれでも参加してください!早解き練習にどうぞ / ABC問題を55分間走るバチャ / ARC104〜最新-2までのなにかがランダムで出現 / 通知bot https://twitter.com/abc_nanica', 'everyday_start_time': '15:00', 'duration_second': 3300, 'penalty_second': 300, 'problem_infos': [ { 'difficulty_range': (0, 4000), 'point': 1, 'include_experimental': True, 'duplicate_remove_days': 60, } ] }, { 'name': '🌙🍘ARCなにか(Cまで)!', 'title': '🌙🍘ARCなにか(Cまで)!', 'memo': 'だれでも参加してください!早解き練習にどうぞ / ABC問題を55分間走るバチャ / ARC104〜最新-2までのなにかがランダムで出現 / 通知bot https://twitter.com/abc_nanica', 'everyday_start_time': '22:00', 'duration_second': 3300, 'penalty_second': 300, 'problem_infos': [ { 'difficulty_range': (0, 4000), 'point': 1, 'include_experimental': True, 'duplicate_remove_days': 60 } ] } ] # agc用 contest_sets_agc = [ { 'name': '☀️🌶AGCなにか(Bまで)!', 'title': '☀️🌶AGCなにか(Bまで)!', 'memo': 'だれでも参加してください!早解き練習にどうぞ / AB問題を55分間走るバチャ / AGC001〜最新-2までのなにかがランダムで出現 / 通知bot https://twitter.com/abc_nanica', 'everyday_start_time': '15:00', 'duration_second': 3300, 'penalty_second': 300, 'problem_infos': [ { 'difficulty_range': (0, 10000), 'point': 1, 'include_experimental': True, 'duplicate_remove_days': 60, } ] }, { 'name': '🌙🌶AGCなにか(Bまで)!', 'title': '🌙🌶AGCなにか(Bまで)!', 'memo': 'だれでも参加してください!早解き練習にどうぞ / AB問題を55分間走るバチャ / AGC001〜最新-2までのなにかがランダムで出現 / 通知bot https://twitter.com/abc_nanica', 'everyday_start_time': '22:00', 'duration_second': 3300, 'penalty_second': 300, 'problem_infos': [ { 'difficulty_range': (0, 10000), 'point': 1, 'include_experimental': True, 'duplicate_remove_days': 60 } ] } ]
main.py
どのバチャを立てるか、を入力で受け取る
14行目付近に打ち込みました。ドドパーン!
contest_typeという変数を作り、ターミナルで入力した「abc」または「arc」または「agc」を代入しています。
上記三種類以外の文字が入力されたら、ここで終了するようにしている。
ところで、いつも競プロでは「exit(print('hoge'))」って書いているので、同じ書き方をしそうになった、が、他の部分と合わせて0を返すようにした。
どうして0を返すのかはまだわかっていない…
print('どのバチャをたてる?') contest_type = input() if contest_type == 'abc': contest_sets = config.contest_sets_abc elif contest_type == 'arc': contest_sets = config.contest_sets_arc elif contest_type == 'agc': contest_sets = config.contest_sets_agc else: print('打ち間違いだよ') exit(0)
バチャの日付設定のYYYY(西暦)を打たなくていいようにする
36, 45行目のinput前に'2023' + を書き加え、月日だけ入力すればOKにしました。来年になったら変えるぞ(どなたか、今年のクリスマスくらいに、私にプレゼントとして思い出させてください…)
date = '2023-' + input('開催日を入力してね(MM-DD): ')
指定コンテスト以外の問題は弾く
59行目の、for文内if条件文を書き換え
冒頭で作ったcontest_typeの文字列が入ってない問題は、さようならします
if not contest_type in problem_id: continue
各コンテストにおける問題数の設定
75行目に追加
- 途中から問題の傾向や、問題の数が変更になっているので、適切な範囲に設定
- 最後の数字を手動で変えなきゃいけないのが若干めんどい。が、おそらくconfig.pyの設定ではじいてるから、適当なでか数字入れておけば良いのかも…
- agcはzfillをするのを諦めてしまっているのがバレるぜ。3桁になったらちゃんとやる…
if contest_type == 'abc': problem_id = f'abc{str(random.randint(126, 300))}_' problem_type = ['a', 'b', 'c', 'd'] elif contest_type == 'arc': problem_id = f'arc{str(random.randint(104, 158))}_' problem_type = ['a', 'b', 'c'] else: problem_id = f'agc0{str(random.randint(10, 60))}_' problem_type = ['a', 'b'] for d in problem_type: problems.append({ 'id': problem_id + d, 'point': problem_info['point'], 'order': i })
tokenの記述
83行目の値を変更
token = 'gho_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
ご自身のトークンに置き換えてくださいませ。xの数はかなりてきとうっす
生成したURLをテキストに書き出し、ツイート用文章作成
103行目に追加
だいたい何をやっているかというと
- ツイート生成用のテキストファイルを4つ作成
- contest_type別にアイコンと、テキストファイルの名前を設定
- 昼か夜か別に、ツイート用の文字列と、テキストファイルの名前を設定
- datetimeから曜日を持ってきて、数値を日本語表記へ変換
- 一覧用ツイート(【たてたよ】)と、通知用ツイート(今日の〇〇のぶん!)をセット。日付部分だけ抜き出しのスライスがなんか大変だった
# 通知ツート生成 if contest_type == 'abc': icon = '🍰' text_name = 'tweet_list_abc_' elif contest_type == 'arc': icon = '🍘' text_name = 'argc_' elif contest_type == 'tweet_list_argc': icon = '🌶' text_name = 'tweet_list_argc_' if contest_index == 0: contest_time = 'おひる' text_name += 'day.txt' else: contest_time = 'よる' text_name += 'night.txt' day = start_dt.weekday() day_of_week = {0: '(月)', 1: '(火)', 2: '(水)', 3: '(木)', 4: '(金)'} # 一覧生成 f = open(text_name, 'a', encoding="utf-8") f.write(str(start_dt)[8:10] + day_of_week[day] + '\n') f.write('https://kenkoooo.com/atcoder/#/contest/show/' + contest_id + '\n\n') f.close() # 通知個別ツイート生成 f = open('tweet.txt', 'a', encoding="utf-8") f.write(problem_id + '\n' + str(start_dt)[8:10] + day_of_week[day] + '\n') f.write(f'{icon}今日の{contest_time}のぶん!' + '\n') f.write('https://kenkoooo.com/atcoder/#/contest/show/' + contest_id + '\n\n') f.close()
printの文言を変更
他、立てていてしあわせになれるよう、変えてみました。
プログラムが終了すると毎回「完了したよ!おつかれさま、いつもありがとう!」と言ってくれるの、愛着が深くなりすぎる…むふふ
こんな感じで立てられるようになったよ!
- main.pyを実行し、立てたいコンテストを入力(abc, arc, agc)
- 昼か夜かを選ぶ
- 立てたい日付を入力する(自動で前回立てた日の翌日になるので、違う場合は変更)
たったこれだけで!
自動的に問題がセットされて!
ツイート用の文章も作って!くれる!!
やばやばのやばで元気が出ました
今後どうにかしたいこと
- 54行目のfor文をしっかり読解し、config.pyに無駄に設定してしまっている領域をすっきりさせたい…
- if文がアホほど多い中学生コードなので、もうちょっと賢い業プロの書き方を知りたい
やってみて思ったこと
仕事以外で、自分のためにプログラミングをするのが初めてだったので、すごく楽しかったです。
今回はKowerKoint さんの素晴らしいベースから、自分仕様にいじいじしただけでしたが、いつか自分のためのツールを0から作ってみたいぞ!!と思いました。
そして、何より
「競プロで、Pythonを選んでよかった…」
これに尽きます…!
競プロ以外でPythonを使わなかったのですが、ほんとーにやっててよかったー!と心から思いました。
これを機に、Pythonで何かを作る、にもどんどんチャレンジしていきたいです。
読んでくださり、ありがとうございました!
ぜひ、ABCなにかで対よろです💪