alexa_generator 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 650a7b5cb37d30de5a4feb18846c71ce321fa48e
4
+ data.tar.gz: c9b7b88fcd63212a071b6b770241cddf5bd87365
5
+ SHA512:
6
+ metadata.gz: 5fa2035fe237d45fe6168855a4c0b2c3034a180d5ea42196b27fb2a69dab9c3171ac8e4a4c8bd3088a2e6214671cb88283a93f20e2a5ecb9d249ec449cc90e99
7
+ data.tar.gz: d3f16acdef5a3cf0c0c5b8f927aa1b572bad896c7ffa5e5ab6c2551dbb863b47ccafd49e257ea7666b0f78cf4b153bb2810b82c17651b21c077bbb304526f049
data/.gitignore ADDED
@@ -0,0 +1,38 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /test/tmp/
9
+ /test/version_tmp/
10
+ /tmp/
11
+
12
+ ## Specific to RubyMotion:
13
+ .dat*
14
+ .repl_history
15
+ build/
16
+
17
+ ## Documentation cache and generated files:
18
+ /.yardoc/
19
+ /_yardoc/
20
+ /doc/
21
+ /rdoc/
22
+
23
+ ## Environment normalisation:
24
+ /.bundle/
25
+ /vendor/bundle
26
+ /lib/bundler/man/
27
+
28
+ # for a library or gem, you might want to ignore these files since the code is
29
+ # intended to run in multiple environments; otherwise, check them in:
30
+ Gemfile.lock
31
+ .ruby-version
32
+ .ruby-gemset
33
+
34
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
35
+ .rvmrc
36
+
37
+ # IntelliJ
38
+ *.iml
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Chris Mullins
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
data/README.md ADDED
@@ -0,0 +1,2 @@
1
+ # alexa_generator
2
+ Rubygem to generate voice interface components for Amazon's Alexa API
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require 'bundler/gem_tasks'
2
+
3
+ require 'rspec/core/rake_task'
4
+ RSpec::Core::RakeTask.new
5
+
6
+ task default: :spec
7
+ task test: :spec
@@ -0,0 +1,28 @@
1
+ $:.push File.expand_path('../lib', __FILE__)
2
+
3
+ require "alexa_generator/version"
4
+
5
+ Gem::Specification.new do |gem|
6
+ gem.name = 'alexa_generator'
7
+ gem.version = AlexaGenerator::VERSION
8
+
9
+ gem.summary = "Generates voice interfaces for Alexa apps based on templates."
10
+
11
+ gem.authors = ['Christopher Mullins']
12
+ gem.email = 'chris@sidoh.org'
13
+ gem.homepage = 'http://github.com/sidoh/alexa_generator'
14
+
15
+ gem.add_development_dependency('rspec', [">= 3.0.0"])
16
+ gem.add_development_dependency('rake')
17
+
18
+ ignores = File.readlines(".gitignore").grep(/\S+/).map(&:chomp)
19
+ dotfiles = %w[.gitignore]
20
+
21
+ all_files_without_ignores = Dir["**/*"].reject { |f|
22
+ File.directory?(f) || ignores.any? { |i| File.fnmatch(i, f) }
23
+ }
24
+
25
+ gem.files = (all_files_without_ignores + dotfiles).sort
26
+
27
+ gem.require_path = "lib"
28
+ end
@@ -0,0 +1,51 @@
1
+ require 'alexa_generator/slot'
2
+ require 'alexa_generator/sample_utterance_template'
3
+
4
+ module AlexaGenerator
5
+ class Intent
6
+ attr_reader :name, :slots
7
+
8
+ class Builder
9
+ attr_reader :bindings, :utterance_templates
10
+
11
+ def initialize(name)
12
+ @name = name
13
+ @slots = []
14
+ @bindings = []
15
+ @utterance_templates = []
16
+ end
17
+
18
+ def add_slot(name, type, &block)
19
+ builder = Slot.build(name, type, &block)
20
+
21
+ slot_bindings = builder.bindings.map { |x| SlotBinding.new(name, x) }
22
+ @bindings.concat(slot_bindings)
23
+
24
+ @slots.push(builder.create)
25
+ end
26
+
27
+ def add_utterance_template(template)
28
+ add_utterance_templates(template)
29
+ end
30
+
31
+ def add_utterance_templates(*templates)
32
+ templates.each { |x| @utterance_templates.push(SampleUtteranceTemplate.new(@name, x)) }
33
+ end
34
+
35
+ def create
36
+ Intent.new(@name, @slots)
37
+ end
38
+ end
39
+
40
+ def initialize(name, slots)
41
+ @name = name
42
+ @slots = slots
43
+ end
44
+
45
+ def self.build(name, &block)
46
+ builder = Builder.new(name)
47
+ block.call(builder)
48
+ builder
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,11 @@
1
+ require 'alexa_generator/intent'
2
+
3
+ module AlexaGenerator
4
+ class IntentSchema
5
+ attr_reader :intents
6
+
7
+ def initialize(intents)
8
+ @intents = intents
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,14 @@
1
+ module AlexaGenerator
2
+ class SampleUtteranceTemplate
3
+ attr_reader :intent_name, :template
4
+
5
+ def initialize(intent_name, template)
6
+ @intent_name = intent_name
7
+ @template = template
8
+ end
9
+
10
+ def referenced_slots
11
+ template.scan( /\{([a-z]+)\}/i ).map(&:first).map(&:to_sym)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,46 @@
1
+ module AlexaGenerator
2
+ class Slot
3
+ module SlotType
4
+ LITERAL = :LITERAL
5
+ NUMBER = :NUMBER
6
+ DATE = :DATE
7
+ TIME = :TIME
8
+ DURATION = :DURATION
9
+ end
10
+
11
+ class Builder
12
+ attr_reader :bindings
13
+
14
+ def initialize(name, type)
15
+ @name = name
16
+ @type = type
17
+ @bindings = []
18
+ end
19
+
20
+ def add_binding(value)
21
+ add_bindings(value)
22
+ end
23
+
24
+ def add_bindings(*values)
25
+ values.map { |v| @bindings.push(v) }
26
+ end
27
+
28
+ def create
29
+ Slot.new(@name, @type)
30
+ end
31
+ end
32
+
33
+ attr_reader :name, :type
34
+
35
+ def initialize(name, type)
36
+ @name = name.to_sym
37
+ @type = type
38
+ end
39
+
40
+ def self.build(name, type, &block)
41
+ builder = Builder.new(name, type)
42
+ block.call(builder)
43
+ builder
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,14 @@
1
+ module AlexaGenerator
2
+ class SlotBinding
3
+ attr_reader :slot_name, :value
4
+
5
+ def initialize(slot_name, value)
6
+ @slot_name = slot_name
7
+ @value = value
8
+ end
9
+
10
+ def bind_to_template!(template)
11
+ template.gsub! "{#{slot_name}}", "{#{value}|#{slot_name}}"
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,3 @@
1
+ module AlexaGenerator
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,105 @@
1
+ require 'alexa_generator/intent_schema'
2
+ require 'alexa_generator/sample_utterance_template'
3
+ require 'alexa_generator/slot_binding'
4
+
5
+ require 'set'
6
+
7
+ module AlexaGenerator
8
+ class VoiceInterface
9
+ attr_reader :intents
10
+
11
+ class Builder
12
+ def initialize
13
+ @intents = []
14
+ @bindings = []
15
+ @utterance_templates = []
16
+ end
17
+
18
+ def add_intent(name, &block)
19
+ builder = Intent.build(name, &block)
20
+ @bindings.concat(builder.bindings)
21
+ @utterance_templates.concat(builder.utterance_templates)
22
+ @intents.push(builder.create)
23
+ end
24
+
25
+ def create
26
+ VoiceInterface.new(@intents, @utterance_templates, @bindings)
27
+ end
28
+ end
29
+
30
+ def initialize(intents, utterance_templates, slot_bindings)
31
+ @intents = Hash[ intents.map {|x| [x.name, x]} ]
32
+
33
+ @utterance_templates = utterance_templates.group_by { |x| x.intent_name }
34
+ @slot_bindings = slot_bindings.group_by { |x| x.slot_name }
35
+ end
36
+
37
+ def intent_schema
38
+ {
39
+ intents: @intents.values.map do |intent|
40
+ {
41
+ intent: intent.name,
42
+ slots: intent.slots.map do |slot|
43
+ {
44
+ name: slot.name,
45
+ type: slot.type
46
+ }
47
+ end
48
+ }
49
+ end
50
+ }
51
+ end
52
+
53
+ def sample_utterances(intent_name)
54
+ templates = @utterance_templates[intent_name] || []
55
+ utterances = Set.new
56
+
57
+ templates.each do |template|
58
+ # Consider only the slots that are referenced in this template
59
+ relevant_slots = template.referenced_slots
60
+
61
+ # Compute all possible value bindings for the relevant slots
62
+ slot_values = relevant_slots.
63
+ # Extract value bindings for each slot
64
+ map { |slot| @slot_bindings[slot] }
65
+
66
+ if slot_values.any?
67
+ slot_value_combinations = slot_values.first
68
+
69
+ if slot_values.count > 1
70
+ remaining_values = slot_values[1..-1]
71
+ slot_value_combinations = slot_value_combinations.product(*remaining_values)
72
+ else
73
+ slot_value_combinations = slot_value_combinations.map { |x| [x] }
74
+ end
75
+
76
+ slot_value_combinations.each do |value_binding|
77
+ raw_template = template.template.dup
78
+
79
+ # puts value_binding.inspect
80
+
81
+ value_binding.each do |binding|
82
+ # puts "----> #{binding}"
83
+ binding.bind_to_template!( raw_template )
84
+ end
85
+
86
+ utterances.add( raw_template )
87
+ end
88
+ # If there are no slot values, then just stuff the untouched template into utterances.
89
+ else
90
+ utterances.add( template.template )
91
+ end
92
+ end
93
+
94
+ utterances.sort.map do |utterance|
95
+ "#{intent_name} #{utterance}"
96
+ end
97
+ end
98
+
99
+ def self.build(&block)
100
+ builder = Builder.new
101
+ block.call(builder)
102
+ builder.create
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,2 @@
1
+ require 'alexa_generator/voice_interface'
2
+ require 'alexa_generator/version'
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+
3
+ describe AlexaGenerator::Slot do
4
+ context 'builder' do
5
+ it 'should return an instance of a builder' do
6
+ slot = AlexaGenerator::Intent.build(:IntentOne) { |x| }
7
+
8
+ expect(slot).to be_an_instance_of(AlexaGenerator::Intent::Builder)
9
+ end
10
+
11
+ it 'should add slot bindings' do
12
+ intent = AlexaGenerator::Intent.build(:IntentOne) do |intent|
13
+ intent.add_slot(:SlotOne, AlexaGenerator::Slot::SlotType::LITERAL) do |slot|
14
+ slot.add_bindings('a', 'b', 'c')
15
+ end
16
+ end
17
+
18
+ expect(intent.bindings).to be_an_instance_of(Array)
19
+ expect(intent.bindings.map(&:value)).to eq(['a', 'b', 'c'])
20
+ end
21
+
22
+ it 'should create an intent when create is called' do
23
+ builder = AlexaGenerator::Intent.build(:IntentOne) do |intent|
24
+ intent.add_slot(:SlotOne, AlexaGenerator::Slot::SlotType::LITERAL) do |slot|
25
+ slot.add_bindings('a', 'b', 'c')
26
+ end
27
+ end
28
+
29
+ intent = builder.create
30
+
31
+ expect(intent.name).to eq(:IntentOne)
32
+
33
+ expect(intent.slots.count).to eq(1)
34
+ expect(intent.slots.first.name).to eq(:SlotOne)
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe AlexaGenerator::SampleUtteranceTemplate do
4
+ it 'should parse slots out of templates' do
5
+ template = AlexaGenerator::SampleUtteranceTemplate.new 'MyIntent', 'Intent, {SlotOne} and {SlotTwo}'
6
+
7
+ expect(template.referenced_slots).to eq([:SlotOne, :SlotTwo])
8
+ end
9
+
10
+ it 'should work with no slots' do
11
+ template = AlexaGenerator::SampleUtteranceTemplate.new 'MyIntent', 'Intent, do that thing'
12
+
13
+ expect(template.referenced_slots).to eq([])
14
+ end
15
+
16
+ it 'should not detect bound slots' do
17
+ template = AlexaGenerator::SampleUtteranceTemplate.new 'MyIntent', 'Intent, do {that|Thing}'
18
+
19
+ expect(template.referenced_slots).to eq([])
20
+ end
21
+ end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+
3
+ describe AlexaGenerator::Slot do
4
+ context 'builder' do
5
+ it 'should return an instance of a builder' do
6
+ slot = AlexaGenerator::Slot.build(:SlotOne, AlexaGenerator::Slot::SlotType::LITERAL) { |x| }
7
+
8
+ expect(slot).to be_an_instance_of(AlexaGenerator::Slot::Builder)
9
+ end
10
+
11
+ it 'should add slot bindings' do
12
+ slot = AlexaGenerator::Slot.build(:SlotOne, AlexaGenerator::Slot::SlotType::LITERAL) do |slot|
13
+ slot.add_bindings('a', 'b', 'c')
14
+ end
15
+
16
+ expect(slot.bindings).to eq(['a', 'b', 'c'])
17
+ end
18
+
19
+ it 'should create a slot when create is called' do
20
+ builder = AlexaGenerator::Slot.build(:SlotOne, AlexaGenerator::Slot::SlotType::LITERAL) do |slot|
21
+ slot.add_bindings('a', 'b', 'c')
22
+ end
23
+
24
+ slot = builder.create
25
+
26
+ expect(slot.name).to eq(:SlotOne)
27
+ expect(slot.type).to eq(AlexaGenerator::Slot::SlotType::LITERAL)
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,146 @@
1
+ require 'spec_helper'
2
+ require 'json'
3
+
4
+ describe AlexaGenerator::VoiceInterface do
5
+ context 'builder' do
6
+ it 'should build a valid voice interface' do
7
+ iface = AlexaGenerator::VoiceInterface.build do |iface|
8
+ iface.add_intent(:IntentOne) do |intent|
9
+ intent.add_slot(:SlotOne, AlexaGenerator::Slot::SlotType::LITERAL) do |slot|
10
+ slot.add_binding('value1')
11
+ end
12
+
13
+ intent.add_utterance_template('test {SlotOne} test')
14
+ end
15
+ end
16
+
17
+ expect(iface).to be_an_instance_of(AlexaGenerator::VoiceInterface)
18
+ expect(iface.intent_schema).to eq(
19
+ {
20
+ intents: [
21
+ {
22
+ intent: :IntentOne,
23
+ slots: [
24
+ {
25
+ name: :SlotOne,
26
+ type: AlexaGenerator::Slot::SlotType::LITERAL
27
+ }
28
+ ]
29
+ }
30
+ ]
31
+ })
32
+ end
33
+
34
+ it 'should produce bound utterances' do
35
+ iface = AlexaGenerator::VoiceInterface.build do |iface|
36
+ iface.add_intent(:MyIntent) do |intent|
37
+ intent.add_slot(:SlotOne, AlexaGenerator::Slot::SlotType::LITERAL) do |slot|
38
+ slot.add_binding('make me a sandwich')
39
+ slot.add_binding('fix my motorcycle')
40
+ end
41
+
42
+ intent.add_slot(:SlotTwo, AlexaGenerator::Slot::SlotType::NUMBER) do |slot|
43
+ slot.add_binding('one')
44
+ slot.add_binding('two')
45
+ end
46
+
47
+ intent.add_slot(:SlotThree, AlexaGenerator::Slot::SlotType::TIME) do |slot|
48
+ slot.add_binding('6 a.m.')
49
+ slot.add_binding('noon')
50
+ end
51
+
52
+ intent.add_utterance_template('Alexa, please {SlotOne} {SlotTwo} at {SlotThree}')
53
+ end
54
+ end
55
+
56
+ actual = iface.sample_utterances(:MyIntent)
57
+
58
+ expect(actual.count).to eq(8)
59
+ expect(actual).to include('MyIntent Alexa, please {fix my motorcycle|SlotOne} {one|SlotTwo} at {noon|SlotThree}')
60
+ expect(actual).to include('MyIntent Alexa, please {fix my motorcycle|SlotOne} {two|SlotTwo} at {noon|SlotThree}')
61
+ expect(actual).to include('MyIntent Alexa, please {make me a sandwich|SlotOne} {one|SlotTwo} at {noon|SlotThree}')
62
+ expect(actual).to include('MyIntent Alexa, please {make me a sandwich|SlotOne} {two|SlotTwo} at {noon|SlotThree}')
63
+ expect(actual).to include('MyIntent Alexa, please {fix my motorcycle|SlotOne} {one|SlotTwo} at {6 a.m.|SlotThree}')
64
+ expect(actual).to include('MyIntent Alexa, please {fix my motorcycle|SlotOne} {two|SlotTwo} at {6 a.m.|SlotThree}')
65
+ expect(actual).to include('MyIntent Alexa, please {make me a sandwich|SlotOne} {one|SlotTwo} at {6 a.m.|SlotThree}')
66
+ expect(actual).to include('MyIntent Alexa, please {make me a sandwich|SlotOne} {two|SlotTwo} at {6 a.m.|SlotThree}')
67
+ end
68
+ end
69
+
70
+ context 'with no templates' do
71
+ intents = [ AlexaGenerator::Intent.new( :MyIntent, [] ) ]
72
+ utterance_templates = [
73
+ AlexaGenerator::SampleUtteranceTemplate.new( :MyIntent, 'Alexa, please do that one thing')
74
+ ]
75
+ slot_bindings = []
76
+
77
+ it 'should produce utterances' do
78
+ actual = AlexaGenerator::VoiceInterface.new(intents, utterance_templates, slot_bindings).sample_utterances(:MyIntent)
79
+ expected = [ "#{utterance_templates.first.intent_name} #{utterance_templates.first.template}" ]
80
+
81
+ expect(actual).to eq(expected)
82
+ end
83
+ end
84
+
85
+ context 'with a single template' do
86
+ intents = [
87
+ AlexaGenerator::Intent.new(
88
+ :MyIntent, [ AlexaGenerator::Slot.new(:SlotOne, AlexaGenerator::Slot::SlotType::LITERAL) ]
89
+ )
90
+ ]
91
+ utterance_templates = [
92
+ AlexaGenerator::SampleUtteranceTemplate.new( :MyIntent, 'Alexa, please {SlotOne}')
93
+ ]
94
+ slot_bindings = [
95
+ AlexaGenerator::SlotBinding.new( :SlotOne, 'make me a sandwich' ),
96
+ AlexaGenerator::SlotBinding.new( :SlotOne, 'fix my motorcycle' )
97
+ ]
98
+
99
+ it 'should produce bound utterances' do
100
+ actual = AlexaGenerator::VoiceInterface.new(intents, utterance_templates, slot_bindings).sample_utterances(:MyIntent)
101
+
102
+ expect(actual.count).to eq(slot_bindings.count)
103
+ expect(actual).to include('MyIntent Alexa, please {make me a sandwich|SlotOne}')
104
+ expect(actual).to include('MyIntent Alexa, please {fix my motorcycle|SlotOne}')
105
+ end
106
+ end
107
+
108
+ context 'with multiple templates' do
109
+ intents = [
110
+ AlexaGenerator::Intent.new(
111
+ :MyIntent, [
112
+ AlexaGenerator::Slot.new(:SlotOne, AlexaGenerator::Slot::SlotType::LITERAL),
113
+ AlexaGenerator::Slot.new(:SlotTwo, AlexaGenerator::Slot::SlotType::NUMBER),
114
+ AlexaGenerator::Slot.new(:SlotThree, AlexaGenerator::Slot::SlotType::TIME),
115
+ ],
116
+ )
117
+ ]
118
+ utterance_templates = [
119
+ AlexaGenerator::SampleUtteranceTemplate.new( :MyIntent, 'Alexa, please {SlotOne} {SlotTwo} at {SlotThree}')
120
+ ]
121
+ slot_bindings = [
122
+ AlexaGenerator::SlotBinding.new( :SlotOne, 'make me a sandwich' ),
123
+ AlexaGenerator::SlotBinding.new( :SlotOne, 'fix my motorcycle' ),
124
+
125
+ AlexaGenerator::SlotBinding.new( :SlotTwo, 'one' ),
126
+ AlexaGenerator::SlotBinding.new( :SlotTwo, 'two' ),
127
+
128
+ AlexaGenerator::SlotBinding.new( :SlotThree, '6 a.m.' ),
129
+ AlexaGenerator::SlotBinding.new( :SlotThree, 'noon' ),
130
+ ]
131
+
132
+ it 'should produce bound utterances' do
133
+ actual = AlexaGenerator::VoiceInterface.new(intents, utterance_templates, slot_bindings).sample_utterances(:MyIntent)
134
+
135
+ expect(actual.count).to eq(8)
136
+ expect(actual).to include('MyIntent Alexa, please {fix my motorcycle|SlotOne} {one|SlotTwo} at {noon|SlotThree}')
137
+ expect(actual).to include('MyIntent Alexa, please {fix my motorcycle|SlotOne} {two|SlotTwo} at {noon|SlotThree}')
138
+ expect(actual).to include('MyIntent Alexa, please {make me a sandwich|SlotOne} {one|SlotTwo} at {noon|SlotThree}')
139
+ expect(actual).to include('MyIntent Alexa, please {make me a sandwich|SlotOne} {two|SlotTwo} at {noon|SlotThree}')
140
+ expect(actual).to include('MyIntent Alexa, please {fix my motorcycle|SlotOne} {one|SlotTwo} at {6 a.m.|SlotThree}')
141
+ expect(actual).to include('MyIntent Alexa, please {fix my motorcycle|SlotOne} {two|SlotTwo} at {6 a.m.|SlotThree}')
142
+ expect(actual).to include('MyIntent Alexa, please {make me a sandwich|SlotOne} {one|SlotTwo} at {6 a.m.|SlotThree}')
143
+ expect(actual).to include('MyIntent Alexa, please {make me a sandwich|SlotOne} {two|SlotTwo} at {6 a.m.|SlotThree}')
144
+ end
145
+ end
146
+ end
@@ -0,0 +1,6 @@
1
+ require 'bundler'
2
+ Bundler.require(:default, :development)
3
+
4
+ require 'rspec'
5
+
6
+ require 'alexa_generator'
metadata ADDED
@@ -0,0 +1,89 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: alexa_generator
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Christopher Mullins
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-07-06 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: 3.0.0
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: 3.0.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description:
42
+ email: chris@sidoh.org
43
+ executables: []
44
+ extensions: []
45
+ extra_rdoc_files: []
46
+ files:
47
+ - .gitignore
48
+ - Gemfile
49
+ - LICENSE
50
+ - README.md
51
+ - Rakefile
52
+ - alexa_generator.gemspec
53
+ - lib/alexa_generator.rb
54
+ - lib/alexa_generator/intent.rb
55
+ - lib/alexa_generator/intent_schema.rb
56
+ - lib/alexa_generator/sample_utterance_template.rb
57
+ - lib/alexa_generator/slot.rb
58
+ - lib/alexa_generator/slot_binding.rb
59
+ - lib/alexa_generator/version.rb
60
+ - lib/alexa_generator/voice_interface.rb
61
+ - spec/alexa_generator/intent_spec.rb
62
+ - spec/alexa_generator/sample_utterance_template_spec.rb
63
+ - spec/alexa_generator/slot_spec.rb
64
+ - spec/alexa_generator/voice_interface_spec.rb
65
+ - spec/spec_helper.rb
66
+ homepage: http://github.com/sidoh/alexa_generator
67
+ licenses: []
68
+ metadata: {}
69
+ post_install_message:
70
+ rdoc_options: []
71
+ require_paths:
72
+ - lib
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ required_rubygems_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ requirements: []
84
+ rubyforge_project:
85
+ rubygems_version: 2.0.14
86
+ signing_key:
87
+ specification_version: 4
88
+ summary: Generates voice interfaces for Alexa apps based on templates.
89
+ test_files: []