zakuro 0.0.3 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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
  #