adhearsion 2.0.0.rc4 → 2.0.0.rc5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.md +4 -0
- data/adhearsion.gemspec +1 -1
- data/bin/ahn +0 -3
- data/lib/adhearsion.rb +7 -4
- data/lib/adhearsion/call.rb +1 -1
- data/lib/adhearsion/call_controller.rb +1 -0
- data/lib/adhearsion/call_controller/menu_dsl.rb +19 -0
- data/lib/adhearsion/call_controller/menu_dsl/calculated_match.rb +43 -0
- data/lib/adhearsion/call_controller/menu_dsl/calculated_match_collection.rb +45 -0
- data/lib/adhearsion/call_controller/menu_dsl/fixnum_match_calculator.rb +22 -0
- data/lib/adhearsion/call_controller/menu_dsl/match_calculator.rb +40 -0
- data/lib/adhearsion/call_controller/menu_dsl/menu.rb +203 -0
- data/lib/adhearsion/call_controller/menu_dsl/menu_builder.rb +84 -0
- data/lib/adhearsion/call_controller/menu_dsl/range_match_calculator.rb +60 -0
- data/lib/adhearsion/call_controller/menu_dsl/string_match_calculator.rb +25 -0
- data/lib/adhearsion/cli.rb +0 -1
- data/lib/adhearsion/router/route.rb +2 -2
- data/lib/adhearsion/version.rb +1 -1
- data/spec/adhearsion/call_controller/input_spec.rb +1 -1
- data/spec/adhearsion/call_controller/menu_dsl/calculated_match_collection_spec.rb +60 -0
- data/spec/adhearsion/call_controller/menu_dsl/calculated_match_spec.rb +61 -0
- data/spec/adhearsion/call_controller/menu_dsl/fixnum_match_calculator_spec.rb +37 -0
- data/spec/adhearsion/call_controller/menu_dsl/match_calculator_spec.rb +17 -0
- data/spec/adhearsion/call_controller/menu_dsl/menu_builder_spec.rb +151 -0
- data/spec/adhearsion/call_controller/menu_dsl/menu_spec.rb +373 -0
- data/spec/adhearsion/call_controller/menu_dsl/range_match_calculator_spec.rb +32 -0
- data/spec/adhearsion/call_controller/menu_dsl/string_match_calculator_spec.rb +40 -0
- metadata +91 -91
- data/lib/adhearsion/menu_dsl.rb +0 -17
- data/lib/adhearsion/menu_dsl/calculated_match.rb +0 -41
- data/lib/adhearsion/menu_dsl/calculated_match_collection.rb +0 -43
- data/lib/adhearsion/menu_dsl/fixnum_match_calculator.rb +0 -20
- data/lib/adhearsion/menu_dsl/match_calculator.rb +0 -38
- data/lib/adhearsion/menu_dsl/menu.rb +0 -201
- data/lib/adhearsion/menu_dsl/menu_builder.rb +0 -82
- data/lib/adhearsion/menu_dsl/range_match_calculator.rb +0 -58
- data/lib/adhearsion/menu_dsl/string_match_calculator.rb +0 -23
- data/spec/adhearsion/menu_dsl/calculated_match_collection_spec.rb +0 -58
- data/spec/adhearsion/menu_dsl/calculated_match_spec.rb +0 -59
- data/spec/adhearsion/menu_dsl/fixnum_match_calculator_spec.rb +0 -35
- data/spec/adhearsion/menu_dsl/match_calculator_spec.rb +0 -15
- data/spec/adhearsion/menu_dsl/menu_builder_spec.rb +0 -149
- data/spec/adhearsion/menu_dsl/menu_spec.rb +0 -371
- data/spec/adhearsion/menu_dsl/range_match_calculator_spec.rb +0 -30
- data/spec/adhearsion/menu_dsl/string_match_calculator_spec.rb +0 -38
data/lib/adhearsion/menu_dsl.rb
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
module Adhearsion
|
4
|
-
module MenuDSL
|
5
|
-
extend ActiveSupport::Autoload
|
6
|
-
|
7
|
-
autoload :Exceptions
|
8
|
-
autoload :CalculatedMatch
|
9
|
-
autoload :CalculatedMatchCollection
|
10
|
-
autoload :MatchCalculator
|
11
|
-
autoload :FixnumMatchCalculator
|
12
|
-
autoload :RangeMatchCalculator
|
13
|
-
autoload :StringMatchCalculator
|
14
|
-
autoload :MenuBuilder
|
15
|
-
autoload :Menu
|
16
|
-
end
|
17
|
-
end
|
@@ -1,41 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
module Adhearsion
|
4
|
-
module MenuDSL
|
5
|
-
class CalculatedMatch
|
6
|
-
|
7
|
-
def self.failed_match!(pattern, query, match_payload)
|
8
|
-
new :pattern => pattern, :query => query, :match_payload => match_payload
|
9
|
-
end
|
10
|
-
|
11
|
-
attr_reader :match_payload, :potential_matches, :exact_matches, :pattern, :query, :block
|
12
|
-
|
13
|
-
def initialize(options = {})
|
14
|
-
@pattern, @query, @match_payload, @block = options.values_at :pattern, :query, :match_payload, :block
|
15
|
-
@potential_matches = options[:potential_matches] ? Array(options[:potential_matches]) : []
|
16
|
-
@exact_matches = options[:exact_matches] ? Array(options[:exact_matches]) : []
|
17
|
-
end
|
18
|
-
|
19
|
-
def exact_match?
|
20
|
-
exact_matches.any?
|
21
|
-
end
|
22
|
-
|
23
|
-
def potential_match?
|
24
|
-
potential_matches.any?
|
25
|
-
end
|
26
|
-
|
27
|
-
def failed_match?
|
28
|
-
!(potential_match? || exact_match?)
|
29
|
-
end
|
30
|
-
|
31
|
-
def type_of_match
|
32
|
-
if exact_match?
|
33
|
-
:exact
|
34
|
-
elsif potential_match?
|
35
|
-
:potential
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
@@ -1,43 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
module Adhearsion
|
4
|
-
module MenuDSL
|
5
|
-
class CalculatedMatchCollection
|
6
|
-
attr_reader :calculated_matches, :potential_matches, :exact_matches,
|
7
|
-
:actual_potential_matches, :actual_exact_matches
|
8
|
-
|
9
|
-
def initialize
|
10
|
-
@calculated_matches = []
|
11
|
-
@potential_matches = []
|
12
|
-
@exact_matches = []
|
13
|
-
@actual_potential_matches = []
|
14
|
-
@actual_exact_matches = []
|
15
|
-
end
|
16
|
-
|
17
|
-
def <<(calculated_match)
|
18
|
-
calculated_matches << calculated_match
|
19
|
-
actual_potential_matches.concat calculated_match.potential_matches
|
20
|
-
actual_exact_matches.concat calculated_match.exact_matches
|
21
|
-
|
22
|
-
potential_matches << calculated_match if calculated_match.potential_match?
|
23
|
-
exact_matches << calculated_match if calculated_match.exact_match?
|
24
|
-
end
|
25
|
-
|
26
|
-
def potential_match_count
|
27
|
-
actual_potential_matches.size
|
28
|
-
end
|
29
|
-
|
30
|
-
def exact_match_count
|
31
|
-
actual_exact_matches.size
|
32
|
-
end
|
33
|
-
|
34
|
-
def potential_match?
|
35
|
-
potential_match_count > 0
|
36
|
-
end
|
37
|
-
|
38
|
-
def exact_match?
|
39
|
-
exact_match_count > 0
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
@@ -1,20 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
module Adhearsion
|
4
|
-
module MenuDSL
|
5
|
-
class FixnumMatchCalculator < MatchCalculator
|
6
|
-
|
7
|
-
def match(query)
|
8
|
-
numeric_query = coerce_to_numeric query
|
9
|
-
exact_match, potential_match = nil
|
10
|
-
if pattern == numeric_query
|
11
|
-
exact_match = pattern
|
12
|
-
elsif pattern.to_s.starts_with? query.to_s
|
13
|
-
potential_match = pattern
|
14
|
-
end
|
15
|
-
new_calculated_match :query => query, :exact_matches => exact_match, :potential_matches => potential_match
|
16
|
-
end
|
17
|
-
|
18
|
-
end # class FixnumMatchCalculator
|
19
|
-
end
|
20
|
-
end
|
@@ -1,38 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
module Adhearsion
|
4
|
-
module MenuDSL
|
5
|
-
class MatchCalculator
|
6
|
-
|
7
|
-
class << self
|
8
|
-
|
9
|
-
def build_with_pattern(pattern, match_payload, &block)
|
10
|
-
class_for_pattern(pattern).new pattern, match_payload, &block
|
11
|
-
end
|
12
|
-
|
13
|
-
private
|
14
|
-
|
15
|
-
def class_for_pattern(pattern)
|
16
|
-
MenuDSL.const_get "#{pattern.class.name.camelize}MatchCalculator"
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
attr_reader :pattern, :match_payload, :block
|
21
|
-
|
22
|
-
def initialize(pattern, match_payload, &block)
|
23
|
-
@pattern, @match_payload, @block = pattern, match_payload, block
|
24
|
-
end
|
25
|
-
|
26
|
-
protected
|
27
|
-
|
28
|
-
def new_calculated_match(options)
|
29
|
-
CalculatedMatch.new({:pattern => pattern, :match_payload => match_payload, :block => block}.merge(options))
|
30
|
-
end
|
31
|
-
|
32
|
-
def coerce_to_numeric(victim)
|
33
|
-
victim.kind_of?(Numeric) ? victim : (victim.to_s =~ /^\d+$/ ? victim.to_s.to_i : nil )
|
34
|
-
end
|
35
|
-
|
36
|
-
end # class MatchCalculator
|
37
|
-
end
|
38
|
-
end
|
@@ -1,201 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
module Adhearsion
|
4
|
-
module MenuDSL
|
5
|
-
|
6
|
-
class Menu
|
7
|
-
|
8
|
-
DEFAULT_MAX_NUMBER_OF_TRIES = 1
|
9
|
-
DEFAULT_TIMEOUT = 5
|
10
|
-
|
11
|
-
InvalidStructureError = Class.new Adhearsion::Error
|
12
|
-
|
13
|
-
attr_reader :builder, :timeout, :tries_count, :max_number_of_tries, :terminator, :limit, :interruptible, :status
|
14
|
-
|
15
|
-
def initialize(options = {}, &block)
|
16
|
-
@tries_count = 0 # Counts the number of tries the menu's been executed
|
17
|
-
@timeout = options[:timeout] || DEFAULT_TIMEOUT
|
18
|
-
@max_number_of_tries = options[:tries] || DEFAULT_MAX_NUMBER_OF_TRIES
|
19
|
-
@terminator = options[:terminator].to_s
|
20
|
-
@limit = options[:limit]
|
21
|
-
@interruptible = options.has_key?(:interruptible) ? options[:interruptible] : true
|
22
|
-
@builder = MenuDSL::MenuBuilder.new
|
23
|
-
@terminated = false
|
24
|
-
|
25
|
-
@builder.build(&block) if block
|
26
|
-
|
27
|
-
initialize_digit_buffer
|
28
|
-
end
|
29
|
-
|
30
|
-
def validate(mode = nil)
|
31
|
-
case mode
|
32
|
-
when :basic
|
33
|
-
@terminator.present? || !!@limit || raise(InvalidStructureError, "You must specify at least one of limit or terminator")
|
34
|
-
else
|
35
|
-
@builder.has_matchers? || raise(InvalidStructureError, "You must specify one or more matchers")
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def <<(other)
|
40
|
-
if other == terminator
|
41
|
-
@terminated = true
|
42
|
-
else
|
43
|
-
digit_buffer << other
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
def digit_buffer
|
48
|
-
@digit_buffer
|
49
|
-
end
|
50
|
-
|
51
|
-
def digit_buffer_string
|
52
|
-
digit_buffer.to_s
|
53
|
-
end
|
54
|
-
alias :result :digit_buffer_string
|
55
|
-
|
56
|
-
def digit_buffer_empty?
|
57
|
-
digit_buffer.empty?
|
58
|
-
end
|
59
|
-
|
60
|
-
def continue
|
61
|
-
return get_another_digit_or_timeout! if digit_buffer_empty?
|
62
|
-
|
63
|
-
return menu_terminated! if @terminated
|
64
|
-
return menu_limit_reached! if limit && digit_buffer.size >= limit
|
65
|
-
|
66
|
-
return menu_validator_terminated! if execute_validator_hook
|
67
|
-
|
68
|
-
calculated_matches = builder.calculate_matches_for digit_buffer_string
|
69
|
-
|
70
|
-
if calculated_matches.exact_match_count >= 1
|
71
|
-
first_exact_match = calculated_matches.exact_matches.first
|
72
|
-
if calculated_matches.potential_match_count.zero?
|
73
|
-
menu_result_found! first_exact_match, digit_buffer_string
|
74
|
-
else
|
75
|
-
get_another_digit_or_finish! first_exact_match.match_payload, first_exact_match.query
|
76
|
-
end
|
77
|
-
elsif calculated_matches.potential_match_count >= 1 || !@builder.has_matchers?
|
78
|
-
get_another_digit_or_timeout!
|
79
|
-
else
|
80
|
-
invalid!
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
def should_continue?
|
85
|
-
tries_count < max_number_of_tries
|
86
|
-
end
|
87
|
-
|
88
|
-
def restart!
|
89
|
-
@tries_count += 1
|
90
|
-
digit_buffer.clear!
|
91
|
-
end
|
92
|
-
|
93
|
-
def execute_invalid_hook
|
94
|
-
builder.execute_hook_for :invalid, digit_buffer_string
|
95
|
-
end
|
96
|
-
|
97
|
-
def execute_timeout_hook
|
98
|
-
builder.execute_hook_for :timeout, digit_buffer_string
|
99
|
-
end
|
100
|
-
|
101
|
-
def execute_failure_hook
|
102
|
-
builder.execute_hook_for :failure, digit_buffer_string
|
103
|
-
end
|
104
|
-
|
105
|
-
def execute_validator_hook
|
106
|
-
builder.execute_hook_for :validator, digit_buffer_string
|
107
|
-
end
|
108
|
-
|
109
|
-
protected
|
110
|
-
|
111
|
-
# If you're using a more complex class in subclasses, you may want to override this method in addition to the
|
112
|
-
# digit buffer, digit_buffer_empty, and digit_buffer_string methods
|
113
|
-
def initialize_digit_buffer
|
114
|
-
@digit_buffer = ClearableStringBuffer.new
|
115
|
-
end
|
116
|
-
|
117
|
-
def invalid!
|
118
|
-
@status = :invalid
|
119
|
-
MenuResultInvalid.new
|
120
|
-
end
|
121
|
-
|
122
|
-
def menu_result_found!(match_object, new_extension)
|
123
|
-
@status = :matched
|
124
|
-
MenuResultFound.new(match_object, new_extension)
|
125
|
-
end
|
126
|
-
|
127
|
-
def menu_terminated!
|
128
|
-
@status = :terminated
|
129
|
-
MenuTerminated.new
|
130
|
-
end
|
131
|
-
|
132
|
-
def menu_validator_terminated!
|
133
|
-
@status = :validator_terminated
|
134
|
-
MenuValidatorTerminated.new
|
135
|
-
end
|
136
|
-
|
137
|
-
def menu_limit_reached!
|
138
|
-
@status = :limited
|
139
|
-
MenuLimitReached.new
|
140
|
-
end
|
141
|
-
|
142
|
-
def get_another_digit_or_finish!(match_payload, new_extension)
|
143
|
-
@status = :multi_matched
|
144
|
-
MenuGetAnotherDigitOrFinish.new(match_payload, new_extension)
|
145
|
-
end
|
146
|
-
|
147
|
-
def get_another_digit_or_timeout!
|
148
|
-
@status = :potential
|
149
|
-
MenuGetAnotherDigitOrTimeout.new
|
150
|
-
end
|
151
|
-
|
152
|
-
# The superclass from which all message-like exceptions descend. It should never
|
153
|
-
# be instantiated directly.
|
154
|
-
MenuResult = Class.new
|
155
|
-
MenuResultDone = Class.new MenuResult
|
156
|
-
|
157
|
-
class MenuResultFound < MenuResult
|
158
|
-
|
159
|
-
attr_reader :match_object, :new_extension
|
160
|
-
|
161
|
-
def initialize(match_object, new_extension)
|
162
|
-
super()
|
163
|
-
@match_object = match_object
|
164
|
-
@new_extension = new_extension
|
165
|
-
end
|
166
|
-
|
167
|
-
end #class MenuResultFound < MenuResult
|
168
|
-
|
169
|
-
MenuGetAnotherDigit = Module.new
|
170
|
-
|
171
|
-
class MenuGetAnotherDigitOrFinish < MenuResultFound
|
172
|
-
include MenuGetAnotherDigit
|
173
|
-
end
|
174
|
-
|
175
|
-
class MenuGetAnotherDigitOrTimeout < MenuResult
|
176
|
-
include MenuGetAnotherDigit
|
177
|
-
end
|
178
|
-
|
179
|
-
MenuResultInvalid = Class.new MenuResult
|
180
|
-
|
181
|
-
MenuTerminated = Class.new MenuResultDone
|
182
|
-
MenuValidatorTerminated = Class.new MenuResultDone
|
183
|
-
MenuLimitReached = Class.new MenuResultDone
|
184
|
-
|
185
|
-
# For our default purpose, we need the digit_buffer to behave much like a normal String except that it should
|
186
|
-
# handle its own resetting (clearing)
|
187
|
-
class ClearableStringBuffer < String
|
188
|
-
def clear!
|
189
|
-
replace ""
|
190
|
-
end
|
191
|
-
|
192
|
-
def <<(other)
|
193
|
-
super other.to_s
|
194
|
-
end
|
195
|
-
end
|
196
|
-
|
197
|
-
|
198
|
-
end # class Menu
|
199
|
-
|
200
|
-
end
|
201
|
-
end
|
@@ -1,82 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
module Adhearsion
|
4
|
-
module MenuDSL
|
5
|
-
|
6
|
-
class MenuBuilder
|
7
|
-
|
8
|
-
attr_accessor :patterns, :menu_callbacks
|
9
|
-
|
10
|
-
def initialize
|
11
|
-
@patterns = []
|
12
|
-
@menu_callbacks = {}
|
13
|
-
@context = nil
|
14
|
-
end
|
15
|
-
|
16
|
-
def build(&block)
|
17
|
-
@context = eval "self", block.binding
|
18
|
-
instance_eval(&block)
|
19
|
-
end
|
20
|
-
|
21
|
-
def match(*args, &block)
|
22
|
-
payload = if block_given?
|
23
|
-
raise ArgumentError, "You cannot specify both a block and a controller name." if args.last.is_a? Class
|
24
|
-
nil
|
25
|
-
else
|
26
|
-
raise ArgumentError, "You need to provide a block or a controller name." unless args.last.is_a? Class
|
27
|
-
args.pop
|
28
|
-
end
|
29
|
-
|
30
|
-
raise ArgumentError, "You cannot call this method without patterns." if args.empty?
|
31
|
-
|
32
|
-
args.each do |pattern|
|
33
|
-
@patterns << MatchCalculator.build_with_pattern(pattern, payload, &block)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
def weighted_match_calculators
|
38
|
-
@patterns
|
39
|
-
end
|
40
|
-
|
41
|
-
def has_matchers?
|
42
|
-
@patterns.size > 0
|
43
|
-
end
|
44
|
-
|
45
|
-
def execute_hook_for(symbol, input)
|
46
|
-
callback = @menu_callbacks[symbol]
|
47
|
-
return unless callback
|
48
|
-
@context.instance_exec input, &callback
|
49
|
-
end
|
50
|
-
|
51
|
-
def invalid(&block)
|
52
|
-
raise LocalJumpError, "Must supply a block!" unless block_given?
|
53
|
-
@menu_callbacks[:invalid] = block
|
54
|
-
end
|
55
|
-
|
56
|
-
def timeout(&block)
|
57
|
-
raise LocalJumpError, "Must supply a block!" unless block_given?
|
58
|
-
@menu_callbacks[:timeout] = block
|
59
|
-
end
|
60
|
-
|
61
|
-
def failure(&block)
|
62
|
-
raise LocalJumpError, "Must supply a block!" unless block_given?
|
63
|
-
@menu_callbacks[:failure] = block
|
64
|
-
end
|
65
|
-
|
66
|
-
def validator(&block)
|
67
|
-
raise LocalJumpError, "Must supply a block!" unless block_given?
|
68
|
-
@menu_callbacks[:validator] = block
|
69
|
-
end
|
70
|
-
|
71
|
-
def calculate_matches_for(result)
|
72
|
-
CalculatedMatchCollection.new.tap do |collection|
|
73
|
-
weighted_match_calculators.each do |pattern|
|
74
|
-
collection << pattern.match(result)
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
end # class MenuBuilder
|
80
|
-
|
81
|
-
end
|
82
|
-
end
|