zakuro 0.1.5 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/lib/zakuro/calculation/monthly/abstract_lunar_phase.rb +169 -0
  3. data/lib/zakuro/calculation/range/medieval_annual_range.rb +105 -0
  4. data/lib/zakuro/calculation/stella/lunar/abstract_location.rb +76 -0
  5. data/lib/zakuro/calculation/stella/lunar/choukei_value.rb +52 -0
  6. data/lib/zakuro/calculation/stella/solar/abstract_average.rb +117 -0
  7. data/lib/zakuro/calculation/stella/solar/abstract_location.rb +187 -0
  8. data/lib/zakuro/calculation/stella/solar/choukei_value.rb +136 -0
  9. data/lib/zakuro/calculation/type/old_float.rb +69 -0
  10. data/lib/zakuro/version.rb +1 -1
  11. data/lib/zakuro/version/gihou/const/number.rb +55 -0
  12. data/lib/zakuro/version/gihou/const/remainder.rb +56 -0
  13. data/lib/zakuro/version/gihou/cycle/remainder.rb +61 -0
  14. data/lib/zakuro/version/gihou/cycle/solar_term.rb +34 -0
  15. data/lib/zakuro/version/gihou/gihou.rb +23 -2
  16. data/lib/zakuro/version/gihou/monthly/lunar_phase.rb +106 -0
  17. data/lib/zakuro/version/gihou/range/annual_range.rb +39 -0
  18. data/lib/zakuro/version/gihou/stella/lunar/adjustment.rb +250 -0
  19. data/lib/zakuro/version/gihou/stella/lunar/localization.rb +44 -0
  20. data/lib/zakuro/version/gihou/stella/lunar/location.rb +86 -0
  21. data/lib/zakuro/version/gihou/stella/lunar/value.rb +74 -0
  22. data/lib/zakuro/version/gihou/stella/origin/average_november.rb +34 -0
  23. data/lib/zakuro/version/gihou/stella/origin/lunar_age.rb +62 -0
  24. data/lib/zakuro/version/gihou/stella/origin/winter_solstice.rb +55 -0
  25. data/lib/zakuro/version/gihou/stella/solar/adjustment.rb +93 -0
  26. data/lib/zakuro/version/gihou/stella/solar/average.rb +97 -0
  27. data/lib/zakuro/version/gihou/stella/solar/interval.rb +108 -0
  28. data/lib/zakuro/version/gihou/stella/solar/location.rb +61 -0
  29. data/lib/zakuro/version/gihou/stella/solar/value.rb +36 -0
  30. data/lib/zakuro/version/senmyou/const/number.rb +1 -1
  31. data/lib/zakuro/version/senmyou/const/remainder.rb +7 -1
  32. data/lib/zakuro/version/senmyou/cycle/solar_term.rb +4 -1
  33. data/lib/zakuro/version/senmyou/monthly/lunar_phase.rb +11 -111
  34. data/lib/zakuro/version/senmyou/range/annual_range.rb +5 -77
  35. data/lib/zakuro/version/senmyou/stella/lunar/localization.rb +2 -3
  36. data/lib/zakuro/version/senmyou/stella/lunar/location.rb +13 -28
  37. data/lib/zakuro/version/senmyou/stella/lunar/value.rb +5 -28
  38. data/lib/zakuro/version/senmyou/stella/solar/adjustment.rb +29 -29
  39. data/lib/zakuro/version/senmyou/stella/solar/average.rb +11 -89
  40. data/lib/zakuro/version/senmyou/stella/solar/location.rb +18 -121
  41. data/lib/zakuro/version/senmyou/stella/solar/value.rb +4 -103
  42. data/lib/zakuro/version/version_class_resolver.rb +4 -0
  43. metadata +28 -2
@@ -0,0 +1,187 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../cycle/abstract_remainder'
4
+
5
+ # :nodoc:
6
+ module Zakuro
7
+ # :nodoc:
8
+ module Calculation
9
+ # :nodoc:
10
+ module Solar
11
+ #
12
+ # AbstractLocation 入定気
13
+ #
14
+ class AbstractLocation
15
+ # @return [True] 計算済み(前回計算あり)
16
+ # @return [False] 未計算(初回計算)
17
+ attr_reader :calculated
18
+ # @return [Integer] 連番
19
+ attr_reader :index
20
+ # @return [Cycle::AbstractRemainder] 大余小余
21
+ attr_reader :remainder
22
+ # @return [Cycle::AbstractRemainder] 弦
23
+ attr_reader :quarter
24
+
25
+ #
26
+ # 初期化
27
+ #
28
+ # @param [Cycle::AbstractRemainder] lunar_age 天正閏余(大余小余)
29
+ # @param [Cycle::AbstractRemainder] quarter 弦
30
+ #
31
+ def initialize(lunar_age:, quarter:)
32
+ @calculated = false
33
+ @index = -1
34
+ @remainder = lunar_age.clone
35
+ @quarter = quarter
36
+ end
37
+
38
+ #
39
+ # 入定気を計算する
40
+ #
41
+ def run
42
+ return current if calculated
43
+
44
+ first
45
+ end
46
+
47
+ #
48
+ # 無効かどうか
49
+ #
50
+ # @return [True] 無効
51
+ # @return [False] 有効
52
+ #
53
+ def invalid?
54
+ @index == -1
55
+ end
56
+
57
+ #
58
+ # 弦の分だけ太陽地点を進める
59
+ #
60
+ def add_quarter
61
+ @remainder.add!(quarter)
62
+ end
63
+
64
+ #
65
+ # 二十四節気番号に対応する入気定日加減数を返す
66
+ #
67
+ # @note 継承で暦ごとの入気定日加減数を返す
68
+ #
69
+ # @param [Integer] index 二十四節気番号
70
+ #
71
+ # @return [Cycle::Remainder] 入気定日加減数
72
+ #
73
+ def interval(index:)
74
+ # abstract
75
+ end
76
+
77
+ #
78
+ # 入気定日加減数の要素数を返す
79
+ #
80
+ # @note 継承で暦ごとの入気定日加減数の要素数を返す
81
+ #
82
+ # @return [Integer] 入気定日加減数の要素数
83
+ #
84
+ def interval_size
85
+ # abstract
86
+ end
87
+
88
+ private
89
+
90
+ #
91
+ # 2回目以降の計算をする
92
+ #
93
+ def current
94
+ decrease_recursively
95
+ end
96
+
97
+ #
98
+ # 初回計算する
99
+ #
100
+ def first
101
+ define_first
102
+ @calculated = true
103
+ end
104
+
105
+ #
106
+ # 初回の入定気を定める
107
+ #
108
+ def define_first
109
+ # 入定気の起算方法
110
+ # 概要:
111
+ # * 太陽の運行による補正値は、二十四節気の気ごとに定められる
112
+ # * 11月経朔の前にある気を求め、それから11月経朔との間隔を求める
113
+ # * 気ごとの補正値と、気から11月経朔までにかかる補正値を求める
114
+ # 前提:
115
+ # * 11月経朔に関わる二十四節気は、時系列から順に、小雪・大雪・冬至である
116
+ # * 小雪〜大雪の間隔は小雪定数で、大雪〜冬至の間隔は大雪定数で決められている(24気損益眺朒(ちょうじく)数のこと)
117
+ # * 11月経朔は、この小雪〜冬至の間のいずれかにある
118
+ # 計算:
119
+ # 2パターンある
120
+ # (a) 大雪〜冬至にある場合
121
+ # *「大雪定数 >= 天正閏余」の場合を指す
122
+ # * * NOTE 資料では「より大きい(>)」とされるが、大雪そのものの場合は大雪から起算すべき
123
+ # * この場合は、大雪〜経朔の間隔を求める
124
+ # (b) 小雪〜大雪にある場合
125
+ # *「大雪定数 < 天正閏余」の場合を指す
126
+ # * この場合は、小雪〜経朔の間隔を求める
127
+
128
+ # NOTE: 上記パターンとは別に、稀だが立冬のパターンも存在する
129
+ # この場合は比較方法はそのままに立冬〜経朔の間隔を求める
130
+
131
+ # 大雪(23)/小雪(22)/立冬(21)
132
+ [23, 22, 21].each do |index|
133
+ prev(index: index)
134
+
135
+ break unless invalid?
136
+ end
137
+
138
+ # 立冬(21)を超える天正閏余は成立し得ない(1朔望月をはるかに超えることになる)
139
+ return unless invalid?
140
+
141
+ raise ArgumentError.new, 'invalid winster solstice age'
142
+ end
143
+
144
+ #
145
+ # 大余小余の分だけ二十四節気を遡る
146
+ #
147
+ # @param [Integer] index 二十四節気番号
148
+ #
149
+ def prev(index:)
150
+ interval = interval(index: index)
151
+ if remainder > interval
152
+ @remainder.sub!(interval)
153
+ return
154
+ end
155
+
156
+ # 入定気が確定する
157
+ @remainder = interval.sub(@remainder)
158
+ @index = index
159
+ end
160
+
161
+ #
162
+ # 二十四節気番号を次に進める
163
+ #
164
+ def next_index
165
+ @index += 1
166
+ @index = 0 if @index >= interval_size
167
+ end
168
+
169
+ #
170
+ # 二十四節気を減算する
171
+ #
172
+ def decrease_recursively
173
+ interval = interval(index: index)
174
+ # 現在の二十四節気に留まる
175
+ return if remainder < interval
176
+
177
+ @remainder.sub!(interval)
178
+
179
+ next_index
180
+
181
+ # 再帰
182
+ decrease_recursively
183
+ end
184
+ end
185
+ end
186
+ end
187
+ end
@@ -0,0 +1,136 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../type/old_float'
4
+
5
+ # :nodoc:
6
+ module Zakuro
7
+ # :nodoc:
8
+ module Calculation
9
+ # :nodoc:
10
+ module Solar
11
+ #
12
+ # ChoukeiValue 再考長慶宣明暦算法
13
+ #
14
+ module ChoukeiValue
15
+ # @return [Output::Logger] ロガー
16
+ LOGGER = Output::Logger.new(location: 'solar_choukei')
17
+
18
+ #
19
+ # 補正値を返す
20
+ #
21
+ # @param [Cycle::AbstractRemainder] remainder 大余小余
22
+ # @param [Adjustment::Row] row 24気損益眺朒(ちょうじく)数
23
+ #
24
+ # @return [Integer] 補正値
25
+ #
26
+ def self.get(remainder:, row:)
27
+ # 損益率/眺朒(ちょうじく)数
28
+ # パラメータ:
29
+ # a: 眺朒(ちょうじく)数の初日の値
30
+ # b: 損益率初日の値
31
+ # c: 損益率の毎日の差
32
+ # n: 定気の日から数えた日数
33
+
34
+ # LOGGER.debug("row.per_day: #{row.per_day}")
35
+ # LOGGER.debug("row.stack: #{row.stack}")
36
+
37
+ day_stack = calc_day_stack(remainder: remainder, row: row)
38
+
39
+ # LOGGER.debug("day_stack: #{day_stack}")
40
+
41
+ month_stack = calc_month_stack(row: row, day: remainder.day)
42
+
43
+ # LOGGER.debug("month_stack: #{month_stack}")
44
+
45
+ # 冬至であれば眺朒数がプラスになり続けて損益率が「益」で、小雪であればマイナスの眺朒数がプラスされ続けて「損」
46
+ month_stack + day_stack
47
+ end
48
+
49
+ #
50
+ # 損益率を求める
51
+ #
52
+ # @param [Remainder] remainder 入定気
53
+ # @param [Adjustment::Row] row 24気損益眺朒(ちょうじく)数
54
+ #
55
+ # @return [Integer] 損益率
56
+ #
57
+ def self.calc_day_stack(remainder:, row:)
58
+ ratio = calc_ratio(day: remainder.day, per_term: row.per_term, per_day: row.per_day)
59
+
60
+ # LOGGER.debug("ratio.sign: #{ratio.sign}")
61
+ # LOGGER.debug("ratio.abs: #{ratio.abs}")
62
+
63
+ calc_day_stack_from_ratio(
64
+ ratio: ratio, minute: remainder.minute, limit: remainder.base_day
65
+ )
66
+ end
67
+ private_class_method :calc_day_stack
68
+
69
+ #
70
+ # 大余に対応する損益率を求める
71
+ # 損益率 = b + n * c
72
+ #
73
+ # @param [Integer] day 大余
74
+ # @param [Integer] per_term 眺朒(ちょうじく)数
75
+ # @param [Integer] per_day 毎日差
76
+ #
77
+ # @return [Type::OldFloat] 大余に対応する損益率
78
+ #
79
+ def self.calc_ratio(day:, per_term:, per_day:)
80
+ ratio = Type::OldFloat.new(per_term + day * per_day)
81
+ # 小数点以下は無視する
82
+ ratio.floor!
83
+
84
+ ratio
85
+ end
86
+ private_class_method :calc_ratio
87
+
88
+ #
89
+ # 小余を含めた損益率を求める
90
+ #
91
+ # @param [Integer] sign 正負(大余に対応する損益率)
92
+ # @param [Integer] ratio 大余に対応する損益率
93
+ # @param [Integer] minute 小余
94
+ #
95
+ # @return [Integer] 小余を含めた損益率
96
+ #
97
+ def self.calc_day_stack_from_ratio(ratio:, minute:, limit:)
98
+ minute_stack = ratio.abs * minute
99
+ day_stack = (minute_stack / limit).floor
100
+ # 四捨五入
101
+ # NOTE 資料では「この余りが4200をこえていれば切り上げる」とあり「>=」とした
102
+ # 1612年の7月(慶長17年7月)が境界値4200だが、繰り上げを行なっていたため
103
+ day_stack += 1 if minute_stack % limit >= (limit / 2)
104
+ day_stack *= ratio.sign
105
+
106
+ day_stack
107
+ end
108
+ private_class_method :calc_day_stack_from_ratio
109
+
110
+ #
111
+ # 眺朒(ちょうじく)数を求める
112
+ # 眺朒(ちょうじく)数 = a + (n * b) + (1/2)n(n-1)c
113
+ #
114
+ # @param [Adjustment::Row] row 24気損益眺朒(ちょうじく)数
115
+ # @param [Integer] day 大余
116
+ #
117
+ # @return [Integer] 眺朒(ちょうじく)数
118
+ #
119
+ def self.calc_month_stack(row:, day:)
120
+ # row.stack: 眺朒(ちょうじく)積
121
+ # row.per_term: 眺朒(ちょうじく)数
122
+ # row.per_day: 毎日差
123
+ month_stack = Type::OldFloat.new(
124
+ row.stack + day * row.per_term + \
125
+ (1 / 2.0) * (day * (day - 1) * row.per_day)
126
+ )
127
+ # 切り捨て(プラスマイナスに関わらず小数点以下切り捨て)
128
+ month_stack.floor!
129
+
130
+ month_stack.get
131
+ end
132
+ private_class_method :calc_month_stack
133
+ end
134
+ end
135
+ end
136
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ # :nodoc:
4
+ module Zakuro
5
+ # :nodoc:
6
+ module Calculation
7
+ # :nodoc:
8
+ module Type
9
+ #
10
+ # OldFloat 浮動小数点数(古代)
11
+ #
12
+ # @note 四捨五入は常に絶対値に対して行う
13
+ # * value.negative? ? value.ceil : value.floor
14
+ # * 絶対値だけを取り出すことで、四捨五入を平易にする
15
+ #
16
+ class OldFloat
17
+ # @return [Integer] 符号
18
+ attr_reader :sign
19
+ # @return [Float] 絶対値
20
+ attr_reader :abs
21
+
22
+ #
23
+ # 初期化
24
+ #
25
+ # @param [Float] value 符号つき浮動小数点数
26
+ #
27
+ def initialize(value)
28
+ @sign = value.negative? ? -1 : 1
29
+ @abs = @sign * value
30
+ end
31
+
32
+ #
33
+ # 四捨五入する
34
+ #
35
+ def floor!
36
+ @abs = floor
37
+ end
38
+
39
+ #
40
+ # 四捨五入する(非破壊的)
41
+ #
42
+ # @return [Float] 絶対値
43
+ #
44
+ def floor
45
+ @abs.floor
46
+ end
47
+
48
+ #
49
+ # 符号つき浮動小数点数を取得する
50
+ #
51
+ # @return [Float] 符号つき浮動小数点数
52
+ #
53
+ def get
54
+ @sign * @abs
55
+ end
56
+
57
+ #
58
+ # 負数かどうか
59
+ #
60
+ # @return [True] 負数
61
+ # @return [False] 正数
62
+ #
63
+ def negative?
64
+ @sign == -1
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -3,5 +3,5 @@
3
3
  # :nodoc:
4
4
  module Zakuro
5
5
  # @return [String] library version
6
- VERSION = '0.1.5'
6
+ VERSION = '0.2.0'
7
7
  end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ # :nodoc:
4
+ module Zakuro
5
+ # :nodoc:
6
+ module Gihou
7
+ #
8
+ # Const 定数
9
+ #
10
+ module Const
11
+ #
12
+ # Number 数値
13
+ #
14
+ module Number
15
+ #
16
+ # Cycle 周期
17
+ #
18
+ module Cycle
19
+ # @return [Integer] 総法(1日=1340分)
20
+ DAY = 1340
21
+ #
22
+ # @return [Float] 変日(1近点月 = 27日743分1秒(1分=12秒))
23
+ # @note 小数点以下の値によって大幅に結果が変わる。除算結果を設定した
24
+ #
25
+ # ANOMALISTIC_MONTH = 36_923.083333333333
26
+ ANOMALISTIC_MONTH = 36_923 + (1.0 / 12)
27
+ # @return [Integer] 朔望月
28
+ SYNODIC_MONTH = 39_571
29
+ # @return [Integer] 一年
30
+ YEAR = 489_428
31
+ end
32
+
33
+ #
34
+ # Derivation 導出
35
+ #
36
+ module Derivation
37
+ # @return [Integer] 通余: (YEAR - DAY * 12 * 30)
38
+ REMAINDER_ALL_YEAR = 7028
39
+ # @return [Integer] 旬周(60日) DAY * 60
40
+ SIXTY_DAYS = 80_400
41
+ end
42
+
43
+ #
44
+ # 累積
45
+ #
46
+ module Stack
47
+ # @return [Integer] 積年(甲子夜半朔旦冬至〜暦の開始前)
48
+ TOTAL_YEAR = 269_880
49
+ # @return [Integer] 暦の開始年(麟徳元年)
50
+ BEGIN_YEAR = 664
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end