when_exe 0.4.1 → 0.4.2

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 (96) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +36 -33
  3. data/bin/locales.rb +1 -1
  4. data/bin/make_ttl.rb.config +1 -1
  5. data/lib/when_exe.rb +27 -16
  6. data/lib/when_exe/basictypes.rb +772 -771
  7. data/lib/when_exe/calendartypes.rb +1485 -1453
  8. data/lib/when_exe/coordinates.rb +5 -0
  9. data/lib/when_exe/core/compatibility.rb +1 -1
  10. data/lib/when_exe/core/duration.rb +147 -116
  11. data/lib/when_exe/core/extension.rb +499 -497
  12. data/lib/when_exe/ephemeris.rb +1952 -1951
  13. data/lib/when_exe/ephemeris/eclipse.rb +5 -4
  14. data/lib/when_exe/ephemeris/notes.rb +457 -421
  15. data/lib/when_exe/ephemeris/planets.rb +585 -585
  16. data/lib/when_exe/ephemeris/sun.rb +214 -214
  17. data/lib/when_exe/google_api.rb +153 -0
  18. data/lib/when_exe/icalendar.rb +1640 -1632
  19. data/lib/when_exe/inspect.rb +42 -20
  20. data/lib/when_exe/linkeddata.rb +28 -7
  21. data/lib/when_exe/locales/autoload.rb +2 -1
  22. data/lib/when_exe/locales/locale.rb +35 -15
  23. data/lib/when_exe/locales/zh.rb +77 -0
  24. data/lib/when_exe/mini_application.rb +3 -1
  25. data/lib/when_exe/{googlecalendar.rb → obsolete/googlecalendar.rb} +144 -144
  26. data/lib/when_exe/parts/enumerator.rb +498 -486
  27. data/lib/when_exe/parts/geometric_complex.rb +397 -397
  28. data/lib/when_exe/parts/timezone.rb +246 -241
  29. data/lib/when_exe/region/armenian.rb +55 -56
  30. data/lib/when_exe/region/babylonian.rb +406 -405
  31. data/lib/when_exe/region/bahai.rb +107 -106
  32. data/lib/when_exe/region/balinese.rb +624 -622
  33. data/lib/when_exe/region/chinese.rb +1071 -1026
  34. data/lib/when_exe/region/chinese/epochs.rb +28 -28
  35. data/lib/when_exe/region/chinese/notes.rb +219 -0
  36. data/lib/when_exe/region/chinese/twins.rb +803 -803
  37. data/lib/when_exe/region/christian.rb +21 -15
  38. data/lib/when_exe/region/coptic.rb +107 -106
  39. data/lib/when_exe/region/discordian.rb +218 -218
  40. data/lib/when_exe/region/east_asian.rb +1 -1
  41. data/lib/when_exe/region/french.rb +126 -56
  42. data/lib/when_exe/region/geologicalage.rb +639 -639
  43. data/lib/when_exe/region/goddess.rb +60 -58
  44. data/lib/when_exe/region/hanke_henry.rb +2 -2
  45. data/lib/when_exe/region/indian.rb +1225 -1222
  46. data/lib/when_exe/region/international_fixed.rb +96 -97
  47. data/lib/when_exe/region/iranian.rb +206 -203
  48. data/lib/when_exe/region/islamic.rb +102 -102
  49. data/lib/when_exe/region/japanese.rb +126 -71
  50. data/lib/when_exe/region/japanese/epochs.rb +426 -426
  51. data/lib/when_exe/region/japanese/notes.rb +101 -81
  52. data/lib/when_exe/region/japanese/residues.rb +1345 -1311
  53. data/lib/when_exe/region/japanese/twins.rb +225 -225
  54. data/lib/when_exe/region/japanese/weeks.rb +112 -112
  55. data/lib/when_exe/region/javanese.rb +230 -230
  56. data/lib/when_exe/region/jewish.rb +130 -131
  57. data/lib/when_exe/region/m17n.rb +114 -114
  58. data/lib/when_exe/region/martian.rb +258 -258
  59. data/lib/when_exe/region/mayan.rb +11 -8
  60. data/lib/when_exe/region/pax.rb +4 -5
  61. data/lib/when_exe/region/pope.rb +1 -1
  62. data/lib/when_exe/region/positivist.rb +100 -100
  63. data/lib/when_exe/region/residue.rb +162 -162
  64. data/lib/when_exe/region/roman.rb +333 -333
  65. data/lib/when_exe/region/{soviet.rb → russian.rb} +221 -209
  66. data/lib/when_exe/region/shire.rb +222 -223
  67. data/lib/when_exe/region/symmetry.rb +50 -50
  68. data/lib/when_exe/region/thai.rb +336 -336
  69. data/lib/when_exe/region/tibetan.rb +315 -316
  70. data/lib/when_exe/region/tranquility.rb +207 -208
  71. data/lib/when_exe/region/vanishing_leprechaun.rb +3 -1
  72. data/lib/when_exe/region/vietnamese.rb +449 -440
  73. data/lib/when_exe/region/weekdate.rb +80 -80
  74. data/lib/when_exe/region/world.rb +170 -171
  75. data/lib/when_exe/region/world_season.rb +89 -89
  76. data/lib/when_exe/region/yerm.rb +3 -3
  77. data/lib/when_exe/region/zoroastrian.rb +205 -205
  78. data/lib/when_exe/timestandard.rb +708 -707
  79. data/lib/when_exe/tmduration.rb +338 -338
  80. data/lib/when_exe/tmobjects.rb +1356 -1356
  81. data/lib/when_exe/tmposition.rb +66 -31
  82. data/lib/when_exe/version.rb +16 -2
  83. data/test/examples/Residue.m17n +83 -83
  84. data/test/examples/Terms.m17n +2 -2
  85. data/test/test.rb +2 -2
  86. data/test/test/google_api.rb +65 -0
  87. data/test/test/linkeddata.rb +1 -1
  88. data/test/test/{googlecalendar.rb → obsolete/googlecalendar.rb} +194 -194
  89. data/test/test/region/indian.rb +90 -85
  90. data/test/test/region/m17n.rb +7 -7
  91. data/test/test/region/mayan.rb +195 -195
  92. data/test/test/region/residue.rb +153 -153
  93. data/test/test/tmposition.rb +11 -1
  94. data/when_exe.gemspec +2 -2
  95. metadata +95 -8
  96. data/test/test.rb.config +0 -1
@@ -1,486 +1,498 @@
1
- # -*- coding: utf-8 -*-
2
- =begin
3
- Copyright (C) 2011-2014 Takashi SUGA
4
-
5
- You may use and/or modify this file according to the license described in the LICENSE.txt file included in this archive.
6
- =end
7
-
8
- #
9
- # 本ライブラリのための諸々の部品
10
- #
11
- module When::Parts
12
-
13
- #
14
- # v1.8.x のための互換性確保用
15
- #
16
- # @private
17
- class Enumerator < ::Enumerator ; end if Object.const_defined?(:Enumerator)
18
-
19
- #
20
- # 本ライブラリ用の Enumerator の雛形
21
- #
22
- class Enumerator
23
-
24
- # @private
25
- def self._options(args)
26
- options = args[-1].kind_of?(Hash) ? args.pop.dup : {}
27
- options[:exdate] =
28
- case options[:exdate]
29
- when GeometricComplex ; options[:exdate].dup
30
- when nil ; GeometricComplex.new()
31
- else ; GeometricComplex.new(options[:exdate])
32
- end
33
- return options
34
- end
35
-
36
- # 生成元オブジェクト
37
- # @return [Comparable]
38
- attr_reader :parent
39
-
40
- # オプション
41
- # @return [Hash]
42
- # @private
43
- attr_accessor :options
44
- protected :options=
45
-
46
- # 除外要素
47
- # @return [When::Parts::GeometricComplex]
48
- attr_accessor :exdate
49
- protected :exdate=
50
-
51
- # 処理済み要素
52
- # @return [When::Parts::GeometricComplex]
53
- attr_accessor :processed
54
- protected :processed=
55
-
56
- # 最初の要素
57
- # @return [Comparable]
58
- attr_accessor :first
59
- protected :first=
60
-
61
- # 最後の要素
62
- # @return [Comparable]
63
- attr_accessor :last
64
- protected :last=
65
-
66
- # 繰り返し方向
67
- # @return [Symbol]
68
- # [ :forward - 昇順 ]
69
- # [ :reverse - 降順 ]
70
- attr_reader :direction
71
-
72
- # 最大繰り返し回数
73
- # @return [Integer]
74
- attr_reader :count_limit
75
-
76
- # 現在の繰り返し回数
77
- # @return [Integer]
78
- attr_reader :count
79
-
80
- # 現在の要素
81
- # @return [Comparable]
82
- attr_accessor :current
83
- protected :current=
84
-
85
- # 現在のインデックス
86
- # @return [Integer]
87
- # @private
88
- attr_reader :index
89
-
90
- # with_object メソッドで渡すインスタンス
91
- # @return [Comparable]
92
- # @private
93
- attr_accessor :object
94
- protected :object=
95
-
96
- #
97
- # ブロックを評価する
98
- #
99
- # @param [Hash] options 以下の通り
100
- # @option options [Symbol] :direction 方向(:forward/:reverse)
101
- # @option options [Comparable] :until 終了閾値
102
- # @option options [Integer] :count_limit 繰り返し回数
103
- #
104
- # @return [rewind された self]
105
- #
106
- def each(options={})
107
- @direction = options[:direction] if options.key?(:direction)
108
- @last = @direction == :reverse ? [options[:until], @last].compact.max :
109
- [options[:until], @last].compact.min
110
- @count_limit = [options[:count_limit], @count_limit].compact.min
111
- return self unless block_given?
112
- while (has_next?) do
113
- if @index
114
- yield(succ, @index)
115
- @index += 1
116
- elsif @object
117
- yield(succ, @object)
118
- else
119
- yield(succ)
120
- end
121
- end
122
- @index = @object = nil
123
- rewind
124
- end
125
-
126
- #
127
- # index をブロックに渡して評価する
128
- #
129
- # @param [Integer] offset index の初期値
130
- #
131
- # @return [When::Parts:Enumerator]
132
- # [ ブロックあり - rewind された self ]
133
- # [ ブロックなし - copy ]
134
- #
135
- def with_index(offset=0, &block)
136
- if block_given?
137
- @index = offset||@count
138
- return each(block)
139
- else
140
- copy = _copy
141
- copy.object = nil
142
- copy.index = offset||@count
143
- return copy
144
- end
145
- end
146
-
147
- #
148
- # index をブロックに渡して評価する
149
- #
150
- # @param [Comparable] object ブロックに渡す Object
151
- #
152
- # @return [When::Parts:Enumerator]
153
- # [ ブロックあり - rewind された self ]
154
- # [ ブロックなし - copy ]
155
- #
156
- def with_object(object, &block)
157
- if block_given?
158
- @object = object
159
- each(block)
160
- return object
161
- else
162
- copy = _copy
163
- copy.object = object
164
- copy.index = nil
165
- return copy
166
- end
167
- end
168
-
169
- #
170
- # 巻き戻す
171
- #
172
- # @return [rewind された self]
173
- #
174
- def _rewind
175
- @processed = @exdate.dup
176
- @count = 0
177
- @current = :first
178
- succ
179
- self
180
- end
181
- alias :rewind :_rewind
182
-
183
- #
184
- # 次の要素があるか?
185
- #
186
- # @return [Boolean]
187
- # [ true - ある ]
188
- # [ false - ない ]
189
- #
190
- def has_next?
191
- return (@count_limit != 0) && (@current != nil)
192
- end
193
-
194
- #
195
- # 次の要素を取り出す
196
- #
197
- # @return [Comparable] 次の要素
198
- # @raise [StopIteration] 次の要素がない場合 rewind して例外を発生
199
- #
200
- def next
201
- return succ if has_next?
202
- rewind
203
- raise StopIteration, "Iteration Stopped"
204
- end
205
-
206
- #
207
- # 次の要素を取り出す
208
- #
209
- # @return [Comparable]
210
- # [ 次の要素あり - 次の要素 ]
211
- # [ 次の要素なし - nil ]
212
- #
213
- # @note
214
- # 次の要素がない場合 rewind や、StopIteration例外発生は行わない
215
- #
216
- def succ
217
- value = @current
218
- if @count_limit.kind_of?(Numeric) && @count >= @count_limit
219
- @current = nil
220
- else
221
- loop do
222
- @current = _succ
223
- break unless @current
224
- next if (@current == :next)
225
- @current = GeometricComplex.new(@current, @duration) if @duration
226
- next if _exclude(@current)
227
- case @direction
228
- when :reverse
229
- next if @current > @first
230
- @current = nil if @last && @current < @last
231
- break
232
- else
233
- next if @current < @first
234
- @current = nil if @last && @current > @last
235
- break
236
- end
237
- end
238
- @count += 1
239
- _exclude(@current) if @current
240
- end
241
- return value
242
- end
243
-
244
- # オブジェクトの生成
245
- #
246
- # @overload initialize(parent, range, count_limit=nil)
247
- # @param [Comparable] parent 生成元
248
- # @param [Range, When::Parts::GeometricComplex] range
249
- # [ 始点 - range.first ]
250
- # [ 終点 - range.last ]
251
- # @param [Integer] count_limit 繰り返し回数(デフォルトは指定なし)
252
- #
253
- # @overload initialize(parent, first, direction, count_limit=nil)
254
- # @param [Comparable] parent 生成元
255
- # @param [When::TM::TemporalPosition] first 始点
256
- # @param [Symbol] direction (options[:direction]で渡してもよい)
257
- # [ :forward - 昇順 ]
258
- # [ :reverse - 降順 ]
259
- # @param [Integer] count_limit 繰り返し回数(デフォルトは指定なし, options[:count_limit]で渡してもよい)
260
- #
261
- def initialize(*args)
262
- @options = self.class._options(args)
263
- @exdate = @options.delete(:exdate)
264
- @exevent = @options.delete(:exevent)
265
- @parent, *rest = args
266
- _range(rest)
267
- _rewind
268
- end
269
-
270
- private
271
-
272
- def _range(rest)
273
- if rest[0].instance_of?(Range)
274
- range, @count_limit, others = rest
275
- raise ArgumentError, "Too many arguments" if others
276
- @first = When.when?(range.first)
277
- @last = When.when?(range.last)
278
- @exdate |= @last if (range.exclude_end?)
279
- if (@first > @last)
280
- @first, @last = @last, @first
281
- @direction = :reverse
282
- else
283
- @direction = :forward
284
- end
285
- else
286
- @first, @direction, @count_limit, others = rest
287
- raise ArgumentError, "Too many arguments" if others
288
- raise ArgumentError, "Too few arguments" unless @first
289
- @direction ||= :forward
290
- @last = nil
291
- end
292
- @count_limit = @options[:count_limit] if @options[:count_limit] && (!@count_limit || @count_limit > @options[:count_limit])
293
- @options.delete(:count_limit)
294
- @direction = @options[:direction] if @options[:direction]
295
- @options.delete(:direction)
296
- end
297
-
298
- def _exclude(value)
299
- if @exevent
300
- @exevent.each do |ev|
301
- return true if ev.include?(value)
302
- end
303
- end
304
- previous = @processed._include?(value)
305
- @processed |= value if previous == false
306
- registered = (previous==value) ? previous : value
307
- registered = registered.first if registered.kind_of?(GeometricComplex)
308
- registered.events ||=[]
309
- registered.events << self.parent
310
- registered.events.uniq!
311
- return previous != false
312
- end
313
-
314
- def _copy
315
- copy = dup
316
- copy.options = @options.dup if @options
317
- copy.exdate = @exdate.dup if @exdate
318
- copy.exevent = @exevent.dup if @exevent
319
- copy.processed = @processed.dup if @processed
320
- copy.first = @first.dup if @first
321
- copy.last = @last.dup if @last
322
- copy.current = @current.dup if @current.respond_to?(:dup)
323
- copy.object = @object.dup if @object.respond_to?(:dup)
324
- return copy
325
- end
326
-
327
- #
328
- # 時間位置の Array を順に取り出す Enumerator
329
- #
330
- class Array < Enumerator
331
-
332
- # 整列して、重複した候補を削除
333
- #
334
- # @param [Array] list
335
- # @param [Symbol] direction
336
- # [ :forward - 昇順 ]
337
- # [ :reverse - 降順 ]
338
- #
339
- # @return [Array]
340
- # @note
341
- # eql? はオーバーライドしない
342
- #
343
- def self._sort(list, direction)
344
- list = list.sort
345
- prev = nil
346
- list.delete_if do |x|
347
- if (x == prev)
348
- true
349
- else
350
- prev = x
351
- false
352
- end
353
- end
354
- list.reverse! if (direction == :reverse)
355
- return list
356
- end
357
-
358
- # 初期リスト
359
- # @return [Array]
360
- # @private
361
- attr_accessor :initial_list
362
- protected :initial_list=
363
-
364
- # 現在リスト
365
- # @return [Array]
366
- # @private
367
- attr_accessor :current_list
368
- protected :current_list=
369
-
370
- #
371
- # 巻き戻す
372
- #
373
- # @return [rewind された self]
374
- # @private
375
- def _rewind
376
- @current_list = @initial_list.dup
377
- super
378
- end
379
-
380
- # オブジェクトの生成
381
- #
382
- # @overload initialize(parent, list, count_limit=nil))
383
- # @param [Comparable] parent 生成元
384
- # @param [Array<When::TM::TemporalPosition>] list 順に取り出す時間位置の Array
385
- # @param [Symbol] direction
386
- # [ :forward - 昇順 ]
387
- # [ :reverse - 降順 ]
388
- # @param [Integer] count_limit 繰り返し回数(デフォルトは指定なし)
389
- #
390
- def initialize(*args)
391
- parent, list, direction, *args = args
392
- raise ArgumentError, "Too few arguments" unless list
393
- @initial_list = self.class._sort(list, direction||:forward)
394
- super(parent, @initial_list[0], direction, *args)
395
- end
396
-
397
- private
398
-
399
- def _succ
400
- return @current_list.shift
401
- end
402
-
403
- def _copy
404
- copy = super
405
- copy.initial_list = @initial_list.dup
406
- copy.current_list = @current_list.dup
407
- return copy
408
- end
409
- end
410
-
411
- #
412
- # 複数の下位 Enumerator の結果を順に取り出す Enumerator
413
- #
414
- class Integrated < Enumerator
415
-
416
- #
417
- # 下位 Enumerator
418
- #
419
- # @return [Array<When::Parts::Enumerator>]
420
- #
421
- attr_accessor :enumerators
422
- protected :enumerators=
423
-
424
- #
425
- # 巻き戻す
426
- #
427
- # @return [rewind された self]
428
- #
429
- def rewind
430
- @enumerators.each do |enum|
431
- enum._rewind
432
- end
433
- super
434
- end
435
-
436
- # オブジェクトの生成
437
- #
438
- # @overload initialize(parent, enumerators, first, count_limit=nil))
439
- # @param [Comparable] parent 生成元
440
- # @param [Array<When::Parts::Enumerator>] list 順に取り出す下位 Enumeratorの Array
441
- # @param [When::TM::TemporalPosition] first 始点
442
- # @param [Symbol] direction
443
- # [ :forward - 昇順 ]
444
- # [ :reverse - 降順 ]
445
- # @param [Integer] count_limit 繰り返し回数(デフォルトは指定なし)
446
- #
447
- def initialize(*args)
448
- parent, @enumerators, *rest = args
449
- raise ArgumentError, "Too few arguments" unless @enumerators.kind_of?(::Array)
450
- super(parent, *rest)
451
- end
452
-
453
- private
454
-
455
- def _copy
456
- copy = super
457
- copy.enumerators = @enumerators.map {|e| e._copy}
458
- return copy
459
- end
460
-
461
- def _succ
462
- current = nil
463
- selected = nil
464
- @enumerators.each_index do |i|
465
- value = @enumerators[i].current
466
- next unless (value)
467
- if (current)
468
- verify = current <=> value
469
- case @direction
470
- when :reverse ; next if (verify > 0)
471
- else ; next if (verify < 0)
472
- end
473
- if (verify == 0)
474
- next if current.kind_of?(GeometricComplex) && current.include?(value)
475
- #next if current.precision <= value.precision # TODO
476
- end
477
- end
478
- current = value
479
- selected = i
480
- end
481
- @enumerators[selected].succ if (selected)
482
- return current
483
- end
484
- end
485
- end
486
- end
1
+ # -*- coding: utf-8 -*-
2
+ =begin
3
+ Copyright (C) 2011-2015 Takashi SUGA
4
+
5
+ You may use and/or modify this file according to the license described in the LICENSE.txt file included in this archive.
6
+ =end
7
+
8
+ #
9
+ # 本ライブラリのための諸々の部品
10
+ #
11
+ module When::Parts
12
+
13
+ #
14
+ # v1.8.x のための互換性確保用
15
+ #
16
+ # @private
17
+ class Enumerator < ::Enumerator ; end if Object.const_defined?(:Enumerator)
18
+
19
+ #
20
+ # 本ライブラリ用の Enumerator の雛形
21
+ #
22
+ class Enumerator
23
+
24
+ # @private
25
+ def self._options(args)
26
+ options = args[-1].kind_of?(Hash) ? args.pop.dup : {}
27
+ options[:exdate] =
28
+ case options[:exdate]
29
+ when GeometricComplex ; options[:exdate].dup
30
+ when nil ; GeometricComplex.new()
31
+ else ; GeometricComplex.new(options[:exdate])
32
+ end
33
+ return options
34
+ end
35
+
36
+ # 生成元オブジェクト
37
+ # @return [Comparable]
38
+ attr_reader :parent
39
+
40
+ # オプション
41
+ # @return [Hash]
42
+ # @private
43
+ attr_accessor :options
44
+ protected :options=
45
+
46
+ # 除外要素
47
+ # @return [When::Parts::GeometricComplex]
48
+ attr_accessor :exdate
49
+ protected :exdate=
50
+
51
+ # 処理済み要素
52
+ # @return [When::Parts::GeometricComplex]
53
+ attr_accessor :processed
54
+ protected :processed=
55
+
56
+ # 最初の要素
57
+ # @return [Comparable]
58
+ attr_accessor :first
59
+ protected :first=
60
+
61
+ # 最後の要素
62
+ # @return [Comparable]
63
+ attr_accessor :last
64
+ protected :last=
65
+
66
+ # 繰り返し方向
67
+ # @return [Symbol]
68
+ # [ :forward - 昇順 ]
69
+ # [ :reverse - 降順 ]
70
+ attr_reader :direction
71
+
72
+ # 最大繰り返し回数
73
+ # @return [Integer]
74
+ attr_reader :count_limit
75
+
76
+ # 現在の繰り返し回数
77
+ # @return [Integer]
78
+ attr_reader :count
79
+
80
+ # 現在の要素
81
+ # @return [Comparable]
82
+ attr_accessor :current
83
+ protected :current=
84
+
85
+ # 現在のインデックス
86
+ # @return [Integer]
87
+ # @private
88
+ attr_reader :index
89
+
90
+ # with_object メソッドで渡すインスタンス
91
+ # @return [Comparable]
92
+ # @private
93
+ attr_accessor :object
94
+ protected :object=
95
+
96
+ #
97
+ # ブロックを評価する
98
+ #
99
+ # @param [Hash] options 以下の通り
100
+ # @option options [Symbol] :direction 方向(:forward/:reverse)
101
+ # @option options [Comparable] :until 終了閾値
102
+ # @option options [Integer] :count_limit 繰り返し回数
103
+ #
104
+ # @return [rewind された self]
105
+ #
106
+ def each(options={})
107
+ @direction = options[:direction] if options.key?(:direction)
108
+ @last = @direction == :reverse ? [options[:until], @last].compact.max :
109
+ [options[:until], @last].compact.min
110
+ @count_limit = [options[:count_limit], @count_limit].compact.min
111
+ return self unless block_given?
112
+ while (has_next?) do
113
+ if @index
114
+ yield(succ, @index)
115
+ @index += 1
116
+ elsif @object
117
+ yield(succ, @object)
118
+ else
119
+ yield(succ)
120
+ end
121
+ end
122
+ @index = @object = nil
123
+ rewind
124
+ end
125
+
126
+ #
127
+ # index をブロックに渡して評価する
128
+ #
129
+ # @param [Integer] offset index の初期値
130
+ #
131
+ # @return [When::Parts:Enumerator]
132
+ # [ ブロックあり - rewind された self ]
133
+ # [ ブロックなし - copy ]
134
+ #
135
+ def with_index(offset=0, &block)
136
+ if block_given?
137
+ @index = offset||@count
138
+ return each(block)
139
+ else
140
+ copy = _copy
141
+ copy.object = nil
142
+ copy.index = offset||@count
143
+ return copy
144
+ end
145
+ end
146
+
147
+ #
148
+ # index をブロックに渡して評価する
149
+ #
150
+ # @param [Comparable] object ブロックに渡す Object
151
+ #
152
+ # @return [When::Parts:Enumerator]
153
+ # [ ブロックあり - rewind された self ]
154
+ # [ ブロックなし - copy ]
155
+ #
156
+ def with_object(object, &block)
157
+ if block_given?
158
+ @object = object
159
+ each(block)
160
+ return object
161
+ else
162
+ copy = _copy
163
+ copy.object = object
164
+ copy.index = nil
165
+ return copy
166
+ end
167
+ end
168
+
169
+ #
170
+ # 巻き戻す
171
+ #
172
+ # @return [rewind された self]
173
+ #
174
+ def _rewind
175
+ @processed = @exdate.dup
176
+ @count = 0
177
+ @current = :first
178
+ succ
179
+ self
180
+ end
181
+ alias :rewind :_rewind
182
+
183
+ #
184
+ # 次の要素があるか?
185
+ #
186
+ # @return [Boolean]
187
+ # [ true - ある ]
188
+ # [ false - ない ]
189
+ #
190
+ def has_next?
191
+ return (@count_limit != 0) && (@current != nil)
192
+ end
193
+
194
+ #
195
+ # 次の要素を取り出す
196
+ #
197
+ # @return [Comparable] 次の要素
198
+ # @raise [StopIteration] 次の要素がない場合 rewind して例外を発生
199
+ #
200
+ def next
201
+ return succ if has_next?
202
+ rewind
203
+ raise StopIteration, "Iteration Stopped"
204
+ end
205
+
206
+ #
207
+ # 次の要素を取り出す
208
+ #
209
+ # @return [Comparable]
210
+ # [ 次の要素あり - 次の要素 ]
211
+ # [ 次の要素なし - nil ]
212
+ #
213
+ # @note
214
+ # 次の要素がない場合 rewind や、StopIteration例外発生は行わない
215
+ #
216
+ def succ
217
+ value = @current
218
+ if @count_limit.kind_of?(Numeric) && @count >= @count_limit
219
+ @current = nil
220
+ else
221
+ loop do
222
+ @current = _succ
223
+ break unless @current
224
+ next if (@current == :next)
225
+ @current = GeometricComplex.new(@current, @duration) if @duration
226
+ next if _exclude(@current)
227
+ case @direction
228
+ when :reverse
229
+ next if @current > @first
230
+ @current = nil if @last && @current < @last
231
+ break
232
+ else
233
+ next if @current < @first
234
+ @current = nil if @last && @current > @last
235
+ break
236
+ end
237
+ end
238
+ @count += 1
239
+ _exclude(@current) if @current
240
+ end
241
+ return value
242
+ end
243
+
244
+ # オブジェクトの生成
245
+ #
246
+ # @overload initialize(parent, range, count_limit=nil)
247
+ # @param [Comparable] parent 生成元
248
+ # @param [Range, When::Parts::GeometricComplex] range
249
+ # [ 始点 - range.first ]
250
+ # [ 終点 - range.last ]
251
+ # @param [Integer] count_limit 繰り返し回数(デフォルトは指定なし)
252
+ #
253
+ # @overload initialize(parent, first, direction, count_limit=nil)
254
+ # @param [Comparable] parent 生成元
255
+ # @param [When::TM::TemporalPosition] first 始点
256
+ # @param [Symbol] direction (options[:direction]で渡してもよい)
257
+ # [ :forward - 昇順 ]
258
+ # [ :reverse - 降順 ]
259
+ # @param [Integer] count_limit 繰り返し回数(デフォルトは指定なし, options[:count_limit]で渡してもよい)
260
+ #
261
+ def initialize(*args)
262
+ @options = self.class._options(args)
263
+ @exdate = @options.delete(:exdate)
264
+ @exevent = @options.delete(:exevent)
265
+ @parent, *rest = args
266
+ _range(rest)
267
+ _rewind
268
+ end
269
+
270
+ private
271
+
272
+ def _range(rest)
273
+ if rest[0].kind_of?(Range)
274
+ range, @count_limit, others = rest
275
+ raise ArgumentError, "Too many arguments" if others
276
+ @first = When.when?(range.first)
277
+ @last = When.when?(range.last)
278
+ @exdate |= @last if range.exclude_end?
279
+ if (@first > @last)
280
+ @first, @last = @last, @first
281
+ @direction = :reverse
282
+ else
283
+ @direction = :forward
284
+ end
285
+ else
286
+ @first, @direction, @count_limit, others = rest
287
+ raise ArgumentError, "Too many arguments" if others
288
+ raise ArgumentError, "Too few arguments" unless @first
289
+ @direction ||= :forward
290
+ @last = nil
291
+ end
292
+ @count_limit = @options[:count_limit] if @options[:count_limit] && (!@count_limit || @count_limit > @options[:count_limit])
293
+ @options.delete(:count_limit)
294
+ @direction = @options[:direction] if @options[:direction]
295
+ @options.delete(:direction)
296
+ end
297
+
298
+ def _exclude(value)
299
+ if @exevent
300
+ @exevent.each do |ev|
301
+ return true if ev.include?(value)
302
+ end
303
+ end
304
+ previous = @processed._include?(value)
305
+ @processed |= value if previous == false
306
+ registered = (previous==value) ? previous : value
307
+ registered = registered.first if registered.kind_of?(GeometricComplex)
308
+ registered.events ||=[]
309
+ registered.events << self.parent
310
+ registered.events.uniq!
311
+ return previous != false
312
+ end
313
+
314
+ def _copy
315
+ copy = dup
316
+ copy.options = @options.dup if @options
317
+ copy.exdate = @exdate.dup if @exdate
318
+ copy.exevent = @exevent.dup if @exevent
319
+ copy.processed = @processed.dup if @processed
320
+ copy.first = @first.dup if @first
321
+ copy.last = @last.dup if @last
322
+ copy.current = @current.dup if @current.respond_to?(:dup)
323
+ copy.object = @object.dup if @object.respond_to?(:dup)
324
+ return copy
325
+ end
326
+
327
+ #
328
+ # 時間位置の Array を順に取り出す Enumerator
329
+ #
330
+ class Array < Enumerator
331
+
332
+ # 整列して、重複した候補を削除
333
+ #
334
+ # @param [Array] list
335
+ # @param [Symbol] direction
336
+ # [ :forward - 昇順 ]
337
+ # [ :reverse - 降順 ]
338
+ #
339
+ # @return [Array]
340
+ # @note
341
+ # eql? はオーバーライドしない
342
+ #
343
+ def self._sort(list, direction)
344
+ list = list.sort
345
+ prev = nil
346
+ list.delete_if do |x|
347
+ if (x == prev)
348
+ true
349
+ else
350
+ prev = x
351
+ false
352
+ end
353
+ end
354
+ list.reverse! if (direction == :reverse)
355
+ return list
356
+ end
357
+
358
+ # 初期リスト
359
+ # @return [Array]
360
+ # @private
361
+ attr_accessor :initial_list
362
+ protected :initial_list=
363
+
364
+ # 現在リスト
365
+ # @return [Array]
366
+ # @private
367
+ attr_accessor :current_list
368
+ protected :current_list=
369
+
370
+ #
371
+ # 巻き戻す
372
+ #
373
+ # @return [rewind された self]
374
+ # @private
375
+ def _rewind
376
+ @current_list = @initial_list.dup
377
+ super
378
+ end
379
+
380
+ # オブジェクトの生成
381
+ #
382
+ # @overload initialize(parent, list, count_limit=nil))
383
+ # @param [Comparable] parent 生成元
384
+ # @param [Array<When::TM::TemporalPosition>] list 順に取り出す時間位置の Array
385
+ # @param [Symbol] direction
386
+ # [ :forward - 昇順 ]
387
+ # [ :reverse - 降順 ]
388
+ # @param [Integer] count_limit 繰り返し回数(デフォルトは指定なし)
389
+ #
390
+ def initialize(*args)
391
+ parent, list, direction, *args = args
392
+ raise ArgumentError, "Too few arguments" unless list
393
+ @initial_list = self.class._sort(list, direction||:forward)
394
+ super(parent, @initial_list[0], direction, *args)
395
+ end
396
+
397
+ private
398
+
399
+ def _range(rest)
400
+ @first, @direction, @count_limit, others = rest
401
+ raise ArgumentError, "Too many arguments" if others
402
+ raise ArgumentError, "Too few arguments" unless @first
403
+ @direction ||= :forward
404
+ @last = nil
405
+ @count_limit = @options[:count_limit] if @options[:count_limit] && (!@count_limit || @count_limit > @options[:count_limit])
406
+ @options.delete(:count_limit)
407
+ @direction = @options[:direction] if @options[:direction]
408
+ @options.delete(:direction)
409
+ end
410
+
411
+ def _succ
412
+ return @current_list.shift
413
+ end
414
+
415
+ def _copy
416
+ copy = super
417
+ copy.initial_list = @initial_list.dup
418
+ copy.current_list = @current_list.dup
419
+ return copy
420
+ end
421
+ end
422
+
423
+ #
424
+ # 複数の下位 Enumerator の結果を順に取り出す Enumerator
425
+ #
426
+ class Integrated < Enumerator
427
+
428
+ #
429
+ # 下位 Enumerator
430
+ #
431
+ # @return [Array<When::Parts::Enumerator>]
432
+ #
433
+ attr_accessor :enumerators
434
+ protected :enumerators=
435
+
436
+ #
437
+ # 巻き戻す
438
+ #
439
+ # @return [rewind された self]
440
+ #
441
+ def rewind
442
+ @enumerators.each do |enum|
443
+ enum._rewind
444
+ end
445
+ super
446
+ end
447
+
448
+ # オブジェクトの生成
449
+ #
450
+ # @overload initialize(parent, enumerators, first, count_limit=nil))
451
+ # @param [Comparable] parent 生成元
452
+ # @param [Array<When::Parts::Enumerator>] list 順に取り出す下位 Enumeratorの Array
453
+ # @param [When::TM::TemporalPosition] first 始点
454
+ # @param [Symbol] direction
455
+ # [ :forward - 昇順 ]
456
+ # [ :reverse - 降順 ]
457
+ # @param [Integer] count_limit 繰り返し回数(デフォルトは指定なし)
458
+ #
459
+ def initialize(*args)
460
+ parent, @enumerators, *rest = args
461
+ raise ArgumentError, "Too few arguments" unless @enumerators.kind_of?(::Array)
462
+ super(parent, *rest)
463
+ end
464
+
465
+ private
466
+
467
+ def _copy
468
+ copy = super
469
+ copy.enumerators = @enumerators.map {|e| e._copy}
470
+ return copy
471
+ end
472
+
473
+ def _succ
474
+ current = nil
475
+ selected = nil
476
+ @enumerators.each_index do |i|
477
+ value = @enumerators[i].current
478
+ next unless (value)
479
+ if (current)
480
+ verify = current <=> value
481
+ case @direction
482
+ when :reverse ; next if (verify > 0)
483
+ else ; next if (verify < 0)
484
+ end
485
+ if (verify == 0)
486
+ next if current.kind_of?(GeometricComplex) && current.include?(value)
487
+ #next if current.precision <= value.precision # TODO
488
+ end
489
+ end
490
+ current = value
491
+ selected = i
492
+ end
493
+ @enumerators[selected].succ if (selected)
494
+ return current
495
+ end
496
+ end
497
+ end
498
+ end