[Atcoder][競プロ]サンプルテストを自動化

##この記事でできるもの

とにかく楽をしたいから自動化を目指す


今回使った例題
https://atcoder.jp/contests/abc190/tasks/abc190_a

ターミナルで

```
$ rn a
```
と打つと

```
---------------情報----------------------
パス : /<path>/atcoder/abc/190
大会レベル : abc
大会番号 : 190
問題番号 : a
URL : https://atcoder.jp/contests/abc190/tasks/abc190_a

---------------エラー内容---------------
--------------------------------------

[INFO] online-judge-tools 11.1.3 (+ online-judge-api-client 10.8.0)
[INFO] 3 cases found
time: illegal option -- f
usage: time [-lp] <command>
[WARNING] GNU time is not available: time

[INFO] sample-1
[INFO] time: 0.055814 sec
[SUCCESS] AC    ←A問サンプル1のテスト結果

[INFO] sample-2
[INFO] time: 0.009793 sec
[SUCCESS] AC    ←A問サンプル2のテスト結果

[INFO] sample-3
[INFO] time: 0.009116 sec
[FAILURE] WA    ←A問サンプル3のテスト結果WAの場合以下が表示
input:          
2 2 1           ←サンプルの値

output:
Aoki            ←実行結果

expected:
Takahashi       ←正しい答え結果


[INFO] slowest: 0.055814 sec  (for sample-1)
[FAILURE] test failed: 2 AC / 3 cases
```

または文法を間違うと以下のように表示させる

```
---------------情報----------------------
パス : /<path>/atcoder/abc/190
大会レベル : abc
大会番号 : 190
問題番号 : a
URL : https://atcoder.jp/contests/abc190/tasks/abc190_a

---------------エラー内容---------------
./a.cpp: In function 'int main()':
./a.cpp:39:13: error: expected ';' before '}' token
   39 |     return 0
      |             ^
      |             ;
   40 | }
      | ~            
----------------------------------------------
```

また，自分のテストケースを実行したい場合

```
rn a test
```

```
---------------エラー内容---------------
---------------入力内容-----------------
1 1 1  <- 入力
No     <- 出力結果
----------------------------------------
```

とすることができる。

これを作る

##準備

こんなフォルダを用意する

```
└─atcoder
  ├─abc
  ├─arc
  ├─agc
  ├─coppy
  │ ├─a.cpp
  │ ├─b.cpp
  │ ├─c.cpp
  │ ├─d.cpp
  │ └─script.sh
  └─coppy.sh
```


##必要なこと
・ シェルスクリプトの使い方
・ エラーコードを読む気持ち
・
・ zsh bash(masOSの方はzshなのでこの記事を丸コピすれば動きます)

##作ってみる


[online-judge-tools](https://github.com/online-judge-tools/oj/blob/master/docs/getting-started.ja.md)
の手順にしたがってojをダウンロード以下手順

```
% pip3 install --user online-judge-tools
ダウンロードの際，ojが存在するパスが表示される
/opt/home/..
/usr/local/bin/..
/Users/..
のどれか


% echo 'export PATH="/表示されたパス/bin:$PATH"' >> ~/.zshrc
//もしくは
% open ~/.zshrc

//bashの場合は .bashrc

#確認
% oj --version
```

###C++ファイル
a.cppやb.cppは
[[競技プログラミング] C++ チートシート](https://qiita.com/akidon0000/items/019c1a6bcb494f0252ea)
のテンプレートを使うと便利

###script.sh

```script.sh
# !/bin/sh
# 第一引数 問題番号
#  cd abc/190

alias g++='g++-10'

# 現在のパスを取得
path=$(cd $(dirname $0); pwd)

# コンテストレベル
contestLevel=${path##*atcoder/}
contestLevel=${contestLevel%/*}

# コンテスト番号
contestNumber=${path#*c/}

# 問題番号 引数
questionNumber="$1"


if [ $# -eq 2 ];then
  echo "---------------エラー内容---------------"
  # コンパイル
  g++ -Wall -std=c++14 ./${questionNumber}.cpp
  echo "---------------入力内容-----------------"
  ./a.out
  echo "----------------------------------------"
  rm -f a.out
  exit
fi



# AtCoderのURL
URL="https://atcoder.jp/contests/${contestLevel}${contestNumber}/tasks/${contestLevel}${contestNumber}_${questionNumber}"

# サンプルデータダウンロード
# oj login "${URL}"
oj dl "${URL}"


echo ""
echo "---------------情報----------------------"

echo "パス : "${path}
echo "大会レベル : "${contestLevel}
echo "大会番号 : "${contestNumber}
echo "問題番号 : "${questionNumber}
echo "URL : "${URL}
echo ""

echo "---------------エラー内容---------------"
# コンパイル
g++ -Wall -std=c++14 ./${questionNumber}.cpp

echo "----------------------------------------"
echo ""

# サンプルテスト
oj test

# 新しくできたファイルを削除
rm -f a.out
rm -rf test
```

<details><summary>ABC like(URLが定常と異なる)場合</summary><div>
URLはその都度入力

```script.sh
#####################################################
alias g++='g++-10'

# AtCoderのURL
URL=""


# 問題番号 引数
questionNumber="$1"


if [ $# -eq 2 ];then
  echo "---------------エラー内容---------------"
  # コンパイル
  g++ -Wall -std=c++14 ./${questionNumber}.cpp
  echo "---------------入力内容-----------------"
  ./a.out
  echo "----------------------------------------"
  rm -f a.out
  exit
fi


# サンプルデータダウンロード
# oj login "${URL}"
oj dl "${URL}"


echo ""
echo "---------------情報----------------------"

echo "URL : "${URL}
echo ""

echo "---------------エラー内容---------------"
# コンパイル
g++ -Wall -std=c++14 ./${questionNumber}.cpp

echo "----------------------------------------"
echo ""

# サンプルテスト
oj test

# 新しくできたファイルを削除
rm -f a.out
rm -rf test
```
---
</div></details>

###coppy.sh

```coppy.sh
# !/bin/sh
# 第一引数 コンテストレベル
# 第二引数 コンテスト番号
# sh coppy.sh abc 191

# 引数が正しく入力されていない場合
if [ ! $# -eq 2 ];then
  echo """
  -------ERROR-------
  コンテストレベルもしくは番号が正しく入力されていません
  AtCoder ABC 第190回コンテストなら
  sh coppy.sh abc 190
  と入力してください
  """
  exit
fi

# 現在のパスを取得 
path=$(cd $(dirname $0); pwd)

# コンテストレベル
contestLevel="$1"

# コンテスト番号
contestNumber="$2"

# コピー 上書き時警告表示
if [ -e ${path}"/"${contestLevel}"/"${contestNumber} ];then
  echo "同じ名前のファイルが以下のパスで見つかりました"
  echo ${path}"/"${contestLevel}"/"${contestNumber}
  read -p "上書きしますか？ (y/N): " yn
  case "$yn" in
    [yY]*) rm -rf ${path}"/"${contestLevel}"/"${contestNumber}
              cp -r coppy ${contestNumber}
              mv ${contestNumber} ${contestLevel}
              echo "完了しました";;
    *) echo "キャンセルしました";;
  esac
else
  cp -r -i coppy ${contestNumber}
  mv ${contestNumber} ${contestLevel}
  echo "完了しました"
fi
```

もし間違ったパスを指定した場合

```
同じ名前のフォルダが以下のパスで見つかりました
/<path>/atcoder/abc/191
上書きしますか？ (y/N): y
完了しました
```

##エイリアス設定
rn a でテスト実行するために

MacOS zsh環境なら

```
$ vim ~/.zshrc
または
$ open ~/.zshrc

vimの操作方法
1, i を押す（編集モード）
2, alias rn='sh script.sh' 　←を記入
3, escapeボタンを押す
4, :wq の順に押してEnter

#更新
$ source ~/.zshrc 
```


##環境設定完了

###コンテスト前のファイル作成

```
$ cd /<path>/atcoder/

#第191回abcコンテストのファイルを作成
$ sh coppy.sh abc 191 
```


###コンテスト中のテスト実行
実際にコンテスト中に使用したい場合は，AtCoderにログインする必要がある。
（コンテスト開始直前でよい）

```
$ oj login https://atcoder.jp/
AtCoderユーザー名：
パスワード：
```

第190回abcコンテストなら

```
$ cd /<path>/atcoder/abc/190

#A問題なら
$ rn a

#B問題なら
$ rn b
...

```

[github](https://github.com/akidon0000/AtCoder)にコードがあるので参考にどうぞ