when_exe 0.4.0 → 0.4.1

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.
@@ -1,307 +1,307 @@
1
- # -*- coding: utf-8 -*-
2
- =begin
3
- Copyright (C) 2013-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
- require 'socket'
9
-
10
- #
11
- # Time for v1.8.x compatibility
12
- #
13
- class Time
14
- if Time.now.respond_to?(:strftime) && Time.now.strftime('%FT%X.%L').length > 0
15
- alias :_log_ :strftime
16
- else
17
- def _log_(format)
18
- "%04d-%02d-%02dT%02d:%02d:%02d.%03d" % [year, month, day, hour, min, sec, usec / 1000]
19
- end
20
- end
21
- end
22
-
23
- #
24
- # Micro Client / Server
25
- #
26
- module When
27
- class << self
28
-
29
- #
30
- # 設定ファイルを読み込む
31
- # @private
32
- def config(path=File.expand_path($0) + '.config')
33
- config = {}
34
- open(path, 'r') do |file|
35
- while (line=file.gets)
36
- next if line =~ /\A\s*#/
37
- key, *value = line.chomp.split(':')
38
- value = value[0] if value.size <= 1
39
- config[key] = value
40
- end
41
- end
42
- config
43
- rescue
44
- {}
45
- end
46
-
47
- #
48
- # マイクロ・サーバーを起動する
49
- #
50
- # @param [#to_i] port 待ち受けるポート番号
51
- #
52
- # @return [void]
53
- #
54
- # @note mini_application
55
- #
56
- def server(port)
57
- config = When.config
58
- TCPServer.open(port.to_i) do |socket|
59
- puts Time.now._log_('%FT%X.%L') + ': Start'
60
- loop do
61
- Thread.start(socket.accept) do |client|
62
- query = client.gets.chomp.force_encoding("UTF-8")
63
- start = Time.now
64
- puts start._log_('%FT%X.%L') + ': Query - ' + When::Locale.translate(query, config['!'])
65
- begin
66
- result = free_conv(*query.split(/\s+/))
67
- result = When::Locale.translate(result, config['!'])
68
- client.puts JSON.generate(Array(_to_string(result))).to_s
69
- stop = Time.now
70
- puts stop._log_('%FT%X.%L') + ": Respond (%7.0f ms)" % (1000 * (stop.to_f - start.to_f))
71
- rescue => err
72
- puts Time.now._log_('%FT%X.%L') + ': error - ' + err.to_s
73
- client.puts JSON.generate({:error=>query}).to_s
74
- end
75
- client.close
76
- end
77
- end
78
- end
79
- rescue Exception => e
80
- puts Time.now._log_('%FT%X.%L') + ': Exception - ' + e.to_s
81
- ensure
82
- puts Time.now._log_('%FT%X.%L') + ': Done.'
83
- end
84
-
85
- #
86
- # マイクロ・クライアントを実行する
87
- #
88
- # @param [String] server マイクロ・サーバのアドレス
89
- # @param [#to_i] port つなぐポート番号
90
- # @param [String] query 問い合わせ文字列
91
- #
92
- # @return [JSON] 応答
93
- #
94
- # @note mini_application
95
- #
96
- def client(server, port, query)
97
- TCPSocket.open(server, port.to_i) do |socket|
98
- socket.puts(query)
99
- results = JSON.parse(socket.gets.force_encoding("UTF-8"))
100
- results = Hash[*results.flatten(1)] if results[0].kind_of?(Array)
101
- _to_symbol(results)
102
- end
103
- end
104
-
105
- # 日付の自由変換
106
- #
107
- # @param [Array<String, When::TM::TemporalPosition, When::TM::CalendarEra or When::TM::Calendar>] args コマンドライン入力
108
- # @param [Block] block ブロック
109
- #
110
- # @return [Array<Hash>] 変換結果
111
- # @return [Array<Array<Numeric>>] 最良近似分数列
112
- #
113
- # @note 暦法のIRI, When.exe Standard Expression, 最良近似分数列の分母分子などを文字列で指定
114
- # @note mini_application
115
- #
116
- def free_conv(*args, &block)
117
- calendars, dates, numbers, methods, output, options = _parse_command(args)
118
-
119
- if numbers.size >= 2 && calendars.size == 0
120
- result = []
121
- When::Coordinates::Residue.new(numbers[0], numbers[1]).each { |v| result << v }
122
- return result
123
- end
124
-
125
- block ||=
126
- if methods.size == 0
127
- lambda {|date| date.send(*output)}
128
- else
129
- lambda {|date, type| column(date, type)}
130
- end
131
- _free_conv(calendars, dates, methods, output, options, &block)
132
- end
133
-
134
- # 七曜表の一日分
135
- #
136
- # @param [When::TM::TemporalPosition] date 処理する一日
137
- # @param [Integer, nil] type 当該日の種類
138
- #
139
- # @return [Object>] 処理結果
140
- #
141
- def column(date, type)
142
- case type
143
- when When::YEAR ; date.strftime("%Y")
144
- when When::MONTH ; date.strftime("%B %Y")
145
- when When::WEEK ; nil
146
- when When::DAY ; date[0]
147
- else ; '-'
148
- end
149
- end
150
-
151
- private
152
-
153
- # to_h メソッドのオプション設定
154
- HashMethod = {:iri => [:to_h, {:method=>:iri , :prefix=>true}],
155
- :to_m17n => [:to_h, {:method=>:to_m17n, :prefix=>true}]}
156
-
157
- # 引数読み込み
158
- #
159
- # args [String] コマンドライン入力
160
- #
161
- # @return [Array] ( calendars, dates, numbers, methods )
162
- # [ calendars [Array<When::TM::Calendar or When::TM::CalendarEra>]]
163
- # [ dates [Array<When::TM::CalData or When::TM::DateAndTime>] ]
164
- # [ numbers [Array<Numeric>]]
165
- # [ methods [Array<String>] メソッド名('week', 'month', 'year') ]
166
- # [ output [Array<Symbol, String>] 出力処理に使うメソッドのシンボルと引数 ]
167
- # [ options [Hash{ :extent=>Boolean, :go_back=><:All || :Before(nil) || :After> }]
168
- #
169
- def _parse_command(args)
170
- calendars = []
171
- dates = []
172
- numbers = []
173
- methods = []
174
- options = {}
175
- output = [:to_s]
176
-
177
- config = When.config
178
- args.flatten.each do |arg|
179
- case arg
180
- when Numeric ; dates << arg ; numbers << arg
181
- when Hash ; options.update(arg)
182
- when Range ; arg.each {|d| dates << d}
183
- when Symbol ; output = [arg]
184
- when When::TM::CalendarEra,
185
- When::TM::Calendar ; calendars << arg
186
- when String
187
- arg = When::EncodingConversion.to_internal_encoding(arg)
188
- case arg
189
- when /\A:(.+?)(?:\[(..)\])?\z/ ; output = [$1.to_sym, $2].compact
190
- when /\A(year|month|week)(?:\[(..)\])?\z/i ; methods << [$1.downcase + '_included', $2||'SU']
191
- when /\A[-+\d]\d*\z/ ; dates << arg.to_i ; numbers << arg.to_i
192
- when /\A[-+.\d][.\d]*\z/ ; dates << arg.to_f ; numbers << arg.to_f
193
- when /\Anow\z/i ; dates << When.now
194
- when /\Atoday\z/i ; dates << When.today
195
- when /(^[-+\d])|\^/ ; dates << arg
196
- when /\A\//
197
- arg[1..-1].scan(/./) do |c|
198
- c = c.upcase
199
- if config.key?(c)
200
- calendar = config[c]
201
- calendar = calendar.join(':') if calendar.kind_of?(Array)
202
- calendars << When.Calendar(calendar)
203
- elsif c == 'D'
204
- calendars << When::TM::JulianDate
205
- end
206
- end
207
- else
208
- begin
209
- calendars << ((arg == 'JulianDate') ? When::TM::JulianDate : When.Calendar(arg))
210
- rescue NameError, OpenURI::HTTPError
211
- dates << arg
212
- end
213
- end
214
- else
215
- dates << arg
216
- end
217
- end
218
- [calendars, dates, numbers, methods, HashMethod[output[0]] || output, options]
219
- end
220
-
221
- # 変換処理(実行部)
222
- #
223
- # @param [When::TM::Calendar, When::TM::CalendarEra] calendars
224
- # @param [When::TM::CalData, When::TM::DateAndTime] dates
225
- # @param [String] methods メソッド名('week', 'month', 'year')
226
- # @param [Hash] options {:extent=>Boolean, :go_back=><:All||:Before(nil)||:After>}
227
- #
228
- # @return [Array] 変換結果
229
- #
230
- def _free_conv(calendars, dates, methods, output, options, &block)
231
- dates[0] ||= When.now
232
- calendars[0] ||= When::Gregorian
233
- result = dates.map {|date|
234
- date = When.when?(date)
235
- opts = {}
236
- opts[:location] = date.location if date.location
237
- opts[:clock ] = date.clock if date.respond_to?(:clock) && date.clock
238
- list = calendars.dup
239
- (0...calendars.size).to_a.reverse.each do |i|
240
- case list[i]
241
- when When::TM::Calendar ; list.slice!(i) if options[:extent] && !list[i].domain[''].include?(date)
242
- when Class ;
243
- else
244
- eras = (date ^ list[i]).delete_if {|e| !e.leaf?}
245
- unless options[:go_back] == :All
246
- if options[:go_back] == :After
247
- eras = [eras[(eras.index {|e| e.calendar_era_name[3]}) || -1]]
248
- else
249
- eras.delete_if {|e| e.calendar_era_name[3]}
250
- end
251
- end
252
- list[i,1] = eras.map {|e| e.calendar_era}
253
- end
254
- end
255
-
256
- if methods.size == 0
257
- list.map {|calendar|
258
- calendar.kind_of?(Class) ?
259
- yield(calendar.new(date, opts.dup)) :
260
- yield(calendar.^(calendar.rate_of_clock == date.time_standard.rate_of_clock ? date.to_i : date, opts))
261
- }
262
- else
263
- list.map {|calendar|
264
- date_for_calendar = calendar.^(calendar.rate_of_clock == date.time_standard.rate_of_clock ? date.to_i : date, opts)
265
- methods.map {|method|
266
- date_for_calendar.send(method[0].to_sym, method[1], &block)
267
- }
268
- }
269
- end
270
- }
271
- result = result[0] while result.kind_of?(Array) && result.size == 1
272
- return result
273
- end
274
-
275
- # JSONで通信するために Symbol を String に変換する
276
- def _to_string(source)
277
- case source
278
- when Array
279
- source.map {|e| _to_string(e)}
280
- when Hash
281
- result = {}
282
- source.each_pair {|k,v|
283
- result[k.kind_of?(Symbol) ? '_sym_' + k.to_s : k] = _to_string(v)
284
- }
285
- result
286
- else
287
- source
288
- end
289
- end
290
-
291
- # JSONで通信するために String を Symbol に変換する
292
- def _to_symbol(source)
293
- case source
294
- when Array
295
- source.map {|e| _to_symbol(e)}
296
- when Hash
297
- result = {}
298
- source.each_pair {|k,v|
299
- result[k =~ /\A_sym_(.+)\z/ ? $1.to_sym : k] = _to_symbol(v)
300
- }
301
- result
302
- else
303
- source
304
- end
305
- end
306
- end
307
- end
1
+ # -*- coding: utf-8 -*-
2
+ =begin
3
+ Copyright (C) 2013-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
+ require 'socket'
9
+
10
+ #
11
+ # Time for v1.8.x compatibility
12
+ #
13
+ class Time
14
+ if Time.now.respond_to?(:strftime) && Time.now.strftime('%FT%X.%L').length > 0
15
+ alias :_log_ :strftime
16
+ else
17
+ def _log_(format)
18
+ "%04d-%02d-%02dT%02d:%02d:%02d.%03d" % [year, month, day, hour, min, sec, usec / 1000]
19
+ end
20
+ end
21
+ end
22
+
23
+ #
24
+ # Micro Client / Server
25
+ #
26
+ module When
27
+ class << self
28
+
29
+ #
30
+ # 設定ファイルを読み込む
31
+ # @private
32
+ def config(path=File.expand_path($0) + '.config')
33
+ config = {}
34
+ open(path, 'r') do |file|
35
+ while (line=file.gets)
36
+ next if line =~ /\A\s*#/
37
+ key, *value = line.chomp.split(':')
38
+ value = value[0] if value.size <= 1
39
+ config[key] = value
40
+ end
41
+ end
42
+ config
43
+ rescue
44
+ {}
45
+ end
46
+
47
+ #
48
+ # マイクロ・サーバーを起動する
49
+ #
50
+ # @param [#to_i] port 待ち受けるポート番号
51
+ #
52
+ # @return [void]
53
+ #
54
+ # @note mini_application
55
+ #
56
+ def server(port)
57
+ config = When.config
58
+ TCPServer.open(port.to_i) do |socket|
59
+ puts Time.now._log_('%FT%X.%L') + ': Start'
60
+ loop do
61
+ Thread.start(socket.accept) do |client|
62
+ query = client.gets.chomp.force_encoding("UTF-8")
63
+ start = Time.now
64
+ puts start._log_('%FT%X.%L') + ': Query - ' + When::Locale.translate(query, config['!'])
65
+ begin
66
+ result = free_conv(*query.split(/\s+/))
67
+ result = When::Locale.translate(result, config['!'])
68
+ client.puts JSON.generate(Array(_to_string(result))).to_s
69
+ stop = Time.now
70
+ puts stop._log_('%FT%X.%L') + ": Respond (%7.0f ms)" % (1000 * (stop.to_f - start.to_f))
71
+ rescue => err
72
+ puts Time.now._log_('%FT%X.%L') + ': error - ' + err.to_s
73
+ client.puts JSON.generate({:error=>query}).to_s
74
+ end
75
+ client.close
76
+ end
77
+ end
78
+ end
79
+ rescue Exception => e
80
+ puts Time.now._log_('%FT%X.%L') + ': Exception - ' + e.to_s
81
+ ensure
82
+ puts Time.now._log_('%FT%X.%L') + ': Done.'
83
+ end
84
+
85
+ #
86
+ # マイクロ・クライアントを実行する
87
+ #
88
+ # @param [String] server マイクロ・サーバのアドレス
89
+ # @param [#to_i] port つなぐポート番号
90
+ # @param [String] query 問い合わせ文字列
91
+ #
92
+ # @return [JSON] 応答
93
+ #
94
+ # @note mini_application
95
+ #
96
+ def client(server, port, query)
97
+ TCPSocket.open(server, port.to_i) do |socket|
98
+ socket.puts(query)
99
+ results = JSON.parse(socket.gets.force_encoding("UTF-8"))
100
+ results = Hash[*results.flatten(1)] if results[0].kind_of?(Array)
101
+ _to_symbol(results)
102
+ end
103
+ end
104
+
105
+ # 日付の自由変換
106
+ #
107
+ # @param [Array<String, When::TM::TemporalPosition, When::TM::CalendarEra or When::TM::Calendar>] args コマンドライン入力
108
+ # @param [Block] block ブロック
109
+ #
110
+ # @return [Array<Hash>] 変換結果
111
+ # @return [Array<Array<Numeric>>] 最良近似分数列
112
+ #
113
+ # @note 暦法のIRI, When.exe Standard Expression, 最良近似分数列の分母分子などを文字列で指定
114
+ # @note mini_application
115
+ #
116
+ def free_conv(*args, &block)
117
+ calendars, dates, numbers, methods, output, options = _parse_command(args)
118
+
119
+ if numbers.size >= 2 && calendars.size == 0
120
+ result = []
121
+ When::Coordinates::Residue.new(numbers[0], numbers[1]).each { |v| result << v }
122
+ return result
123
+ end
124
+
125
+ block ||=
126
+ if methods.size == 0
127
+ lambda {|date| date.send(*output)}
128
+ else
129
+ lambda {|date, type| column(date, type)}
130
+ end
131
+ _free_conv(calendars, dates, methods, output, options, &block)
132
+ end
133
+
134
+ # 七曜表の一日分
135
+ #
136
+ # @param [When::TM::TemporalPosition] date 処理する一日
137
+ # @param [Integer, nil] type 当該日の種類
138
+ #
139
+ # @return [Object>] 処理結果
140
+ #
141
+ def column(date, type)
142
+ case type
143
+ when When::YEAR ; date.strftime("%Y")
144
+ when When::MONTH ; date.strftime("%B %Y")
145
+ when When::WEEK ; nil
146
+ when When::DAY ; date[0]
147
+ else ; '-'
148
+ end
149
+ end
150
+
151
+ private
152
+
153
+ # to_h メソッドのオプション設定
154
+ HashMethod = {:iri => [:to_h, {:method=>:iri , :prefix=>true}],
155
+ :to_m17n => [:to_h, {:method=>:to_m17n, :prefix=>true}]}
156
+
157
+ # 引数読み込み
158
+ #
159
+ # args [String] コマンドライン入力
160
+ #
161
+ # @return [Array] ( calendars, dates, numbers, methods )
162
+ # [ calendars [Array<When::TM::Calendar or When::TM::CalendarEra>]]
163
+ # [ dates [Array<When::TM::CalData or When::TM::DateAndTime>] ]
164
+ # [ numbers [Array<Numeric>]]
165
+ # [ methods [Array<String>] メソッド名('week', 'month', 'year') ]
166
+ # [ output [Array<Symbol, String>] 出力処理に使うメソッドのシンボルと引数 ]
167
+ # [ options [Hash{ :extent=>Boolean, :go_back=><:All || :Before(nil) || :After> }]
168
+ #
169
+ def _parse_command(args)
170
+ calendars = []
171
+ dates = []
172
+ numbers = []
173
+ methods = []
174
+ options = {}
175
+ output = [:to_s]
176
+
177
+ config = When.config
178
+ args.flatten.each do |arg|
179
+ case arg
180
+ when Numeric ; dates << arg ; numbers << arg
181
+ when Hash ; options.update(arg)
182
+ when Range ; arg.each {|d| dates << d}
183
+ when Symbol ; output = [arg]
184
+ when When::TM::CalendarEra,
185
+ When::TM::Calendar ; calendars << arg
186
+ when String
187
+ arg = When::EncodingConversion.to_internal_encoding(arg)
188
+ case arg
189
+ when /\A:(.+?)(?:\[(..)\])?\z/ ; output = [$1.to_sym, $2].compact
190
+ when /\A(year|month|week)(?:\[(..)\])?\z/i ; methods << [$1.downcase + '_included', $2||'SU']
191
+ when /\A[-+\d]\d*\z/ ; dates << arg.to_i ; numbers << arg.to_i
192
+ when /\A[-+.\d][.\d]*\z/ ; dates << arg.to_f ; numbers << arg.to_f
193
+ when /\Anow\z/i ; dates << When.now
194
+ when /\Atoday\z/i ; dates << When.today
195
+ when /(^[-+\d])|\^/ ; dates << arg
196
+ when /\A\//
197
+ arg[1..-1].scan(/./) do |c|
198
+ c = c.upcase
199
+ if config.key?(c)
200
+ calendar = config[c]
201
+ calendar = calendar.join(':') if calendar.kind_of?(Array)
202
+ calendars << When.Calendar(calendar)
203
+ elsif c == 'D'
204
+ calendars << When::TM::JulianDate
205
+ end
206
+ end
207
+ else
208
+ begin
209
+ calendars << ((arg == 'JulianDate') ? When::TM::JulianDate : When.Calendar(arg))
210
+ rescue NameError, OpenURI::HTTPError
211
+ dates << arg
212
+ end
213
+ end
214
+ else
215
+ dates << arg
216
+ end
217
+ end
218
+ [calendars, dates, numbers, methods, HashMethod[output[0]] || output, options]
219
+ end
220
+
221
+ # 変換処理(実行部)
222
+ #
223
+ # @param [When::TM::Calendar, When::TM::CalendarEra] calendars
224
+ # @param [When::TM::CalData, When::TM::DateAndTime] dates
225
+ # @param [String] methods メソッド名('week', 'month', 'year')
226
+ # @param [Hash] options {:extent=>Boolean, :go_back=><:All||:Before(nil)||:After>}
227
+ #
228
+ # @return [Array] 変換結果
229
+ #
230
+ def _free_conv(calendars, dates, methods, output, options, &block)
231
+ dates[0] ||= When.now
232
+ calendars[0] ||= When::Gregorian
233
+ result = dates.map {|date|
234
+ date = When.when?(date)
235
+ opts = {}
236
+ opts[:location] = date.location if date.location
237
+ opts[:clock ] = date.clock if date.respond_to?(:clock) && date.clock
238
+ list = calendars.dup
239
+ (0...calendars.size).to_a.reverse.each do |i|
240
+ case list[i]
241
+ when When::TM::Calendar ; list.slice!(i) if options[:extent] && !list[i].domain[''].include?(date)
242
+ when Class ;
243
+ else
244
+ eras = (date ^ list[i]).delete_if {|e| !e.leaf?}
245
+ unless options[:go_back] == :All
246
+ if options[:go_back] == :After
247
+ eras = [eras[(eras.index {|e| e.calendar_era_go_back}) || -1]]
248
+ else
249
+ eras.delete_if {|e| e.calendar_era_go_back}
250
+ end
251
+ end
252
+ list[i,1] = eras.map {|e| e.calendar_era}
253
+ end
254
+ end
255
+
256
+ if methods.size == 0
257
+ list.map {|calendar|
258
+ calendar.kind_of?(Class) ?
259
+ yield(calendar.new(date, opts.dup)) :
260
+ yield(calendar.^(calendar.rate_of_clock == date.time_standard.rate_of_clock ? date.to_i : date, opts))
261
+ }
262
+ else
263
+ list.map {|calendar|
264
+ date_for_calendar = calendar.^(calendar.rate_of_clock == date.time_standard.rate_of_clock ? date.to_i : date, opts)
265
+ methods.map {|method|
266
+ date_for_calendar.send(method[0].to_sym, method[1], &block)
267
+ }
268
+ }
269
+ end
270
+ }
271
+ result = result[0] while result.kind_of?(Array) && result.size == 1
272
+ return result
273
+ end
274
+
275
+ # JSONで通信するために Symbol を String に変換する
276
+ def _to_string(source)
277
+ case source
278
+ when Array
279
+ source.map {|e| _to_string(e)}
280
+ when Hash
281
+ result = {}
282
+ source.each_pair {|k,v|
283
+ result[k.kind_of?(Symbol) ? '_sym_' + k.to_s : k] = _to_string(v)
284
+ }
285
+ result
286
+ else
287
+ source
288
+ end
289
+ end
290
+
291
+ # JSONで通信するために String を Symbol に変換する
292
+ def _to_symbol(source)
293
+ case source
294
+ when Array
295
+ source.map {|e| _to_symbol(e)}
296
+ when Hash
297
+ result = {}
298
+ source.each_pair {|k,v|
299
+ result[k =~ /\A_sym_(.+)\z/ ? $1.to_sym : k] = _to_symbol(v)
300
+ }
301
+ result
302
+ else
303
+ source
304
+ end
305
+ end
306
+ end
307
+ end