when_exe 0.3.4 → 0.3.5

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 (168) hide show
  1. data/bin/locales.rb +2 -2
  2. data/bin/when.rb +2 -2
  3. data/lib/when_exe.rb +161 -55
  4. data/lib/when_exe/basictypes.rb +34 -26
  5. data/lib/when_exe/calendarnote.rb +654 -0
  6. data/lib/when_exe/calendartypes.rb +49 -474
  7. data/lib/when_exe/coordinates.rb +141 -34
  8. data/lib/when_exe/core/compatibility.rb +22 -2
  9. data/lib/when_exe/core/extension.rb +47 -3
  10. data/lib/when_exe/ephemeris.rb +82 -109
  11. data/lib/when_exe/googlecalendar.rb +1 -1
  12. data/lib/when_exe/icalendar.rb +26 -14
  13. data/lib/when_exe/inspect.rb +82 -68
  14. data/lib/when_exe/locales/af.rb +1 -1
  15. data/lib/when_exe/locales/ar.rb +1 -1
  16. data/lib/when_exe/locales/az.rb +1 -1
  17. data/lib/when_exe/locales/bg.rb +1 -1
  18. data/lib/when_exe/locales/bn.rb +1 -1
  19. data/lib/when_exe/locales/bs.rb +1 -1
  20. data/lib/when_exe/locales/ca.rb +1 -1
  21. data/lib/when_exe/locales/cs.rb +1 -1
  22. data/lib/when_exe/locales/cy.rb +1 -1
  23. data/lib/when_exe/locales/da.rb +1 -1
  24. data/lib/when_exe/locales/de.rb +1 -1
  25. data/lib/when_exe/locales/de_AT.rb +1 -1
  26. data/lib/when_exe/locales/de_CH.rb +1 -1
  27. data/lib/when_exe/locales/el.rb +1 -1
  28. data/lib/when_exe/locales/en.rb +1 -1
  29. data/lib/when_exe/locales/en_AU.rb +1 -1
  30. data/lib/when_exe/locales/en_CA.rb +1 -1
  31. data/lib/when_exe/locales/en_GB.rb +1 -1
  32. data/lib/when_exe/locales/en_IE.rb +1 -1
  33. data/lib/when_exe/locales/en_IN.rb +1 -1
  34. data/lib/when_exe/locales/en_NZ.rb +1 -1
  35. data/lib/when_exe/locales/en_US.rb +1 -1
  36. data/lib/when_exe/locales/eo.rb +1 -1
  37. data/lib/when_exe/locales/es.rb +1 -1
  38. data/lib/when_exe/locales/es_419.rb +1 -1
  39. data/lib/when_exe/locales/es_AR.rb +1 -1
  40. data/lib/when_exe/locales/es_CL.rb +1 -1
  41. data/lib/when_exe/locales/es_CO.rb +1 -1
  42. data/lib/when_exe/locales/es_CR.rb +1 -1
  43. data/lib/when_exe/locales/es_EC.rb +1 -1
  44. data/lib/when_exe/locales/es_MX.rb +1 -1
  45. data/lib/when_exe/locales/es_PA.rb +1 -1
  46. data/lib/when_exe/locales/es_PE.rb +1 -1
  47. data/lib/when_exe/locales/es_VE.rb +1 -1
  48. data/lib/when_exe/locales/et.rb +1 -1
  49. data/lib/when_exe/locales/eu.rb +1 -1
  50. data/lib/when_exe/locales/fa.rb +1 -1
  51. data/lib/when_exe/locales/fi.rb +1 -1
  52. data/lib/when_exe/locales/fr.rb +1 -1
  53. data/lib/when_exe/locales/fr_CA.rb +1 -1
  54. data/lib/when_exe/locales/fr_CH.rb +1 -1
  55. data/lib/when_exe/locales/gl.rb +1 -1
  56. data/lib/when_exe/locales/he.rb +1 -1
  57. data/lib/when_exe/locales/hi.rb +1 -1
  58. data/lib/when_exe/locales/hi_IN.rb +1 -1
  59. data/lib/when_exe/locales/hr.rb +1 -1
  60. data/lib/when_exe/locales/hu.rb +1 -1
  61. data/lib/when_exe/locales/id.rb +1 -1
  62. data/lib/when_exe/locales/is.rb +1 -1
  63. data/lib/when_exe/locales/it.rb +1 -1
  64. data/lib/when_exe/locales/it_CH.rb +1 -1
  65. data/lib/when_exe/locales/ja.rb +1 -1
  66. data/lib/when_exe/locales/kn.rb +1 -1
  67. data/lib/when_exe/locales/ko.rb +1 -1
  68. data/lib/when_exe/locales/lo.rb +1 -1
  69. data/lib/when_exe/locales/locales.rb +1 -1
  70. data/lib/when_exe/locales/lt.rb +1 -1
  71. data/lib/when_exe/locales/lv.rb +1 -1
  72. data/lib/when_exe/locales/mk.rb +1 -1
  73. data/lib/when_exe/locales/mn.rb +1 -1
  74. data/lib/when_exe/locales/ms.rb +1 -1
  75. data/lib/when_exe/locales/nb.rb +1 -1
  76. data/lib/when_exe/locales/ne.rb +1 -1
  77. data/lib/when_exe/locales/nl.rb +1 -1
  78. data/lib/when_exe/locales/nn.rb +1 -1
  79. data/lib/when_exe/locales/or.rb +1 -1
  80. data/lib/when_exe/locales/pl.rb +1 -1
  81. data/lib/when_exe/locales/pt.rb +1 -1
  82. data/lib/when_exe/locales/pt_BR.rb +1 -1
  83. data/lib/when_exe/locales/rm.rb +1 -1
  84. data/lib/when_exe/locales/ro.rb +1 -1
  85. data/lib/when_exe/locales/ru.rb +1 -1
  86. data/lib/when_exe/locales/sk.rb +1 -1
  87. data/lib/when_exe/locales/sl.rb +1 -1
  88. data/lib/when_exe/locales/sr.rb +1 -1
  89. data/lib/when_exe/locales/sv.rb +1 -1
  90. data/lib/when_exe/locales/sw.rb +1 -1
  91. data/lib/when_exe/locales/th.rb +1 -1
  92. data/lib/when_exe/locales/tl.rb +1 -1
  93. data/lib/when_exe/locales/tr.rb +1 -1
  94. data/lib/when_exe/locales/uk.rb +1 -1
  95. data/lib/when_exe/locales/ur.rb +1 -1
  96. data/lib/when_exe/locales/uz.rb +1 -1
  97. data/lib/when_exe/locales/vi.rb +1 -1
  98. data/lib/when_exe/locales/wo.rb +1 -1
  99. data/lib/when_exe/locales/zh_CN.rb +1 -1
  100. data/lib/when_exe/locales/zh_HK.rb +1 -1
  101. data/lib/when_exe/locales/zh_TW.rb +1 -1
  102. data/lib/when_exe/mini_application.rb +6 -2
  103. data/lib/when_exe/parts/enumerator.rb +13 -8
  104. data/lib/when_exe/parts/geometric_complex.rb +3 -5
  105. data/lib/when_exe/parts/locale.rb +185 -28
  106. data/lib/when_exe/parts/method_cash.rb +20 -10
  107. data/lib/when_exe/parts/resource.rb +154 -76
  108. data/lib/when_exe/parts/timezone.rb +11 -6
  109. data/lib/when_exe/region/bahai.rb +2 -2
  110. data/lib/when_exe/region/balinese.rb +296 -296
  111. data/lib/when_exe/region/chinese.rb +564 -564
  112. data/lib/when_exe/region/chinese_calendar.rb +5 -1
  113. data/lib/when_exe/region/chinese_epoch.rb +47 -102
  114. data/lib/when_exe/region/chinese_twin.rb +798 -0
  115. data/lib/when_exe/region/christian.rb +314 -338
  116. data/lib/when_exe/region/coptic.rb +88 -0
  117. data/lib/when_exe/region/ephemeric_notes.rb +322 -307
  118. data/lib/when_exe/region/french.rb +2 -2
  119. data/lib/when_exe/region/indian.rb +361 -272
  120. data/lib/when_exe/region/iranian.rb +2 -2
  121. data/lib/when_exe/region/islamic.rb +3 -3
  122. data/lib/when_exe/region/japanese.rb +1 -1
  123. data/lib/when_exe/region/japanese_notes.rb +165 -103
  124. data/lib/when_exe/region/japanese_residues.rb +56 -55
  125. data/lib/when_exe/region/japanese_twin.rb +228 -0
  126. data/lib/when_exe/region/javanese.rb +2 -2
  127. data/lib/when_exe/region/jewish.rb +2 -2
  128. data/lib/when_exe/region/korean.rb +4 -4
  129. data/lib/when_exe/region/m17n.rb +19 -19
  130. data/lib/when_exe/region/martian.rb +21 -9
  131. data/lib/when_exe/region/mayan.rb +19 -11
  132. data/lib/when_exe/region/moon.rb +7 -7
  133. data/lib/when_exe/region/nihon_shoki.rb +7 -7
  134. data/lib/when_exe/region/roman.rb +100 -100
  135. data/lib/when_exe/region/shire.rb +130 -147
  136. data/lib/when_exe/region/thai.rb +2 -2
  137. data/lib/when_exe/region/tibetan.rb +2 -2
  138. data/lib/when_exe/region/vietnamese.rb +383 -114
  139. data/lib/when_exe/region/world.rb +112 -129
  140. data/lib/when_exe/timestandard.rb +12 -1
  141. data/lib/when_exe/tmposition.rb +28 -14
  142. data/lib/when_exe/tmreference.rb +96 -93
  143. data/lib/when_exe/version.rb +1 -1
  144. data/test/examples/Terms.m17n +2 -2
  145. data/test/examples/sample.json +16 -0
  146. data/test/examples/sample.xml +1 -1
  147. data/test/test.rb +4 -0
  148. data/test/test/basictypes.rb +2 -2
  149. data/test/test/calendarnote.rb +69 -0
  150. data/test/test/calendartypes.rb +41 -1
  151. data/test/test/coordinates.rb +12 -1
  152. data/test/test/ephemeris.rb +13 -66
  153. data/test/test/icalendar.rb +3 -3
  154. data/test/test/inspect.rb +1 -1
  155. data/test/test/parts.rb +7 -4
  156. data/test/test/region/chinese.rb +45 -0
  157. data/test/test/region/coptic.rb +27 -0
  158. data/test/test/region/indian.rb +1 -1
  159. data/test/test/region/japanese.rb +4 -4
  160. data/test/test/region/jewish.rb +1 -1
  161. data/test/test/region/m17n.rb +7 -5
  162. data/test/test/region/residue.rb +2 -2
  163. data/test/test/region/vietnamese.rb +102 -0
  164. data/test/test/timestandard.rb +81 -0
  165. data/test/test/tmposition.rb +1 -1
  166. data/test/test/tmreference.rb +1 -1
  167. data/when_exe.gemspec +2 -2
  168. metadata +16 -7
@@ -0,0 +1,654 @@
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
+ module When
9
+
10
+ #
11
+ # 暦注 - Calendar Note
12
+ #
13
+ class CalendarNote < TM::ReferenceSystem
14
+
15
+ #
16
+ # 暦注要素への名前アクセス機能提供
17
+ #
18
+ # @private
19
+ module LabelAccess
20
+ attr_reader :_pool
21
+
22
+ #
23
+ # 暦注要素への名前(label)によるアクセス
24
+ #
25
+ # @param [Numeric] key 配列インデックスと見なしてアクセス
26
+ # @param [String] key 名前(label)と見なしてアクセス
27
+ #
28
+ # @return [Object] 暦注要素
29
+ #
30
+ def [](key)
31
+ return super if key.kind_of?(Numeric)
32
+ @_pool ||= Hash[*(inject([]) {|pair, v| pair << v.label.to_s << v})]
33
+ @_pool[key]
34
+ end
35
+ end
36
+
37
+ #
38
+ # 暦注要素のひな形クラス
39
+ #
40
+ # @private
41
+ class NoteElement < When::BasicTypes::Object
42
+ #
43
+ # _m17n_form のための要素生成
44
+ #
45
+ # @param [Hash] options 下記のとおり
46
+ # @option options [Symbol] :method :to_m17n なら label を返す、その他は When::Parts::Resource#to_h 参照
47
+ #
48
+ def _to_hash_value(options={})
49
+ options[:method] == :to_m17n ? label : super
50
+ end
51
+ end
52
+
53
+ #
54
+ # 暦注検索結果を保存するコンテナ
55
+ #
56
+ module Notes
57
+
58
+ class << self
59
+ #
60
+ # 永続データに暦注検索結果を登録する
61
+ #
62
+ # @private
63
+ def register(notes, persistence, sdn)
64
+ if persistence
65
+ persistence.store(sdn, notes)
66
+ persistence.extend(self)
67
+ end
68
+ notes.extend(self)
69
+ end
70
+
71
+ #
72
+ # 永続データから暦注検索結果を取り出す
73
+ #
74
+ # @private
75
+ def retrieve(persistence, sdn)
76
+ return false unless persistence
77
+ persistence.fetch(sdn, false)
78
+ end
79
+
80
+ #
81
+ # パターンの値の一致を判定する
82
+ #
83
+ # @private
84
+ def verify(pattern, value)
85
+ value = value.label if !value.kind_of?(When::BasicTypes::M17n) && value.respond_to?(:label)
86
+ pattern.kind_of?(Regexp) ? value =~ pattern : value == pattern
87
+ end
88
+ end
89
+
90
+ # 暦注検索結果コンテナの次元を下げる
91
+ #
92
+ # @param [Boolean] compact 余分な nil や空配列を除去するか否か
93
+ #
94
+ # @return [Notes]
95
+ #
96
+ def simplify(compact=true)
97
+ if kind_of?(Hash) && !key?(:note)
98
+ # Persistent Notes
99
+ simplified = {}
100
+ each_pair do |key, value|
101
+ value = value.simplify(compact) if value.kind_of?(Notes)
102
+ simplified[key] = value if value
103
+ end
104
+ else
105
+ # Non-Persistent Notes
106
+ simplified = self
107
+ simplified = _compact(simplified) if compact
108
+ simplified = simplified[0] while simplified.kind_of?(Array) && simplified.size <= 1
109
+ end
110
+ _bless(simplified)
111
+ end
112
+
113
+ # 暦注検索結果コンテナのハッシュ要素
114
+ #
115
+ # @param [Boolean] compact 余分な nil や空配列を除去するか否か
116
+ # @param [Symbol] symbol 取り出したいハッシュ要素(:note, :value, etc.)
117
+ #
118
+ # @return [Array] ハッシュ要素からなる配列(元の構造が配列であった場合)
119
+ #
120
+ # @note 引数 symbol が Integer の場合は添え字とみなして元の配列の要素を取り出す
121
+ #
122
+ def value(compact=true, symbol=:value)
123
+ if kind_of?(Hash) && !key?(:note)
124
+ # Persistent Notes
125
+ sliced = {}
126
+ each_pair do |key, val|
127
+ sliced[key] = val[symbol]
128
+ end
129
+ else
130
+ # Non-Persistent Notes
131
+ return _bless(slice(symbol)) if symbol.kind_of?(Integer)
132
+ sliced = _dig(self) {|target| target.fetch(symbol, nil)}
133
+ end
134
+ sliced = _bless(sliced)
135
+ compact ? sliced.simplify : sliced
136
+ end
137
+
138
+ # 暦注検索結果コンテナのハッシュ要素
139
+ #
140
+ # @param [Symbol] symbol 取り出したいハッシュ要素(:note, :value, etc.)
141
+ #
142
+ # @return [Array] ハッシュ要素からなる配列(元の構造が配列であった場合)
143
+ #
144
+ # @note 引数 symbol が Integer の場合は添え字とみなして元の配列の要素を取り出す
145
+ #
146
+ def [](symbol)
147
+ value(false, symbol)
148
+ end
149
+
150
+ # 暦注検索結果コンテナの条件に合う要素を抽出する
151
+ #
152
+ # @param [Hash{Symbol=>String or Regexp}] condition 条件
153
+ # @param [Boolean] compact 余分な nil や空配列を除去するか否か
154
+ #
155
+ # @return [Array] ハッシュ要素からなる配列(元の構造が配列であった場合)
156
+ #
157
+ def subset(condition, compact=true)
158
+ if kind_of?(Hash) && !key?(:note)
159
+ # Persistent Notes
160
+ result = {}
161
+ each_pair do |key, value|
162
+ value = value.subset(condition, compact) if value.kind_of?(Notes)
163
+ result[key] = value if value
164
+ end
165
+ else
166
+ # Non-Persistent Notes
167
+ result = _dig(self) {|target|
168
+ (condition.each_pair {|key, pattern| break nil unless Notes.verify(pattern, target[key])}) ? target : nil
169
+ }
170
+ result = _compact(result) if compact
171
+ end
172
+ _bless(result)
173
+ end
174
+
175
+ private
176
+
177
+ #
178
+ # 対象オブジェクトを Notes にする
179
+ #
180
+ def _bless(target)
181
+ target.extend(Notes) if target && !equal?(target)
182
+ target
183
+ end
184
+
185
+ #
186
+ # 多次元配列要素に対して再帰的に要素を抽出して操作を施す
187
+ #
188
+ def _dig(list, &block)
189
+ return yield(list) unless list.kind_of?(Array)
190
+ list.map {|element| _dig(element, &block)}
191
+ end
192
+
193
+ #
194
+ # 多次元配列要素に対して再帰的に作用し nil や空配列を削除する
195
+ #
196
+ def _compact(list)
197
+ return list unless list.kind_of?(Array)
198
+ result = list.map {|element| _compact(element)}.compact
199
+ return result unless result.empty?
200
+ nil
201
+ end
202
+ end
203
+
204
+ # デフォルトイベント名
205
+ #
206
+ # @return [String]
207
+ #
208
+ # @note イベント名の後ろに数字が使われている場合、数字部分以降はイベントメソッドの引数になります。
209
+ # SolarTermsクラスで 'term180' は、太陽黄経180度のイベントすなわち秋分を意味します。
210
+ #
211
+ attr_accessor :event
212
+ protected :event=
213
+
214
+ # デフォルトイベントの指定
215
+ #
216
+ # @param [String] event 指定値を@eventとした新しいオブジェクトを作る
217
+ #
218
+ # @return [When::CalendarNote]
219
+ #
220
+ def copy(event)
221
+ c = self.clone
222
+ c.event = event
223
+ c
224
+ end
225
+
226
+ # 典型的なイベントの発生間隔
227
+ #
228
+ # @param [String] event
229
+ #
230
+ # @return [When::TM::PeriodDuration]
231
+ #
232
+ def duration(event=@event)
233
+ void, event, parameter = event.split(/^([^\d]+)/)
234
+ send((event+'_delta').downcase.to_sym, parameter)
235
+ end
236
+
237
+ # 指定の日時が指定イベントに該当するか?
238
+ #
239
+ # @param [When::TM::TemporalPosition] date チェックされる日時
240
+ # @param [String] event チェックするイベント名
241
+ #
242
+ # @return [Boolean]
243
+ # [ true - 該当する ]
244
+ # [ false - 該当しない ]
245
+ #
246
+ def include?(date, event=@event)
247
+ enum_for(date, :forward, event.downcase).next.include?(date)
248
+ end
249
+
250
+ # Enumeratorの生成
251
+ #
252
+ # @overload enum_for(range, options={})
253
+ # @param [Range, When::Parts::GeometricComplex] range
254
+ # [ 始点 - range.first ]
255
+ # [ 終点 - range.last ]
256
+ # @param [Hash] options 以下の通り
257
+ # @option options [String] :event イベント名(デフォルトは@event)
258
+ # @option options [Integer] :count_limit 繰り返し回数(デフォルトは指定なし)
259
+ #
260
+ # @overload enum_for(first, direction=:forward, options={})
261
+ # @param [When::TM::TemporalPosition] first 始点
262
+ # @param [Symbol] direction (options[:direction]で渡してもよい)
263
+ # [:forward] 昇順(デフォルト)
264
+ # [:reverse] 降順
265
+ # @param [Hash] options 以下の通り
266
+ # @option options [String] :event イベント名(デフォルトは@event)
267
+ # @option options [Integer] :count_limit 繰り返し回数(デフォルトは指定なし)
268
+ #
269
+ # @return [Enumerator]
270
+ #
271
+ def enum_for(*args)
272
+ params = args.dup
273
+ options = params[-1].kind_of?(Hash) ? params.pop.dup : {}
274
+ options[:event] ||= @event
275
+ self.class::Enumerator.new(*(params[0].kind_of?(Range) ?
276
+ [self, params[0], options] :
277
+ [self, params[0], params[1] || :forward, options]))
278
+ end
279
+ alias :to_enum :enum_for
280
+
281
+ # 暦注の計算
282
+ #
283
+ # @param [When::TM::TemporalPosition] date 暦注を計算する日時
284
+ # @param [When::TM::TemporalPosition 以外] date When::TM::TemporalPosition に変換して使用する
285
+ # @param [String] options { :notes => String } という Hash の指定と等価
286
+ # @param [Integer] options { :indices => Integer} という Hash の指定と等価
287
+ # @param [Hash] options 下記のとおり
288
+ # @option options [Integer] :indices Integerで指定した暦座標の暦注を計算
289
+ # [ When::DAY ( 0) - 日 ]
290
+ # [ When::MONTH(-1) - 月 ]
291
+ # [ When::YEAR (-2) - 年 ]
292
+ #
293
+ # @option options [Array<Integer>] :indices Integerで指定したすべて暦座標の暦注を計算
294
+ # @option options [nil] :indices すべての暦座標の暦注を計算(デフォルト)
295
+ # @option options [String] :notes 計算する暦注名(日の暦注)
296
+ # @option options [Integer] :notes 計算する暦注のビット配列(日の暦注)
297
+ # @option options [Array<Array<String>>] :notes 計算する暦注名の Array の Array
298
+ # @option options [Array<Integer>] :notes 計算する暦注のビット配列の Array
299
+ # @option options [:all] :notes すべての暦注を計算
300
+ # @option options [:prime, nil] :notes @prime に登録した暦注を計算、@prime未登録なら :all と同じ(デフォルト)
301
+ # @option options [Hash] :persistence {ユリウス通日=>暦注計算結果}を保持する永続オブジェクト
302
+ # @option options [Hash] :conditions 暦注計算の条件
303
+ # [ :location => 暦注計算の基準となる場所(String or When::Coordinates::Spatial) ]
304
+ # [ その他のキー => 個々の暦注クラスごとにその他のキーを使用できる ]
305
+ #
306
+ # @option options [Hash] その他のキー date を When::TM::TemporalPosition に変換するために使用する
307
+ # see {When::TM::TemporalPosition._instance}
308
+ #
309
+ # @note CalendarNoteオブジェクト生成時に _normalize メソッド内で @prime 変数を設定しておけば、
310
+ # 本メソッドの :prime オプションで参照される。(BalineseNote#_normalize等参照)
311
+ #
312
+ # @note 暦注のビットアドレスは、暦注サブクラスのNoteObjects定数の中の定義順序による。
313
+ # When::CalendarNote クラスの場合 new の引数とした暦注要素リストの定義順序による。
314
+ # ビットアドレスの値が 1 の暦注が計算対象となる。
315
+ #
316
+ # @return [Array<Array<Hash>>] 暦注計算結果(When::CalendarNote::Notesモジュールをextendしている)
317
+ # [ :note => 暦注要素 (When::Coordinates::Residue, String, When::BasicTypes::M17n) ]
318
+ # [ :value => 暦注の値 (When::Coordinates::Residue, String, When::BasicTypes::M17n, When::TM::TemporalPosition) ]
319
+ #
320
+ # @note
321
+ # 戻り値の :value が When::TM::TemporalPosition の場合、その日時オブジェクトの events[0] に暦注名の入った
322
+ # 暦注に該当する日付である。(例) Christian クラス で easter を計算した場合、当該年の復活祭の日付オブジェクトが返る。
323
+ # @note
324
+ # 暦注サブクラスの場合、暦注要素が増えたり、:note の暦注要素の型が変わったりすることがある。
325
+ #
326
+ def notes(date, options={})
327
+ dates, indices, notes, persistence, conditions, options = _parse_note(date, options)
328
+ retrieved = Notes.retrieve(persistence, date.to_i)
329
+ return retrieved unless retrieved == false
330
+ Notes.register(indices.map {|i|
331
+ next [] unless i <= date.precision
332
+ _note_values(dates, notes[i-1], _all_keys[i-1], _elements[i-1]) do |dates, focused_notes, notes_hash|
333
+ focused_notes.each do |note|
334
+ unless notes_hash[note]
335
+ void, event, *parameter = note.split(/^([^\d]+)/)
336
+ method = event.downcase
337
+ parameter << conditions unless conditions.empty?
338
+ notes_hash[note] =
339
+ if respond_to?(method)
340
+ send(method, dates, *parameter)
341
+ else
342
+ _elements[i-1][note].send(When::Coordinates::PRECISION_NAME[i].downcase, dates)
343
+ end
344
+ end
345
+ end
346
+ notes_hash
347
+ end
348
+ }, persistence, date.to_i)
349
+ end
350
+
351
+ #
352
+ # 暦注の一致 or 不一致
353
+ #
354
+ # @param [When::TM::TemporalPosition] date 暦注を確認する日時
355
+ # @param [When::TM::TemporalPosition 以外] date When::TM::TemporalPosition に変換して使用する
356
+ # @param [String] options { :notes => String } または { :value => String } という Hash の指定と等価
357
+ # (指定の notes が存在する場合は前者、しない場合は後者)
358
+ # @param [Integer] options { :indices => Integer } という Hash の指定と等価
359
+ # @param [Hash] options 下記のとおり
360
+ # @option options [暦注の値] :value 確認する暦注の値(または正規表現)
361
+ # @option options [それぞれ] その他 {When::CalendarNote#notes} を参照
362
+ #
363
+ # @return [Boolean]
364
+ # [ true - 暦注が一致 ]
365
+ # [ false - 暦注が不一致 ]
366
+ #
367
+ def note?(date, options={})
368
+ options = _find_note(options) if options.kind_of?(String)
369
+ pattern = options.delete(:value) if options.kind_of?(Hash)
370
+ result = notes(date, options)
371
+ result.flatten!
372
+ result.delete_if {|hash| hash.empty?}
373
+ return false unless result.size > 0
374
+ return true unless pattern
375
+ result.each do |hash|
376
+ return true if Notes.verify(pattern, hash[:value])
377
+ end
378
+ return false
379
+ end
380
+
381
+ # 年の名前を暦注として返す
382
+ # @method year
383
+ # @return [When::BasicTypes::M17n]
384
+
385
+ # 月の名前を暦注として返す
386
+ # @method month
387
+ # @return [When::BasicTypes::M17n]
388
+
389
+ # 日の名前を暦注として返す
390
+ # @method day
391
+ # @return [When::BasicTypes::M17n]
392
+
393
+ #
394
+ # 標準的な暦注として、暦座標の値の名前を暦注として返すメソッドを登録
395
+ #
396
+ # @private
397
+ ['year', 'month', 'day'].each do |c|
398
+ module_eval %Q{
399
+ def #{c}(date)
400
+ date.name('#{c}')
401
+ end
402
+ }
403
+ end
404
+
405
+ private
406
+
407
+ #
408
+ # オブジェクトの正規化
409
+ #
410
+ def _normalize(args=[], options={})
411
+ @_elements = (args.size == 0 && self.class.const_defined?(:NoteObjects)) ?
412
+ When::Parts::Resource.base_uri + self.class.to_s.split(/::/)[1..-1].join('/') + '/NoteObjects' :
413
+ _to_iri(args, options[:prefix] || '_co:')
414
+ if @_elements.kind_of?(Array)
415
+ @_elements.each do |e|
416
+ e.extend LabelAccess
417
+ end
418
+ end
419
+ end
420
+
421
+ # 暦注要素
422
+ #
423
+ # @return [Array<Array<When::Parts::Resource>>]
424
+ #
425
+ def _elements
426
+ @_elements = When.Resource(@_elements) if @_elements.kind_of?(String)
427
+ @_elements
428
+ end
429
+
430
+ #
431
+ # [[暦注名]](全暦注)
432
+ #
433
+ # @return [Array<Array<String, When::BasicTypes::M17n>>]
434
+ #
435
+ def _all_keys
436
+ @_all_keys ||= _elements.map { |c|
437
+ c.map {|n|
438
+ n.label.to_s
439
+ }
440
+ }
441
+ end
442
+
443
+ #
444
+ # [[暦注名]](主要暦注)
445
+ #
446
+ # @return [Array<Array<When::Parts::Resource>>]
447
+ #
448
+ def _prime_keys
449
+ @prime ||= _all_keys
450
+ end
451
+
452
+ #
453
+ # notes メソッドの引数を parse する
454
+ #
455
+ # @return [Array] dates, indices, notes
456
+ #
457
+ def _parse_note(date, options)
458
+ options =
459
+ case options
460
+ when Hash ; options
461
+ when String ; {:notes => options}
462
+ when Integer ; {:indices => options}
463
+ else ; {}
464
+ end
465
+ conditions = options.delete(:conditions) || {}
466
+ _opt = options.dup
467
+ persistence = _opt.delete(:persistence)
468
+ notes = _notes(_opt.delete(:notes) || :prime)
469
+ indices = _indices(_opt.delete(:indices), notes)
470
+ _opt.keys.each do |key|
471
+ conditions[key] = _opt[key] unless date.class::FormOptions.include?(key)
472
+ end
473
+ [_to_date_for_note(date), indices, notes, persistence, conditions, options]
474
+ end
475
+
476
+ #
477
+ # notes メソッドの 文字列引数の意味を解釈する
478
+ #
479
+ # @return [Hash] options for note String
480
+ #
481
+ def _find_note(note)
482
+ _elements.each_index do |index|
483
+ return {:notes=>note, :indices => [-index]} if _elements[-1-index]._pool[note]
484
+ end
485
+ {:value => note}
486
+ end
487
+
488
+ #
489
+ # 計算する暦注
490
+ #
491
+ # @return [Array<Array<String>, Integer>]
492
+ #
493
+ def _notes(notes)
494
+ case notes
495
+ when :all ; _all_keys
496
+ when :prime ; _prime_keys
497
+ when Integer ; [notes]
498
+ when String ; [[notes]]
499
+ else ; notes
500
+ end
501
+ end
502
+
503
+ #
504
+ # 暦注を計算する暦座標の配列
505
+ #
506
+ # @return [Array<Integer>]
507
+ #
508
+ def _indices(indices, notes)
509
+ case indices
510
+ when nil ; (0...notes.size).to_a.reverse.map {|i| -i}
511
+ when Range ; indices.to_a
512
+ when Array ; indices
513
+ else ; [indices.to_i]
514
+ end
515
+ end
516
+
517
+ #
518
+ # 年月日暦注計算の共通処理 - コールバック元
519
+ #
520
+ def _note_values(dates, focused_notes, all_notes, note_objects)
521
+ return [] unless dates && all_notes
522
+
523
+ # prepare focused notes
524
+ case focused_notes
525
+ when Integer
526
+ bits = ~focused_notes << 1
527
+ focused_notes = all_notes.dup.delete_if { (bits>>=1)[0] == 1 }
528
+ when []
529
+ focused_notes = all_notes
530
+ when nil
531
+ focused_notes = []
532
+ end
533
+ focused_notes = focused_notes.dup
534
+ not_focused_notes = all_notes - focused_notes
535
+ notes = {}
536
+ not_focused_notes.each do |note|
537
+ notes[note] = true
538
+ end
539
+ focused_notes.each do |note|
540
+ notes[note] = nil
541
+ end
542
+
543
+ # update notes
544
+ notes = yield(dates, focused_notes, notes)
545
+ notes.keys.each do |note|
546
+ notes.delete(note) unless focused_notes.include?(note)
547
+ end
548
+
549
+ # return Array of Hash
550
+ focused_notes.map {|note|
551
+ next {} unless notes[note]
552
+ if note_objects[note].respond_to?(:to_note_hash)
553
+ note_objects[note].to_note_hash(notes[note], dates)
554
+ else
555
+ {:note=>note_objects[note].label, :value=>notes[note]}
556
+ end
557
+ }
558
+ end
559
+
560
+ #
561
+ # 再帰的に配列の中を Resource化する
562
+ #
563
+ def _to_iri(args, prefix)
564
+ args.map {|arg|
565
+ case arg
566
+ when String
567
+ arg, method = $1, $2 if (arg =~ /^(.+)#([_A-Z0-9]+)$/i)
568
+ obj = When.Resource(arg, prefix)
569
+ obj = obj.copy(method) if method
570
+ obj
571
+ when Array
572
+ _to_iri(arg, prefix)
573
+ else
574
+ arg
575
+ end
576
+ }
577
+ end
578
+
579
+ #
580
+ # 暦日を当該暦注計算用クラスに変換
581
+ #
582
+ # 基底クラスである本クラスでは何もしないで、引数をそのまま返す
583
+ #
584
+ def _to_date_for_note(date)
585
+ date
586
+ end
587
+
588
+ #
589
+ # イベントを取得する Enumerator
590
+ #
591
+ class Enumerator < When::Parts::Enumerator
592
+
593
+ #
594
+ # 次のイベントを得る
595
+ #
596
+ # @return [When::TM::TemporalPosition]
597
+ #
598
+ def _succ
599
+ @current = (@current==:first) ? @first : event_eval(@current + @delta)
600
+ end
601
+
602
+ # オブジェクトの生成
603
+ #
604
+ # @overload initialize(parent, range, options)
605
+ # @param [When::CalendarNote] parent 暦注アルゴリズム
606
+ # @param [Range, When::Parts::GeometricComplex] range
607
+ # [ 始点 - range.first ]
608
+ # [ 終点 - range.last ]
609
+ # @param [Hash] options 以下の通り
610
+ # @option options [String] :event イベント名
611
+ # @option options [Integer] :count_limit 繰り返し回数(デフォルトは指定なし)
612
+ #
613
+ # @overload initialize(parent, first, direction, options)
614
+ # @param [When::CalendarNote] parent 暦注アルゴリズム
615
+ # @param [When::TM::TemporalPosition] first 始点
616
+ # @param [Symbol] direction (options[:direction]で渡してもよい)
617
+ # [:forward] 昇順(デフォルト)
618
+ # [:reverse] 降順
619
+ # @param [Hash] options 以下の通り
620
+ # @option options [String] :event イベント名
621
+ # @option options [Integer] :count_limit 繰り返し回数(デフォルトは指定なし)
622
+ #
623
+ def initialize(*args)
624
+ if args[1].kind_of?(Range)
625
+ parent, range, options = args
626
+ first = range.first
627
+ last = range.last
628
+ direction = first < last ? :forward : :reverse
629
+ else
630
+ parent, first, direction, options = args
631
+ end
632
+ direction = options[:direction] if options[:direction]
633
+ @parent = parent
634
+ void, @event, @parameter = options.delete(:event).split(/^([^\d]+)/)
635
+ @delta = @parent.send((@event+'_delta').to_sym, @parameter)
636
+ instance_eval %Q{
637
+ def event_eval(date)
638
+ @parent.#{@event}(date, @parameter)
639
+ end
640
+ }
641
+ date = event_eval(first)
642
+ if direction == :reverse
643
+ @delta = -@delta
644
+ date = event_eval(first + @delta) if first.to_i < date.to_i
645
+ else
646
+ date = event_eval(first + @delta) if first.to_i > date.to_i
647
+ end
648
+ range ?
649
+ super(@parent, range.exclude_end? ? date...last : date..last, options) :
650
+ super(@parent, date, direction, options)
651
+ end
652
+ end
653
+ end
654
+ end