when_exe 0.3.4 → 0.3.5

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