volt 0.6.5 → 0.7.0
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.
- checksums.yaml +4 -4
- data/Readme.md +47 -40
- data/VERSION +1 -1
- data/app/volt/controllers/notices_controller.rb +3 -3
- data/app/volt/tasks/live_query/data_store.rb +2 -2
- data/app/volt/tasks/live_query/live_query.rb +20 -20
- data/app/volt/tasks/live_query/live_query_pool.rb +6 -6
- data/app/volt/tasks/live_query/query_tracker.rb +15 -15
- data/app/volt/tasks/query_tasks.rb +13 -13
- data/app/volt/tasks/store_tasks.rb +7 -7
- data/app/volt/views/notices/index.html +17 -18
- data/lib/volt/assets/test.rb +2 -2
- data/lib/volt/benchmark/benchmark.rb +25 -23
- data/lib/volt/cli/asset_compile.rb +11 -0
- data/lib/volt/cli/new_gem.rb +16 -16
- data/lib/volt/cli.rb +14 -12
- data/lib/volt/console.rb +5 -6
- data/lib/volt/controllers/model_controller.rb +18 -18
- data/lib/volt/extra_core/array.rb +4 -4
- data/lib/volt/extra_core/hash.rb +3 -3
- data/lib/volt/extra_core/object.rb +6 -6
- data/lib/volt/extra_core/string.rb +6 -6
- data/lib/volt/extra_core/symbol.rb +5 -5
- data/lib/volt/extra_core/time.rb +4 -4
- data/lib/volt/extra_core/true_false.rb +6 -6
- data/lib/volt/extra_core/try.rb +9 -9
- data/lib/volt/models/array_model.rb +26 -26
- data/lib/volt/models/model.rb +35 -35
- data/lib/volt/models/model_hash_behaviour.rb +15 -15
- data/lib/volt/models/model_helpers.rb +8 -8
- data/lib/volt/models/model_wrapper.rb +6 -6
- data/lib/volt/models/persistors/array_store.rb +36 -36
- data/lib/volt/models/persistors/base.rb +6 -6
- data/lib/volt/models/persistors/flash.rb +5 -5
- data/lib/volt/models/persistors/model_identity_map.rb +2 -2
- data/lib/volt/models/persistors/model_store.rb +22 -22
- data/lib/volt/models/persistors/params.rb +3 -3
- data/lib/volt/models/persistors/query/query_listener.rb +14 -14
- data/lib/volt/models/persistors/query/query_listener_pool.rb +2 -2
- data/lib/volt/models/persistors/store.rb +8 -8
- data/lib/volt/models/persistors/store_factory.rb +2 -2
- data/lib/volt/models/url.rb +37 -37
- data/lib/volt/page/bindings/attribute_binding.rb +14 -14
- data/lib/volt/page/bindings/base_binding.rb +9 -9
- data/lib/volt/page/bindings/component_binding.rb +7 -7
- data/lib/volt/page/bindings/content_binding.rb +3 -3
- data/lib/volt/page/bindings/each_binding.rb +13 -13
- data/lib/volt/page/bindings/event_binding.rb +4 -4
- data/lib/volt/page/bindings/if_binding.rb +12 -12
- data/lib/volt/page/bindings/template_binding.rb +30 -30
- data/lib/volt/page/channel.rb +19 -19
- data/lib/volt/page/channel_stub.rb +6 -6
- data/lib/volt/page/document.rb +2 -2
- data/lib/volt/page/document_events.rb +4 -4
- data/lib/volt/page/draw_cycle.rb +3 -3
- data/lib/volt/page/memory_test.rb +6 -6
- data/lib/volt/page/page.rb +19 -19
- data/lib/volt/page/reactive_template.rb +9 -9
- data/lib/volt/page/sub_context.rb +5 -5
- data/lib/volt/page/targets/attribute_section.rb +9 -9
- data/lib/volt/page/targets/attribute_target.rb +3 -3
- data/lib/volt/page/targets/base_section.rb +2 -2
- data/lib/volt/page/targets/binding_document/component_node.rb +23 -23
- data/lib/volt/page/targets/binding_document/html_node.rb +2 -2
- data/lib/volt/page/targets/dom_section.rb +40 -38
- data/lib/volt/page/targets/dom_target.rb +2 -2
- data/lib/volt/page/tasks.rb +12 -12
- data/lib/volt/page/template_renderer.rb +4 -4
- data/lib/volt/page/url_tracker.rb +6 -6
- data/lib/volt/reactive/array_extensions.rb +2 -2
- data/lib/volt/reactive/destructive_methods.rb +5 -5
- data/lib/volt/reactive/event_chain.rb +25 -25
- data/lib/volt/reactive/events.rb +33 -33
- data/lib/volt/reactive/object_tracker.rb +21 -21
- data/lib/volt/reactive/object_tracking.rb +2 -2
- data/lib/volt/reactive/reactive_array.rb +57 -57
- data/lib/volt/reactive/reactive_tags.rb +16 -16
- data/lib/volt/reactive/reactive_value.rb +72 -72
- data/lib/volt/reactive/string_extensions.rb +3 -3
- data/lib/volt/router/routes.rb +22 -23
- data/lib/volt/server/component_handler.rb +5 -5
- data/lib/volt/server/component_templates.rb +14 -11
- data/lib/volt/server/html_parser/attribute_scope.rb +116 -0
- data/lib/volt/server/html_parser/each_scope.rb +18 -0
- data/lib/volt/server/html_parser/if_view_scope.rb +71 -0
- data/lib/volt/server/html_parser/sandlebars_parser.rb +219 -0
- data/lib/volt/server/html_parser/textarea_scope.rb +31 -0
- data/lib/volt/server/html_parser/view_handler.rb +82 -0
- data/lib/volt/server/html_parser/view_parser.rb +23 -0
- data/lib/volt/server/html_parser/view_scope.rb +145 -0
- data/lib/volt/server/rack/asset_files.rb +17 -17
- data/lib/volt/server/rack/component_paths.rb +18 -18
- data/lib/volt/server/rack/index_files.rb +8 -8
- data/lib/volt/server/rack/opal_files.rb +11 -11
- data/lib/volt/server/socket_connection_handler.rb +13 -13
- data/lib/volt/server/socket_connection_handler_stub.rb +2 -2
- data/lib/volt/server.rb +18 -18
- data/lib/volt/tasks/dispatcher.rb +5 -5
- data/lib/volt/utils/ejson.rb +2 -2
- data/lib/volt/utils/generic_counting_pool.rb +8 -8
- data/lib/volt/utils/generic_pool.rb +16 -16
- data/lib/volt/volt/environment.rb +4 -4
- data/lib/volt.rb +6 -6
- data/spec/integration/test_integration_spec.rb +2 -2
- data/spec/models/event_chain_spec.rb +38 -38
- data/spec/models/model_spec.rb +128 -128
- data/spec/models/old_model_spec.rb +17 -17
- data/spec/models/persistors/params_spec.rb +3 -3
- data/spec/models/persistors/store_spec.rb +7 -7
- data/spec/models/reactive_array_spec.rb +82 -82
- data/spec/models/reactive_generator_spec.rb +11 -11
- data/spec/models/reactive_tags_spec.rb +6 -6
- data/spec/models/reactive_value_spec.rb +70 -70
- data/spec/models/store_spec.rb +4 -4
- data/spec/models/string_extensions_spec.rb +13 -13
- data/spec/page/bindings/content_binding_spec.rb +6 -6
- data/spec/page/sub_context_spec.rb +1 -1
- data/spec/router/routes_spec.rb +3 -3
- data/spec/server/html_parser/sample_page.html +595 -0
- data/spec/server/html_parser/sandlebars_parser_spec.rb +192 -0
- data/spec/server/html_parser/view_parser_spec.rb +286 -0
- data/spec/server/rack/asset_files_spec.rb +6 -6
- data/spec/server/rack/component_paths_spec.rb +5 -5
- data/spec/spec_helper.rb +4 -5
- data/spec/store/mongo_spec.rb +3 -3
- data/spec/tasks/live_query_spec.rb +6 -6
- data/spec/tasks/query_tasks.rb +4 -4
- data/spec/tasks/query_tracker_spec.rb +20 -20
- data/spec/templates/targets/binding_document/component_node_spec.rb +4 -4
- data/spec/templates/template_binding_spec.rb +28 -28
- data/spec/utils/generic_counting_pool_spec.rb +5 -5
- data/spec/utils/generic_pool_spec.rb +14 -14
- data/templates/newgem/app/newgem/views/index/index.html +1 -2
- data/templates/project/app/home/config/dependencies.rb +1 -1
- data/templates/project/app/home/controllers/index_controller.rb +1 -1
- data/templates/project/app/home/views/index/about.html +4 -6
- data/templates/project/app/home/views/index/home.html +4 -5
- data/templates/project/app/home/views/index/index.html +8 -9
- data/templates/project/spec/spec_helper.rb +1 -1
- metadata +17 -8
- data/lib/volt/server/binding_setup.rb +0 -2
- data/lib/volt/server/if_binding_setup.rb +0 -31
- data/lib/volt/server/scope.rb +0 -43
- data/lib/volt/server/template_parser.rb +0 -453
- data/spec/server/template_parser_spec.rb +0 -50
|
@@ -3,20 +3,20 @@ require 'volt/reactive/object_tracking'
|
|
|
3
3
|
class ReactiveArray# < Array
|
|
4
4
|
include ReactiveTags
|
|
5
5
|
include ObjectTracking
|
|
6
|
-
|
|
6
|
+
|
|
7
7
|
def initialize(array=[])
|
|
8
8
|
@array = array
|
|
9
9
|
end
|
|
10
|
-
|
|
10
|
+
|
|
11
11
|
# Forward any missing methods to the array
|
|
12
12
|
def method_missing(method_name, *args, &block)
|
|
13
13
|
@array.send(method_name, *args, &block)
|
|
14
14
|
end
|
|
15
|
-
|
|
15
|
+
|
|
16
16
|
def ==(*args)
|
|
17
17
|
@array.==(*args)
|
|
18
18
|
end
|
|
19
|
-
|
|
19
|
+
|
|
20
20
|
tag_method(:each) do
|
|
21
21
|
destructive!
|
|
22
22
|
end
|
|
@@ -24,22 +24,22 @@ class ReactiveArray# < Array
|
|
|
24
24
|
def each(&block)
|
|
25
25
|
@array.each(&block)
|
|
26
26
|
end
|
|
27
|
-
|
|
27
|
+
|
|
28
28
|
tag_method(:[]=) do
|
|
29
29
|
pass_reactive!
|
|
30
30
|
end
|
|
31
|
-
|
|
31
|
+
|
|
32
32
|
# alias :__old_assign :[]=
|
|
33
|
-
def []=(index, value)
|
|
34
|
-
index_val = index.cur
|
|
33
|
+
def []=(index, value)
|
|
34
|
+
index_val = index.cur
|
|
35
35
|
# Clean old value
|
|
36
36
|
__clear_element(index)
|
|
37
|
-
|
|
37
|
+
|
|
38
38
|
@array[index.cur] = value
|
|
39
|
-
|
|
39
|
+
|
|
40
40
|
# Track new value
|
|
41
41
|
__track_element(index, value)
|
|
42
|
-
|
|
42
|
+
|
|
43
43
|
# Also track the index if its reactive
|
|
44
44
|
if index.reactive?
|
|
45
45
|
# TODO: Need to clean this up when the index changes
|
|
@@ -47,38 +47,38 @@ class ReactiveArray# < Array
|
|
|
47
47
|
trigger_for_index!(event, index.cur)
|
|
48
48
|
end
|
|
49
49
|
end
|
|
50
|
-
|
|
50
|
+
|
|
51
51
|
# Trigger changed
|
|
52
52
|
trigger_for_index!('changed', index_val)
|
|
53
53
|
end
|
|
54
|
-
|
|
54
|
+
|
|
55
55
|
tag_method(:delete_at) do
|
|
56
56
|
destructive!
|
|
57
57
|
end
|
|
58
58
|
# alias :__old_delete_at :delete_at
|
|
59
59
|
def delete_at(index)
|
|
60
60
|
index_val = index.cur
|
|
61
|
-
|
|
61
|
+
|
|
62
62
|
__clear_element(index)
|
|
63
|
-
|
|
63
|
+
|
|
64
64
|
model = @array.delete_at(index_val)
|
|
65
|
-
|
|
65
|
+
|
|
66
66
|
trigger_on_direct_listeners!('removed', index_val)
|
|
67
|
-
|
|
68
|
-
# Trigger a changed event for each element in the zone where the
|
|
67
|
+
|
|
68
|
+
# Trigger a changed event for each element in the zone where the
|
|
69
69
|
# lookup would change
|
|
70
70
|
index.upto(self.size+1) do |position|
|
|
71
71
|
trigger_for_index!('changed', position)
|
|
72
72
|
end
|
|
73
|
-
|
|
73
|
+
|
|
74
74
|
trigger_size_change!
|
|
75
|
-
|
|
75
|
+
|
|
76
76
|
@persistor.removed(model) if @persistor
|
|
77
|
-
|
|
77
|
+
|
|
78
78
|
return model
|
|
79
79
|
end
|
|
80
|
-
|
|
81
|
-
|
|
80
|
+
|
|
81
|
+
|
|
82
82
|
# Delete is implemented as part of delete_at
|
|
83
83
|
tag_method(:delete) do
|
|
84
84
|
destructive!
|
|
@@ -86,7 +86,7 @@ class ReactiveArray# < Array
|
|
|
86
86
|
def delete(val)
|
|
87
87
|
self.delete_at(@array.index(val))
|
|
88
88
|
end
|
|
89
|
-
|
|
89
|
+
|
|
90
90
|
# Removes all items in the array model.
|
|
91
91
|
tag_method(:clear) do
|
|
92
92
|
destructive!
|
|
@@ -102,35 +102,35 @@ class ReactiveArray# < Array
|
|
|
102
102
|
# alias :__old_append :<<
|
|
103
103
|
def <<(value)
|
|
104
104
|
result = (@array << value)
|
|
105
|
-
|
|
105
|
+
|
|
106
106
|
# Track new value
|
|
107
107
|
__track_element(self.size-1, value)
|
|
108
|
-
|
|
108
|
+
|
|
109
109
|
trigger_for_index!('changed', self.size-1)
|
|
110
110
|
trigger_on_direct_listeners!('added', self.size-1)
|
|
111
|
-
|
|
111
|
+
|
|
112
112
|
trigger_size_change!
|
|
113
113
|
|
|
114
114
|
return result
|
|
115
115
|
end
|
|
116
|
-
|
|
117
|
-
|
|
116
|
+
|
|
117
|
+
|
|
118
118
|
def +(array)
|
|
119
119
|
old_size = self.size
|
|
120
|
-
|
|
120
|
+
|
|
121
121
|
# TODO: += is funky here, might need to make a .plus! method
|
|
122
122
|
result = ReactiveArray.new(@array.dup + array)
|
|
123
|
-
|
|
123
|
+
|
|
124
124
|
old_size.upto(result.size-1) do |index|
|
|
125
125
|
trigger_for_index!('changed', index)
|
|
126
126
|
trigger_on_direct_listeners!('added', old_size + index)
|
|
127
127
|
end
|
|
128
|
-
|
|
128
|
+
|
|
129
129
|
trigger_size_change!
|
|
130
|
-
|
|
130
|
+
|
|
131
131
|
return result
|
|
132
132
|
end
|
|
133
|
-
|
|
133
|
+
|
|
134
134
|
tag_method(:insert) do
|
|
135
135
|
destructive!
|
|
136
136
|
end
|
|
@@ -145,37 +145,37 @@ class ReactiveArray# < Array
|
|
|
145
145
|
objects.size.times do |count|
|
|
146
146
|
trigger_on_direct_listeners!('added', index+count)
|
|
147
147
|
end
|
|
148
|
-
|
|
148
|
+
|
|
149
149
|
trigger_size_change!
|
|
150
|
-
|
|
150
|
+
|
|
151
151
|
return result
|
|
152
152
|
end
|
|
153
|
-
|
|
153
|
+
|
|
154
154
|
def trigger_on_direct_listeners!(event, *args)
|
|
155
155
|
trigger_by_scope!(event, *args) do |scope|
|
|
156
156
|
# Only if it is bound directly to us. Don't pass
|
|
157
157
|
# down the chain
|
|
158
158
|
!scope || scope[0] == nil
|
|
159
159
|
end
|
|
160
|
-
|
|
160
|
+
|
|
161
161
|
end
|
|
162
|
-
|
|
162
|
+
|
|
163
163
|
def trigger_size_change!
|
|
164
164
|
trigger_by_scope!('changed') do |scope|
|
|
165
165
|
# method_name, *args, block = scope
|
|
166
166
|
method_name, args, block = split_scope(scope)
|
|
167
|
-
|
|
167
|
+
|
|
168
168
|
result = case method_name && method_name.to_sym
|
|
169
169
|
when :size, :length
|
|
170
170
|
true
|
|
171
171
|
else
|
|
172
172
|
false
|
|
173
173
|
end
|
|
174
|
-
|
|
174
|
+
|
|
175
175
|
result
|
|
176
176
|
end
|
|
177
177
|
end
|
|
178
|
-
|
|
178
|
+
|
|
179
179
|
# TODO: This is an opal work around. Currently there is a bug with destructuring
|
|
180
180
|
# method_name, *args, block = scope
|
|
181
181
|
def split_scope(scope)
|
|
@@ -183,18 +183,18 @@ class ReactiveArray# < Array
|
|
|
183
183
|
scope = scope.dup
|
|
184
184
|
method_name = scope.shift
|
|
185
185
|
block = scope.pop
|
|
186
|
-
|
|
186
|
+
|
|
187
187
|
return method_name, scope, block
|
|
188
188
|
else
|
|
189
189
|
return nil,[],nil
|
|
190
190
|
end
|
|
191
191
|
end
|
|
192
|
-
|
|
193
|
-
# Trigger the changed event to any values fetched either through the
|
|
194
|
-
# lookup ([]), #last, or any fetched through the array its self. (sum, max, etc...)
|
|
192
|
+
|
|
193
|
+
# Trigger the changed event to any values fetched either through the
|
|
194
|
+
# lookup ([]), #last, or any fetched through the array its self. (sum, max, etc...)
|
|
195
195
|
# On an array, when an element is added or removed, we need to trigger change
|
|
196
196
|
# events on each method that does the following:
|
|
197
|
-
# 1. uses the whole array (max, sum, etc...)
|
|
197
|
+
# 1. uses the whole array (max, sum, etc...)
|
|
198
198
|
# 2. accesses this specific element - array[index]
|
|
199
199
|
# 3. accesses an element via a method (first, last)
|
|
200
200
|
def trigger_for_index!(event_name, index, *passed_args)
|
|
@@ -202,7 +202,7 @@ class ReactiveArray# < Array
|
|
|
202
202
|
# method_name, *args, block = scope
|
|
203
203
|
method_name, args, block = split_scope(scope)
|
|
204
204
|
# puts "SCOPE CHECK: TFI: #{method_name.inspect} - #{args.inspect} on #{self.inspect}"
|
|
205
|
-
|
|
205
|
+
|
|
206
206
|
result = case method_name
|
|
207
207
|
when nil
|
|
208
208
|
# no method name means the event was bound directly, we don't
|
|
@@ -211,7 +211,7 @@ class ReactiveArray# < Array
|
|
|
211
211
|
when :[]
|
|
212
212
|
# Extract the current index if its reactive
|
|
213
213
|
arg_index = args[0].cur
|
|
214
|
-
|
|
214
|
+
|
|
215
215
|
# TODO: we could handle negative indicies better
|
|
216
216
|
arg_index == index.cur || arg_index < 0
|
|
217
217
|
when :last
|
|
@@ -224,17 +224,17 @@ class ReactiveArray# < Array
|
|
|
224
224
|
else
|
|
225
225
|
true
|
|
226
226
|
end
|
|
227
|
-
|
|
227
|
+
|
|
228
228
|
result
|
|
229
229
|
end
|
|
230
|
-
end
|
|
231
|
-
|
|
230
|
+
end
|
|
231
|
+
|
|
232
232
|
def inspect
|
|
233
233
|
"#<#{self.class.to_s} #{@array.inspect}>"
|
|
234
234
|
end
|
|
235
|
-
|
|
235
|
+
|
|
236
236
|
private
|
|
237
|
-
|
|
237
|
+
|
|
238
238
|
def __clear_element(index)
|
|
239
239
|
# Cleanup any tracking on an index
|
|
240
240
|
if @reactive_element_listeners && self[index].reactive?
|
|
@@ -242,11 +242,11 @@ class ReactiveArray# < Array
|
|
|
242
242
|
@reactive_element_listeners.delete(index)
|
|
243
243
|
end
|
|
244
244
|
end
|
|
245
|
-
|
|
245
|
+
|
|
246
246
|
def __track_element(index, value)
|
|
247
247
|
__setup_tracking(index, value) do |event, index, args|
|
|
248
248
|
trigger_for_index!(event, index, *args)
|
|
249
249
|
end
|
|
250
250
|
end
|
|
251
|
-
|
|
252
|
-
end
|
|
251
|
+
|
|
252
|
+
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
require 'volt/reactive/destructive_methods'
|
|
2
2
|
|
|
3
|
-
# ReactiveTags provide an easy way to specify how a class deals with
|
|
3
|
+
# ReactiveTags provide an easy way to specify how a class deals with
|
|
4
4
|
# reactive events and method calls.als
|
|
5
5
|
module ReactiveTags
|
|
6
6
|
class MethodTags
|
|
@@ -9,40 +9,40 @@ module ReactiveTags
|
|
|
9
9
|
|
|
10
10
|
class MethodTagger
|
|
11
11
|
attr_reader :method_tags
|
|
12
|
-
|
|
12
|
+
|
|
13
13
|
def initialize
|
|
14
14
|
@method_tags = MethodTags.new
|
|
15
15
|
end
|
|
16
|
-
|
|
16
|
+
|
|
17
17
|
def destructive!(&block)
|
|
18
18
|
@method_tags.destructive = block || true
|
|
19
19
|
end
|
|
20
|
-
|
|
20
|
+
|
|
21
21
|
def pass_reactive!
|
|
22
22
|
@method_tags.pass_reactive = true
|
|
23
23
|
end
|
|
24
24
|
end
|
|
25
|
-
|
|
26
|
-
module ClassMethods
|
|
25
|
+
|
|
26
|
+
module ClassMethods
|
|
27
27
|
def tag_method(method_name, &block)
|
|
28
28
|
tagger = MethodTagger.new
|
|
29
|
-
|
|
29
|
+
|
|
30
30
|
tagger.instance_eval(&block)
|
|
31
|
-
|
|
31
|
+
|
|
32
32
|
@reactive_method_tags ||= {}
|
|
33
33
|
@reactive_method_tags[method_name.to_sym] = tagger.method_tags
|
|
34
|
-
|
|
34
|
+
|
|
35
35
|
# Track a destructive method
|
|
36
36
|
if tagger.method_tags.destructive
|
|
37
37
|
DestructiveMethods.add_method(method_name)
|
|
38
38
|
end
|
|
39
39
|
end
|
|
40
|
-
|
|
40
|
+
|
|
41
41
|
def tag_all_methods(&block)
|
|
42
42
|
tagger = MethodTagger.new
|
|
43
|
-
|
|
43
|
+
|
|
44
44
|
tagger.instance_eval(&block)
|
|
45
|
-
|
|
45
|
+
|
|
46
46
|
@reactive_method_tags ||= {}
|
|
47
47
|
@reactive_method_tags[:__all_methods] = tagger.method_tags
|
|
48
48
|
end
|
|
@@ -53,19 +53,19 @@ module ReactiveTags
|
|
|
53
53
|
# Check to make sure we haven't gone above a class that has included
|
|
54
54
|
# ReactiveTags
|
|
55
55
|
return nil if !klass || !klass.method_defined?(:reactive_method_tag)
|
|
56
|
-
|
|
56
|
+
|
|
57
57
|
tags = klass.instance_variable_get('@reactive_method_tags')
|
|
58
58
|
|
|
59
59
|
if tags && (tag = tags[method_name.to_sym]) && (tag = tag.send(tag_name))
|
|
60
60
|
return tag
|
|
61
61
|
end
|
|
62
|
-
|
|
62
|
+
|
|
63
63
|
return self.reactive_method_tag(method_name, tag_name, klass.superclass)
|
|
64
64
|
end
|
|
65
|
-
|
|
65
|
+
|
|
66
66
|
|
|
67
67
|
def self.included(base)
|
|
68
68
|
base.send(:extend, ClassMethods)
|
|
69
69
|
base.send(:include, Events)
|
|
70
70
|
end
|
|
71
|
-
end
|
|
71
|
+
end
|