atcoder-cliでコンテスト期間中に問題の追加があった場合の対応
要約
・コンテスト期間中に問題追加された場合は、contest.acc.jsonを直接編集し、$ acc add --force コマンドを実施する。
背景
E869120氏主催の「競プロ典型90問」を、AtCoderのジャッジを利用して挑戦中。
普段自分はatcoder-cliとonline-judge-toolsの併用で、テストケースのチェックなど一括で実施中。
しかし、「競プロ典型90問」は毎日一題ずつ追加される仕様のため、atcoder-cliの新規コンテスト追加では追加された問題に対応不可能であった。
今回はcontest.acc.jsonの編集により、コンテスト中の問題追加への対応を行った。
問題追加の方法
既存の問題追加は$ acc add コマンドで行えるが、このコマンドでは今回のケースに対応できない。
なぜならacc addはコンテストの仕様をダウンロードした際の問題数しか登録されておらず、途中で問題が増えても新規の問題には対応できない(ようだ)。
helpを読むと、$ acc add --force で上書きはできるようだが、追加問題の上書きは達成できず。
そこでcontest.acc.jsonを直接編集し、$ acc add --forceを行うことで、問題を無理やり追加することに成功した。
contest.acc.jsonの編集
contest.acc.jsonは以下のような構成である。
{ "contest": { "id": "typical90", "title": "競プロ典型 90 問", "url": "https://atcoder.jp/contests/typical90" }, "tasks": [ { "id": "typical90_a", "label": "001", "title": "Yokan Party(★4)", "url": "https://atcoder.jp/contests/typical90/tasks/typical90_a", "directory": { "path": "001", "testdir": "tests", "submit": "main.cpp" } }, { "id": "typical90_b", "label": "002", "title": "Encyclopedia of Parentheses(★3)", "url": "https://atcoder.jp/contests/typical90/tasks/typical90_b", "directory": { "path": "002", "testdir": "tests", "submit": "main.cpp" } }, /*以下略*/ ] }
連番がaからzまであり、次はaaからazまで、その次はbaからbzに変化する構成である。
最初は、手作業でコピペしていたが、30問あたりから面倒に感じたため、半自動で生成するコードを作製した。(C++で作成)
※21/5/7追記:さすがに冗長だったため、まとめられるところをまとめた。
#include <bits/stdc++.h> using namespace std; typedef long long int ll; #define REPS(i, x) for (ll i = 1; i <= (ll)(x); i++) int main() { ios::sync_with_stdio(false); cin.tie(0); REPS(i, 90) { if (i <= 26) { char ch = i + 'Z'+6; printf(" {\n"); printf(" \"id\": \"typical90_%c\",\n", ch); printf(" \"label\": \"%03lld\",\n", i); printf(" \"title\": \"xxx\",\n"); printf(" \"url\": \"https://atcoder.jp/contests/typical90/tasks/typical90_%c \",\n", ch); } else if(i<=52){ char ch = i + 'Z' + 6-26; printf(" {\n"); printf(" \"id\": \"typical90_a%c\",\n", ch); printf(" \"label\": \"%03lld\",\n", i); printf(" \"title\": \"xxx\",\n"); printf(" \"url\": \"https://atcoder.jp/contests/typical90/tasks/typical90_a%c\",\n", ch); } else if(i<=78){ char ch = i + 'Z' + 6 - 52; printf(" {\n"); printf(" \"id\": \"typical90_b%c\",\n", ch); printf(" \"label\": \"%03lld\",\n", i); printf(" \"title\": \"xxx\",\n"); printf(" \"url \": \"https://atcoder.jp/contests/typical90/tasks/typical90_b%c\",\n", ch); } else{ char ch = i + 'Z' + 6 - 78; printf(" {\n"); printf(" \"id\": \"typical90_c%c\",\n", ch); printf(" \"label\": \"%03lld\",\n", i); printf(" \"title\": \"xxx\",\n"); printf(" \"url\": \"https://atcoder.jp/contests/typical90/tasks/typical90_c%c\",\n", ch); } printf(" \"directory\": {\n"); printf(" \"path\": \"%03lld\",\n", i); printf(" \"testdir\": \"tests\",\n"); printf(" \"submit\": \"main.cpp\"\n"); printf(" }\n"); printf(" },\n"); } }
もっとキレイに書きたかったが、仕方なく原始的な場合分けを行った。
問題タイトルのスクレイピング能力はないため、問題が追加され次第自分でコピペしてaccコマンドを実施する。