はじめてのAlexaスキル
ようやくAmazon echoの招待が来たので早速「Alexaスキルを作ってみよう」と思い立った。サイコロを振るスキルなんか簡単そうだしどうだろう?…
「Alexa、サイコロふって」「はい、1がでました!」
「Alexa、サイコロ2個ふって」「はい、10がでました!」
えっ?!Echo、できる子…
「Alexa、サイコロ3個ふって」「ごめんなさい…」
よしっ、サイコロ何個でも投げてやりますとも!
対話モデルをつくる

発話
ユーザからは、サイコロの個数を指定してもらってサイコロを投げるだけなので、発話はすべて 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のコード全体は以下の通り。
"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標準機能のサイコロと違って、ゾロ目かどうかもわかりますよ。