zakuro 0.0.3 → 0.1.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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +85 -43
  3. data/doc/operation.md +25 -0
  4. data/doc/operation/csv/month.csv +202 -0
  5. data/doc/operation/operation.xlsx +0 -0
  6. data/doc/operation/transfer.rb +73 -0
  7. data/lib/zakuro/era/japan/gengou.rb +106 -0
  8. data/lib/zakuro/era/japan/gengou/parser.rb +169 -0
  9. data/lib/zakuro/era/japan/gengou/type.rb +178 -0
  10. data/lib/zakuro/era/japan/gengou/validator.rb +234 -0
  11. data/lib/zakuro/era/japan/reki.rb +91 -0
  12. data/lib/zakuro/era/{gengou → japan/yaml}/set-001-until-south.yaml +0 -0
  13. data/lib/zakuro/era/{gengou → japan/yaml}/set-002-from-north.yaml +0 -0
  14. data/lib/zakuro/era/{gengou → japan/yaml}/set-003-modern.yaml +0 -0
  15. data/lib/zakuro/era/western.rb +1 -1
  16. data/lib/zakuro/operation/month/parser.rb +277 -0
  17. data/lib/zakuro/operation/month/type.rb +452 -0
  18. data/lib/zakuro/operation/month/validator.rb +498 -0
  19. data/lib/zakuro/operation/operation.rb +45 -0
  20. data/lib/zakuro/operation/yaml/month.yaml +6452 -0
  21. data/lib/zakuro/output/error.rb +2 -0
  22. data/lib/zakuro/output/logger.rb +2 -0
  23. data/lib/zakuro/output/response.rb +17 -15
  24. data/lib/zakuro/result/core.rb +52 -0
  25. data/lib/zakuro/result/data.rb +187 -0
  26. data/lib/zakuro/result/operation.rb +86 -0
  27. data/lib/zakuro/result/result.rb +37 -0
  28. data/lib/zakuro/{output → tools}/stringifier.rb +14 -7
  29. data/lib/zakuro/tools/typeof.rb +33 -0
  30. data/lib/zakuro/version.rb +1 -1
  31. data/lib/zakuro/version/senmyou/base/era.rb +1 -1
  32. data/lib/zakuro/version/senmyou/base/multi_gengou.rb +1 -1
  33. data/lib/zakuro/version/senmyou/base/multi_gengou_roller.rb +13 -1
  34. data/lib/zakuro/version/senmyou/base/solar_term.rb +10 -0
  35. data/lib/zakuro/version/senmyou/monthly/first_day.rb +44 -0
  36. data/lib/zakuro/version/senmyou/monthly/initialized_month.rb +48 -0
  37. data/lib/zakuro/version/senmyou/monthly/month.rb +127 -68
  38. data/lib/zakuro/version/senmyou/monthly/month_label.rb +87 -0
  39. data/lib/zakuro/version/senmyou/monthly/operated_month.rb +167 -0
  40. data/lib/zakuro/version/senmyou/{summary → range}/annual_range.rb +20 -23
  41. data/lib/zakuro/version/senmyou/{summary → range}/full_range.rb +102 -2
  42. data/lib/zakuro/version/senmyou/range/operated_range.rb +105 -0
  43. data/lib/zakuro/version/senmyou/range/operated_solar_terms.rb +163 -0
  44. data/lib/zakuro/version/senmyou/senmyou.rb +2 -2
  45. data/lib/zakuro/version/senmyou/{summary/specifier.rb → specifier/single_day_specifier.rb} +13 -14
  46. data/lib/zakuro/version/senmyou/stella/solar_average.rb +3 -7
  47. data/lib/zakuro/version/senmyou/summary/single.rb +71 -0
  48. data/lib/zakuro/version_factory.rb +1 -1
  49. metadata +35 -11
  50. data/lib/zakuro/era/japan.rb +0 -664
  51. data/lib/zakuro/output/result.rb +0 -225
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ # TODO: moduleでMonthly とする(全暦むけに共通化したあと)
4
+
5
+ # :nodoc:
6
+ module Zakuro
7
+ # :nodoc:
8
+ module Senmyou
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
@@ -0,0 +1,167 @@
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 Senmyou
10
+ #
11
+ # OperatedMonth 月情報(運用)
12
+ #
13
+ class OperatedMonth < Month
14
+ # @return [Operation::MonthHistory] 変更履歴(月)
15
+ attr_reader :history
16
+ # @return [OperatedSolarTerms] 運用時二十四節気
17
+ attr_reader :operated_solar_terms
18
+
19
+ #
20
+ # 初期化
21
+ #
22
+ # @param [MonthLabel] month_label 月表示名
23
+ # @param [FirstDay] first_day 月初日(朔日)
24
+ # @param [Array<SolarTerm>] solar_terms 二十四節気
25
+ # @param [Operation::MonthHistory] history 変更履歴(月)
26
+ #
27
+ def initialize(operated_solar_terms:, month_label: MonthLabel.new, first_day: FirstDay.new, solar_terms: [],
28
+ history: Operation::MonthHistory.new)
29
+ super(month_label: month_label, first_day: first_day, solar_terms: solar_terms)
30
+ @history = history
31
+ @operated_solar_terms = operated_solar_terms
32
+ end
33
+
34
+ #
35
+ # 書き換える
36
+ #
37
+ def rewrite
38
+ rewrite_month
39
+ rewrite_solar_terms
40
+ rewrite_first_day
41
+ end
42
+
43
+ #
44
+ # 月ごとの差分で書き換える
45
+ #
46
+ def rewrite_month
47
+ diff = history.diffs.month
48
+
49
+ @month_label = MonthLabel.new(
50
+ number: rewrite_number(diff: diff.number),
51
+ is_many_days: rewrite_many_days(diff: diff.days),
52
+ leaped: rewrite_leaped(diff: diff.leaped)
53
+ )
54
+ end
55
+
56
+ #
57
+ # 月ごとの差分(月)で書き換える
58
+ #
59
+ # @param [Operation::Number] diff 差分
60
+ #
61
+ # @return [Integer] 月
62
+ #
63
+ def rewrite_number(diff:)
64
+ return month_label.number if diff.invalid?
65
+
66
+ diff.actual
67
+ end
68
+
69
+ #
70
+ # 月ごとの差分(月の大小)で書き換える
71
+ #
72
+ # @param [Operation::Days] diff 差分
73
+ #
74
+ # @return [Integer] 月の大小
75
+ #
76
+ def rewrite_many_days(diff:)
77
+ return month_label.is_many_days if diff.invalid?
78
+
79
+ diff.many_days_actual?
80
+ end
81
+
82
+ #
83
+ # 月ごとの差分(閏有無)で書き換える
84
+ #
85
+ # @param [Operation::Days] diff 差分
86
+ #
87
+ # @return [True] 閏あり
88
+ # @return [False] 閏なし
89
+ #
90
+ def rewrite_leaped(diff:)
91
+ return month_label.leaped if diff.invalid?
92
+
93
+ diff.actual
94
+ end
95
+
96
+ #
97
+ # 二十四節気ごとの差分で書き換える
98
+ #
99
+ def rewrite_solar_terms
100
+ # TODO: リファクタリング
101
+ operated_solar_terms = []
102
+ matched, operated_solar_term = @operated_solar_terms.get(
103
+ western_date: @first_day.western_date
104
+ )
105
+
106
+ return unless matched
107
+
108
+ used = false
109
+ @solar_terms.each do |solar_term|
110
+ if operated_solar_term.index == solar_term.index
111
+ used = true
112
+ next
113
+ end
114
+
115
+ operated_solar_terms.push(solar_term)
116
+ end
117
+
118
+ operated_solar_terms.push(operated_solar_term) unless used
119
+
120
+ @solar_terms = operated_solar_terms
121
+ end
122
+
123
+ #
124
+ # 月初日ごとの差分で書き換える
125
+ #
126
+ def rewrite_first_day
127
+ diffs = @history.diffs
128
+ return if diffs.invalid_days?
129
+
130
+ days = diffs.days
131
+
132
+ @first_day = FirstDay.new(
133
+ western_date: rewrite_western_date(days: days),
134
+ remainder: rewrite_remainder(days: days)
135
+ )
136
+ end
137
+
138
+ #
139
+ # 月初日の大余小余を日差分で書き換える
140
+ #
141
+ # @param [Integer] days 日差分
142
+ #
143
+ # @return [Remainder] 月初日の大余小余
144
+ #
145
+ def rewrite_remainder(days:)
146
+ remainder = @first_day.remainder.clone
147
+ remainder.add!(Remainder.new(day: days, minute: 0, second: 0))
148
+
149
+ remainder
150
+ end
151
+
152
+ #
153
+ # 月初日の西暦日を日差分で書き換える
154
+ #
155
+ # @param [Integer] days 日差分
156
+ #
157
+ # @return [Western::Calendar] 月初日の西暦日
158
+ #
159
+ def rewrite_western_date(days:)
160
+ western_date = @first_day.western_date.clone
161
+ western_date += days
162
+
163
+ western_date
164
+ end
165
+ end
166
+ end
167
+ end
@@ -2,7 +2,7 @@
2
2
 
3
3
  require_relative '../../../output/logger'
4
4
  require_relative '../base/remainder'
5
- require_relative '../monthly/month'
5
+ require_relative '../monthly/initialized_month'
6
6
  require_relative '../base/solar_term'
7
7
  require_relative '../monthly/lunar_phase'
8
8
  require_relative '../stella/solar_orbit'
@@ -13,7 +13,9 @@ require_relative '../stella/lunar_orbit'
13
13
  module Zakuro
14
14
  # :nodoc:
15
15
  module Senmyou
16
- # AnnualRange 年間データ
16
+ #
17
+ # AnnualRange 年間範囲
18
+ #
17
19
  module AnnualRange
18
20
  # @return [Logger] ロガー
19
21
  LOGGER = Logger.new(location: 'annual_range')
@@ -126,8 +128,9 @@ module Zakuro
126
128
  adjusted = lunar_phase.next_month
127
129
 
128
130
  result.push(
129
- Month.new(is_last_year: is_last_year, number: month,
130
- remainder: adjusted, phase_index: 0)
131
+ InitializedMonth.new(month_label: MonthLabel.new(number: month),
132
+ first_day: FirstDay.new(remainder: adjusted),
133
+ is_last_year: is_last_year, phase_index: 0)
131
134
  )
132
135
  is_last_year = false if month == 12
133
136
  end
@@ -141,14 +144,12 @@ module Zakuro
141
144
  # @param [Array<Month>] annual_range 1年データ
142
145
  #
143
146
  def self.apply_big_and_small_of_the_month(annual_range:)
144
- size = annual_range.size - 1
145
- (0...size).each do |idx|
146
- current_month = annual_range[idx]
147
- next_month = annual_range[idx + 1]
148
- current_month.is_many_days = \
149
- current_month.remainder.same_remainder_divided_by_ten?(
150
- other: next_month.remainder.day
151
- )
147
+ annual_range.each_with_index do |range, index|
148
+ # 最後は比較対象がないためスキップする(=計算外の余分な月が最後に必要である)
149
+ next if index == annual_range.size - 1
150
+
151
+ next_month = annual_range[index + 1]
152
+ range.eval_many_days(next_month_day: next_month.remainder.day)
152
153
  end
153
154
  end
154
155
  private_class_method :apply_big_and_small_of_the_month
@@ -165,20 +166,16 @@ module Zakuro
165
166
  # 閏による月の再調整を行う
166
167
  leaped = false
167
168
  annual_range.each_with_index do |month, index|
168
- if month.even_term.invalid?
169
- month.leaped = true
170
- # NOTE: 初回閏月(閏11月)は前回月が存在しないため調整外
171
- leaped = true unless index.zero?
172
- end
169
+ month.eval_leaped
170
+ # NOTE: 初回閏月(閏11月)は前回月が存在しないため調整外
171
+ leaped = true if month.leaped? && !index.zero?
172
+
173
173
  next unless leaped
174
174
 
175
175
  # NOTE: 常気法では閏月は2-3年に一度のため、1年に二度発生しない前提
176
- number = month.number - 1
177
- if number <= 0
178
- month.is_last_year = true
179
- number = 12
180
- end
181
- month.number = number
176
+
177
+ # 閏の分だけ1ヶ月ずらす
178
+ month.back_to_last_month
182
179
  end
183
180
  end
184
181
  private_class_method :adjust_leap_month
@@ -5,6 +5,8 @@ require_relative '../base/multi_gengou_roller'
5
5
  require_relative '../../../era/western'
6
6
  require_relative './annual_range'
7
7
 
8
+ require_relative '../base/year'
9
+
8
10
  # :nodoc:
9
11
  module Zakuro
10
12
  # :nodoc:
@@ -20,25 +22,82 @@ module Zakuro
20
22
  # * 引き当てたい日付が元旦ではない場合、その月日に従い元号を再度求める
21
23
  # * この再計算が必要になるのは、元号が切り替わる年のみである
22
24
  class FullRange
23
- attr_reader :multi_gengou_roller, :new_year_date, :western_year
25
+ # @return [Western::Calendar] 開始日
26
+ attr_reader :start_date
27
+ # @return [Western::Calendar] 終了日
28
+ attr_reader :end_date
29
+ # @return [MultiGengouRoller] 改元処理
30
+ attr_reader :multi_gengou_roller
31
+ # @return [Western::Calendar] 最過去の元旦
32
+ attr_reader :new_year_date
33
+ # @return [Integer] 西暦年
34
+ attr_reader :western_year
24
35
 
25
36
  # @return [Logger] ロガー
26
37
  LOGGER = Logger.new(location: 'full_range')
27
38
 
39
+ #
40
+ # 初期化
41
+ #
42
+ # @param [Western::Calendar] start_date 開始日
43
+ # @param [Western::Calendar] end_date 終了日
44
+ #
28
45
  def initialize(start_date: Western::Calendar.new, end_date: Western::Calendar.new)
46
+ @start_date = start_date
47
+ @end_date = end_date
48
+ return if invalid?
49
+
29
50
  @multi_gengou_roller = MultiGengouRoller.new(start_date: start_date, end_date: end_date)
30
51
  @new_year_date = @multi_gengou_roller.oldest_date.clone
31
52
  @western_year = @new_year_date.year
32
53
  end
33
54
 
55
+ #
56
+ # 無効か
57
+ #
58
+ # @return [True] 無効
59
+ # @return [False] 有効
60
+ #
61
+ def invalid?
62
+ @start_date.invalid?
63
+ end
64
+
34
65
  #
35
66
  # 完全範囲を取得する
36
67
  #
37
68
  # @return [Array<Year>] 完全範囲
38
69
  #
39
70
  def get
71
+ return [] if invalid?
72
+
73
+ pre_get
74
+
40
75
  years = FullRange.rearranged_years(annual_ranges: annual_ranges)
41
- update_gengou(years: years)
76
+ years = update_gengou(years: years)
77
+ years = update_first_day(years: years)
78
+
79
+ post_get
80
+
81
+ years
82
+ end
83
+
84
+ #
85
+ # 取得前処理
86
+ #
87
+ def pre_get
88
+ # FIXME: 別インスタンス変数を定義する方法は改善したい(ディープコピーにするか、get再取得を廃止するか)
89
+ @new_year_date_ = @new_year_date.clone
90
+ @multi_gengou_roller_ = @multi_gengou_roller.clone
91
+ end
92
+
93
+ #
94
+ # 取得前処理
95
+ #
96
+ # 再取得に備えて、カウントアップした日付を元に戻す
97
+ #
98
+ def post_get
99
+ @new_year_date = @new_year_date_
100
+ @multi_gengou_roller = @multi_gengou_roller_
42
101
  end
43
102
 
44
103
  # :reek:TooManyStatements { max_statements: 6 }
@@ -109,6 +168,47 @@ module Zakuro
109
168
  updated_years
110
169
  end
111
170
 
171
+ #
172
+ # 月初日の西暦日を更新する
173
+ #
174
+ # @param [Array<Year>] years 完全範囲(月初日なし)
175
+ #
176
+ # @return [Array<Year>] 完全範囲(月初日あり)
177
+ #
178
+ def update_first_day(years:)
179
+ # TODO: リファクタリング
180
+
181
+ result = []
182
+
183
+ years.each do |year|
184
+ new_year_date = year.new_year_date.clone
185
+ date = new_year_date.clone
186
+
187
+ months = []
188
+ year.months.each do |month|
189
+ first_day = month.first_day
190
+ updated_month = Month.new(
191
+ month_label: month.month_label,
192
+ first_day: FirstDay.new(remainder: first_day.remainder,
193
+ western_date: date),
194
+ solar_terms: month.solar_terms
195
+ )
196
+ months.push(updated_month)
197
+
198
+ date = date.clone + updated_month.days
199
+ end
200
+
201
+ updated_year = Year.new(
202
+ multi_gengou: year.multi_gengou, new_year_date: new_year_date,
203
+ months: months, total_days: year.total_days
204
+ )
205
+
206
+ result.push(updated_year)
207
+ end
208
+
209
+ result
210
+ end
211
+
112
212
  #
113
213
  # 当年データを生成する
114
214
  #