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
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