The Dice Championship project is about exploring how a simple voice app - Dice Championship - can be implemented and extended using different frameworks, platforms and services. It was initiated and published by me (Florian Hollandt), but contributions of ideas, implementations and improvements are very welcome. :)
This is the implementation of Dice Championship that got published to the US, (english) Canadian and German Alexa Skill Store, and it contains the complete set of features to elevate the Skill from the simplified, easy-to-follow base version to a something that evidently passed certification.
Here are the differences in detail:
Base version | Live Alexa Skill version | |
---|---|---|
Persistence | Only within sessions | Between sessions, using a separate DynamoDB table for user data |
Returning users | Treated as new users, i.e. no functionality covering returning users | Proper treatment of returning users, i.e. greeting and summary |
Help intent | Not handled | Handler with different behavior for launch and within-session help request |
Round counter | Not implemented | Implemented (number of rounds within session and in total) |
Leaderboard |
Contains attributes id and score
|
Contains more attributes (platform , locale , rounds & userStatus and date )
|
Regional availability |
Only en-US 🇺🇸
|
en-US + es-US 🇺🇸, en-CA + fr-CA 🍁,en-GB 🇬🇧, de-DE 🇩🇪, fr-FR 🇫🇷,es-ES 🇪🇸, es-MX 🌵, it-IT 🇮🇹
|
Sounds | Game show sounds from ASK Sound Library | Licensed and remixed sounds from Audiojungle |
Brief mode | None | Reduced amount of response text after 2nd round |
Visuals | None | APL support |
Ultimately, this version of Dice Championship will combine the most publication-worthy features of all implementations within this project.
This version uses different, and thus less generic sound effects than the base version. It might be educational to have a bit of background on where these sound effects were obtained (short answer: Audiojungle) and how they were selected.
Base version | Live Alexa Skill version | |
---|---|---|
Welcome / intro sound | "Gameshow Intro (1)" ("Gameshow" category) |
"Victory" *
|
Goodbye / outro sound | "Gameshow Outro (1)" ("Gameshow" category) |
"Small Success" *
|
Dice sound | "Board Games (8)" ("Toys_Games/Board_Games" category) | "Playing Dice - Rolling (6 variations)" |
Tally with positive result | "Gameshow Tally Positive (1)" ("Gameshow" category) |
"Game Points Count Rapid" +
"Small Success" *
|
Tally with negative result | "Gameshow Tally Negative (1)" ("Gameshow" category) |
"Game Points Count Rapid" (shorter version) +
"Soft Fail" *
|
Minor success (new personal highscore) | "Gameshow Positive Response (1)" ("Gameshow" category) |
"Victory" *
|
Medium success (Higher rank) | "Gameshow Positive Response (2)" ("Gameshow" category) |
"Victory" *
|
Major success (First rank!) | "Gameshow Positive Response (3)" ("Gameshow" category) |
"Win Fanfare" *
|
All audio files marked with *
were produced by the same Audiojungle user, to ensure a consistent audio experience across the Skill. The tally and dice sounds were mixed using GarageBand.
I have purchase a single-use license for the Audiojungle sounds mentioned here, so if you plan to use these sounds in your own voice apps, you will need to purchase your own license.
Dice Championship uses APL to enrich the conversation with visual feedback. In order to provide value through this additional output channel, it displays the individual dice faces of each round - They are too long to enumerate in the dialog, but can be nicely represented visually. To convey the experience of throwing a handfull of dice, their individual positions and rotations are randomly generated (while avoiding collisions).
Here's an example of how the visuals look like, in this case on the Echo Show 5:
Disclaimer: The following setup instruction is copied from the base version, because the only difference is that you need a slightly different IAM policy, and another environment variable for the user database.
- Setting up the project folder
- Clone this repository, run
npm install --save
and make a copy of.env.example
named.env
. We'll use environment variables to set up all the required credentials. - You can already make a decision about your database table names for scores and users (let's say
diceChampionship_scores
anddiceChamptionship_users
) and favorite AWS region (e.g. Ireland/eu-west-1
) for the steps and services described below, and include them in your.env
file like this:DYNAMODB_REGION='eu-west-1'
,DYNAMODB_TABLE_NAME_SCORES='diceChamptionship_scores'
andDYNAMODB_TABLE_NAME_USERS='diceChamptionship_users'
- Clone this repository, run
- Setting up access to your DynamoDB table
- Depending on whether you want to run the Skill locally or on Lambda, you need either a programmatic user (aka serivce account) a role with access to both your new cluster and its credentials secret. To cover both, start out by creating a new AWS IAM policy 'diceChampionship_policy' using the one from
policy.json
in this repo. - Change the resource ARN for the first group in line 14 if you chose a different table name in step 1.
- Create a new AWS IAM user 'diceChampionship_user' with programmatic access and the policy 'diceChampionship_policy' you just created. Instead of downloading the credentials file, you can directly copy the access key ID and secret access key into your
.env
file asDYNAMODB_ACCESS_KEY_ID='<your-access-key-id>'
andDYNAMODB_SECRET_ACCESS_KEY='<your-secret-access-key>'
. - Simliarly, create a new AWS IAM role
diceChampionship_role
, again with the 'diceChampionship_policy' policy from above. It already has write access to CloudWatch logs, so you know what's going on on your Lambda.
- Depending on whether you want to run the Skill locally or on Lambda, you need either a programmatic user (aka serivce account) a role with access to both your new cluster and its credentials secret. To cover both, start out by creating a new AWS IAM policy 'diceChampionship_policy' using the one from
- Creating your DynamoDB score table
- For your convenience, I provided a setup script
setup.js
in this repo that uses the config and credentials from your.env
file along with the table config fromsrc/config.js
to create the required table. - The table will be set up with a reserved read and write capacity of 1 each, because that's what's eligible for the AWS free tier. If you prefer 'on-demand' scaling and billing, choose 'pay-per-request' as your billing mode.
- To execute this script, run
node setup.js
from your command line. It will check which DynamoDB tables exist in your region, and create a new table with the name ofDYNAMODB_TABLE_NAME
from your.env
file ('diceChampionship' by default) if it doesn't - You don't need to set up the DynamoDB user table explicitly like that - the Jovo DynamoDB plugin will do this for you. However, it will set up the table with a read and write capacity of 5 each, which you might want to reduce to save costs
- For your convenience, I provided a setup script
- Creating your Lambda function
- I didn't provide a setup script for your Lambda function, as this would have used an excessive amount of access privileges. However, setting up a Lambda function is a routine thing, so let's quickly walk through this!
- Open the AWS Lambda functions overview in your selected region and hit Create function.
- Give your Lambda a Node 8.10 runtime (or above) and the existing role 'diceChampionship_role' from step 2.
- Add 'Alexa Skills Kit' as a trigger for your Lambda function. For now you can disable the restriction to a defined Skill ID.
- Copy the environment variables
DYNAMODB_TABLE_NAME_USERS
,DYNAMODB_TABLE_NAME_SCORES
and their respective values from your local.env
file to the Lambda's environment variable section. - Copy the Lambda's ARN into your local
.env
file, as the value ofLAMBDA_ARN_STAGING
(more on staging below).
- Creating the Alexa Skill
- This is something you could do directly in the Alexa developer console, but here we're using the Jovo CLI because it's super convenient. So be sure to have the Jovo CLI installed and optimally your ASK CLI and AWS CLI profiles set up.
- Write the name of the ASK CLI profile you plan to use into your local
.env
file as e.g.ASK_PROFILE='default'
. - Now execute
jovo build -p alexaSkill --stage local --deploy
from your command line. This builds the Skill manifest (platforms/alexaSkill/skill.json
) and language model (platforms/alexaSkill/models/en-US.json
) from the information in the project configuration file (project.js
) and the Jovo language model (models/en-US.json
), and uses them to set up a new Skill 'Dice Tournament' in your Alexa developer console.
The result should look like this:
- Now copy the Skill ID from the console output and paste it as the value of the
SKILL_ID_STAGING
variable in your.env
file. - Execute
jovo run --watch
from your command line to activate your local endpoint. The Skill endpoint will create the DynamoDB user table.
You can already test your Skill in the Alexa developer console, or on your device by saying "Alexa, open Dice Tournament"!
The remaining steps are optional, but recommended. Before we proceed to uploading the Skill to Lambda, let me explain the staging setup.
- Reviewing the staging setup
- This project comes with a setup for three stages, to propagate good practices and let you try out things both locally and on Lambda, because it might behave differently (e.g. in terms of latency)
* It would make sense for your live Skill to use different databases than the `local` and `staging` stages
- Uploading your Skill code to Lambda
- After having reviewed the staging setup, it's clear that uploading your Skill to Lambda is as easy as building and deploying the staging stage of your project.
- To be able to upload your code to Lambda with the Jovo CLI, make sure your AWS CLI profile is linked to your ASK CLI profile, and has Lambda upload privileges
- Now all you need to do it execute
jovo build -p alexaSkill --stage staging --deploy
- The result should look like this:
- Again, you can now test your Skill in the Alexa developer console just like after step 5, in the same Skill
- Preparing and deploying the live stage
- I'll cover this part more briefly than the ones before, because it's more about deployment than about getting this Skill to work
- First, you need a new Lambda function - Just set one up like in step 4 (with the same role, trigger and environment variables), and copy its ARN as the value of
LAMBDA_ARN_LIVE
in your.env
file - If you want to use different DynamoDB tables for your live stage, you need to set up the score table (with the same hash key
id
), paste its name into the environment variableDYNAMODB_TABLE_NAME_SCORES
of your Lambda function, and accordingly expand your policydiceChampionship_policy
's resource part.
If you want a different table for user data for this stage, just write the name you want the new DynamoDB table to have as the value ofDYNAMODB_TABLE_NAME_SCORES
, and the Jovo framework's DynamoDB integration will set it up for you. - To set up the new Skill (using the new Lambda endoint, the invocation name 'dice championship', and an expanded version of the manifest including a different Skill icon), execute
jovo build -p alexaSkill --stage live --deploy
. - After the first deployment, copy the new Skill's ID and paste it as the value of
SKILL_ID_LIVE
in your.env
file
I hope you find both this entire project and the individual variants interesting and valuable. Again, if you like this project and want to see it implementing your favorite platform, service or feature, please get in touch or start implementing right away.