Hardware components | ||||||
| × | 1 | ||||
Software apps and online services | ||||||
| ||||||
|
This trivia game tests your knowledge of the human digestive system. It suits children and adults alike. This game is very easy to play. It will ask you a set of 5 questions any you try your best to answer the questions correctly.
You can start the skill by saying "Alexa, open Digestive System".
There are many tutorials showing the steps about how to develop and test Alexa skills, e.g. this project that i made. Hence, I am not going to do that here. I will post only the relevant codes and screen captures.
Prepare the Lambda Files- Create a directory called
digestive_system
.
- Create
index.js
andpackage.json
files from the respective codes included in the code section. Change the following line of code to the correct application ID value in theindex.js
file.
skillService.pre = function(request, response, type) {
if (request.sessionDetails.application.applicationId != "amzn1.echo-sdk-ams.app.000000-d0ed-0000-ad00-000000d00ebe") {
// Fail ungracefully
response.fail("Invalid applicationId");
}
};
- With nodejs and npm installed, run "
npm install
" in thedigestive_system
directory to install required packages specified in thepackage.json
file. You will find a new directorynode_modules
created.
- Select all the files and directory, then create a zip file call digestive_system.zip. Keep this zip file as it will be used in the next step.
Upload the above zip file to create and setup up the lambda.
Cut and paste the schema, slot types and utterances from the code section. Below are the respective screen captures of the Alexa skill.
Skill Information
Interaction Model
Configuration
Publishing Information
Privacy & Compliance
end
{
"name": "digestive_system",
"version": "1.0.0",
"description": "A digestive system Alexa app",
"main": "index.js",
"author": "vincent wong @ wesee",
"license": "ISC",
"alexa": {
"applicationId":"amzn1.echo-sdk-ams.app.000000-d0ed-0000-ad00-000000d00ebe"
},
"dependencies": {
"alexa-app": "^2.3.2"
}
}
'use strict';
var Skill = require('alexa-app');
var skillService = new Skill.app('digestive_system');
var questions = [
{
"What is the digestive system?": [
"The body's food-processing system", "The body's breathing system", "The body's system of nerves", "The body's blood-transporting system"
] },
{
"Digestion begins in the mouth. Which of the following statement is INCORRECT?": [
"The tongue aids in the digestion of the food.", "The saliva changes some of the starches in the food to sugar.", "The tongue keeps the food in place in the mouth while the food is being chewed.", "The digestive juices can react more easily with the food when chewed."
] },
{
"Where does food pass through between the mouth and the stomach?": [
"The gullet", "The rectum", "The small intestine", "The large intestine"
] },
{
"Our throat divides into two separate tubes: the windpipe and the gullet. What prevents food from entering the windpipe?": [
"The epiglottis", "The uvula", "The tongue", "The trachea"
] },
{
"What happens when food reaches the stomach?": [
"Juices mix with the food and stomach muscles squeeze it.", "Nothing. No digestion occurs in the stomach.", "The food moves quickly into the small intestine.", "The food is completely digested and is absorbed by tiny blood vessels in the walls of the stomach."
] },
{
"Where does the partly-digested food (in liquid form) go after it leaves the stomach?": [
"The small intestine", "The gullet", "The appendix", "The large intestine"
] },
{
"How does digested food finally reach the bloodstream?": [
"It is absorbed into the blood through blood vessels.", "It passes through the gullet into the blood.", "It is absorbed into the blood through the walls of the lungs.", "It passes from the small intestine into the large intestine, then into the blood."
] },
{
"The digestive system processes food into usable and unusable materials. The usable materials are sent to the body's cells as food. What happens to unusable materials?": [
"It goes into the large intestine to await disposal.", "It goes into the pancreas to await disposal.", "It goes to the right ventricle to await disposal.", "It goes into the small intestine to await disposal."
] },
{
"Solid waste leaves the body through the rectum then the anus. Liquid waste leaves the body after passing through the ...": [
"kidneys and bladder", "blood vessels and lungs", "large intestine and bowel", "small intestine and large intestine"
] },
{
"Digestion takes place in a long tube-like canal called the alimentary canal, or the digestive tract. Food travels through these organs in the following order:": [
"Mouth, gullet, stomach, small intestine, large intestine and rectum", "Mouth, oesophagus, stomach, large intestine, small intestine and rectum", "Mouth, stomach, oesophagus, small intestine, large intestine and rectum", "Mouth, stomach, gullet, small intestine, large intestine and rectum"
] },
{
"Which of the following does NOT manufacture digestive juices?": [
"Kidneys", "Liver", "Stomach", "Pancreas"
] },
{
"The liver is located in the abdomen and performs many functions. Which of the following is NOT a function of the liver?": [
"Manufacturing insulin", "Storing food", "Producing digestive juices", "Healing itself when it is damaged"
] }
];
var ANSWER_COUNT = 4;
var GAME_LENGTH = 5;
var CARD_TITLE = "Digestive System"; // Be sure to change this for your skill.
skillService.pre = function(request, response, type) {
if (request.sessionDetails.application.applicationId != "amzn1.echo-sdk-ams.app.000000-d0ed-0000-ad00-000000d00ebe") {
// Fail ungracefully
response.fail("Invalid applicationId");
}
};
skillService.launch(function(request, response) {
getWelcomeResponse(response);
});
skillService.intent('AnswerIntent',
{
"slots": {"ANSWER": "LIST_OF_ANSWERS"},
"utterances": ["{the|my} answer is {-|ANSWER}", "is it {-|ANSWER}", "{-|ANSWER} is my answer"]
},
function(request, response){
handleAnswerRequest(request, response);
}
);
skillService.intent('AnswerOnlyIntent',
{
"slots": {"ANSWER": "LIST_OF_ANSWERS"},
"utterances": ["{-|ANSWER}"]
},
function(request, response){
handleAnswerRequest(request, response);
}
);
skillService.intent('DontKnowIntent',
{
"utterances": [ "{i|} don't know {that|that one|this question|}", "skip", "who knows", "dunno"]
},
function(request, response){
handleAnswerRequest(request, response);
}
);
skillService.intent('AMAZON.YesIntent', {},
function(request, response){
if (request.session('userPromptedToContinue')) {
response.clearSession('userPromptedToContinue');
handleRepeatRequest(request, response);
} else {
handleAnswerRequest(request, response);
}
}
);
skillService.intent('AMAZON.NoIntent', {},
function(request, response){
if (request.session('userPromptedToContinue')) {
response.clearSession('userPromptedToContinue');
handleFinishSessionRequest(response);
} else {
handleAnswerRequest(request, response);
}
}
);
skillService.intent('AMAZON.HelpIntent', {},
function(request, response){
handleGetHelpRequest(response);
}
);
skillService.intent('AMAZON.StopIntent', {},
function(request, response){
handleFinishSessionRequest(response);
}
);
skillService.intent('AMAZON.StartOverIntent',
{
"utterances":[ "start", "{start|new} game", "start new game" ]
},
function(request, response){
getWelcomeResponse(response);
}
);
skillService.intent('AMAZON.CancelIntent', {},
function(request, response){
handleFinishSessionRequest(response);
}
);
skillService.intent('AMAZON.RepeatIntent', {},
function(request, response){
handleRepeatRequest(request, response);
}
);
skillService.sessionEnded(function(request,response) {
// Clean up the user's server-side stuff, if necessary
// No response necessary
});
// ------- Skill specific business logic -------
function writeSessionData(response, sessionAttributes) {
for (var k in sessionAttributes) {
if (sessionAttributes.hasOwnProperty(k)) {
response.session(k, sessionAttributes[k]);
}
}
}
function populateGameQuestions() {
var gameQuestions = [];
var indexList = [];
var index = questions.length;
if (GAME_LENGTH > index){
throw "Invalid Game Length.";
}
for (var i = 0; i < questions.length; i++){
indexList.push(i);
}
// Pick GAME_LENGTH random questions from the list to ask the user, make sure there are no repeats.
for (var j = 0; j < GAME_LENGTH; j++){
var rand = Math.floor(Math.random() * index);
index -= 1;
var temp = indexList[index];
indexList[index] = indexList[rand];
indexList[rand] = temp;
gameQuestions.push(indexList[index]);
}
return gameQuestions;
}
function populateRoundAnswers(gameQuestionIndexes, correctAnswerIndex, correctAnswerTargetLocation) {
// Get the answers for a given question, and place the correct answer at the spot marked by the
// correctAnswerTargetLocation variable. Note that you can have as many answers as you want but
// only ANSWER_COUNT will be selected.
var answers = [],
answersCopy = questions[gameQuestionIndexes[correctAnswerIndex]][Object.keys(questions[gameQuestionIndexes[correctAnswerIndex]])[0]],
temp, i;
var index = answersCopy.length;
if (index < ANSWER_COUNT){
throw "Not enough answers for question.";
}
// Shuffle the answers, excluding the first element.
for (var j = 1; j < answersCopy.length; j++){
var rand = Math.floor(Math.random() * (index - 1)) + 1;
index -= 1;
var temp = answersCopy[index];
answersCopy[index] = answersCopy[rand];
answersCopy[rand] = temp;
}
// Swap the correct answer into the target location
for (i = 0; i < ANSWER_COUNT; i++) {
answers[i] = answersCopy[i];
}
temp = answers[0];
answers[0] = answers[correctAnswerTargetLocation];
answers[correctAnswerTargetLocation] = temp;
return answers;
}
function handleAnswerRequest(request, response) {
// console.log("data->" + JSON.stringify(request.data));
// console.log("intent->" + request.data.request.intent.name);
var speechOutput = "";
var reprompt = "";
var card = {};
var sessionAttributes = {};
var gameInProgress = request.session('questions');
var answerSlotValid = isAnswerSlotValid(parseInt(request.slot('ANSWER', 0)));
var userGaveUp = request.data.request.intent.name === "DontKnowIntent";
if (!gameInProgress) {
// If the user responded with an answer but there is no game in progress, ask the user
// if they want to start a new game. Set a flag to track that we've prompted the user.
sessionAttributes.userPromptedToContinue = true;
speechOutput = "There is no game in progress. Do you want to start a new game? ";
card = {
type: "Simple",
title: CARD_TITLE,
content: speechOutput
};
writeSessionData(response, sessionAttributes);
buildSpeechletResponse(response, speechOutput, speechOutput, card, false);
} else if (!answerSlotValid && !userGaveUp) {
// If the user provided answer isn't a number > 0 and < ANSWER_COUNT,
// return an error message to the user. Remember to guide the user into providing correct values.
reprompt = request.session('speechOutput');
speechOutput = "Your answer must be a number between 1 and " + ANSWER_COUNT + ". " + reprompt;
card = {
type: "Simple",
title: CARD_TITLE,
content: speechOutput
};
writeSessionData(response, sessionAttributes);
buildSpeechletResponse(response, speechOutput, speechOutput, card, false);
} else {
var gameQuestions = request.session('questions'),
correctAnswerIndex = parseInt(request.session('correctAnswerIndex')),
currentScore = parseInt(request.session('score')),
currentQuestionIndex = parseInt(request.session('currentQuestionIndex')),
correctAnswerText = request.session('correctAnswerText');
var speechOutputAnalysis = "";
if (answerSlotValid && parseInt(request.slot('ANSWER')) == correctAnswerIndex) {
currentScore++;
speechOutputAnalysis = "correct. ";
} else {
if (!userGaveUp) {
speechOutputAnalysis = "wrong. "
}
speechOutputAnalysis += "The correct answer is " + correctAnswerIndex + ": " + correctAnswerText + ". ";
}
// if currentQuestionIndex is 4, we've reached 5 questions (zero-indexed) and can exit the game session
if (currentQuestionIndex == GAME_LENGTH - 1) {
speechOutput = userGaveUp ? "" : "That answer is ";
speechOutput += speechOutputAnalysis + "You got " + currentScore.toString() + " out of "
+ GAME_LENGTH.toString() + " questions correct. Thank you for playing!";
card = {
type: "Simple",
title: CARD_TITLE,
content: speechOutput
};
writeSessionData(response, sessionAttributes);
buildSpeechletResponse(response, speechOutput, "", card, true);
} else {
currentQuestionIndex += 1;
var spokenQuestion = Object.keys(questions[gameQuestions[currentQuestionIndex]])[0];
// Generate a random index for the correct answer, from 0 to 3
correctAnswerIndex = Math.floor(Math.random() * (ANSWER_COUNT));
var roundAnswers = populateRoundAnswers(gameQuestions, currentQuestionIndex, correctAnswerIndex),
questionIndexForSpeech = currentQuestionIndex + 1,
repromptText = "Question " + questionIndexForSpeech.toString() + ". " + spokenQuestion + " ";
for (var i = 0; i < ANSWER_COUNT; i++) {
repromptText += (i+1).toString() + ". " + roundAnswers[i] + ". "
}
speechOutput += userGaveUp ? "" : "That answer is ";
speechOutput += speechOutputAnalysis + "Your score is " + currentScore.toString() + ". " + repromptText;
card = {
type: "Simple",
title: CARD_TITLE,
content: speechOutput
};
sessionAttributes = {
"speechOutput": repromptText,
"repromptText": repromptText,
"currentQuestionIndex": currentQuestionIndex,
"correctAnswerIndex": correctAnswerIndex + 1,
"questions": gameQuestions,
"score": currentScore,
"correctAnswerText":
questions[gameQuestions[currentQuestionIndex]][Object.keys(questions[gameQuestions[currentQuestionIndex]])[0]][0]
};
writeSessionData(response, sessionAttributes);
buildSpeechletResponse(response, speechOutput, speechOutput, card, false);
}
}
}
function getWelcomeResponse(response) {
var sessionAttributes = {},
speechOutput = "I will ask you " + GAME_LENGTH.toString()
+ " questions, try to get as many right as you can. Just say the number of the answer. Let's begin. ",
shouldEndSession = false,
gameQuestions = populateGameQuestions(),
correctAnswerIndex = Math.floor(Math.random() * (ANSWER_COUNT)), // Generate a random index for the correct answer, from 0 to 3
roundAnswers = populateRoundAnswers(gameQuestions, 0, correctAnswerIndex),
currentQuestionIndex = 0,
spokenQuestion = Object.keys(questions[gameQuestions[currentQuestionIndex]])[0],
repromptText = "Question 1. " + spokenQuestion + " ",
i, j;
for (i = 0; i < ANSWER_COUNT; i++) {
repromptText += (i+1).toString() + ". " + roundAnswers[i] + ". "
}
speechOutput += repromptText;
var card = {
type: "Simple",
title: CARD_TITLE,
content: speechOutput
};
sessionAttributes = {
"speechOutput": repromptText,
"repromptText": repromptText,
"currentQuestionIndex": currentQuestionIndex,
"correctAnswerIndex": correctAnswerIndex + 1,
"questions": gameQuestions,
"score": 0,
"correctAnswerText":
questions[gameQuestions[currentQuestionIndex]][Object.keys(questions[gameQuestions[currentQuestionIndex]])[0]][0]
};
writeSessionData(response, sessionAttributes);
buildSpeechletResponse(response, speechOutput, repromptText, card, shouldEndSession);
}
function handleGetHelpRequest(response) {
// Provide a help prompt for the user, explaining how the game is played. Then, continue the game
// if there is one in progress, or provide the option to start another one.
// Set a flag to track that we're in the Help state.
response.session('userPromptedToContinue', true);
// Do not edit the help dialogue. This has been created by the Alexa team to demonstrate best practices.
var speechOutput = "I will ask you " + GAME_LENGTH + " multiple choice questions. Respond with the number of the answer. "
+ "For example, say one, two, three, or four. To start a new game at any time, say, start game. "
+ "To repeat the last question, say, repeat. "
+ "Would you like to keep playing?",
repromptText = "To give an answer to a question, respond with the number of the answer . "
+ "Would you like to keep playing?";
var shouldEndSession = false;
buildSpeechletResponseWithoutCard(response, speechOutput, repromptText, shouldEndSession);
}
function handleRepeatRequest(request, response) {
// Repeat the previous speechOutput and repromptText from the session attributes if available
// else start a new game session
if (!request.session('speechOutput')) {
getWelcomeResponse(response);
} else {
buildSpeechletResponseWithoutCard(response, request.session('speechOutput'), request.session('repromptText'), false);
}
}
function handleFinishSessionRequest(response) {
// End the session with a "Good bye!" if the user wants to quit the game
buildSpeechletResponseWithoutCard(response, "Good bye!", "", true);
}
function isAnswerSlotValid(answer) {
return answer < (ANSWER_COUNT + 1) && answer > 0;
}
// ------- Helper functions to build responses -------
function buildSpeechletResponse(response, speechOutput, repromptText, card, shouldEndSession) {
response.say(speechOutput);
response.reprompt(repromptText);
response.card(card);
response.shouldEndSession(shouldEndSession);
}
function buildSpeechletResponseWithoutCard(response, speechOutput, repromptText, shouldEndSession) {
response.say(speechOutput);
response.reprompt(repromptText);
response.shouldEndSession(shouldEndSession);
}
module.exports = skillService;
{
"intents": [
{
"intent": "AnswerIntent",
"slots": [
{
"name": "ANSWER",
"type": "LIST_OF_ANSWERS"
}
]
},
{
"intent": "AnswerOnlyIntent",
"slots": [
{
"name": "ANSWER",
"type": "LIST_OF_ANSWERS"
}
]
},
{
"intent": "DontKnowIntent",
"slots": []
},
{
"intent": "AMAZON.YesIntent",
"slots": []
},
{
"intent": "AMAZON.NoIntent",
"slots": []
},
{
"intent": "AMAZON.HelpIntent",
"slots": []
},
{
"intent": "AMAZON.StopIntent",
"slots": []
},
{
"intent": "AMAZON.StartOverIntent",
"slots": []
},
{
"intent": "AMAZON.CancelIntent",
"slots": []
},
{
"intent": "AMAZON.RepeatIntent",
"slots": []
}
]
}
AnswerIntent the answer is {ANSWER}
AnswerIntent my answer is {ANSWER}
AnswerIntent is it {ANSWER}
AnswerIntent {ANSWER} is my answer
AnswerOnlyIntent {ANSWER}
DontKnowIntent i don't know that
DontKnowIntent don't know that
DontKnowIntent i don't know that one
DontKnowIntent don't know that one
DontKnowIntent i don't know this question
DontKnowIntent don't know this question
DontKnowIntent i don't know
DontKnowIntent don't know
DontKnowIntent skip
DontKnowIntent who knows
DontKnowIntent dunno
AMAZON.StartOverIntent start
AMAZON.StartOverIntent start game
AMAZON.StartOverIntent new game
AMAZON.StartOverIntent start new game
Comments