zakuro 0.2.0 → 0.3.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.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/lib/zakuro/calculation/cycle/abstract_remainder.rb +33 -20
  3. data/lib/zakuro/calculation/stella/lunar/abstract_location.rb +9 -7
  4. data/lib/zakuro/calculation/stella/lunar/choukei_value.rb +19 -0
  5. data/lib/zakuro/era/japan/reki.rb +1 -1
  6. data/lib/zakuro/version.rb +1 -1
  7. data/lib/zakuro/version/context.rb +1 -1
  8. data/lib/zakuro/version/daien/const/number.rb +55 -0
  9. data/lib/zakuro/version/daien/const/remainder.rb +53 -0
  10. data/lib/zakuro/version/daien/cycle/remainder.rb +59 -0
  11. data/lib/zakuro/version/daien/cycle/solar_term.rb +34 -0
  12. data/lib/zakuro/version/daien/daien.rb +36 -0
  13. data/lib/zakuro/version/daien/monthly/lunar_phase.rb +106 -0
  14. data/lib/zakuro/version/daien/range/annual_range.rb +39 -0
  15. data/lib/zakuro/version/daien/stella/lunar/adjustment.rb +240 -0
  16. data/lib/zakuro/version/daien/stella/lunar/localization.rb +44 -0
  17. data/lib/zakuro/version/daien/stella/lunar/location.rb +80 -0
  18. data/lib/zakuro/version/daien/stella/lunar/value.rb +75 -0
  19. data/lib/zakuro/version/daien/stella/origin/average_november.rb +34 -0
  20. data/lib/zakuro/version/daien/stella/origin/lunar_age.rb +62 -0
  21. data/lib/zakuro/version/daien/stella/origin/winter_solstice.rb +55 -0
  22. data/lib/zakuro/version/daien/stella/solar/adjustment.rb +93 -0
  23. data/lib/zakuro/version/daien/stella/solar/average.rb +98 -0
  24. data/lib/zakuro/version/daien/stella/solar/interval.rb +108 -0
  25. data/lib/zakuro/version/daien/stella/solar/location.rb +61 -0
  26. data/lib/zakuro/version/daien/stella/solar/value.rb +36 -0
  27. data/lib/zakuro/version/gihou/const/remainder.rb +0 -2
  28. data/lib/zakuro/version/gihou/cycle/remainder.rb +1 -6
  29. data/lib/zakuro/version/gihou/monthly/lunar_phase.rb +1 -1
  30. data/lib/zakuro/version/gihou/stella/lunar/location.rb +2 -8
  31. data/lib/zakuro/version/gihou/stella/lunar/value.rb +3 -2
  32. data/lib/zakuro/version/gihou/stella/solar/average.rb +1 -1
  33. data/lib/zakuro/version/senmyou/const/remainder.rb +0 -2
  34. data/lib/zakuro/version/senmyou/cycle/remainder.rb +1 -6
  35. data/lib/zakuro/version/senmyou/monthly/lunar_phase.rb +1 -1
  36. data/lib/zakuro/version/senmyou/stella/lunar/location.rb +2 -8
  37. data/lib/zakuro/version/senmyou/stella/lunar/value.rb +3 -2
  38. data/lib/zakuro/version/senmyou/stella/solar/average.rb +1 -1
  39. data/lib/zakuro/version/version_class_resolver.rb +4 -0
  40. data/lib/zakuro/version_factory.rb +1 -1
  41. metadata +25 -7
  42. data/lib/zakuro/version/taien/taien.rb +0 -19
@@ -0,0 +1,106 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../../calculation/monthly/abstract_lunar_phase'
4
+
5
+ require_relative '../const/remainder'
6
+
7
+ require_relative '../stella/solar/location'
8
+ require_relative '../stella/solar/value'
9
+ require_relative '../stella/lunar/location'
10
+ require_relative '../stella/lunar/value'
11
+
12
+ require_relative '../stella/origin/lunar_age'
13
+ require_relative '../stella/origin/average_november'
14
+
15
+ # :nodoc:
16
+ module Zakuro
17
+ # :nodoc:
18
+ module Daien
19
+ # :nodoc:
20
+ module Monthly
21
+ #
22
+ # LunarPhase 月の位相
23
+ #
24
+ class LunarPhase < Calculation::Monthly::AbstractLunarPhase
25
+ # @return [Cycle::Remainder] 弦
26
+ QUARTER = Const::Remainder::Solar::QUARTER
27
+
28
+ #
29
+ # 初期化
30
+ #
31
+ # @param [Integer] western_year 西暦年
32
+ #
33
+ def initialize(western_year:)
34
+ # 天正閏余
35
+ lunar_age = Origin::LunarAge.get(western_year: western_year)
36
+
37
+ super(
38
+ quater: QUARTER,
39
+ average_remainder: Origin::AverageNovember.get(western_year: western_year),
40
+ solar_location: Solar::Location.new(lunar_age: lunar_age),
41
+ lunar_location: Lunar::Location.new(
42
+ western_year: western_year,
43
+ lunar_age: Cycle::LunarRemainder.new(total: 0).add!(lunar_age)
44
+ )
45
+ )
46
+ end
47
+
48
+ private
49
+
50
+ # :reek:TooManyStatements { max_statements: 6 }
51
+
52
+ #
53
+ # 現在の定朔を取得する
54
+ #
55
+ # @return [Remainder] 定朔
56
+ #
57
+ def current_remainder
58
+ # debug("@average_remainder.format: #{@average_remainder.format(form: '%d-%d-%.5f')}")
59
+
60
+ sum = correction_value
61
+ adjusted = @average_remainder.add(
62
+ Cycle::Remainder.new(day: 0, minute: sum, second: 0)
63
+ )
64
+ # TODO: 大衍暦では進朔するか
65
+ # adjusted.up_on_new_moon!
66
+
67
+ debug("result: #{adjusted.format}")
68
+
69
+ adjusted
70
+ end
71
+
72
+ #
73
+ # 太陽運動の補正値を得る
74
+ #
75
+ # @return [Integer] 太陽運動の補正値
76
+ #
77
+ def correction_solar_value
78
+ @solar_location.run
79
+ # debug("@solar_term.remainder: #{@solar_location.remainder.format(form: '%d-%d-%.5f')}")
80
+ # debug("@solar_term.index: #{@solar_location.index}")
81
+
82
+ Solar::Value.get(solar_location: @solar_location)
83
+ end
84
+
85
+ # :reek:TooManyStatements { max_statements: 6 }
86
+
87
+ #
88
+ # 月運動の補正値を得る
89
+ #
90
+ # @return [Integer] 月運動の補正値
91
+ #
92
+ def correction_moon_value
93
+ @lunar_location.run
94
+
95
+ remainder = @lunar_location.adjusted_remainder
96
+
97
+ # debug("[lunar]remainder.format: #{remainder.format(form: '%d-%d-%.5f')}")
98
+ # debug("[lunar]remainder.day: #{remainder.day}")
99
+ # debug("[lunar]remainder.minute: #{remainder.minute}")
100
+
101
+ Lunar::Value.get(remainder: remainder)
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../../calculation/range/medieval_annual_range'
4
+ require_relative '../monthly/lunar_phase'
5
+ require_relative '../stella/solar/average'
6
+
7
+ # :nodoc:
8
+ module Zakuro
9
+ # :nodoc:
10
+ module Daien
11
+ # :nodoc:
12
+ module Range
13
+ #
14
+ # AnnualRange 年間範囲
15
+ #
16
+ module AnnualRange
17
+ #
18
+ # 一覧取得する
19
+ #
20
+ # * 対象年に対して、前年11月-当年11月までを出力する
21
+ # * 対象年(西暦)と計算年(元号x年)の紐付けは行わない
22
+ #
23
+ # @param [Context] context 暦コンテキスト
24
+ # @param [Integer] western_year 西暦年
25
+ #
26
+ # @return [Array<Month>] 1年データ
27
+ #
28
+ def self.get(context:, western_year:)
29
+ lunar_phase = Monthly::LunarPhase.new(western_year: western_year)
30
+ solar_average = Solar::Average.new(western_year: western_year)
31
+
32
+ Calculation::Range::MedievalAnnualRange.get(
33
+ context: context, lunar_phase: lunar_phase, solar_average: solar_average
34
+ )
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,240 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../const/number'
4
+
5
+ # :nodoc:
6
+ module Zakuro
7
+ # :nodoc:
8
+ module Daien
9
+ # :nodoc:
10
+ module Lunar
11
+ #
12
+ # Adjustment 補正値情報
13
+ #
14
+ module Adjustment
15
+ # 『歴代天文律暦等志彙編 七』中華書房 p.2230
16
+ #
17
+ # 遠/近の地点での中間
18
+ #
19
+ # @return [Hash<Integer>] 遠/近の地点での中間
20
+ DAY_LIMIT = {
21
+ 7 => 2701,
22
+ 14 => 2363,
23
+ 21 => 2024,
24
+ 28 => 1686
25
+ }.freeze
26
+
27
+ #
28
+ # Row 行情報
29
+ #
30
+ class Row
31
+ # @return [Integer] 入暦(1-14)
32
+ attr_reader :day
33
+ # @return [Range] 小余範囲
34
+ attr_reader :range
35
+ # @return [Value] 補正値
36
+ attr_reader :value
37
+
38
+ #
39
+ # 初期化
40
+ #
41
+ # @param [Integer] day 入暦(1-14)
42
+ # @param [Range] range 小余範囲
43
+ # @param [Value] value 補正値
44
+ #
45
+ def initialize(day:, range:, value:)
46
+ @day = day
47
+ @range = range
48
+ @value = value
49
+ end
50
+
51
+ # :reek:ControlParameter
52
+
53
+ #
54
+ # 一致するか
55
+ #
56
+ # @param [Integer] day 入暦(1-14)
57
+ # @param [Integer] minute 小余
58
+ #
59
+ # @return [True] 一致
60
+ # @return [False] 不一致
61
+ #
62
+ def match?(day:, minute:)
63
+ return false unless @day == day
64
+
65
+ return false unless @range.include?(minute: minute)
66
+
67
+ true
68
+ end
69
+
70
+ #
71
+ # 分母を返す
72
+ #
73
+ # @return [Integer] 分母
74
+ #
75
+ def denominator
76
+ @range.denominator
77
+ end
78
+ end
79
+
80
+ #
81
+ # Range 小余範囲
82
+ #
83
+ class Range
84
+ # @return [Integer] 下限
85
+ MIN = 0
86
+ # @return [Integer] 上限
87
+ MAX = Const::Number::Cycle::DAY
88
+
89
+ # @return [Integer] 下限
90
+ attr_reader :min
91
+ # @return [Integer] 上限
92
+ attr_reader :max
93
+
94
+ #
95
+ # 初期化
96
+ #
97
+ # @param [Integer] min 下限
98
+ # @param [Integer] max 上限
99
+ #
100
+ def initialize(min: MIN, max: MAX)
101
+ @min = min
102
+ @max = max
103
+ end
104
+
105
+ #
106
+ # 含まれるか
107
+ #
108
+ # @param [Integer] minute 小余
109
+ #
110
+ # @return [True] 含まれる
111
+ # @return [False] 含まれない
112
+ #
113
+ def include?(minute:)
114
+ minute >= @min && minute <= @max
115
+ end
116
+
117
+ #
118
+ # 分母を返す
119
+ #
120
+ # @return [Integer] 分母
121
+ #
122
+ def denominator
123
+ @max - @min
124
+ end
125
+ end
126
+
127
+ #
128
+ # Value 補正値
129
+ #
130
+ class Value
131
+ # @return [Integer] 増減率
132
+ attr_reader :per
133
+ # @return [Integer] 遅速積
134
+ attr_reader :stack
135
+
136
+ #
137
+ # 初期化
138
+ #
139
+ # @param [Integer] per 増減率
140
+ # @param [Integer] stack 遅速積
141
+ #
142
+ def initialize(per:, stack:)
143
+ @per = per
144
+ @stack = stack
145
+ end
146
+
147
+ #
148
+ # 文字化
149
+ #
150
+ # @return [String] 文字
151
+ #
152
+ def to_s
153
+ "per:#{@per}, stack:#{@stack}"
154
+ end
155
+ end
156
+
157
+ # rubocop:disable Layout/LineLength
158
+
159
+ # 『歴代天文律暦等志彙編 七』中華書房 p.2228-2230
160
+ #
161
+ # @note 7日、14日、21日、28日の小余は DAY_LIMIT を参照のこと
162
+ #
163
+ # @return [Array<Row>] 月の補正値情報
164
+ #
165
+ LIST = [
166
+ Row.new(day: 1, range: Range.new, value: Value.new(per: +297, stack: 0)),
167
+ Row.new(day: 2, range: Range.new, value: Value.new(per: +259, stack: +297)),
168
+ Row.new(day: 3, range: Range.new, value: Value.new(per: +220, stack: +556)),
169
+ Row.new(day: 4, range: Range.new, value: Value.new(per: +180, stack: +776)),
170
+ Row.new(day: 5, range: Range.new, value: Value.new(per: +139, stack: +956)),
171
+ Row.new(day: 6, range: Range.new, value: Value.new(per: +97, stack: +1095)),
172
+ Row.new(day: 7, range: Range.new(max: DAY_LIMIT[7]), value: Value.new(per: +48, stack: +1192)),
173
+ Row.new(day: 7, range: Range.new(min: DAY_LIMIT[7]), value: Value.new(per: -6, stack: +1240)), # stack: +1192 + 48
174
+ Row.new(day: 8, range: Range.new, value: Value.new(per: -64, stack: +1234)),
175
+ Row.new(day: 9, range: Range.new, value: Value.new(per: -106, stack: +1170)),
176
+ Row.new(day: 10, range: Range.new, value: Value.new(per: -148, stack: +1064)),
177
+ Row.new(day: 11, range: Range.new, value: Value.new(per: -189, stack: +916)),
178
+ Row.new(day: 12, range: Range.new, value: Value.new(per: -229, stack: +727)),
179
+ Row.new(day: 13, range: Range.new, value: Value.new(per: -267, stack: +498)),
180
+ Row.new(day: 14, range: Range.new(max: DAY_LIMIT[14]), value: Value.new(per: -231, stack: +231)),
181
+ Row.new(day: 14, range: Range.new(min: DAY_LIMIT[14]), value: Value.new(per: -66, stack: 0)), # stack: +232 - 231
182
+ Row.new(day: 15, range: Range.new, value: Value.new(per: -289, stack: -66)),
183
+ Row.new(day: 16, range: Range.new, value: Value.new(per: -250, stack: -355)),
184
+ Row.new(day: 17, range: Range.new, value: Value.new(per: -211, stack: -605)),
185
+ Row.new(day: 18, range: Range.new, value: Value.new(per: -171, stack: -816)),
186
+ Row.new(day: 19, range: Range.new, value: Value.new(per: -130, stack: -987)),
187
+ Row.new(day: 20, range: Range.new, value: Value.new(per: -87, stack: -1117)),
188
+ Row.new(day: 21, range: Range.new(max: DAY_LIMIT[21]), value: Value.new(per: -36, stack: -1204)),
189
+ Row.new(day: 21, range: Range.new(min: DAY_LIMIT[21]), value: Value.new(per: +18, stack: -1240)), # stack: -1204 - 36
190
+ Row.new(day: 22, range: Range.new, value: Value.new(per: +73, stack: -1222)),
191
+ Row.new(day: 23, range: Range.new, value: Value.new(per: +116, stack: -1149)),
192
+ Row.new(day: 24, range: Range.new, value: Value.new(per: +157, stack: -1033)),
193
+ Row.new(day: 25, range: Range.new, value: Value.new(per: +198, stack: -876)),
194
+ Row.new(day: 26, range: Range.new, value: Value.new(per: +237, stack: -678)),
195
+ Row.new(day: 27, range: Range.new, value: Value.new(per: +276, stack: -441)),
196
+ Row.new(day: 28, range: Range.new(max: DAY_LIMIT[28]), value: Value.new(per: +165, stack: -165))
197
+ ].freeze
198
+ # rubocop:enable Layout/LineLength
199
+
200
+ #
201
+ # 月軌道の補正に必要な基本値を引き当てる
202
+ #
203
+ # @param [True, False] forward 進(遠地点より数える)/退(近地点より数える)
204
+ # @param [Integer] day 大余
205
+ # @param [Integer] minute 小余
206
+ #
207
+ # @return [Row] 補正値
208
+ #
209
+ def self.specify(day:, minute:)
210
+ LIST.each do |row|
211
+ # NOTE: 範囲が重複している場合、最初に引き当てたほうを優先する
212
+ return row if row.match?(day: day, minute: minute)
213
+ end
214
+
215
+ raise ArgumentError.new, "invalid parameter: #{day}/#{minute}"
216
+ end
217
+
218
+ # :reek:ControlParameter
219
+
220
+ #
221
+ # 小余の下げ幅を求める
222
+ #
223
+ # @param [Integer] day 大余
224
+ # @param [Integer] minute 小余
225
+ #
226
+ # @return [Integer] 小余の下げ幅
227
+ #
228
+ def self.minus_minute(day:, minute:)
229
+ limit = DAY_LIMIT.fetch(day, -1)
230
+ # 該当なし
231
+ return minute if limit == -1
232
+
233
+ return minute unless minute > limit
234
+
235
+ minute - limit
236
+ end
237
+ end
238
+ end
239
+ end
240
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../const/number'
4
+
5
+ # :nodoc:
6
+ module Zakuro
7
+ # :nodoc:
8
+ module Daien
9
+ # :nodoc:
10
+ module Lunar
11
+ #
12
+ # Localization 入暦特定
13
+ #
14
+ module Localization
15
+ # @return [Integer] 1近点月
16
+ ANOMALISTIC_MONTH = Const::Number::Cycle::ANOMALISTIC_MONTH
17
+ # @return [Integer] 積年
18
+ TOTAL_YEAR = Const::Number::Stack::TOTAL_YEAR
19
+ # @return [Integer] 開始年
20
+ BEGIN_YEAR = Const::Number::Stack::BEGIN_YEAR
21
+ # @return [Integer] 年
22
+ YEAR = Const::Number::Cycle::YEAR
23
+
24
+ #
25
+ # 対象年の最初の入暦を求める
26
+ #
27
+ # @param [Remainder] lunar_age 天正閏余
28
+ # @param [Integer] western_year 西暦年
29
+ #
30
+ # @return [Cycle::LunarRemainder] 入暦
31
+ #
32
+ def self.first_remainder(lunar_age:, western_year:)
33
+ # 積年の開始から対象年までの年数
34
+ total_year = TOTAL_YEAR + western_year - BEGIN_YEAR
35
+
36
+ # 通積分 - 天正閏余
37
+ total_day = total_year * YEAR - lunar_age.to_minute
38
+
39
+ Cycle::LunarRemainder.new(total: (total_day % ANOMALISTIC_MONTH))
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../../../calculation/stella/lunar/abstract_location'
4
+
5
+ require_relative '../../const/remainder'
6
+
7
+ require_relative './localization'
8
+
9
+ # :nodoc:
10
+ module Zakuro
11
+ # :nodoc:
12
+ module Daien
13
+ # :nodoc:
14
+ module Lunar
15
+ #
16
+ # Location 入暦
17
+ #
18
+ class Location < Calculation::Lunar::AbstractLocation
19
+ # @return [Cycle::LunarRemainder] 1近点月
20
+ ANOMALISTIC_MONTH = Const::Remainder::Lunar::ANOMALISTIC_MONTH
21
+ # @return [Cycle::LunarRemainder] 弦
22
+ QUARTER = Const::Remainder::Lunar::QUARTER
23
+
24
+ #
25
+ # 初期化
26
+ #
27
+ # @param [Cycle::LunarRemainder] lunar_age 天正閏余(大余小余)
28
+ # @param [Integer] western_year 西暦年
29
+ #
30
+ def initialize(lunar_age:, western_year:)
31
+ super(lunar_age: lunar_age, western_year: western_year)
32
+ end
33
+
34
+ #
35
+ # 入暦を計算する
36
+ #
37
+ def run
38
+ if calculated
39
+ decrease(limit: ANOMALISTIC_MONTH)
40
+ return
41
+ end
42
+
43
+ first
44
+ end
45
+
46
+ #
47
+ # 弦の分だけ月地点を進める
48
+ #
49
+ def add_quarter
50
+ remainder.add!(QUARTER)
51
+ end
52
+
53
+ private
54
+
55
+ #
56
+ # 初回計算
57
+ #
58
+ def first
59
+ @remainder = Localization.first_remainder(
60
+ lunar_age: remainder, western_year: western_year
61
+ )
62
+ decrease(limit: ANOMALISTIC_MONTH)
63
+
64
+ @calculated = true
65
+ end
66
+
67
+ #
68
+ # 大余小余に合わせて減算する(折り返す)
69
+ #
70
+ # @param [Cycle::LunarRemainder] limit 上限
71
+ #
72
+ def decrease(limit:)
73
+ return if remainder < limit
74
+
75
+ remainder.sub!(limit)
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end