libtad 0.1.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 +7 -0
- data/lib/libtad.rb +123 -0
- data/lib/services/astronomy.rb +102 -0
- data/lib/services/date_calculator.rb +155 -0
- data/lib/services/holidays.rb +34 -0
- data/lib/services/onthisday.rb +42 -0
- data/lib/services/places.rb +26 -0
- data/lib/services/time.rb +143 -0
- data/lib/types/astronomy/astronomy_current.rb +58 -0
- data/lib/types/astronomy/astronomy_day.rb +32 -0
- data/lib/types/astronomy/astronomy_day_event.rb +76 -0
- data/lib/types/astronomy/astronomy_event.rb +24 -0
- data/lib/types/astronomy/astronomy_event_class.rb +37 -0
- data/lib/types/astronomy/astronomy_location.rb +31 -0
- data/lib/types/astronomy/astronomy_object.rb +27 -0
- data/lib/types/astronomy/astronomy_object_details.rb +32 -0
- data/lib/types/astronomy/astronomy_object_type.rb +36 -0
- data/lib/types/astronomy/moonphase.rb +37 -0
- data/lib/types/date_calculator/business_days_filter.rb +39 -0
- data/lib/types/date_calculator/business_holiday.rb +26 -0
- data/lib/types/date_calculator/period.rb +44 -0
- data/lib/types/date_calculator/weekdays.rb +54 -0
- data/lib/types/holidays/holiday.rb +93 -0
- data/lib/types/holidays/holiday_state.rb +35 -0
- data/lib/types/holidays/holiday_type.rb +107 -0
- data/lib/types/onthisday/event.rb +51 -0
- data/lib/types/onthisday/event_type.rb +15 -0
- data/lib/types/onthisday/name.rb +24 -0
- data/lib/types/onthisday/person.rb +39 -0
- data/lib/types/places/country.rb +20 -0
- data/lib/types/places/geo.rb +34 -0
- data/lib/types/places/location.rb +43 -0
- data/lib/types/places/location_ref.rb +24 -0
- data/lib/types/places/place.rb +24 -0
- data/lib/types/places/region.rb +35 -0
- data/lib/types/time/datetime.rb +93 -0
- data/lib/types/time/dst_entry.rb +48 -0
- data/lib/types/time/time.rb +30 -0
- data/lib/types/time/time_change.rb +49 -0
- data/lib/types/time/timezone.rb +51 -0
- metadata +137 -0
@@ -0,0 +1,26 @@
|
|
1
|
+
module LibTAD
|
2
|
+
class Client
|
3
|
+
# Places API.
|
4
|
+
module PlacesService
|
5
|
+
# @return [Array<::LibTAD::Places::Place>]
|
6
|
+
# @param geo [Boolean] Return longitude or latitude for the geo object.
|
7
|
+
# @param lang [Boolean] The preferred language for the texts.
|
8
|
+
#
|
9
|
+
# The Places service can be used to retrieve the list of supported places. The ids for the places are
|
10
|
+
# then used in the other services to indicate the location to be queried.
|
11
|
+
def get_places(geo: nil, lang: nil)
|
12
|
+
args = {
|
13
|
+
geo: geo,
|
14
|
+
lang: lang
|
15
|
+
}.compact
|
16
|
+
|
17
|
+
response = get('places', args)
|
18
|
+
places = response.fetch('places', [])
|
19
|
+
|
20
|
+
places.collect do |e|
|
21
|
+
::LibTAD::Places::Place.new(e)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
module LibTAD
|
2
|
+
class Client
|
3
|
+
# Time API.
|
4
|
+
module TimeService
|
5
|
+
# @return [Array<::LibTAD::Places::Location>]
|
6
|
+
# @param place_id [String] Specify the ID or a list of the ID's for a location which you would like to get the current time from.
|
7
|
+
# @param query [String] Query for a location by specifying the name.
|
8
|
+
# @param qlimit [Integer] Maximum number of query results to be returned.
|
9
|
+
# @param geo [Boolean] Return longitude and latitude for the geo object.
|
10
|
+
# @param lang [String] The preferred language for the texts.
|
11
|
+
# @param radius [Integer] Search radius for translating coordinates to locations.
|
12
|
+
# @param sun [Boolean] Controls if the astronomy element with information about sunrise and sunset shall be added to the result.
|
13
|
+
# @param time [Boolean] Adds current time under the location object.
|
14
|
+
# @param time_changes [Boolean] Adds a list of thime changes during the year to the location object.
|
15
|
+
# @param timezone [Boolean] Adds time zone information under the time object.
|
16
|
+
#
|
17
|
+
# The Time service can be used to retrieve the current time in one or more places.
|
18
|
+
# Additionally, information about time zones and related changes and the time of sunrise and sunset can be queried.
|
19
|
+
#
|
20
|
+
# Either a place_id or a query is required.
|
21
|
+
def get_current_time(
|
22
|
+
place_id: nil,
|
23
|
+
query: nil,
|
24
|
+
qlimit: nil,
|
25
|
+
geo: nil,
|
26
|
+
lang: nil,
|
27
|
+
radius: nil,
|
28
|
+
sun: nil,
|
29
|
+
time: nil,
|
30
|
+
time_changes: nil,
|
31
|
+
timezone: nil
|
32
|
+
)
|
33
|
+
args = {
|
34
|
+
placeid: place_id,
|
35
|
+
query: query,
|
36
|
+
qlimit: qlimit,
|
37
|
+
geo: geo,
|
38
|
+
lang: lang,
|
39
|
+
radius: radius,
|
40
|
+
sun: sun,
|
41
|
+
time: time,
|
42
|
+
timechanges: time_changes,
|
43
|
+
tz: timezone
|
44
|
+
}.compact
|
45
|
+
|
46
|
+
response = get('timeservice', args)
|
47
|
+
locations = response.fetch('locations', [])
|
48
|
+
|
49
|
+
locations.collect do |e|
|
50
|
+
::LibTAD::Places::Location.new(e)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# @return [::LibTAD::TADTime::TADTime, Array<::LibTAD::Places::Locations>]
|
55
|
+
# @param from_id [String] Specify the ID of the location for which the supplied time stamp corresponds.
|
56
|
+
# @param to_id [String] Specify the ID or a list of ID's for the location(s) for which the time stamp should be converted.
|
57
|
+
# @param iso [String] Time stamp in ISO8601 format.
|
58
|
+
# @param datetime [::LibTAD::TADTime::TADDateTime] A date object.
|
59
|
+
# @param lang [String] The preferred language for the texts.
|
60
|
+
# @param radius [Integer] Search radius for translating coordinates to locations.
|
61
|
+
# @param time_changes [Boolean] Add a list of time changes during the year to the location object.
|
62
|
+
# @param timezone [Boolean] Add time zone information under the time object.
|
63
|
+
#
|
64
|
+
# The Converttime service can be used to convert any time from UTC or any of the supported locations to any other of the supported locations.
|
65
|
+
# You have to specify a time stamp either in ISO8601 representation via the iso argument, or you have to specify the date via the datetime argument.
|
66
|
+
# Skipped components will not yield an error message, but use a default value instead (which corresponds to 01.01.2001, 00:00:00).
|
67
|
+
def convert_time(
|
68
|
+
from_id:,
|
69
|
+
to_id: nil,
|
70
|
+
iso: nil,
|
71
|
+
datetime: nil,
|
72
|
+
lang: nil,
|
73
|
+
radius: nil,
|
74
|
+
time_changes: nil,
|
75
|
+
timezone: nil
|
76
|
+
)
|
77
|
+
args = {
|
78
|
+
fromid: from_id,
|
79
|
+
toid: to_id,
|
80
|
+
iso: iso,
|
81
|
+
year: (datetime.year unless datetime.nil?),
|
82
|
+
month: (datetime.month unless datetime.nil?),
|
83
|
+
day: (datetime.day unless datetime.nil?),
|
84
|
+
hour: (datetime.hour unless datetime.nil?),
|
85
|
+
min: (datetime.minute unless datetime.nil?),
|
86
|
+
sec: (datetime.second unless datetime.nil?),
|
87
|
+
lang: lang,
|
88
|
+
radius: radius,
|
89
|
+
timechanges: time_changes,
|
90
|
+
tz: timezone
|
91
|
+
}.compact
|
92
|
+
|
93
|
+
response = get('converttime', args)
|
94
|
+
utc = ::LibTAD::TADTime::TADTime.new response.dig('utc', 'time') unless response.dig('utc', 'time').nil?
|
95
|
+
locations = response.fetch('locations', [])
|
96
|
+
.map { |e| ::LibTAD::Places::Location.new(e) }
|
97
|
+
|
98
|
+
return utc, locations
|
99
|
+
end
|
100
|
+
|
101
|
+
# @return [Array<::LibTAD::DST::DSTEntry>]
|
102
|
+
# @param year [Integer] The year you want to retrieve the information for. Defaults to current year.
|
103
|
+
# @param country [String] Specify the country for which you want to retrieve information for. If unspecified, information for all countries will be returned.
|
104
|
+
# Specifying this parameter automatically sets the parameter onlydst to 0.
|
105
|
+
# @param lang [String] The preferred language for the texts.
|
106
|
+
# @param list_places [Boolean] For every time zone/country, list the individual places that belong to each record.
|
107
|
+
# @param only_dst [Boolean] Return only countries which actually observe DST in the queried year. Other countries will be suppressed.
|
108
|
+
# @param time_changes [Boolean] Add a list of time changes during the year to the dstentry object.
|
109
|
+
#
|
110
|
+
# The Dstlist service can be used to obtain data about time zones for all supported countries in our database.
|
111
|
+
# This includes the start and end date of daylight savings time, and UTC offset for the time zones.
|
112
|
+
#
|
113
|
+
# The resulting data is aggregated on country and time zone level. By default, only information from countries which actually observe DST is
|
114
|
+
# returned without listing the individually affected locations – see the parameters list_places and only_dst to change this behavior.
|
115
|
+
def get_daylight_savings_time(
|
116
|
+
year: nil,
|
117
|
+
country: nil,
|
118
|
+
lang: nil,
|
119
|
+
list_places: nil,
|
120
|
+
only_dst: nil,
|
121
|
+
time_changes: nil
|
122
|
+
)
|
123
|
+
args = {
|
124
|
+
year: year,
|
125
|
+
country: country,
|
126
|
+
lang: lang,
|
127
|
+
listplaces: list_places,
|
128
|
+
onlydst: only_dst,
|
129
|
+
timechanges: time_changes
|
130
|
+
}.compact
|
131
|
+
|
132
|
+
response = get('dstlist', args)
|
133
|
+
|
134
|
+
dstlist = response.fetch('dstlist', [])
|
135
|
+
|
136
|
+
dstlist.collect do |e|
|
137
|
+
::LibTAD::TADTime::DSTEntry.new(e)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module LibTAD
|
2
|
+
module Astronomy
|
3
|
+
# Current information about an astronomy object.
|
4
|
+
class AstronomyCurrent
|
5
|
+
# @return [String]
|
6
|
+
# Local time stamp for the data in ISO 8601 format (including UTC offset).
|
7
|
+
# Only returned if requested by specifying the parameter isotime.
|
8
|
+
#
|
9
|
+
# Example: 2012-04-17T00:57:42+02:00
|
10
|
+
attr_reader :isotime
|
11
|
+
|
12
|
+
# @return [String]
|
13
|
+
# UTC time stamp for the data in ISO 8601 format.
|
14
|
+
# Only returned if requested by specifying the parameter utctime.
|
15
|
+
#
|
16
|
+
# Example: 2012-04-16T22:57:42
|
17
|
+
attr_reader :utctime
|
18
|
+
|
19
|
+
# @return [Float]
|
20
|
+
# Altitude of the center of the queried astronomical object above an ideal horizon.
|
21
|
+
attr_reader :altitude
|
22
|
+
|
23
|
+
# @return [Float] (degrees)
|
24
|
+
# Horizontal direction of the astronomical object at set/rise time (referring to true north).
|
25
|
+
# North is 0 degrees, east is 90 degrees, south is 180 degrees and west is 270 degrees.
|
26
|
+
attr_reader :azimuth
|
27
|
+
|
28
|
+
# @return [Float] (km)
|
29
|
+
# Distance of the earth's center to the center of the queried astronomical object in kilometers.
|
30
|
+
attr_reader :distance
|
31
|
+
|
32
|
+
# @return [Float] (percent)
|
33
|
+
# The fraction of the Moon's surface illuminated by the Sun's rays as seen from the selected location.
|
34
|
+
# Only available for the moon object.
|
35
|
+
attr_reader :illuminated
|
36
|
+
|
37
|
+
# @return [Float] (degrees)
|
38
|
+
# The counterclockwise angle of the midpoint of the Moon's bright limb as seen from the selected location.
|
39
|
+
# Only available for the moon object.
|
40
|
+
attr_reader :posangle
|
41
|
+
|
42
|
+
# @return [MoonPhase]
|
43
|
+
# The current phase of the moon. Only available for the moon object.
|
44
|
+
attr_reader :moonphase
|
45
|
+
|
46
|
+
def initialize(hash)
|
47
|
+
@isotime = hash.fetch('isotime', nil)
|
48
|
+
@utctime = hash.fetch('utctime', nil)
|
49
|
+
@altitude = hash.fetch('altitude', nil)
|
50
|
+
@azimuth = hash.fetch('azimuth', nil)
|
51
|
+
@distance = hash.fetch('distance', nil)
|
52
|
+
@illuminated = hash.fetch('illuminated', nil)
|
53
|
+
@posangle = hash.fetch('posangle', nil)
|
54
|
+
@moonphase = MoonPhase.new hash['moonphase'] unless !hash.key?('moonphase')
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module LibTAD
|
2
|
+
module Astronomy
|
3
|
+
# Information about an astronomy object for a specific day.
|
4
|
+
class AstronomyDay
|
5
|
+
# @return [String]
|
6
|
+
# Date for the current information.
|
7
|
+
attr_reader :date
|
8
|
+
|
9
|
+
# @return [String]
|
10
|
+
# Length of this day (time between sunrise and sunset). If the sun is not up on this day, 00:00:00 will reported.
|
11
|
+
# If the sun does not set on this day, the value will read 24:00:00.
|
12
|
+
# Attribute only applies for the sun object and if requested.
|
13
|
+
attr_reader :daylength
|
14
|
+
|
15
|
+
# @return [String]
|
16
|
+
# Moon phase for the day. Only if requested.
|
17
|
+
attr_reader :moonphase
|
18
|
+
|
19
|
+
# @return [Array<AstronomyDayEvent>]
|
20
|
+
# Lists all events during the day.
|
21
|
+
attr_reader :events
|
22
|
+
|
23
|
+
def initialize(hash)
|
24
|
+
@date = hash.fetch('date', nil)
|
25
|
+
@daylength = hash.fetch('daylength', nil)
|
26
|
+
@moonphase = hash.fetch('moonphase', nil)
|
27
|
+
@events = hash.fetch('events', nil)
|
28
|
+
&.map { |e| AstronomyDayEvent.new(e) }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module LibTAD
|
2
|
+
module Astronomy
|
3
|
+
# Information about an astronomical event at a specific day.
|
4
|
+
class AstronomyDayEvent
|
5
|
+
# @return [String]
|
6
|
+
# Indicates the type of the event.
|
7
|
+
attr_reader :type
|
8
|
+
|
9
|
+
# @return [Integer]
|
10
|
+
# Hour at which the event is happening (local time).
|
11
|
+
attr_reader :hour
|
12
|
+
|
13
|
+
# @return [Integer]
|
14
|
+
# Minute at which the event is happening (local time).
|
15
|
+
attr_reader :minute
|
16
|
+
|
17
|
+
# @return [Integer]
|
18
|
+
# Second at which the event is happening (local time).
|
19
|
+
attr_reader :second
|
20
|
+
|
21
|
+
# @return [String]
|
22
|
+
# Local time at which the event is happening in ISO 8601 format (including UTC offset).
|
23
|
+
# Only returned if requested by specifying the parameter isotime.
|
24
|
+
#
|
25
|
+
# Example: 2012-04-17T00:57:42+02:00
|
26
|
+
attr_reader :isotime
|
27
|
+
|
28
|
+
# @return [String]
|
29
|
+
# UTC time at which the event is happening in ISO 8601 format.
|
30
|
+
# Only returned if requested by specifying the parameter utctime.
|
31
|
+
#
|
32
|
+
# Example: 2012-04-16T22:57:42
|
33
|
+
attr_reader :utctime
|
34
|
+
|
35
|
+
# @return [Float] (degrees)
|
36
|
+
# Altitude of the center of the queried astronomical object above an ideal horizon.
|
37
|
+
# Only for meridian type events.
|
38
|
+
attr_reader :altitude
|
39
|
+
|
40
|
+
# @return [Float] (degrees)
|
41
|
+
# Horizontal direction of the astronomical object at set/rise time (referring to true north).
|
42
|
+
# North is 0 degrees, east is 90 degrees, south is 180 degrees and west is 270 degrees.
|
43
|
+
# Only for rise and set type events.
|
44
|
+
attr_reader :azimuth
|
45
|
+
|
46
|
+
# @return [Float] (km)
|
47
|
+
# Distance of the earth's center to the center of the queried astronomical object in kilometers.
|
48
|
+
# Only for meridian type events.
|
49
|
+
attr_reader :distance
|
50
|
+
|
51
|
+
# @return [Float] (percent)
|
52
|
+
# The fraction of the Moon's surface illuminated by the Sun's rays as seen from the selected location.
|
53
|
+
# Only for the moon for meridian type events.
|
54
|
+
attr_reader :illuminated
|
55
|
+
|
56
|
+
# @return [Float] (degrees)
|
57
|
+
# The counterclockwise angle of the midpoint of the Moon's bright limb as seen from the selected location.
|
58
|
+
# Only for the moon for meridian type events.
|
59
|
+
attr_reader :posangle
|
60
|
+
|
61
|
+
def initialize(hash)
|
62
|
+
@type = hash.fetch('type', nil)
|
63
|
+
@hour = hash.fetch('hour', nil)
|
64
|
+
@min = hash.fetch('min', nil)
|
65
|
+
@sec = hash.fetch('sec', nil)
|
66
|
+
@isotime = hash.fetch('isotime', nil)
|
67
|
+
@utctime = hash.fetch('utctime', nil)
|
68
|
+
@altitude = hash.fetch('altitude', nil)
|
69
|
+
@azimuth = hash.fetch('azimuth', nil)
|
70
|
+
@distance = hash.fetch('distance', nil)
|
71
|
+
@illuminated = hash.fetch('illuminated', nil)
|
72
|
+
@posangle = hash.fetch('posangle', nil)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module LibTAD
|
2
|
+
module Astronomy
|
3
|
+
# Information about a sunrise/sunset event for a specific day.
|
4
|
+
class AstronomyEvent
|
5
|
+
# @return [String]
|
6
|
+
# Indicates the type of the event.
|
7
|
+
attr_reader :type
|
8
|
+
|
9
|
+
# @return [Integer]
|
10
|
+
# Hour at which the event is happening (local time).
|
11
|
+
attr_reader :hour
|
12
|
+
|
13
|
+
# @return [Integer]
|
14
|
+
# Minute at which the event is happening (local time).
|
15
|
+
attr_reader :minute
|
16
|
+
|
17
|
+
def initialize(hash)
|
18
|
+
@type = hash.fetch('type', nil)
|
19
|
+
@hour = hash.fetch('hour', nil)
|
20
|
+
@minute = hash.fetch('minute', nil)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module LibTAD
|
2
|
+
module Astronomy
|
3
|
+
# All valid astronomy event classes
|
4
|
+
ASTRONOMY_EVENT_CLASS = [
|
5
|
+
# Combination of all known classes.
|
6
|
+
:all,
|
7
|
+
|
8
|
+
# The current phase for the place requested. Additional attributes for illumination (moon), azimuth, distance.
|
9
|
+
:current,
|
10
|
+
|
11
|
+
# Day length. Day length is not reported as an event, but as a separate attribute.
|
12
|
+
:daylength,
|
13
|
+
|
14
|
+
# Meridian (Noon, highest point) and Anti-Meridian (lowest point) events.
|
15
|
+
:meridian,
|
16
|
+
|
17
|
+
# Moon phase events. Additionally to the phase events (only occurring on four days per lunar month),
|
18
|
+
# an additional attribute for the current moon phase is reported for every day.
|
19
|
+
:phase,
|
20
|
+
|
21
|
+
# Set and rise events. Event times take atmospheric refraction into account.
|
22
|
+
:setrise,
|
23
|
+
|
24
|
+
# Combination of all 3 twilight classes.
|
25
|
+
:twilight,
|
26
|
+
|
27
|
+
# Civil twilight (-6°).
|
28
|
+
:twilight6,
|
29
|
+
|
30
|
+
# Nautical twilight (-12°).
|
31
|
+
:twilight12,
|
32
|
+
|
33
|
+
# Astronomical twilight (-18°).
|
34
|
+
:twilight18
|
35
|
+
].freeze
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module LibTAD
|
2
|
+
module Astronomy
|
3
|
+
# Information about location and astronomical objects requested.
|
4
|
+
class AstronomyLocation
|
5
|
+
# @return [String]
|
6
|
+
# The id of the location.
|
7
|
+
attr_reader :id
|
8
|
+
|
9
|
+
# @return [String]
|
10
|
+
# The part of the queried placeid that this location matches.
|
11
|
+
attr_reader :matchparam
|
12
|
+
|
13
|
+
# @return [GeoType]
|
14
|
+
# Geographical information about the location.
|
15
|
+
attr_reader :geo
|
16
|
+
|
17
|
+
# @return [Array<AstronomyObjectDetails>]
|
18
|
+
# Requested astronomical information.
|
19
|
+
attr_reader :objects
|
20
|
+
|
21
|
+
def initialize(hash)
|
22
|
+
@id = hash.fetch('id', nil)
|
23
|
+
@matchparam = hash.fetch('matchparam', nil)
|
24
|
+
@geo = ::LibTAD::Places::Geo.new hash.fetch('geo', nil)
|
25
|
+
@objects = hash.fetch('astronomy', nil)
|
26
|
+
&.fetch('objects', nil)
|
27
|
+
&.map { |e| AstronomyObjectDetails.new(e) }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module LibTAD
|
2
|
+
module Astronomy
|
3
|
+
# Astronomical information - sunrise and sunset times.
|
4
|
+
class AstronomyObject
|
5
|
+
# @return [String]
|
6
|
+
# Object name. Currently, the sun is the only supported astronomical object.
|
7
|
+
attr_reader :name
|
8
|
+
|
9
|
+
# @return [Array<AstronomyEvent>]
|
10
|
+
# Lists all sunrise/sunset events during the day.
|
11
|
+
attr_reader :events
|
12
|
+
|
13
|
+
# @return [String]
|
14
|
+
# This element is only present if there are no astronomical events.
|
15
|
+
# In this case it will indicate if the sun is up or down the whole day.
|
16
|
+
attr_reader :special
|
17
|
+
|
18
|
+
def initialize(hash)
|
19
|
+
@name = hash.fetch('name', nil)
|
20
|
+
@events = hash.fetch('events', nil)
|
21
|
+
&.map { |e| AstronomyEvent.new(e) }
|
22
|
+
|
23
|
+
@special = hash.dig('special', 'type')
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|