AtCoder コンテストでテストケース取得、テスト、提出までをコマンドラインで行う

## はじめに
`atcoder-cli`, `online-judge-tools` を用い、ターミナル上 (Mac) でテストケース取得、テスト、提出まで行う手順です。

AtCoder を始めた頃は、特に環境整備をせずにコンテストページ上のコードテストを利用していましたが、この記事の通り環境整備をしたことで Visual Studio Code + iTerm2 上で全て完結するようになり、提出までのスピードが上がりました。


## 事前準備
必要なツールのインストール

```sh
$ pip3 install online-judge-tools
$ npm install -g atcoder-cli
$ pip3 install selenium
```

ツールで AtCoder へログイン

```sh
$ acc login
$ oj login https://atcoder.jp/
```

## 設定
全部の問題ディレクトリが作られるようにする。例えば、AtCoder Begginer Contest の場合、acc new abcXXX コマンドで a ~ f の問題が作成されるようにする

```sh
$ acc config default-task-choice all
```

config ディレクトリの場所を表示

```sh
$ acc config-dir
```

テンプレート設定を行う。config ディレクトリに template 名のフォルダを作成し、その中にテンプレートのソースコード (例：`main.py`)と、テンプレートの設定ファイル(`template.json`)を作成する。

```sh
# config ディレクトリへ移動
$ cd /Users/xxxxxxxxxx/Library/Preferences/atcoder-cli-nodejs
$ mkdir py
$ cd py
$ touch main.py template.json
```

問題のディレクトリを作った時に、main.py が作成され、提出対象も main.py とするには下記のように書く。

```sh
$ cat template.json 
{
  "task":{
    "program": ["main.py"],
    "submit": "main.py"
  }
}
```

main.py が作成された時のデフォルト設定を編集する。`#!/usr/bin/env python3` は必須。自分の場合は追加でよくある入力パターンをデフォルトで書き込んでいる。

```sh
$ cat main.py 
#!/usr/bin/env python3
S = input()
N = int(input()) 
S = input().split()
A, B, C = input().split()
L = list(map(int, input().split()))
H, N = map(int, input().split())
```

デフォルトのテンプレートの設定を py にする (py ディレクトリで設定したファイルが適用)

```sh
$ acc config default-template py
```

テンプレートの確認

```sh 
$ acc templates
search template directories in /Users/xxxxxxxxxx/Library/Preferences/atcoder-cli-nodejs
NAME  SUBMIT-PROGRAM
py    main.py
```

## ディレクトリ作成
下記の例は、AtCoder Bergginer Contest 154 のディレクトリを作成する場合。`main.py` とテストの入力と出力のファイルが作成される。

```sh
$ acc new abc154
$ tree
.
├── a
│   ├── main.py
│   └── tests
│       ├── sample-1.in
│       ├── sample-1.out
│       ├── sample-2.in
│       └── sample-2.out
├── b
│   ├── main.py
│   └── tests
│       ├── sample-1.in
│       ├── sample-1.out
│       ├── sample-2.in
│       ├── sample-2.out
│       ├── sample-3.in
│       └── sample-3.out
├── c
│   ├── main.py
│   └── tests
│       ├── sample-1.in
│       ├── sample-1.out
│       ├── sample-2.in
│       ├── sample-2.out
│       ├── sample-3.in
│       └── sample-3.out
├── contest.acc.json
├── d
│   ├── main.py
│   └── tests
│       ├── sample-1.in
│       ├── sample-1.out
│       ├── sample-2.in
│       ├── sample-2.out
│       ├── sample-3.in
│       └── sample-3.out
├── e
│   ├── main.py
│   └── tests
│       ├── sample-1.in
│       ├── sample-1.out
│       ├── sample-2.in
│       ├── sample-2.out
│       ├── sample-3.in
│       ├── sample-3.out
│       ├── sample-4.in
│       └── sample-4.out
└── f
    ├── main.py
    └── tests
        ├── sample-1.in
        ├── sample-1.out
        ├── sample-2.in
        └── sample-2.out

12 directories, 41 files
```

## テスト
プログラムが完成したら `online-judge-tools` を使いテストを行う (atcoder-cli にはテストのコマンドは無い)

```sh
$ oj t -c "python3 main.py" -d ./tests/
```

自分の場合は alias を貼ることで 対象の問題のディレクトリで `test`コマンドのみでテストができるようにしています。

```sh
$ vim ~/.bash_profile

# 以下を追加
alias test='oj t -c "python3 main.py" -d ./tests/'

$ source ~/.bash_profile
```

 対象の問題のディレクトリで `test`コマンドを実行

```sh
$ pwd
/xxxxx/atcoder/problem/abc151/a
$ test
```

デバッグ中などで、問題文以外に載っているテストケース以外でテストをしたい場合は、普通にプログラムを実行し、テスケースを入力する。下記のようなプログラムの場合、

```python
n = int(input()) 
print(n)
```

下記のように実行して入力することで出力を得ることで想定される結果が返ってくるか確認する。

```sh
$ python main.py
1 # 入力
1 # 出力
```

## 提出
問題のディレクトリにて下記コマンドを行うことで自動で AtCoder のページに飛んで提出する。

```sh
$ acc s
```


## 参考
- [AtCoder](https://atcoder.jp/)
- [AtCoder Problems](https://kenkoooo.com/atcoder/#/table/taigok)
- [online-judge-tools](https://github.com/kmyk/online-judge-tools)
- [atcoder-cli](https://github.com/Tatamo/atcoder-cli)
   - [コマンドラインツールatcoder-cliを公開しました](http://tatamo.81.la/blog/2018/12/07/atcoder-cli/)