zakuro 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. checksums.yaml +4 -4
  2. data/lib/zakuro/calculation/base/multi_gengou.rb +101 -0
  3. data/lib/zakuro/calculation/base/multi_gengou_roller.rb +218 -0
  4. data/lib/zakuro/calculation/base/year.rb +107 -0
  5. data/lib/zakuro/calculation/cycle/abstract_remainder.rb +471 -0
  6. data/lib/zakuro/calculation/cycle/abstract_solar_term.rb +173 -0
  7. data/lib/zakuro/calculation/cycle/zodiac.rb +106 -0
  8. data/lib/zakuro/calculation/monthly/abstract_lunar_phase.rb +169 -0
  9. data/lib/zakuro/calculation/monthly/first_day.rb +45 -0
  10. data/lib/zakuro/calculation/monthly/initialized_month.rb +125 -0
  11. data/lib/zakuro/calculation/monthly/month.rb +187 -0
  12. data/lib/zakuro/calculation/monthly/month_label.rb +88 -0
  13. data/lib/zakuro/calculation/monthly/operated_month.rb +209 -0
  14. data/lib/zakuro/calculation/range/full_range.rb +210 -0
  15. data/lib/zakuro/calculation/range/medieval_annual_range.rb +105 -0
  16. data/lib/zakuro/calculation/range/operated_range.rb +144 -0
  17. data/lib/zakuro/calculation/range/operated_solar_terms.rb +201 -0
  18. data/lib/zakuro/calculation/range/transfer/western_date_allocation.rb +82 -0
  19. data/lib/zakuro/calculation/range/transfer/year_boundary.rb +146 -0
  20. data/lib/zakuro/calculation/specifier/single_day.rb +109 -0
  21. data/lib/zakuro/calculation/stella/lunar/abstract_location.rb +76 -0
  22. data/lib/zakuro/calculation/stella/lunar/choukei_value.rb +52 -0
  23. data/lib/zakuro/calculation/stella/solar/abstract_average.rb +117 -0
  24. data/lib/zakuro/calculation/stella/solar/abstract_location.rb +187 -0
  25. data/lib/zakuro/calculation/stella/solar/choukei_value.rb +136 -0
  26. data/lib/zakuro/calculation/summary/single.rb +129 -0
  27. data/lib/zakuro/calculation/type/old_float.rb +69 -0
  28. data/lib/zakuro/merchant.rb +2 -2
  29. data/lib/zakuro/operation/month/parser.rb +1 -1
  30. data/lib/zakuro/operation/month/type.rb +5 -10
  31. data/lib/zakuro/output/error.rb +7 -6
  32. data/lib/zakuro/output/logger.rb +50 -49
  33. data/lib/zakuro/output/response.rb +145 -144
  34. data/lib/zakuro/tools/typeof.rb +2 -2
  35. data/lib/zakuro/version.rb +1 -1
  36. data/lib/zakuro/version/abstract_version.rb +1 -1
  37. data/lib/zakuro/version/context.rb +23 -0
  38. data/lib/zakuro/version/gihou/const/number.rb +55 -0
  39. data/lib/zakuro/version/gihou/const/remainder.rb +56 -0
  40. data/lib/zakuro/version/gihou/cycle/remainder.rb +61 -0
  41. data/lib/zakuro/version/gihou/cycle/solar_term.rb +34 -0
  42. data/lib/zakuro/version/gihou/gihou.rb +23 -2
  43. data/lib/zakuro/version/gihou/monthly/lunar_phase.rb +106 -0
  44. data/lib/zakuro/version/gihou/range/annual_range.rb +39 -0
  45. data/lib/zakuro/version/gihou/stella/lunar/adjustment.rb +250 -0
  46. data/lib/zakuro/version/gihou/stella/lunar/localization.rb +44 -0
  47. data/lib/zakuro/version/gihou/stella/lunar/location.rb +86 -0
  48. data/lib/zakuro/version/gihou/stella/lunar/value.rb +74 -0
  49. data/lib/zakuro/version/gihou/stella/origin/average_november.rb +34 -0
  50. data/lib/zakuro/version/gihou/stella/origin/lunar_age.rb +62 -0
  51. data/lib/zakuro/version/gihou/stella/origin/winter_solstice.rb +55 -0
  52. data/lib/zakuro/version/gihou/stella/solar/adjustment.rb +93 -0
  53. data/lib/zakuro/version/gihou/stella/solar/average.rb +97 -0
  54. data/lib/zakuro/version/gihou/stella/solar/interval.rb +108 -0
  55. data/lib/zakuro/version/gihou/stella/solar/location.rb +61 -0
  56. data/lib/zakuro/version/gihou/stella/solar/value.rb +36 -0
  57. data/lib/zakuro/version/senmyou/const/number.rb +51 -0
  58. data/lib/zakuro/version/senmyou/const/remainder.rb +49 -0
  59. data/lib/zakuro/version/senmyou/cycle/remainder.rb +61 -0
  60. data/lib/zakuro/version/senmyou/cycle/solar_term.rb +34 -0
  61. data/lib/zakuro/version/senmyou/monthly/lunar_phase.rb +80 -195
  62. data/lib/zakuro/version/senmyou/range/annual_range.rb +25 -170
  63. data/lib/zakuro/version/senmyou/senmyou.rb +10 -4
  64. data/lib/zakuro/version/senmyou/stella/lunar/adjustment.rb +237 -0
  65. data/lib/zakuro/version/senmyou/stella/lunar/localization.rb +44 -0
  66. data/lib/zakuro/version/senmyou/stella/lunar/location.rb +93 -0
  67. data/lib/zakuro/version/senmyou/stella/lunar/value.rb +66 -0
  68. data/lib/zakuro/version/senmyou/stella/origin/average_november.rb +34 -0
  69. data/lib/zakuro/version/senmyou/stella/origin/lunar_age.rb +62 -0
  70. data/lib/zakuro/version/senmyou/stella/origin/winter_solstice.rb +55 -0
  71. data/lib/zakuro/version/senmyou/stella/solar/adjustment.rb +93 -0
  72. data/lib/zakuro/version/senmyou/stella/solar/average.rb +97 -0
  73. data/lib/zakuro/version/senmyou/stella/solar/interval.rb +103 -0
  74. data/lib/zakuro/version/senmyou/stella/solar/location.rb +61 -0
  75. data/lib/zakuro/version/senmyou/stella/solar/value.rb +39 -0
  76. data/lib/zakuro/version/version_class_resolver.rb +66 -0
  77. data/lib/zakuro/version_factory.rb +2 -2
  78. metadata +64 -24
  79. data/lib/zakuro/cycle/abstract_remainder.rb +0 -456
  80. data/lib/zakuro/cycle/zodiac.rb +0 -103
  81. data/lib/zakuro/version/senmyou/base/era.rb +0 -83
  82. data/lib/zakuro/version/senmyou/base/multi_gengou.rb +0 -98
  83. data/lib/zakuro/version/senmyou/base/multi_gengou_roller.rb +0 -217
  84. data/lib/zakuro/version/senmyou/base/remainder.rb +0 -60
  85. data/lib/zakuro/version/senmyou/base/solar_term.rb +0 -86
  86. data/lib/zakuro/version/senmyou/base/year.rb +0 -104
  87. data/lib/zakuro/version/senmyou/monthly/first_day.rb +0 -44
  88. data/lib/zakuro/version/senmyou/monthly/initialized_month.rb +0 -48
  89. data/lib/zakuro/version/senmyou/monthly/month.rb +0 -181
  90. data/lib/zakuro/version/senmyou/monthly/month_label.rb +0 -87
  91. data/lib/zakuro/version/senmyou/monthly/operated_month.rb +0 -167
  92. data/lib/zakuro/version/senmyou/range/full_range.rb +0 -324
  93. data/lib/zakuro/version/senmyou/range/operated_range.rb +0 -126
  94. data/lib/zakuro/version/senmyou/range/operated_solar_terms.rb +0 -181
  95. data/lib/zakuro/version/senmyou/specifier/single_day_specifier.rb +0 -102
  96. data/lib/zakuro/version/senmyou/stella/lunar_orbit.rb +0 -332
  97. data/lib/zakuro/version/senmyou/stella/solar_average.rb +0 -214
  98. data/lib/zakuro/version/senmyou/stella/solar_orbit.rb +0 -394
  99. data/lib/zakuro/version/senmyou/stella/winter_solstice.rb +0 -106
  100. data/lib/zakuro/version/senmyou/summary/single.rb +0 -125
@@ -1,214 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # :nodoc:
4
- module Zakuro
5
- # :nodoc:
6
- module Senmyou
7
- #
8
- # SolarAverage 常気(太陽軌道平均)
9
- #
10
- module SolarAverage
11
- # @return [Remainder] 気策(24分の1年)
12
- SOLAR_TERM_AVERAGE = Remainder.new(day: 15, minute: 1835, second: 5)
13
-
14
- # :reek:TooManyStatements { max_statements: 6 }
15
-
16
- #
17
- # 冬至から数えた1年データの月ごとに二十四節気を割り当てる
18
- #
19
- # @param [Integer] western_year 西暦年
20
- # @param [Array<Month>] annual_range 1年データ
21
- #
22
- # @return [Array<Month>] 1年データ
23
- #
24
- def self.set_solar_terms_into_annual_range(western_year:, annual_range:)
25
- # 天正冬至
26
- winter_solstice = WinterSolstice.calc(western_year: western_year)
27
-
28
- # 前年冬至からの二十四節気
29
- solar_terms = collect_solar_terms_from_last_winter_solstice(
30
- winter_solstice: winter_solstice
31
- )
32
-
33
- apply_solar_terms_from_last_winter_solstice(annual_range: annual_range,
34
- solar_terms: solar_terms)
35
-
36
- # 前後の二十四節気
37
- rest_solar_terms = \
38
- collect_solar_terms_before_and_after(solar_terms: solar_terms)
39
-
40
- apply_solar_terms_before_and_after(annual_range: annual_range,
41
- rest_solar_terms: rest_solar_terms)
42
-
43
- annual_range
44
- end
45
-
46
- # :reek:TooManyStatements { max_statements: 6 }
47
-
48
- #
49
- # 前年冬至から当年大雪までの二十四節気を計算する
50
- #
51
- # @param [Remainder] winter_solstice 冬至
52
- #
53
- # @return [Array<Remainder>] 二十四節気
54
- #
55
- def self.collect_solar_terms_from_last_winter_solstice(winter_solstice:)
56
- result = []
57
- term = winter_solstice
58
- (0...24).each do |_i|
59
- result.push(term)
60
- term = term.add(SOLAR_TERM_AVERAGE)
61
- end
62
-
63
- result
64
- end
65
- private_class_method :collect_solar_terms_from_last_winter_solstice
66
-
67
- # :reek:TooManyStatements { max_statements: 9 }
68
-
69
- #
70
- # 各月の二十四節気を設定する
71
- #
72
- # @param [Array<Month>] annual_range 1年データ
73
- # @param [Array<Remainder>] solar_terms 1年データ内の全二十四節気
74
- #
75
- def self.apply_solar_terms_from_last_winter_solstice(annual_range:, solar_terms:)
76
- month_index = 0
77
- solar_term_index = 0
78
- month_size = annual_range.size
79
-
80
- while month_index < month_size && solar_term_index < solar_terms.size
81
- raise StandardError, "month is over. idx: #{month_index}" if month_index >= month_size
82
-
83
- if set_solar_term_on_current_month(current_month: annual_range[month_index],
84
- next_month: annual_range[month_index + 1],
85
- solar_term: solar_terms[solar_term_index],
86
- solar_term_index: solar_term_index)
87
- solar_term_index += 1
88
- next
89
- end
90
-
91
- month_index += 1
92
- end
93
- end
94
- private_class_method :apply_solar_terms_from_last_winter_solstice
95
-
96
- #
97
- # 当月に二十四節気を設定する
98
- #
99
- # @param [Remainder] current_month 当月
100
- # @param [Month] next_month 次月
101
- # @param [Month] solar_term 二十四節気
102
- # @param [Integer] solar_term_index 二十四節気位置
103
- #
104
- # @return [True] 設定済
105
- # @return [False] 未設定
106
- #
107
- def self.set_solar_term_on_current_month(current_month:,
108
- next_month:, solar_term:, solar_term_index:)
109
- if in_range_solar_term?(target: solar_term, min: current_month.remainder,
110
- max: next_month.remainder)
111
- set_solar_term(month: current_month,
112
- solar_term: solar_term, solar_term_index: solar_term_index)
113
- return true
114
- end
115
-
116
- # 一度も割り当てがない場合は設定済みとして次の二十四節気を進める
117
- return true if current_month.empty_solar_term?
118
-
119
- false
120
- end
121
-
122
- #
123
- # 1年データ内の二十四節気の前後を収集する
124
- #
125
- # @param [Array<Remainder>] solar_terms 1年データ内の全二十四節気
126
- #
127
- # @return [Hash<Integer, Hash<Symbol, Integer>>, Hash<Integer, Hash<Symbol, Remainder>>] 前後
128
- #
129
- def self.collect_solar_terms_before_and_after(solar_terms:)
130
- raise ArgumentError, 'parameter must be 24 solar terms' unless solar_terms.size == 24
131
-
132
- touji = solar_terms[-1].add(SOLAR_TERM_AVERAGE)
133
- {
134
- # 前年大雪
135
- 23 => { index: 0, solar_term: solar_terms[0].sub(SOLAR_TERM_AVERAGE) },
136
- # 当年冬至
137
- 0 => { index: -2, solar_term: touji },
138
- # 当年小寒
139
- 1 => { index: -2, solar_term: touji.add(SOLAR_TERM_AVERAGE) }
140
- }
141
- end
142
- private_class_method :collect_solar_terms_before_and_after
143
-
144
- # :reek:TooManyStatements { max_statements: 6 }
145
-
146
- #
147
- # 1年データ前後の二十四節気を適用する
148
- #
149
- # @param [Array<Month>] annual_range 1年データ
150
- # @param [Hash<Integer, Hash<Symbol, Integer>>, Hash<Integer, Hash<Symbol, Remainder>>]
151
- # rest_solar_terms 前後
152
- #
153
- def self.apply_solar_terms_before_and_after(annual_range:, rest_solar_terms:)
154
- rest_solar_terms.each do |key, value|
155
- index = value[:index]
156
- solar_term = value[:solar_term]
157
- data = annual_range[index]
158
- next unless in_range_solar_term?(
159
- target: solar_term,
160
- min: data.remainder, max: annual_range[index + 1].remainder
161
- )
162
-
163
- set_solar_term(month: data,
164
- solar_term: solar_term, solar_term_index: key)
165
- end
166
- end
167
- private_class_method :apply_solar_terms_before_and_after
168
-
169
- # :reek:TooManyStatements { max_statements: 7 }
170
-
171
- #
172
- # 月内(currentからnextの間)に二十四節気があるか
173
- # @note 大余60で一巡するため 以下2パターンがある
174
- # * current(min) <= next(max) : (二十四節気) >= current && (二十四節気) < next
175
- # * current(min) > next(max) : (二十四節気) >= current || (二十四節気) < next
176
- #
177
- # @param [Remainder] target 対象の二十四節気
178
- # @param [Remainder] min 月初
179
- # @param [Remainder] max 月末
180
- #
181
- # @return [True] 対象の二十四節気がある
182
- # @return [False] 対象の二十四節気がない
183
- #
184
- def self.in_range_solar_term?(target:, min:, max:)
185
- # 大余で比較する
186
- target_time = target.day
187
- min_time = min.day
188
- max_time = max.day
189
- min_over = (target_time >= min_time)
190
- max_under = (target_time < max_time)
191
-
192
- (min_time <= max_time ? min_over && max_under : min_over || max_under)
193
- end
194
- private_class_method :in_range_solar_term?
195
-
196
- #
197
- # 二十四節気を設定する
198
- #
199
- # @param [Month] month 月
200
- # @param [Remainder] solar_term 二十四節気
201
- # @param [Integer] solar_term_index 連番(二十四節気)
202
- #
203
- def self.set_solar_term(month:, solar_term:, solar_term_index:)
204
- term = SolarTerm.new(remainder: solar_term, index: solar_term_index)
205
-
206
- # 設定する
207
- month.add_term(term: term)
208
-
209
- nil
210
- end
211
- private_class_method :set_solar_term
212
- end
213
- end
214
- end
@@ -1,394 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative '../base/solar_term'
4
-
5
- # :nodoc:
6
- module Zakuro
7
- # :nodoc:
8
- module Senmyou
9
- #
10
- # SolarOrbit 太陽軌道
11
- #
12
- module SolarOrbit
13
- # @return [Integer] 統法(1日=8400分)
14
- DAY = 8400
15
-
16
- #
17
- # Interval 入気定日加減数(二十四節気の間隔)
18
- #
19
- module Interval
20
- # @return [Hash<Symbol, Remainder>] 一覧
21
- LIST = {
22
- # 冬至(とうじ)・大雪(たいせつ)
23
- touji: Remainder.new(day: 14, minute: 4235, second: 5),
24
- taisetsu: Remainder.new(day: 14, minute: 4235, second: 5),
25
- # 小寒(しょうかん)・小雪(しょうせつ)
26
- shoukan: Remainder.new(day: 14, minute: 5235, second: 5),
27
- shousetsu: Remainder.new(day: 14, minute: 5235, second: 5),
28
- # 大寒(だいかん)・立冬(りっとう)
29
- daikan: Remainder.new(day: 14, minute: 6235, second: 5),
30
- rittou: Remainder.new(day: 14, minute: 6235, second: 5),
31
- # 立春(りっしゅん)・霜降(そうこう)
32
- risshun: Remainder.new(day: 14, minute: 7235, second: 5),
33
- soukou: Remainder.new(day: 14, minute: 7235, second: 5),
34
- # 雨水(うすい)・寒露(かんろ)
35
- usui: Remainder.new(day: 15, minute: 35, second: 5),
36
- kanro: Remainder.new(day: 15, minute: 35, second: 5),
37
- # 啓蟄(けいちつ)・秋分(しゅうぶん)
38
- keichitsu: Remainder.new(day: 15, minute: 1235, second: 5),
39
- shuubun: Remainder.new(day: 15, minute: 1235, second: 5),
40
- # 春分(しゅんぶん)・白露(はくろ)
41
- shunbun: Remainder.new(day: 15, minute: 2435, second: 5),
42
- hakuro: Remainder.new(day: 15, minute: 2435, second: 5),
43
- # 清明(せいめい)・処暑(しょしょ)
44
- seimei: Remainder.new(day: 15, minute: 3635, second: 5),
45
- shosho: Remainder.new(day: 15, minute: 3635, second: 5),
46
- # 穀雨(こくう)・立秋(りっしゅう)
47
- kokuu: Remainder.new(day: 15, minute: 4835, second: 5),
48
- risshuu: Remainder.new(day: 15, minute: 4835, second: 5),
49
- # 立夏(りっか)・大暑(たいしょ)
50
- rikka: Remainder.new(day: 15, minute: 5835, second: 5),
51
- taisho: Remainder.new(day: 15, minute: 5835, second: 5),
52
- # 小満(しょうまん)・小暑(しょうしょ)
53
- shouman: Remainder.new(day: 15, minute: 6835, second: 5),
54
- shousho: Remainder.new(day: 15, minute: 6835, second: 5),
55
- # 芒種(ぼうしゅ)・夏至(げし)
56
- boushu: Remainder.new(day: 15, minute: 7835, second: 5),
57
- geshi: Remainder.new(day: 15, minute: 7835, second: 5)
58
- }.freeze
59
-
60
- # @return [Array<Remainder>] 索引
61
- INDEXES = [
62
- LIST[:touji], # 0
63
- LIST[:shoukan], # 1
64
- LIST[:daikan], # 2
65
- LIST[:risshun], # 3
66
- LIST[:usui], # 4
67
- LIST[:keichitsu], # 5
68
- LIST[:shunbun], # 6
69
- LIST[:seimei], # 7
70
- LIST[:kokuu], # 8
71
- LIST[:rikka], # 9
72
- LIST[:shouman], # 10
73
- LIST[:boushu], # 11
74
- LIST[:geshi], # 12
75
- LIST[:shousho], # 13
76
- LIST[:taisho], # 14
77
- LIST[:risshuu], # 15
78
- LIST[:shosho], # 16
79
- LIST[:hakuro], # 17
80
- LIST[:shuubun], # 18
81
- LIST[:kanro], # 19
82
- LIST[:soukou], # 20
83
- LIST[:rittou], # 21
84
- LIST[:shousetsu], # 22
85
- LIST[:taisetsu] # 23
86
- ].freeze
87
- end
88
-
89
- #
90
- # 24気損益眺朒(ちょうじく)数
91
- #
92
- module Adjustment
93
- #
94
- # Item 24気損益眺朒(ちょうじく)数
95
- #
96
- class Item
97
- # @return [Integer] 眺朒(ちょうじく)積
98
- attr_reader :stack
99
- # @return [Integer] 眺朒(ちょうじく)数
100
- attr_reader :per_term
101
- # @return [Integer] 毎日差
102
- attr_reader :per_day
103
-
104
- #
105
- # 初期化
106
- #
107
- # @param [Integer] stack 眺朒(ちょうじく)積
108
- # @param [Integer] per_term 眺朒(ちょうじく)数
109
- # @param [Integer] per_day 毎日差
110
- #
111
- def initialize(stack:, per_term:, per_day:)
112
- @stack = stack
113
- @per_term = per_term
114
- @per_day = per_day
115
- end
116
-
117
- #
118
- # 文字化
119
- #
120
- # @return [String] 文字
121
- #
122
- def to_s
123
- "stack:#{@stack}, per_term:#{@per_term}, per_day:#{@per_day}"
124
- end
125
- end
126
-
127
- # @return [Array<Item>] 24気損益眺朒(ちょうじく)数
128
- LIST = {
129
- touji: Item.new(stack: 0.0, per_term: +33.4511, per_day: -0.3695), # 冬至(とうじ)
130
- shoukan: Item.new(stack: +449.0, per_term: +28.0389, per_day: -0.3606), # 小寒(しょうかん)
131
- daikan: Item.new(stack: +823.0, per_term: +22.6998, per_day: -0.3519), # 大寒(だいかん)
132
- risshun: Item.new(stack: +1122.0, per_term: +17.8923, per_day: -0.4068), # 立春(りっしゅん)
133
- usui: Item.new(stack: +1346.0, per_term: +11.7966, per_day: -0.3998), # 雨水(うすい)
134
- keichitsu: Item.new(stack: +1481.0, per_term: +5.7986, per_day: -0.3998), # 啓蟄(けいちつ)
135
- shunbun: Item.new(stack: +1526.0, per_term: -0.2433, per_day: -0.3779), # 春分(しゅんぶん)
136
- seimei: Item.new(stack: +1481.0, per_term: -6.1254, per_day: -0.3634), # 清明(せいめい)
137
- kokuu: Item.new(stack: +1346.0, per_term: -12.2048, per_day: -0.2987), # 穀雨(こくう)
138
- rikka: Item.new(stack: +1122.0, per_term: -16.9060, per_day: -0.2919), # 立夏(りっか)
139
- shouman: Item.new(stack: +823.0, per_term: -21.5362, per_day: -0.2854), # 小満(しょうまん)
140
- boushu: Item.new(stack: +449.0, per_term: -26.0498, per_day: -0.2854), # 芒種(ぼうしゅ)
141
- geshi: Item.new(stack: 0.0, per_term: -30.3119, per_day: +0.2854), # 夏至(げし)
142
- shousho: Item.new(stack: -449.0, per_term: -25.8126, per_day: +0.2919), # 小暑(しょうしょ)
143
- taisho: Item.new(stack: -823.0, per_term: -21.2454, per_day: +0.2987), # 大暑(たいしょ)
144
- risshuu: Item.new(stack: -1122.0, per_term: -17.0296, per_day: +0.3634), # 立秋(りっしゅう)
145
- shosho: Item.new(stack: -1346.0, per_term: -11.4744, per_day: +0.3779), # 処暑(しょしょ)
146
- hakuro: Item.new(stack: -1481.0, per_term: -5.6429, per_day: +0.3779), # 白露(はくろ)
147
- shuubun: Item.new(stack: -1526.0, per_term: +0.1432, per_day: +0.3998), # 秋分(しゅうぶん)
148
- kanro: Item.new(stack: -1481.0, per_term: +6.1488, per_day: +0.4068), # 寒露(かんろ)
149
- soukou: Item.new(stack: -1346.0, per_term: +12.6336, per_day: +0.3519), # 霜降(そうこう)
150
- rittou: Item.new(stack: -1122.0, per_term: +17.8043, per_day: +0.3606), # 立冬(りっとう)
151
- shousetsu: Item.new(stack: -823.0, per_term: +23.0590, per_day: +0.3695), # 小雪(しょうせつ)
152
- taisetsu: Item.new(stack: -449.0, per_term: +28.4618, per_day: +0.3695) # 大雪(たいせつ)
153
- }.freeze
154
- end
155
-
156
- #
157
- # 二十四節気 と 補正値 を計算する
158
- #
159
- # @param [SolarTerm] solar_term 二十四節気
160
- #
161
- # @return [SolarTerm] 二十四節気
162
- # @return [Integer] 補正値
163
- #
164
- def self.calc_term_and_orbit_value(solar_term:)
165
- remainder = calc_solar_term_by_remainder(
166
- solar_term: solar_term
167
- )
168
- value = calc_sun_orbit_value(
169
- solar_term: remainder
170
- )
171
- [remainder, value]
172
- end
173
-
174
- # :reek:ControlParameter and :reek:BooleanParameter
175
-
176
- #
177
- # 二十四節気を計算する
178
- #
179
- # @param [SolarTerm] solar_term 二十四節気
180
- #
181
- # @return [SolarTerm] 二十四節気
182
- #
183
- def self.calc_solar_term_by_remainder(solar_term:)
184
- if solar_term.index.negative?
185
- return calc_first_solar_term(
186
- winter_solstice_age: solar_term.remainder
187
- )
188
- end
189
-
190
- calc_next_solar_term_recursively(
191
- solar_term: solar_term
192
- )
193
- end
194
-
195
- # :reek:TooManyStatements { max_statements: 8 }
196
-
197
- #
198
- # 入定気(定気の開始点からの日時)と属する定気を計算する
199
- #
200
- # @param [Remainder] winter_solstice_age 天正冬至
201
- #
202
- # @return [SolarTerm] 二十四節気
203
- # SolarTerm.remainder : 入定気(定気の開始点からの日時)
204
- # SolarTerm.index : 定気
205
- #
206
- def self.calc_first_solar_term(winter_solstice_age:)
207
- # 入定気の起算方法
208
- # 概要:
209
- # * 太陽の運行による補正値は、二十四節気の気ごとに定められる
210
- # * 11月経朔の前にある気を求め、それから11月経朔との間隔を求める
211
- # * 気ごとの補正値と、気から11月経朔までにかかる補正値を求める
212
- # 前提:
213
- # * 11月経朔に関わる二十四節気は、時系列から順に、小雪・大雪・冬至である
214
- # * 小雪〜大雪の間隔は小雪定数で、大雪〜冬至の間隔は大雪定数で決められている(24気損益眺朒(ちょうじく)数のこと)
215
- # * 11月経朔は、この小雪〜冬至の間のいずれかにある
216
- # 計算:
217
- # 2パターンある
218
- # (a) 大雪〜冬至にある場合
219
- # *「大雪定数 >= 天正閏余」の場合を指す
220
- # * * NOTE 資料では「より大きい(>)」とされるが、大雪そのものの場合は大雪から起算すべき
221
- # * この場合は、大雪〜経朔の間隔を求める
222
- # (b) 小雪〜大雪にある場合
223
- # *「大雪定数 < 天正閏余」の場合を指す
224
- # * この場合は、小雪〜経朔の間隔を求める
225
- taisetsu = 23
226
- taisetsu_interval = Interval::INDEXES[taisetsu]
227
-
228
- if winter_solstice_age > taisetsu_interval
229
- # (b)
230
- shousetsu = 22
231
- diff = winter_solstice_age.sub(taisetsu_interval)
232
-
233
- return SolarTerm.new(remainder: Interval::INDEXES[shousetsu].sub(diff),
234
- index: shousetsu)
235
- end
236
- # (a)
237
- SolarTerm.new(remainder: taisetsu_interval.sub(winter_solstice_age),
238
- index: taisetsu)
239
- end
240
-
241
- # :reek:TooManyStatements { max_statements: 8 }
242
-
243
- #
244
- # 次の二十四節気を計算する
245
- #
246
- # @param [SolarTerm] solar_term 今回の二十四節気
247
- #
248
- # @return [SolarTerm] 次回の二十四節気
249
- #
250
- def self.calc_next_solar_term_recursively(solar_term:)
251
- remainder = solar_term.remainder
252
- index = solar_term.index
253
- interval = Interval::INDEXES[index]
254
- return solar_term if remainder < interval
255
-
256
- remainder.sub!(interval)
257
- index += 1
258
- index = 0 if index >= Interval::INDEXES.size
259
- calc_next_solar_term_recursively(
260
- solar_term: SolarTerm.new(remainder: remainder, index: index)
261
- )
262
- end
263
-
264
- #
265
- # 太陽の運行による補正値を算出する
266
- #
267
- # @param [SolarTerm] solar_term 二十四節気
268
- #
269
- # @return [Integer] 補正値
270
- #
271
- def self.calc_sun_orbit_value(solar_term:)
272
- remainder = solar_term.remainder
273
-
274
- adjustment = specify_solar_term_adjustment(index: solar_term.index)
275
- # 損益率/眺朒(ちょうじく)数
276
- # パラメータ:
277
- # a: 眺朒(ちょうじく)数の初日の値
278
- # b: 損益率初日の値
279
- # c: 損益率の毎日の差
280
- # n: 定気の日から数えた日数
281
-
282
- day_stack = calc_day_stack(remainder: remainder, adjustment: adjustment)
283
-
284
- month_stack = calc_month_stack(stack: adjustment.stack, day: remainder.day,
285
- per_term: adjustment.per_term, per_day:
286
- adjustment.per_day)
287
-
288
- # 冬至であれば眺朒数がプラスになり続けて損益率が「益」で、小雪であればマイナスの眺朒数がプラスされ続けて「損」
289
- month_stack + day_stack
290
- end
291
-
292
- #
293
- # 損益率を求める
294
- #
295
- # @param [Remainder] remainder 入定気
296
- # @param [Adjustment::Item] adjustment 24気損益眺朒(ちょうじく)数
297
- #
298
- # @return [Integer] 損益率
299
- #
300
- def self.calc_day_stack(remainder:, adjustment:)
301
- per_term = adjustment.per_term
302
- per_day = adjustment.per_day
303
- sign, ratio = calc_ratio(day: remainder.day, per_term: per_term, per_day: per_day)
304
-
305
- calc_day_stack_from_ratio(sign: sign, ratio: ratio,
306
- minute: remainder.minute)
307
- end
308
- private_class_method :calc_day_stack
309
-
310
- #
311
- # 24気損益眺朒(ちょうじく)数を特定する
312
- #
313
- # @param [Integer] index 連番(二十四節気)
314
- #
315
- # @return [Adjustment::Item] 24気損益眺朒(ちょうじく)数
316
- #
317
- def self.specify_solar_term_adjustment(index:)
318
- key = SolarTerm::ORDER[index]
319
- Adjustment::LIST[key].clone
320
- end
321
- private_class_method :specify_solar_term_adjustment
322
-
323
- # :reek:TooManyStatements { max_statements: 6 }
324
-
325
- #
326
- # 大余に対応する損益率を求める
327
- # 損益率 = b + n * c
328
- #
329
- # @param [Integer] day 大余
330
- # @param [Integer] per_term 眺朒(ちょうじく)数
331
- # @param [Integer] per_day 毎日差
332
- #
333
- # @return [Integer] 正負
334
- # @return [Integer] 大余に対応する損益率
335
- #
336
- def self.calc_ratio(day:, per_term:, per_day:)
337
- ratio = per_term + day * per_day
338
- sign = 1
339
- if ratio.negative?
340
- sign = -1
341
- ratio *= sign
342
- end
343
- # 小数点以下は無視する
344
- ratio = ratio.floor
345
-
346
- [sign, ratio]
347
- end
348
- private_class_method :calc_ratio
349
-
350
- #
351
- # 小余を含めた損益率を求める
352
- #
353
- # @param [Integer] sign 正負(大余に対応する損益率)
354
- # @param [Integer] ratio 大余に対応する損益率
355
- # @param [Integer] minute 小余
356
- #
357
- # @return [Integer] 小余を含めた損益率
358
- #
359
- def self.calc_day_stack_from_ratio(sign:, ratio:, minute:)
360
- minute_stack = ratio * minute
361
- day_stack = (minute_stack / DAY).floor
362
- # 四捨五入
363
- # NOTE 資料では「この余りが4200をこえていれば切り上げる」とあり「>=」とした
364
- # 1612年の7月(慶長17年7月)が境界値4200だが、繰り上げを行なっていたため
365
- day_stack += 1 if minute_stack % DAY >= (DAY / 2)
366
- day_stack *= sign
367
-
368
- day_stack
369
- end
370
- private_class_method :calc_day_stack_from_ratio
371
-
372
- # :reek:LongParameterList { max_params: 4 }
373
-
374
- #
375
- # 眺朒(ちょうじく)数を求める
376
- # 眺朒(ちょうじく)数 = a + (n * b) + (1/2)n(n-1)c
377
- #
378
- # @param [Integer] stack 眺朒(ちょうじく)積
379
- # @param [Integer] day 大余
380
- # @param [Integer] per_term 眺朒(ちょうじく)数
381
- # @param [Integer] per_day 毎日差f
382
- #
383
- # @return [Integer] 眺朒(ちょうじく)数
384
- #
385
- def self.calc_month_stack(stack:, day:, per_term:, per_day:)
386
- month_stack = stack + day * per_term + \
387
- (1 / 2.0) * (day * (day - 1) * per_day)
388
- # 切り捨て(プラスマイナスに関わらず小数点以下切り捨て)
389
- month_stack.negative? ? month_stack.ceil : month_stack.floor
390
- end
391
- private_class_method :calc_month_stack
392
- end
393
- end
394
- end