zakuro 0.0.2 → 0.1.3

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 (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,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../western'
4
+
5
+ # :nodoc:
6
+ module Zakuro
7
+ #
8
+ # Japan 和暦
9
+ #
10
+ module Japan
11
+ #
12
+ # Reki 暦
13
+ #
14
+ module Reki
15
+ #
16
+ # Range 暦(範囲)
17
+ #
18
+ class Range
19
+ # @return [String] 暦のクラス名
20
+ # version 以下を参照
21
+ attr_reader :class_name
22
+ # @return [Western::Calendar] 暦の開始日
23
+ attr_reader :start_date
24
+
25
+ #
26
+ # 初期化
27
+ #
28
+ # @param [String] class_name 暦のクラス名
29
+ # @param [Western::Calendar] start_date 暦の開始日
30
+ #
31
+ def initialize(class_name:, start_date:)
32
+ @class_name = class_name
33
+ @start_date = start_date
34
+ end
35
+ end
36
+
37
+ LIST = [
38
+ Range.new(
39
+ class_name: 'Zakuro::Genka::Gateway',
40
+ start_date: Western::Calendar.new(year: 445, month: 1, day: 24)
41
+ ),
42
+ Range.new(
43
+ class_name: 'Zakuro::Gihou::Gateway',
44
+ start_date: Western::Calendar.new(year: 698, month: 2, day: 16)
45
+ ),
46
+ Range.new(
47
+ class_name: 'Zakuro::Taien::Gateway',
48
+ start_date: Western::Calendar.new(year: 764, month: 2, day: 7)
49
+ ),
50
+ Range.new(
51
+ class_name: 'Zakuro::Senmyou::Gateway',
52
+ start_date: Western::Calendar.new(year: 862, month: 2, day: 3)
53
+ ),
54
+ Range.new(
55
+ class_name: 'Zakuro::Joukyou::Gateway',
56
+ start_date: Western::Calendar.new(year: 1685, month: 2, day: 4)
57
+ ),
58
+ Range.new(
59
+ class_name: 'Zakuro::Houryaku::Gateway',
60
+ start_date: Western::Calendar.new(year: 1755, month: 2, day: 11)
61
+ ),
62
+ Range.new(
63
+ class_name: 'Zakuro::Kansei::Gateway',
64
+ start_date: Western::Calendar.new(year: 1798, month: 2, day: 16)
65
+ ),
66
+ Range.new(
67
+ class_name: 'Zakuro::Tenpou::Gateway',
68
+ start_date: Western::Calendar.new(year: 1844, month: 2, day: 18)
69
+ ),
70
+ Range.new(
71
+ class_name: 'Zakuro::Gregorio::Gateway',
72
+ start_date: Western::Calendar.new(year: 1872, month: 12, day: 9)
73
+ )
74
+ ].freeze
75
+
76
+ #
77
+ # 指定した日付から対象の暦を引き当てる
78
+ #
79
+ # @param [Western::Calendar] date 日付
80
+ #
81
+ # @return [String] 暦のクラス名
82
+ #
83
+ def self.class_name(date: Western::Calendar.new)
84
+ LIST.reverse_each do |range|
85
+ return range.class_name if date >= range.start_date
86
+ end
87
+ raise ArgumentError, "invalid date: #{date.format}"
88
+ end
89
+ end
90
+ end
91
+ end
@@ -21,7 +21,7 @@ list:
21
21
  new_year_date: "1926-1-1"
22
22
  note: ""
23
23
  - name: "令和"
24
- # -
24
+ # 1年5月1日
25
25
  start_year: 1
26
26
  start_date: "2019-5-1"
27
27
  new_year_date: "2019-1-1"
@@ -109,7 +109,7 @@ module Zakuro
109
109
  end
110
110
  end
111
111
 
112
- # :reek:TooManyMethods { max_methods: 17 }
112
+ # :reek:TooManyMethods { max_methods: 18 }
113
113
 
114
114
  #
115
115
  # Calendar 年月日情報(西暦)
@@ -22,7 +22,7 @@ module Zakuro
22
22
  #
23
23
  def initialize(condition: {})
24
24
  failed = Condition.validate(hash: condition)
25
- raise ZakuroError, failed.join('\n') unless failed.empty?
25
+ raise Output::ZakuroError, failed.join('\n') unless failed.empty?
26
26
 
27
27
  @condition = Condition.new(hash: condition)
28
28
  end
@@ -36,7 +36,7 @@ module Zakuro
36
36
  #
37
37
  def offer(condition: {})
38
38
  failed = Condition.validate(hash: condition)
39
- raise ZakuroError, failed.join('\n') unless failed.empty?
39
+ raise Output::ZakuroError, failed.join('\n') unless failed.empty?
40
40
 
41
41
  @condition.rewrite(hash: condition)
42
42
 
@@ -0,0 +1,373 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'yaml'
4
+ require_relative '../../era/western'
5
+ require_relative './validator'
6
+ require_relative './type'
7
+
8
+ # :nodoc:
9
+ module Zakuro
10
+ #
11
+ # Operation 運用
12
+ #
13
+ module Operation
14
+ #
15
+ # TypeParser 型ごと変換
16
+ #
17
+ module TypeParser
18
+ #
19
+ # 無効値かを判定する
20
+ #
21
+ # @param [String] str 文字列
22
+ #
23
+ # @return [True] 無効値
24
+ # @return [False] 有効値
25
+ #
26
+ def self.invalid?(str:)
27
+ str == '-'
28
+ end
29
+
30
+ def self.text(str:)
31
+ return '' if invalid?(str: str)
32
+
33
+ str
34
+ end
35
+
36
+ #
37
+ # 有効行を変換する
38
+ #
39
+ # @param [String] str 文字列
40
+ #
41
+ # @return [True] 有効
42
+ # @return [False] 無効
43
+ #
44
+ def self.modified?(str:)
45
+ str == 'true'
46
+ end
47
+
48
+ #
49
+ # 月を変換する
50
+ #
51
+ # @param [String] str 文字列
52
+ #
53
+ # @return [Integer] 月
54
+ #
55
+ def self.month_number(str:)
56
+ return -1 if invalid?(str: str)
57
+
58
+ str.to_i
59
+ end
60
+
61
+ #
62
+ # 閏有無を変換する
63
+ #
64
+ # @param [String] str 文字列
65
+ #
66
+ # @return [True] 閏あり
67
+ # @return [True] 閏なし/閏設定なし
68
+ #
69
+ def self.month_leaped(str:)
70
+ str == 'true'
71
+ end
72
+
73
+ #
74
+ # 西暦日を変換する
75
+ #
76
+ # @param [String] str 文字列
77
+ #
78
+ # @return [Western::Calendar] 西暦日
79
+ #
80
+ def self.western_date(str:)
81
+ return Western::Calendar.new if invalid?(str: str)
82
+
83
+ Western::Calendar.parse(str: str)
84
+ end
85
+
86
+ #
87
+ # 日(差分)を変換する
88
+ #
89
+ # @param [String] str 文字列
90
+ #
91
+ # @return [Integer] 日(差分)
92
+ #
93
+ def self.days(str:)
94
+ return INVALID_DAY_VALUE if invalid?(str: str)
95
+
96
+ str.to_i
97
+ end
98
+
99
+ def self.solar_term_index(str:)
100
+ return -1 if invalid?(str: str)
101
+
102
+ str.to_i
103
+ end
104
+ end
105
+
106
+ #
107
+ # MonthParser 月情報解析(yaml)
108
+ #
109
+ module MonthParser
110
+ #
111
+ # 実行する
112
+ #
113
+ # @return [Array<MonthHistory>] 変更履歴
114
+ #
115
+ def self.run(filepath:)
116
+ hash = YAML.load_file(filepath)
117
+
118
+ failed = Validator.run(yaml_hash: hash)
119
+
120
+ raise ArgumentError, failed.join("\n") unless failed.empty?
121
+
122
+ load(yaml_hash: hash)
123
+ end
124
+
125
+ #
126
+ # 設定ファイルを読み込む
127
+ #
128
+ # @param [Hash] yaml_hash 設定ファイルテキスト
129
+ #
130
+ # @return [Array<MonthHistory>] 変更履歴
131
+ #
132
+ def self.load(yaml_hash: {})
133
+ histories = create_histories(yaml_hash: yaml_hash)
134
+
135
+ annotation_parser = AnnotationParser.new(yaml_hash: yaml_hash)
136
+ annotation_parser.create
137
+
138
+ add_annotations(histories: histories, annotation_parser: annotation_parser)
139
+ end
140
+
141
+ #
142
+ # 変更履歴を読み込む
143
+ #
144
+ # @param [Hash] yaml_hash 設定ファイルテキスト
145
+ #
146
+ # @return [Array<MonthHistory>] 変更履歴
147
+ #
148
+ def self.create_histories(yaml_hash: {})
149
+ result = []
150
+ yaml_hash.each do |month|
151
+ next unless Operation::TypeParser.modified?(str: month['modified'])
152
+
153
+ result.push(
154
+ create_history(yaml_hash: month)
155
+ )
156
+ end
157
+ result
158
+ end
159
+ private_class_method :create_histories
160
+
161
+ def self.create_history(yaml_hash: {})
162
+ diffs = MonthDiffsParser.create(yaml_hash: yaml_hash['diffs'])
163
+
164
+ western_date = Operation::TypeParser.western_date(str: yaml_hash['western_date'])
165
+ reference = Reference.new(page: yaml_hash['page'].to_i, number: yaml_hash['number'].to_i,
166
+ japan_date: yaml_hash['japan_date'])
167
+ MonthHistory.new(id: yaml_hash['id'],
168
+ parent_id: Operation::TypeParser.text(str: yaml_hash['parent_id']),
169
+ reference: reference,
170
+ western_date: western_date,
171
+ diffs: diffs)
172
+ end
173
+ private_class_method :create_history
174
+
175
+ def self.add_annotations(annotation_parser:, histories: [])
176
+ result = []
177
+ histories.each do |history|
178
+ id = history.id
179
+ result.push(
180
+ MonthHistory.new(
181
+ id: id, parent_id: history.parent_id, reference: history.reference,
182
+ western_date: history.western_date,
183
+ annotations: annotation_parser.specify(id: id),
184
+ diffs: history.diffs
185
+ )
186
+ )
187
+ end
188
+
189
+ result
190
+ end
191
+ private_class_method :add_annotations
192
+
193
+ def self.create_history_annnotations(history:, annotations: {}, relations: {})
194
+ history_id = history.id
195
+ history_annotations = []
196
+ [history_id, relations.fetch(history_id, '')].each do |id|
197
+ add_annotation(history_annotations: history_annotations,
198
+ annotations: annotations, id: id)
199
+ end
200
+
201
+ history_annotations
202
+ end
203
+
204
+ def self.add_annotation(history_annotations: [], annotations: {}, id: '')
205
+ annotation = annotations.fetch(id, Annotation.new)
206
+ return if annotation.invalid?
207
+
208
+ history_annotations.push(annotation)
209
+ end
210
+ private_class_method :add_annotation
211
+ end
212
+
213
+ #
214
+ # AnnotationParser 注釈解析
215
+ #
216
+ class AnnotationParser
217
+ # @return [Hash<String, Annotation>] 注釈
218
+ attr_reader :annotations
219
+ # @return [Hash<String, String>] 関連注釈の対応関係
220
+ attr_reader :relations
221
+
222
+ #
223
+ # 初期化
224
+ #
225
+ # @param [Hash] yaml_hash 設定ファイルテキスト
226
+ #
227
+ def initialize(yaml_hash: {})
228
+ @annotations = {}
229
+ @relations = {}
230
+ @yaml_hash = yaml_hash
231
+ end
232
+
233
+ #
234
+ # 注釈を生成する
235
+ #
236
+ def create
237
+ @yaml_hash.each do |month|
238
+ AnnotationParser.resolve_history(
239
+ hash: month, annotations: @annotations, relations: @relations
240
+ )
241
+ end
242
+ end
243
+
244
+ #
245
+ # 月別履歴情報から注釈情報を取り出す
246
+ #
247
+ # @param [<Type>] hash 月別履歴情報yaml
248
+ # @param [Hash<String, Annotation>] annotations 注釈
249
+ # @param [Hash<String, String>] relations 関連注釈の対応関係
250
+ #
251
+ def self.resolve_history(hash: {}, annotations: {}, relations: {})
252
+ id = hash['id']
253
+ annotations[id] = Annotation.new(
254
+ id: id,
255
+ description: Operation::TypeParser.text(str: hash['description']),
256
+ note: Operation::TypeParser.text(str: hash['note'])
257
+ )
258
+ relation_id = hash['relation_id']
259
+
260
+ return if Operation::TypeParser.invalid?(str: relation_id)
261
+
262
+ relations[id] = relation_id
263
+ end
264
+
265
+ #
266
+ # 注釈を特定する
267
+ #
268
+ # @param [String] id ID
269
+ #
270
+ # @return [Array<Annotation>] 注釈
271
+ #
272
+ def specify(id: '')
273
+ ids = [id, relations.fetch(id, '')]
274
+ specify_by_ids(ids: ids)
275
+ end
276
+
277
+ private
278
+
279
+ def specify_by_ids(ids: [])
280
+ annotations = []
281
+ ids.each do |id|
282
+ add_annotation(id: id, annotations: annotations)
283
+ end
284
+
285
+ annotations
286
+ end
287
+
288
+ def add_annotation(id: '', annotations: [])
289
+ annotation = annotation(id: id)
290
+ return if annotation.invalid?
291
+
292
+ annotations.push(annotation)
293
+ end
294
+
295
+ def annotation(id: '')
296
+ @annotations.fetch(id, Annotation.new)
297
+ end
298
+ end
299
+
300
+ #
301
+ # MonthDiffsParser 月情報(差分)解析
302
+ #
303
+ module MonthDiffsParser
304
+ def self.create(yaml_hash: {})
305
+ Diffs.new(
306
+ month: create_month(yaml_hash: yaml_hash['month']),
307
+ solar_term: create_solar_term(yaml_hash: yaml_hash['solar_term']),
308
+ days: Operation::TypeParser.days(str: yaml_hash['days'])
309
+ )
310
+ end
311
+
312
+ def self.create_solar_term(yaml_hash: {})
313
+ SolarTerm::Direction.new(
314
+ source: create_source_solar_term(yaml_hash: yaml_hash['calc']),
315
+ destination: create_destination_solar_term(yaml_hash: yaml_hash['actual']),
316
+ days: Operation::TypeParser.days(str: yaml_hash['days'])
317
+ )
318
+ end
319
+ private_class_method :create_solar_term
320
+
321
+ def self.create_source_solar_term(yaml_hash: {})
322
+ SolarTerm::Source.new(
323
+ index: Operation::TypeParser.solar_term_index(str: yaml_hash['index']),
324
+ to: Operation::TypeParser.western_date(str: yaml_hash['to']),
325
+ zodiac_name: Operation::TypeParser.text(str: yaml_hash['zodiac_name'])
326
+ )
327
+ end
328
+ private_class_method :create_source_solar_term
329
+
330
+ def self.create_destination_solar_term(yaml_hash: {})
331
+ SolarTerm::Destination.new(
332
+ index: Operation::TypeParser.solar_term_index(str: yaml_hash['index']),
333
+ from: Operation::TypeParser.western_date(str: yaml_hash['from']),
334
+ zodiac_name: Operation::TypeParser.text(str: yaml_hash['zodiac_name'])
335
+ )
336
+ end
337
+ private_class_method :create_destination_solar_term
338
+
339
+ def self.create_month(yaml_hash: {})
340
+ Month.new(
341
+ number: create_month_number(yaml_hash: yaml_hash['number']),
342
+ leaped: create_month_leaped(yaml_hash: yaml_hash['leaped']),
343
+ is_many_days: create_month_day(yaml_hash: yaml_hash['days'])
344
+ )
345
+ end
346
+ private_class_method :create_month
347
+
348
+ def self.create_month_number(yaml_hash: {})
349
+ Number.new(
350
+ calc: Operation::TypeParser.month_number(str: yaml_hash['calc']),
351
+ actual: Operation::TypeParser.month_number(str: yaml_hash['actual'])
352
+ )
353
+ end
354
+ private_class_method :create_month_number
355
+
356
+ def self.create_month_leaped(yaml_hash: {})
357
+ Leaped.new(
358
+ calc: Operation::TypeParser.month_leaped(str: yaml_hash['calc']),
359
+ actual: Operation::TypeParser.month_leaped(str: yaml_hash['actual'])
360
+ )
361
+ end
362
+ private_class_method :create_month_leaped
363
+
364
+ def self.create_month_day(yaml_hash: {})
365
+ Days.new(
366
+ calc: yaml_hash['calc'],
367
+ actual: yaml_hash['actual']
368
+ )
369
+ end
370
+ private_class_method :create_month_day
371
+ end
372
+ end
373
+ end