zakuro 0.1.4 → 0.1.5

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 (27) hide show
  1. checksums.yaml +4 -4
  2. data/lib/zakuro/calculation/cycle/abstract_remainder.rb +12 -0
  3. data/lib/zakuro/calculation/range/full_range.rb +1 -1
  4. data/lib/zakuro/version.rb +1 -1
  5. data/lib/zakuro/version/senmyou/const/number.rb +51 -0
  6. data/lib/zakuro/version/senmyou/const/remainder.rb +43 -0
  7. data/lib/zakuro/version/senmyou/cycle/remainder.rb +4 -6
  8. data/lib/zakuro/version/senmyou/monthly/lunar_phase.rb +35 -54
  9. data/lib/zakuro/version/senmyou/range/annual_range.rb +9 -65
  10. data/lib/zakuro/version/senmyou/stella/lunar/adjustment.rb +237 -0
  11. data/lib/zakuro/version/senmyou/stella/lunar/localization.rb +45 -0
  12. data/lib/zakuro/version/senmyou/stella/lunar/location.rb +108 -0
  13. data/lib/zakuro/version/senmyou/stella/lunar/value.rb +89 -0
  14. data/lib/zakuro/version/senmyou/stella/origin/average_november.rb +34 -0
  15. data/lib/zakuro/version/senmyou/stella/origin/lunar_age.rb +62 -0
  16. data/lib/zakuro/version/senmyou/stella/origin/winter_solstice.rb +55 -0
  17. data/lib/zakuro/version/senmyou/stella/solar/adjustment.rb +93 -0
  18. data/lib/zakuro/version/senmyou/stella/solar/average.rb +175 -0
  19. data/lib/zakuro/version/senmyou/stella/solar/interval.rb +103 -0
  20. data/lib/zakuro/version/senmyou/stella/solar/location.rb +164 -0
  21. data/lib/zakuro/version/senmyou/stella/solar/value.rb +138 -0
  22. metadata +20 -11
  23. data/lib/zakuro/version/senmyou/stella/lunar_orbit.rb +0 -332
  24. data/lib/zakuro/version/senmyou/stella/solar_average.rb +0 -169
  25. data/lib/zakuro/version/senmyou/stella/solar_location.rb +0 -213
  26. data/lib/zakuro/version/senmyou/stella/solar_orbit.rb +0 -213
  27. data/lib/zakuro/version/senmyou/stella/winter_solstice.rb +0 -106
@@ -0,0 +1,237 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../const/number'
4
+
5
+ # :nodoc:
6
+ module Zakuro
7
+ # :nodoc:
8
+ module Senmyou
9
+ # :nodoc:
10
+ module Lunar
11
+ #
12
+ # Adjustment 補正値情報
13
+ #
14
+ module Adjustment
15
+ # @return [Integer] 遠/近の地点での中間
16
+ HALF_DAYS = [7].freeze
17
+
18
+ #
19
+ # Row 行情報
20
+ #
21
+ class Row
22
+ # @return [True] 進(遠地点より数える)
23
+ # @return [False] 退(近地点より数える)
24
+ attr_reader :forward
25
+ # @return [Integer] 入暦(1-14)
26
+ attr_reader :day
27
+ # @return [Range] 小余範囲
28
+ attr_reader :range
29
+ # @return [Value] 補正値
30
+ attr_reader :value
31
+
32
+ #
33
+ # 初期化
34
+ #
35
+ # @param [True, False] forward 進(遠地点より数える)/退(近地点より数える)
36
+ # @param [Integer] day 入暦(1-14)
37
+ # @param [Range] range 小余範囲
38
+ # @param [Value] value 補正値
39
+ #
40
+ def initialize(forward:, day:, range:, value:)
41
+ @forward = forward
42
+ @day = day
43
+ @range = range
44
+ @value = value
45
+ end
46
+
47
+ # :reek:ControlParameter
48
+
49
+ #
50
+ # 一致するか
51
+ #
52
+ # @param [True, False] forward 進(遠地点より数える)/退(近地点より数える)
53
+ # @param [Integer] day 入暦(1-14)
54
+ # @param [Integer] minute 小余
55
+ #
56
+ # @return [True] 一致
57
+ # @return [False] 不一致
58
+ #
59
+ def match?(forward:, day:, minute:)
60
+ return false unless @forward == forward
61
+
62
+ return false unless @day == day
63
+
64
+ return false unless @range.include?(minute: minute)
65
+
66
+ true
67
+ end
68
+
69
+ #
70
+ # 分母を返す
71
+ #
72
+ # @return [Integer] 分母
73
+ #
74
+ def denominator
75
+ @range.denominator
76
+ end
77
+ end
78
+
79
+ #
80
+ # Range 小余範囲
81
+ #
82
+ class Range
83
+ # @return [Integer] 下限
84
+ MIN = 0
85
+ # @return [Integer] 上限
86
+ MAX = Const::Number::Cycle::DAY
87
+ # @return [Integer] 遠/近の地点での中間
88
+ HALF = 7465
89
+ # @return [Integer] 各地点の最後
90
+ LAST = 6529
91
+
92
+ # @return [Integer] 下限
93
+ attr_reader :min
94
+ # @return [Integer] 上限
95
+ attr_reader :max
96
+
97
+ #
98
+ # 初期化
99
+ #
100
+ # @param [Integer] min 下限
101
+ # @param [Integer] max 上限
102
+ #
103
+ def initialize(min: MIN, max: MAX)
104
+ @min = min
105
+ @max = max
106
+ end
107
+
108
+ #
109
+ # 含まれるか
110
+ #
111
+ # @param [Integer] minute 小余
112
+ #
113
+ # @return [True] 含まれる
114
+ # @return [False] 含まれない
115
+ #
116
+ def include?(minute:)
117
+ minute >= @min && minute <= @max
118
+ end
119
+
120
+ #
121
+ # 分母を返す
122
+ #
123
+ # @return [Integer] 分母
124
+ #
125
+ def denominator
126
+ @max - @min
127
+ end
128
+ end
129
+
130
+ #
131
+ # Value 補正値
132
+ #
133
+ class Value
134
+ # @return [Integer] 損益率
135
+ attr_reader :per
136
+ # @return [Integer] 眺朒(ちょうじく)積
137
+ attr_reader :stack
138
+
139
+ #
140
+ # 初期化
141
+ #
142
+ # @param [Integer] per 損益率
143
+ # @param [Integer] stack 眺朒(ちょうじく)積
144
+ #
145
+ def initialize(per:, stack:)
146
+ @per = per
147
+ @stack = stack
148
+ end
149
+
150
+ #
151
+ # 文字化
152
+ #
153
+ # @return [String] 文字
154
+ #
155
+ def to_s
156
+ "per:#{@per}, stack:#{@stack}"
157
+ end
158
+ end
159
+
160
+ # rubocop:disable Layout/LineLength
161
+
162
+ #
163
+ # @return [Array<Row>] 月の補正値情報
164
+ #
165
+ LIST = [
166
+ Row.new(forward: true, day: 1, range: Range.new, value: Value.new(per: +830, stack: 0)),
167
+ Row.new(forward: true, day: 2, range: Range.new, value: Value.new(per: +726, stack: +830)),
168
+ Row.new(forward: true, day: 3, range: Range.new, value: Value.new(per: +606, stack: +1556)),
169
+ Row.new(forward: true, day: 4, range: Range.new, value: Value.new(per: +471, stack: +2162)),
170
+ Row.new(forward: true, day: 5, range: Range.new, value: Value.new(per: +337, stack: +2633)),
171
+ Row.new(forward: true, day: 6, range: Range.new, value: Value.new(per: +202, stack: +2970)),
172
+ Row.new(forward: true, day: 7, range: Range.new(max: Range::HALF), value: Value.new(per: +53, stack: +3172)),
173
+ Row.new(forward: true, day: 7, range: Range.new(min: Range::HALF), value: Value.new(per: -7, stack: +3225)), # +3172 + 53(初益)
174
+ Row.new(forward: true, day: 8, range: Range.new, value: Value.new(per: -82, stack: +3218)),
175
+ Row.new(forward: true, day: 9, range: Range.new, value: Value.new(per: -224, stack: +3136)),
176
+ Row.new(forward: true, day: 10, range: Range.new, value: Value.new(per: -366, stack: +2912)),
177
+ Row.new(forward: true, day: 11, range: Range.new, value: Value.new(per: -509, stack: +2546)),
178
+ Row.new(forward: true, day: 12, range: Range.new, value: Value.new(per: -643, stack: +2037)),
179
+ Row.new(forward: true, day: 13, range: Range.new, value: Value.new(per: -748, stack: +1394)),
180
+ Row.new(forward: true, day: 14, range: Range.new(max: Range::LAST), value: Value.new(per: -646, stack: +646)), # 14日の小余は常に6529以下
181
+ Row.new(forward: false, day: 1, range: Range.new, value: Value.new(per: -830, stack: 0)),
182
+ Row.new(forward: false, day: 2, range: Range.new, value: Value.new(per: -726, stack: -830)),
183
+ Row.new(forward: false, day: 3, range: Range.new, value: Value.new(per: -598, stack: -1556)),
184
+ Row.new(forward: false, day: 4, range: Range.new, value: Value.new(per: -464, stack: -2154)),
185
+ Row.new(forward: false, day: 5, range: Range.new, value: Value.new(per: -329, stack: -2618)),
186
+ Row.new(forward: false, day: 6, range: Range.new, value: Value.new(per: -195, stack: -2947)),
187
+ Row.new(forward: false, day: 7, range: Range.new(max: Range::HALF), value: Value.new(per: -53, stack: -3142)),
188
+ Row.new(forward: false, day: 7, range: Range.new(min: Range::HALF), value: Value.new(per: +7, stack: -3195)), # -3142 - 53(初益)
189
+ Row.new(forward: false, day: 8, range: Range.new, value: Value.new(per: +82, stack: -3188)),
190
+ Row.new(forward: false, day: 9, range: Range.new, value: Value.new(per: +225, stack: -3106)),
191
+ Row.new(forward: false, day: 10, range: Range.new, value: Value.new(per: +366, stack: -2881)),
192
+ Row.new(forward: false, day: 11, range: Range.new, value: Value.new(per: +501, stack: -2515)),
193
+ Row.new(forward: false, day: 12, range: Range.new, value: Value.new(per: +628, stack: -2014)),
194
+ Row.new(forward: false, day: 13, range: Range.new, value: Value.new(per: +740, stack: -1386)),
195
+ Row.new(forward: false, day: 14, range: Range.new(max: Range::LAST), value: Value.new(per: +646, stack: -646)) # 14日の小余は常に6529以下
196
+ ].freeze
197
+ # rubocop:enable Layout/LineLength
198
+
199
+ #
200
+ # 月軌道の補正に必要な基本値を引き当てる
201
+ #
202
+ # @param [True, False] forward 進(遠地点より数える)/退(近地点より数える)
203
+ # @param [Integer] day 大余
204
+ # @param [Integer] minute 小余
205
+ #
206
+ # @return [Row] 補正値
207
+ #
208
+ def self.specify(forward:, day:, minute:)
209
+ LIST.each do |row|
210
+ # NOTE: 範囲が重複している場合、最初に引き当てたほうを優先する
211
+ return row if row.match?(forward: forward, day: day, minute: minute)
212
+ end
213
+
214
+ raise ArgumentError.new, "invalid parameter: #{forward}/#{day}/#{minute}"
215
+ end
216
+
217
+ # :reek:ControlParameter
218
+
219
+ #
220
+ # 小余の下げ幅を求める
221
+ #
222
+ # @param [Integer] day 大余
223
+ # @param [Integer] minute 小余
224
+ #
225
+ # @return [Integer] 小余の下げ幅
226
+ #
227
+ def self.minus_minute(day:, minute:)
228
+ return minute unless HALF_DAYS.include?(day)
229
+
230
+ return minute unless minute > Range::HALF
231
+
232
+ minute - Range::HALF
233
+ end
234
+ end
235
+ end
236
+ end
237
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../const/number'
4
+
5
+ # :nodoc:
6
+ module Zakuro
7
+ # :nodoc:
8
+ module Senmyou
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 = \
38
+ total_year * YEAR - lunar_age.to_minute
39
+
40
+ Cycle::LunarRemainder.new(total: (total_day % ANOMALISTIC_MONTH))
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,108 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../const/remainder'
4
+
5
+ require_relative './localization'
6
+
7
+ # :nodoc:
8
+ module Zakuro
9
+ # :nodoc:
10
+ module Senmyou
11
+ # :nodoc:
12
+ module Lunar
13
+ #
14
+ # Location 入暦
15
+ #
16
+ class Location
17
+ # @return [Cycle::LunarRemainder] 暦中日
18
+ HALF_ANOMALISTIC_MONTH = Const::Remainder::Lunar::HALF_ANOMALISTIC_MONTH
19
+ # @return [Cycle::LunarRemainder] 入暦上限
20
+ LIMIT = Const::Remainder::Lunar::LIMIT
21
+ # @return [Cycle::LunarRemainder] 弦
22
+ QUARTER = Const::Remainder::Lunar::QUARTER
23
+
24
+ # @return [True] 計算済み(前回計算あり)
25
+ # @return [False] 未計算(初回計算)
26
+ attr_reader :calculated
27
+ # @return [Integer] 西暦年
28
+ attr_reader :western_year
29
+ # @return [True] 進(遠地点より数える)
30
+ # @return [False] 退(近地点より数える)
31
+ attr_reader :forward
32
+ # @return [Cycle::LunarRemainder] 大余小余(初回:昨年天正閏余)
33
+ attr_reader :remainder
34
+
35
+ #
36
+ # 初期化
37
+ #
38
+ # @param [Cycle::LunarRemainder] lunar_age 天正閏余(大余小余)
39
+ # @param [Integer] western_year 西暦年
40
+ # @param [True, False] forward 進(遠地点より数える)/退(近地点より数える)
41
+ #
42
+ def initialize(lunar_age:, western_year:)
43
+ @calculated = false
44
+ @western_year = western_year
45
+ # 進
46
+ @forward = true
47
+ @remainder = lunar_age
48
+ end
49
+
50
+ #
51
+ # 入暦を計算する
52
+ #
53
+ def run
54
+ if calculated
55
+ # 1始まりで計算しているので、入暦上限を用いる
56
+ decrease(limit: LIMIT)
57
+ return
58
+ end
59
+
60
+ first
61
+ end
62
+
63
+ #
64
+ # 弦の分だけ月地点を進める
65
+ #
66
+ def add_quarter
67
+ @remainder.add!(QUARTER)
68
+ end
69
+
70
+ private
71
+
72
+ #
73
+ # 初回計算
74
+ #
75
+ def first
76
+ @remainder = Localization.first_remainder(
77
+ lunar_age: @remainder, western_year: @western_year
78
+ )
79
+ # 初回は0始まりで計算しているので、暦中日を用いる
80
+ decrease(limit: HALF_ANOMALISTIC_MONTH)
81
+ # 1始まりに改める
82
+ one_based
83
+
84
+ @calculated = true
85
+ end
86
+
87
+ #
88
+ # 大余小余に合わせて減算する(折り返す)
89
+ #
90
+ # @param [Cycle::LunarRemainder] limit 上限
91
+ #
92
+ def decrease(limit:)
93
+ return if @remainder < limit
94
+
95
+ @remainder.sub!(HALF_ANOMALISTIC_MONTH)
96
+ @forward = !@forward
97
+ end
98
+
99
+ #
100
+ # 1始まりにする
101
+ #
102
+ def one_based
103
+ @remainder.add!(Cycle::Remainder.new(day: 1, minute: 0, second: 0))
104
+ end
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../cycle/remainder'
4
+
5
+ require_relative './adjustment'
6
+
7
+ # :nodoc:
8
+ module Zakuro
9
+ # :nodoc:
10
+ module Senmyou
11
+ # :nodoc:
12
+ module Lunar
13
+ #
14
+ # Value 月補正値
15
+ #
16
+ module Value
17
+ # :reek:TooManyStatements { max_statements: 9 }
18
+
19
+ #
20
+ # 月の運行による補正値を算出する
21
+ #
22
+ # @param [Cycle::LunarRemainder] remainder 月の大余小余
23
+ # @param [True, False] forward 進(遠地点より数える)/退(近地点より数える)
24
+ #
25
+ # @return [Integer] 補正値
26
+ #
27
+ def self.get(remainder:, forward:)
28
+ valid?(remainder: remainder)
29
+
30
+ day = remainder.day
31
+ minute = remainder.floor_minute
32
+
33
+ # 引き当て
34
+ row = Adjustment.specify(forward: forward, day: day, minute: minute)
35
+
36
+ value = row.value
37
+ denominator = row.denominator
38
+
39
+ minus_minute = Adjustment.minus_minute(day: day, minute: minute)
40
+
41
+ day = calc_day(per: value.per, denominator: denominator,
42
+ minute: minus_minute)
43
+
44
+ value.stack + day
45
+ end
46
+
47
+ #
48
+ # 大余小余を検証する
49
+ #
50
+ # @param [Cycle::LunarRemainder] remainder 大余小余
51
+ #
52
+ # @return [True] 正しい(月の位相計算に使う大余小余)
53
+ # @return [True] 正しくない
54
+ #
55
+ def self.valid?(remainder:)
56
+ return if remainder.is_a?(Cycle::LunarRemainder)
57
+
58
+ raise ArgumentError, "unmatch parameter type: #{remainder.class}"
59
+ end
60
+ private_class_method :valid?
61
+
62
+ # :reek:TooManyStatements { max_statements: 9 }
63
+
64
+ #
65
+ # 累計値(大余)を作成する
66
+ #
67
+ # @param [Integer] per 入暦(1-14)
68
+ # @param [Integer] denominator 小余の分母
69
+ # @param [Integer] minute 小余
70
+ #
71
+ # @return [Integer] 累計値(大余)
72
+ #
73
+ def self.calc_day(per:, denominator:, minute:)
74
+ remainder_minute = (per * minute).to_f
75
+ day = remainder_minute / denominator
76
+ # 切り捨て(プラスマイナスに関わらず小数点以下切り捨て)
77
+ day = day.negative? ? day.ceil : day.floor
78
+ sign = remainder_minute.negative? ? -1 : 1
79
+ remainder_day = (sign * remainder_minute) % denominator
80
+ # 四捨五入(8400ならその半分の4200以上を繰り上げる)
81
+ day += sign if remainder_day >= (denominator / 2)
82
+
83
+ day
84
+ end
85
+ private_class_method :calc_day
86
+ end
87
+ end
88
+ end
89
+ end