kyanite 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. data/0 start all Tests.bat +23 -0
  2. data/History.txt +4 -0
  3. data/License.txt +21 -0
  4. data/Manifest.txt +88 -0
  5. data/PostInstall.txt +4 -0
  6. data/README.txt +48 -0
  7. data/Rakefile.rb +79 -0
  8. data/init.rb +2 -0
  9. data/lib/kyanite.rb +39 -0
  10. data/lib/kyanite/array.rb +5 -0
  11. data/lib/kyanite/array/array.rb +172 -0
  12. data/lib/kyanite/array/array2.rb +140 -0
  13. data/lib/kyanite/array/matrix2.rb +120 -0
  14. data/lib/kyanite/array_of_enumerables.rb +2 -0
  15. data/lib/kyanite/array_of_numerics.rb +2 -0
  16. data/lib/kyanite/array_of_strings.rb +2 -0
  17. data/lib/kyanite/basics.rb +60 -0
  18. data/lib/kyanite/dictionary.rb +116 -0
  19. data/lib/kyanite/enumerable.rb +7 -0
  20. data/lib/kyanite/enumerable/enumerable_enumerables.rb +70 -0
  21. data/lib/kyanite/enumerable/enumerable_numerics.rb +171 -0
  22. data/lib/kyanite/enumerable/enumerable_strings.rb +58 -0
  23. data/lib/kyanite/enumerable/structure.rb +170 -0
  24. data/lib/kyanite/general.rb +8 -0
  25. data/lib/kyanite/general/callerutils.rb +128 -0
  26. data/lib/kyanite/general/classutils.rb +246 -0
  27. data/lib/kyanite/general/kernel.rb +105 -0
  28. data/lib/kyanite/general/nil.rb +64 -0
  29. data/lib/kyanite/general/object.rb +86 -0
  30. data/lib/kyanite/general/true_false.rb +65 -0
  31. data/lib/kyanite/general/undoable.rb +24 -0
  32. data/lib/kyanite/hash.rb +170 -0
  33. data/lib/kyanite/matrix2.rb +2 -0
  34. data/lib/kyanite/nil.rb +3 -0
  35. data/lib/kyanite/numeric.rb +4 -0
  36. data/lib/kyanite/numeric/float.rb +26 -0
  37. data/lib/kyanite/numeric/integer.rb +34 -0
  38. data/lib/kyanite/numeric/numeric.rb +45 -0
  39. data/lib/kyanite/operation.rb +5 -0
  40. data/lib/kyanite/operation/call_tracker.rb +69 -0
  41. data/lib/kyanite/operation/rake.rb +101 -0
  42. data/lib/kyanite/operation/regexp.rb +23 -0
  43. data/lib/kyanite/operation/unit_test.rb +53 -0
  44. data/lib/kyanite/optimizer.rb +119 -0
  45. data/lib/kyanite/rake.rb +2 -0
  46. data/lib/kyanite/range.rb +54 -0
  47. data/lib/kyanite/set.rb +219 -0
  48. data/lib/kyanite/smart_load_path.rb +2 -0
  49. data/lib/kyanite/string.rb +13 -0
  50. data/lib/kyanite/string/cast.rb +104 -0
  51. data/lib/kyanite/string/chars.rb +184 -0
  52. data/lib/kyanite/string/chars_const.rb +190 -0
  53. data/lib/kyanite/string/diff.rb +78 -0
  54. data/lib/kyanite/string/div.rb +19 -0
  55. data/lib/kyanite/string/include.rb +43 -0
  56. data/lib/kyanite/string/list.rb +84 -0
  57. data/lib/kyanite/string/mgsub.rb +35 -0
  58. data/lib/kyanite/string/nested.rb +253 -0
  59. data/lib/kyanite/string/random.rb +69 -0
  60. data/lib/kyanite/string/split.rb +136 -0
  61. data/lib/kyanite/symbol.rb +19 -0
  62. data/lib/kyanite/tree.rb +99 -0
  63. data/lib/kyanite/undoable.rb +2 -0
  64. data/lib/kyanite/unit_test.rb +2 -0
  65. data/test/_start_all.rb +17 -0
  66. data/test/array/test_array.rb +106 -0
  67. data/test/array/test_matrix2.rb +162 -0
  68. data/test/enumerable/test_enumerable_enumerables.rb +46 -0
  69. data/test/enumerable/test_enumerable_numerics.rb +93 -0
  70. data/test/enumerable/test_enumerable_strings.rb +22 -0
  71. data/test/enumerable/test_structure.rb +220 -0
  72. data/test/general/test_classutils.rb +45 -0
  73. data/test/general/test_nil.rb +44 -0
  74. data/test/general/test_object.rb +49 -0
  75. data/test/general/test_true_false.rb +28 -0
  76. data/test/numeric/test_numeric_integer.rb +28 -0
  77. data/test/string/test_cast.rb +108 -0
  78. data/test/string/test_chars.rb +255 -0
  79. data/test/string/test_diff.rb +95 -0
  80. data/test/string/test_list.rb +141 -0
  81. data/test/string/test_nested.rb +361 -0
  82. data/test/string/test_split.rb +187 -0
  83. data/test/test_dictionary.rb +128 -0
  84. data/test/test_hash.rb +59 -0
  85. data/test/test_optimizer.rb +150 -0
  86. data/test/test_range.rb +41 -0
  87. data/test/test_set.rb +210 -0
  88. data/test/test_tree.rb +94 -0
  89. metadata +217 -0
@@ -0,0 +1,23 @@
1
+
2
+
3
+ @ECHO OFF
4
+
5
+ rem CODEPAGE �NDERN
6
+ @cmd /C chcp 1252 > NUL
7
+
8
+
9
+
10
+ echo.
11
+
12
+
13
+ ruby test/_start_all.rb
14
+
15
+
16
+
17
+
18
+
19
+
20
+ echo.
21
+ echo.
22
+ echo.
23
+ pause
data/History.txt ADDED
@@ -0,0 +1,4 @@
1
+ == 0.0.1 2008-08-01
2
+
3
+ * 1 major enhancement:
4
+ * Initial release
data/License.txt ADDED
@@ -0,0 +1,21 @@
1
+ LICENSE: GNU General Public License (GPL)
2
+ Autor: Bjoern Klippstein
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining
5
+ a copy of this software and associated documentation files (the
6
+ "Software"), to deal in the Software without restriction, including
7
+ without limitation the rights to use, copy, modify, merge, publish,
8
+ distribute, sublicense, and/or sell copies of the Software, and to
9
+ permit persons to whom the Software is furnished to do so, subject to
10
+ the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Manifest.txt ADDED
@@ -0,0 +1,88 @@
1
+ lib/kyanite.rb
2
+ lib/kyanite/array/array2.rb
3
+ lib/kyanite/array/array.rb
4
+ lib/kyanite/array/matrix2.rb
5
+ lib/kyanite/enumerable/enumerable_enumerables.rb
6
+ lib/kyanite/enumerable/enumerable_numerics.rb
7
+ lib/kyanite/enumerable/enumerable_strings.rb
8
+ lib/kyanite/enumerable/structure.rb
9
+ lib/kyanite/general/callerutils.rb
10
+ lib/kyanite/general/classutils.rb
11
+ lib/kyanite/general/kernel.rb
12
+ lib/kyanite/general/nil.rb
13
+ lib/kyanite/general/object.rb
14
+ lib/kyanite/general/true_false.rb
15
+ lib/kyanite/general/undoable.rb
16
+ lib/kyanite/numeric/float.rb
17
+ lib/kyanite/numeric/integer.rb
18
+ lib/kyanite/numeric/numeric.rb
19
+ lib/kyanite/operation/call_tracker.rb
20
+ lib/kyanite/operation/rake.rb
21
+ lib/kyanite/operation/unit_test.rb
22
+ lib/kyanite/operation/regexp.rb
23
+ lib/kyanite/string/cast.rb
24
+ lib/kyanite/string/chars.rb
25
+ lib/kyanite/string/chars_const.rb
26
+ lib/kyanite/string/diff.rb
27
+ lib/kyanite/string/div.rb
28
+ lib/kyanite/string/include.rb
29
+ lib/kyanite/string/list.rb
30
+ lib/kyanite/string/mgsub.rb
31
+ lib/kyanite/string/nested.rb
32
+ lib/kyanite/string/random.rb
33
+ lib/kyanite/string/split.rb
34
+ lib/kyanite/array.rb
35
+ lib/kyanite/array_of_enumerables.rb
36
+ lib/kyanite/array_of_numerics.rb
37
+ lib/kyanite/array_of_strings.rb
38
+ lib/kyanite/basics.rb
39
+ lib/kyanite/dictionary.rb
40
+ lib/kyanite/enumerable.rb
41
+ lib/kyanite/general.rb
42
+ lib/kyanite/hash.rb
43
+ lib/kyanite/matrix2.rb
44
+ lib/kyanite/nil.rb
45
+ lib/kyanite/numeric.rb
46
+ lib/kyanite/operation.rb
47
+ lib/kyanite/optimizer.rb
48
+ lib/kyanite/rake.rb
49
+ lib/kyanite/range.rb
50
+ lib/kyanite/set.rb
51
+ lib/kyanite/smart_load_path.rb
52
+ lib/kyanite/string.rb
53
+ lib/kyanite/symbol.rb
54
+ lib/kyanite/tree.rb
55
+ lib/kyanite/undoable.rb
56
+ lib/kyanite/unit_test.rb
57
+ 0 start all Tests.bat
58
+ History.txt
59
+ init.rb
60
+ License.txt
61
+ Manifest.txt
62
+ PostInstall.txt
63
+ Rakefile.rb
64
+ README.txt
65
+ test/array/test_array.rb
66
+ test/array/test_matrix2.rb
67
+ test/enumerable/test_enumerable_enumerables.rb
68
+ test/enumerable/test_enumerable_numerics.rb
69
+ test/enumerable/test_enumerable_strings.rb
70
+ test/enumerable/test_structure.rb
71
+ test/general/test_classutils.rb
72
+ test/general/test_nil.rb
73
+ test/general/test_object.rb
74
+ test/general/test_true_false.rb
75
+ test/numeric/test_numeric_integer.rb
76
+ test/string/test_cast.rb
77
+ test/string/test_chars.rb
78
+ test/string/test_diff.rb
79
+ test/string/test_list.rb
80
+ test/string/test_nested.rb
81
+ test/string/test_split.rb
82
+ test/_start_all.rb
83
+ test/test_dictionary.rb
84
+ test/test_hash.rb
85
+ test/test_optimizer.rb
86
+ test/test_range.rb
87
+ test/test_set.rb
88
+ test/test_tree.rb
data/PostInstall.txt ADDED
@@ -0,0 +1,4 @@
1
+
2
+ Kyanite is a general toolbox like Facets or ActiveSupport.
3
+ For more information on Kyanite, see http://kyanite.rubyforge.org
4
+
data/README.txt ADDED
@@ -0,0 +1,48 @@
1
+ = Kyanite
2
+
3
+ * FIX (url)
4
+
5
+ == DESCRIPTION:
6
+
7
+ FIX (describe your package)
8
+
9
+ == FEATURES/PROBLEMS:
10
+
11
+ * FIX (list of features or problems)
12
+
13
+ == SYNOPSIS:
14
+
15
+ FIX (code sample of usage)
16
+
17
+ == REQUIREMENTS:
18
+
19
+ * FIX (list of requirements)
20
+
21
+ == INSTALL:
22
+
23
+ * FIX (sudo gem install, anything else)
24
+
25
+ == LICENSE:
26
+
27
+ (The MIT License)
28
+
29
+ Copyright (c) 2008 FIXME full name
30
+
31
+ Permission is hereby granted, free of charge, to any person obtaining
32
+ a copy of this software and associated documentation files (the
33
+ 'Software'), to deal in the Software without restriction, including
34
+ without limitation the rights to use, copy, modify, merge, publish,
35
+ distribute, sublicense, and/or sell copies of the Software, and to
36
+ permit persons to whom the Software is furnished to do so, subject to
37
+ the following conditions:
38
+
39
+ The above copyright notice and this permission notice shall be
40
+ included in all copies or substantial portions of the Software.
41
+
42
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
43
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
44
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
45
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
46
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
47
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
48
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile.rb ADDED
@@ -0,0 +1,79 @@
1
+
2
+ # ----------------------------------------------------------------------------------------------
3
+ # NewGem
4
+ #
5
+
6
+ %w[rubygems rake rake/clean fileutils newgem rubigen].each { |f| require f }
7
+ require File.dirname(__FILE__) + '/lib/kyanite'
8
+
9
+ # Generate all the Rake tasks
10
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
11
+ $hoe = Hoe.new('kyanite', Kyanite::VERSION) do |p|
12
+ p.developer('Bjoern Klippstein', 'bjoernklippstein@gmail.com')
13
+ p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
14
+ p.post_install_message = 'PostInstall.txt' # TODO remove if post-install message not required
15
+ p.rubyforge_name = p.name # TODO this is default value
16
+ p.extra_deps = [
17
+ ['activesupport', '>= 2.2.2'],
18
+ ['facets', '>= 2.5.0'],
19
+ ['rubytree', '>= 0.5.2']
20
+ ]
21
+ p.extra_dev_deps = [
22
+ ['newgem', ">= #{::Newgem::VERSION}"]
23
+ ]
24
+
25
+ p.clean_globs |= %w[**/.DS_Store tmp *.log]
26
+ path = (p.rubyforge_name == p.name) ? p.rubyforge_name : "\#{p.rubyforge_name}/\#{p.name}"
27
+ p.remote_rdoc_dir = File.join(path.gsub(/^#{p.rubyforge_name}\/?/,''), 'rdoc')
28
+ p.rsync_args = '-av --delete --ignore-errors'
29
+ end
30
+
31
+ require 'newgem/tasks' # load /tasks/*.rake
32
+ Dir['tasks/**/*.rake'].each { |t| load t }
33
+
34
+ # TODO - want other tests/tasks run by default? Add them to the list
35
+ # task :default => [:spec, :features]
36
+
37
+
38
+
39
+ # ----------------------------------------------------------------------------------------------
40
+ # Kyanite
41
+ #
42
+
43
+ $rake_tasks_ausblenden = %w{ bundles:tm deps:email deps:fetch deps:list manifest manifest:refresh
44
+ announce check_manifest debug_gem email install_gem install_gem_no_doc
45
+ local_deploy package post_blog post_news ridocs test_deps}
46
+ require 'kyanite/rake'
47
+
48
+
49
+
50
+
51
+
52
+
53
+
54
+ # ----------------------------------------------------------------------------------------------
55
+ # Documentation
56
+ #
57
+ # http://github.com/mislav/hanna/tree/master
58
+
59
+ # instead of 'rake/rdoctask':
60
+ require 'hanna/rdoctask'
61
+
62
+ desc 'Generate RDoc documentation for Kyanite'
63
+ Rake::RDocTask.new do |rdoc|
64
+ rdoc.rdoc_dir = 'doc'
65
+ rdoc.title = "Kyanite is a general toolbox like Facets or ActiveSupport"
66
+ rdoc.rdoc_files.include('README.txt', 'License.txt')
67
+ rdoc.rdoc_files.include('lib/**/*.rb')
68
+ rdoc.rdoc_files.include('test/**/test_*.rb')
69
+ rdoc.rdoc_files.exclude('lib/kyanite/array/array2')
70
+ rdoc.rdoc_files.exclude('lib/kyanite/array/matrix2')
71
+ rdoc.rdoc_files.exclude('lib/kyanite.rb')
72
+ rdoc.options += [
73
+ '-SNap',
74
+ '-w4',
75
+ '--charset=utf8',
76
+ ]
77
+ end
78
+
79
+
data/init.rb ADDED
@@ -0,0 +1,2 @@
1
+
2
+ require File.join(File.dirname(__FILE__), 'lib', 'kyanite.rb' )
data/lib/kyanite.rb ADDED
@@ -0,0 +1,39 @@
1
+
2
+ # Required alle Kyanite-Libs
3
+ # -- eine Auswahl der wichtigsten Kyanite-Libs required man mit
4
+ # require 'kyanite/basics'
5
+
6
+ $KCODE = 'UTF8'
7
+
8
+ if $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
9
+ # puts 'Path schon aktuell'
10
+ else
11
+ $:.unshift(File.dirname(__FILE__))
12
+ end
13
+
14
+
15
+ # Die Versionsnummer steht ausserdem
16
+ # * im Script '2 install gem.bat'
17
+ # * in der gem-Verkn�pfung
18
+ module Kyanite
19
+ VERSION = '0.3.1'
20
+ end
21
+
22
+
23
+ require 'kyanite/array'
24
+ # require 'kyanite/basics' # Auswahl
25
+ require 'kyanite/dictionary'
26
+ require 'kyanite/enumerable'
27
+ require 'kyanite/general'
28
+ require 'kyanite/hash'
29
+ # require 'kyanite/matrix2' # ist schon in array
30
+ # require 'kyanite/nil' # ist schon in general
31
+ require 'kyanite/numeric'
32
+ # require 'kyanite/operation' # nur manuell
33
+ require 'kyanite/optimizer'
34
+ require 'kyanite/range'
35
+ require 'kyanite/set'
36
+ require 'kyanite/string'
37
+ require 'kyanite/symbol'
38
+ require 'kyanite/tree'
39
+ # require 'kyanite/unit_test' # nur f�r Tests
@@ -0,0 +1,5 @@
1
+
2
+ require 'kyanite/array/matrix2' # das ist die oberste Ebene, array2 und array werden ebenfalls required
3
+ require 'kyanite/enumerable/enumerable_enumerables'
4
+ require 'kyanite/enumerable/enumerable_numerics'
5
+ require 'kyanite/enumerable/enumerable_strings'
@@ -0,0 +1,172 @@
1
+
2
+ require 'facets/array/delete' # Methoden delete_unless, delete_values, delete_values_at
3
+ require 'facets/array/rotate' # Methoden rotate, rotate!
4
+ require 'facets/array/select' # Methode select!
5
+ require 'facets/to_hash' # Methode to_h (in der Facets-Bibliothek falsch einsortiert?)
6
+
7
+ require 'kyanite/enumerable' #
8
+ require 'kyanite/general/object' # Methode respond
9
+ require 'kyanite/general/classutils' # <=> für Class
10
+ require 'kyanite/symbol' # size
11
+
12
+
13
+ # Array, ArrayOfNumerics, ArrayOfStrings, ArrayOfEnumerables, Set
14
+ #
15
+ # Tests und Beispiele siehe TestKyaniteArray
16
+ #
17
+ # Aus {Facets/Array}[http://facets.rubyforge.org/doc/api/core/classes/Array.html] eingefügt:
18
+ # * *delete_unless* <tt>(&block)</tt> Ergänzung zum regulären +delete_if+
19
+ # * *delete_values* <tt>(*values)</tt> Findet und löscht bestimmte Werte
20
+ # * *delete_values_at* <tt>(*selectors)</tt> Löscht Elemente an bestimmten Positionen
21
+ #
22
+ # * *rotate* <tt>(n=1)</tt> Alles rückt n Positionen auf
23
+ # * <b>select!</b> <tt>{ |obj| block }</tt> Wie +select+, aber modifiziert das Objekt
24
+ # * *to_h* <tt>(arrayed=nil)</tt> Converts a two-element associative array into a hash.
25
+ # * *to_hash* <tt>()</tt> (Unterschied zu +to_h+ ???)
26
+ #
27
+ #
28
+ class Array
29
+
30
+ # schneidet vorne ein Element ab und gibt den Rest zurück.
31
+ # Wenn der Rest nur noch aus einem Element besteht, wird er 'pur' zurückgeliefert und nicht als Array.
32
+ # Nützlich für Rekursionen. Bsp.:
33
+ # [1,2,3].shift_complement => [2,3]
34
+ # [1,2,3].shift_complement.shift_complement => 3
35
+ # [1,2,3].shift_complement.shift_complement.shift_complement => nil
36
+ #
37
+ # Tests und Beispiele siehe TestKyaniteArray#test_array_shift_complement
38
+ #
39
+ def shift_complement
40
+ if self.size > 2
41
+ self[1..-1]
42
+ else
43
+ self[-1]
44
+ end
45
+ end
46
+
47
+
48
+
49
+
50
+
51
+ # Formuliert den Index eines Arrays
52
+ # :pos als positive Angabe
53
+ # :neg als negative Angabe
54
+ # :inv wenn positiv, dann negativ und umgekehrt
55
+ #
56
+ # Liefert eine Integerzahl.
57
+ #
58
+ # Tests und Beispiele siehe TestKyaniteArray#test_rephrase_index
59
+ #
60
+ def rephrase_index(i, style=:inv)
61
+ return i if i > (size-1)
62
+ return i if i < -size
63
+ case style
64
+ when :inv
65
+ if i >=0 # pos >> neg
66
+ (i - size)
67
+ else # neg >> pos
68
+ (i + size)
69
+ end
70
+ when :pos
71
+ if i >= 0 # pos bleibt
72
+ i
73
+ else # neg >> pos
74
+ (i + size)
75
+ end
76
+ when :neg
77
+ if i >= 0 # pos >> neg
78
+ (i - size)
79
+ else # neg bleibt
80
+ i
81
+ end
82
+ end #case
83
+ end #def
84
+
85
+
86
+
87
+
88
+
89
+
90
+
91
+
92
+
93
+ # ==================================================================================
94
+ # divide
95
+ #
96
+
97
+
98
+
99
+ # Set#divide doesn't work well recursively because Set can't handle Sets of Sets properly
100
+ #
101
+ #
102
+ # Test und Beispiel siehe TestKyaniteArray#test_divide
103
+ #
104
+ def divide(&func)
105
+ require 'tsort'
106
+ class << dig = {} # :nodoc:
107
+ include TSort
108
+ alias tsort_each_node each_key
109
+ def tsort_each_child(node, &block)
110
+ fetch(node).each(&block)
111
+ end #def
112
+ end #class
113
+
114
+ each { |u|
115
+ dig[u] = a = []
116
+ each{ |v| func.call(u, v) and a << v }
117
+ }
118
+
119
+ result = []
120
+ dig.each_strongly_connected_component { |css| result << (self.class.new(css)) }
121
+ result
122
+ end #def
123
+
124
+
125
+
126
+
127
+ # ==================================================================================
128
+ # Zufall
129
+ #
130
+
131
+
132
+ # Bringt das Array in eine zufällige Reihenfolge
133
+ def shuffle
134
+ sort_by { rand }
135
+ end
136
+
137
+
138
+ # In-place-Variante von shuffle
139
+ def shuffle!
140
+ self.replace shuffle
141
+ end
142
+
143
+
144
+
145
+ end # class Array
146
+
147
+
148
+
149
+ class NilClass
150
+ def shift_complement; nil; end
151
+ end
152
+
153
+
154
+
155
+
156
+
157
+
158
+
159
+
160
+
161
+
162
+
163
+
164
+
165
+
166
+
167
+
168
+
169
+
170
+
171
+
172
+