LoginSignup
1
2

More than 5 years have passed since last update.

Alexaでサイコロを投げまくる

Posted at

はじめてのAlexaスキル

ようやくAmazon echoの招待が来たので早速「Alexaスキルを作ってみよう」と思い立った。サイコロを振るスキルなんか簡単そうだしどうだろう?…

「Alexa、サイコロふって」「はい、1がでました!」
「Alexa、サイコロ2個ふって」「はい、10がでました!」

えっ?!Echo、できる子…

「Alexa、サイコロ3個ふって」「ごめんなさい…」

よしっ、サイコロ何個でも投げてやりますとも!

対話モデルをつくる

Paper.アイデア.1.png
最初のやり取りでサイコロの個数が指定されたら、それ以降はサイコロの個数を指定しなくてもよいようにセッションを維持するようにしてみる。

発話

ユーザからは、サイコロの個数を指定してもらってサイコロを投げるだけなので、発話はすべて CastDiceIntent にマッピングされる。

CastDiceIntent さいころ振って
CastDiceIntent {Number} 個振って
CastDiceIntent 振って
CastDiceIntent さいころ投げて
CastDiceIntent {Number} 個投げて
CastDiceIntent 投げて

Intent Schema

CastDiceIntentにはサイコロの個数を示すNumberスロットを設定する。

{
  "intents": [
    {
      "slots": [
        {
          "name": "Number",
          "type": "AMAZON.NUMBER"
        }
      ],
      "intent": "CastDiceIntent"
    },
    {
      "intent": "AMAZON.HelpIntent"
    },
    {
      "intent": "AMAZON.StopIntent"
    },
    {
      "intent": "AMAZON.CancelIntent"
    }
  ]
}

Lambda

CastDiceIntentの中では、サイコロの個数を表すSlotを参照する。2個以上のサイコロが指定されたら、2投目以降はあらためてサイコロの個数を指定しなくてもいいよう、セッションアトリビュートを使ってセッションを維持する。

        var number = this.event.request.intent.slots.Number.value; // サイコロの個数
        if (!number) {
            number = 1; // slotに値がなければ1個
        }
        this.attributes['number'] = number;

また、2個以上のサイコロが指定されたときには状態をREPEATMODEに遷移し、サイコロ投げを繰り返す。
サイコロが1個の場合はセッションを維持する必要が無いので、応答を返してセッションを終了する。無駄にサイコロをたくさん指定したときもセッションを終了する。

        if (number == 1 || number > 10) {
            this.emit(':tell', message); // レスポンスの生成
        } else {
            this.handler.state = states.REPEATMODE;

Lambdaのコード全体は以下の通り。

index.js
"use strict";
const Alexa = require('alexa-sdk');

const states = {
    REPEATMODE: '_REPEAT'
};

// Lambda関数のメイン処理
exports.handler = function(event, context, callback) {
    var alexa = Alexa.handler(event, context); // Alexa SDKのインスタンス生成
    //alexa.appId = process.env.APP_ID;
    alexa.registerHandlers(handlers, stateHandlers); // ハンドラの登録
    alexa.execute();                  // インスタンスの実行
};

var handlers = {
    // インテントに紐付かないリクエスト
    'LaunchRequest': function () {
    this.emit('AMAZON.HelpIntent'); // AMAZON.HelpIntentの呼び出し
    },

    // ヘルプインテント
    'AMAZON.HelpIntent': function () {
        this.emit(':tell', 'サイコロを振ります' +
            'たとえば、サイコロ振ってと言って下さい');
    },

    // さいころを投げるインテント
    'CastDiceIntent': function () {
        var number = this.event.request.intent.slots.Number.value; // サイコロの個数
        if (!number) {
            number = 1; // slotに値がなければ1個
        }
        this.attributes['number'] = number;

        var message;
        if (number > 10) {
            message = 'そんなにたくさんサイコロ持てないですよ';
        } else {
            message = rollDice(number);
        }

        if (number == 1 || number > 10) {
            this.emit(':tell', message); // レスポンスの生成
        } else {
            this.handler.state = states.REPEATMODE;
            this.emit(':ask', message); // レスポンスの生成
        }
        console.log(message);
    }
};

var stateHandlers = Alexa.CreateStateHandler(states.REPEATMODE, {
  'CastDiceIntent': function() {
    var number = this.attributes['number']; // セッションアトリビュート参照
    var message = rollDice(number);
    this.emit(':ask', message);
    console.log(message);
  },
  'Unhandled': function() {
    this.handler.state = '';
    this.attributes['STATE'] = '';
    var message = '終了します';
    this.emit(':tell', message);
    console.log(message);
  }
});

function rollDice(number) {
    var message = '目は';
    for (var i = 0; i < number; i++) {
        var dice = Math.floor(Math.random()*6) + 1;
        if (i > 0) {
            message = message + '';
        }
        message = message + dice;
    }
    message = message + 'です';
    return message;
}

サイコロ投げた

これで好きな数だけサイコロを投げられるようになりました! Alexa標準機能のサイコロと違って、ゾロ目かどうかもわかりますよ。

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2