when_exe 0.4.1 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
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