astronoby 0.5.0 → 0.6.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: 43ef390a6ab6a498edbf148b2af44c906daf73ff9ba61b5aafeadd828fb550e4
4
- data.tar.gz: b2cf0743676aa49f95f24c62b3d5d759553014bc52114260a71ecedfb9e6c1cb
3
+ metadata.gz: 15679e58775b5058f6a154502a3e94731effe12a9c90d0a28c642b96d07aa6b2
4
+ data.tar.gz: 00f9bcc5a4c0fa4111e33911ba3f1e3da4829edad54e4d1419c0d716f660ea69
5
5
  SHA512:
6
- metadata.gz: 052bfebf4ddaf6ef3f24883fec090a831d38a9e4124dd5f561d6b1dd7074b6385502396edddd5496ab6066ff93acab4f220ec3aaa244ad0638c0b65fbaace55f
7
- data.tar.gz: fe37ac2714328893b068ba958e37a3b057a76ddfa1b299a35f22be005687d3168d20e98ebe571db519bd6cf69227cc0f0dc4c0889dd9ca5bb9d1abb2b1ee550d
6
+ metadata.gz: b524b994952bfec402e42e69976c5f74d69d51e1d6fbf3b2f21327c9ed0e02011c32d897d09c216f7784c3c286ed69c11beee466207a64051aef536fbc8f5a64
7
+ data.tar.gz: 5ebbd92e2bb360d2d354800b7f05d35e4e74bce01cae06c8cf8176dae286e8ae70baa39c509c2c3466b05c676d624d4942a4a7cd08546ec895255785645e235b
data/CHANGELOG.md CHANGED
@@ -1,5 +1,51 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.6.0 - 2024-12-10
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
+ ### Bug fixes
10
+
11
+ * Fix `ObservationEvents` infinite loop in ([#110])
12
+ * Fix observation events times with local time dates in ([#105])
13
+ * Fix `IncompatibleArgumentsError` on Moon's observation events in ([#111])
14
+
15
+ ### Features
16
+
17
+ * Add `Astronoby::Moon#current_phase_fraction` in ([#115])
18
+ * Add sources and results for comparison in ([#114])
19
+
20
+ ### Improvements
21
+
22
+ * Bump standard from 1.36.0 to 1.39.2 by @dependabot in ([#95])
23
+ * Bump standard from 1.39.2 to 1.40.0 by @dependabot in ([#96])
24
+ * Bump dependencies in ([#100])
25
+ * Move dependencies to development ones in ([#99])
26
+ * Bump standard from 1.40.0 to 1.41.1 by @dependabot in ([#104])
27
+ * Bump standard from 1.41.1 to 1.42.0 by @dependabot in ([#107])
28
+ * Bump standard from 1.42.0 to 1.42.1 by @dependabot in ([#108])
29
+ * Bump dependencies in ([#116])
30
+ * Add supported Ruby versions in ([#117])
31
+
32
+ **Full Changelog**: https://github.com/rhannequin/astronoby/compare/v0.5.0...v0.6.0
33
+
34
+ [#95]: https://github\.com/rhannequin/astronoby/pull/95
35
+ [#96]: https://github\.com/rhannequin/astronoby/pull/96
36
+ [#99]: https://github\.com/rhannequin/astronoby/pull/99
37
+ [#100]: https://github\.com/rhannequin/astronoby/pull/100
38
+ [#104]: https://github\.com/rhannequin/astronoby/pull/104
39
+ [#105]: https://github\.com/rhannequin/astronoby/pull/105
40
+ [#107]: https://github\.com/rhannequin/astronoby/pull/107
41
+ [#108]: https://github\.com/rhannequin/astronoby/pull/108
42
+ [#110]: https://github\.com/rhannequin/astronoby/pull/110
43
+ [#111]: https://github\.com/rhannequin/astronoby/pull/111
44
+ [#114]: https://github\.com/rhannequin/astronoby/pull/114
45
+ [#115]: https://github\.com/rhannequin/astronoby/pull/115
46
+ [#116]: https://github\.com/rhannequin/astronoby/pull/116
47
+ [#117]: https://github\.com/rhannequin/astronoby/pull/117
48
+
3
49
  ## 0.5.0 - 2024-06-11
4
50
 
5
51
  _If you are upgrading: please see [UPGRADING.md]._
data/Gemfile.lock CHANGED
@@ -1,74 +1,69 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- astronoby (0.5.0)
4
+ astronoby (0.6.0)
5
5
  matrix (~> 0.4.2)
6
- rake (~> 13.0)
7
- rspec (~> 3.0)
8
6
 
9
7
  GEM
10
8
  remote: https://rubygems.org/
11
9
  specs:
12
10
  ast (2.4.2)
13
11
  diff-lcs (1.5.1)
14
- json (2.7.2)
12
+ json (2.9.0)
15
13
  language_server-protocol (3.17.0.3)
16
14
  lint_roller (1.1.0)
17
15
  matrix (0.4.2)
18
- parallel (1.24.0)
19
- parser (3.3.1.0)
16
+ parallel (1.26.3)
17
+ parser (3.3.6.0)
20
18
  ast (~> 2.4.1)
21
19
  racc
22
- racc (1.7.3)
20
+ racc (1.8.1)
23
21
  rainbow (3.1.1)
24
22
  rake (13.2.1)
25
- regexp_parser (2.9.1)
26
- rexml (3.2.8)
27
- strscan (>= 3.0.9)
23
+ regexp_parser (2.9.3)
28
24
  rspec (3.13.0)
29
25
  rspec-core (~> 3.13.0)
30
26
  rspec-expectations (~> 3.13.0)
31
27
  rspec-mocks (~> 3.13.0)
32
- rspec-core (3.13.0)
28
+ rspec-core (3.13.2)
33
29
  rspec-support (~> 3.13.0)
34
- rspec-expectations (3.13.0)
30
+ rspec-expectations (3.13.3)
35
31
  diff-lcs (>= 1.2.0, < 2.0)
36
32
  rspec-support (~> 3.13.0)
37
- rspec-mocks (3.13.0)
33
+ rspec-mocks (3.13.2)
38
34
  diff-lcs (>= 1.2.0, < 2.0)
39
35
  rspec-support (~> 3.13.0)
40
- rspec-support (3.13.1)
41
- rubocop (1.63.5)
36
+ rspec-support (3.13.2)
37
+ rubocop (1.68.0)
42
38
  json (~> 2.3)
43
39
  language_server-protocol (>= 3.17.0)
44
40
  parallel (~> 1.10)
45
41
  parser (>= 3.3.0.2)
46
42
  rainbow (>= 2.2.2, < 4.0)
47
- regexp_parser (>= 1.8, < 3.0)
48
- rexml (>= 3.2.5, < 4.0)
49
- rubocop-ast (>= 1.31.1, < 2.0)
43
+ regexp_parser (>= 2.4, < 3.0)
44
+ rubocop-ast (>= 1.32.2, < 2.0)
50
45
  ruby-progressbar (~> 1.7)
51
46
  unicode-display_width (>= 2.4.0, < 3.0)
52
- rubocop-ast (1.31.3)
47
+ rubocop-ast (1.36.2)
53
48
  parser (>= 3.3.1.0)
54
- rubocop-performance (1.21.0)
49
+ rubocop-performance (1.22.1)
55
50
  rubocop (>= 1.48.1, < 2.0)
56
51
  rubocop-ast (>= 1.31.1, < 2.0)
57
52
  ruby-progressbar (1.13.0)
58
- standard (1.36.0)
53
+ rubyzip (2.3.2)
54
+ standard (1.42.1)
59
55
  language_server-protocol (~> 3.17.0.2)
60
56
  lint_roller (~> 1.0)
61
- rubocop (~> 1.63.0)
57
+ rubocop (~> 1.68.0)
62
58
  standard-custom (~> 1.0.0)
63
- standard-performance (~> 1.4)
59
+ standard-performance (~> 1.5)
64
60
  standard-custom (1.0.2)
65
61
  lint_roller (~> 1.0)
66
62
  rubocop (~> 1.50)
67
- standard-performance (1.4.0)
63
+ standard-performance (1.5.0)
68
64
  lint_roller (~> 1.1)
69
- rubocop-performance (~> 1.21.0)
70
- strscan (3.1.0)
71
- unicode-display_width (2.5.0)
65
+ rubocop-performance (~> 1.22.0)
66
+ unicode-display_width (2.6.0)
72
67
 
73
68
  PLATFORMS
74
69
  ruby
@@ -76,6 +71,9 @@ PLATFORMS
76
71
 
77
72
  DEPENDENCIES
78
73
  astronoby!
74
+ rake (~> 13.0)
75
+ rspec (~> 3.0)
76
+ rubyzip (~> 2.3)
79
77
  standard (~> 1.3)
80
78
 
81
79
  BUNDLED WITH
data/README.md CHANGED
@@ -140,32 +140,37 @@ horizontal_coordinates.altitude.str(:dms)
140
140
 
141
141
  #### Sunrise and sunset times and azimuths
142
142
 
143
+ Only date part of the time is relevant for the calculation. The offset must
144
+ be provided to the observer.
145
+
143
146
  ```rb
144
- time = Time.new(2015, 2, 5)
147
+ utc_offset = "-05:00"
148
+ time = Time.new(2015, 2, 5, 0, 0, 0, utc_offset)
145
149
  observer = Astronoby::Observer.new(
146
150
  latitude: Astronoby::Angle.from_degrees(38),
147
- longitude: Astronoby::Angle.from_degrees(-78)
151
+ longitude: Astronoby::Angle.from_degrees(-78),
152
+ utc_offset: utc_offset
148
153
  )
149
154
  sun = Astronoby::Sun.new(time: time)
150
155
  observation_events = sun.observation_events(observer: observer)
151
156
 
152
- observation_events.rising_time
153
- # => 2015-02-05 12:12:59 UTC
157
+ observation_events.rising_time.getlocal(utc_offset)
158
+ # => 2015-02-05 07:12:59 -0500
154
159
 
155
160
  observation_events.rising_azimuth.str(:dms)
156
- # => "+109° 29′ 34.3674″"
161
+ # => "+109° 29′ 35.5069″"
157
162
 
158
- observation_events.transit_time
159
- # => 2015-02-05 17:25:59 UTC
163
+ observation_events.transit_time.getlocal(utc_offset)
164
+ # => 2015-02-05 12:25:59 -0500
160
165
 
161
166
  observation_events.transit_altitude.str(:dms)
162
- # => "+36° 8′ 15.8197″"
167
+ # => "+36° 8′ 14.9673″"
163
168
 
164
- observation_events.setting_time
165
- # => 2015-02-05 22:39:27 UTC
169
+ observation_events.setting_time.getlocal(utc_offset)
170
+ # => 2015-02-05 17:39:27 -0500
166
171
 
167
172
  observation_events.setting_azimuth.str(:dms)
168
- # => "+250° 40′ 42.8609″"
173
+ # => "+250° 40′ 41.7129″"
169
174
  ```
170
175
 
171
176
  #### Twilight times
@@ -244,6 +249,9 @@ moon = Astronoby::Moon.new(time: time)
244
249
  moon.illuminated_fraction.round(2)
245
250
  # => 0.31
246
251
 
252
+ moon.current_phase_fraction.round(2)
253
+ # => 0.82
254
+
247
255
  moon.distance.km.round
248
256
  # => 368409
249
257
 
@@ -268,32 +276,37 @@ june_phases.each { puts "#{_1.phase}: #{_1.time}" }
268
276
 
269
277
  #### Moonrise and moonset times and azimuths
270
278
 
279
+ Only date part of the time is relevant for the calculation. The offset must
280
+ be provided to the observer.
281
+
271
282
  ```rb
272
- time = Time.utc(2024, 6, 1, 10, 0, 0)
283
+ utc_offset = "-10:00"
284
+ time = Time.new(2024, 9, 1, 0, 0, 0, utc_offset)
273
285
  observer = Astronoby::Observer.new(
274
- latitude: Astronoby::Angle.from_degrees(48.8566),
275
- longitude: Astronoby::Angle.from_degrees(2.3522)
286
+ latitude: Astronoby::Angle.from_degrees(-17.5325),
287
+ longitude: Astronoby::Angle.from_degrees(-149.5677),
288
+ utc_offset: utc_offset
276
289
  )
277
290
  moon = Astronoby::Moon.new(time: time)
278
291
  observation_events = moon.observation_events(observer: observer)
279
292
 
280
- observation_events.rising_time
281
- # => 2024-06-01 00:35:36 UTC
293
+ observation_events.rising_time.getlocal(utc_offset)
294
+ # => 2024-09-01 05:24:55 -1000
282
295
 
283
296
  observation_events.rising_azimuth.str(:dms)
284
- # => "+93° 743.2347″"
297
+ # => "+72° 1519.1814″"
285
298
 
286
- observation_events.transit_time
287
- # => 2024-06-01 02:42:43 UTC
299
+ observation_events.transit_time.getlocal(utc_offset)
300
+ # => 2024-09-01 11:12:32 -1000
288
301
 
289
302
  observation_events.transit_altitude.str(:dms)
290
- # => "+26° 5930.9915″"
303
+ # => "+56° 3959.132″"
291
304
 
292
- observation_events.setting_time
293
- # => 2024-06-01 16:02:26 UTC
305
+ observation_events.setting_time.getlocal(utc_offset)
306
+ # => 2024-09-01 16:12:08 -1000
294
307
 
295
308
  observation_events.setting_azimuth.str(:dms)
296
- # => "+273° 2930.0954″"
309
+ # => "+290° 2542.5421″"
297
310
  ```
298
311
 
299
312
  ## Precision
@@ -0,0 +1,131 @@
1
+ # Benchmark
2
+
3
+ This is a first attempt to benchmark the accuracy of the library. It is not
4
+ very scientific, but it gives a rough idea.
5
+
6
+ ## Method
7
+
8
+ The goal is to answer these two questions:
9
+ - Is the library accurate enough compared to a source of truth?
10
+ - Is the library accurate enough compared with other Ruby libraries?
11
+
12
+ The source of truth is the <abbr title="Institut de Mécanique
13
+ Céleste et de Calcul des Éphémérides">IMCCE</abbr>, a French public
14
+ institude attached to the Paris Observatory. Their ephemerides are used by
15
+ governements and public institutions in multiple European countries, their
16
+ precesion is among the highest in the world.
17
+ They also provide web services to easily access all their data. Many thanks
18
+ for providing such high accuracy data for free.
19
+
20
+ The other Ruby library is [sun_calc](https://github.com/fishbrain/sun_calc).
21
+
22
+ 474,336 combinations of dates, latitudes and longitudes have been used to
23
+ produce time predictions for the following events:
24
+ - sunrise
25
+ - sun's highest point
26
+ - sunset
27
+ - moonrise
28
+ - moon's highest point
29
+ - moonset
30
+
31
+ For each combination, we first find out which of SunCalc or Astronoby is the
32
+ closest to the IMCCE. Then we calculate the difference between Astronoby and
33
+ the IMCCE, to discover if the difference is larger than the defined
34
+ threshold of 5 minutes.
35
+
36
+ ## Results
37
+
38
+ The following output has been generated using what will be part of version 0.6.
39
+
40
+ ```
41
+ Unarchiving sun_calc.csv.zip...
42
+ Done unarchiving sun_calc.csv.zip.
43
+ Parsing sun_calc.csv...
44
+ Done parsing sun_calc.csv.
45
+ Unarchiving imcce.csv.zip...
46
+ Done unarchiving imcce.csv.zip.
47
+ Parsing imcce.csv...
48
+ Done parsing imcce.csv.
49
+ Comparing data...
50
+ 2024-01-01: Done.
51
+ 2024-01-02: Done.
52
+ ...
53
+ 2024-12-30: Done.
54
+ 2024-12-31: Done.
55
+ Done comparing data.
56
+
57
+
58
+ Sun rising time:
59
+ astronoby: 295395 (62.28%)
60
+ sun_calc: 99710 (21.02%)
61
+ n/a: 79231 (16.7%)
62
+
63
+ Sun transit time:
64
+ astronoby: 434495 (91.6%)
65
+ sun_calc: 39769 (8.38%)
66
+ n/a: 72 (0.02%)
67
+
68
+ Sun setting time:
69
+ astronoby: 358428 (75.56%)
70
+ n/a: 79231 (16.7%)
71
+ sun_calc: 36677 (7.73%)
72
+
73
+ Moon rising time:
74
+ astronoby: 290866 (61.32%)
75
+ n/a: 113815 (23.99%)
76
+ sun_calc: 69655 (14.68%)
77
+
78
+ Moon transit time:
79
+ astronoby: 341902 (72.08%)
80
+ n/a: 101916 (21.49%)
81
+ sun_calc: 30518 (6.43%)
82
+
83
+ Moon setting time:
84
+ astronoby: 327099 (68.96%)
85
+ n/a: 114308 (24.1%)
86
+ sun_calc: 32929 (6.94%)
87
+
88
+ Moon illuminated fraction:
89
+ astronoby: 474336 (100.0%)
90
+
91
+ Sun rising time too far:
92
+ false: 452887 (95.48%)
93
+ true: 21449 (4.52%)
94
+
95
+ Sun transit time too far:
96
+ false: 396617 (83.62%)
97
+ true: 77719 (16.38%)
98
+
99
+ Sun setting time too far:
100
+ false: 453208 (95.55%)
101
+ true: 21128 (4.45%)
102
+
103
+ Moon rising time too far:
104
+ false: 459044 (96.78%)
105
+ true: 15292 (3.22%)
106
+
107
+ Moon transit time too far:
108
+ false: 384516 (81.06%)
109
+ true: 89820 (18.94%)
110
+
111
+ Moon setting time too far:
112
+ false: 459222 (96.81%)
113
+ true: 15114 (3.19%)
114
+ ```
115
+
116
+ ## Conclusion
117
+
118
+ As we can see, Astronoby is more accurate than SunCalc in a vast majority of
119
+ cases. When it comes to the Moon's illuminated fraction, Astronoby is always
120
+ more accurate than SunCalc.
121
+
122
+ `n/a` values means that at least one of the three sources don't have a value
123
+ for the combination of date, latitude and longitude. This happens because
124
+ the Moon and the Sun cannot always rise, transit and set everywhere on Earth
125
+ every day of the year. Latitudes close to the poles are more likely to miss
126
+ data.
127
+
128
+ Astronoby can be considered "good enough" for more around 90% of the cases,
129
+ which means there is still work to do if we want to always be less than 5
130
+ minutes away from the what the IMCCE provides. We can notice that transit
131
+ times are those that experience the most significant differences.
@@ -0,0 +1,259 @@
1
+ require "astronoby"
2
+ require "csv"
3
+ require "zip"
4
+
5
+ class Source
6
+ NAMES = [
7
+ ASTRONOBY = "astronoby",
8
+ IMCCE = "imcce",
9
+ SUN_CALC = "sun_calc"
10
+ ].freeze
11
+
12
+ attr_accessor :name,
13
+ :sun_rising_time,
14
+ :sun_transit_time,
15
+ :sun_setting_time,
16
+ :moon_rising_time,
17
+ :moon_transit_time,
18
+ :moon_setting_time,
19
+ :moon_illuminated_fraction
20
+ end
21
+
22
+ class Comparison
23
+ SUN_CALC = "sun_calc"
24
+ ASTRONOBY = "astronoby"
25
+ NON_APPLICABLE = "n/a"
26
+
27
+ TOO_FAR_THRESHOLD = 60 * 5 # 5 minutes
28
+
29
+ attr_accessor :sources, :truth
30
+
31
+ def initialize
32
+ @sources = []
33
+ end
34
+
35
+ %i[
36
+ sun_rising_time
37
+ sun_transit_time
38
+ sun_setting_time
39
+ moon_rising_time
40
+ moon_transit_time
41
+ moon_setting_time
42
+ ].each do |attribute|
43
+ define_method(:"closest_#{attribute}") do
44
+ compare(attribute)
45
+ end
46
+
47
+ define_method(:"#{attribute}_too_far?") do
48
+ too_far?(attribute)
49
+ end
50
+ end
51
+
52
+ def closest_moon_illuminated_fraction
53
+ compare(:moon_illuminated_fraction)
54
+ end
55
+
56
+ private
57
+
58
+ def compare(attribute)
59
+ unless truth.public_send(attribute) && sources.all? { |source| source.public_send(attribute) }
60
+ return NON_APPLICABLE
61
+ end
62
+
63
+ closest_source = sources.min_by do |source|
64
+ (truth.public_send(attribute) - source.public_send(attribute)).abs
65
+ end
66
+
67
+ closest_source.name
68
+ end
69
+
70
+ def too_far?(attribute)
71
+ truth_attribute = truth.public_send(attribute)
72
+ astronoby_attribute = sources
73
+ .find { _1.name == Source::ASTRONOBY }
74
+ .public_send(attribute)
75
+
76
+ return false unless truth_attribute && astronoby_attribute
77
+
78
+ (truth_attribute - astronoby_attribute).abs > TOO_FAR_THRESHOLD
79
+ end
80
+ end
81
+
82
+ class Result
83
+ def initialize
84
+ @sun_rising_time = []
85
+ @sun_transit_time = []
86
+ @sun_setting_time = []
87
+ @moon_rising_time = []
88
+ @moon_transit_time = []
89
+ @moon_setting_time = []
90
+ @illuminated_fraction = []
91
+ @sun_rising_time_too_far = []
92
+ @sun_transit_time_too_far = []
93
+ @sun_setting_time_too_far = []
94
+ @moon_rising_time_too_far = []
95
+ @moon_transit_time_too_far = []
96
+ @moon_setting_time_too_far = []
97
+ end
98
+
99
+ def add_comparison(comparison)
100
+ @sun_rising_time << comparison.closest_sun_rising_time
101
+ @sun_transit_time << comparison.closest_sun_transit_time
102
+ @sun_setting_time << comparison.closest_sun_setting_time
103
+ @moon_rising_time << comparison.closest_moon_rising_time
104
+ @moon_transit_time << comparison.closest_moon_transit_time
105
+ @moon_setting_time << comparison.closest_moon_setting_time
106
+ @illuminated_fraction << comparison.closest_moon_illuminated_fraction
107
+ @sun_rising_time_too_far << comparison.sun_rising_time_too_far?
108
+ @sun_transit_time_too_far << comparison.sun_transit_time_too_far?
109
+ @sun_setting_time_too_far << comparison.sun_setting_time_too_far?
110
+ @moon_rising_time_too_far << comparison.moon_rising_time_too_far?
111
+ @moon_transit_time_too_far << comparison.moon_transit_time_too_far?
112
+ @moon_setting_time_too_far << comparison.moon_setting_time_too_far?
113
+ end
114
+
115
+ def display
116
+ puts "Sun rising time:"
117
+ tally(@sun_rising_time)
118
+ puts "Sun transit time:"
119
+ tally(@sun_transit_time)
120
+ puts "Sun setting time:"
121
+ tally(@sun_setting_time)
122
+ puts "Moon rising time:"
123
+ tally(@moon_rising_time)
124
+ puts "Moon transit time:"
125
+ tally(@moon_transit_time)
126
+ puts "Moon setting time:"
127
+ tally(@moon_setting_time)
128
+ puts "Moon illuminated fraction:"
129
+ tally(@illuminated_fraction)
130
+ puts "Sun rising time too far:"
131
+ tally(@sun_rising_time_too_far)
132
+ puts "Sun transit time too far:"
133
+ tally(@sun_transit_time_too_far)
134
+ puts "Sun setting time too far:"
135
+ tally(@sun_setting_time_too_far)
136
+ puts "Moon rising time too far:"
137
+ tally(@moon_rising_time_too_far)
138
+ puts "Moon transit time too far:"
139
+ tally(@moon_transit_time_too_far)
140
+ puts "Moon setting time too far:"
141
+ tally(@moon_setting_time_too_far)
142
+ end
143
+
144
+ private
145
+
146
+ def tally(data)
147
+ t = data.tally
148
+ t.sort_by { |_key, value| -value }.each do |key, value|
149
+ puts "#{key}: #{value} (#{(value.to_f / t.values.sum * 100).round(2)}%)"
150
+ end
151
+ puts "\n"
152
+ end
153
+ end
154
+
155
+ data = {}
156
+ result = Result.new
157
+
158
+ sun_calc_zip_file = File.join(File.dirname(__FILE__), "data/sun_calc.csv.zip")
159
+ imcce_zip_file = File.join(File.dirname(__FILE__), "data/imcce.csv.zip")
160
+
161
+ puts "Unarchiving sun_calc.csv.zip..."
162
+
163
+ Zip::File.open(sun_calc_zip_file) do |zip_file|
164
+ puts "Done unarchiving sun_calc.csv.zip."
165
+
166
+ csv_file = zip_file.find { |entry| entry.name.end_with?(".csv") }
167
+ break unless csv_file
168
+
169
+ puts "Parsing sun_calc.csv..."
170
+
171
+ csv_content = csv_file.get_input_stream.read
172
+ CSV.parse(csv_content, headers: true) do |row|
173
+ data[row["date"]] ||= {}
174
+ data[row["date"]][row["latitude"]] ||= {}
175
+ data[row["date"]][row["latitude"]][row["longitude"]] = Comparison.new.tap do |comparison|
176
+ source = Source.new.tap do |source|
177
+ source.name = Source::SUN_CALC
178
+ source.sun_rising_time = Time.new(row["sun_rising_time"]) if row["sun_rising_time"]
179
+ source.sun_transit_time = Time.new(row["sun_transit_time"]) if row["sun_transit_time"]
180
+ source.sun_setting_time = Time.new(row["sun_setting_time"]) if row["sun_setting_time"]
181
+ source.moon_rising_time = Time.new(row["moon_rising_time"]) if row["moon_rising_time"]
182
+ source.moon_transit_time = Time.new(row["moon_transit_time"]) if row["moon_transit_time"]
183
+ source.moon_setting_time = Time.new(row["moon_setting_time"]) if row["moon_setting_time"]
184
+ source.moon_illuminated_fraction = row["illuminated_fraction"].to_f
185
+ end
186
+ comparison.sources << source
187
+ end
188
+ end
189
+
190
+ puts "Done parsing sun_calc.csv."
191
+ end
192
+
193
+ puts "Unarchiving imcce.csv.zip..."
194
+
195
+ Zip::File.open(imcce_zip_file) do |zip_file|
196
+ puts "Done unarchiving imcce.csv.zip."
197
+
198
+ csv_file = zip_file.find { |entry| entry.name.end_with?(".csv") }
199
+ break unless csv_file
200
+
201
+ puts "Parsing imcce.csv..."
202
+
203
+ csv_content = csv_file.get_input_stream.read
204
+ CSV.parse(csv_content, headers: true) do |row|
205
+ comparison = data[row["date"]][row["latitude"]][row["longitude"]]
206
+ comparison.truth = Source.new.tap do |source|
207
+ source.name = Source::IMCCE
208
+ source.sun_rising_time = Time.new(row["sun_rising_time"] + " UTC") if row["sun_rising_time"]
209
+ source.sun_transit_time = Time.new(row["sun_transit_time"] + " UTC") if row["sun_transit_time"]
210
+ source.sun_setting_time = Time.new(row["sun_setting_time"] + " UTC") if row["sun_setting_time"]
211
+ source.moon_rising_time = Time.new(row["moon_rising_time"] + " UTC") if row["moon_rising_time"]
212
+ source.moon_transit_time = Time.new(row["moon_transit_time"] + " UTC") if row["moon_transit_time"]
213
+ source.moon_setting_time = Time.new(row["moon_setting_time"] + " UTC") if row["moon_setting_time"]
214
+ source.moon_illuminated_fraction = row["illuminated_fraction"].to_f
215
+ end
216
+ end
217
+
218
+ puts "Done parsing imcce.csv."
219
+ end
220
+
221
+ puts "Comparing data..."
222
+
223
+ data.each do |date, latitudes|
224
+ latitudes.each do |latitude, longitudes|
225
+ longitudes.each do |longitude, comparison|
226
+ noon = Time.new("#{date}T12:00:00Z")
227
+ observer = Astronoby::Observer.new(
228
+ latitude: Astronoby::Angle.from_degrees(latitude.to_i),
229
+ longitude: Astronoby::Angle.from_degrees(longitude.to_i)
230
+ )
231
+ sun = Astronoby::Sun.new(time: noon)
232
+ sun_observation_events = sun.observation_events(observer: observer)
233
+ moon = Astronoby::Moon.new(time: noon)
234
+ moon_observation_events = moon.observation_events(observer: observer)
235
+
236
+ source = Source.new.tap do |source|
237
+ source.name = Source::ASTRONOBY
238
+ source.sun_rising_time = sun_observation_events.rising_time
239
+ source.sun_transit_time = sun_observation_events.transit_time
240
+ source.sun_setting_time = sun_observation_events.setting_time
241
+ source.moon_rising_time = moon_observation_events.rising_time
242
+ source.moon_transit_time = moon_observation_events.transit_time
243
+ source.moon_setting_time = moon_observation_events.setting_time
244
+ source.moon_illuminated_fraction = moon.illuminated_fraction
245
+ end
246
+
247
+ comparison.sources << source
248
+ result.add_comparison(comparison)
249
+ end
250
+ end
251
+
252
+ puts "#{date}: Done."
253
+ end
254
+
255
+ puts "Done comparing data."
256
+ puts
257
+ puts
258
+
259
+ puts result.display
Binary file
Binary file
@@ -167,6 +167,11 @@ module Astronoby
167
167
  @illuminated_fraction ||= (1 + phase_angle.cos) / 2
168
168
  end
169
169
 
170
+ # @return [Float] Phase fraction, from 0 to 1
171
+ def current_phase_fraction
172
+ mean_elongation.degrees / Constants::DEGREES_PER_CIRCLE
173
+ end
174
+
170
175
  # @param observer [Astronoby::Observer] Observer of the event
171
176
  # @return [Astronoby::Events::ObservationEvents] Moon's observation events
172
177
  def observation_events(observer:)
@@ -7,6 +7,7 @@ module Astronoby
7
7
  RISING_SETTING_HOUR_ANGLE_RATIO_RANGE = (-1..1)
8
8
  EARTH_SIDEREAL_ROTATION_RATE = 360.98564736629
9
9
  ITERATION_PRECISION = 0.0001
10
+ ITERATION_LIMIT = 5
10
11
 
11
12
  attr_reader :rising_time,
12
13
  :rising_azimuth,
@@ -53,7 +54,11 @@ module Astronoby
53
54
 
54
55
  def compute
55
56
  @initial_transit = initial_transit
56
- @transit_time = Util::Time.decimal_hour_to_time(@date, @initial_transit)
57
+ @transit_time = Util::Time.decimal_hour_to_time(
58
+ @date,
59
+ @observer.utc_offset,
60
+ @initial_transit
61
+ )
57
62
  @transit_altitude = local_horizontal_altitude_transit
58
63
 
59
64
  return if h0.nil?
@@ -79,20 +84,33 @@ module Astronoby
79
84
  Constants::HOURS_PER_DAY * @final_setting
80
85
  )
81
86
 
82
- @rising_time = Util::Time.decimal_hour_to_time(@date, rationalized_corrected_rising)
87
+ @rising_time = Util::Time.decimal_hour_to_time(
88
+ @date,
89
+ @observer.utc_offset,
90
+ rationalized_corrected_rising
91
+ )
83
92
  @rising_azimuth = local_horizontal_azimuth_rising
84
- @transit_time = Util::Time.decimal_hour_to_time(@date, rationalized_corrected_transit)
93
+ @transit_time = Util::Time.decimal_hour_to_time(
94
+ @date,
95
+ @observer.utc_offset,
96
+ rationalized_corrected_transit
97
+ )
85
98
  @transit_altitude = local_horizontal_altitude_transit
86
- @setting_time = Util::Time.decimal_hour_to_time(@date, rationalized_corrected_setting)
99
+ @setting_time = Util::Time.decimal_hour_to_time(
100
+ @date,
101
+ @observer.utc_offset,
102
+ rationalized_corrected_setting
103
+ )
87
104
  @setting_azimuth = local_horizontal_azimuth_setting
88
105
  end
89
106
 
90
107
  def iterate(initial_rising, initial_transit, initial_setting)
91
108
  delta = 1
109
+ iteration = 1
92
110
  corrected_rising = initial_rising
93
111
  corrected_transit = initial_transit
94
112
  corrected_setting = initial_setting
95
- until delta < ITERATION_PRECISION
113
+ until delta < ITERATION_PRECISION || iteration > ITERATION_LIMIT
96
114
  iterate = RiseTransitSetIteration.new(
97
115
  observer: @observer,
98
116
  date: @date,
@@ -108,6 +126,7 @@ module Astronoby
108
126
  corrected_rising = rationalize_decimal_time corrected_rising + iterate[0]
109
127
  corrected_transit = rationalize_decimal_time corrected_transit + iterate[1]
110
128
  corrected_setting = rationalize_decimal_time corrected_setting + iterate[2]
129
+ iteration += 1
111
130
  end
112
131
  [corrected_rising, corrected_transit, corrected_setting]
113
132
  end
@@ -155,11 +174,6 @@ module Astronoby
155
174
  )
156
175
  end
157
176
 
158
- def leap_day_portion
159
- leap_seconds = Util::Time.terrestrial_universal_time_delta(@date)
160
- leap_seconds / Constants::SECONDS_PER_DAY
161
- end
162
-
163
177
  def local_hour_angle_transit
164
178
  gst_transit - observer_longitude - right_ascension_transit
165
179
  end
@@ -168,6 +182,8 @@ module Astronoby
168
182
  term1 = declination_rising.sin + (-shift).sin * @observer.latitude.cos
169
183
  term2 = (-shift).cos * @observer.latitude.cos
170
184
  angle = term1 / term2
185
+ return nil if angle.abs > 1
186
+
171
187
  Angle.acos(angle)
172
188
  end
173
189
 
@@ -182,14 +198,16 @@ module Astronoby
182
198
  term1 = declination_setting.sin + (-shift).sin * @observer.latitude.cos
183
199
  term2 = (-shift).cos * @observer.latitude.cos
184
200
  angle = term1 / term2
201
+ return nil if angle.abs > 1
202
+
185
203
  Angle.from_degrees(
186
204
  Constants::DEGREES_PER_CIRCLE - Angle.acos(angle).degrees
187
205
  )
188
206
  end
189
207
 
190
208
  def rationalize_decimal_time(decimal_time)
191
- decimal_time += 1 if decimal_time.negative?
192
- decimal_time -= 1 if decimal_time > 1
209
+ decimal_time += 1 while decimal_time.negative?
210
+ decimal_time -= 1 while decimal_time > 1
193
211
  decimal_time
194
212
  end
195
213
 
@@ -202,12 +220,14 @@ module Astronoby
202
220
  def right_ascension_transit
203
221
  Angle.from_degrees(
204
222
  Util::Maths.interpolate(
205
- [
206
- @coordinates_of_the_previous_day.right_ascension.degrees,
207
- @coordinates_of_the_day.right_ascension.degrees,
208
- @coordinates_of_the_next_day.right_ascension.degrees
209
- ],
210
- (@final_transit || @initial_transit) + leap_day_portion
223
+ Util::Maths.normalize_angles_for_interpolation(
224
+ [
225
+ @coordinates_of_the_previous_day.right_ascension.degrees,
226
+ @coordinates_of_the_day.right_ascension.degrees,
227
+ @coordinates_of_the_next_day.right_ascension.degrees
228
+ ]
229
+ ),
230
+ @final_transit || @initial_transit
211
231
  )
212
232
  )
213
233
  end
@@ -215,12 +235,14 @@ module Astronoby
215
235
  def declination_rising
216
236
  Angle.from_degrees(
217
237
  Util::Maths.interpolate(
218
- [
219
- @coordinates_of_the_previous_day.declination.degrees,
220
- @coordinates_of_the_day.declination.degrees,
221
- @coordinates_of_the_next_day.declination.degrees
222
- ],
223
- @final_rising + leap_day_portion
238
+ Util::Maths.normalize_angles_for_interpolation(
239
+ [
240
+ @coordinates_of_the_previous_day.declination.degrees,
241
+ @coordinates_of_the_day.declination.degrees,
242
+ @coordinates_of_the_next_day.declination.degrees
243
+ ]
244
+ ),
245
+ @final_rising
224
246
  )
225
247
  )
226
248
  end
@@ -228,12 +250,14 @@ module Astronoby
228
250
  def declination_transit
229
251
  Angle.from_degrees(
230
252
  Util::Maths.interpolate(
231
- [
232
- @coordinates_of_the_previous_day.declination.degrees,
233
- @coordinates_of_the_day.declination.degrees,
234
- @coordinates_of_the_next_day.declination.degrees
235
- ],
236
- (@final_transit || @initial_transit) + leap_day_portion
253
+ Util::Maths.normalize_angles_for_interpolation(
254
+ [
255
+ @coordinates_of_the_previous_day.declination.degrees,
256
+ @coordinates_of_the_day.declination.degrees,
257
+ @coordinates_of_the_next_day.declination.degrees
258
+ ]
259
+ ),
260
+ @final_transit || @initial_transit
237
261
  )
238
262
  )
239
263
  end
@@ -241,12 +265,14 @@ module Astronoby
241
265
  def declination_setting
242
266
  Angle.from_degrees(
243
267
  Util::Maths.interpolate(
244
- [
245
- @coordinates_of_the_previous_day.declination.degrees,
246
- @coordinates_of_the_day.declination.degrees,
247
- @coordinates_of_the_next_day.declination.degrees
248
- ],
249
- @final_setting + leap_day_portion
268
+ Util::Maths.normalize_angles_for_interpolation(
269
+ [
270
+ @coordinates_of_the_previous_day.declination.degrees,
271
+ @coordinates_of_the_day.declination.degrees,
272
+ @coordinates_of_the_next_day.declination.degrees
273
+ ]
274
+ ),
275
+ @final_setting
250
276
  )
251
277
  )
252
278
  end
@@ -112,13 +112,6 @@ module Astronoby
112
112
  )
113
113
  end
114
114
 
115
- def leap_day_portion
116
- @leap_day_portion ||= begin
117
- leap_seconds = Util::Time.terrestrial_universal_time_delta(@date)
118
- leap_seconds / Constants::SECONDS_PER_DAY
119
- end
120
- end
121
-
122
115
  def local_hour_angle_rising
123
116
  @local_hour_angle_rising ||=
124
117
  gst_rising - observer_longitude - right_ascension_rising
@@ -150,12 +143,14 @@ module Astronoby
150
143
  def right_ascension_rising
151
144
  Angle.from_degrees(
152
145
  Util::Maths.interpolate(
153
- [
154
- @coordinates_of_the_previous_day.right_ascension.degrees,
155
- @coordinates_of_the_day.right_ascension.degrees,
156
- @coordinates_of_the_next_day.right_ascension.degrees
157
- ],
158
- @initial_rising + leap_day_portion
146
+ Util::Maths.normalize_angles_for_interpolation(
147
+ [
148
+ @coordinates_of_the_previous_day.right_ascension.degrees,
149
+ @coordinates_of_the_day.right_ascension.degrees,
150
+ @coordinates_of_the_next_day.right_ascension.degrees
151
+ ]
152
+ ),
153
+ @initial_rising
159
154
  )
160
155
  )
161
156
  end
@@ -163,12 +158,14 @@ module Astronoby
163
158
  def right_ascension_transit
164
159
  Angle.from_degrees(
165
160
  Util::Maths.interpolate(
166
- [
167
- @coordinates_of_the_previous_day.right_ascension.degrees,
168
- @coordinates_of_the_day.right_ascension.degrees,
169
- @coordinates_of_the_next_day.right_ascension.degrees
170
- ],
171
- @initial_transit + leap_day_portion
161
+ Util::Maths.normalize_angles_for_interpolation(
162
+ [
163
+ @coordinates_of_the_previous_day.right_ascension.degrees,
164
+ @coordinates_of_the_day.right_ascension.degrees,
165
+ @coordinates_of_the_next_day.right_ascension.degrees
166
+ ]
167
+ ),
168
+ @initial_transit
172
169
  )
173
170
  )
174
171
  end
@@ -176,12 +173,14 @@ module Astronoby
176
173
  def right_ascension_setting
177
174
  Angle.from_degrees(
178
175
  Util::Maths.interpolate(
179
- [
180
- @coordinates_of_the_previous_day.right_ascension.degrees,
181
- @coordinates_of_the_day.right_ascension.degrees,
182
- @coordinates_of_the_next_day.right_ascension.degrees
183
- ],
184
- @initial_setting + leap_day_portion
176
+ Util::Maths.normalize_angles_for_interpolation(
177
+ [
178
+ @coordinates_of_the_previous_day.right_ascension.degrees,
179
+ @coordinates_of_the_day.right_ascension.degrees,
180
+ @coordinates_of_the_next_day.right_ascension.degrees
181
+ ]
182
+ ),
183
+ @initial_setting
185
184
  )
186
185
  )
187
186
  end
@@ -189,12 +188,14 @@ module Astronoby
189
188
  def declination_rising
190
189
  Angle.from_degrees(
191
190
  Util::Maths.interpolate(
192
- [
193
- @coordinates_of_the_previous_day.declination.degrees,
194
- @coordinates_of_the_day.declination.degrees,
195
- @coordinates_of_the_next_day.declination.degrees
196
- ],
197
- @initial_rising + leap_day_portion
191
+ Util::Maths.normalize_angles_for_interpolation(
192
+ [
193
+ @coordinates_of_the_previous_day.declination.degrees,
194
+ @coordinates_of_the_day.declination.degrees,
195
+ @coordinates_of_the_next_day.declination.degrees
196
+ ]
197
+ ),
198
+ @initial_rising
198
199
  )
199
200
  )
200
201
  end
@@ -202,12 +203,14 @@ module Astronoby
202
203
  def declination_setting
203
204
  Angle.from_degrees(
204
205
  Util::Maths.interpolate(
205
- [
206
- @coordinates_of_the_previous_day.declination.degrees,
207
- @coordinates_of_the_day.declination.degrees,
208
- @coordinates_of_the_next_day.declination.degrees
209
- ],
210
- @initial_setting + leap_day_portion
206
+ Util::Maths.normalize_angles_for_interpolation(
207
+ [
208
+ @coordinates_of_the_previous_day.declination.degrees,
209
+ @coordinates_of_the_day.declination.degrees,
210
+ @coordinates_of_the_next_day.declination.degrees
211
+ ]
212
+ ),
213
+ @initial_setting
211
214
  )
212
215
  )
213
216
  end
@@ -10,12 +10,18 @@ module Astronoby
10
10
  MOLAR_MASS_OF_AIR = 0.0289644
11
11
  UNIVERSAL_GAS_CONSTANT = 8.31432
12
12
 
13
- attr_reader :latitude, :longitude, :elevation, :temperature, :pressure
13
+ attr_reader :latitude,
14
+ :longitude,
15
+ :elevation,
16
+ :utc_offset,
17
+ :temperature,
18
+ :pressure
14
19
 
15
20
  # @param latitude [Angle] geographic latitude of the observer
16
21
  # @param longitude [Angle] geographic longitude of the observer
17
22
  # @param elevation [Astronoby::Distance] geographic elevation (or altitude)
18
23
  # of the observer above sea level
24
+ # @param utc_offset [Numeric, String] offset from Coordinated Universal Time
19
25
  # @param temperature [Numeric] temperature at the observer's location in
20
26
  # kelvins
21
27
  # @param pressure [Numeric] atmospheric pressure at the observer's
@@ -24,12 +30,14 @@ module Astronoby
24
30
  latitude:,
25
31
  longitude:,
26
32
  elevation: DEFAULT_ELEVATION,
33
+ utc_offset: 0,
27
34
  temperature: DEFAULT_TEMPERATURE,
28
35
  pressure: nil
29
36
  )
30
37
  @latitude = latitude
31
38
  @longitude = longitude
32
39
  @elevation = elevation
40
+ @utc_offset = utc_offset
33
41
  @temperature = temperature
34
42
  @pressure = pressure || compute_pressure
35
43
  end
@@ -40,6 +48,7 @@ module Astronoby
40
48
  @latitude == other.latitude &&
41
49
  @longitude == other.longitude &&
42
50
  @elevation == other.elevation &&
51
+ @utc_offset == other.utc_offset &&
43
52
  @temperature == other.temperature &&
44
53
  @pressure == other.pressure
45
54
  end
@@ -51,6 +60,7 @@ module Astronoby
51
60
  @latitude,
52
61
  @longitude,
53
62
  @elevation,
63
+ @utc_offset,
54
64
  @temperature,
55
65
  @pressure
56
66
  ].hash
@@ -65,7 +65,7 @@ module Astronoby
65
65
 
66
66
  utc = SIDEREAL_MINUTE_IN_UT_MINUTE * a
67
67
 
68
- Util::Time.decimal_hour_to_time(date, utc)
68
+ Util::Time.decimal_hour_to_time(date, 0, utc)
69
69
  end
70
70
 
71
71
  def to_lst(longitude:)
@@ -29,6 +29,28 @@ module Astronoby
29
29
  "Only 3 or 5 terms are supported for interpolation"
30
30
  end
31
31
 
32
+ # Fixes angles forced to be in range [0, 360] or other angle range, for
33
+ # interpolation use
34
+ # @param angles [Array<Integer|Float>] Angles values
35
+ # @param full_circle [Integer] Full circle value
36
+ # @return [Array<Interger|Float>] Normalized values
37
+ def normalize_angles_for_interpolation(angles, full_circle: 360)
38
+ normalized = angles.dup
39
+
40
+ (1...normalized.size).each do |i|
41
+ prev_angle = normalized[i - 1]
42
+
43
+ while normalized[i] - prev_angle > full_circle / 2
44
+ normalized[i] -= full_circle
45
+ end
46
+ while normalized[i] - prev_angle < -full_circle / 2
47
+ normalized[i] += full_circle
48
+ end
49
+ end
50
+
51
+ normalized
52
+ end
53
+
32
54
  private
33
55
 
34
56
  # @return [Float] Interpolated value
@@ -6,7 +6,7 @@ module Astronoby
6
6
  # @param date [Date]
7
7
  # @param decimal [Numeric] Hour of the day, in decimal hours
8
8
  # @return [::Time] Date and time
9
- def self.decimal_hour_to_time(date, decimal)
9
+ def self.decimal_hour_to_time(date, utc_offset, decimal)
10
10
  absolute_hour = decimal.abs
11
11
  hour = absolute_hour.floor
12
12
 
@@ -25,6 +25,17 @@ module Astronoby
25
25
  second = Constants::SECONDS_PER_MINUTE *
26
26
  (absolute_decimal_minute - absolute_decimal_minute.floor)
27
27
 
28
+ date_in_local_time = ::Time
29
+ .utc(date.year, date.month, date.day, hour, minute, second)
30
+ .getlocal(utc_offset)
31
+ .to_date
32
+
33
+ if date_in_local_time < date
34
+ date = date.next_day
35
+ elsif date_in_local_time > date
36
+ date = date.prev_day
37
+ end
38
+
28
39
  ::Time.utc(date.year, date.month, date.day, hour, minute, second).round
29
40
  end
30
41
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Astronoby
4
- VERSION = "0.5.0"
4
+ VERSION = "0.6.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: astronoby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rémy Hannequin
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-06-11 00:00:00.000000000 Z
11
+ date: 2024-12-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: matrix
@@ -31,7 +31,7 @@ dependencies:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
33
  version: '13.0'
34
- type: :runtime
34
+ type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
@@ -45,13 +45,27 @@ dependencies:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
47
  version: '3.0'
48
- type: :runtime
48
+ type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rubyzip
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '2.3'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '2.3'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: standard
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -86,6 +100,10 @@ files:
86
100
  - README.md
87
101
  - Rakefile
88
102
  - UPGRADING.md
103
+ - benchmark/README.md
104
+ - benchmark/benchmark.rb
105
+ - benchmark/data/imcce.csv.zip
106
+ - benchmark/data/sun_calc.csv.zip
89
107
  - lib/astronoby.rb
90
108
  - lib/astronoby/aberration.rb
91
109
  - lib/astronoby/angle.rb