mits 0.1.0 → 0.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.
- checksums.yaml +4 -4
- data/.gitignore +1 -1
- data/README.md +4 -4
- data/lib/mits.rb +4 -1
- data/lib/mits/base_mapper.rb +20 -0
- data/lib/mits/document.rb +16 -5
- data/lib/mits/saxerator_ext.rb +8 -1
- data/lib/mits/v3.0/address.rb +20 -0
- data/lib/mits/v3.0/amenity.rb +12 -0
- data/lib/mits/v3.0/company.rb +13 -0
- data/lib/mits/v3.0/deposit.rb +13 -0
- data/lib/mits/v3.0/fees.rb +17 -0
- data/lib/mits/v3.0/file.rb +18 -0
- data/lib/mits/v3.0/floorplan.rb +13 -0
- data/lib/mits/v3.0/mapper.rb +50 -0
- data/lib/mits/v3.0/mapper/address_mapper.rb +35 -0
- data/lib/mits/v3.0/mapper/amenities_mapper.rb +19 -0
- data/lib/mits/v3.0/mapper/company_mapper.rb +15 -0
- data/lib/mits/v3.0/mapper/deposit_mapper.rb +32 -0
- data/lib/mits/v3.0/mapper/fees_mapper.rb +19 -0
- data/lib/mits/v3.0/mapper/files_mapper.rb +25 -0
- data/lib/mits/v3.0/mapper/floorplan_mapper.rb +27 -0
- data/lib/mits/v3.0/mapper/pet_policy_mapper.rb +37 -0
- data/lib/mits/v3.0/mapper/policy_mapper.rb +12 -0
- data/lib/mits/v3.0/mapper/property_mapper.rb +57 -0
- data/lib/mits/v3.0/pet.rb +13 -0
- data/lib/mits/v3.0/pet_policy.rb +17 -0
- data/lib/mits/v3.0/policy.rb +10 -0
- data/lib/mits/v3.0/property.rb +23 -0
- data/lib/mits/v4.1/address.rb +21 -0
- data/lib/mits/v4.1/amenity.rb +21 -0
- data/lib/mits/v4.1/company.rb +8 -0
- data/lib/mits/v4.1/deposit.rb +8 -0
- data/lib/mits/v4.1/fees.rb +8 -0
- data/lib/mits/v4.1/file.rb +8 -0
- data/lib/mits/v4.1/mapper.rb +45 -0
- data/lib/mits/v4.1/mapper/address_mapper.rb +29 -0
- data/lib/mits/v4.1/mapper/company_mapper.rb +9 -0
- data/lib/mits/v4.1/mapper/property_mapper.rb +48 -0
- data/lib/mits/v4.1/mapper/units_mapper.rb +26 -0
- data/lib/mits/v4.1/pet.rb +8 -0
- data/lib/mits/v4.1/pet_policy.rb +8 -0
- data/lib/mits/v4.1/policy.rb +8 -0
- data/lib/mits/v4.1/property.rb +22 -0
- data/lib/mits/v4.1/unit.rb +13 -0
- data/lib/mits/version.rb +1 -1
- data/mits.gemspec +5 -4
- data/spec/fixtures/MITS_3.0_Property.yml +583 -0
- data/spec/fixtures/MITS_3.0_Sample.xml +589 -0
- data/spec/fixtures/{property.yml → MITS_4.1_Property.yml} +0 -0
- data/spec/fixtures/{mits.xml → MITS_4.1_Sample.xml} +0 -0
- data/spec/lib/mits/document_spec.rb +3 -3
- data/spec/lib/mits/v3.0/address_spec.rb +21 -0
- data/spec/lib/mits/v3.0/amenity_spec.rb +13 -0
- data/spec/lib/mits/{entities → v3.0}/company_spec.rb +0 -0
- data/spec/lib/mits/v3.0/deposit_spec.rb +14 -0
- data/spec/lib/mits/v3.0/fees_spec.rb +18 -0
- data/spec/lib/mits/v3.0/file_spec.rb +20 -0
- data/spec/lib/mits/v3.0/floorplan_spec.rb +14 -0
- data/spec/lib/mits/v3.0/mapper_spec.rb +198 -0
- data/spec/lib/mits/v3.0/pet_policy_spec.rb +17 -0
- data/spec/lib/mits/v3.0/pet_spec.rb +15 -0
- data/spec/lib/mits/v3.0/property_spec.rb +23 -0
- data/spec/lib/mits/v4.1/address_spec.rb +22 -0
- data/spec/lib/mits/v4.1/amenity_spec.rb +11 -0
- data/spec/lib/mits/v4.1/company_spec.rb +0 -0
- data/spec/lib/mits/v4.1/deposit_spec.rb +14 -0
- data/spec/lib/mits/v4.1/fees_spec.rb +18 -0
- data/spec/lib/mits/v4.1/file_spec.rb +20 -0
- data/spec/lib/mits/v4.1/mapper_spec.rb +194 -0
- data/spec/lib/mits/v4.1/pet_policy_spec.rb +16 -0
- data/spec/lib/mits/v4.1/pet_spec.rb +15 -0
- data/spec/lib/mits/v4.1/property_spec.rb +23 -0
- data/spec/lib/mits/v4.1/unit_spec.rb +14 -0
- metadata +112 -53
- data/lib/mits/entities/address.rb +0 -16
- data/lib/mits/entities/amenity.rb +0 -8
- data/lib/mits/entities/company.rb +0 -11
- data/lib/mits/entities/deposit.rb +0 -11
- data/lib/mits/entities/fees.rb +0 -15
- data/lib/mits/entities/file.rb +0 -16
- data/lib/mits/entities/pet.rb +0 -11
- data/lib/mits/entities/pet_policy.rb +0 -15
- data/lib/mits/entities/property.rb +0 -20
- data/lib/mits/entities/unit.rb +0 -11
- data/lib/mits/mapper.rb +0 -48
- data/lib/mits/mappers/address_mapper.rb +0 -29
- data/lib/mits/mappers/amenities_mapper.rb +0 -14
- data/lib/mits/mappers/company_mapper.rb +0 -11
- data/lib/mits/mappers/deposit_mapper.rb +0 -24
- data/lib/mits/mappers/fees_mapper.rb +0 -15
- data/lib/mits/mappers/files_mapper.rb +0 -19
- data/lib/mits/mappers/pet_policy_mapper.rb +0 -28
- data/lib/mits/mappers/property_mapper.rb +0 -41
- data/lib/mits/mappers/units_mapper.rb +0 -22
- data/spec/lib/mits/entities/address_spec.rb +0 -16
- data/spec/lib/mits/entities/amenity_spec.rb +0 -8
- data/spec/lib/mits/entities/deposit_spec.rb +0 -11
- data/spec/lib/mits/entities/fees_spec.rb +0 -15
- data/spec/lib/mits/entities/file_spec.rb +0 -17
- data/spec/lib/mits/entities/pet_policy_spec.rb +0 -14
- data/spec/lib/mits/entities/pet_spec.rb +0 -12
- data/spec/lib/mits/entities/property_spec.rb +0 -20
- data/spec/lib/mits/entities/unit_spec.rb +0 -11
- data/spec/lib/mits/mapper_spec.rb +0 -180
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bbed76e9f570ddc78b834b3bd6b26afc0044c8e8
|
|
4
|
+
data.tar.gz: 4f5122214d0e595df65971b65966c1c78ba6575e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 12b04c823773fb1917f4fac79739a74c4f955a93e1cc16fa279a89331070f0c06ba651a53cb9b88324cc589afef949f8b8bae4ace94162b2c88b34e43f92c90a
|
|
7
|
+
data.tar.gz: 9a6eac1e8f0b43a2bb35df3b891f8e8de40a49302872647207aa2f87308dbed867b3918c81f6c5085e56bb06e95f4e9d7e862d9912c3dbdb0862f37abe9fc55c
|
data/.gitignore
CHANGED
data/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
A SAX powered reader for [Multifamily Information and Transactions Standard \(MITS\)](http://www.mitsproject.org/) compatible documents.
|
|
4
4
|
|
|
5
|
-
Currently supporting MITS __4.1__.
|
|
5
|
+
Currently supporting MITS __3.0__ & __4.1__ (default).
|
|
6
6
|
|
|
7
7
|
[](https://rubygems.org/gems/mits) [](https://travis-ci.org/doomspork/mits) [](https://codeclimate.com/github/doomspork/mits) [](https://coveralls.io/r/doomspork/mits?branch=master) [](https://gemnasium.com/doomspork/mits)
|
|
8
8
|
|
|
@@ -15,7 +15,7 @@ Currently supporting MITS __4.1__.
|
|
|
15
15
|
Create a `MITS::Document` with a local filepath or URL:
|
|
16
16
|
|
|
17
17
|
```ruby
|
|
18
|
-
document = MITS::Document.new('/example/path/mits_compatible_feed.xml')
|
|
18
|
+
document = MITS::Document.new('/example/path/mits_compatible_feed.xml', version: 3.0)
|
|
19
19
|
```
|
|
20
20
|
|
|
21
21
|
Iterating over properties is easy:
|
|
@@ -38,11 +38,11 @@ end
|
|
|
38
38
|
|
|
39
39
|
## Contributing
|
|
40
40
|
|
|
41
|
-
Feedback, feature requests, and fixes are
|
|
41
|
+
Feedback, feature requests, and fixes are welcomed and encouraged. Please make appropriate use of [Issues](https://github.com/doomspork/mits/issues) and [Pull Requests](https://github.com/doomspork/mits/pulls). All code should have accompanying tests.
|
|
42
42
|
|
|
43
43
|
## Author
|
|
44
44
|
|
|
45
|
-
MITS is written and maintained by [@doomspork](http://github.com/doomspork) as part of [CityLeash](https://cityleash.com).
|
|
45
|
+
MITS is written and maintained by [@doomspork](http://github.com/doomspork) as part of [CityLeash.com](https://cityleash.com).
|
|
46
46
|
|
|
47
47
|
## License
|
|
48
48
|
|
data/lib/mits.rb
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
require 'open-uri'
|
|
2
2
|
require 'saxerator'
|
|
3
3
|
require 'simple_objects'
|
|
4
|
+
require 'versions'
|
|
4
5
|
|
|
6
|
+
require 'mits/base_mapper'
|
|
5
7
|
require 'mits/document'
|
|
6
|
-
require 'mits/mapper'
|
|
7
8
|
require 'mits/saxerator_ext'
|
|
8
9
|
require 'mits/version'
|
|
9
10
|
|
|
10
11
|
module MITS
|
|
12
|
+
Versions.config.base_dir = File.join(File.realpath(__dir__), 'mits')
|
|
13
|
+
Versions.config.class_prefix = 'MITS::V'
|
|
11
14
|
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module MITS
|
|
2
|
+
module BaseMapper
|
|
3
|
+
protected
|
|
4
|
+
|
|
5
|
+
def bool(value)
|
|
6
|
+
value == 'true'
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def try(*values, method)
|
|
10
|
+
value, *args = values
|
|
11
|
+
return nil unless value
|
|
12
|
+
if value.respond_to?(method)
|
|
13
|
+
value.send(method)
|
|
14
|
+
elsif self.respond_to?(method)
|
|
15
|
+
args = [args] unless args.is_a? Array
|
|
16
|
+
self.send(method, value, *args)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
data/lib/mits/document.rb
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
module MITS
|
|
2
2
|
class Document
|
|
3
|
-
attr_reader :parser
|
|
3
|
+
attr_reader :parser, :version
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
DEFAULT_VERSION = '4.1'
|
|
6
|
+
|
|
7
|
+
def initialize(url, opts = {})
|
|
8
|
+
@version = (opts[:version] || DEFAULT_VERSION).to_s
|
|
9
|
+
@parser = ::Saxerator.parser(open(url)) do |c|
|
|
7
10
|
c.put_attributes_in_hash!
|
|
8
11
|
c.symbolize_keys!
|
|
9
12
|
end
|
|
@@ -13,7 +16,7 @@ module MITS
|
|
|
13
16
|
return enum_for(:properties) unless block_given?
|
|
14
17
|
|
|
15
18
|
physical_property.for_tag(:Property).each do |tag|
|
|
16
|
-
yield
|
|
19
|
+
yield mapper.property(tag)
|
|
17
20
|
end
|
|
18
21
|
end
|
|
19
22
|
|
|
@@ -21,15 +24,23 @@ module MITS
|
|
|
21
24
|
return enum_for(:companies) unless block_given?
|
|
22
25
|
|
|
23
26
|
physical_property.within(:Management).within(:PropertyContacts).each do |tag|
|
|
24
|
-
yield
|
|
27
|
+
yield mapper.company(tag, company_entity)
|
|
25
28
|
end
|
|
26
29
|
end
|
|
27
30
|
|
|
28
31
|
private
|
|
29
32
|
|
|
33
|
+
def company_entity
|
|
34
|
+
Versions.for(:company).select(version)
|
|
35
|
+
end
|
|
36
|
+
|
|
30
37
|
def physical_property
|
|
31
38
|
parser.within(:PhysicalProperty)
|
|
32
39
|
end
|
|
33
40
|
|
|
41
|
+
def mapper
|
|
42
|
+
@mapper ||= Versions.for(:mapper).select(version)
|
|
43
|
+
end
|
|
44
|
+
|
|
34
45
|
end
|
|
35
46
|
end
|
data/lib/mits/saxerator_ext.rb
CHANGED
|
@@ -2,7 +2,7 @@ module Saxerator
|
|
|
2
2
|
module Builder
|
|
3
3
|
class HashElement < Hash
|
|
4
4
|
def deep_hash
|
|
5
|
-
|
|
5
|
+
reduce({}) do |memo, (key, value)|
|
|
6
6
|
as_hash = if value.is_a? Array
|
|
7
7
|
value.map { |v| try_hash(v) }
|
|
8
8
|
else
|
|
@@ -25,5 +25,12 @@ module Saxerator
|
|
|
25
25
|
end
|
|
26
26
|
end
|
|
27
27
|
end
|
|
28
|
+
|
|
29
|
+
class StringElement
|
|
30
|
+
def to_h
|
|
31
|
+
to_s
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
28
35
|
end
|
|
29
36
|
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module MITS
|
|
2
|
+
module V3_0
|
|
3
|
+
class Address
|
|
4
|
+
include SimpleObjects::Base
|
|
5
|
+
|
|
6
|
+
attribute :address
|
|
7
|
+
attribute :city
|
|
8
|
+
attribute :country
|
|
9
|
+
attribute :county_name
|
|
10
|
+
attribute :description
|
|
11
|
+
attribute :latitude
|
|
12
|
+
attribute :longitude
|
|
13
|
+
attribute :postal_code
|
|
14
|
+
attribute :province
|
|
15
|
+
attribute :state
|
|
16
|
+
attribute :type
|
|
17
|
+
attribute :unparsed_address
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module MITS
|
|
2
|
+
module V3_0
|
|
3
|
+
class Fees
|
|
4
|
+
include SimpleObjects::Base
|
|
5
|
+
|
|
6
|
+
attribute :admin_fee
|
|
7
|
+
attribute :application_fee
|
|
8
|
+
attribute :broker_fee
|
|
9
|
+
attribute :late_fee_per_day
|
|
10
|
+
attribute :late_min_fee
|
|
11
|
+
attribute :late_percent
|
|
12
|
+
attribute :late_type
|
|
13
|
+
attribute :non_refundable_hold_fee
|
|
14
|
+
attribute :prorate_type
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module MITS
|
|
2
|
+
module V3_0
|
|
3
|
+
class File
|
|
4
|
+
include SimpleObjects::Base
|
|
5
|
+
|
|
6
|
+
attribute :active
|
|
7
|
+
attribute :caption
|
|
8
|
+
attribute :description
|
|
9
|
+
attribute :format
|
|
10
|
+
attribute :height
|
|
11
|
+
attribute :id
|
|
12
|
+
attribute :name
|
|
13
|
+
attribute :rank
|
|
14
|
+
attribute :source
|
|
15
|
+
attribute :width
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
require_relative 'address'
|
|
2
|
+
require_relative 'amenity'
|
|
3
|
+
require_relative 'company'
|
|
4
|
+
require_relative 'deposit'
|
|
5
|
+
require_relative 'fees'
|
|
6
|
+
require_relative 'file'
|
|
7
|
+
require_relative 'floorplan'
|
|
8
|
+
require_relative 'pet'
|
|
9
|
+
require_relative 'pet_policy'
|
|
10
|
+
require_relative 'policy'
|
|
11
|
+
require_relative 'property'
|
|
12
|
+
|
|
13
|
+
require_relative 'mapper/address_mapper'
|
|
14
|
+
require_relative 'mapper/amenities_mapper'
|
|
15
|
+
require_relative 'mapper/company_mapper'
|
|
16
|
+
require_relative 'mapper/deposit_mapper'
|
|
17
|
+
require_relative 'mapper/fees_mapper'
|
|
18
|
+
require_relative 'mapper/files_mapper'
|
|
19
|
+
require_relative 'mapper/floorplan_mapper'
|
|
20
|
+
require_relative 'mapper/pet_policy_mapper'
|
|
21
|
+
require_relative 'mapper/policy_mapper'
|
|
22
|
+
require_relative 'mapper/property_mapper'
|
|
23
|
+
|
|
24
|
+
module MITS
|
|
25
|
+
module V3_0
|
|
26
|
+
module Mapper
|
|
27
|
+
extend BaseMapper
|
|
28
|
+
|
|
29
|
+
extend AddressMapper
|
|
30
|
+
extend AmenitiesMapper
|
|
31
|
+
extend CompanyMapper
|
|
32
|
+
extend DepositMapper
|
|
33
|
+
extend FeesMapper
|
|
34
|
+
extend FilesMapper
|
|
35
|
+
extend FloorplanMapper
|
|
36
|
+
extend PetPolicyMapper
|
|
37
|
+
extend PolicyMapper
|
|
38
|
+
extend PropertyMapper
|
|
39
|
+
|
|
40
|
+
def range_tag(tag)
|
|
41
|
+
min = tag[:Min]
|
|
42
|
+
max = tag[:Max]
|
|
43
|
+
Range.new(min.to_i, max.to_i)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
extend self
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module MITS
|
|
2
|
+
module V3_0
|
|
3
|
+
module Mapper
|
|
4
|
+
module AddressMapper
|
|
5
|
+
def address(tag, secondary_tag = nil, entity = Address)
|
|
6
|
+
attrs = address_attributes(tag)
|
|
7
|
+
|
|
8
|
+
if secondary_tag
|
|
9
|
+
attrs[:latitude] = try(secondary_tag[:Latitude], :to_f)
|
|
10
|
+
attrs[:longitude] = try(secondary_tag[:Longitude], :to_f)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
entity.new(attrs)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
def address_attributes(tag)
|
|
19
|
+
{
|
|
20
|
+
address: tag[:Address],
|
|
21
|
+
city: tag[:City],
|
|
22
|
+
country: tag[:Country],
|
|
23
|
+
country_name: tag[:CountyName],
|
|
24
|
+
description: tag[:Description],
|
|
25
|
+
postal_code: tag[:PostalCode],
|
|
26
|
+
province: tag[:Province],
|
|
27
|
+
state: tag[:State],
|
|
28
|
+
type: tag[:AddressType],
|
|
29
|
+
unparsed_address: tag[:UnparsedAddress]
|
|
30
|
+
}
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module MITS
|
|
2
|
+
module V3_0
|
|
3
|
+
module Mapper
|
|
4
|
+
module AmenitiesMapper
|
|
5
|
+
def amenities(tags, entity = Amenity)
|
|
6
|
+
tags = [tags] unless tags.is_a? Array
|
|
7
|
+
tags.map { |tag| amenity(tag, entity) }
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def amenity(tag, entity = Amenity)
|
|
11
|
+
entity.new(description: tag[:Description],
|
|
12
|
+
rank: tag[:Rank],
|
|
13
|
+
subtype: tag[:AmenitySubType],
|
|
14
|
+
type: tag[:AmenityType])
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module MITS
|
|
2
|
+
module V3_0
|
|
3
|
+
module Mapper
|
|
4
|
+
module CompanyMapper
|
|
5
|
+
def company(tag, entity = Company)
|
|
6
|
+
entity.new(address: address(tag[:Address]),
|
|
7
|
+
id: tag[:Identification][:IDValue],
|
|
8
|
+
logo: tag[:Logo],
|
|
9
|
+
name: tag[:CompanyName],
|
|
10
|
+
website: tag[:Website])
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
module MITS
|
|
2
|
+
module V3_0
|
|
3
|
+
module Mapper
|
|
4
|
+
module DepositMapper
|
|
5
|
+
def deposits(tags, entity = Deposit)
|
|
6
|
+
tags = [tags] unless tags.is_a? Array
|
|
7
|
+
tags.map { |tag| deposit(tag, entity) }
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def deposit(tag, entity = Deposit)
|
|
11
|
+
entity.new(amount: deposit_amount(tag[:Amount][:ValueRange]),
|
|
12
|
+
description: tag[:Description],
|
|
13
|
+
percent_refundable: try(tag[:PercentRefundable], :to_f),
|
|
14
|
+
portion_refundable: try(tag[:PortionRefundable], :to_f),
|
|
15
|
+
type: tag[:DepositType])
|
|
16
|
+
end
|
|
17
|
+
private
|
|
18
|
+
|
|
19
|
+
def deposit_amount(tag)
|
|
20
|
+
if tag[:Exact]
|
|
21
|
+
amount = tag[:Exact].to_f
|
|
22
|
+
else
|
|
23
|
+
min = tag[:Min].to_f
|
|
24
|
+
max = tag[:Max].to_f
|
|
25
|
+
amount = Range.new(min, max)
|
|
26
|
+
end
|
|
27
|
+
amount
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|