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,802 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'yaml'
4
+ require_relative '../../era/western'
5
+
6
+ # :nodoc:
7
+ module Zakuro
8
+ #
9
+ # Operation 運用
10
+ #
11
+ module Operation
12
+ #
13
+ # Validator バリデーション
14
+ #
15
+ module Validator
16
+ #
17
+ # Types 型判定
18
+ #
19
+ module Types
20
+ EMPTY_STRING = '-'
21
+ BOOLEANS = %w[true false].freeze
22
+
23
+ #
24
+ # 有効文字列か
25
+ #
26
+ # @param [String] str 対象文字列
27
+ #
28
+ # @return [True] 有効
29
+ # @return [False] 無効
30
+ #
31
+ def self.string?(str: '')
32
+ return false if str == ''
33
+
34
+ return false unless str
35
+
36
+ str.is_a?(String)
37
+ end
38
+
39
+ #
40
+ # 有効文字列(空文字許容)か
41
+ #
42
+ # @param [String] str 対象文字列
43
+ #
44
+ # @return [True] 有効
45
+ # @return [False] 無効
46
+ #
47
+ def self.empiable_string?(str: '')
48
+ return false unless str
49
+
50
+ str.is_a?(String)
51
+ end
52
+
53
+ #
54
+ # 正数か
55
+ #
56
+ # @param [String] str 対象文字列
57
+ #
58
+ # @return [True] 正数
59
+ # @return [False] 負数
60
+ #
61
+ def self.positive?(str: '')
62
+ return true if str == EMPTY_STRING
63
+
64
+ return false unless str
65
+
66
+ /^[0-9]+$/.match?(str)
67
+ end
68
+
69
+ #
70
+ # 数値か
71
+ #
72
+ # @param [String] str 対象文字列
73
+ #
74
+ # @return [True] 数値
75
+ # @return [False] 非数値
76
+ #
77
+ def self.num?(str: '')
78
+ return true if str == EMPTY_STRING
79
+
80
+ return false unless str
81
+
82
+ /^[-0-9]+$/.match?(str)
83
+ end
84
+
85
+ #
86
+ # booleanか
87
+ #
88
+ # @param [String] str 対象文字列
89
+ #
90
+ # @return [True] boolean
91
+ # @return [False] 非boolean
92
+ #
93
+ def self.bool?(str: '')
94
+ BOOLEANS.include?(str)
95
+ end
96
+
97
+ #
98
+ # boolean(空許容)か
99
+ #
100
+ # @param [String] str 対象文字列
101
+ #
102
+ # @return [True] boolean
103
+ # @return [False] 非boolean
104
+ #
105
+ def self.empiable_bool?(str: '')
106
+ return true if str == EMPTY_STRING
107
+
108
+ bool?(str: str)
109
+ end
110
+
111
+ #
112
+ # 月差分か
113
+ #
114
+ # @param [String] str 対象文字列
115
+ #
116
+ # @return [True] 有効
117
+ # @return [False] 無効
118
+ #
119
+ def self.month_days?(str: '')
120
+ return true if str == EMPTY_STRING
121
+
122
+ return false unless str
123
+
124
+ /^[大小]$/.match?(str)
125
+ end
126
+
127
+ #
128
+ # 西暦日か
129
+ #
130
+ # @param [String] str 対象文字列
131
+ #
132
+ # @return [True] 有効
133
+ # @return [False] 無効
134
+ #
135
+ def self.western_date?(str: '')
136
+ return Western::Calendar.new if str == EMPTY_STRING
137
+
138
+ Western::Calendar.valid_date_string(str: str)
139
+ end
140
+ end
141
+
142
+ # :reek:TooManyInstanceVariables { max_instance_variables: 5 }
143
+
144
+ #
145
+ # MonthHistory 変更履歴
146
+ #
147
+ class MonthHistory
148
+ # @return [Integer] 連番
149
+ attr_reader :index
150
+ # @return [String] ID
151
+ attr_reader :id
152
+ # @return [String] 親ID
153
+ attr_reader :parend_id
154
+ # @return [String] 西暦日
155
+ attr_reader :western_date
156
+ # @return [String] 有効行
157
+ attr_reader :modified
158
+
159
+ #
160
+ # 初期化
161
+ #
162
+ # @param [Integer] index 連番
163
+ # @param [Hash<String, String>] yaml_hash yaml
164
+ # @option yaml_hash [String] :id ID
165
+ # @option yaml_hash [String] :parent_id 親ID
166
+ # @option yaml_hash [String] :western_date 西暦日
167
+ # @option yaml_hash [String] :modified 有効行
168
+ #
169
+ def initialize(index:, yaml_hash: {})
170
+ @index = index
171
+ @id = yaml_hash['id']
172
+ @parent_id = yaml_hash['parent_id']
173
+ @western_date = yaml_hash['western_date']
174
+ @modified = yaml_hash['modified']
175
+ end
176
+
177
+ # :reek:TooManyStatements { max_statements: 7 }
178
+
179
+ #
180
+ # 検証する
181
+ #
182
+ # @return [Array<String>] エラーメッセージ
183
+ #
184
+ def validate
185
+ failed = []
186
+
187
+ prefix = "[#{@index}] invalid"
188
+
189
+ failed.push("#{prefix} 'id'. #{@id}") unless id?
190
+
191
+ failed.push("#{prefix} 'parent_id'. #{@id}") unless parent_id?
192
+
193
+ failed.push("#{prefix} 'western_date'. #{@western_date}") unless western_date?
194
+
195
+ failed.push("#{prefix} 'modified'. #{@modified}") unless modified?
196
+
197
+ failed
198
+ end
199
+
200
+ def id?
201
+ Types.string?(str: @id)
202
+ end
203
+
204
+ def parent_id?
205
+ Types.string?(str: @parent_id)
206
+ end
207
+
208
+ def western_date?
209
+ Types.western_date?(str: @western_date)
210
+ end
211
+
212
+ def modified?
213
+ Types.bool?(str: @modified)
214
+ end
215
+ end
216
+
217
+ #
218
+ # Annotation 注釈
219
+ #
220
+ class Annotation
221
+ # @return [Integer] 連番
222
+ attr_reader :index
223
+ # @return [String] ID
224
+ attr_reader :id
225
+ # @return [String] 注釈内容
226
+ attr_reader :description
227
+ # @return [String] 補足
228
+ attr_reader :note
229
+
230
+ #
231
+ # 初期化
232
+ #
233
+ # @param [Integer] index 連番
234
+ # @param [Hash<String, String>] yaml_hash yaml
235
+ # @option yaml_hash [String] :id ID
236
+ # @option yaml_hash [String] :description 注釈内容
237
+ # @option yaml_hash [String] :note 補足
238
+ #
239
+ def initialize(index:, yaml_hash: {})
240
+ @index = index
241
+ @id = yaml_hash['id']
242
+ @description = yaml_hash['description']
243
+ @note = yaml_hash['note']
244
+ end
245
+
246
+ # :reek:TooManyStatements { max_statements: 6 }
247
+
248
+ #
249
+ # 検証する
250
+ #
251
+ # @return [Array<String>] エラーメッセージ
252
+ #
253
+ def validate
254
+ failed = []
255
+
256
+ prefix = "[#{@index}] invalid"
257
+
258
+ failed.push("#{prefix} 'id'. #{@id}") unless id?
259
+
260
+ failed.push("#{prefix} 'description'. #{@description}") unless description?
261
+
262
+ failed.push("#{prefix} 'note'. #{@note}") unless note?
263
+
264
+ failed
265
+ end
266
+
267
+ def id?
268
+ Types.string?(str: @id)
269
+ end
270
+
271
+ def description?
272
+ Types.empiable_string?(str: @description)
273
+ end
274
+
275
+ def note?
276
+ Types.string?(str: @note)
277
+ end
278
+ end
279
+
280
+ #
281
+ # Reference 参照
282
+ #
283
+ class Reference
284
+ # @return [Integer] 連番
285
+ attr_reader :index
286
+ # @return [String] 原文頁数
287
+ attr_reader :page
288
+ # @return [String] 原文注釈番号
289
+ attr_reader :number
290
+ # @return [String] 和暦日
291
+ attr_reader :japan_date
292
+
293
+ #
294
+ # 初期化
295
+ #
296
+ # @param [Integer] index 連番
297
+ # @param [Hash<String, String>] yaml_hash yaml
298
+ # @option yaml_hash [String] :page 原文頁数
299
+ # @option yaml_hash [String] :number 原文注釈番号
300
+ # @option yaml_hash [String] :japan_date 和暦日
301
+ #
302
+ def initialize(index:, yaml_hash: {})
303
+ @index = index
304
+ @page = yaml_hash['page']
305
+ @number = yaml_hash['number']
306
+ @japan_date = yaml_hash['japan_date']
307
+ end
308
+
309
+ # :reek:TooManyStatements { max_statements: 6 }
310
+
311
+ #
312
+ # 検証する
313
+ #
314
+ # @return [Array<String>] エラーメッセージ
315
+ #
316
+ def validate
317
+ failed = []
318
+
319
+ prefix = "[#{@index}] invalid"
320
+
321
+ failed.push("#{prefix} 'page'. #{@page}") unless page?
322
+
323
+ failed.push("#{prefix} 'number'. #{@number}") unless number?
324
+
325
+ failed.push("#{prefix} 'japan_date'. #{@japan_date}") unless japan_date?
326
+
327
+ failed
328
+ end
329
+
330
+ def page?
331
+ Types.positive?(str: @page)
332
+ end
333
+
334
+ def number?
335
+ Types.positive?(str: @number)
336
+ end
337
+
338
+ def japan_date?
339
+ Types.string?(str: @japan_date)
340
+ end
341
+ end
342
+
343
+ #
344
+ # Diffs 総差分
345
+ #
346
+ class Diffs
347
+ # @return [Integer] 連番
348
+ attr_reader :index
349
+ # @return [Hash] 月差分
350
+ attr_reader :month
351
+ # @return [Hash] 二十四節気差分
352
+ attr_reader :solar_term
353
+ # @return [String] 日差分
354
+ attr_reader :days
355
+
356
+ #
357
+ # 初期化
358
+ #
359
+ # @param [Integer] index 連番
360
+ # @param [Hash] yaml_hash yaml
361
+ # @option yaml_hash [Hash] :month 月差分
362
+ # @option yaml_hash [Hash] :solar_term 二十四節気差分
363
+ # @option yaml_hash [String] :days 日差分
364
+ #
365
+ def initialize(index:, yaml_hash: {})
366
+ @index = index
367
+ @month = Month.new(index: index, yaml_hash: yaml_hash['month'])
368
+ @solar_term = SolarTerm::Direction.new(index: index, yaml_hash: yaml_hash['solar_term'])
369
+ @days = yaml_hash['days']
370
+ end
371
+
372
+ # :reek:TooManyStatements { max_statements: 6 }
373
+
374
+ #
375
+ # 検証する
376
+ #
377
+ # @return [Array<String>] エラーメッセージ
378
+ #
379
+ def validate
380
+ failed = []
381
+
382
+ prefix = "[#{@index}] invalid"
383
+
384
+ failed += @month.validate
385
+
386
+ failed += @solar_term.validate
387
+
388
+ failed.push("#{prefix} 'days'. #{@days}") unless days?
389
+
390
+ failed
391
+ end
392
+
393
+ def days?
394
+ Types.num?(str: @days)
395
+ end
396
+ end
397
+
398
+ #
399
+ # Month 月
400
+ #
401
+ class Month
402
+ # @return [Integer] 連番
403
+ attr_reader :index
404
+ # @return [Hash] 月差分
405
+ attr_reader :number
406
+ # @return [Hash] 閏有無差分
407
+ attr_reader :leaped
408
+ # @return [String] 中気差分
409
+ attr_reader :days
410
+
411
+ #
412
+ # 初期化
413
+ #
414
+ # @param [Integer] index 連番
415
+ # @param [Hash<String, Object>] yaml_hash yaml
416
+ # @option yaml_hash [Hash] :number 月差分
417
+ # @option yaml_hash [Hash] :leaped 閏有無差分
418
+ # @option yaml_hash [String] :days 中気差分
419
+ #
420
+ def initialize(index:, yaml_hash: {})
421
+ @index = index
422
+ @number = Number.new(index: index, yaml_hash: yaml_hash['number'])
423
+ @leaped = Leaped.new(index: index, yaml_hash: yaml_hash['leaped'])
424
+ @days = Days.new(index: index, yaml_hash: yaml_hash['days'])
425
+ end
426
+
427
+ #
428
+ # 検証する
429
+ #
430
+ # @return [Array<String>] エラーメッセージ
431
+ #
432
+ def validate
433
+ failed = []
434
+
435
+ failed += @number.validate
436
+
437
+ failed += @leaped.validate
438
+
439
+ failed += @days.validate
440
+
441
+ failed
442
+ end
443
+ end
444
+
445
+ module SolarTerm
446
+ #
447
+ # Direction 二十四節気(移動)
448
+ #
449
+ class Direction
450
+ # @return [Integer] 連番
451
+ attr_reader :index
452
+ # @return [Source] 移動元
453
+ attr_reader :source
454
+ # @return [Destination] 移動先
455
+ attr_reader :destination
456
+ # @return [String] 中気差分
457
+ attr_reader :days
458
+
459
+ #
460
+ # 初期化
461
+ #
462
+ # @param [Integer] index 連番
463
+ # @param [Hash<String, Object>] yaml_hash yaml
464
+ # @option yaml_hash [Hash] :calc 移動元
465
+ # @option yaml_hash [Hash] :actual 移動先
466
+ # @option yaml_hash [String] :days 中気差分
467
+ #
468
+ def initialize(index:, yaml_hash: {})
469
+ @index = index
470
+ @source = Source.new(diff_index: index, yaml_hash: yaml_hash['calc'])
471
+ @destination = Destination.new(diff_index: index, yaml_hash: yaml_hash['actual'])
472
+ @days = yaml_hash['days']
473
+ end
474
+
475
+ def days?
476
+ Types.positive?(str: @days)
477
+ end
478
+
479
+ # :reek:TooManyStatements { max_statements: 6 }
480
+
481
+ #
482
+ # 検証する
483
+ #
484
+ # @return [Array<String>] エラーメッセージ
485
+ #
486
+ def validate
487
+ failed = []
488
+
489
+ prefix = "[#{index}][solar_term] invalid"
490
+
491
+ failed += @source.validate
492
+
493
+ failed += @destination.validate
494
+
495
+ failed.push("#{prefix} 'days'. #{@days}") unless days?
496
+
497
+ failed
498
+ end
499
+ end
500
+
501
+ #
502
+ # Source 二十四節気(移動元)
503
+ #
504
+ class Source
505
+ # @return [Integer] 連番
506
+ attr_reader :diff_index
507
+ # @return [String] 移動対象の二十四節気番号
508
+ attr_reader :index
509
+ # @return [String] 移動先の月初日
510
+ attr_reader :to
511
+ # @return [String] 十干十二支
512
+ attr_reader :zodiac_name
513
+
514
+ #
515
+ # 初期化
516
+ #
517
+ # @param [Integer] diff_index 連番
518
+ # @param [Hash<String, String>] yaml_hash yaml
519
+ # @option yaml_hash [String] :index 移動対象の二十四節気番号
520
+ # @option yaml_hash [String] :to 移動先の月初日
521
+ # @option yaml_hash [String] :zodiac_name 十干十二支
522
+ #
523
+ def initialize(diff_index:, yaml_hash: {})
524
+ @diff_index = diff_index
525
+ @index = yaml_hash['index']
526
+ @to = yaml_hash['to']
527
+ @zodiac_name = yaml_hash['zodiac_name']
528
+ end
529
+
530
+ # :reek:TooManyStatements { max_statements: 6 }
531
+
532
+ #
533
+ # 検証する
534
+ #
535
+ # @return [Array<String>] エラーメッセージ
536
+ #
537
+ def validate
538
+ failed = []
539
+
540
+ prefix = "[#{@diff_index}][solar_term.calc] invalid"
541
+
542
+ failed.push("#{prefix} 'index'. #{@index}") unless index?
543
+
544
+ failed.push("#{prefix} 'to'. #{@to}") unless to?
545
+
546
+ failed.push("#{prefix} 'zodiac_name'. #{@zodiac_name}") unless zodiac_name?
547
+
548
+ failed
549
+ end
550
+
551
+ def index?
552
+ Types.positive?(str: @index)
553
+ end
554
+
555
+ def to?
556
+ Types.western_date?(str: @to)
557
+ end
558
+
559
+ def zodiac_name?
560
+ Types.string?(str: @zodiac_name)
561
+ end
562
+ end
563
+
564
+ #
565
+ # Destination 二十四節気(移動先)
566
+ #
567
+ class Destination
568
+ # @return [Integer] 連番
569
+ attr_reader :diff_index
570
+ # @return [String] 移動対象の二十四節気番号
571
+ attr_reader :index
572
+ # @return [String] 移動元の月初日
573
+ attr_reader :from
574
+ # @return [String] 十干十二支
575
+ attr_reader :zodiac_name
576
+
577
+ #
578
+ # 初期化
579
+ #
580
+ # @param [Integer] diff_index 連番
581
+ # @param [Hash<String, String>] yaml_hash yaml
582
+ # @option yaml_hash [String] :index 移動対象の二十四節気番号
583
+ # @option yaml_hash [String] :from 移動元の月初日
584
+ # @option yaml_hash [String] :zodiac_name 十干十二支
585
+ #
586
+ def initialize(diff_index:, yaml_hash: {})
587
+ @diff_index = diff_index
588
+ @index = yaml_hash['index']
589
+ @from = yaml_hash['from']
590
+ @zodiac_name = yaml_hash['zodiac_name']
591
+ end
592
+
593
+ # :reek:TooManyStatements { max_statements: 6 }
594
+
595
+ #
596
+ # 検証する
597
+ #
598
+ # @return [Array<String>] エラーメッセージ
599
+ #
600
+ def validate
601
+ failed = []
602
+
603
+ prefix = "[#{@diff_index}][solar_term.actual] invalid"
604
+
605
+ failed.push("#{prefix} 'index'. #{@index}") unless index?
606
+
607
+ failed.push("#{prefix} 'from'. #{@from}") unless from?
608
+
609
+ failed.push("#{prefix} 'zodiac_name'. #{@zodiac_name}") unless zodiac_name?
610
+
611
+ failed
612
+ end
613
+
614
+ def index?
615
+ Types.positive?(str: @index)
616
+ end
617
+
618
+ def from?
619
+ Types.western_date?(str: @from)
620
+ end
621
+
622
+ def zodiac_name?
623
+ Types.string?(str: @zodiac_name)
624
+ end
625
+ end
626
+ end
627
+
628
+ #
629
+ # Number 月
630
+ #
631
+ class Number
632
+ NAME = 'number'
633
+
634
+ # @return [Integer] 連番
635
+ attr_reader :index
636
+ # @return [String] 計算
637
+ attr_reader :calc
638
+ # @return [String] 運用
639
+ attr_reader :actual
640
+
641
+ #
642
+ # 初期化
643
+ #
644
+ # @param [Integer] index 連番
645
+ # @param [Hash<String, String>] yaml_hash yaml
646
+ # @option yaml_hash [String] :calc 計算
647
+ # @option yaml_hash [String] :actual 運用
648
+ #
649
+ def initialize(index:, yaml_hash: {})
650
+ @index = index
651
+ @calc = yaml_hash['calc']
652
+ @actual = yaml_hash['actual']
653
+ end
654
+
655
+ #
656
+ # 検証する
657
+ #
658
+ # @return [Array<String>] エラーメッセージ
659
+ #
660
+ def validate
661
+ failed = []
662
+
663
+ prefix = "[#{@index}][#{NAME}] invalid"
664
+
665
+ failed.push("#{prefix} 'calc'. #{@calc}") unless calc?
666
+
667
+ failed.push("#{prefix} 'actual'. #{@actual}") unless actual?
668
+
669
+ failed
670
+ end
671
+
672
+ def calc?
673
+ Types.positive?(str: @calc)
674
+ end
675
+
676
+ def actual?
677
+ Types.positive?(str: @actual)
678
+ end
679
+ end
680
+
681
+ #
682
+ # Leaped 閏有無
683
+ #
684
+ class Leaped
685
+ NAME = 'leaped'
686
+
687
+ # @return [Integer] 連番
688
+ attr_reader :index
689
+ # @return [String] 計算
690
+ attr_reader :calc
691
+ # @return [String] 運用
692
+ attr_reader :actual
693
+
694
+ #
695
+ # 初期化
696
+ #
697
+ # @param [Integer] index 連番
698
+ # @param [Hash<String, String>] yaml_hash yaml
699
+ # @option yaml_hash [String] :calc 計算
700
+ # @option yaml_hash [String] :actual 運用
701
+ #
702
+ def initialize(index:, yaml_hash: {})
703
+ @index = index
704
+ @calc = yaml_hash['calc']
705
+ @actual = yaml_hash['actual']
706
+ end
707
+
708
+ #
709
+ # 検証する
710
+ #
711
+ # @return [Array<String>] エラーメッセージ
712
+ #
713
+ def validate
714
+ failed = []
715
+
716
+ prefix = "[#{@index}][#{NAME}] invalid"
717
+
718
+ failed.push("#{prefix} 'calc'. #{@calc}") unless calc?
719
+
720
+ failed.push("#{prefix} 'actual'. #{@actual}") unless actual?
721
+
722
+ failed
723
+ end
724
+
725
+ def calc?
726
+ Types.empiable_bool?(str: @calc)
727
+ end
728
+
729
+ def actual?
730
+ Types.empiable_bool?(str: @actual)
731
+ end
732
+ end
733
+
734
+ #
735
+ # Days 月日数(大小)
736
+ #
737
+ class Days
738
+ NAME = 'days'
739
+
740
+ # @return [Integer] 連番
741
+ attr_reader :index
742
+ # @return [String] 計算
743
+ attr_reader :calc
744
+ # @return [String] 運用
745
+ attr_reader :actual
746
+
747
+ #
748
+ # 初期化
749
+ #
750
+ # @param [Integer] index 連番
751
+ # @param [Hash<String, String>] yaml_hash yaml
752
+ # @option yaml_hash [String] :calc 計算
753
+ # @option yaml_hash [String] :actual 運用
754
+ #
755
+ def initialize(index:, yaml_hash: {})
756
+ @index = index
757
+ @calc = yaml_hash['calc']
758
+ @actual = yaml_hash['actual']
759
+ end
760
+
761
+ #
762
+ # 検証する
763
+ #
764
+ # @return [Array<String>] エラーメッセージ
765
+ #
766
+ def validate
767
+ failed = []
768
+
769
+ prefix = "[#{@index}][#{NAME}] invalid"
770
+
771
+ failed.push("#{prefix} 'calc'. #{@calc}") unless calc?
772
+
773
+ failed.push("#{prefix} 'actual'. #{@actual}") unless actual?
774
+
775
+ failed
776
+ end
777
+
778
+ def calc?
779
+ Types.month_days?(str: @calc)
780
+ end
781
+
782
+ def actual?
783
+ Types.month_days?(str: @actual)
784
+ end
785
+ end
786
+
787
+ # :reek:TooManyStatements { max_statements: 7 }
788
+
789
+ def self.run(yaml_hash: {})
790
+ failed = []
791
+ yaml_hash.each_with_index do |history, index|
792
+ failed += MonthHistory.new(index: index, yaml_hash: history).validate
793
+ failed += Annotation.new(index: index, yaml_hash: history).validate
794
+ failed += Reference.new(index: index, yaml_hash: history).validate
795
+ failed += Diffs.new(index: index, yaml_hash: history['diffs']).validate
796
+ end
797
+
798
+ failed
799
+ end
800
+ end
801
+ end
802
+ end