【IBM Watson Assistant】で素因数分解ゲームを作る

チャットボットに簡単なゲーム機能を実装します。

IBM Watson Assistantは、APIを呼び出すことができます。
今回はこの機能を使って、IBM Cloud FunctionsからAPIを呼び出す形で実装します。

できあがるもの
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1865650/42e682d8-cdfd-a972-62b6-8d83b6bfc34d.png)

###参考
IBM Watson AssistantでIBM Cloud Functionsを実行する方法については、
こちらの記事でとても丁寧に解説してくれているので、参考にしてください。
[Watson AssistantからIBM Cloud Functionsを呼び出す](https://qiita.com/makaishi2/items/349d366e550b37cf4521)

###Skillデータ
[GitHub](https://github.com/AmanatsuTouko/CompositeNumberQuiz-IBMWatsonAssistant)にSkillデータを置いておきます。

#1.Functionを作る
今回、IBM Cloud Functionで作るAPIは2つです。

1-1.合成数を生成するAPI
1-2.約数を受け取り、合成数を割った数を返すAPI

今回はPythonでそれぞれ作成します。

####1-1.合成数を生成するAPI
```InitializeCompositeNumber.py
import sys
import random

def main(dict):
    #約数の数
    divisor = 4
    #素数リスト
    Prime = [2,3,5,7,11,13,17]
    
    #合成数
    CompositeNumber = 1
    for i in range(divisor):
        CompositeNumber *= Prime[random.randint(0,len(Prime)-1)]
    
    return { 'CompositeNumber': CompositeNumber }
```

####1-2.約数を受け取り、合成数を割った数を返すAPI
```DivideCompositeNumber.py
import sys

def main(dict):
    """
    返り値
    CompositeNumber:CompositeNumber/=InputNumber 通常
    error:0 通常時
    error:1 終了時
    error:2 割り切れないとき(失敗)
    エラー時
    CompositeNumber:CompositeNumber そのまま返す
    error:3 入力が数字以外の時
    error:4 入力値が合成数よりも大きいとき
    error:5 入力値が素数でないとき
    """
    
    #素数かどうか判定する関数
    def isPrime(input):
        Prime = False
        
        if input == 1:
            Prime = False
            return Prime
        elif input == 2:
            Prime = True
            return Prime
        elif input%2 == 0:
            Prime = False
            return Prime
        else:
            i = 3
            while True:
                if input == i:
                    Prime = True
                    break
                elif input%i == 0:
                    break
                i+=2
            return Prime
    
    #エラー変数
    error = 0
    
    #合成数の読み込み
    CompositeNumber = dict['CompositeNumber']
    InputNumber = dict['InputNumber']
    
    #入力が数字以外の文字の時はエラー3を返す
    if InputNumber.isdigit() == False:
        error = 3
        return {'CompositeNumber': CompositeNumber, 'InputNumber': InputNumber, 'Error': error}
    
    #整数への変換
    CompositeNumber = int(CompositeNumber)
    InputNumber = int(InputNumber)
    
    #error:4 入力値が合成数よりも大きいとき
    if InputNumber > CompositeNumber:
        error = 4
        return {'CompositeNumber': CompositeNumber, 'InputNumber': InputNumber, 'Error': error}
    
    #error:5 入力値が素数でないとき
    if isPrime(InputNumber) == False:
        error = 5
        return {'CompositeNumber': CompositeNumber, 'InputNumber': InputNumber, 'Error': error}
    
    #割れるときは割った後の数を返す
    if CompositeNumber%InputNumber == 0:
        CompositeNumber /= InputNumber
        #error:1 終了時
        if isPrime(CompositeNumber) == True:
            error = 1
        return {'CompositeNumber': CompositeNumber, 'InputNumber': InputNumber, 'Error': error}
    #error:2 割り切れないとき(失敗)
    else:
        error = 2
        return {'CompositeNumber': CompositeNumber, 'InputNumber': InputNumber, 'Error': error}
        
    return {'CompositeNumber': CompositeNumber, 'InputNumber': InputNumber, 'Error': error}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1865650/aa4aaa8a-a1ab-e04a-4ebd-6f9cd4a080ac.png)
Webアクションとして有効化に忘れずにチェックを付けておきましょう。


#2.Dialogを作る
IBM Watson Assistantで作るDialogです。全貌です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1865650/311d8420-4167-a23b-7a5d-4150af4538a2.png)

####2-1.ようこそノード
Open JSON editorを開いてcontext変数を追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1865650/033b1685-b0ab-2e15-f26d-b0c56077f819.png)

```welcome.js
"context": {
    "number": {
      "Error": "",
      "InputNumber": "",
      "CompositeNumber": ""
    },
    "private": {
      "my_credentials": {
        "user": "",
        "password": ""
      }
    }
  }
```
userとpasswordはこちらを参考にして書き換えてください。
[Watson AssistantからIBM Cloud Functionsを呼び出す](https://qiita.com/makaishi2/items/349d366e550b37cf4521)


####2-2.request_CompositeNumberノード
前のノードで、ユーザ入力をスキップしているのでこのノードがそのまま実行されるように
If assistant recognizeをtrueにします。同様にOpen JSON editorを開いて書き換えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1865650/0486a7e4-2c2b-b45a-702b-c83a83d499ff.png)

```request_CompositeNumber.js
{
  "output": {},
  "actions": [
    {
      "name": "/<namespace>/InitializeCompositeNumber",
      "type": "server",
      "parameters": {},
      "credentials": "$private.my_credentials",
      "result_variable": "context.number"
    }
  ]
}
```
"namespace"は書き換えてください。


####2-3.display_nodeノード
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1865650/2a510db5-b810-06c8-0146-5244d50c8ce9.png)
$number.CompositeNumberで変数にアクセスできます。

####2-4.request_DivideCompositeNumberノード
```request_DivideCompositeNumber.js
{
  "output": {},
  "actions": [
    {
      "name": "/<namespace>/DivideCompositeNumber",
      "type": "server",
      "parameters": {
        "InputNumber": "<? input.text ?>",
        "CompositeNumber": "$number.CompositeNumber"
      },
      "credentials": "$private.my_credentials",
      "result_variable": "context.number"
    }
  ]
}
```
"namespace"は書き換えてください。
```<? input.text ?>```とすると、入力されたテキストにアクセスできます。

####2-5.$number.Errorノード
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1865650/d2030ff5-9499-b8c0-8c73-4c4e9b1408d8.png)
条件をそれぞれのErrorに対応させます。
"number.Error==0","number.Error==3"は、display_nodeへJump
それ以外は、ようこそノードへJumpさせます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1865650/7fe2c757-dd67-1af7-2ba1-0459e597b5d5.png)

以上です。
IBM Cloud Functionを用いると、IBM Watson Assistantにゲームを組み込むことができます。
他にも色々応用が利くので、作ってみてください。

#関連リンク
[Watson Assistantを使ってゲームを作る](https://qiita.com/ymunemasa/items/00efccb76613a14f11e2)