xamplr 1.2.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.
Files changed (142) hide show
  1. data/CHANGES.txt +13 -0
  2. data/LICENSE +3 -0
  3. data/README.rdoc +26 -0
  4. data/README.rdoc.orig +118 -0
  5. data/Rakefile +85 -0
  6. data/VERSION.yml +4 -0
  7. data/examples/random-people-shared-addresses/Makefile +16 -0
  8. data/examples/random-people-shared-addresses/batch-load-users.rb +83 -0
  9. data/examples/random-people-shared-addresses/find-mentions.rb +47 -0
  10. data/examples/random-people-shared-addresses/find-people-by-address.rb +104 -0
  11. data/examples/random-people-shared-addresses/optimise.rb +16 -0
  12. data/examples/random-people-shared-addresses/people.rb +35 -0
  13. data/examples/random-people-shared-addresses/query.rb +75 -0
  14. data/examples/random-people-shared-addresses/query2.rb +73 -0
  15. data/examples/random-people-shared-addresses/random-names.csv +10000 -0
  16. data/examples/random-people-shared-addresses/settings.rb +3 -0
  17. data/examples/random-people-shared-addresses/what-to-query-on.rb +82 -0
  18. data/examples/random-people-shared-addresses/xampl-gen.rb +36 -0
  19. data/examples/random-people-shared-addresses/xml/people.xml +14 -0
  20. data/examples/random-people/Makefile +16 -0
  21. data/examples/random-people/batch-load-users.rb +61 -0
  22. data/examples/random-people/optimise.rb +16 -0
  23. data/examples/random-people/people.rb +22 -0
  24. data/examples/random-people/query.rb +73 -0
  25. data/examples/random-people/query2.rb +73 -0
  26. data/examples/random-people/random-names.csv +10000 -0
  27. data/examples/random-people/rawtc.rb +91 -0
  28. data/examples/random-people/settings.rb +3 -0
  29. data/examples/random-people/what-to-query-on.rb +80 -0
  30. data/examples/random-people/xampl-gen.rb +36 -0
  31. data/examples/random-people/xml/people.xml +11 -0
  32. data/examples/read-testing/Makefile +10 -0
  33. data/examples/read-testing/load.rb +65 -0
  34. data/examples/read-testing/read.rb +51 -0
  35. data/examples/read-testing/rrr.rb +87 -0
  36. data/examples/read-testing/settings.rb +2 -0
  37. data/examples/read-testing/xampl-gen.rb +36 -0
  38. data/examples/read-testing/xml/text.xml +8 -0
  39. data/examples/tokyo-cabinet-experimental/expt-query.rb +42 -0
  40. data/examples/tokyo-cabinet-experimental/expt-query2.rb +42 -0
  41. data/examples/tokyo-cabinet-experimental/expt-query3.rb +41 -0
  42. data/examples/tokyo-cabinet-experimental/expt-reader.rb +32 -0
  43. data/examples/tokyo-cabinet-experimental/expt.rb +61 -0
  44. data/examples/tokyo-cabinet-experimental/xampl-gen.rb +36 -0
  45. data/examples/tokyo-cabinet-experimental/xml/tcx.xml +6 -0
  46. data/lib/xampl-generator.rb +3 -0
  47. data/lib/xampl.rb +3 -0
  48. data/lib/xamplr-generator.rb +10 -0
  49. data/lib/xamplr.rb +37 -0
  50. data/lib/xamplr/README-POSSIBLE-PROBLEMS +5 -0
  51. data/lib/xamplr/TODO +1 -0
  52. data/lib/xamplr/exceptions.rb +97 -0
  53. data/lib/xamplr/from-xml-orig.rb +350 -0
  54. data/lib/xamplr/from-xml.rb +439 -0
  55. data/lib/xamplr/gen-elements.xml +6230 -0
  56. data/lib/xamplr/gen.elements.xml +108 -0
  57. data/lib/xamplr/generate-elements.rb +15 -0
  58. data/lib/xamplr/generator.rb +5 -0
  59. data/lib/xamplr/graphml-out.rb +470 -0
  60. data/lib/xamplr/handwritten/example.rb +698 -0
  61. data/lib/xamplr/handwritten/hand-example.rb +533 -0
  62. data/lib/xamplr/handwritten/test-handwritten.rb +873 -0
  63. data/lib/xamplr/indexed-array.rb +115 -0
  64. data/lib/xamplr/mixins.rb +397 -0
  65. data/lib/xamplr/my.gen.elements.xml +461 -0
  66. data/lib/xamplr/notifications.rb +57 -0
  67. data/lib/xamplr/obsolete/fsdb.rb +62 -0
  68. data/lib/xamplr/persist-to-xml.rb +249 -0
  69. data/lib/xamplr/persistence.rb +522 -0
  70. data/lib/xamplr/persistence.rb.more_thread_safe +771 -0
  71. data/lib/xamplr/persistence.rb.partially_thread_safe +763 -0
  72. data/lib/xamplr/persister.rb +310 -0
  73. data/lib/xamplr/persisters/caches.rb +186 -0
  74. data/lib/xamplr/persisters/caching.rb +172 -0
  75. data/lib/xamplr/persisters/filesystem.rb +60 -0
  76. data/lib/xamplr/persisters/in-memory.rb +180 -0
  77. data/lib/xamplr/persisters/simple.rb +59 -0
  78. data/lib/xamplr/persisters/tokyo-cabinet.rb +641 -0
  79. data/lib/xamplr/simpleTemplate/danger.rx +4 -0
  80. data/lib/xamplr/simpleTemplate/obsolete/input-c.r4 +35 -0
  81. data/lib/xamplr/simpleTemplate/obsolete/play.r6.txt +12 -0
  82. data/lib/xamplr/simpleTemplate/obsolete/play_more.r6.txt +20 -0
  83. data/lib/xamplr/simpleTemplate/obsolete/test001.r5 +8 -0
  84. data/lib/xamplr/simpleTemplate/obsolete/test002.r5 +13 -0
  85. data/lib/xamplr/simpleTemplate/obsolete/test003.r5 +37 -0
  86. data/lib/xamplr/simpleTemplate/old/r6.000.rb +122 -0
  87. data/lib/xamplr/simpleTemplate/old/r6.001.rb +145 -0
  88. data/lib/xamplr/simpleTemplate/play.r6 +12 -0
  89. data/lib/xamplr/simpleTemplate/play_more.r6 +20 -0
  90. data/lib/xamplr/simpleTemplate/play_noblanks.r6 +21 -0
  91. data/lib/xamplr/simpleTemplate/playq.r6 +16 -0
  92. data/lib/xamplr/simpleTemplate/r6.rb +87 -0
  93. data/lib/xamplr/simpleTemplate/simple-template.rb +75 -0
  94. data/lib/xamplr/templates/child.template +47 -0
  95. data/lib/xamplr/templates/child_indexed.template +89 -0
  96. data/lib/xamplr/templates/child_modules.template +5 -0
  97. data/lib/xamplr/templates/element_classes.template +11 -0
  98. data/lib/xamplr/templates/element_data.template +282 -0
  99. data/lib/xamplr/templates/element_empty.template +285 -0
  100. data/lib/xamplr/templates/element_mixed.template +277 -0
  101. data/lib/xamplr/templates/element_simple.template +276 -0
  102. data/lib/xamplr/templates/package.template +26 -0
  103. data/lib/xamplr/test-support/Makefile +47 -0
  104. data/lib/xamplr/test-support/bench-cache.rb +80 -0
  105. data/lib/xamplr/test-support/bench-script.rb +21 -0
  106. data/lib/xamplr/test-support/bench.rb +116 -0
  107. data/lib/xamplr/test-support/bench2.rb +132 -0
  108. data/lib/xamplr/test-support/test-cache.rb +147 -0
  109. data/lib/xamplr/test-support/test-data/binding.xml +7 -0
  110. data/lib/xamplr/test-support/test-data/example.xml +14 -0
  111. data/lib/xamplr/test-support/test-data/internationalization-utf8.txt +1 -0
  112. data/lib/xamplr/test-support/test-data/labels.xml +37 -0
  113. data/lib/xamplr/test-support/test-data/labels001.xml +38 -0
  114. data/lib/xamplr/test-support/test-deep-change.rb +135 -0
  115. data/lib/xamplr/test-support/test-elements.rb +109 -0
  116. data/lib/xamplr/test-support/test-indexed-array.rb +169 -0
  117. data/lib/xamplr/test-support/test-misc.rb +73 -0
  118. data/lib/xamplr/test-support/test-names.rb +67 -0
  119. data/lib/xamplr/test-support/test-rollback.rb +106 -0
  120. data/lib/xamplr/test-support/test.rb +1504 -0
  121. data/lib/xamplr/to-ruby.rb +220 -0
  122. data/lib/xamplr/to-xml.rb +158 -0
  123. data/lib/xamplr/version.rb +67 -0
  124. data/lib/xamplr/visitor.rb +140 -0
  125. data/lib/xamplr/visitors.rb +573 -0
  126. data/lib/xamplr/xampl-generator.rb +533 -0
  127. data/lib/xamplr/xampl-hand-generated.rb +1535 -0
  128. data/lib/xamplr/xampl-module.rb +36 -0
  129. data/lib/xamplr/xampl-object-internals.rb +6 -0
  130. data/lib/xamplr/xampl-object.rb +202 -0
  131. data/lib/xamplr/xampl-persisted-object.rb +122 -0
  132. data/lib/xamplr/xml-text.rb +117 -0
  133. data/lib/xamplr/xml/document.xml +7 -0
  134. data/lib/xamplr/xml/elements.xml +101 -0
  135. data/lib/xamplr/xml/elements000.xml +73 -0
  136. data/lib/xamplr/xml/example.xml +23 -0
  137. data/lib/xamplr/xml/options.xml +12 -0
  138. data/lib/xamplr/xml/uche.xml +38 -0
  139. data/lib/xamplr/yEd-sample.graphml +300 -0
  140. data/test/test_helper.rb +10 -0
  141. data/test/xamplr_test.rb +7 -0
  142. metadata +245 -0
@@ -0,0 +1,2 @@
1
+ Xampl.set_default_persister_kind(:tokyo_cabinet)
2
+ Xampl.set_default_persister_format(:xml_format)
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env ruby -w -I..
2
+
3
+ if $0 == __FILE__ then
4
+
5
+ class File
6
+ def File.sjoin(*args)
7
+ File.join(args.select{ | o | o })
8
+ end
9
+ end
10
+
11
+ require 'xamplr-generator'
12
+
13
+ include XamplGenerator
14
+ include Xampl
15
+
16
+ Xampl.transaction("setup", :in_memory) do
17
+ directory = File.sjoin(".", "xampl_generated_code")
18
+
19
+ options = Xampl.make(Options) do |options|
20
+ options.new_index_attribute("pid").persisted = true
21
+ options.new_index_attribute("id")
22
+
23
+ options.resolve("http://xampl.com/performance", "Perf", "p")
24
+ end
25
+
26
+ filenames = Dir.glob("./xml/**/*.xml")
27
+
28
+ generator = Generator.new
29
+ generator.go(:options => options,
30
+ :filenames => filenames,
31
+ :directory => directory)
32
+
33
+ #puts generator.print_elements("./generated-elements.xml")
34
+ exit!
35
+ end
36
+ end
@@ -0,0 +1,8 @@
1
+ <root pid=''
2
+ xmlns="http://xampl.com/performance">
3
+ <text pid=''
4
+ size=''
5
+ stuff=''>
6
+ actual text
7
+ </text>
8
+ </root>
@@ -0,0 +1,42 @@
1
+ require 'rubygems'
2
+
3
+ $LOAD_PATH.unshift("xampl_generated_code")
4
+
5
+ require 'TokyoCabinetExperimental'
6
+
7
+ Xampl.set_default_persister_kind(:tokyo_cabinet)
8
+ Xampl.set_default_persister_format(:xml_format)
9
+
10
+ module TokyoCabinetExperimental
11
+
12
+ start = Time.now
13
+ found = Xampl.transaction("setup") do
14
+ Xampl.query do | q |
15
+ q.add_condition('age', :numle, '50')
16
+ q.order_by('age', :numasc)
17
+ end
18
+ end
19
+ query_done = Time.now
20
+
21
+ total = 0
22
+ found.each do | person_meta |
23
+ total += person_meta['age'].to_i
24
+ end
25
+
26
+ meta_done = Time.now
27
+
28
+ total1 = 0
29
+ found.each do | person_meta |
30
+ total1 += person_meta['xampl'].age.to_i
31
+ end
32
+
33
+ done = Time.now
34
+
35
+ found.each do | person_meta |
36
+ puts "name: #{ person_meta['name']}"
37
+ end
38
+ puts "found: #{ found.size }"
39
+ puts "Total age: #{ total }, #{ total1 }"
40
+ puts "done: #{ done - start }:: #{ query_done - start } + #{ meta_done - query_done } + #{ done - meta_done }"
41
+
42
+ end
@@ -0,0 +1,42 @@
1
+ require 'rubygems'
2
+
3
+ $LOAD_PATH.unshift("xampl_generated_code")
4
+
5
+ require 'TokyoCabinetExperimental'
6
+
7
+ Xampl.set_default_persister_kind(:tokyo_cabinet)
8
+ Xampl.set_default_persister_format(:xml_format)
9
+
10
+ module TokyoCabinetExperimental
11
+
12
+ start = Time.now
13
+ found = Xampl.transaction("setup") do
14
+ @@persister.query do | q |
15
+ q.add_condition('age', :numle, '50')
16
+ q.order_by('name', :strasc)
17
+ end
18
+ end
19
+ query_done = Time.now
20
+
21
+ total = 0
22
+ found.each do | person_meta |
23
+ total += person_meta['age'].to_i
24
+ end
25
+
26
+ meta_done = Time.now
27
+
28
+ total1 = 0
29
+ found.each do | person_meta |
30
+ total1 += person_meta['xampl'].age.to_i
31
+ end
32
+
33
+ done = Time.now
34
+
35
+ found.each do | person_meta |
36
+ puts "name: #{ person_meta['name']}"
37
+ end
38
+ puts "found: #{ found.size }"
39
+ puts "Total age: #{ total }, #{ total1 }"
40
+ puts "done: #{ done - start }:: #{ query_done - start } + #{ meta_done - query_done } + #{ done - meta_done }"
41
+
42
+ end
@@ -0,0 +1,41 @@
1
+ require 'rubygems'
2
+
3
+ $LOAD_PATH.unshift("xampl_generated_code")
4
+
5
+ require 'TokyoCabinetExperimental'
6
+
7
+ Xampl.set_default_persister_kind(:tokyo_cabinet)
8
+ Xampl.set_default_persister_format(:xml_format)
9
+
10
+ module TokyoCabinetExperimental
11
+
12
+ start = Time.now
13
+ found = Xampl.transaction("setup") do
14
+ @@persister.query do | q |
15
+ q.add_condition('age', :numle, '50')
16
+ end
17
+ end
18
+ query_done = Time.now
19
+
20
+ total = 0
21
+ found.each do | person_meta |
22
+ total += person_meta['age'].to_i
23
+ end
24
+
25
+ meta_done = Time.now
26
+
27
+ total1 = 0
28
+ found.each do | person_meta |
29
+ total1 += person_meta['xampl'].age.to_i
30
+ end
31
+
32
+ done = Time.now
33
+
34
+ found.each do | person_meta |
35
+ puts "name: #{ person_meta['name']}"
36
+ end
37
+ puts "found: #{ found.size }"
38
+ puts "Total age: #{ total }, #{ total1 }"
39
+ puts "done: #{ done - start }:: #{ query_done - start } + #{ meta_done - query_done } + #{ done - meta_done }"
40
+
41
+ end
@@ -0,0 +1,32 @@
1
+ require 'rubygems'
2
+
3
+ $LOAD_PATH.unshift("xampl_generated_code")
4
+
5
+ require 'TokyoCabinetExperimental'
6
+
7
+ Xampl.set_default_persister_kind(:tokyo_cabinet)
8
+ Xampl.set_default_persister_format(:xml_format)
9
+
10
+ module TokyoCabinetExperimental
11
+
12
+ start = Time.now
13
+ people = nil
14
+
15
+ Xampl.transaction("setup") do
16
+ people = People['people']
17
+ end
18
+
19
+ loop_start = Time.now
20
+
21
+ total = 0
22
+ people.person.each do | person |
23
+ age = person.age.to_i
24
+ total += age
25
+ end
26
+
27
+ done = Time.now
28
+
29
+ puts "Total age: #{ total }"
30
+ puts "done: #{ done - start }:: #{ loop_start - start} + #{ done - loop_start}"
31
+
32
+ end
@@ -0,0 +1,61 @@
1
+ require 'rubygems'
2
+
3
+ $LOAD_PATH.unshift("xampl_generated_code")
4
+
5
+ require 'TokyoCabinetExperimental'
6
+
7
+ Xampl.set_default_persister_kind(:tokyo_cabinet)
8
+ Xampl.set_default_persister_format(:xml_format)
9
+
10
+ module TokyoCabinetExperimental
11
+
12
+ class Person
13
+ def describe_yourself
14
+ {
15
+ 'name' => self.name,
16
+ 'age' => self.age
17
+ }
18
+ end
19
+ end
20
+
21
+ people = nil
22
+ n = 1000
23
+
24
+ start = Time.now
25
+ Xampl.transaction("setup") do
26
+ people = People.new('people')
27
+ jack = people.ensure_person('jack')
28
+ jack.age = '0'
29
+ jack.name = 'jack'
30
+ jill = people.ensure_person('jill')
31
+ jill.age = '0'
32
+ jill.name = 'jill'
33
+
34
+ (1..n).each do | i |
35
+ person = people.ensure_person("person-#{i}")
36
+ person.age = i.to_s
37
+ person.name = "person-#{ i }"
38
+ end
39
+ end
40
+
41
+ start_search = Time.now
42
+
43
+ found = Xampl.transaction("setup") do
44
+ puts ">>>>>> #{@@persister.class.name}"
45
+ @@persister.query do | q |
46
+ puts ">>>> #{ q.class.name }"
47
+ q.add_condition('age', :numle, '50')
48
+ q.order_by('age', :numasc)
49
+ end
50
+ end
51
+
52
+ # found.each do | person |
53
+ # puts "person(#{person[:pk]}):: age: #{person['age']}"
54
+ # end
55
+
56
+ done = Time.now
57
+ puts "done: #{ done - start }:: construct in: #{ start_search - start}, search in: #{ done - start_search} (#{ found.size } results)"
58
+ puts "added: #{ n }, found: #{ found.size }"
59
+
60
+ # puts people.pp_xml
61
+ end
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env ruby -w -I..
2
+
3
+ if $0 == __FILE__ then
4
+
5
+ class File
6
+ def File.sjoin(*args)
7
+ File.join(args.select{ | o | o })
8
+ end
9
+ end
10
+
11
+ require 'xamplr-generator'
12
+
13
+ include XamplGenerator
14
+ include Xampl
15
+
16
+ Xampl.transaction("setup", :in_memory) do
17
+ directory = File.sjoin(".", "xampl_generated_code")
18
+
19
+ options = Xampl.make(Options) do |options|
20
+ options.new_index_attribute("pid").persisted = true
21
+ options.new_index_attribute("id")
22
+
23
+ options.resolve("http://xampl.com/tcx", "TokyoCabinetExperimental", "tcx")
24
+ end
25
+
26
+ filenames = Dir.glob("./xml/**/*.xml")
27
+
28
+ generator = Generator.new
29
+ generator.go(:options => options,
30
+ :filenames => filenames,
31
+ :directory => directory)
32
+
33
+ #puts generator.print_elements("./generated-elements.xml")
34
+ exit!
35
+ end
36
+ end
@@ -0,0 +1,6 @@
1
+ <people pid=''
2
+ xmlns="http://xampl.com/tcx">
3
+ <person pid=''
4
+ name=''
5
+ age=''/>
6
+ </people>
@@ -0,0 +1,3 @@
1
+
2
+ require "xamplr-generator"
3
+
data/lib/xampl.rb ADDED
@@ -0,0 +1,3 @@
1
+
2
+ require "xamplr"
3
+
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ module Xampl
4
+
5
+ require "xamplr"
6
+ require "xamplr/xampl-generator"
7
+
8
+ end
9
+
10
+
data/lib/xamplr.rb ADDED
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ module Xampl
4
+
5
+ require "yaml"
6
+ require "logger"
7
+
8
+ require "xamplr-pp"
9
+
10
+ @@logger = Logger.new(STDOUT)
11
+ @@logger.level = Logger::WARN
12
+
13
+ def Xampl.log
14
+ return @@logger
15
+ end
16
+
17
+ require "xamplr/xampl-module"
18
+ require "xamplr/xampl-object-internals"
19
+ require "xamplr/xampl-object"
20
+ require "xamplr/xampl-persisted-object"
21
+
22
+ require "xamplr/exceptions"
23
+ require "xamplr/xml-text"
24
+ require "xamplr/notifications"
25
+ require "xamplr/mixins"
26
+
27
+ require "xamplr/from-xml"
28
+ require "xamplr/to-xml"
29
+ require "xamplr/to-ruby"
30
+
31
+ require "xamplr/visitor"
32
+ require "xamplr/persist-to-xml"
33
+ require "xamplr/visitors"
34
+
35
+ end
36
+
37
+
@@ -0,0 +1,5 @@
1
+
2
+ I modified from-xml around 180-190 in a couple of places, marked with TODO comments
3
+
4
+ Why this cropped up now I DO NOT KNOW and this makes me nervous.
5
+
data/lib/xamplr/TODO ADDED
@@ -0,0 +1 @@
1
+ -- escaped content is being repeatedly escaped (confirm, just a suspiscion from a long time ago)
@@ -0,0 +1,97 @@
1
+
2
+ module Xampl
3
+
4
+ class XamplIsInvalid < Exception
5
+ attr_reader :msg, :xampl
6
+
7
+ def initialize(xampl)
8
+ @xampl = xampl
9
+ @msg = "Invalid Xampl:: #{xampl}"
10
+ end
11
+
12
+ def message
13
+ @msg
14
+ end
15
+ end
16
+
17
+ class AlreadyKnownToPersister < Exception
18
+ attr_reader :msg, :xampl
19
+
20
+ def initialize(xampl, persister)
21
+ @xampl = xampl
22
+ @msg = "#{xampl} #{xampl.get_the_index} is already known by a persister: #{xampl.persister.name}, so cannot use persister #{persister.name}"
23
+ end
24
+
25
+ def message
26
+ @msg
27
+ end
28
+ end
29
+
30
+ class XamplException < Exception
31
+ attr_reader :name, :msg
32
+
33
+ def initialize(name, message=nil)
34
+ @name = name
35
+ @msg = message ? message : ""
36
+ end
37
+
38
+ def message
39
+ "XamplException #{@name} #{@msg}"
40
+ end
41
+ end
42
+
43
+ class NoActivePersister < Exception
44
+ def message
45
+ "No Persister is active"
46
+ end
47
+ end
48
+
49
+ class BlockedChange < Exception
50
+ attr_reader :xampl
51
+
52
+ def initialize(xampl=nil)
53
+ @xampl = xampl
54
+ end
55
+
56
+ def message
57
+ "attempt to change #{@xampl}, pid: #{@xampl.get_the_index}, oid: #{@xampl.object_id} when changes are blocked"
58
+ end
59
+ end
60
+
61
+ class UnmanagedChange < Exception
62
+ attr_reader :xampl
63
+
64
+ def initialize(xampl=nil)
65
+ @xampl = xampl
66
+ end
67
+
68
+ def message
69
+ "attempt to change #{@xampl}, pid: #{@xampl.get_the_index}, oid: #{@xampl.object_id} outside of its persister's management"
70
+ end
71
+ end
72
+
73
+ class IncompatiblePersisterRequest < Exception
74
+ attr_reader :msg
75
+
76
+ def initialize(persister, feature_name, requested_feature_value, actual_feature_value)
77
+ @msg = "persister #{persister.name}:: requested feature: #{feature_name} #{requested_feature_value}, actual: #{actual_feature_value}"
78
+ end
79
+
80
+ def message
81
+ @msg
82
+ end
83
+ end
84
+
85
+ class MixedPersisters < Exception
86
+ attr_reader :msg
87
+
88
+ def initialize(active, local)
89
+ @msg = "mixed persisters:: active #{active.name}, local: #{local.name}"
90
+ end
91
+
92
+ def message
93
+ @msg
94
+ end
95
+ end
96
+
97
+ end