ruby_mvc 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. data/LICENSE +19 -0
  2. data/README.md +69 -0
  3. data/lib/ruby_mvc.rb +33 -0
  4. data/lib/ruby_mvc/application.rb +53 -0
  5. data/lib/ruby_mvc/controllers/app_controller.rb +93 -0
  6. data/lib/ruby_mvc/controllers/rails_controller.rb +71 -0
  7. data/lib/ruby_mvc/models.rb +28 -0
  8. data/lib/ruby_mvc/models/array_table_model.rb +59 -0
  9. data/lib/ruby_mvc/models/keyed_array_table_model.rb +83 -0
  10. data/lib/ruby_mvc/models/table_model.rb +42 -0
  11. data/lib/ruby_mvc/module.rb +35 -0
  12. data/lib/ruby_mvc/renderers.rb +26 -0
  13. data/lib/ruby_mvc/renderers/html4_table_model_renderer.rb +100 -0
  14. data/lib/ruby_mvc/toolkit.rb +31 -0
  15. data/lib/ruby_mvc/toolkit/app.rb +32 -0
  16. data/lib/ruby_mvc/toolkit/dialog.rb +31 -0
  17. data/lib/ruby_mvc/toolkit/frame.rb +34 -0
  18. data/lib/ruby_mvc/toolkit/notification.rb +202 -0
  19. data/lib/ruby_mvc/toolkit/peers/wxruby.rb +31 -0
  20. data/lib/ruby_mvc/toolkit/peers/wxruby/app.rb +44 -0
  21. data/lib/ruby_mvc/toolkit/peers/wxruby/box_layout.rb +48 -0
  22. data/lib/ruby_mvc/toolkit/peers/wxruby/common.rb +72 -0
  23. data/lib/ruby_mvc/toolkit/peers/wxruby/frame.rb +49 -0
  24. data/lib/ruby_mvc/toolkit/peers/wxruby/web_view.rb +87 -0
  25. data/lib/ruby_mvc/toolkit/web_view.rb +60 -0
  26. data/lib/ruby_mvc/toolkit/widget.rb +108 -0
  27. data/lib/ruby_mvc/views.rb +85 -0
  28. data/lib/ruby_mvc/views/ar_model_editor.rb +84 -0
  29. data/lib/ruby_mvc/views/ar_type_editor.rb +65 -0
  30. data/lib/ruby_mvc/views/ar_type_list.rb +45 -0
  31. data/lib/ruby_mvc/views/table_view.rb +96 -0
  32. data/lib/ruby_mvc/views/web_view.rb +65 -0
  33. data/lib/ruby_mvc/wx.rb +26 -0
  34. data/ruby_mvc.gemspec +37 -0
  35. data/sample/frame.rb +28 -0
  36. data/sample/mvc.rb +29 -0
  37. data/sample/test.html +118 -0
  38. data/sample/web_view.rb +34 -0
  39. data/test/unit/models/test_array_table_model.rb +56 -0
  40. data/test/unit/models/test_keyed_array_table_model.rb +54 -0
  41. data/test/unit/test_array_table_model.rb +38 -0
  42. metadata +107 -0
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ ######################################################################
2
+ #
3
+ # Copyright 2011 Andrew S. Townley
4
+ #
5
+ # Permission to use, copy, modify, and disribute this software for
6
+ # any purpose with or without fee is hereby granted, provided that
7
+ # the above copyright notices and this permission notice appear in
8
+ # all copies.
9
+ #
10
+ # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL
11
+ # WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13
+ # AUTHORS BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT OR
14
+ # CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15
+ # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
16
+ # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
17
+ # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
+ #
19
+ ######################################################################
data/README.md ADDED
@@ -0,0 +1,69 @@
1
+
2
+ README for Ruby MVC
3
+ ===================
4
+
5
+ This project is based on previous work on [Shoes
6
+ MVC](https://github.com/atownley/shoes_mvc), but now does not
7
+ use the Shoes toolkit. At the moment, it achieves a minimal set of
8
+ cross-platform functionality based on using the wxRuby gem. There are
9
+ plans to make this change in the future, but right now, the goal is
10
+ just to get something working.
11
+
12
+ *NOTE: this code is **highly experimental** and an early work
13
+ in progress. It may or may not ever be completed, and it may
14
+ or may not ever be useful.*
15
+
16
+ DEPENDENCIES
17
+ ============
18
+
19
+ You'll need to have the following gems installed to use this library:
20
+
21
+ - activerecord (to use the Rails integration)
22
+ - tagz (for the HTML rendering)
23
+ - wxruby (use wxruby-ruby19 for Ruby 1.9)
24
+ - sqlite3 (to use the SQLite3 drivers)
25
+
26
+ Platform Notes
27
+ --------------
28
+
29
+ There are some tweaks required using the library with various
30
+ environments. The known ones are highlighted below.
31
+
32
+ ### Ruby 1.8.7
33
+
34
+ Apparently, there's a change in 1.8.7 that causes trouble with SWIG
35
+ libraries: http://www.ruby-forum.com/topic/161876. You may or may not
36
+ hit this problem running 1.8.7, as it appears to be rather
37
+ intermittent.
38
+
39
+
40
+ ### MacOS X
41
+
42
+ If you're using this on a 64-bit version of OSX, you'll want to make
43
+ sure you do the following when you're installing the dependency gems:
44
+
45
+ $ env ARCHFLAGS="-arch x86_64 -arch i686" gem install --no-ri --no-rdoc
46
+
47
+ The above line will ensure that when you run in 32-bit mode for
48
+ wxRuby, that things will all work as expected.
49
+
50
+ Additionally, you might consider an alias like the following somewhere
51
+ handy like .profile or .bashrc
52
+
53
+ $ alias wxruby="arch -i386 ruby -rubygems"
54
+
55
+ This link is also useful if using rvm and ruby 1.9.x:
56
+ http://www.ruby-forum.com/topic/212707#969982. The magic is this
57
+ command:
58
+
59
+ $ rvm install ruby-1.9.2-head -C --with-arch=x86_64,i386
60
+
61
+ Once you do the above, you should be able to successfully install the
62
+ wxruby-ruby19 gem using the following platform magic:
63
+
64
+ $ gem install --platform x86-darwin-9 --no-ri --no-rdoc wxruby-ruby19
65
+
66
+ ### Windows
67
+
68
+ Amazingly enough, it seems to *just work* on Windows (Vista is the
69
+ only tested configuration at the moment). YMMV.
data/lib/ruby_mvc.rb ADDED
@@ -0,0 +1,33 @@
1
+ #--
2
+ ######################################################################
3
+ #
4
+ # Copyright 2011 Andrew S. Townley
5
+ #
6
+ # Permission to use, copy, modify, and disribute this software for
7
+ # any purpose with or without fee is hereby granted, provided that
8
+ # the above copyright notices and this permission notice appear in
9
+ # all copies.
10
+ #
11
+ # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL
12
+ # WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
13
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
14
+ # AUTHORS BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT OR
15
+ # CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
16
+ # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
17
+ # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
18
+ # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
+ #
20
+ # File: ruby_mvc.rb
21
+ # Created: Sat 19 Nov 2011 11:24:19 GMT
22
+ #
23
+ ######################################################################
24
+ #++
25
+
26
+ require 'yaml'
27
+ require 'ruby_mvc/module'
28
+ require 'ruby_mvc/toolkit'
29
+ require 'ruby_mvc/renderers'
30
+ require 'ruby_mvc/controllers/app_controller'
31
+ require 'ruby_mvc/models'
32
+ require 'ruby_mvc/views'
33
+ require 'ruby_mvc/application'
@@ -0,0 +1,53 @@
1
+ #--
2
+ ######################################################################
3
+ #
4
+ # Copyright 2011 Andrew S. Townley
5
+ #
6
+ # Permission to use, copy, modify, and disribute this software for
7
+ # any purpose with or without fee is hereby granted, provided that
8
+ # the above copyright notices and this permission notice appear in
9
+ # all copies.
10
+ #
11
+ # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL
12
+ # WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
13
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
14
+ # AUTHORS BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT OR
15
+ # CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
16
+ # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
17
+ # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
18
+ # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
+ #
20
+ # File: application.rb
21
+ # Created: Wed 23 Nov 2011 11:01:20 GMT
22
+ #
23
+ ######################################################################
24
+ #++
25
+
26
+ module RubyMVC
27
+
28
+ # This provides the entry point for a basic application.
29
+ class Application
30
+ attr_accessor :frame
31
+ attr_accessor :controller
32
+
33
+ def initialize(options, &block)
34
+ self.frame = Toolkit::Frame.new(options)
35
+ if cc = options[:controller]
36
+ self.controller = cc
37
+ self.controller.app = self
38
+ self.controller.init
39
+ end
40
+ self.instance_eval(&block) if block
41
+ self.frame.show
42
+ end
43
+ end
44
+
45
+ # This method creates a default application and runs it
46
+ # using the active toolkit.
47
+
48
+ def self.app(*args, &block)
49
+ Toolkit::App.new do
50
+ Application.new(*args, &block)
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,93 @@
1
+ #--
2
+ ######################################################################
3
+ #
4
+ # Copyright 2011 Andrew S. Townley
5
+ #
6
+ # Permission to use, copy, modify, and disribute this software for
7
+ # any purpose with or without fee is hereby granted, provided that
8
+ # the above copyright notices and this permission notice appear in
9
+ # all copies.
10
+ #
11
+ # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL
12
+ # WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
13
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
14
+ # AUTHORS BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT OR
15
+ # CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
16
+ # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
17
+ # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
18
+ # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
+ #
20
+ # File: app_controller.rb
21
+ # Created: Sat 19 Nov 2011 11:29:49 GMT
22
+ #
23
+ #####################################################################
24
+ #++
25
+
26
+ module RubyMVC
27
+
28
+ # This module takes care of dispatching links to controller
29
+ # classes.
30
+
31
+ module LinkDispatcher
32
+ # This method is a callback to allow links embedded in
33
+ # views to trigger controller actions in a loosely-coupled
34
+ # manner.
35
+ #
36
+ # The default implementation will attempt to call methods
37
+ # based on applying the RubyMVC#method_name
38
+ # transformation and checking if the controller responds
39
+ # to the method. To manually dispatch the method, simply
40
+ # override this method in the derived class.
41
+
42
+ def link_activated(sender, link)
43
+ puts "#link_activated(#{sender}, #{link})"
44
+ m = RubyMVC.method_name(link).to_sym
45
+ if self.respond_to? m
46
+ self.send(m, sender, link)
47
+ end
48
+ end
49
+ end
50
+
51
+ class AppController
52
+ include LinkDispatcher
53
+
54
+ attr_accessor :app
55
+
56
+ # By convention, the application is configured using an
57
+ # app.yml file in the same directory as the application
58
+ # controller.
59
+
60
+ def initialize(app_file)
61
+ @config_file = File.expand_path(File.join(File.dirname(app_file), "../app.yml"))
62
+ if !File.exist? @config_file
63
+ @shoes.alert("Unable to locate configuration file.\nFile '#{@config_file}' not found.")
64
+ @shoes.exit
65
+ end
66
+
67
+ @config = YAML.load(File.new(@config_file))
68
+ setup
69
+ run
70
+ end
71
+
72
+ # This method is a placeholder for the actual
73
+ # initialization to be performed by the Ruby application
74
+ # itself. It is called automatically by the constructor
75
+ # of the application controller.
76
+
77
+ def run
78
+ end
79
+
80
+ protected
81
+ def config
82
+ @config || {}
83
+ end
84
+
85
+ # This method is called prior to calling the #run method
86
+ # to give the derived controller classes an opportunity to
87
+ # perform any specific initialization.
88
+
89
+ def setup
90
+ end
91
+ end
92
+
93
+ end
@@ -0,0 +1,71 @@
1
+ #--
2
+ ######################################################################
3
+ #
4
+ # Copyright 2011 Andrew S. Townley
5
+ #
6
+ # Permission to use, copy, modify, and disribute this software for
7
+ # any purpose with or without fee is hereby granted, provided that
8
+ # the above copyright notices and this permission notice appear in
9
+ # all copies.
10
+ #
11
+ # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL
12
+ # WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
13
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
14
+ # AUTHORS BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT OR
15
+ # CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
16
+ # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
17
+ # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
18
+ # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
+ #
20
+ # File: rails_controller.rb
21
+ # Created: Sat 19 Nov 2011 11:29:49 GMT
22
+ #
23
+ #####################################################################
24
+ #++
25
+
26
+ require 'active_record'
27
+
28
+ module RubyMVC
29
+
30
+ # This controller is used to assist in writing Ruby
31
+ # applications for an existing Rails application. All of
32
+ # the models will be automatically loaded based on the
33
+ # directory configuration of the Rails environment, and the
34
+ # database connection environment will be used.
35
+ #
36
+ # This controller uses the following configuration settings
37
+ # to help it initialize itself:
38
+ #
39
+ # rails_app - the location of the app directory of the Rails
40
+ # application
41
+ #
42
+ # config - the default database configuration to use by
43
+ # the application
44
+
45
+ class RailsController < AppController
46
+ def setup
47
+ @rails_app = File.expand_path(File.join(
48
+ File.dirname(@config_file), config["rails_app"]))
49
+ connect_db
50
+ load_models
51
+ end
52
+
53
+ private
54
+ def connect_db
55
+ yml = File.expand_path(File.join(@rails_app, "../config/database.yml"))
56
+ dbconf = YAML.load(File.new(yml))
57
+ env = dbconf[config["config"]]
58
+
59
+ case(env["adapter"])
60
+ when "sqlite3"
61
+ env["database"] = File.join("#{@rails_app}/..", env["database"])
62
+ end
63
+ ActiveRecord::Base.establish_connection(env)
64
+ end
65
+
66
+ def load_models
67
+ Dir.glob(File.join(@rails_app, "models/*.rb")) { |m| require m }
68
+ end
69
+ end
70
+
71
+ end
@@ -0,0 +1,28 @@
1
+ #--
2
+ ######################################################################
3
+ #
4
+ # Copyright 2011 Andrew S. Townley
5
+ #
6
+ # Permission to use, copy, modify, and disribute this software for
7
+ # any purpose with or without fee is hereby granted, provided that
8
+ # the above copyright notices and this permission notice appear in
9
+ # all copies.
10
+ #
11
+ # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL
12
+ # WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
13
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
14
+ # AUTHORS BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT OR
15
+ # CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
16
+ # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
17
+ # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
18
+ # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
+ #
20
+ # File: models.rb
21
+ # Created: Sat 19 Nov 2011 19:50:32 GMT
22
+ #
23
+ #####################################################################
24
+ #++
25
+
26
+ require 'ruby_mvc/models/table_model'
27
+ require 'ruby_mvc/models/array_table_model'
28
+ require 'ruby_mvc/models/keyed_array_table_model'
@@ -0,0 +1,59 @@
1
+ #--
2
+ ######################################################################
3
+ #
4
+ # Copyright 2011 Andrew S. Townley
5
+ #
6
+ # Permission to use, copy, modify, and disribute this software for
7
+ # any purpose with or without fee is hereby granted, provided that
8
+ # the above copyright notices and this permission notice appear in
9
+ # all copies.
10
+ #
11
+ # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL
12
+ # WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
13
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
14
+ # AUTHORS BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT OR
15
+ # CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
16
+ # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
17
+ # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
18
+ # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
+ #
20
+ # File: array_table_model.rb
21
+ # Created: Sat 19 Nov 2011 19:56:17 GMT
22
+ #
23
+ #####################################################################
24
+ #++
25
+
26
+ module ShoesMVC
27
+ module Models
28
+
29
+ # This class implements the TableModel interface based on
30
+ # the data being stored in an array. The elements in the
31
+ # array must either be a Hash, or they must respond to the
32
+ # [] accessors for retrieving elements by key and implement
33
+ # a #keys method for indicating the properties in each row
34
+ # instance.
35
+
36
+ class ArrayTableModel < TableModel
37
+ def initialize(data)
38
+ @data = data
39
+ end
40
+
41
+ def keys
42
+ if @data && @data.size > 0
43
+ @data.keys
44
+ else
45
+ {}
46
+ end
47
+ end
48
+
49
+ def each(&block)
50
+ @data.each(&block)
51
+ end
52
+
53
+ def each_with_index(&block)
54
+ @data.each_with_index(&block)
55
+ end
56
+ end
57
+
58
+ end
59
+ end
@@ -0,0 +1,83 @@
1
+ #--
2
+ ######################################################################
3
+ #
4
+ # Copyright 2011 Andrew S. Townley
5
+ #
6
+ # Permission to use, copy, modify, and disribute this software for
7
+ # any purpose with or without fee is hereby granted, provided that
8
+ # the above copyright notices and this permission notice appear in
9
+ # all copies.
10
+ #
11
+ # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL
12
+ # WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
13
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
14
+ # AUTHORS BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT OR
15
+ # CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
16
+ # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
17
+ # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
18
+ # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
+ #
20
+ # File: keyed_array_table_model.rb
21
+ # Created: Sat 19 Nov 2011 18:58:36 GMT
22
+ #
23
+ #####################################################################
24
+ #++
25
+
26
+ module ShoesMVC
27
+ module Models
28
+
29
+ class KeyedArrayTableModel < TableModel
30
+
31
+ # This class provides a row adapter for each row in the
32
+ # array so that it behaves effectively like a Hash
33
+ # instance, but which still allows the underlying array to
34
+ # be manipulated without problem.
35
+
36
+ class Row
37
+ # The instance is created with an array of strings or
38
+ # symbols used to denote the keys of the model. The keys
39
+ # MUST be specified in the order of the data elements in
40
+ # the data array. When the model is asked for the value
41
+ # for a given key, the value is retrieved from the data
42
+ # array by the position of the key in the keys array.
43
+
44
+ def initialize(keys, row)
45
+ @keys = keys
46
+ @row = row
47
+ end
48
+
49
+ def [](key)
50
+ @row[@keys[key.to_sym]]
51
+ end
52
+
53
+ def []=(key, val)
54
+ @row[@keys[key.to_sym]] = val
55
+ end
56
+ end
57
+
58
+ # This method is used to initialize the mo
59
+ def initialize(keys, data)
60
+ @keys = {}
61
+ keys.each_with_index { |x, i| @keys[x.to_sym] = i }
62
+ @data = data
63
+ end
64
+
65
+ def keys
66
+ @keys.keys
67
+ end
68
+
69
+ def each(&block)
70
+ @data.each do |x|
71
+ block.call(Row.new(@keys, x))
72
+ end
73
+ end
74
+
75
+ def each_with_index(&block)
76
+ @data.each_with_index do |x, i|
77
+ block.call(Row.new(@keys, x), i)
78
+ end
79
+ end
80
+ end
81
+
82
+ end
83
+ end