gloo 0.3.0 → 0.4.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/.rubocop.yml +73 -0
- data/Gemfile +2 -2
- data/Gemfile.lock +3 -3
- data/Rakefile +6 -6
- data/bin/console +4 -4
- data/gloo.gemspec +19 -18
- data/lib/gloo.rb +6 -6
- data/lib/gloo/app/args.rb +30 -31
- data/lib/gloo/app/engine.rb +33 -28
- data/lib/gloo/app/help.rb +17 -11
- data/lib/gloo/app/info.rb +3 -3
- data/lib/gloo/app/log.rb +17 -17
- data/lib/gloo/app/mode.rb +4 -4
- data/lib/gloo/app/settings.rb +43 -40
- data/lib/gloo/core/baseo.rb +7 -7
- data/lib/gloo/core/dictionary.rb +30 -27
- data/lib/gloo/core/error.rb +50 -0
- data/lib/gloo/core/event_manager.rb +17 -19
- data/lib/gloo/core/factory.rb +92 -39
- data/lib/gloo/core/gloo_system.rb +49 -54
- data/lib/gloo/core/heap.rb +15 -13
- data/lib/gloo/core/it.rb +5 -5
- data/lib/gloo/core/literal.rb +7 -7
- data/lib/gloo/core/obj.rb +89 -79
- data/lib/gloo/core/obj_finder.rb +9 -14
- data/lib/gloo/core/op.rb +8 -8
- data/lib/gloo/core/parser.rb +25 -26
- data/lib/gloo/core/pn.rb +65 -50
- data/lib/gloo/core/runner.rb +26 -0
- data/lib/gloo/core/script.rb +7 -7
- data/lib/gloo/core/tokens.rb +39 -41
- data/lib/gloo/core/verb.rb +30 -19
- data/lib/gloo/expr/expression.rb +35 -43
- data/lib/gloo/expr/l_boolean.rb +7 -6
- data/lib/gloo/expr/l_integer.rb +5 -4
- data/lib/gloo/expr/l_string.rb +13 -15
- data/lib/gloo/expr/op_div.rb +3 -5
- data/lib/gloo/expr/op_minus.rb +3 -5
- data/lib/gloo/expr/op_mult.rb +3 -5
- data/lib/gloo/expr/op_plus.rb +5 -7
- data/lib/gloo/objs/basic/boolean.rb +63 -38
- data/lib/gloo/objs/basic/container.rb +40 -12
- data/lib/gloo/objs/basic/integer.rb +40 -16
- data/lib/gloo/objs/basic/script.rb +62 -38
- data/lib/gloo/objs/basic/string.rb +39 -15
- data/lib/gloo/objs/basic/text.rb +43 -20
- data/lib/gloo/objs/basic/untyped.rb +35 -10
- data/lib/gloo/objs/cli/colorize.rb +53 -23
- data/lib/gloo/objs/cli/confirm.rb +63 -29
- data/lib/gloo/objs/cli/prompt.rb +63 -29
- data/lib/gloo/objs/ctrl/each.rb +98 -60
- data/lib/gloo/objs/dev/git.rb +98 -64
- data/lib/gloo/objs/ror/erb.rb +81 -41
- data/lib/gloo/objs/ror/eval.rb +73 -31
- data/lib/gloo/objs/snd/play.rb +71 -0
- data/lib/gloo/objs/snd/say.rb +120 -0
- data/lib/gloo/objs/system/file_handle.rb +80 -48
- data/lib/gloo/objs/system/system.rb +84 -38
- data/lib/gloo/objs/web/http_get.rb +83 -46
- data/lib/gloo/objs/web/http_post.rb +69 -43
- data/lib/gloo/objs/web/slack.rb +89 -58
- data/lib/gloo/objs/web/teams.rb +88 -53
- data/lib/gloo/persist/file_loader.rb +81 -82
- data/lib/gloo/persist/file_saver.rb +12 -12
- data/lib/gloo/persist/file_storage.rb +15 -15
- data/lib/gloo/persist/line_splitter.rb +74 -0
- data/lib/gloo/persist/persist_man.rb +29 -29
- data/lib/gloo/utils/words.rb +2 -2
- data/lib/gloo/verbs/alert.rb +67 -16
- data/lib/gloo/verbs/beep.rb +70 -0
- data/lib/gloo/verbs/context.rb +61 -21
- data/lib/gloo/verbs/create.rb +52 -21
- data/lib/gloo/verbs/help.rb +177 -27
- data/lib/gloo/verbs/if.rb +54 -21
- data/lib/gloo/verbs/list.rb +55 -24
- data/lib/gloo/verbs/load.rb +46 -12
- data/lib/gloo/verbs/put.rb +90 -34
- data/lib/gloo/verbs/quit.rb +43 -12
- data/lib/gloo/verbs/run.rb +42 -11
- data/lib/gloo/verbs/save.rb +45 -10
- data/lib/gloo/verbs/show.rb +56 -22
- data/lib/gloo/verbs/tell.rb +44 -12
- data/lib/gloo/verbs/unless.rb +55 -21
- data/lib/gloo/verbs/version.rb +42 -12
- data/lib/run.rb +5 -5
- metadata +19 -12
@@ -1,84 +1,116 @@
|
|
1
1
|
# Author:: Eric Crane (mailto:eric.crane@mac.com)
|
2
2
|
# Copyright:: Copyright (c) 2019 Eric Crane. All rights reserved.
|
3
3
|
#
|
4
|
-
# An object that
|
4
|
+
# An object that points to a file in the system.
|
5
5
|
#
|
6
6
|
|
7
7
|
module Gloo
|
8
8
|
module Objs
|
9
9
|
class FileHandle < Gloo::Core::Obj
|
10
|
-
|
11
|
-
KEYWORD = 'file'
|
12
|
-
KEYWORD_SHORT = 'dir'
|
13
10
|
|
14
|
-
|
11
|
+
KEYWORD = 'file'.freeze
|
12
|
+
KEYWORD_SHORT = 'dir'.freeze
|
13
|
+
|
14
|
+
#
|
15
15
|
# The name of the object type.
|
16
|
-
#
|
16
|
+
#
|
17
17
|
def self.typename
|
18
18
|
return KEYWORD
|
19
19
|
end
|
20
20
|
|
21
|
-
#
|
21
|
+
#
|
22
22
|
# The short name of the object type.
|
23
|
-
#
|
23
|
+
#
|
24
24
|
def self.short_typename
|
25
25
|
return KEYWORD_SHORT
|
26
26
|
end
|
27
|
-
|
28
|
-
|
27
|
+
|
29
28
|
# ---------------------------------------------------------------------
|
30
29
|
# Messages
|
31
30
|
# ---------------------------------------------------------------------
|
32
31
|
|
33
|
-
#
|
32
|
+
#
|
34
33
|
# Get a list of message names that this object receives.
|
35
|
-
#
|
34
|
+
#
|
36
35
|
def self.messages
|
37
|
-
return super + [
|
38
|
-
|
36
|
+
return super + %w[read write check_exists check_is_file check_is_dir]
|
37
|
+
end
|
38
|
+
|
39
|
+
def msg_read
|
40
|
+
return unless value && File.file?( value )
|
41
|
+
|
42
|
+
data = File.read( value )
|
43
|
+
if @params&.token_count&.positive?
|
44
|
+
pn = Gloo::Core::Pn.new @params.first
|
45
|
+
o = pn.resolve
|
46
|
+
o.set_value data
|
47
|
+
else
|
48
|
+
$engine.heap.it.set_to data
|
49
|
+
end
|
39
50
|
end
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
def msg_write
|
56
|
-
data = ""
|
57
|
-
if value
|
58
|
-
if @params && @params.token_count > 0
|
59
|
-
expr = Gloo::Expr::Expression.new( @params.tokens )
|
60
|
-
data = expr.evaluate
|
61
|
-
end
|
62
|
-
File.write( value, data )
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
51
|
+
|
52
|
+
def msg_write
|
53
|
+
data = ''
|
54
|
+
return unless value
|
55
|
+
|
56
|
+
if @params&.token_count&.positive?
|
57
|
+
expr = Gloo::Expr::Expression.new( @params.tokens )
|
58
|
+
data = expr.evaluate
|
59
|
+
end
|
60
|
+
File.write( value, data )
|
61
|
+
end
|
62
|
+
|
66
63
|
# Check to see if the file exists.
|
67
64
|
def msg_check_exists
|
68
|
-
|
69
|
-
|
65
|
+
result = File.exist? value
|
66
|
+
$engine.heap.it.set_to result
|
70
67
|
end
|
71
68
|
|
72
|
-
|
69
|
+
# Check to see if the file is a file.
|
73
70
|
def msg_check_is_file
|
74
|
-
|
75
|
-
|
71
|
+
result = File.file? value
|
72
|
+
$engine.heap.it.set_to result
|
76
73
|
end
|
77
74
|
|
78
|
-
|
75
|
+
# Check to see if the file is a directory.
|
79
76
|
def msg_check_is_dir
|
80
|
-
|
81
|
-
|
77
|
+
result = File.directory? value
|
78
|
+
$engine.heap.it.set_to result
|
79
|
+
end
|
80
|
+
|
81
|
+
# ---------------------------------------------------------------------
|
82
|
+
# Help
|
83
|
+
# ---------------------------------------------------------------------
|
84
|
+
|
85
|
+
#
|
86
|
+
# Get help for this object type.
|
87
|
+
#
|
88
|
+
def self.help
|
89
|
+
return <<~TEXT
|
90
|
+
FILE OBJECT TYPE
|
91
|
+
NAME: file
|
92
|
+
SHORTCUT: dir
|
93
|
+
|
94
|
+
DESCRIPTION
|
95
|
+
Reference to a file or folder (directory) on disk.
|
96
|
+
The string value of the file object is the path and name
|
97
|
+
of the file.
|
98
|
+
|
99
|
+
CHILDREN
|
100
|
+
None.
|
101
|
+
|
102
|
+
MESSAGES
|
103
|
+
read <into.obj> - Read file and put data in the specified object.
|
104
|
+
If the <into.obj> is not specified, the data will be in <it>.
|
105
|
+
write <from.obj> - Write the data in the <from.object> into
|
106
|
+
the file.
|
107
|
+
check_exists - Check to see if the file exists.
|
108
|
+
<It> will be true or false.
|
109
|
+
check_is_file - Check to see if the file specified is a
|
110
|
+
regular file. <It> will be true or false.
|
111
|
+
check_is_dir - Check to see if the file specified is a
|
112
|
+
diretory. <It> will be true or false.
|
113
|
+
TEXT
|
82
114
|
end
|
83
115
|
|
84
116
|
end
|
@@ -7,57 +7,59 @@
|
|
7
7
|
module Gloo
|
8
8
|
module Objs
|
9
9
|
class System < Gloo::Core::Obj
|
10
|
-
|
11
|
-
KEYWORD = 'system'
|
12
|
-
KEYWORD_SHORT = 'sys'
|
13
|
-
CMD = 'command'
|
14
|
-
RESULT = 'result'
|
15
|
-
GET_OUTPUT = 'get_output'
|
16
|
-
|
17
|
-
#
|
10
|
+
|
11
|
+
KEYWORD = 'system'.freeze
|
12
|
+
KEYWORD_SHORT = 'sys'.freeze
|
13
|
+
CMD = 'command'.freeze
|
14
|
+
RESULT = 'result'.freeze
|
15
|
+
GET_OUTPUT = 'get_output'.freeze
|
16
|
+
|
17
|
+
#
|
18
18
|
# The name of the object type.
|
19
|
-
#
|
19
|
+
#
|
20
20
|
def self.typename
|
21
21
|
return KEYWORD
|
22
22
|
end
|
23
23
|
|
24
|
-
#
|
24
|
+
#
|
25
25
|
# The short name of the object type.
|
26
|
-
#
|
26
|
+
#
|
27
27
|
def self.short_typename
|
28
28
|
return KEYWORD_SHORT
|
29
29
|
end
|
30
|
-
|
31
|
-
#
|
30
|
+
|
31
|
+
#
|
32
32
|
# Get the URI from the child object.
|
33
33
|
# Returns nil if there is none.
|
34
|
-
#
|
35
|
-
def
|
34
|
+
#
|
35
|
+
def cmd_value
|
36
36
|
cmd = find_child CMD
|
37
37
|
return nil unless cmd
|
38
|
+
|
38
39
|
return cmd.value
|
39
40
|
end
|
40
|
-
|
41
|
-
#
|
41
|
+
|
42
|
+
#
|
42
43
|
# Set the result of the system call.
|
43
|
-
#
|
44
|
-
def set_result data
|
44
|
+
#
|
45
|
+
def set_result( data )
|
45
46
|
r = find_child RESULT
|
46
47
|
return nil unless r
|
48
|
+
|
47
49
|
r.set_value data
|
48
50
|
end
|
49
|
-
|
50
|
-
#
|
51
|
+
|
52
|
+
#
|
51
53
|
# Should the system call get output?
|
52
54
|
# If so, the system call will run and get output,
|
53
55
|
# otherwise it will just get the result of the call.
|
54
|
-
#
|
55
|
-
def
|
56
|
+
#
|
57
|
+
def output?
|
56
58
|
o = find_child GET_OUTPUT
|
57
59
|
return false unless o
|
60
|
+
|
58
61
|
return o.value
|
59
62
|
end
|
60
|
-
|
61
63
|
|
62
64
|
# ---------------------------------------------------------------------
|
63
65
|
# Children
|
@@ -69,52 +71,96 @@ module Gloo
|
|
69
71
|
def add_children_on_create?
|
70
72
|
return true
|
71
73
|
end
|
72
|
-
|
74
|
+
|
73
75
|
# Add children to this object.
|
74
|
-
# This is used by containers to add children needed
|
76
|
+
# This is used by containers to add children needed
|
75
77
|
# for default configurations.
|
76
78
|
def add_default_children
|
77
79
|
fac = $engine.factory
|
78
|
-
fac.create
|
79
|
-
|
80
|
-
|
80
|
+
fac.create( { :name => 'command',
|
81
|
+
:type => 'string',
|
82
|
+
:value => 'date',
|
83
|
+
:parent => self } )
|
84
|
+
fac.create( { :name => 'get_output',
|
85
|
+
:type => 'boolean',
|
86
|
+
:value => true,
|
87
|
+
:parent => self } )
|
88
|
+
fac.create( { :name => 'result',
|
89
|
+
:type => 'string',
|
90
|
+
:value => nil,
|
91
|
+
:parent => self } )
|
81
92
|
end
|
82
93
|
|
83
|
-
|
84
94
|
# ---------------------------------------------------------------------
|
85
95
|
# Messages
|
86
96
|
# ---------------------------------------------------------------------
|
87
97
|
|
88
|
-
#
|
98
|
+
#
|
89
99
|
# Get a list of message names that this object receives.
|
90
|
-
#
|
100
|
+
#
|
91
101
|
def self.messages
|
92
|
-
return super + [
|
102
|
+
return super + [ 'run' ]
|
93
103
|
end
|
94
|
-
|
104
|
+
|
95
105
|
# Run the system command.
|
96
106
|
def msg_run
|
97
|
-
if
|
107
|
+
if output?
|
98
108
|
run_with_output
|
99
109
|
else
|
100
110
|
run_with_result
|
101
111
|
end
|
102
112
|
end
|
103
|
-
|
113
|
+
|
104
114
|
def run_with_output
|
105
|
-
cmd =
|
115
|
+
cmd = cmd_value
|
106
116
|
return unless cmd
|
117
|
+
|
107
118
|
result = `#{cmd}`
|
108
119
|
set_result result
|
109
120
|
end
|
110
121
|
|
111
122
|
def run_with_result
|
112
|
-
cmd =
|
123
|
+
cmd = cmd_value
|
113
124
|
return unless cmd
|
125
|
+
|
114
126
|
result = system cmd
|
115
127
|
set_result result
|
116
128
|
end
|
117
129
|
|
130
|
+
# ---------------------------------------------------------------------
|
131
|
+
# Help
|
132
|
+
# ---------------------------------------------------------------------
|
133
|
+
|
134
|
+
#
|
135
|
+
# Get help for this object type.
|
136
|
+
#
|
137
|
+
def self.help
|
138
|
+
return <<~TEXT
|
139
|
+
SYSTEM OBJECT TYPE
|
140
|
+
NAME: system
|
141
|
+
SHORTCUT: sys
|
142
|
+
|
143
|
+
DESCRIPTION
|
144
|
+
Execute a system command.
|
145
|
+
|
146
|
+
CHILDREN
|
147
|
+
command - string - 'date'
|
148
|
+
The command that will be sent to the system.
|
149
|
+
get_output - boolean - true
|
150
|
+
Should executing the command get the output and put it
|
151
|
+
in the result object?
|
152
|
+
result - string
|
153
|
+
The result of running the command.
|
154
|
+
The result will only be set if the 'get_output' child
|
155
|
+
is set to true.
|
156
|
+
|
157
|
+
MESSAGES
|
158
|
+
run - Run the system level command.
|
159
|
+
Set the result value to the output of the command if the
|
160
|
+
'get_output' child is marked as true.
|
161
|
+
TEXT
|
162
|
+
end
|
163
|
+
|
118
164
|
end
|
119
165
|
end
|
120
166
|
end
|
@@ -10,62 +10,63 @@ require 'json'
|
|
10
10
|
module Gloo
|
11
11
|
module Objs
|
12
12
|
class HttpGet < Gloo::Core::Obj
|
13
|
-
|
14
|
-
KEYWORD = 'http_get'
|
15
|
-
KEYWORD_SHORT = 'get'
|
16
|
-
URL = 'uri'
|
17
|
-
PARAMS = 'params'
|
18
|
-
RESULT = 'result'
|
19
|
-
|
20
|
-
#
|
13
|
+
|
14
|
+
KEYWORD = 'http_get'.freeze
|
15
|
+
KEYWORD_SHORT = 'get'.freeze
|
16
|
+
URL = 'uri'.freeze
|
17
|
+
PARAMS = 'params'.freeze
|
18
|
+
RESULT = 'result'.freeze
|
19
|
+
|
20
|
+
#
|
21
21
|
# The name of the object type.
|
22
|
-
#
|
22
|
+
#
|
23
23
|
def self.typename
|
24
24
|
return KEYWORD
|
25
25
|
end
|
26
26
|
|
27
|
-
#
|
27
|
+
#
|
28
28
|
# The short name of the object type.
|
29
|
-
#
|
29
|
+
#
|
30
30
|
def self.short_typename
|
31
31
|
return KEYWORD_SHORT
|
32
32
|
end
|
33
|
-
|
34
|
-
#
|
33
|
+
|
34
|
+
#
|
35
35
|
# Get the URI from the child object.
|
36
36
|
# Returns nil if there is none.
|
37
|
-
#
|
38
|
-
def
|
37
|
+
#
|
38
|
+
def uri_value
|
39
39
|
uri = find_child URL
|
40
40
|
return nil unless uri
|
41
|
+
|
41
42
|
return uri.value
|
42
43
|
end
|
43
|
-
|
44
|
-
#
|
44
|
+
|
45
|
+
#
|
45
46
|
# Set the result of the API call.
|
46
|
-
#
|
47
|
-
def
|
47
|
+
#
|
48
|
+
def update_result( data )
|
48
49
|
r = find_child RESULT
|
49
50
|
return nil unless r
|
51
|
+
|
50
52
|
r.set_value data
|
51
53
|
end
|
52
|
-
|
53
|
-
#
|
54
|
+
|
55
|
+
#
|
54
56
|
# Get the URL for the service including all URL params.
|
55
|
-
#
|
56
|
-
def
|
57
|
-
p =
|
57
|
+
#
|
58
|
+
def full_url_value
|
59
|
+
p = ''
|
58
60
|
params = find_child PARAMS
|
59
61
|
params.children.each do |child|
|
60
|
-
p << ( p.empty? ?
|
61
|
-
|
62
|
+
p << ( p.empty? ? '?' : '&' )
|
63
|
+
|
62
64
|
# TODO: Quote URL params for safety
|
63
65
|
p << "#{child.name}=#{child.value}"
|
64
66
|
end
|
65
|
-
return "#{
|
67
|
+
return "#{uri_value}#{p}"
|
66
68
|
end
|
67
69
|
|
68
|
-
|
69
70
|
# ---------------------------------------------------------------------
|
70
71
|
# Children
|
71
72
|
# ---------------------------------------------------------------------
|
@@ -76,53 +77,89 @@ module Gloo
|
|
76
77
|
def add_children_on_create?
|
77
78
|
return true
|
78
79
|
end
|
79
|
-
|
80
|
+
|
80
81
|
# Add children to this object.
|
81
|
-
# This is used by containers to add children needed
|
82
|
+
# This is used by containers to add children needed
|
82
83
|
# for default configurations.
|
83
84
|
def add_default_children
|
84
85
|
fac = $engine.factory
|
85
|
-
fac.create
|
86
|
-
|
87
|
-
|
86
|
+
fac.create( { :name => 'uri',
|
87
|
+
:type => 'string',
|
88
|
+
:value => 'https://web.site/',
|
89
|
+
:parent => self } )
|
90
|
+
fac.create( { :name => 'params',
|
91
|
+
:type => 'container',
|
92
|
+
:value => nil,
|
93
|
+
:parent => self } )
|
94
|
+
fac.create( { :name => 'result',
|
95
|
+
:type => 'string',
|
96
|
+
:value => nil,
|
97
|
+
:parent => self } )
|
88
98
|
end
|
89
99
|
|
90
|
-
|
91
100
|
# ---------------------------------------------------------------------
|
92
101
|
# Messages
|
93
102
|
# ---------------------------------------------------------------------
|
94
103
|
|
95
|
-
#
|
104
|
+
#
|
96
105
|
# Get a list of message names that this object receives.
|
97
|
-
#
|
106
|
+
#
|
98
107
|
def self.messages
|
99
|
-
return super + [
|
108
|
+
return super + [ 'run' ]
|
100
109
|
end
|
101
|
-
|
110
|
+
|
102
111
|
# Post the content to the endpoint.
|
103
112
|
def msg_run
|
104
|
-
url =
|
113
|
+
url = full_url_value
|
105
114
|
$log.debug url
|
106
|
-
|
107
|
-
set_result result
|
115
|
+
update_result Gloo::Objs::HttpGet.invoke_request url
|
108
116
|
end
|
109
|
-
|
110
|
-
|
117
|
+
|
111
118
|
# ---------------------------------------------------------------------
|
112
119
|
# Static functions
|
113
120
|
# ---------------------------------------------------------------------
|
114
121
|
|
115
122
|
# Post the content to the endpoint.
|
116
|
-
def self.
|
123
|
+
def self.invoke_request( url )
|
117
124
|
uri = URI( url )
|
118
|
-
|
119
|
-
|
125
|
+
use_ssl = uri.scheme.downcase.equal?( 'https' )
|
126
|
+
Net::HTTP.start( uri.host, uri.port, :use_ssl => use_ssl ) do |http|
|
120
127
|
request = Net::HTTP::Get.new uri
|
121
128
|
response = http.request request # Net::HTTPResponse object
|
122
129
|
return response.body
|
123
130
|
end
|
124
131
|
end
|
125
132
|
|
133
|
+
# ---------------------------------------------------------------------
|
134
|
+
# Help
|
135
|
+
# ---------------------------------------------------------------------
|
136
|
+
|
137
|
+
#
|
138
|
+
# Get help for this object type.
|
139
|
+
#
|
140
|
+
def self.help
|
141
|
+
return <<~TEXT
|
142
|
+
HTTP_GET OBJECT TYPE
|
143
|
+
NAME: http_get
|
144
|
+
SHORTCUT: get
|
145
|
+
|
146
|
+
DESCRIPTION
|
147
|
+
Perform an HTTP Get.
|
148
|
+
|
149
|
+
CHILDREN
|
150
|
+
uri - string - 'https://web.site/'
|
151
|
+
The URI for the HTTP Get request.
|
152
|
+
params - container
|
153
|
+
Collection of parameters for the HTTP Get.
|
154
|
+
result - string
|
155
|
+
The result of the request. Whatever was returned from
|
156
|
+
the HTTP Get call.
|
157
|
+
|
158
|
+
MESSAGES
|
159
|
+
run - Run the HTTP Get and update the result.
|
160
|
+
TEXT
|
161
|
+
end
|
162
|
+
|
126
163
|
end
|
127
164
|
end
|
128
165
|
end
|