AtCoder環境をDockerで作ってみた

## はじめに
自分なりには環境を整えているつもりですが、プロの方からしたらまだまだ使いづらく感じると思います。そのような点ありましたらご指摘お願いします。

https://github.com/kurimochi/atcoder_on_docker

## なぜDocker?
「Dockerじゃなくてもいいのでは?」という意見の方も多いと思います。しかし、Dockerを使うことで様々な恩恵を受けることができます。例えば、以下のようなメリットがあります。
- 別のPCでAtCoderをやるときも環境を楽に作り、楽に消すことができる 
- -> **移植性が高い**
- **ホスト環境を一切汚さない**

## 準備
まず、[リポジトリ](https://github.com/kurimochi/atcoder_on_docker)を任意のディレクトリにクローンします。
```shell_session
$ git clone https://github.com/kurimochi/atcoder_on_docker
```
次に、コンテナ内でAtCoderにログインするための作業を実施します。今回使う`online-judge-tools`と`atcoder-cli`自体にもログイン機能が備わっているのですが、AtCoder側の仕様変更によりそれが使えなくなってしまいました。これらのツールにはcookieを保存する場所があるので、今回はログイン済みのセッションクッキーをコピーする形をとります。

ホスト側のWebブラウザでAtCoderにログインします。その後、F12キーでDevToolsを開き、`Application -> Cookies -> https://atcoder.jp`と進み`REVEL_SESSION`という名前のクッキーの`Value`をコピーしてください。そして、`.devcontainer/src/cookie-template.jar`を`.devcontainer/src/cookie.jar`に、`.devcontainer/src/session-template.json`を`.devcontainer/secrets/session.json`にコピーし、`{Insert the copied value}`という部分を先ほどの値に置き換えます。
```shell_session
$ cp .devcontainer/src/cookie-template.jar .devcontainer/secrets/cookie.jar
$ cp .devcontainer/src/session-template.json .devcontainer/secrets/session.json
```
最後に、`.devcontainer`ディレクトリに移動しコンテナを作成します。
```shell-session
$ cd .devcontainer
$ docker compose up -d --build
```
私の環境ではイメージの作成だけでも3分強かかりました。また、このイメージは最終的に3GBを超えるほどの大きさになるのでそれなりのディスクスペースも必要です。

## 使い方
もしコンテナを終了させていたら、再度起動してください。
```shell_session
$ docker compose up -d
```
VSCodeで`Dev Containers`拡張機能をインストールし、リモートタブで`atcoder`コンテナにアタッチします。

### テストデータのダウンロード
以下では、実際に問題を解く手順を説明します。
まず、`contest/` にアクセスし、問題のテストデータをダウンロードします。例えば、`abc001`という問題は以下のようにダウンロードできます。ユーザ名とパスワードの入力を求められることがありますが、空欄のままで構いません。
```shell_session
$ acc new abc001
```
`--template python`オプションを付けることで、Pythonで解答することができます。
```shell_session
$ acc new abc001 --template python
```
詳しくは、[`atcoder-cli`のリポジトリ](https://github.com/Tatamo/atcoder-cli)かヘルプ(`-h`)をご覧ください。

### 解答
`contest/`配下にコンテストのディレクトリがあり、その配下には各問題のディレクトリがあります。VSCodeで解きたい問題のディレクトリにある`main.*`を編集してください。

### テスト
本来ならもっと長いコマンドを入力するのですが、エイリアスをあらかじめ設定しておいたのでその必要はありません。それぞれ以下のコマンドでテストを実行できます。

C++: `cpptest`
Python3(PyPy): `pypytest`
Python3(CPython): `py3test`

### 提出
テストが成功したら、AtCoderに提出しましょう。なお、ここでも以下のようにエイリアスを設定しています。

C++: `cppsb`  
Python3(PyPy): `pypysb`  
Python3(CPython): `py3sb`

提出前に確認として文字列の入力を求められるので、それに従って提出してください。結果はAtCoderのWebページで見ることができます。

## カスタマイズ
リポジトリの構成は以下のようになっており、`*`はそのファイル/ディレクトリがカスタマイズできることを意味します。
```
.
│  .gitignore
│  README.md
│
├─.devcontainer/
│  │  devcontainer.json         *
│  │  docker-compose.yml        *
│  │  Dockerfile                *
│  │
│  └─src
│      │  .bashrc               *
│      │  cookie-template.jar
│      │  requirements.txt      *
│      │  template.json
│      │
│      └─templates              *
│          ├─cpp
│          │      main.cpp
│          │      template.json
│          │
│          └─python
│                  main.py
│                  template.json
│
├─.vscode
│      c_cpp_properties.json
│
└─contest
    └─...
```
以下のセクションでは、各ファイル/ディレクトリのカスタマイズ方法について説明します。

### .devcontainer/devcontainer.json
`devcontainer.json`はVSCodeが使用する設定ファイルです。ここでカスタマイズできるのは `{.customizations.vscode}`で、`extensions`にはプリインストールされる拡張機能を、`settings`には標準の設定を指定することができます。

### .devcontainer/docker-compose.yml
`docker-compose.yml` はコンテナ設定ファイルです。`.service.atcoder.container_name`でコンテナ名を変更できます。

### .devcontainer/Dockerfile
`Dockerfile`はコンテナイメージの設計書です。ここでカスタマイズできるのは5行目の`apt install`コマンドで、インストールするパッケージをカスタマイズできます。例えば、この環境に`Ruby`をインストールしたいなら、`apt install -y`の後に `ruby`を追加します。初心者にはあまりお勧めできませんが、独自のコマンドを追加することも可能です。

### .devcontainer/src/.bashrc
`.bashrc`にはエイリアスが設定されています。新しい言語を追加したり、別のコマンドのエイリアスを設定したい場合は、ここに追加することができます。

### .devcontainer/src/requirements.txt
`requirements.txt`では、pipでインストールするライブラリをカスタマイズできます。例えば`numpy`をインストールしたい場合は、`requirements.txt`に`numpy`を追加します。

### .devcontainer/src/templates/
このディレクトリには`atcoder-cli`でテストデータのディレクトリを作成するためのテンプレートが設定されています。テンプレートは`main.*`で自由に変更することができます。
テンプレートを追加するには、`templates`の下にディレクトリを作成し(ディレクトリ名はテンプレート名にする)、使用する言語のコードテンプレートを書きます。次に、`src/template.json`をそのディレクトリにコピーし、`{Insert file name}`を作成したコードのファイル名に置き換えます。
デフォルトのテンプレートを変更するには、以下のコマンドを実行します。`{Insert template name}`をテンプレートの名前に置き換えてください。
```shell_session
$ acc config default-template {Insert template name}
```

## 参考にした記事
https://qiita.com/gomatofu/items/1adae9b7cd79b0f8044f

https://miiitomi.github.io/p/kyopro-env/

https://qiita.com/sorachandu/items/a06e4ed61d169ba067f3