C#で競技プログラミング(AtCoder)用のライブラリを作ろう！

# 目的

競技プログラミングに慣れてくると、入出力の処理や頻出のアルゴリズムをいちいち打つのが面倒になり、関数にまとめてライブラリ化したいと思うようになります。
この記事では、C# のカスタムテンプレートというものを使って、AtCoder で使えるライブラリを作っていきます。

**追記: もっと簡単に、既存のプロジェクトを問題分だけコピーするツールを作りました!!**
[MakeAC](https://github.com/kazurego7/MakeAC)

# こんなことができます!

```
$ dotnet new actemp -o A
```

こんなコマンド一つで、
![CanIt_newA1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250243/5d0bbed6-2ce1-7c86-94af-8093ff8fe173.png)
![CanIt_newA2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250243/2281a94f-b62e-a89d-7a8b-e6c513624021.png)

**問題一問分のプロジェクト（ソースファイルなどが含まれた作業用のフォルダ）が生成されます！**

もちろんソースファイルには、自分で作ったライブラリを含めることができます。
![CanIt_Library.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250243/f1362274-1632-749e-697e-de1382051be5.png)

また、自分で作ったシェルスクリプトを使って

```
$ mkac 142
```

のようにコマンドを打つと、
![CanIt_newA-F1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250243/fffc745f-c354-acb1-fab2-e89639ccd3e7.png)
![CanIt_newA-F2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250243/4dbddc20-e914-7976-b520-930c87eecef9.png)

**コンテストのフォルダと、その中に問題 A~F のプロジェクトを一気に生成する、ということもできるようになります！**



# 前提知識

- パスやフォルダ(ディレクトリ)階層についての知識(カレントディレクトリ、相対パスなどがわかるか)
- cd, ls などの簡単なコマンド操作( cd コマンドでフォルダ階層を移動し、 ls コマンドでディレクトリの内容を確認できるか)

PC 初心者の内 Windows を使っている方は、パスの概念やコマンド操作に触れる機会が無く、知らないという人も多いかもしれません。
コマンド操作を知っておくと、いろいろな場面で「[こんなことができます!](# こんなことができます!)」のような自動化ができて非常に便利です。

[絶対パスと相対パス](http://www14.plala.or.jp/campus-note/vine_linux/others/path.html)
[Windows のコマンド操作](https://kenjisato.github.io/pynote/arrangement/cui_win.html)

# 方法

1. dotnet CLI をインストールする

2. カスタムテンプレートにしたい元のプロジェクトを作る

3. カスタムテンプレートの構成ファイル(*template.json*)を作る

4. dotnet CLI に、作ったカスタムテンプレートをインストールする

5. 自作のカスタムテンプレートを使ってプロジェクトを作ってみる

*※注意*（**わからない人は飛ばしてOK**）
AtCoder の[ルール](https://atcoder.jp/contests/abc138/rules)では実行環境が C# (Mono 4.6.2.0) ですが、 Mono プロジェクト を dotnet CLI で扱う方法がわかりませんでした……
気になる方は Windows ならば、 Mono は .NET Framework と互換性があるので、 .NET Framework プロジェクトで問題ないと思います。
Linux ならば、Mono と互換性のない .NET Core プロジェクトになります。(おそらく問題ないと思うのですが、そこら辺の知識が乏しいのでわかりません……)
いろいろ調べたのですがめんどくさくなったので、今回は既存のコンソールアプリケーションのテンプレートを使った .NET Core 2.2 のプロジェクトを元に作ることにします。

## 1. dotnet CLI をインストールする

dotnet CLI は、アプリケーションを作るために必要な、プロジェクトの作成・ビルド・実行・テストなどの操作を、コマンドライン上で行うことができるツールです。

開発環境に VisualStudio を使っている方には、あまり馴染みがないかもしれません。

**dotnet CLI は .NET Core SDK に含まれているため、公式で最新の .Net Core SDK をインストールします。
現在の最新バージョンは、 .NET Core 2.2 です。**
[Download .NET](https://dotnet.microsoft.com/download)

*以下は、dotnet CLI について詳しく知りたい人だけ読んでください*

dotnet CLI についての具体的な使い方は、以下の記事がわかりやすいです。
[コマンドラインでC#プログラミング](https://qiita.com/shuhey/items/b4211f196259156df8f4)
また、より詳しいコマンドの説明は、公式のドキュメントを確認してください。
[.NET Core コマンドライン インターフェイス (CLI) ツール](https://docs.microsoft.com/ja-jp/dotnet/core/tools/?tabs=netcore2x)

## 2. カスタムテンプレートにしたい元のプロジェクトを作る

カスタムテンプレートの目的は、あるプロジェクト（ソースファイルなどが含まれた作業用のフォルダ）を雛形として中身が同じ別のプロジェクトを作る、ことです。
雛形となるプロジェクトにカスタムテンプレート用の構成ファイルを含めたものが、カスタムテンプレートとなります。

**まずは、カスタムテンプレートの元となる AtCoderTemplate プロジェクトを作っていきます。
dotnet CLI の dotnet new コマンドで、既存のカスタムテンプレートからプロジェクトを作ることができます。**

```
$ dotnet new console -o AtCoderTemplate
```

ls コマンドで確認してみると

```
$ ls AtCoderTemplate
```

**AtCoderTemplate プロジェクト(フォルダ)が存在し、その中に AtCoderTemplate.csproj ファイルや、 Program.cs ファイル、 bin フォルダ、 obj フォルダが確認できます。**
フォルダ階層は、以下のようになっています。

```
―― AtCoderTemplate
      | AtCoderTemplate.csproj
      | Program.cs
      | bin
      | obj
```

この内、 Program.cs ファイルに Main 関数を含む Program クラスがあります。

さて、 AtCoder に提出するコードでは外部のライブラリを呼ぶことができないため、自作ライブラリのクラスと Main 関数を持つ Program クラスを一つのファイルにまとめないといけません。

**具体的には、以下のように1つの Program.cs ファイルの中に、Program クラスと MyLibrary クラスを置き、 MyLibrary クラスに自作の関数を追加していく形になります。**

```csharp:Program.cs
using System;
using static AtCoderTemplate.MyLibrary;

namespace AtCoderTemplate {
    class Program {
        static void Main (string[] args) {
            // 問題のコードをここに書く
        }
    }

    class MyLibrary {

        // 自作の関数
        public static int MyFunction (int n) {
            // 便利な処理
            // ~~~~~~~~
            // ~~~~~~~~
        }

        // 自作のすごい関数
        public static long MySuperAlgorithm (long m) {
            // ちょーすごいアルゴリズム
            // ~~~~~~~~
            // ~~~~~~~~
        }
    }
}
```

## 3. カスタムテンプレートの構成ファイル(*template.json*)を作る

構成ファイル(*template.json*)は、カスタムテンプレートの名前や種類などの情報を含むファイルです。

**[2. カスタムテンプレートにしたい元のプロジェクトを作る](# 2. カスタムテンプレートにしたい元のプロジェクトを作る) で作った AtCoderTemplate プロジェクト(フォルダ)の中に .tmeplate.config フォルダを作成し、さらに .template.config フォルダの中に、空の template.json ファイルを作成します。**
フォルダ階層は以下のようになります。

```
―― AtCoderTemplate
    | AtCoderTemplate.csproj
    | Program.cs
    | bin
    | obj
    └──.template.config
         | template.json
```

**次に、 template.json ファイルを開き、以下のように書き込みます。**

``` json:template.json
{
    "$schema": "http://json.schemastore.org/template",
    "author": "hogehoge",
    "classifications": [
        "Common",
        "Console"
    ],
    "identity": "AtCoderLibrary.Template.CSharp",
    "name": "AtCoderLibraryTemplate",
    "shortName": "actemp",
    "sources": [
        {
            "source": "./",
            "target": "./",
            "exclude": [
                "**/[Bb]in/**",
                "**/[Oo]bj/**"
            ]
        }
    ],
    "symbols": {
        "skipRestore": {
            "type": "parameter",
            "datatype": "bool",
            "description": "If specified, skips the automatic restore of the project on create.",
            "defaultValue": "false"
        }
    },
    "postActions": [
        {
            "condition": "(!skipRestore)",
            "description": "Restore NuGet packages required by this project.",
            "manualInstructions": [
                {
                    "text": "Run 'dotnet restore'"
                }
            ],
            "actionId": "210D431B-A78B-4D2F-B762-4ED3E3EA9025",
            "continueOnError": true
        }
    ],
    "primaryOutputs": [
        {
            "path": "AtCoderTemplate.csproj"
        }
    ]
}
```

今回、template.json の内容については説明しません。
**ただし、この template.json で、 カスタムテンプレートの名前を AtCoderLibraryTemplate と設定したことだけ、覚えておいてください。**

*以下は template.json の内容について、詳しく知りたい人だけ読んでください。*

template.json の詳細については公式のドキュメントを確認してください。
[dotnet new のカスタム テンプレート](https://docs.microsoft.com/ja-jp/dotnet/core/tools/custom-templates)
また、 "symbols", "postActions", "primaryOutputs" の設定については、以下の記事を確認してください。
[プロジェクト作成時に依存関係を復元(dotnet restore)させる](https://qiita.com/watertight/items/4680b52728e24deca004)

## 4. dotnet CLI に、作ったカスタムテンプレートをインストールする

**AtCoderTemplate プロジェクトを AtCoderLibraryTemplate という名前のカスタムテンプレートとして、 dotnet CLI にインストールします。** (template.json に記載されている)

```
$ dotnet new -i AtCoderTemplate
```

インストールが成功した場合、以下の画像のように表示されます。
![dotnetNewOK.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250243/85dfb6cb-b58f-d521-eeb3-4e59c950ab79.png)
少し、拡大してみます。
![dotnetNewOK2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250243/68637fbe-d7d4-5613-7f1b-fad94763b397.png)

**図のように、 AtCoderLibraryTemplate という名前が表示されていれば、インストールが成功しています。**

Linuxの方で Permission denied というエラーが出てしまう場合は、以下のようにroot権限でコマンドを実行してみてください。

```
$ sudo dotnet new -i AtCoderTemplate
```


お疲れ様でした。
これで、カスタムテンプレートのインストールは完了です。
**これ以降は、AtCoderTemplate プロジェクトの中身(例えばProgram.cs ファイル)を変更すると、インストールしたカスタムテンプレートである AtCoderLibraryTemplate に反映されるようになります。**

## 5. 自作のカスタムテンプレートを使ってプロジェクトを作ってみる

さあ、 dotnet new コマンドで、カスタムテンプレート AtCoderLibraryTemplate からコンテスト用のプロジェクトを作ってみましょう！

まずは、 コンテスト用のフォルダを作ります。今回は例として ABC141 を作ります。

```
$ mkdir ABC141
$ cd ABC141
```

ABC141 フォルダを生成して、移動することができました。

**dotnet new コマンドを使ってA問題のプロジェクトを作成しましょう。**

```
$ dotnet new AtCoderLibraryTemplate -o A
```

もしくは、 AtCoderLibraryTemplate の省略名である actemp を使って、

```
$ dotnet new actemp -o A
```

このようにコマンドを打ちます。

-o は、生成されるプロジェクトフォルダの場所や名前を決めるオプションです。

**「テンプレート "AtCoderLibraryTemplate" が正常に作成されました。」と表示されれば、成功です！**

# さらに自動化

dotnet CLI はコマンドラインインターフェースのため、シェルスクリプトからの操作も可能です。

Windowsならば bat ファイル (または PowerShell スクリプト)を使い、Linux ならば bash スクリプトを使って、「[こんなことができます!](# こんなことができます!)」のように、一回のコマンドでコンテスト用のプロジェクトを一気に生成することができます。

bat ファイル (mkac.bat)・ bash スクリプト(mkac) どちらも私の GitHub リポジトリにあるので、よろしければご利用ください。
また、私の拙いライブラリもありますので、よろしければそちらもご利用ください。
[kazurego7/AtCoderTools](https://github.com/kazurego7/AtCoderTools)

ふぅー、つかれた〜
早く水色になりたいなー