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