zakuro 0.1.5 → 0.2.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 (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