functio 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +3 -0
- data/CHANGELOG.md +9 -0
- data/COPYING +674 -0
- data/Gemfile +16 -0
- data/Gemfile.lock +79 -0
- data/README.md +109 -0
- data/Rakefile +47 -0
- data/bin/fn +28 -0
- data/features/expression_evaluation.feature +58 -0
- data/features/function_creation.feature +74 -0
- data/features/function_deletion.feature +37 -0
- data/features/function_list.feature +35 -0
- data/features/function_use.feature +56 -0
- data/features/help_option.feature +13 -0
- data/features/step_definitions/steps.rb +36 -0
- data/features/support/env.rb +41 -0
- data/features/support/functio_world.rb +45 -0
- data/features/version_option.feature +19 -0
- data/functio.gemspec +43 -0
- data/lib/functio.rb +24 -0
- data/lib/functio/data_storage.rb +90 -0
- data/lib/functio/errors.rb +47 -0
- data/lib/functio/expression.rb +61 -0
- data/lib/functio/formatted_num.rb +39 -0
- data/lib/functio/functio_cli.rb +111 -0
- data/lib/functio/function.rb +104 -0
- data/lib/functio/function_repository.rb +73 -0
- data/lib/functio/version.rb +23 -0
- data/test/doubles/expression_double.rb +33 -0
- data/test/doubles/function_double.rb +34 -0
- data/test/doubles/storage_double.rb +36 -0
- data/test/doubles/test_expression_double.rb +30 -0
- data/test/doubles/test_function_double.rb +30 -0
- data/test/doubles/test_storage_double.rb +30 -0
- data/test/expression_interface_test.rb +30 -0
- data/test/interface_test_helper.rb +25 -0
- data/test/license_test_helper.rb +49 -0
- data/test/storable_interface_test.rb +30 -0
- data/test/storage_interface_test.rb +30 -0
- data/test/test_data_storage.rb +127 -0
- data/test/test_expression.rb +89 -0
- data/test/test_formatted_num.rb +56 -0
- data/test/test_function.rb +142 -0
- data/test/test_function_repository.rb +97 -0
- data/test/test_helper.rb +22 -0
- data/test/test_licenses_compatibility.rb +29 -0
- metadata +140 -0
@@ -0,0 +1,34 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (C) 2016 Cassiano Rocha Kuplich
|
3
|
+
#
|
4
|
+
# This file is part of Functio.
|
5
|
+
#
|
6
|
+
# Functio is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU General Public License as published by
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# Functio is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU General Public License
|
17
|
+
# along with Functio. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
#++
|
19
|
+
|
20
|
+
class FunctionDouble # :nodoc:
|
21
|
+
attr_reader :attributes
|
22
|
+
|
23
|
+
def self.build(attributes)
|
24
|
+
new(attributes)
|
25
|
+
end
|
26
|
+
|
27
|
+
def initialize(attributes)
|
28
|
+
@attributes = attributes
|
29
|
+
end
|
30
|
+
|
31
|
+
def ==(other)
|
32
|
+
attributes == other.attributes
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (C) 2016 Cassiano Rocha Kuplich
|
3
|
+
#
|
4
|
+
# This file is part of Functio.
|
5
|
+
#
|
6
|
+
# Functio is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU General Public License as published by
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# Functio is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU General Public License
|
17
|
+
# along with Functio. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
#++
|
19
|
+
|
20
|
+
class StorageDouble # :nodoc:
|
21
|
+
attr_reader :all
|
22
|
+
|
23
|
+
def initialize(results = {})
|
24
|
+
@find = results[:find]
|
25
|
+
@all = results[:all]
|
26
|
+
@delete = results[:delete]
|
27
|
+
end
|
28
|
+
|
29
|
+
def find(_fields)
|
30
|
+
@find
|
31
|
+
end
|
32
|
+
|
33
|
+
def delete(_fields)
|
34
|
+
@delete
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (C) 2016 Cassiano Rocha Kuplich
|
3
|
+
#
|
4
|
+
# This file is part of Functio.
|
5
|
+
#
|
6
|
+
# Functio is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU General Public License as published by
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# Functio is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU General Public License
|
17
|
+
# along with Functio. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
#++
|
19
|
+
|
20
|
+
require 'minitest/autorun'
|
21
|
+
require 'doubles/expression_double'
|
22
|
+
require 'expression_interface_test'
|
23
|
+
|
24
|
+
class TestExpressionDouble < Minitest::Test # :nodoc:
|
25
|
+
include ExpressionInterfaceTest
|
26
|
+
|
27
|
+
def setup
|
28
|
+
@object = ExpressionDouble.new
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (C) 2016 Cassiano Rocha Kuplich
|
3
|
+
#
|
4
|
+
# This file is part of Functio.
|
5
|
+
#
|
6
|
+
# Functio is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU General Public License as published by
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# Functio is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU General Public License
|
17
|
+
# along with Functio. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
#++
|
19
|
+
|
20
|
+
require 'minitest/autorun'
|
21
|
+
require 'doubles/function_double'
|
22
|
+
require 'storable_interface_test'
|
23
|
+
|
24
|
+
class TestFunctionDouble < Minitest::Test # :nodoc:
|
25
|
+
include StorableInterfaceTest
|
26
|
+
|
27
|
+
def setup
|
28
|
+
@object = FunctionDouble.new({})
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (C) 2016 Cassiano Rocha Kuplich
|
3
|
+
#
|
4
|
+
# This file is part of Functio.
|
5
|
+
#
|
6
|
+
# Functio is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU General Public License as published by
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# Functio is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU General Public License
|
17
|
+
# along with Functio. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
#++
|
19
|
+
|
20
|
+
require 'minitest/autorun'
|
21
|
+
require 'doubles/storage_double'
|
22
|
+
require 'storage_interface_test'
|
23
|
+
|
24
|
+
class TestStorageDouble < Minitest::Test # :nodoc:
|
25
|
+
include StorageInterfaceTest
|
26
|
+
|
27
|
+
def setup
|
28
|
+
@object = StorageDouble.new
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (C) 2016 Cassiano Rocha Kuplich
|
3
|
+
#
|
4
|
+
# This file is part of Functio.
|
5
|
+
#
|
6
|
+
# Functio is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU General Public License as published by
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# Functio is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU General Public License
|
17
|
+
# along with Functio. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
#++
|
19
|
+
|
20
|
+
require 'interface_test_helper'
|
21
|
+
|
22
|
+
module ExpressionInterfaceTest # :nodoc:
|
23
|
+
include InterfaceTestHelper
|
24
|
+
|
25
|
+
def test_implements_the_expression_interface
|
26
|
+
assert_implements(@object, :expression, 0)
|
27
|
+
assert_implements(@object, :variables, 0)
|
28
|
+
assert_implements(@object, :evaluate, -1)
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (C) 2016 Cassiano Rocha Kuplich
|
3
|
+
#
|
4
|
+
# This file is part of Functio.
|
5
|
+
#
|
6
|
+
# Functio is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU General Public License as published by
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# Functio is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU General Public License
|
17
|
+
# along with Functio. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
#++
|
19
|
+
|
20
|
+
module InterfaceTestHelper # :nodoc:
|
21
|
+
def assert_implements(object, method, arity)
|
22
|
+
assert_respond_to(object, method)
|
23
|
+
assert_equal(arity, object.method(method).arity)
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (C) 2016 Cassiano Rocha Kuplich
|
3
|
+
#
|
4
|
+
# This file is part of Functio.
|
5
|
+
#
|
6
|
+
# Functio is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU General Public License as published by
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# Functio is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU General Public License
|
17
|
+
# along with Functio. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
#++
|
19
|
+
|
20
|
+
require 'minitest/autorun'
|
21
|
+
require 'papers'
|
22
|
+
|
23
|
+
# Configures Papers for license compatibility validation.
|
24
|
+
Papers.configure do |config|
|
25
|
+
# A whitelist of accepted licenses.
|
26
|
+
config.license_whitelist = ['MIT', 'BSD', 'BSD-2-Clause', 'Ruby', 'GPL-3.0+']
|
27
|
+
|
28
|
+
# The location of your dependency manifest. Defaults to
|
29
|
+
# config/papers_manifest.yml
|
30
|
+
config.manifest_file = File.join('config', 'papers_manifest.yml')
|
31
|
+
|
32
|
+
# Configures Papers to validate licenses for bundled gems. Defaults to true.
|
33
|
+
config.validate_gems = true
|
34
|
+
|
35
|
+
# Configures Papers to validate licenses for included JavaScript and
|
36
|
+
# CoffeScript files. Defaults to true.
|
37
|
+
config.validate_javascript = false
|
38
|
+
|
39
|
+
# Configures Papers to validate licenses for bower components. Defaults to
|
40
|
+
# false.
|
41
|
+
config.validate_bower_components = false
|
42
|
+
|
43
|
+
# Configures Papers to validate licenses for NPM dependencies. Defaults to
|
44
|
+
# false.
|
45
|
+
config.validate_npm_packages = false
|
46
|
+
|
47
|
+
# Configured Papers to ignore NPM dev dependencies. Defaults to false.
|
48
|
+
config.ignore_npm_dev_dependencies = false
|
49
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (C) 2016 Cassiano Rocha Kuplich
|
3
|
+
#
|
4
|
+
# This file is part of Functio.
|
5
|
+
#
|
6
|
+
# Functio is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU General Public License as published by
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# Functio is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU General Public License
|
17
|
+
# along with Functio. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
#++
|
19
|
+
|
20
|
+
require 'interface_test_helper'
|
21
|
+
|
22
|
+
module StorableInterfaceTest # :nodoc:
|
23
|
+
include InterfaceTestHelper
|
24
|
+
|
25
|
+
def test_implements_the_storable_interface
|
26
|
+
assert_implements(@object.class, :build, 1)
|
27
|
+
assert_implements(@object, :attributes, 0)
|
28
|
+
assert_implements(@object, :==, 1)
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (C) 2016 Cassiano Rocha Kuplich
|
3
|
+
#
|
4
|
+
# This file is part of Functio.
|
5
|
+
#
|
6
|
+
# Functio is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU General Public License as published by
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# Functio is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU General Public License
|
17
|
+
# along with Functio. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
#++
|
19
|
+
|
20
|
+
require 'interface_test_helper'
|
21
|
+
|
22
|
+
module StorageInterfaceTest # :nodoc:
|
23
|
+
include InterfaceTestHelper
|
24
|
+
|
25
|
+
def test_implements_storage_interface
|
26
|
+
assert_implements(@object, :all, 0)
|
27
|
+
assert_implements(@object, :find, 1)
|
28
|
+
assert_implements(@object, :delete, 1)
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (C) 2016 Cassiano Rocha Kuplich
|
3
|
+
#
|
4
|
+
# This file is part of Functio.
|
5
|
+
#
|
6
|
+
# Functio is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU General Public License as published by
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# Functio is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU General Public License
|
17
|
+
# along with Functio. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
#++
|
19
|
+
|
20
|
+
require 'test_helper'
|
21
|
+
require 'functio/data_storage'
|
22
|
+
require 'fileutils'
|
23
|
+
require 'storage_interface_test'
|
24
|
+
|
25
|
+
class TestDataStorage < Minitest::Test # :nodoc:
|
26
|
+
include StorageInterfaceTest
|
27
|
+
|
28
|
+
def setup
|
29
|
+
@real_home = ENV['HOME']
|
30
|
+
|
31
|
+
ENV['HOME'] = File.join('/tmp', 'fake_home')
|
32
|
+
@default_data_file = File.join(ENV['HOME'], '.functio', 'functions.csv')
|
33
|
+
|
34
|
+
FileUtils.remove_dir(ENV['HOME'], true)
|
35
|
+
FileUtils.mkdir_p(ENV['HOME'])
|
36
|
+
|
37
|
+
@object = @storage = DataStorage.new
|
38
|
+
end
|
39
|
+
|
40
|
+
def teardown
|
41
|
+
ENV['HOME'] = @real_home
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_store
|
45
|
+
@storage.store(name: 'first', definition: 'record')
|
46
|
+
first = "name,definition\nfirst,record\n"
|
47
|
+
|
48
|
+
assert File.exist?(@default_data_file)
|
49
|
+
assert_equal(first, File.read(@default_data_file))
|
50
|
+
|
51
|
+
@storage.store(name: 'second', definition: 'record')
|
52
|
+
assert_equal(first + "second,record\n", File.read(@default_data_file))
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_find_stored_record
|
56
|
+
set_fixture_csv
|
57
|
+
expected = { name: 'first', definition: 'one' }
|
58
|
+
assert_equal(expected, @storage.find(name: 'first'))
|
59
|
+
assert_equal(expected, @storage.find(definition: 'one'))
|
60
|
+
assert_equal(expected, @storage.find(name: 'first', definition: 'one'))
|
61
|
+
|
62
|
+
expected = { name: 'second', definition: 'two' }
|
63
|
+
assert_equal(expected, @storage.find(name: 'second'))
|
64
|
+
assert_equal(expected, @storage.find(definition: 'two'))
|
65
|
+
assert_equal(expected, @storage.find(name: 'second', definition: 'two'))
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_find_inexistent_record
|
69
|
+
assert_nil(@storage.find(name: 'first'))
|
70
|
+
assert_nil(@storage.find(definition: 'two'))
|
71
|
+
|
72
|
+
set_fixture_csv
|
73
|
+
assert_nil(@storage.find(name: 'something else'))
|
74
|
+
assert_nil(@storage.find(definition: 'something else'))
|
75
|
+
assert_nil(@storage.find(name: 'first', definition: 'two'))
|
76
|
+
assert_nil(@storage.find(other: 'test'))
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_get_all_records
|
80
|
+
assert_equal([], @storage.all)
|
81
|
+
|
82
|
+
set_fixture_csv
|
83
|
+
all_records = @storage.all
|
84
|
+
assert_equal(2, all_records.size)
|
85
|
+
assert_includes(all_records, name: 'first', definition: 'one')
|
86
|
+
assert_includes(all_records, name: 'second', definition: 'two')
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_delete_stored_record
|
90
|
+
set_fixture_csv
|
91
|
+
|
92
|
+
expected = "name,definition\nsecond,two\n"
|
93
|
+
assert @storage.delete(name: 'first')
|
94
|
+
assert_equal(expected, File.read(@default_data_file))
|
95
|
+
|
96
|
+
assert @storage.delete(definition: 'two', name: 'second')
|
97
|
+
refute File.exist?(@default_data_file)
|
98
|
+
end
|
99
|
+
|
100
|
+
def test_delete_from_empty_data
|
101
|
+
refute @storage.delete(name: 'something', definition: 'else')
|
102
|
+
end
|
103
|
+
|
104
|
+
def test_delete_inexistent_record
|
105
|
+
set_fixture_csv
|
106
|
+
|
107
|
+
expected = "name,definition\nfirst,one\nsecond,two\n"
|
108
|
+
fields_cases = [{ name: 'something else' },
|
109
|
+
{ definition: 'something else' },
|
110
|
+
{ other: 'something else' }]
|
111
|
+
fields_cases.each do |fields|
|
112
|
+
refute @storage.delete(fields)
|
113
|
+
assert_equal(expected, File.read(@default_data_file))
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
private
|
118
|
+
|
119
|
+
def set_fixture_csv
|
120
|
+
FileUtils.mkdir_p(File.dirname(@default_data_file))
|
121
|
+
File.open(@default_data_file, 'a') do |f|
|
122
|
+
f.puts 'name,definition'
|
123
|
+
f.puts 'first,one'
|
124
|
+
f.puts 'second,two'
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|