This repository has been archived by the owner on Feb 21, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 219
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Jamison
committed
Aug 1, 2016
0 parents
commit 39e692b
Showing
80 changed files
with
6,627 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
# OS generated files | ||
.DS_Store* | ||
ehthumbs.db | ||
Icon? | ||
Thumbs.db | ||
.idea | ||
|
||
# Logs and databases | ||
*.log | ||
|
||
# ignore compiled files | ||
dest/ | ||
*.com | ||
*.class | ||
*.dll | ||
*.exe | ||
*.o | ||
*.so | ||
|
||
# ignore packaged files | ||
*.crx | ||
*.7z | ||
*.dmg | ||
*.gz | ||
*.iso | ||
*.jar | ||
*.rar | ||
*.tar | ||
*.zip | ||
|
||
# Media Files | ||
*.avi | ||
*.swf | ||
*.flv | ||
*.mpg | ||
*.mpe | ||
*.mpeg | ||
*.m4v | ||
*.mp4 | ||
*.mp3 | ||
*.mov | ||
*.webm | ||
*.ogg | ||
*.ogv | ||
|
||
# Dependancies | ||
dist/ | ||
docs/ | ||
report/ | ||
node_modules/ | ||
jspm_packages/ | ||
bower_components/ | ||
.tmp/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
# -*-perl-*- | ||
|
||
package.ADXDT-Alexa-Skill-Decision-Tree-Editor = { | ||
interfaces = (1.0); | ||
|
||
deploy = { | ||
generic = true; | ||
}; | ||
|
||
build-environment = { | ||
chroot = basic; | ||
network-access = blocked; | ||
}; | ||
|
||
# Use NoOpBuild. See https://w.amazon.com/index.php/BrazilBuildSystem/NoOpBuild | ||
build-system = no-op; | ||
build-tools = { | ||
1.0 = { | ||
NoOpBuild = 1.0; | ||
}; | ||
}; | ||
|
||
# Use runtime-dependencies for when you want to bring in additional | ||
# packages when deploying. | ||
# Use dependencies instead if you intend for these dependencies to | ||
# be exported to other packages that build against you. | ||
dependencies = { | ||
1.0 = { | ||
}; | ||
}; | ||
|
||
runtime-dependencies = { | ||
1.0 = { | ||
}; | ||
}; | ||
|
||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
web: node index.js |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
# Interactive Adventure Game Tool | ||
|
||
This tool provides an easy to use front-end that allows developers to instantly deploy code for your story, or use the generated code as a starting point for more complex projects. It was written in Node.js by Thomas Yuill, a designer and engineer in the Amazon Advertising team. | ||
|
||
 | ||
|
||
## How to Get Started | ||
|
||
Setup AWS and the Amazon Developer Console | ||
|
||
To get started with the included sample project, you'll need to setup a few pre-requisites: | ||
|
||
* The tool generates Node.js code that will be deployed to AWS Lambda to handle requests from users passed to you from the Alexa platform. | ||
* The skill uses a table in AWS DynamoDB to save the user's progress between sessions. | ||
* You can then register your skill with Alexa using the Amazon Developer website, linking it to your AWS resources. | ||
|
||
You can change the name of these resources to whatever you like later, but for now, setup the following items: | ||
|
||
1. Create or login to an AWS account. In the AWS Console: | ||
1. Create an AWS role with full access to Lambda and DynamoDB. | ||
1. Create an AWS Lambda function named MyAlexaSkillLambdaFunction being sure to select the role created above and configuring "Alexa Skills Kit" as the "Event Source". Take note of the ARN on the upper right, which you'll configure in the Developer Console later. | ||
|
||
 | ||
|
||
 | ||
|
||
1. Create an AWS DynamoDB table named MyAlexaSkillTable with the case sensitive primary key "userId". | ||
|
||
 | ||
|
||
1. Create or login to an [Amazon Developer account](https://developer.amazon.com). In the Developer Console: | ||
1. [Create an Alexa Skill](https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/developing-an-alexa-skill-as-a-lambda-function) named MySkill and using the invocation name "my skill" and using the ARN you noted above. | ||
|
||
 | ||
|
||
 | ||
|
||
## Set up Your Machine | ||
|
||
Next, you'll setup your local environment to run the tool. It's run using Node.js and you access it with a standard web browser. On OS X: | ||
|
||
1. Configure AWS credentials the tool will use to upload code to your Skill. You do this by creating a file under a ".aws" directory in your home directory. | ||
|
||
``` | ||
mkdir ~/.aws/ | ||
touch ~/.aws/credentials | ||
``` | ||
2. The file should have the format, and include keys you retrieve from the AWS console: | ||
``` | ||
[default] | ||
aws_access_key_id = [KEY FROM AWS] | ||
aws_secret_access_key = [SECRET KEY FROM AWS] | ||
``` | ||
2. Setup NodeJS and NPM: | ||
``` | ||
brew install node | ||
``` | ||
3. Get the code and install dependencies: | ||
``` | ||
git clone https://github.com/alexa/interactive-adventure-game-tool.git | ||
npm install | ||
``` | ||
4. Launch: | ||
``` | ||
npm start | ||
``` | ||
## Using the Tool | ||
Once the tool opens in a browser window, you'll see that a sample project is pre-loaded that shows off the main features of the tool. | ||
On the left, you'll see a tree of nodes, which represents how users will navigate your skill. Users start at the big blue "Start" node. | ||
The smaller bubbles above each node represents the utterance, a phrase the user will say to reach that node, and Alexa will read these to the user when they reach the parent node unless you override this using "Override Default Prompt" or if the node is hidden (see below). | ||
In the sample skill, an example interaction with Alexa might be: | ||
``` | ||
User: Alexa, launch My Alexa Skill. | ||
Alexa: Welcome to my Alexa Skill. To learn how to use this skill, say "Help". When you are ready, say "Begin". | ||
User: Begin | ||
Alexa: You enter a room with three doors, each with a distinct number on it. Which door would you like to open? | ||
``` | ||
If you select a node, you can see the Voice and Card elements on the right that Alexa will send/say to the user upon reaching the node. | ||
Under the "Advanced" options, you can change the color of the node to help you organize (colors don't change the behavior of your skill) and you can "hide" nodes, causing Alexa to skip reading their utterance as part of the default prompt of the parent. | ||
If you click on an utterance, you can enter multiple variations of the phrase that will also be accepted by Alexa. Only the first one will be read to the user in the default prompt. | ||
Lastly, the icons on the upper right allow you to: | ||
*  Save the Skill code, which will be output to "./src/skill". | ||
*  | ||
Upload the Skill code to the Lambda function you configured earlier. You can configure the function name by clicking the home icon and changing the values under "AWS Settings". | ||
*  See help content for the tool. | ||
 | ||
 | ||
## Finishing Deployment of Your Skill | ||
Click the "Save" icon (if you haven't already), and the "Upload" icon to send the Skill code up to Lambda. When you save the Skill, the tool generates some additional configuration inside "./src/skill/models/" that you'll use to tell Alexa how users will interact with you Skill. | ||
You'll need to complete the configuration manually by logging into the [Developer Console](https://developer.amazon.com) and accessing the "My Alexa Skill" you created above. On the "Interaction Model" tab, copy and paste the Intent Schema from "./src/skill/models/intentSchema.json" and Sample Utterances from "./src/skill/models/utterances.txt". | ||
Click save, and the Skill should now be available on your developer account. If your Alexa device is associated with the same Amazon account as your Developer Console account, then you can start using the skill immediately. Or you can use it on the [online simulator](https://echosim.io) by logging in using the same account. | ||
Congrats! Enjoy and let your imagination run wild, we can't wait to see what you come up with! |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"key": "value", | ||
"key2": "value2", | ||
"other_key": "other_value" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
var gulp = require('gulp'); | ||
var runSequence = require('run-sequence'); | ||
|
||
gulp.task('default', function () { | ||
runSequence(['styles','tags'],'serve'); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
var fs = require('fs') | ||
var gulp = require('gulp') | ||
var $ = require('gulp-load-plugins')() | ||
|
||
gulp.task('generate', function ( cb ) { | ||
|
||
var config = JSON.parse(fs.readFileSync('./src/skill/models/config.json','utf8')) | ||
var scenes = JSON.parse(fs.readFileSync('./src/skill/models/scenes.json','utf8')) | ||
var intentSchema = {} | ||
|
||
return new Promise( function ( resolve, reject ) { | ||
|
||
var intentNames = new Set() | ||
var functionDefs = {} | ||
var utterances = [] | ||
|
||
intentSchema.intents = [{ intent: 'UnrecognizedIntent' }] | ||
utterances.push.apply( utterances, [ | ||
'UnrecognizedIntent ThisIsPurposlyNonSense', | ||
'UnrecognizedIntent ThisIsPurposlyNonSense ThisIsPurposlyNonSense', | ||
'UnrecognizedIntent ThisIsPurposlyNonSense ThisIsPurposlyNonSense ThisIsPurposlyNonSense', | ||
'UnrecognizedIntent ThisIsPurposlyNonSense ThisIsPurposlyNonSense ThisIsPurposlyNonSense ThisIsPurposlyNonSense', | ||
'UnrecognizedIntent ThisIsPurposlyNonSense ThisIsPurposlyNonSense ThisIsPurposlyNonSense ThisIsPurposlyNonSense ThisIsPurposlyNonSense' | ||
]) | ||
|
||
// process commands from config.json | ||
Object.keys( config.commands ).forEach( function( intent ) { | ||
functionDefs[ intent ] = createFunctionDefinition( intent, config.commands[ intent ][0] ) | ||
config.commands[ intent ].forEach( function ( utterance ) { | ||
utterance = replaceIntegersWithWords( utterance ) | ||
utterances.push( intent + ' ' + utterance ) | ||
intentNames.add( intent ) | ||
}) | ||
}) | ||
|
||
// process scenes from script/.json | ||
scenes.forEach( function( scene ) { | ||
if ( ! scene.options ) return // exit | ||
scene.options.forEach( function( option ) { | ||
var intent = createIntentName(replaceIntegersWithWords( option.utterances[0] )) | ||
functionDefs[ intent ] = createFunctionDefinition( intent, option.utterances[0] ) | ||
intentNames.add( intent ) | ||
option.utterances.forEach( utterance => { | ||
utterance = replaceIntegersWithWords( utterance ) | ||
utterances.push( intent + ' ' + utterance ) | ||
}) | ||
}) | ||
}) | ||
|
||
// construct intent schema | ||
for ( var name in functionDefs ) { | ||
var intentExists = intentSchema.intents.find( function ( intent ) { | ||
return ( intent.intent === name ) | ||
}) | ||
if ( ! intentExists ) { | ||
intentSchema.intents.push({ intent: name, }) | ||
} | ||
} | ||
|
||
// write generated intents | ||
functionDefsWriteStream = fs.createWriteStream('./src/skill/handlers/intentHandlers_generated.js') | ||
functionDefsWriteStream.on('open', function () { | ||
functionDefsWriteStream.write('var processUtterance = require(\'./processUtterance\')\n\n') | ||
functionDefsWriteStream.write('module.exports = {\n') | ||
for ( var name in functionDefs ) { | ||
functionDefsWriteStream.write( '\t"' + name + '": ' + functionDefs[ name ] ) | ||
} | ||
functionDefsWriteStream.write('}') | ||
functionDefsWriteStream.end() | ||
}) | ||
|
||
// write utterance | ||
utterancesWriteStream = fs.createWriteStream('./src/skill/models/utterances.txt') | ||
utterancesWriteStream.on('open', function () { | ||
utterancesWriteStream.write( utterances.join('\n') ) | ||
utterancesWriteStream.end() | ||
}) | ||
|
||
// write intent schema | ||
intentSchemaWriteStream = fs.createWriteStream('./src/skill/models/intentSchema.json') | ||
intentSchemaWriteStream.on('open', function () { | ||
var content = JSON.stringify( intentSchema, null, 2 ) | ||
intentSchemaWriteStream.write( content ) | ||
intentSchemaWriteStream.end() | ||
}) | ||
|
||
resolve() | ||
|
||
}) | ||
|
||
}) | ||
|
||
function createIntentName ( utterance ) { | ||
return utterance.toLowerCase().split(' ').map( function ( word ) { | ||
return word.charAt(0).toUpperCase() + word.slice(1) | ||
}).join('') + 'Intent' | ||
} | ||
|
||
function createFunctionDefinition ( intentName, utterance ) { | ||
return 'function ( intent, session, request, response ) {\n' | ||
+ '\t\tprocessUtterance( intent, session, request, response, "' + utterance + '" )\n' | ||
+ '\t},\n' | ||
} | ||
|
||
function replaceIntegersWithWords ( utterance ) { | ||
return utterance.split(' ').map( function ( word ) { | ||
if ( Number( word ) ) return word = convertIntegerToWord( Number( word ) ) | ||
return word | ||
}).join(' ') | ||
} | ||
|
||
function convertIntegerToWord ( it ) { | ||
|
||
var units = new Array ("zero","one","two","three","four","five","six","seven","eight","nine","ten","eleven","twelve","thirteen","fourteen","fifteen","sixteen","seventeen","eighteen","nineteen") | ||
var tens = new Array ("twenty","thirty","forty","fifty","sixty","seventy","eighty","ninety") | ||
var theword = "" | ||
var started | ||
|
||
if ( it > 999 ) return "Lots" | ||
if ( it == 0 ) return units[0] | ||
|
||
for (var i = 9; i >= 1; i--){ | ||
if (it>=i*100) { | ||
theword += units[i] | ||
started = 1 | ||
theword += " hundred" | ||
if (it!=i*100) theword += " and " | ||
it -= i*100 | ||
i=0 | ||
} | ||
} | ||
|
||
for (var i = 9; i >= 2; i--){ | ||
if (it>=i*10) { | ||
theword += (started?tens[i-2].toLowerCase():tens[i-2]) | ||
started = 1 | ||
if (it!=i*10) theword += "-" | ||
it -= i*10 | ||
i=0 | ||
} | ||
} | ||
|
||
for (var i=1; i < 20; i++) { | ||
if (it==i) { | ||
theword += (started?units[i].toLowerCase():units[i]) | ||
} | ||
} | ||
|
||
return theword | ||
|
||
} |
Oops, something went wrong.