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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a5bbb00f73830eff0f9e912c0fa0c10d49d7849b3f46395c19de8ec1f71f8012
4
- data.tar.gz: e95b80813e7ce382e0c5fce6a62382d3c26383db6f0b7e64e82bd1f005a6f15c
3
+ metadata.gz: a4269bda9e7a1bc90589d072ac97a0acc089f098a5b1e8bbe6d04d661407c256
4
+ data.tar.gz: cb8821e9f1f9692a867c4baec73ce515281d3bf4ef8a04db676909d03cd3b7b0
5
5
  SHA512:
6
- metadata.gz: a3bb973f87a0bb6e3d3caffca76e9cc57cf5748e16bb3e9f87b3e9ffe2307682646aa08077ad6685a04ec282d255aa0f3ecf5992d2595f89bcd00b364aa22f45
7
- data.tar.gz: f85ca93529ec87eb15e97f2564509429b95d8433c22d3141bdef26fa79154689030d9552ca38e8e81812289d5adf272b8445e510a21967cd9b517c805e6956a5
6
+ metadata.gz: f4acc077c7191f18601765cc81668660f4fe0af9dbeecf0af74cf0841f20546a0792484bbcc9bf8c490f62065ef8b32c9268def780037ec62739665823950d47
7
+ data.tar.gz: 97ea77400bd644d2c84e08e4d3056ee121563e5d52e1b418dfb57e50cbf5c741f4dde1954d4951460618b5c5837bc13103f8ae7857075b159a307986e2fb39af
@@ -0,0 +1,169 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../output/logger'
4
+
5
+ # :nodoc:
6
+ module Zakuro
7
+ # :nodoc:
8
+ module Calculation
9
+ # :nodoc:
10
+ module Monthly
11
+ #
12
+ # AbstractLunarPhase 月の位相
13
+ #
14
+ class AbstractLunarPhase
15
+ # @return [Output::Logger] ロガー
16
+ LOGGER = Output::Logger.new(location: 'lunar_phase')
17
+
18
+ # @return [Array<String>] 月内の弦
19
+ PHASE_INDEXES = %w[朔日 上弦 望月 下弦].freeze
20
+
21
+ # @return [Cycle::AbstractRemainder] 経
22
+ attr_reader :average_remainder
23
+ # @return [Solar::AbstractLocation] 入定気
24
+ attr_reader :solar_location
25
+ # @return [Lunar::AbstractLocation] 入暦
26
+ attr_reader :lunar_location
27
+ # @return [Integer] 弦の位置
28
+ attr_reader :index
29
+
30
+ #
31
+ # 初期化
32
+ #
33
+ # @param [Cycle::AbstractRemainder] quater 弦
34
+ # @param [Solar::AbstractLocation] average_remainder 経
35
+ # @param [Solar::AbstractLocation] solar_location 入定気
36
+ # @param [Lunar::AbstractLocation] lunar_location 入暦
37
+ #
38
+ def initialize(quater:, average_remainder:, solar_location:, lunar_location:)
39
+ # 弦
40
+ @quarter = quater
41
+ # 経
42
+ @average_remainder = average_remainder
43
+ # 入定気
44
+ @solar_location = solar_location
45
+ # 入暦
46
+ @lunar_location = lunar_location
47
+
48
+ # 弦の位置
49
+ @index = 0
50
+ end
51
+
52
+ #
53
+ # 次の弦に進める
54
+ #
55
+ # @return [Remainder] 定朔
56
+ #
57
+ def next_phase
58
+ adjusted = current_remainder
59
+
60
+ add_quarter_moon_size
61
+
62
+ adjusted
63
+ end
64
+
65
+ #
66
+ # 次の月に進める
67
+ # @note 進めた後の月の定朔ではなく、当月のものを返却する
68
+ #
69
+ # @return [Remainder] 当月初の定朔
70
+ #
71
+ def next_month
72
+ result = nil
73
+ PHASE_INDEXES.each_with_index do |_phase, index|
74
+ adjust = next_phase
75
+ result = adjust if index.zero?
76
+ end
77
+
78
+ result
79
+ end
80
+
81
+ private
82
+
83
+ #
84
+ # 次の弦に進める
85
+ #
86
+ # @return [Integer] 弦
87
+ #
88
+ def next_index
89
+ @index += 1
90
+ @index = 0 if @index >= PHASE_INDEXES.size
91
+ @index
92
+ end
93
+
94
+ #
95
+ # 朔月(月初)であるか
96
+ #
97
+ # @return [True] 朔月である
98
+ # @return [False] 朔月ではない
99
+ #
100
+ def first_phase?
101
+ @index.zero?
102
+ end
103
+
104
+ #
105
+ # 朔月のみログ出力する
106
+ #
107
+ # @param [String] messages メッセージ(可変長)
108
+ #
109
+ def debug(*messages)
110
+ # 全ての弦を対象にするためコメントアウトする
111
+ # return unless first_phase?
112
+
113
+ LOGGER.debug(*messages)
114
+ end
115
+
116
+ #
117
+ # 現在の定朔を取得する
118
+ #
119
+ # @return [Remainder] 定朔
120
+ #
121
+ def current_remainder
122
+ # abstract
123
+ end
124
+
125
+ #
126
+ # 補正値を得る
127
+ #
128
+ # @return [Integer] 補正値
129
+ #
130
+ def correction_value
131
+ sun = correction_solar_value
132
+ moon = correction_moon_value
133
+
134
+ sum = sun + moon
135
+
136
+ debug("sun: #{sun}", "moon: #{moon}", "sun + moon : #{sum}")
137
+
138
+ sum
139
+ end
140
+
141
+ #
142
+ # 太陽運動の補正値を得る
143
+ #
144
+ # @return [Integer] 太陽運動の補正値
145
+ #
146
+ def correction_solar_value
147
+ # abstract
148
+ end
149
+
150
+ #
151
+ # 月運動の補正値を得る
152
+ #
153
+ # @return [Integer] 月運動の補正値
154
+ #
155
+ def correction_moon_value
156
+ # abstract
157
+ end
158
+
159
+ def add_quarter_moon_size
160
+ @average_remainder.add!(@quarter)
161
+ @solar_location.add_quarter
162
+ @lunar_location.add_quarter
163
+
164
+ next_index
165
+ end
166
+ end
167
+ end
168
+ end
169
+ end
@@ -0,0 +1,105 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../output/logger'
4
+ require_relative '../monthly/initialized_month'
5
+ require_relative '../monthly/month_label'
6
+ require_relative '../monthly/first_day'
7
+
8
+ # :nodoc:
9
+ module Zakuro
10
+ # :nodoc:
11
+ module Calculation
12
+ # :nodoc:
13
+ module Range
14
+ #
15
+ # MedievalAnnualRange 年間範囲(中世)
16
+ #
17
+ # * 儀鳳暦 ~ 宣明暦 を便宜的に中世とした
18
+ # * 冬至から1年の開始を算出する
19
+ # * 二十四節気:平気法
20
+ # * 月の大小:定朔
21
+ #
22
+ module MedievalAnnualRange
23
+ # @return [Output::Logger] ロガー
24
+ LOGGER = Output::Logger.new(location: 'medieval_annual_range')
25
+
26
+ #
27
+ # 一覧取得する
28
+ #
29
+ # * 対象年に対して、前年11月-当年11月までを出力する
30
+ # * 対象年(西暦)と計算年(元号x年)の紐付けは行わない
31
+ #
32
+ # @param [Context] context 暦コンテキスト
33
+ # @param [Monthly::AbstractLunarPhase] lunar_phase 月の位相
34
+ # @param [Solar::AbstractAverage] solar_average 定気(太陽軌道平均)
35
+ #
36
+ # @return [Array<Month>] 1年データ
37
+ #
38
+ def self.get(context:, lunar_phase:, solar_average:)
39
+ annual_range = initialized_annual_range(context: context, lunar_phase: lunar_phase)
40
+
41
+ apply_big_and_small_of_the_month(annual_range: annual_range)
42
+
43
+ solar_average.set(annual_range: annual_range)
44
+
45
+ # 月間隔を取得するためだけの末尾要素を削除
46
+ annual_range.pop
47
+
48
+ initialize_month_label(annual_range: annual_range)
49
+ end
50
+
51
+ #
52
+ # 1年データを取得する
53
+ #
54
+ # @param [Context] context 暦コンテキスト
55
+ # @param [Monthly::LunarPhase] lunar_phase 月の位相
56
+ #
57
+ # @return [Array<Month>] 1年データ
58
+ #
59
+ def self.initialized_annual_range(context:, lunar_phase:)
60
+ result = []
61
+
62
+ # 14ヶ月分を生成する(閏年で最大13ヶ月 + 末月の大小/二十四節気を求めるために必要な月)
63
+ (0..13).each do |_index|
64
+ adjusted = lunar_phase.next_month
65
+
66
+ result.push(
67
+ Monthly::InitializedMonth.new(
68
+ context: context,
69
+ month_label: Monthly::MonthLabel.new,
70
+ first_day: Monthly::FirstDay.new(remainder: adjusted),
71
+ phase_index: 0
72
+ )
73
+ )
74
+ end
75
+
76
+ result
77
+ end
78
+ private_class_method :initialized_annual_range
79
+
80
+ #
81
+ # 1年データの各月に月の大小を設定する
82
+ #
83
+ # @param [Array<Month>] annual_range 1年データ
84
+ #
85
+ def self.apply_big_and_small_of_the_month(annual_range:)
86
+ # NOTE: 最後の月は処理できない(=計算外の余分な月が最後に必要である)
87
+ annual_range.each_cons(2) do |(current_month, next_month)|
88
+ current_month.eval_many_days(next_month_day: next_month.remainder.day)
89
+ end
90
+ end
91
+ private_class_method :apply_big_and_small_of_the_month
92
+
93
+ #
94
+ # 月表示情報を更新する
95
+ #
96
+ # @param [Array<Month>] annual_range 1年データ
97
+ #
98
+ def self.initialize_month_label(annual_range:)
99
+ annual_range.each(&:rename_month_label_by_solar_term)
100
+ end
101
+ private_class_method :initialize_month_label
102
+ end
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,76 @@
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 Lunar
11
+ #
12
+ # AbstractLocation 入暦
13
+ #
14
+ class AbstractLocation
15
+ # @return [True] 計算済み(前回計算あり)
16
+ # @return [False] 未計算(初回計算)
17
+ attr_reader :calculated
18
+ # @return [Integer] 西暦年
19
+ attr_reader :western_year
20
+ # @return [Cycle::LunarRemainder] 大余小余(初回:昨年天正閏余)
21
+ attr_reader :remainder
22
+
23
+ #
24
+ # 初期化
25
+ #
26
+ # @param [Cycle::LunarRemainder] lunar_age 天正閏余(大余小余)
27
+ # @param [Integer] western_year 西暦年
28
+ #
29
+ def initialize(lunar_age:, western_year:)
30
+ @calculated = false
31
+ @western_year = western_year
32
+ @remainder = lunar_age
33
+ end
34
+
35
+ #
36
+ # 入暦を計算する
37
+ #
38
+ def run
39
+ # abstract
40
+ end
41
+
42
+ #
43
+ # 弦の分だけ月地点を進める
44
+ #
45
+ def add_quarter
46
+ # abstract
47
+ end
48
+
49
+ private
50
+
51
+ #
52
+ # 初回計算
53
+ #
54
+ def first
55
+ # abstract
56
+ end
57
+
58
+ #
59
+ # 大余小余に合わせて減算する(折り返す)
60
+ #
61
+ # @param [Cycle::LunarRemainder] limit 上限
62
+ #
63
+ def decrease(limit:)
64
+ # abstract
65
+ end
66
+
67
+ #
68
+ # 1始まりにする
69
+ #
70
+ def one_based
71
+ @remainder.add!(Cycle::AbstractRemainder.new(day: 1, minute: 0, second: 0))
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,52 @@
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 Lunar
11
+ #
12
+ # ChoukeiValue 再考長慶宣明暦算法
13
+ #
14
+ module ChoukeiValue
15
+ #
16
+ # 四捨五入した大余を返す
17
+ #
18
+ # @param [Integer] per 増減率
19
+ # @param [Integer] denominator 小余の分母
20
+ # @param [Integer] minute 小余
21
+ #
22
+ # @return [Integer] 累計値(大余)
23
+ #
24
+ def self.rounded_day(per:, denominator:, minute:)
25
+ remainder_minute = Type::OldFloat.new((per * minute).to_f)
26
+ day = day_only(remainder_minute: remainder_minute.get, denominator: denominator)
27
+ # 繰り上げ結果を足す
28
+ day += carried_minute(remainder_minute: remainder_minute, denominator: denominator)
29
+
30
+ day
31
+ end
32
+
33
+ def self.day_only(remainder_minute:, denominator:)
34
+ float_day = Type::OldFloat.new(remainder_minute / denominator)
35
+ # 切り捨て(プラスマイナスに関わらず小数点以下切り捨て)
36
+ float_day.floor!
37
+ float_day.get
38
+ end
39
+ private_class_method :day_only
40
+
41
+ def self.carried_minute(remainder_minute:, denominator:)
42
+ remainder_day = remainder_minute.abs % denominator
43
+ # 四捨五入(1/2日 以上なら繰り上げる)
44
+ return remainder_minute.sign if remainder_day >= (denominator / 2)
45
+
46
+ 0
47
+ end
48
+ private_class_method :carried_minute
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,117 @@
1
+ # frozen_string_literal: true
2
+
3
+ # :nodoc:
4
+ module Zakuro
5
+ # :nodoc:
6
+ module Calculation
7
+ # :nodoc:
8
+ module Solar
9
+ #
10
+ # AbstractAverage 平気(太陽軌道平均)
11
+ #
12
+ class AbstractAverage
13
+ #
14
+ # 初期化
15
+ #
16
+ # @param [Cycle::AbstractSolarTerm] solar_term 入定気
17
+ #
18
+ def initialize(solar_term:)
19
+ @solar_term = solar_term
20
+ end
21
+
22
+ #
23
+ # 冬至から数えた1年データの月ごとに二十四節気を割り当てる
24
+ #
25
+ # @param [Array<Month>] annual_range 1年データ
26
+ #
27
+ # @return [Array<Month>] 1年データ
28
+ #
29
+ def set(annual_range:)
30
+ # 次月と比較しながら当月の二十四節気を決める
31
+ # NOTE: 最後の月は処理できない(=計算外の余分な月が最後に必要である)
32
+ annual_range.each_cons(2) do |(current_month, next_month)|
33
+ set_solar_term(
34
+ current_month: current_month,
35
+ next_month: next_month
36
+ )
37
+ end
38
+
39
+ annual_range
40
+ end
41
+
42
+ # :reek:TooManyStatements { max_statements: 7 }
43
+
44
+ #
45
+ # 月内(当月朔日から当月末日(来月朔日の前日)の間)に二十四節気があるか
46
+ # @note 大余60で一巡するため 以下2パターンがある
47
+ # * current_month <= next_month : (二十四節気) >= current_month && (二十四節気) < next_month
48
+ # * current_month > next_month : (二十四節気) >= current_month || (二十四節気) < next_month
49
+ #
50
+ # @param [Cycle::AbstractRemainder] solar_term 二十四節気
51
+ # @param [Cycle::AbstractRemainder] current_month 月初
52
+ # @param [Cycle::AbstractRemainder] next_month 月末
53
+ #
54
+ # @return [True] 対象の二十四節気がある
55
+ # @return [False] 対象の二十四節気がない
56
+ #
57
+ def self.in_solar_term?(solar_term:, current_month:, next_month:)
58
+ # 大余で比較する
59
+ target_time = solar_term.day
60
+ current_month_time = current_month.day
61
+ next_month_time = next_month.day
62
+ current_month_over = (target_time >= current_month_time)
63
+ next_month_under = (target_time < next_month_time)
64
+
65
+ return current_month_over && next_month_under if current_month_time <= next_month_time
66
+
67
+ current_month_over || next_month_under
68
+ end
69
+
70
+ private
71
+
72
+ # :reek:TooManyStatements { max_statements: 8 }
73
+
74
+ #
75
+ # 二十四節気を設定する
76
+ #
77
+ # @param [Month] current_month 当月
78
+ # @param [Month] next_month 次月
79
+ #
80
+ def set_solar_term(current_month:, next_month:)
81
+ # 安全策として無限ループは回避する
82
+ # * 最大試行回数:4回(設定なし => 設定あり => 設定あり => 設定なし)
83
+ # * 閏月は1回しか設定しない
84
+ # * 最大2回設定する(中気・節気)
85
+ (0..3).each do |_index|
86
+ in_range = AbstractAverage.in_solar_term?(
87
+ solar_term: @solar_term.remainder, current_month: current_month.remainder,
88
+ next_month: next_month.remainder
89
+ )
90
+
91
+ # 範囲外
92
+ unless in_range
93
+ # 1つ以上設定されていれば切り上げる(一つ飛ばしで二十四節気を設定することはない)
94
+ break unless current_month.empty_solar_term?
95
+
96
+ next_solar_term
97
+ next
98
+ end
99
+
100
+ current_month.add_term(term: @solar_term.clone)
101
+ next_solar_term
102
+
103
+ # 定気は最大2つまで
104
+ break if current_month.solar_term_size == 2
105
+ end
106
+ end
107
+
108
+ #
109
+ # 次の二十四節気に移る
110
+ #
111
+ def next_solar_term
112
+ @solar_term.next_term!
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end