astronoby 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1c5bcfe7077b3772243f90a9c8a9ac8b0b0d90fdce2c777d6f05ab88062bc94c
4
- data.tar.gz: ecd3bbbbcf699c1bde1b2fd6a92ccd7dc45ed1839cb3e6e6549ddb2d52002e48
3
+ metadata.gz: 25e45175dabf69ffa0c98ffdf3e93cb21b9ce004fe4e0ffe61a4cfc92794ae44
4
+ data.tar.gz: 2d1ad05a74a171c71f6ff0a7fa7c3af1874f07379c8be407ff633d61ad4dd78e
5
5
  SHA512:
6
- metadata.gz: a97c4ee597dbcd5b3adbb9da8402dd95d413d120e51c263675a8019e839496168d4a893c473b6dbf1687463eb8e2f4749b13a9acab1205488944ae49f160de83
7
- data.tar.gz: 70b0f12a52a668e1f3948a20fb5fe38b59e42ed0531381b8a5a03d130d1e64b2e7ba2c56806982d1f0e667dc47776a54609d7a35a5b067594b78295a440cf020
6
+ metadata.gz: 74cdfbf511e8094bd410c67ed86eaff12f03124bec48c769eb3e6ebf1fd54870145a556cc82214db5147bd2c6e4631d0514973a76648d0e68d8770162401d338
7
+ data.tar.gz: 7a6c7f98fff52a04d60dc5c4eced47610900aa10a64f8016000b9294276d547d4d350ef0d269a25f42ae9b0078d110ad9b73884f3834e55a12084274f358ae15
data/CHANGELOG.md CHANGED
@@ -1,5 +1,53 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.2.0 - 2024-03-24
4
+
5
+ _If you are upgrading: please see [`UPGRADING.md`]._
6
+
7
+ [`UPGRADING.md`]: https://github.com/rhannequin/astronoby/blob/main/UPGRADING.md
8
+
9
+ ### Features
10
+
11
+ * Angle comparison ([#21])
12
+ * Add `#distance` and `#angular_size` to `Astronoby::Sun` ([#30])
13
+ * Add geocentric parallax `Astronoby::GeocentricParallax` ([#31])
14
+ * Ability to calculate equinoxes and solstices times ([#32])
15
+ * Round rising and setting times to the second ([#38])
16
+ * Provide sunrise and sunset times ([#35])
17
+ * Provide sunrise and sunset azimuths ([#39])
18
+ * Ability to calculate the equation of time ([#40])
19
+
20
+ ### Breaking changes
21
+
22
+ * **breaking:** Accurate setting and rising times for punctual bodies ([#29])
23
+ * **breaking:** Drop `Astronoby::Util::Time` in favor of
24
+ `Astronoby::GreenwichSiderealTime` and `Astonoby::LocalSiderealTime` ([#36])
25
+
26
+ ### Improvements
27
+
28
+ * Add Dependabot for Bundler and GitHub Actions ([#24])
29
+ * Add bundler-audit GitHub Action ([#25])
30
+ * Bump actions/checkout from 3 to 4 ([#26])
31
+ * Bump standard from 1.29.0 to 1.35.1 ([#27], [#37])
32
+ * Bump rspec from 3.12.0 to 3.13.0 ([#28])
33
+
34
+ [#21]: https://github.com/rhannequin/astronoby/pull/21
35
+ [#24]: https://github.com/rhannequin/astronoby/pull/24
36
+ [#25]: https://github.com/rhannequin/astronoby/pull/25
37
+ [#26]: https://github.com/rhannequin/astronoby/pull/26
38
+ [#27]: https://github.com/rhannequin/astronoby/pull/27
39
+ [#28]: https://github.com/rhannequin/astronoby/pull/28
40
+ [#29]: https://github.com/rhannequin/astronoby/pull/29
41
+ [#30]: https://github.com/rhannequin/astronoby/pull/30
42
+ [#31]: https://github.com/rhannequin/astronoby/pull/31
43
+ [#32]: https://github.com/rhannequin/astronoby/pull/32
44
+ [#35]: https://github.com/rhannequin/astronoby/pull/35
45
+ [#36]: https://github.com/rhannequin/astronoby/pull/36
46
+ [#37]: https://github.com/rhannequin/astronoby/pull/37
47
+ [#28]: https://github.com/rhannequin/astronoby/pull/38
48
+ [#39]: https://github.com/rhannequin/astronoby/pull/39
49
+ [#40]: https://github.com/rhannequin/astronoby/pull/40
50
+
3
51
  ## 0.1.0 - 2024-02-28
4
52
 
5
53
  ### Features
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- astronoby (0.1.0)
4
+ astronoby (0.2.0)
5
5
  matrix (~> 0.4.2)
6
6
  rake (~> 13.0)
7
7
  rspec (~> 3.0)
@@ -10,61 +10,63 @@ GEM
10
10
  remote: https://rubygems.org/
11
11
  specs:
12
12
  ast (2.4.2)
13
- diff-lcs (1.5.0)
14
- json (2.6.3)
13
+ diff-lcs (1.5.1)
14
+ json (2.7.1)
15
15
  language_server-protocol (3.17.0.3)
16
- lint_roller (1.0.0)
16
+ lint_roller (1.1.0)
17
17
  matrix (0.4.2)
18
- parallel (1.23.0)
19
- parser (3.2.2.3)
18
+ parallel (1.24.0)
19
+ parser (3.3.0.5)
20
20
  ast (~> 2.4.1)
21
21
  racc
22
- racc (1.7.0)
22
+ racc (1.7.3)
23
23
  rainbow (3.1.1)
24
24
  rake (13.1.0)
25
- regexp_parser (2.8.1)
26
- rexml (3.2.5)
27
- rspec (3.12.0)
28
- rspec-core (~> 3.12.0)
29
- rspec-expectations (~> 3.12.0)
30
- rspec-mocks (~> 3.12.0)
31
- rspec-core (3.12.2)
32
- rspec-support (~> 3.12.0)
33
- rspec-expectations (3.12.3)
25
+ regexp_parser (2.9.0)
26
+ rexml (3.2.6)
27
+ rspec (3.13.0)
28
+ rspec-core (~> 3.13.0)
29
+ rspec-expectations (~> 3.13.0)
30
+ rspec-mocks (~> 3.13.0)
31
+ rspec-core (3.13.0)
32
+ rspec-support (~> 3.13.0)
33
+ rspec-expectations (3.13.0)
34
34
  diff-lcs (>= 1.2.0, < 2.0)
35
- rspec-support (~> 3.12.0)
36
- rspec-mocks (3.12.6)
35
+ rspec-support (~> 3.13.0)
36
+ rspec-mocks (3.13.0)
37
37
  diff-lcs (>= 1.2.0, < 2.0)
38
- rspec-support (~> 3.12.0)
39
- rspec-support (3.12.1)
40
- rubocop (1.52.0)
38
+ rspec-support (~> 3.13.0)
39
+ rspec-support (3.13.1)
40
+ rubocop (1.62.1)
41
41
  json (~> 2.3)
42
+ language_server-protocol (>= 3.17.0)
42
43
  parallel (~> 1.10)
43
- parser (>= 3.2.0.0)
44
+ parser (>= 3.3.0.2)
44
45
  rainbow (>= 2.2.2, < 4.0)
45
46
  regexp_parser (>= 1.8, < 3.0)
46
47
  rexml (>= 3.2.5, < 4.0)
47
- rubocop-ast (>= 1.28.0, < 2.0)
48
+ rubocop-ast (>= 1.31.1, < 2.0)
48
49
  ruby-progressbar (~> 1.7)
49
50
  unicode-display_width (>= 2.4.0, < 3.0)
50
- rubocop-ast (1.29.0)
51
- parser (>= 3.2.1.0)
52
- rubocop-performance (1.18.0)
53
- rubocop (>= 1.7.0, < 2.0)
54
- rubocop-ast (>= 0.4.0)
51
+ rubocop-ast (1.31.2)
52
+ parser (>= 3.3.0.4)
53
+ rubocop-performance (1.20.2)
54
+ rubocop (>= 1.48.1, < 2.0)
55
+ rubocop-ast (>= 1.30.0, < 2.0)
55
56
  ruby-progressbar (1.13.0)
56
- standard (1.29.0)
57
+ standard (1.35.1)
57
58
  language_server-protocol (~> 3.17.0.2)
58
59
  lint_roller (~> 1.0)
59
- rubocop (~> 1.52.0)
60
+ rubocop (~> 1.62.0)
60
61
  standard-custom (~> 1.0.0)
61
- standard-performance (~> 1.1.0)
62
- standard-custom (1.0.1)
62
+ standard-performance (~> 1.3)
63
+ standard-custom (1.0.2)
63
64
  lint_roller (~> 1.0)
64
- standard-performance (1.1.0)
65
- lint_roller (~> 1.0)
66
- rubocop-performance (~> 1.18.0)
67
- unicode-display_width (2.4.2)
65
+ rubocop (~> 1.50)
66
+ standard-performance (1.3.1)
67
+ lint_roller (~> 1.1)
68
+ rubocop-performance (~> 1.20.2)
69
+ unicode-display_width (2.5.0)
68
70
 
69
71
  PLATFORMS
70
72
  ruby
data/README.md CHANGED
@@ -24,8 +24,11 @@ executing:
24
24
 
25
25
  ## Usage
26
26
 
27
- This library is still in heavy development. The following API is likely to
28
- change any time.
27
+ This library is still in heavy development. The public is not stable, please
28
+ be aware new minor versions will probably lead to breaking changes until a
29
+ major one is released.
30
+
31
+ ### Sun's location in the sky
29
32
 
30
33
  ```rb
31
34
  time = Time.utc(2023, 2, 17, 11, 0, 0)
@@ -48,6 +51,18 @@ horizontal_coordinates.altitude.str(:dms)
48
51
  # => "+27° 30′ 8.5144″"
49
52
  ```
50
53
 
54
+ ### Solstice and Equinox times
55
+
56
+ ```rb
57
+ year = 2024
58
+
59
+ Astronoby::EquinoxSolstice.march_equinox(year)
60
+ # => 2024-03-20 03:05:00 UTC
61
+
62
+ Astronoby::EquinoxSolstice.june_solstice(year)
63
+ # => 2024-06-20 20:50:14 UTC
64
+ ```
65
+
51
66
  ## Precision
52
67
 
53
68
  The current precision for the Sun's apparent location in the sky, compared
data/UPGRADING.md ADDED
@@ -0,0 +1,109 @@
1
+ # Upgrading
2
+
3
+ Astronoby is still in development phase and no major version has been
4
+ released yet. Please consider the public API as unstable and expect breaking
5
+ changes to it as long as a major version has not been released.
6
+
7
+ If you are already using Astronoby and wish to follow the changes to its
8
+ public API, please read the upgrading notes for each release.
9
+
10
+ ## Upgrading from 0.1.0 to 0.2.0
11
+
12
+ ### `Observer` class added (#29)
13
+
14
+ The `Observer` class aims to represent an observer's location and local
15
+ parameters such as the temperature and astmospheric pressure.
16
+
17
+ ### `Refraction` constructor changed (#29)
18
+
19
+ `Refraction.new` now takes the following arguments:
20
+
21
+ * `coordinates` (`Coordinates::Horizontal`)
22
+ * `observer` (`Observer`)
23
+
24
+ ### `Refraction::for_horizontal_coordinates` removed (#29)
25
+
26
+ Please now use `Refraction.correct_horizontal_coordinates`.
27
+
28
+ ### `Refraction::angle` added (#29)
29
+
30
+ This returns a refraction angle (`Angle`) based on an observer (`Observer`)
31
+ and the horizontal coordinates (`Coordinates::Horizontal`) of a body in the sky.
32
+
33
+ ### `apparent` argument added to `Body::rising_time` (#29)
34
+
35
+ With a default value of `true`, this new argument will make consider a
36
+ default vertical refraction angle or not.
37
+
38
+ ### `apparent` argument added to `Body::setting_time` (#29)
39
+
40
+ With a default value of `true`, this new argument will make consider a
41
+ default vertical refraction angle or not.
42
+
43
+ ### `Sun::equation_of_time` method added (#40)
44
+
45
+ Returns the equation of time for a given date.
46
+
47
+ ### `Sun#distance` method added (#30)
48
+
49
+ Returns the approximate Earth-Sun distance in meters (`Numeric`).
50
+
51
+ ### `Sun#angular_size` method added (#30)
52
+
53
+ Returns the apparent Sun's angular size (`Angle`).
54
+
55
+ ### `Sun#true_anomaly` method added (#32)
56
+
57
+ Returns the apparent Sun's true anomaly (`Angle`).
58
+
59
+ ### `Sun#longitude_at_perigee` method added (#32)
60
+
61
+ Returns the apparent Sun's longitude (`Angle`) at its perigee.
62
+
63
+ ### `Sun#rising_time` method added (#35)
64
+
65
+ Returns the UTC `Time` of the sunrise.`
66
+
67
+ ### `Sun#rising_azimuth` method added (#39)
68
+
69
+ Returns the Sun's azimuth (`Angle`) at sunrise.
70
+
71
+ ### `Sun#setting_time` method added (#35)
72
+
73
+ Returns the UTC `Time` of the sunset.
74
+
75
+ ### `Sun#setting_azimuth` method added (#39)
76
+
77
+ Returns the Sun's azimuth (`Angle`) at sunset.
78
+
79
+ ### Added comparison methods to `Angle` (#21)
80
+
81
+ With the inclusion of `Comparable`, comparison methods such as `#==`, `#<`,
82
+ `#>`, `#<=`, `#>=`, `#!=`, `#<=>` have been added to `Angle`.
83
+
84
+ ### `GeocentricParallax` class added
85
+
86
+ Calculates the equatorial horizontal parallax for an observed body. The
87
+ class provided two class methods:
88
+ - `::angle` which returns the parallax angle
89
+ - `::for_equatorial_coordinates` which correct equatorial coordinates with
90
+ the parallax correction
91
+
92
+ ### `EquinoxSolstice` class added
93
+
94
+ This class exposes `::march_equinox`, `::june_solstice`,
95
+ `::september_equinox` and `::december_soltice` that all require a year
96
+ (`Integer`) as parameter and return a date-time (`Time`) computed for the event.
97
+
98
+ ### `Util::Time` class dropped
99
+
100
+ Time-related utility functions have been deleted, in favor of new classes
101
+ (see below).
102
+
103
+ ### `GreenwichSiderealTime` class added
104
+
105
+ Enables to instantiate a GST from UTC, or convert a GST to UTC.
106
+
107
+ ### `LocalSiderealTime` class added
108
+
109
+ Enables to instantiate a LST from GST, or convert a LST to GST.
@@ -4,6 +4,8 @@ require "bigdecimal/math"
4
4
 
5
5
  module Astronoby
6
6
  class Angle
7
+ include Comparable
8
+
7
9
  PRECISION = 14
8
10
  PI = BigMath.PI(PRECISION)
9
11
  PI_IN_DEGREES = BigDecimal("180")
@@ -2,16 +2,46 @@
2
2
 
3
3
  module Astronoby
4
4
  class Sun
5
+ SEMI_MAJOR_AXIS_IN_METERS = 149_598_500_000
6
+ ANGULAR_DIAMETER = Angle.as_degrees(0.533128)
7
+ INTERPOLATION_FACTOR = BigDecimal("24.07")
8
+
9
+ # Source:
10
+ # Title: Practical Astronomy with your Calculator or Spreadsheet
11
+ # Authors: Peter Duffett-Smith and Jonathan Zwart
12
+ # Edition: Cambridge University Press
13
+ # Chapter: 51 - The equation of time
14
+
15
+ # @param date [Date] Requested date
16
+ # @return [Integer] Equation of time in seconds
17
+ def self.equation_of_time(date:)
18
+ noon = Time.utc(date.year, date.month, date.day, 12)
19
+ epoch_at_noon = Epoch.from_time(noon)
20
+ sun_at_noon = new(epoch: epoch_at_noon)
21
+ equatorial_hours = sun_at_noon
22
+ .ecliptic_coordinates
23
+ .to_equatorial(epoch: epoch_at_noon)
24
+ .right_ascension
25
+ .hours
26
+ gst = GreenwichSiderealTime
27
+ .new(date: date, time: equatorial_hours)
28
+ .to_utc
29
+
30
+ (noon - gst).to_i
31
+ end
32
+
5
33
  # Source:
6
34
  # Title: Celestial Calculations
7
35
  # Author: J. L. Lawrence
8
36
  # Edition: MIT Press
9
37
  # Chapter: 6 - The Sun
10
38
 
39
+ # @param epoch [Numeric] Considered epoch, in Julian days
11
40
  def initialize(epoch:)
12
41
  @epoch = epoch
13
42
  end
14
43
 
44
+ # @return [Astronoby::Coordinates::Ecliptic] Sun's ecliptic coordinates
15
45
  def ecliptic_coordinates
16
46
  Coordinates::Ecliptic.new(
17
47
  latitude: Angle.zero,
@@ -21,6 +51,11 @@ module Astronoby
21
51
  )
22
52
  end
23
53
 
54
+ # Computes the Sun's horizontal coordinates
55
+ #
56
+ # @param latitude [Astronoby::Angle] Latitude of the observer
57
+ # @param longitude [Astronoby::Angle] Longitude of the observer
58
+ # @return [Astronoby::Coordinates::Horizontal] Sun's horizontal coordinates
24
59
  def horizontal_coordinates(latitude:, longitude:)
25
60
  time = Epoch.to_utc(@epoch)
26
61
 
@@ -29,14 +64,69 @@ module Astronoby
29
64
  .to_horizontal(time: time, latitude: latitude, longitude: longitude)
30
65
  end
31
66
 
32
- private
67
+ # @param observer [Astronoby::Observer] Observer of the event
68
+ # @return [Time] Time of sunrise
69
+ def rising_time(observer:)
70
+ event_date = Epoch.to_utc(@epoch).to_date
71
+ lst1 = event_local_sidereal_time_for_date(event_date, observer, :rising)
72
+ next_day = event_date.next_day(1)
73
+ lst2 = event_local_sidereal_time_for_date(next_day, observer, :rising)
74
+ time = (INTERPOLATION_FACTOR * lst1) / (INTERPOLATION_FACTOR + lst1 - lst2)
33
75
 
34
- def mean_anomaly
35
- Angle.as_degrees(
36
- (longitude_at_base_epoch - longitude_at_perigee).degrees % 360
76
+ LocalSiderealTime.new(
77
+ date: event_date,
78
+ time: time,
79
+ longitude: observer.longitude
80
+ ).to_gst.to_utc
81
+ end
82
+
83
+ # @param observer [Astronoby::Observer] Observer of the event
84
+ # @return [Astronoby::Angle, nil] Azimuth of sunrise
85
+ def rising_azimuth(observer:)
86
+ equatorial_coordinates = ecliptic_coordinates.to_equatorial(epoch: @epoch)
87
+ Body.new(equatorial_coordinates).rising_azimuth(
88
+ latitude: observer.latitude,
89
+ vertical_shift: vertical_shift
37
90
  )
38
91
  end
39
92
 
93
+ # @param observer [Astronoby::Observer] Observer of the event
94
+ # @return [Time] Time of sunset
95
+ def setting_time(observer:)
96
+ event_date = Epoch.to_utc(@epoch).to_date
97
+ lst1 = event_local_sidereal_time_for_date(event_date, observer, :setting)
98
+ next_day = event_date.next_day(1)
99
+ lst2 = event_local_sidereal_time_for_date(next_day, observer, :setting)
100
+ time = (INTERPOLATION_FACTOR * lst1) / (INTERPOLATION_FACTOR + lst1 - lst2)
101
+
102
+ LocalSiderealTime.new(
103
+ date: event_date,
104
+ time: time,
105
+ longitude: observer.longitude
106
+ ).to_gst.to_utc
107
+ end
108
+
109
+ # @param observer [Astronoby::Observer] Observer of the event
110
+ # @return [Astronoby::Angle, nil] Azimuth of sunset
111
+ def setting_azimuth(observer:)
112
+ equatorial_coordinates = ecliptic_coordinates.to_equatorial(epoch: @epoch)
113
+ Body.new(equatorial_coordinates).setting_azimuth(
114
+ latitude: observer.latitude,
115
+ vertical_shift: vertical_shift
116
+ )
117
+ end
118
+
119
+ # @return [Numeric] Earth-Sun distance in meters
120
+ def earth_distance
121
+ SEMI_MAJOR_AXIS_IN_METERS / distance_angular_size_factor
122
+ end
123
+
124
+ # @return [Astronoby::Angle] Apparent Sun's angular size
125
+ def angular_size
126
+ Angle.as_degrees(ANGULAR_DIAMETER.degrees * distance_angular_size_factor)
127
+ end
128
+
129
+ # @return [Astronoby::Angle] Sun's true anomaly
40
130
  def true_anomaly
41
131
  eccentric_anomaly = Util::Astrodynamics.eccentric_anomaly_newton_raphson(
42
132
  mean_anomaly,
@@ -52,6 +142,28 @@ module Astronoby
52
142
  Angle.as_degrees((Angle.atan(tan).degrees * 2) % 360)
53
143
  end
54
144
 
145
+ # @return [Astronoby::Angle] Sun's longitude at perigee
146
+ def longitude_at_perigee
147
+ Angle.as_degrees(
148
+ (281.2208444 + 1.719175 * centuries + 0.000452778 * centuries**2) % 360
149
+ )
150
+ end
151
+
152
+ # @return [Astronoby::Angle] Sun's orbital eccentricity
153
+ def orbital_eccentricity
154
+ Angle.as_degrees(
155
+ (0.01675104 - 0.0000418 * centuries - 0.000000126 * centuries**2) % 360
156
+ )
157
+ end
158
+
159
+ private
160
+
161
+ def mean_anomaly
162
+ Angle.as_degrees(
163
+ (longitude_at_base_epoch - longitude_at_perigee).degrees % 360
164
+ )
165
+ end
166
+
55
167
  def days_since_epoch
56
168
  Epoch::DEFAULT_EPOCH - @epoch
57
169
  end
@@ -66,16 +178,49 @@ module Astronoby
66
178
  )
67
179
  end
68
180
 
69
- def longitude_at_perigee
70
- Angle.as_degrees(
71
- (281.2208444 + 1.719175 * centuries + 0.000452778 * centuries**2) % 360
72
- )
181
+ def distance_angular_size_factor
182
+ term1 = 1 + orbital_eccentricity.degrees * true_anomaly.cos
183
+ term2 = 1 - orbital_eccentricity.degrees**2
184
+
185
+ term1 / term2
73
186
  end
74
187
 
75
- def orbital_eccentricity
76
- Angle.as_degrees(
77
- (0.01675104 - 0.0000418 * centuries - 0.000000126 * centuries**2) % 360
78
- )
188
+ def event_local_sidereal_time_for_date(date, observer, event)
189
+ midnight_utc = Time.utc(date.year, date.month, date.day)
190
+ epoch = Epoch.from_time(midnight_utc)
191
+ sun_at_midnight = self.class.new(epoch: epoch)
192
+ shift = Body::DEFAULT_REFRACTION_VERTICAL_SHIFT +
193
+ GeocentricParallax.angle(distance: sun_at_midnight.earth_distance) +
194
+ Angle.as_degrees(sun_at_midnight.angular_size.degrees / 2)
195
+ ecliptic_coordinates = sun_at_midnight.ecliptic_coordinates
196
+ equatorial_coordinates = ecliptic_coordinates.to_equatorial(epoch: epoch)
197
+
198
+ event_time = if event == :rising
199
+ Body.new(equatorial_coordinates).rising_time(
200
+ latitude: observer.latitude,
201
+ longitude: observer.longitude,
202
+ date: midnight_utc.to_date,
203
+ vertical_shift: shift
204
+ )
205
+ else
206
+ Body.new(equatorial_coordinates).setting_time(
207
+ latitude: observer.latitude,
208
+ longitude: observer.longitude,
209
+ date: midnight_utc.to_date,
210
+ vertical_shift: shift
211
+ )
212
+ end
213
+
214
+ GreenwichSiderealTime
215
+ .from_utc(event_time.utc)
216
+ .to_lst(longitude: observer.longitude)
217
+ .time
218
+ end
219
+
220
+ def vertical_shift
221
+ Astronoby::Body::DEFAULT_REFRACTION_VERTICAL_SHIFT +
222
+ Astronoby::GeocentricParallax.angle(distance: earth_distance) +
223
+ Astronoby::Angle.as_degrees(angular_size.degrees / 2)
79
224
  end
80
225
  end
81
226
  end