このページの本文へ

前へ 1 2 次へ

日曜プログラマーのための「Clovaスキルつくり隊!」 第3回

セッションを管理するプログラミングを学ぼう

パーティーゲームの定番「ビンゴ」スキルをスマートスピーカー用につくってみよう

2019年06月28日 11時00分更新

文● ASCII編集部

  • この記事をはてなブックマークに追加
  • 本文印刷

 というわけで、さっそく見て行きましょう。できあがったのがこちらのスキルです。

 今回もスキルのアイコンには、「かわいいフリー素材いらすとや」さんのイラストを使わせていただきました。今回使用したのはは、「ビンゴゲームのイラスト」です。

 ソースコードはこちら(リスト1)。Node.js(サーバー側でJavaScriptを使う言語)で書かれています。

const clova = require('@line/clova-cek-sdk-nodejs');
const express = require('express');

const clovaSkillHandler = clova.Client
.configureSkill()
//起動時
.onLaunchRequest(responseHelper => {
responseHelper.setSpeechList([
{
lang: 'ja',
type: 'PlainText', value: 'ちょっと豪華な気分の音声ビンゴを起動しました。'
},
{
lang: 'ja',
type: 'PlainText',
value: 'ビンゴ、スタート、の掛け声で、出た数字を読み上げます。'
}
]);

})

//ユーザーからの発話が来たら反応する箇所
.onIntentRequest(async responseHelper => {
//1-①セッション情報を取得する。
const bingo_session = responseHelper.getSessionAttributes();

let bingo_number = [];
let select_number = [];

//1-②数字を格納する
if (Object.keys(bingo_session).length == 0) {
for (let i = 1; i <= 75; i++) {
bingo_number.push(i);
}
} else {
bingo_number = bingo_session['bingo_number'];
select_number = bingo_session['select_number'];
}

const intent = responseHelper.getIntentName();
switch (intent) {
//ビンゴスタート
case 'BingoIntent':
//bingo_numberが空だったら終了
if (bingo_number.length == 0) {
//セッションを終了し初期化を行う。
responseHelper.endSession();
responseHelper.setSessionAttributes();
responseHelper.setSimpleSpeech({
lang: 'ja',
type: 'PlainText',
value: 'すべての番号が出ました、ビンゴを終了します。'
});
} else {
let speechlist = [];
//ランダムで選定
let random = Math.floor(Math.random() * bingo_number.length);
let current_number = bingo_number[random];
select_number.push(current_number);
bingo_number.splice(random, 1);

//1-③セッション情報を保存する。
responseHelper.setSessionAttributes({'bingo_number':bingo_number, 'select_number':select_number});

speechlist = [
{
lang: '',
type: 'URL',
value: 'https://URL/drumroll.mp3'
},
{
lang: '',
type: 'URL',
value: 'https://URL/rollfinish.mp3'
},
{
lang: 'ja',
type: 'PlainText',
value: current_number + '番です。'
}
];

//bingo_numberが空になったら
if (bingo_number.length == 0) {
speechlist.push({
lang: 'ja',
type: 'PlainText',
value: 'すべての番号が出揃いました。'
});
} else {
//2-①数秒間音楽を流す。
speechlist.push(
{
lang: '',
type: 'URL',
value: 'sample.mp3'
},
{
lang: 'ja',
type: 'PlainText',
value: 'ビンゴ、スタート、または、読み上げ、といってください。'
}
);

//2-②リプロンプト
responseHelper.setSimpleSpeech({
lang: 'ja',
type: 'PlainText',
value: 'ビンゴ、スタート、または、読み上げ、といってください。'
}, true);
}

responseHelper.setSpeechList(speechlist);
}//endif
break;
//今までの数字を読み上げ
case 'ReadIntent':
let read_number = [];
//select_numberが空なら数字を読み上げない
if (select_number.length == 0) {
responseHelper.setSimpleSpeech({
lang: 'ja',
type: 'PlainText',
value: '今までに出た数字はありません。',
});
break;
}
select_number.forEach(number => {
read_number.push({
lang: 'ja',
type: 'PlainText',
value: number + '番'
});
});
read_number.push({
lang: 'ja',
type: 'PlainText',
value: '以上です。'
});

responseHelper.setSpeechList(read_number);
break;
//最後に出た数字
case 'LastNumberIntent':
let lastNumberSpeech;
//select_numberが空なら数字を読み上げない
if (select_number.length == 0) {
lastNumberSpeech = '今までに出た数字はありません。';
} else {
lastNumberSpeech = select_number[select_number.length - 1] + '番です。';
}
responseHelper.setSimpleSpeech({
lang: 'ja',
type: 'PlainText',
value: lastNumberSpeech
});
break;
//初期化
case 'ResetIntent':
//1-④セッションを初期化する。
responseHelper.setSessionAttributes();
responseHelper.setSimpleSpeech({
lang: 'ja',
type: 'PlainText',
value: '初期化しました。'
});
break;
//使い方
case 'Clova.GuideIntent':
default:
responseHelper.setSpeechList([
{
lang: 'ja',
type: 'PlainText',
value: 'ビンゴ、スタート、の掛け声で、出た数字を読み上げます。'
},
{
lang: 'ja',
type: 'PlainText',
value: '読み上げ、と言うと、今まで出た数字を、読み上げます。'
},
{
lang: 'ja',
type: 'PlainText',
value: '最後に出た数字、と言うと、最後に出た数字を、読み上げます。'
},
{
lang: 'ja',
type: 'PlainText',
value: '初期化して、と言うと、引いた番号がクリアされ、初期の状態の戻ります。'
}
]);
break;
}

console.log('Intent:' + intent);
})

//終了時
.onSessionEndedRequest(responseHelper => {
const sessionId = responseHelper.getSessionId();
})
.handle();

//ポート3000番で起動しリクエスト待受
const app = new express();
const port = process.env.PORT || 3000;

//applicationIdの検証、基本情報のExtension IDを入力
const clovaMiddleware = clova.Middleware({applicationId: 'YOUR_APPLICATION_ID'});

//ルートディレクトリ配下の本ディレクトリを指定
app.post('/PATH/TO/DEV', clovaMiddleware, clovaSkillHandler);
app.listen(port, () => console.log(`Server running on `));

 どんな命令が実行されているかは、「//」で始まる行に書いてあるコメントを参照してください。

 それでは、今回のプログラムのキモになる部分を少し詳しくみていきましょう。

スキルづくりのワンポイントテク
ビンゴスキルは乱数取得と数字管理がキーポイント

 今回のスキルのワンポイントは、乱数取得の方法です。占いやおみくじは、用意された選択肢の中から、ランダムで1つを取り出すプログラム、と言い換えてもいいかもしれません。

 ここでは、プログラムソースコード内のコメント番号1-①~1-④について説明していきます。

1-①セッション情報を取得する

 const bingo_session = responseHelper.getSessionAttributes()で現在のセッション情報を取得します。今回のプログラムでは、bingo_numberにはまだ引かれていない数字、select_numberには既に引かれた数字が格納されています。

const bingo_session = responseHelper.getSessionAttributes();
let bingo_number = [];
let select_number = [];

【例】
"sessionAttributes": {
"bingo_number": [
1,
2,
3,
5,
6,
9,
12,
13,
14,
15,
17,
18,
19,
21,
23,
26,
28,
29,
30,
31,
32,
35,
36,
37,
40,
41,
42,
44,
45,
46,
51,
52,
54,
55,
56,
58,
60,
61,
62,
63,
65,
66,
68,
69,
70,
71,
72,
73
],
"select_number": [
43,
48,
50,
10,
57,
25,
27,
33,
74,
11,
34,
39,
59,
20,
7,
38,
47,
22,
53,
16,
8,
49,
75,
64,
67,
4,
24
]
}

1-②番号を格納する

 1-①で取得したセッション情報が空だった場合1~75までの数字をfor分を使い配列bingo_numberに格納します。

for (let i = 1; i <= 75; i++) {
bingo_number.push(i);
}

1-①で取得したセッション情報が存在した場合にはセッション情報を配列bingo_numberと配列select_numberにそれぞれ格納します。

bingo_number = bingo_session['bingo_number'];
select_number = bingo_session['select_number'];

1-③セッション情報を保存する。

 ランダムで選ばれた数字を記憶させておくためにセッション情報の保存を行います。

responseHelper.setSessionAttributes({'bingo_number':bingo_number, 'select_number':select_number});

1-④セッションを初期化する。

 ビンゴを最初から始めることができるように初期化機能を設けてあります。

 responseHelper.setSessionAttributes();でセッション情報を空にすることで初期化を行っています。

スキルづくりのワンポイントテクその2
応答時間を調整する

 Clovaスキルは数秒間応答がないとスキルが終了してしまいます。そのため今回のビンゴスキルではすぐに終了しないために工夫を行っています。プログラム内のコメント番号2-①~2-②に該当します。

2-①数秒間音楽を流す。

 番号を読み上げた後、数秒間音楽を流すことで、次の発話要求まで時間を持たせています。

2-②リプロンプト

 返答メソッドの最後の引数にtrueを指定すると数秒間発話がなかった場合に呼び出される処理となります。この処理を入れてあげることで、発話の待ち時間を最大1回延長させることができます。

responseHelper.setSimpleSpeech({
lang: 'ja',
type: 'PlainText',
value: 'ビンゴ、スタート、または、読み上げ、といってください。'
}, true);

 この連載では、これからも面白いスキルをジャンジャンつくっていくので、みんなもぜひ挑戦してみてくださいね!

前へ 1 2 次へ

カテゴリートップへ

この連載の記事