zakuro 0.0.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +3 -0
  3. data/README.md +102 -42
  4. data/doc/operation.md +25 -0
  5. data/doc/operation/csv/month.csv +202 -0
  6. data/doc/operation/operation.xlsx +0 -0
  7. data/doc/operation/transfer.rb +77 -0
  8. data/lib/zakuro/calculation/base/multi_gengou.rb +101 -0
  9. data/lib/zakuro/calculation/base/multi_gengou_roller.rb +218 -0
  10. data/lib/zakuro/calculation/base/year.rb +107 -0
  11. data/lib/zakuro/calculation/cycle/abstract_remainder.rb +459 -0
  12. data/lib/zakuro/calculation/cycle/abstract_solar_term.rb +151 -0
  13. data/lib/zakuro/calculation/cycle/zodiac.rb +106 -0
  14. data/lib/zakuro/calculation/monthly/first_day.rb +45 -0
  15. data/lib/zakuro/calculation/monthly/initialized_month.rb +120 -0
  16. data/lib/zakuro/calculation/monthly/month.rb +184 -0
  17. data/lib/zakuro/calculation/monthly/month_label.rb +88 -0
  18. data/lib/zakuro/calculation/monthly/operated_month.rb +201 -0
  19. data/lib/zakuro/calculation/range/full_range.rb +210 -0
  20. data/lib/zakuro/calculation/range/operated_range.rb +134 -0
  21. data/lib/zakuro/calculation/range/operated_solar_terms.rb +201 -0
  22. data/lib/zakuro/calculation/range/transfer/western_date_allocation.rb +76 -0
  23. data/lib/zakuro/calculation/range/transfer/year_boundary.rb +142 -0
  24. data/lib/zakuro/calculation/specifier/single_day.rb +109 -0
  25. data/lib/zakuro/calculation/summary/single.rb +129 -0
  26. data/lib/zakuro/condition.rb +17 -13
  27. data/lib/zakuro/era/japan/gengou.rb +106 -0
  28. data/lib/zakuro/era/japan/gengou/parser.rb +167 -0
  29. data/lib/zakuro/era/japan/gengou/type.rb +178 -0
  30. data/lib/zakuro/era/japan/gengou/validator.rb +236 -0
  31. data/lib/zakuro/era/japan/reki.rb +91 -0
  32. data/lib/zakuro/era/{gengou → japan/yaml}/set-001-until-south.yaml +0 -0
  33. data/lib/zakuro/era/{gengou → japan/yaml}/set-002-from-north.yaml +0 -0
  34. data/lib/zakuro/era/{gengou → japan/yaml}/set-003-modern.yaml +1 -1
  35. data/lib/zakuro/era/western.rb +1 -1
  36. data/lib/zakuro/merchant.rb +2 -2
  37. data/lib/zakuro/operation/month/parser.rb +373 -0
  38. data/lib/zakuro/operation/month/type.rb +453 -0
  39. data/lib/zakuro/operation/month/validator.rb +802 -0
  40. data/lib/zakuro/operation/operation.rb +66 -0
  41. data/lib/zakuro/operation/yaml/month.yaml +6452 -0
  42. data/lib/zakuro/output/error.rb +7 -4
  43. data/lib/zakuro/output/logger.rb +50 -47
  44. data/lib/zakuro/output/response.rb +146 -143
  45. data/lib/zakuro/result/core.rb +52 -0
  46. data/lib/zakuro/result/data.rb +187 -0
  47. data/lib/zakuro/result/operation.rb +114 -0
  48. data/lib/zakuro/result/result.rb +37 -0
  49. data/lib/zakuro/{output → tools}/stringifier.rb +16 -9
  50. data/lib/zakuro/tools/typeof.rb +33 -0
  51. data/lib/zakuro/version.rb +1 -1
  52. data/lib/zakuro/version/abstract_version.rb +1 -1
  53. data/lib/zakuro/version/context.rb +23 -0
  54. data/lib/zakuro/version/senmyou/cycle/remainder.rb +63 -0
  55. data/lib/zakuro/version/senmyou/cycle/solar_term.rb +31 -0
  56. data/lib/zakuro/version/senmyou/monthly/lunar_phase.rb +186 -182
  57. data/lib/zakuro/version/senmyou/range/annual_range.rb +164 -0
  58. data/lib/zakuro/version/senmyou/senmyou.rb +10 -4
  59. data/lib/zakuro/version/senmyou/stella/lunar_orbit.rb +7 -7
  60. data/lib/zakuro/version/senmyou/stella/solar_average.rb +103 -138
  61. data/lib/zakuro/version/senmyou/stella/solar_location.rb +213 -0
  62. data/lib/zakuro/version/senmyou/stella/solar_orbit.rb +6 -191
  63. data/lib/zakuro/version/senmyou/stella/winter_solstice.rb +4 -4
  64. data/lib/zakuro/version/version_class_resolver.rb +62 -0
  65. data/lib/zakuro/version_factory.rb +3 -3
  66. metadata +49 -20
  67. data/lib/zakuro/cycle/abstract_remainder.rb +0 -457
  68. data/lib/zakuro/cycle/zodiac.rb +0 -103
  69. data/lib/zakuro/era/japan.rb +0 -660
  70. data/lib/zakuro/output/result.rb +0 -219
  71. data/lib/zakuro/version/senmyou/base/era.rb +0 -83
  72. data/lib/zakuro/version/senmyou/base/multi_gengou.rb +0 -98
  73. data/lib/zakuro/version/senmyou/base/multi_gengou_roller.rb +0 -205
  74. data/lib/zakuro/version/senmyou/base/remainder.rb +0 -60
  75. data/lib/zakuro/version/senmyou/base/solar_term.rb +0 -66
  76. data/lib/zakuro/version/senmyou/base/year.rb +0 -104
  77. data/lib/zakuro/version/senmyou/monthly/month.rb +0 -122
  78. data/lib/zakuro/version/senmyou/summary/annual_range.rb +0 -186
  79. data/lib/zakuro/version/senmyou/summary/full_range.rb +0 -216
  80. data/lib/zakuro/version/senmyou/summary/specifier.rb +0 -100
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ # :nodoc:
4
+ module Zakuro
5
+ # :nodoc:
6
+ module Calculation
7
+ # :nodoc:
8
+ module Monthly
9
+ #
10
+ # MonthLabel 月表示情報
11
+ #
12
+ class MonthLabel
13
+ # @return [True] 大の月(30日)
14
+ # @return [False] 小の月(29日)
15
+ attr_reader :is_many_days
16
+ # @return [Integer] 月(xx月のxx)
17
+ attr_reader :number
18
+ # @return [True] 閏月
19
+ # @return [False] 平月
20
+ attr_reader :leaped
21
+
22
+ # :reek:ControlParameter and :reek:BooleanParameter
23
+
24
+ #
25
+ # 初期化
26
+ #
27
+ # @param [Integer] number 月(xx月のxx)
28
+ # @param [True, False] is_many_days 月の大小
29
+ # @param [True, False] leaped 閏月/平月
30
+ #
31
+ def initialize(number: -1, is_many_days: false, leaped: false)
32
+ # 月の大小
33
+ @is_many_days = is_many_days
34
+ # 月
35
+ @number = number
36
+ # 閏
37
+ @leaped = leaped
38
+ end
39
+
40
+ #
41
+ # 月の日数を返す
42
+ #
43
+ # @return [Integer] 日数
44
+ #
45
+ def days
46
+ @is_many_days ? 30 : 29
47
+ end
48
+
49
+ #
50
+ # 月の名前(大小)を返す
51
+ #
52
+ # @return [String] 月の名前(大小)
53
+ #
54
+ def days_name
55
+ @is_many_days ? '大' : '小'
56
+ end
57
+
58
+ #
59
+ # 一ヶ月戻す
60
+ #
61
+ # @return [True] 昨年
62
+ # @return [False] 今年
63
+ #
64
+ def back_to_last_month
65
+ @number -= 1
66
+
67
+ return false if @number.positive?
68
+
69
+ @number = 12
70
+
71
+ true
72
+ end
73
+
74
+ #
75
+ # 同一の月情報かを検証する
76
+ #
77
+ # @param [Month] other 他の月情報
78
+ #
79
+ # @return [True] 同一の月
80
+ # @return [False] 異なる月
81
+ #
82
+ def same?(other:)
83
+ @number == other.number && @leaped == other.leaped
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,201 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative './month'
4
+ require_relative '../../operation/operation'
5
+
6
+ # :nodoc:
7
+ module Zakuro
8
+ # :nodoc:
9
+ module Calculation
10
+ # :nodoc:
11
+ module Monthly
12
+ # :reek:TooManyInstanceVariables { max_instance_variables: 5 }
13
+
14
+ #
15
+ # OperatedMonth 月情報(運用)
16
+ #
17
+ class OperatedMonth < Month
18
+ # @return [Operation::MonthHistory] 変更履歴(月)
19
+ attr_reader :history
20
+ # @return [OperatedSolarTerms] 運用時二十四節気
21
+ attr_reader :operated_solar_terms
22
+
23
+ #
24
+ # 初期化
25
+ #
26
+ # @param [OperatedSolarTerms] operated_solar_terms 運用時二十四節気
27
+ # @param [MonthLabel] month_label 月表示名
28
+ # @param [FirstDay] first_day 月初日(朔日)
29
+ # @param [Array<SolarTerm>] solar_terms 二十四節気
30
+ # @param [Operation::MonthHistory] history 変更履歴(月)
31
+ #
32
+ def initialize(operated_solar_terms:, month_label: MonthLabel.new, first_day: FirstDay.new,
33
+ solar_terms: [], history: Operation::MonthHistory.new)
34
+ super(month_label: month_label, first_day: first_day, solar_terms: solar_terms)
35
+ @history = history
36
+ @operated_solar_terms = operated_solar_terms
37
+ end
38
+
39
+ #
40
+ # 書き換える
41
+ #
42
+ def rewrite
43
+ rewrite_month
44
+ rewrite_solar_terms
45
+ rewrite_first_day
46
+ end
47
+
48
+ #
49
+ # 月ごとの差分で書き換える
50
+ #
51
+ def rewrite_month
52
+ diff = history.diffs.month
53
+
54
+ @month_label = MonthLabel.new(
55
+ number: OperatedMonth.rewrite_month_fields(
56
+ month_diff: diff, month_label: month_label, name: 'number'
57
+ ),
58
+ is_many_days: OperatedMonth.rewrite_month_fields(
59
+ month_diff: diff, month_label: month_label, name: 'is_many_days'
60
+ ),
61
+ leaped: OperatedMonth.rewrite_month_fields(
62
+ month_diff: diff, month_label: month_label, name: 'leaped'
63
+ )
64
+ )
65
+ end
66
+
67
+ def self.rewrite_month_fields(month_diff:, month_label:, name:)
68
+ method_name = name.intern
69
+
70
+ diff = month_diff.send(method_name)
71
+ default = month_label.send(method_name)
72
+ return default if diff.invalid?
73
+
74
+ diff.actual
75
+ end
76
+
77
+ #
78
+ # 二十四節気ごとの差分で書き換える
79
+ #
80
+ def rewrite_solar_terms
81
+ matched, operated_solar_term = @operated_solar_terms.get(
82
+ western_date: first_day.western_date
83
+ )
84
+
85
+ return unless matched
86
+
87
+ @solar_terms = OperatedMonth.create_operated_solar_terms(
88
+ operated_solar_term: operated_solar_term,
89
+ solar_terms: solar_terms
90
+ )
91
+ end
92
+
93
+ #
94
+ # <Description>
95
+ #
96
+ # @param [<Type>] operated_solar_term <description>
97
+ # @param [Array<SolarTerm>] solar_terms 二十四節気
98
+ #
99
+ # @return [Array<SolarTerm>] 二十四節気
100
+ #
101
+ def self.create_operated_solar_terms(operated_solar_term:, solar_terms:)
102
+ index = operated_solar_term.index
103
+
104
+ # 別の月に移動する二十四節気。割り当てない。
105
+ result = remove_solar_term(index: index, solar_terms: solar_terms)
106
+
107
+ return result if used_solar_term?(index: index, solar_terms: solar_terms)
108
+
109
+ result.push(operated_solar_term)
110
+
111
+ result
112
+ end
113
+
114
+ # :reek:ControlParameter
115
+
116
+ #
117
+ # 二十四節気が使用されているか
118
+ #
119
+ # @param [Integer] index 二十四節気番号
120
+ # @param [Array<SolarTerm>] solar_terms 二十四節気
121
+ #
122
+ # @return [True] 使用
123
+ # @return [False] 未使用
124
+ #
125
+ def self.used_solar_term?(index:, solar_terms:)
126
+ solar_terms.each do |solar_term|
127
+ return true if index == solar_term.index
128
+ end
129
+
130
+ false
131
+ end
132
+
133
+ # :reek:ControlParameter
134
+
135
+ #
136
+ # 対象の二十四節気を除外する
137
+ #
138
+ # @param [Integer] index 二十四節気番号
139
+ # @param [Array<SolarTerm>] solar_terms 二十四節気
140
+ #
141
+ # @return [Array<SolarTerm>] 二十四節気(対象除外済)
142
+ #
143
+ def self.remove_solar_term(index:, solar_terms:)
144
+ result = []
145
+ solar_terms.each do |solar_term|
146
+ next if index == solar_term.index
147
+
148
+ result.push(solar_term)
149
+ end
150
+
151
+ result
152
+ end
153
+
154
+ #
155
+ # 月初日ごとの差分で書き換える
156
+ #
157
+ def rewrite_first_day
158
+ diffs = @history.diffs
159
+ return if diffs.invalid_days?
160
+
161
+ days = diffs.days
162
+
163
+ @first_day = FirstDay.new(
164
+ western_date: rewrite_western_date(days: days),
165
+ remainder: rewrite_remainder(days: days)
166
+ )
167
+ end
168
+
169
+ #
170
+ # 月初日の大余小余を日差分で書き換える
171
+ #
172
+ # @param [Integer] days 日差分
173
+ #
174
+ # @return [Remainder] 月初日の大余小余
175
+ #
176
+ def rewrite_remainder(days:)
177
+ remainder = first_day.remainder.clone
178
+ remainder.add!(
179
+ Cycle::AbstractRemainder.new(day: days, minute: 0, second: 0)
180
+ )
181
+
182
+ remainder
183
+ end
184
+
185
+ #
186
+ # 月初日の西暦日を日差分で書き換える
187
+ #
188
+ # @param [Integer] days 日差分
189
+ #
190
+ # @return [Western::Calendar] 月初日の西暦日
191
+ #
192
+ def rewrite_western_date(days:)
193
+ western_date = first_day.western_date.clone
194
+ western_date += days
195
+
196
+ western_date
197
+ end
198
+ end
199
+ end
200
+ end
201
+ end
@@ -0,0 +1,210 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../era/western'
4
+ require_relative '../../output/logger'
5
+
6
+ require_relative '../base/multi_gengou_roller'
7
+ require_relative '../base/year'
8
+
9
+ require_relative './transfer/year_boundary'
10
+ require_relative './transfer/western_date_allocation'
11
+
12
+ # :nodoc:
13
+ module Zakuro
14
+ # :nodoc:
15
+ module Calculation
16
+ # :nodoc:
17
+ module Range
18
+ # :reek:TooManyInstanceVariables { max_instance_variables: 6 }
19
+
20
+ #
21
+ # FullRange 完全範囲
22
+ # ある日からある日の範囲を計算可能な年月範囲
23
+ # * 前提として元号年はその元号の開始年から数える
24
+ # * ある日の元号年を求める場合、その元号が含まれる最初の年まで遡る
25
+ # * 元号は一つとは限らない。南北朝などで二つある場合は、古い方の元号から求める
26
+ #
27
+ # NOTE: 割り当てた元号は年初を基準にした元号年である
28
+ # * 元旦を基準にした時の正しい元号を設定している
29
+ # * 引き当てたい日付が元旦ではない場合、その月日に従い元号を再度求める
30
+ # * この再計算が必要になるのは、元号が切り替わる年のみである
31
+ #
32
+ class FullRange
33
+ # @return [Western::Calendar] 開始日
34
+ attr_reader :start_date
35
+ # @return [Western::Calendar] 終了日
36
+ attr_reader :end_date
37
+ # @return [MultiGengouRoller] 改元処理
38
+ attr_reader :multi_gengou_roller
39
+ # @return [Western::Calendar] 最過去の元旦
40
+ attr_reader :new_year_date
41
+ # @return [Integer] 西暦年
42
+ attr_reader :western_year
43
+ # @return [Context] 暦コンテキスト
44
+ attr_reader :context
45
+
46
+ # @return [Output::Logger] ロガー
47
+ LOGGER = Output::Logger.new(location: 'full_range')
48
+
49
+ #
50
+ # 初期化
51
+ #
52
+ # @param [Context] context 暦コンテキスト
53
+ # @param [Western::Calendar] start_date 開始日
54
+ # @param [Western::Calendar] end_date 終了日
55
+ #
56
+ def initialize(context:, start_date: Western::Calendar.new, end_date: Western::Calendar.new)
57
+ @start_date = start_date
58
+ @end_date = end_date
59
+ return if invalid?
60
+
61
+ @context = context
62
+ @multi_gengou_roller = Base::MultiGengouRoller.new(
63
+ start_date: start_date, end_date: end_date
64
+ )
65
+ @new_year_date = @multi_gengou_roller.oldest_date.clone
66
+ @western_year = @new_year_date.year
67
+ end
68
+
69
+ #
70
+ # 無効か
71
+ #
72
+ # @return [True] 無効
73
+ # @return [False] 有効
74
+ #
75
+ def invalid?
76
+ @start_date.invalid?
77
+ end
78
+
79
+ #
80
+ # 完全範囲を取得する
81
+ #
82
+ # @return [Array<Year>] 完全範囲
83
+ #
84
+ def get
85
+ return [] if invalid?
86
+
87
+ years = Transfer::YearBoundary.get(
88
+ annual_ranges: annual_ranges
89
+ )
90
+ years = update_gengou(years: years)
91
+
92
+ Transfer::WesternDateAllocation.update_first_day(
93
+ years: years
94
+ )
95
+
96
+ years
97
+ end
98
+
99
+ # :reek:TooManyStatements { max_statements: 7 }
100
+
101
+ #
102
+ # 完全範囲内の年データを取得する
103
+ #
104
+ # @return [Array<Year>] 年データ(冬至基準)
105
+ #
106
+ def annual_ranges
107
+ oldest_date = @new_year_date
108
+ newest_date = @multi_gengou_roller.newest_date
109
+ annual_range = context.resolver.annual_range
110
+
111
+ years = []
112
+ ((oldest_date.year)..(newest_date.year + 2)).each do |year|
113
+ years.push(
114
+ annual_range.collect_annual_range_after_last_november_1st(
115
+ western_year: year
116
+ )
117
+ )
118
+ end
119
+
120
+ years
121
+ end
122
+
123
+ # :reek:TooManyStatements { max_statements: 8 }
124
+
125
+ #
126
+ # 完全範囲内の年データの元号を開始年基準で更新する
127
+ #
128
+ # @param [Array<Year>] years 年データ(元旦基準)
129
+ #
130
+ # @return [Array<Year>] 元号更新済み年データ(元旦基準)
131
+ #
132
+ def update_gengou(years:)
133
+ updated_years = []
134
+
135
+ nearest_end_date = choise_nearest_end_date
136
+
137
+ years.each do |year|
138
+ next_year(years: updated_years, year: year)
139
+
140
+ if @new_year_date > nearest_end_date
141
+ @multi_gengou_roller.transfer
142
+ nearest_end_date = choise_nearest_end_date
143
+ end
144
+ @multi_gengou_roller.next_year
145
+ end
146
+
147
+ updated_years
148
+ end
149
+
150
+ private
151
+
152
+ #
153
+ # 元号処理対象の年を進める
154
+ #
155
+ # @param [Array<Year>] years 元号処理済み年データ(元旦基準)
156
+ # @param [Year] year 元号処理前の年(元旦基準)
157
+ #
158
+ def next_year(years:, year:)
159
+ updated_year = update_year(year: year)
160
+
161
+ years.push(updated_year)
162
+
163
+ next_new_year_date(total_days: updated_year.total_days)
164
+
165
+ nil
166
+ end
167
+
168
+ #
169
+ # 年の元号を更新する
170
+ #
171
+ # @param [Year] year 元号処理前の年(元旦基準)
172
+ #
173
+ # @return [Year] 元号処理済の年(元旦基準)
174
+ #
175
+ def update_year(year:)
176
+ multi_gengou = @multi_gengou_roller.multi_gengou.clone
177
+
178
+ updated_year = Base::Year.new(
179
+ multi_gengou: multi_gengou, new_year_date: @new_year_date.clone,
180
+ months: year.months
181
+ )
182
+ updated_year.commit
183
+
184
+ updated_year
185
+ end
186
+
187
+ #
188
+ # 次の年に進める
189
+ #
190
+ # @param [Integer] total_days 年の日数
191
+ #
192
+ def next_new_year_date(total_days:)
193
+ @new_year_date += total_days
194
+ @multi_gengou_roller.next(days: total_days)
195
+
196
+ nil
197
+ end
198
+
199
+ #
200
+ # 現在日からみて直近の未来に対する元号の切替前日を求める
201
+ #
202
+ # @return [Western::Calendar] 元号の切替前日
203
+ #
204
+ def choise_nearest_end_date
205
+ @multi_gengou_roller.choise_nearest_end_date
206
+ end
207
+ end
208
+ end
209
+ end
210
+ end