when_exe 0.3.7 → 0.3.8

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