10 月 6 日に発売開始された Google Home が届いたので、モジュロ演算をしてくれる Google Assistant に対応したサンプルアプリを作ってみました。

目次

  • モジュロ演算とは?
  • アプリを作る
    • 開発環境
    • Actions on Google コンソールでプロジェクト作成
    • Dialogflow コンソールで Agent を作成
    • Agent の Fulfillment の設定をする
    • Welcome Intent を編集
    • 今回のアプリの会話の本流となる Intent を新規作成する
    • Intent
    • モジュロ演算のスクリプトを作成
    • Dialogflow の Fulfillment を再度設定する
    • Integrations を設定
    • テストする
    • シミュレータで遊ぶ
  • まとめ

モジュロ演算とは?

モジュロ演算とは年月日(西暦)からその日の曜日を算出する演算方法です。
詳しい算出方法は、以下のようになっています。

  1. 年の下2桁の値を A とする
  2. A を 4 で割った商 を B とする
  3. 下の表から月に該当する数字を C とする

    1月 2月 3月 4月 5月 6月 7月 8月 9月 10月 11月 12月
    1 4 4 0 2 5 0 3 6 1 4 6
  4. 日付を D とする

  5. 年の上2桁が 19 なら 0, 20 なら 6 と考え、これを E とする

  6. A ~ E の和を 7 で割った余りを以下の表と照らし合わせて曜日を算出

    1 2 3 4 5 6 0

アプリを作る

さて、モジュロ演算を紹介し終わったところで実際にアプリ作成していきたいと思います。
今回は、 Dialogflow (旧 api.ai) を使った方法です。
また、言語は日本語で作ります。
大まかな流れは、こちらのガイドに載っているので参考にしてみてください。

開発環境

Dialogflow を使った方法では、最後にモジュロ演算をする部分を Node.js を使って javascript で記述します。
なので、あらかじめ Node.js をインストールしておいてください。
今回の開発で使用した Node.js のバージョンは v8.7.0 です。

Actions on Google コンソールでプロジェクト作成

まずは、Actions on Google コンソール にログインしてプロジェクトを作成します。

作成が完了すると以下の画面になります。
この画面の「 Dialogflow 」カードの「 BUILD 」ボタンを押下してください。

「 BUILD 」ボタンを押下すると以下のような Popup が表示されるので、「 CREATE ACTIONS ON DIALOGFLOW 」を押下し、 Dialogflow のコンソールに移動します。

Dialogflow コンソールで Agent を作成

Dialogflow コンソールに移動すると以下のような画面になっています。
Agent とは、 Dialogflow におけるプロジェクトのようなもので、 Actions on Google のプロジェクトと紐づけて使用するものです。
Actions on Google から遷移すると自動で紐づいているので、気にしなくても大丈夫です。
さて、ここで Default Language を「 Japanese – ja 」にして、「 SAVE 」を押下します。
Default Language は、後から変更できない項目なので注意してください。

作成が完了すると以下の画面になります。

Agent の Fulfillment の設定をする

Fulfillment は会話が完了した時の挙動を設定する項目です。
画面左のメニューの「 Fulfillment 」を押下し設定画面に遷移します。

今回は、会話の完了時に Webhook をさせたいので、 Webhook を「 ENABLED 」にし、「 URL 」には適当な URL を入れて、最下部の「 SAVE 」を押下します。
* URL は後で変更します。

Welcome Intent を編集

まずは、 Dialogflow コンソールの左メニューから「 Intents 」を押下し、 Intents 一覧画面に遷移します。
Intents 一覧画面の初期状態は以下のようになっており、「 Default Fallback Intent 」と「 Default Welcome Intent 」の 2 つが作成されています。
それぞれ特殊な Intent のデフォルトなので、削除しないほうがいいです。
  

このうちの「 Default Welcome Intent 」を選択し、アプリ起動時に Google Assistant が発する言葉を定義します。
Intent の編集画面は以下のようになっており、 Response 項目の Text Response に Intent が呼び出された時の言葉入れます。
デフォルトで「こんにちは!」と入力されていますが、これを編集してお好みの言葉を入れて「 SAVE 」を押下してください。
今回は「こんにちは!モジュロ演算をします。あなたの生年月日を西暦で教えてください。」と入力しました。

今回のアプリの会話の本流となる Intent を新規作成する

Dialogflow の左メニューの「 Intents 」項目にある「+」ボタンを押下し、新規に Intent を作成します。

Intent 名に「 calc_mojuro 」と入力する

Action 項目に「 mojuro 」と入力する。
その下の Parameter の項目を以下の表のようにする。

REQUIRED PARAMETER NAME ENTITY VALUE IS LIST PROMPTS
チェック year @sys.number $year アンチェック 未入力

この段階で Action 項目は以下のようになっているはずです。

次に今入力した year パラメータの PROMPT の Define prompts を押下すると以下の Popup が出ますので Popup の PROMPTS にユーザーの言葉が未入力だった時に発する言葉を入れます。
今回は、「生まれた年を西暦で教えてください」と入力します。

そして、 Popup の「 CLOSE 」を押下して Popup を閉じると以下のようになっているはずです。

他にも year と同じように month と date パラメータも用意し、入力を以下のようにします。  

REQUIRED PARAMETER NAME ENTITY VALUE IS LIST PROMPTS
チェック month @sys.number $month アンチェック 生まれた月を教えてください
チェック date @sys.number $date アンチェック 生まれた日を教えてください

ここまでで Action 項目は以下のようになっているはずです。

次に User Says 項目を編集します。
User Says 項目は、ユーザーの言葉の入力例を定義する項目です。
入力欄に「2017年11月5日」と入力します。
入力直後だと全選択されていますが選択範囲を「2017」に絞り、表示された Popup の @sys.number:year を選択。

同じように選択範囲をさらに「11」に追加し @sys.number:month を選択、選択範囲をさらに「5」に追加し @sys.number:date を選択する。
ここまでで User Says の項目は以下のようになっているはずです。

次に Fulfillment 項目と Google Assistant 項目を以下のように入力します。

最後に「 SAVE 」を押下して保存します。

Intent

Intent とは、会話の流れを定義する単位です。
Intent には、特殊なものが以下の 2 種類存在します。

  • Welcome Intent
    • Welcome Intent は、アプリ起動時に最初に呼ばれる Intent です。
  • Fallback Intent
    • Fallback Intent は、言葉を聞き取れなかった時に呼ばれる典型的な Intent です。

モジュロ演算のスクリプトを作成

まず、スクリプト作成用のプロジェクトを作成するため Firebase Tools をインストールします。
以下のコマンドをターミナル等で入力してください。

npm install -g firebase-tools
firebase login
mkdir mojuro_sample
cd mojuro_sample

次に以下のコマンドを入力します。

firebase init

すると、以下の選択項目が表示されるので十字キーで「 Functions 」を選択し「 Enter 」を押下する。

? Which Firebase CLI features do you want to setup for this folder? Press Space to select features, the
n Enter to confirm your choices.
 ◯ Database: Deploy Firebase Realtime Database Rules
 ◯ Firestore: Deploy rules and create indexes for Firestore
❯◯ Functions: Configure and deploy Cloud Functions
 ◯ Hosting: Configure and deploy Firebase Hosting sites
 ◯ Storage: Deploy Cloud Storage security rules

次に表示される選択項目で今回作成した「 MojuroSample 」を十字キーで選択し「 Enter 」を押下する。

? Select a default Firebase project for this directory:
  [don't setup a default project]
❯ MojuroSample (mojurosample)
  [create a new project]

mojuro_sample フォルダ直下で以下のコマンドを実行。

mkdir functions
cd functions
npm init
npm install --save actions-on-google firebase-admin firebase-functions

次に functions フォルダに index.js を作成し、ファイルに以下の内容を書き込む。

'use strict'

process.env.DEBUG = 'actions-on-google:*';
const App = require('actions-on-google').DialogflowApp;
const functions = require('firebase-functions');

const NAME_ACTION = "mojuro";
const YEAR_ARG = "year";
const MONTH_ARG = "month";
const DATE_ARG = "date";
const MONTH_CONVERT_NUMBER = {
    "1": 1,
    "2": 4,
    "3": 4,
    "4": 0,
    "5": 2,
    "6": 5,
    "7": 0,
    "8": 3,
    "9": 6,
    "10": 1,
    "11": 4,
    "12": 6
};
const DAY_OF_WEEK = {
    0: "土",
    1: "日",
    2: "月",
    3: "火",
    4: "水",
    5: "木",
    6: "金",
}

exports.mojuro = functions.https.onRequest((request, response) => {
    const app = new App({ request, response });

    function calcMojuro(app) {
        let year = app.getArgument(YEAR_ARG);
        let month = app.getArgument(MONTH_ARG);
        let date = app.getArgument(DATE_ARG);

        var yearOverHundred = new Number(year.substring(0, 2));

        var yearUnderHundred = new Number(year.substring(2, 4));
        var yearUnderHundredPer4 = Math.floor(yearUnderHundred / 4);
        var monthNumber = MONTH_CONVERT_NUMBER[month];
        var dateNumber = new Number(date);
        var yearConvertNmuber = yearOverHundred == 19 ? 0 : 6

        var calcSum = yearUnderHundred +
            yearUnderHundredPer4 +
            monthNumber +
            dateNumber +
            yearConvertNmuber

        var dayOfWeek = calcSum % 7;
        var dayOfWeekStr = DAY_OF_WEEK[dayOfWeek] + "曜日";

        app.tell("あなたの生まれた" + year + "年" + month + "月" + date + "日は、" + dayOfWeekStr + "でした。");
    }

    let actionMap = new Map();
    actionMap.set(NAME_ACTION, calcMojuro);

    app.handleRequest(actionMap);
});

index.js の編集が完了したら以下のコマンドを実行し Firebase の Function にデプロイする。

firebase deploy --only functions

デプロイが完了するとこのスクリプトを実行するための URL が表示されるのでコピーする。

Function URL (mojuro): <URL が表示される>

Agent の Fulfillment を再度設定する

Dialogflow コンソールに再度戻り、 Agent の Fulfillment 設定画面の Webhook 項目の URL にコピーした URL を入力し、「 SAVE 」を押下する。

Integrations を設定

Dialogflow コンソールの左メニューから「 Integrations 」を選択する。
Integration のカード一覧より「 Google Assistant 」を有効化する。

テストする

まず、Actvity Controlsで、ログインしてる Google Account の「ウェブとアプリのアクティビティ」と「音声アクティビティ」を有効にします。
次に、 Dialogflow コンソールの Integration のカード一覧より「 Google Assistant 」カードを押下して Popup で「 TEST 」を押下してテストアプリに登録する。
*「 TEST 」ボタンが表示されていなかった場合、「 AUTHORIZE 」ボタンが表示されていると思いますので、押下して Google Acount の認証処理を続けてください

「 TEST 」を押下してしばらくすると緑色のバーが表示されるので、バー右側の「 VIEW 」を押下してシミュレータを起動する。

シミュレータで遊ぶ

シミュレータ画面は以下のようになっています。
赤枠の部分はユーザーから言葉の入力欄です。

さぁ、実際に遊んでみましょう。
入力欄に「テスト用アプリにつないで」と入力すると、アプリが起動します。
次に自分の生年月日を入れてください。
計算結果がシミュレータに表示されるはずです。

まとめ

うまくシミュレータで動かせたでしょうか?
シミュレータで動かせたら、 Google Home でも同じように遊ぶことができます。
ただし、今回アプリを作成するために使用した Google Account と紐付けをしている Google Home でのみ起動できる点に注意してください。
今回やったことは、 Google Assistant に対応したアプリの作成です。
つまり、 Google Assistant に対応したデバイスであれば Google Home を使わなくても起動できます。
設定項目は多いですが、設定しなければいけない流れさえ掴んでしまえば難しいことはありません。
是非、ご自身で思い思いのアプリを作ってみてください。