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.
- checksums.yaml +4 -4
- data/lib/zakuro/calculation/monthly/abstract_lunar_phase.rb +169 -0
- data/lib/zakuro/calculation/range/medieval_annual_range.rb +105 -0
- data/lib/zakuro/calculation/stella/lunar/abstract_location.rb +76 -0
- data/lib/zakuro/calculation/stella/lunar/choukei_value.rb +52 -0
- data/lib/zakuro/calculation/stella/solar/abstract_average.rb +117 -0
- data/lib/zakuro/calculation/stella/solar/abstract_location.rb +187 -0
- data/lib/zakuro/calculation/stella/solar/choukei_value.rb +136 -0
- data/lib/zakuro/calculation/type/old_float.rb +69 -0
- data/lib/zakuro/version.rb +1 -1
- data/lib/zakuro/version/gihou/const/number.rb +55 -0
- data/lib/zakuro/version/gihou/const/remainder.rb +56 -0
- data/lib/zakuro/version/gihou/cycle/remainder.rb +61 -0
- data/lib/zakuro/version/gihou/cycle/solar_term.rb +34 -0
- data/lib/zakuro/version/gihou/gihou.rb +23 -2
- data/lib/zakuro/version/gihou/monthly/lunar_phase.rb +106 -0
- data/lib/zakuro/version/gihou/range/annual_range.rb +39 -0
- data/lib/zakuro/version/gihou/stella/lunar/adjustment.rb +250 -0
- data/lib/zakuro/version/gihou/stella/lunar/localization.rb +44 -0
- data/lib/zakuro/version/gihou/stella/lunar/location.rb +86 -0
- data/lib/zakuro/version/gihou/stella/lunar/value.rb +74 -0
- data/lib/zakuro/version/gihou/stella/origin/average_november.rb +34 -0
- data/lib/zakuro/version/gihou/stella/origin/lunar_age.rb +62 -0
- data/lib/zakuro/version/gihou/stella/origin/winter_solstice.rb +55 -0
- data/lib/zakuro/version/gihou/stella/solar/adjustment.rb +93 -0
- data/lib/zakuro/version/gihou/stella/solar/average.rb +97 -0
- data/lib/zakuro/version/gihou/stella/solar/interval.rb +108 -0
- data/lib/zakuro/version/gihou/stella/solar/location.rb +61 -0
- data/lib/zakuro/version/gihou/stella/solar/value.rb +36 -0
- data/lib/zakuro/version/senmyou/const/number.rb +1 -1
- data/lib/zakuro/version/senmyou/const/remainder.rb +7 -1
- data/lib/zakuro/version/senmyou/cycle/solar_term.rb +4 -1
- data/lib/zakuro/version/senmyou/monthly/lunar_phase.rb +11 -111
- data/lib/zakuro/version/senmyou/range/annual_range.rb +5 -77
- data/lib/zakuro/version/senmyou/stella/lunar/localization.rb +2 -3
- data/lib/zakuro/version/senmyou/stella/lunar/location.rb +13 -28
- data/lib/zakuro/version/senmyou/stella/lunar/value.rb +5 -28
- data/lib/zakuro/version/senmyou/stella/solar/adjustment.rb +29 -29
- data/lib/zakuro/version/senmyou/stella/solar/average.rb +11 -89
- data/lib/zakuro/version/senmyou/stella/solar/location.rb +18 -121
- data/lib/zakuro/version/senmyou/stella/solar/value.rb +4 -103
- data/lib/zakuro/version/version_class_resolver.rb +4 -0
- 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
|
data/lib/zakuro/version.rb
CHANGED
@@ -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
|