Microsoft Bot Framework v3.0 からはじめる BOT 開発: 〇ブウェイがBOTで注文を受付したら - FormFlow(1)

# FormFlow を使った、定型リスト質問を行う BOT 動作の開発
今回は、選択肢による質問(複数)を行う定型でプロセスを FormFlow クラスを利用して作成します。これを利用することで、例えばファーストフードや宅配ピザの注文のように、いくつかの定型質問を元に注文を受け付けるようなフローが Bot Framework だけで作成できます。
ということで、タイトル通り「〇ブウェイがBOTで注文を受付したら」という趣旨で単純なサンドイッチ注文 BOT を作成していきます。

##Visual Studio テンプレートから新規 BOT アプリケーションの作成～下準備
[Bot Framework を使うための開発環境](http://qiita.com/annie/items/edc26c0ee9603e84a2e4#bot-framework-%E3%82%92%E4%BD%BF%E3%81%86%E3%81%9F%E3%82%81%E3%81%AE%E9%96%8B%E7%99%BA%E7%92%B0%E5%A2%83) を参考に開発環境を作成し、[Visual Studio テンプレートから Bot アプリケーションの作成](http://qiita.com/annie/items/edc26c0ee9603e84a2e4#visual-studio-%E3%83%86%E3%83%B3%E3%83%97%E3%83%AC%E3%83%BC%E3%83%88%E3%81%8B%E3%82%89-bot-%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E4%BD%9C%E6%88%90) と同じプロセスで新規アプリケーションを作成します。今回は SandwichBot という名称で作成しています。
![Visual Studio テンプレートから Bot アプリケーションの作成](https://msdnshared.blob.core.windows.net/media/2016/08/bluesky_20160810_01-e1470741795353.png)

テンプレートから作成される *MessageController.cs* (Controllerフォルダ下にあります) を編集していきます。
今回は、メッセージの送受信を行う Microsoft.Bot.Builder.Dialogs に加えて Bot.Builder.FormFlow への参照を追加します。また、System.Collections.Generic も合わせて追加しておきます。
![MessageController の編集](https://msdnshared.blob.core.windows.net/media/2016/08/bluesky_20160810_02-e1470741864593.png)

```csharp:MessageController.cs
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.Bot.Builder.FormFlow;
using System.Collections.Generic;
```


##質問項目の設定
テンプレートにデフォルトで作成されている MessageController クラス内に、まずは質問項目とその回答リストを enum (列挙型) で定義します。今回はサンドイッチを作成するのに必要な ①SandwichOptions(サンドイッチの種類)、②LengthOptions(サイズ)、③BreadOptions(パンの種類)、④ToppingsOptions(トッピング)、⑤VegetableLessOption(減らす野菜)、⑥VegetableMoreOptions(増やす野菜)、⑦SauseOptions(ソース) を作成しました。

```csharp:MessageController.cs
[BotAuthentication]
    public class MessagesController : ApiController
    {
        :
        //質問項目と回答
        public enum SandwichOptions
        { 
            RoastBeef, BLT, SubwayClub, RoastChicken,
            TeriyakiChicken, TurkeyBreast, Ham, Tuna, VeggieDelite
        }
        public enum LengthOptions
        { 
            Regular, Footlong
        }
        public enum BreadOptions
        {
            Flatbread, White, Wheat, Sesame, HoneyOats
        }
        public enum ToppingsOptions
        {
            SliceCheese, CreamCheese, Bacon, Tuna, Avocado, Jalapeno, None
        }
        public enum VegetableLessOptions
        {
            All, Lettuce, Tomato, Pement, Onion, Pickles, Olives, None
        }
        public enum VegetableMoreOptions
        {
            All, Lettuce, Tomato, Pement, Onion, Pickles, Olives, None
        }
        public enum SauseOptions
        {
            Caesar, HoneyMustard,  WasabiSoy, Basil, Balsamico, Mayonnaise, OilVinegar
        }

```

##質問フォームの作成と呼び出し
"Form Definition" (フォーム定義の)インターフェース を SandwichOrder という名称で作成し、上で作成した質問項目を追加します。回答リストから1つだけ選択させたい場合はそのまま、複数選択可能な場合は System.Collections.Generic.List<>を使用します。
続けて SandwichOrder クラスに Microsoft.Bot.Builder.FormFlow.IForm を追加、FormBuilder でこれらの項目を呼び出して質問を行うフォームを構成します。FormBuilder.Message で初期メッセージを設定しています。

```csharp:MessageController.cs
[BotAuthentication]
public class MessagesController : ApiController
{
    :
    [Serializable]
    public class SandwichOrder
    {
        public SandwichOptions? 種類;
        public LengthOptions? サイズ;
        public BreadOptions? パンの種類;
        public List<ToppingsOptions> オプション追加;
        public List<VegetableLessOptions> 抜きたい野菜;
        public List<VegetableMoreOptions> 増やしたい野菜;
        public List<SauseOptions> ソース;

        public static IForm<SandwichOrder> BuildForm()
        {
            return new FormBuilder<SandwichOrder>()
                .Message("こんにちは! 野菜の○ブウェイです。ご注文をどうぞ!")
                .Build();
        }
    }
```

Microsoft.Bot.Builder.Dialogs.IDialog で "Chainable"(鎖のようにつながった) インターフェースを作成します。

```csharp:MessageController.cs
[BotAuthentication]
public class MessagesController : ApiController
{
    :
    internal static IDialog<SandwichOrder> MakeRootDialog()
    {
        return Chain.From(() =>         
            FormDialog.FromForm(SandwichOrder.BuildForm));
    }
```

あとは、何かメッセージを受信したら、この MakeRootDialog を呼び出すように設定すれば完成です。ひとまずテンプレートの Post の部分を以下のように修整すればOKです。
>メッセージの送受信については [コミュニケーションの基本クラス - Dialog(1)](http://qiita.com/annie/items/bd4248bb07eafcf83a3a) をご確認ください。


```csharp:MessageController.cs
public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
        {
            if (activity.Type == ActivityTypes.Message)
            {
                await Conversation.SendAsync(activity, MakeRootDialog);
            }
            else
            :
```

##Emulator による動作確認
ここまでの内容で動作を確認します。[Botアプリケーションのローカル実行とエミュレーターによるアクセス](http://qiita.com/annie/items/edc26c0ee9603e84a2e4#bot%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E3%83%AD%E3%83%BC%E3%82%AB%E3%83%AB%E5%AE%9F%E8%A1%8C%E3%81%A8%E3%82%A8%E3%83%9F%E3%83%A5%E3%83%AC%E3%83%BC%E3%82%BF%E3%83%BC%E3%81%AB%E3%82%88%E3%82%8B%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9) と同様に Visual Studio から F5 でビルド＆デバック実行を開始し、Bot Framework Channel Emulator からメッセージを送信します。
作成した7つの質問項目とリストが表示され、各項目を入力していくと、最後に確認メッセージが表示されるのを確認してください。
![Bot Framework Channel Emulator による定型リスト質問](https://msdnshared.blob.core.windows.net/media/2016/08/bluesky_20160810_03-e1470741887785.png)