AtCoderのワークフローをVSCode内で自動化する

# 0. はじめに

こんにちは。
本稿では競技プログラミングサイトAtCoderを使っている人・始める人に向けて、ファイル作成から提出までの作業の一連を効率良く行うための方法を説明します。VSCode内からキーボードを叩けば面倒な作業を全て行えるようにするため、サンプルやソースコードをコピペする手間を省くことができます。
特にコンテストで早解きが重要になるため環境構築は大切ですが、どうしても時間がかかってしまいます。そのため、本稿ではatcoder-cliとonline-judge-toolsの導入、VSCode側の設定と手順を２つに分けてできるだけシンプルに説明しています。また、言語特定の設定などの具体的な内容は省略しています。

**対象環境**

- OS: Windowsの場合はWSL環境、Linux。Macの場合の手順もほとんど一緒です。
- pip, npmが使える環境
- VSCodeが使える環境

![atcoder-environment-usage.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/334026/7d7bc696-f0c4-5302-b681-56082a208560.gif)

## 0.1 注意事項
本稿ではいくつかのツールを紹介しますが、これらはAtCoderのウェブサイトをスクレイピングしているため、常に動作することが保証できるわけではありません。オープンソースですので、不具合があればを管理者に報告してください。

# 1. atcoder-cli, online-judge-tools導入

AtCoderからの問題・サンプルケースのダウンロード・テスト・提出を行うためのライブラリです。

## 1.1 インストール

PipとNode.jsを使ってダウロードします。

```bash
pip install online-judge-tools
npm -g install atcoder-cli
```

詳細：https://qiita.com/Adaachill/items/3d4ddad56c5c2cc372cd

インストール確認：

```bash
acc -v
oj --version
```

## 1.2 ログイン
コンテストのリアルタイムへの参加や、ローカル環境からの問題の提出する場合は、ログインする必要があります。

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

## 1.3 テンプレートファイルの作成

テンプレートファイルを作成することで、提出するファイルをゼロから作る手間が省けます。

```
cd $(acc config-dir)
mkdir ＜テンプレートの名前＞
cd ＜テンプレートの名前＞
vim template.json 
vim ＜テンプレートファイルの名前＞
```

以下、テンプレートファイルの名前を`main.cpp`と仮定して説明します。

`template.json`の例：

```template.json
{
    "task": {
        "program": ["main.cpp"],
        "submit": "main.cpp"
    }
}
```

programとsubmitのフィールドは必須で、前者はテンプレートファイルへのパス、後者は提出時に自動で提出されるファイルの名前です。

テンプレートファイルの例：

```main.cpp
#include <iostream>

using namespace std;

int main() {

}
```

詳細：https://github.com/Tatamo/atcoder-cli#create-a-new-template
## 1.4 問題・テストケースのダウンロード

abc101の問題を使う場合：

```
acc new abc101
```

表示されるメニューに従い、問題を選ぶと次のようなファイル構造でデータがダウンロードされます。

```
abc101
+-- a
|   +-- tests
|   +-- main.cpp
+-- b
|   +-- tests
|   +-- main.cpp
.
.
.
+-- contest.acc.json
```

## 1.5 テスト

プログラムを書いてコンパイルしたら、サンプルケースに対してテストを行えます。

```
oj test -c ./a.out -d ./tests
```

`./a.out`をプログラムを実行するコマンドと置き換えてください。

## 1.6 提出

```
acc submit
```

実際に提出したくない場合は、途中で聞かれるのでキャンセルすることができます。

# 2. VSCode側の設定

atcoder-cliとonline-judge-toolsが導入できたら、一連の作業をVSCode内から行うための設定をします！

VSCodeのダウンロードや、各言語環境の詳しい設定などは省いています。

例【WSLとC++】：https://qiita.com/2019Shun/items/5ab290a4117a00e373b6

## 2.1 コンパイラ・デバッガの設定

場合によっては、`launch.json`や`tasks.json`においてコンパイラ・デバッガの設定が必要です。
また、コンパイル・デバッグ用のコマンドは、使いやすいキーボードショートカットを適用しておきます。

## 2.2 Command Runnerの設定

VSCode内からシェルコマンドを実行できるようにしたいので、拡張機能をインストールします。もちろんこの拡張機能でなくても、同じようなことができれば大丈夫です。
https://marketplace.visualstudio.com/items?itemName=edonet.vscode-command-runner

`settings.json`を編集して、必要なコマンドを追加します。
`settings.json`の開き方：https://qiita.com/y-w/items/614843b259c04bb91495

`settings.json`の例：

```settings.json
{
    "command-runner.commands": {
        "oj test": "oj test -c ${fileDirname}/a.out -d ${fileDirname}/tests",
        "acc submit": "cd ${fileDirname} && acc submit ${file} || cd ../../",
        "echo": "echo 'this is a test command: ${file}'"
    }
}
```

C++を使っていない場合、または出力先が`a.out`ではない場合などは、`${fileDirname}/a.out`の部分を、プログラムを実行するコマンドと置き換えてください。

## 2.3 Command Runnerのキーボードショートカットの作成

また、キーボードショートカットを作成する必要があるので、`keybindings.json`を編集します。
`keybindings.json`のの開き方：https://qiita.com/TakahiRoyte/items/cdab6fca64da386a690b#%E3%82%AD%E3%83%BC%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%9E%E3%82%A4%E3%82%BA

何回も使うショートカットなので、使いやすいものを選んでください。

`keybindings.json`の例：

```keybindings.json
// Place your key bindings in this file to override the defaults
[
  {
    "key": "ctrl+meta+l",
    "command": "command-runner.run",
    "args": {
      "command": "oj test"
    }
  },
  {
    "key": "ctrl+meta+;",
    "command": "command-runner.run",
    "args": {
      "command": "acc submit"
    }
  }
]
```

# 3. 実際に試してみる

設定が完了したら実際に動作確認をしましょう。

1)ターミナルからacc newで問題・サンプルケースをダウンロード **【1.4】**
2) VSCode内でmain.cppを開き、編集開始
3) VSCode内からコンパイルする **【2.1】**
4) VSCode内からテストを走らせる **【2.3】**
5) 必要な場合VSCode内からデバッグする **【2.1】**
6) VSCode内から提出する **【2.3】**

# 4. 最後に

読んでいただきありがとうございました。もし記事に間違いを発見されましたら、[@ntszw](https://twitter.com/ntszw)までご一報ください。競プロライフを楽しみましょう！