metric_tools 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gem 'google_drive', '~>0'
4
+ gem 'hirb', '~>0'
5
+ gem 'aws-s3', '~>0'
data/Gemfile.lock ADDED
@@ -0,0 +1,29 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ faraday (0.8.4)
5
+ multipart-post (~> 1.1)
6
+ google_drive (0.3.2)
7
+ nokogiri (>= 1.4.4, != 1.5.2, != 1.5.1)
8
+ oauth (>= 0.3.6)
9
+ oauth2 (>= 0.5.0)
10
+ httpauth (0.2.0)
11
+ jwt (0.1.5)
12
+ multi_json (>= 1.0)
13
+ multi_json (1.5.0)
14
+ multipart-post (1.1.5)
15
+ nokogiri (1.5.6)
16
+ oauth (0.4.7)
17
+ oauth2 (0.8.0)
18
+ faraday (~> 0.8)
19
+ httpauth (~> 0.1)
20
+ jwt (~> 0.1.4)
21
+ multi_json (~> 1.0)
22
+ rack (~> 1.2)
23
+ rack (1.5.1)
24
+
25
+ PLATFORMS
26
+ ruby
27
+
28
+ DEPENDENCIES
29
+ google_drive (~> 0)
data/README.md ADDED
@@ -0,0 +1,13 @@
1
+ #metric_tools
2
+
3
+ 各種指標を観察したり、データを先方に共有したりといった時によく使う便利なユーティリティをまとめました
4
+
5
+ ---
6
+
7
+ ##Install
8
+
9
+ gem install metric_tools
10
+
11
+
12
+ ##Version Info
13
+ - 0.0.0 (2013/2/1 commited)
@@ -0,0 +1,9 @@
1
+ root_path = File.expand_path("#{File.dirname(__FILE__)}/../")
2
+ require File.join(root_path, "config", "pref.rb")
3
+
4
+ lib_path = File.join(File.dirname(__FILE__), "/metric_tools")
5
+ Dir["#{File.join(lib_path, '/*.rb')}"].each {|f| require f }
6
+
7
+ module MetricTools
8
+ include Pref
9
+ end
@@ -0,0 +1,78 @@
1
+ require 'json'
2
+
3
+ module MetricTools
4
+
5
+ #
6
+ # Tree構造のHash
7
+ #
8
+ class IndexTree
9
+
10
+ def initialize(hash_or_json=nil)
11
+ if hash_or_json.kind_of? Hash
12
+ build_with_hash(hash_or_json)
13
+ elsif hash_or_json.kind_of? String
14
+ build_with_json(hash_or_json)
15
+ else
16
+ @_hash = {}
17
+ end
18
+ end
19
+
20
+
21
+ def [](*args)
22
+ ret = nil
23
+ process_tracing_keys(@_hash, args) {|obj, key, is_leaf|
24
+ ret = obj[key] if is_leaf
25
+ }
26
+ ret
27
+ end
28
+
29
+ def []=(*args)
30
+ val = args.pop
31
+ process_tracing_keys(@_hash, args) {|obj, key, is_leaf|
32
+ if is_leaf
33
+ obj[key] = val
34
+ else
35
+ obj[key] ||= {}
36
+ end
37
+ }
38
+ end
39
+
40
+ def clear
41
+ @_hash = {}
42
+ end
43
+
44
+ def to_s
45
+ @_hash.to_s
46
+ end
47
+
48
+ def to_json(option={})
49
+ if option[:pretty]
50
+ JSON.pretty_generate(@_hash)
51
+ else
52
+ JSON.generate(@_hash)
53
+ end
54
+ end
55
+
56
+ protected
57
+ def build_with_hash(hash)
58
+ @_hash = hash
59
+ end
60
+
61
+ def build_with_json(json)
62
+ @_hash = JSON.parse(json)
63
+ end
64
+
65
+ private
66
+ def process_tracing_keys(obj, keys, &proc)
67
+ current_obj = obj
68
+ keys.each_with_index{|current_key, index|
69
+ break if current_obj.nil?
70
+
71
+ proc.call(current_obj, current_key, index == keys.length-1)
72
+ current_obj = current_obj[current_key]
73
+ }
74
+ end
75
+
76
+ end
77
+
78
+ end
@@ -0,0 +1,87 @@
1
+ require 'aws/s3'
2
+ require 'fileutils'
3
+
4
+ module MetricTools
5
+
6
+ #
7
+ # S3からログなどをDownloadするためのクラスです
8
+ #
9
+ class S3
10
+
11
+ class << self
12
+
13
+ public
14
+ #
15
+ # access_key, secret_key, bucket_nameを指定してログインします。
16
+ #
17
+ def login(key, secret, bucket_name)
18
+ @key = key
19
+ @secret = secret
20
+ @bucket_name = bucket_name
21
+
22
+ AWS::S3::Base.establish_connection!(
23
+ :access_key_id => key,
24
+ :secret_access_key => secret,
25
+ )
26
+ @bucket = AWS::S3::Service.buckets.find{|b| b.name == @bucket_name}
27
+ raise "The bucket named '#{@bucket_name}' doesn't exist." if @bucket.nil?
28
+ end
29
+
30
+ #
31
+ # loginしているかどうかを返します
32
+ #
33
+ def login?
34
+ return !bucket.nil?
35
+ end
36
+
37
+ #
38
+ # file_keyを指定してファイルをダウンロードします。
39
+ # target_dirが存在しない場合は、勝手に作成します。
40
+ # hierarchy=trueにすると、S3上のディレクトリ構造を保持してDownloadします。
41
+ #
42
+ def download(file_key, target_dir, hierarchy=false)
43
+ file_path = File.join(target_dir, hierarchy ? file_key : File.basename(file_key))
44
+ mkdir_for_file(file_path)
45
+ puts "Downloading from S3 : #{file_key} => #{file_path}"
46
+
47
+ File.open(file_path, "w") {|fp|
48
+ AWS::S3::S3Object.stream(file_key, @bucket.name) {|chunk|
49
+ fp.write chunk
50
+ }
51
+ }
52
+ end
53
+
54
+ #
55
+ # 指定されたdir_key以下のファイル/ディレクトリをすべてDLします。
56
+ # force_all=falseにすると、既にローカルにファイルが有る場合はDLしません。
57
+ #
58
+ def fetch_all(dir_key, target_dir, force_all=false, &condition)
59
+ remote_files = @bucket
60
+ .select{|obj|
61
+ key = obj.key
62
+ is_dir = (key[key.length-1] == '/')
63
+ name = key.include? dir_key
64
+ cond = condition.nil? ? true : condition.call(obj)
65
+ !is_dir && name && cond }
66
+ .collect{|obj| obj.key }
67
+ local_files = Dir.glob(File.join(target_dir, "**/*"))
68
+
69
+ remote_files.each {|key|
70
+ if force_all || !local_files.include?(File.basename(key))
71
+ download(key, target_dir, true)
72
+ end
73
+ }
74
+
75
+ end
76
+
77
+ private
78
+ def mkdir_for_file(file_path)
79
+ dir_path = File.dirname(file_path)
80
+ FileUtils.mkdir_p(dir_path) unless File.exists?(dir_path)
81
+ end
82
+
83
+ end
84
+
85
+ end
86
+
87
+ end
@@ -0,0 +1,68 @@
1
+ require 'rb-skypemac'
2
+
3
+ module MetricTools
4
+
5
+ #
6
+ # Skypeのチャットにメッセージをpostするクラスです。
7
+ # 使用するMac上でSkype for Mac OSXが起動していて、
8
+ # 対象のチャットルームに発言できるアカウントでログインされている必要があります。
9
+ #
10
+ class Skype
11
+
12
+ class << self
13
+
14
+ #
15
+ # nameで指定したチャットルームに発言出来る状態にします。
16
+ # login_chat("[GREE] パンカク連絡チャット")
17
+ #
18
+ def login_chat(name)
19
+ chats = SkypeMac::Skype.send_(:command => 'SEARCH RECENTCHATS')
20
+ chats = chats.sub("CHATS ","").split(/,/)
21
+
22
+ for id in chats
23
+ chat_info = SkypeMac::Skype.send_(:command => 'GET CHAT %s FRIENDLYNAME' % id).split(' ')
24
+ friendly_name = chat_info[3]
25
+
26
+ if friendly_name.include?(name)
27
+ @chat_id = chat_info[1]
28
+ @chat_name = friendly_name
29
+ end
30
+ end
31
+
32
+ raise "not existing chat room : #{name}" if @chat_id.nil?
33
+ @chat_id
34
+ end
35
+
36
+ def logout
37
+ @chat_id = nil
38
+ @chat_name = nil
39
+ end
40
+
41
+ #
42
+ # 現在のチャットルームのidを返します
43
+ #
44
+ def current_chat_id
45
+ @chat_id
46
+ end
47
+
48
+ #
49
+ # 現在のチャットルームの表示名を返します
50
+ #
51
+ def current_chat_name
52
+ @chat_name
53
+ end
54
+
55
+ #
56
+ # 現在のチャットルームに発言します
57
+ #
58
+ def post(message)
59
+ return puts 'please login before.' if current_chat_id.nil?
60
+
61
+ SkypeMac::Skype.send_(:command => "CHATMESSAGE #{current_chat_id} #{message}");
62
+ end
63
+
64
+ end
65
+
66
+ end
67
+
68
+ end
@@ -0,0 +1,108 @@
1
+ require 'google_drive'
2
+
3
+ module MetricTools
4
+
5
+ #
6
+ # Google DocsのSpreadSheetを更新するためのクラス
7
+ # (gem google_driveのラッパーです)
8
+ #
9
+ class SpreadSheet
10
+
11
+ class << self
12
+ attr_accessor :mail, :password, :key
13
+
14
+ # session lifetime
15
+
16
+ #
17
+ # mail, passwordでログインし, 該当するkeyのspreadsheetを編集可能にします
18
+ #
19
+ def login(mail, password, key)
20
+ @mail = mail
21
+ @password = password
22
+ @key = key
23
+
24
+ @session = GoogleDrive.login(@mail, @password)
25
+ @spread_sheet = @session.spreadsheet_by_key(@key)
26
+ end
27
+
28
+ #
29
+ # ログアウトします
30
+ #
31
+ def logout
32
+ @session = nil
33
+ @spread_sheet = nil
34
+ @worksheet = nil
35
+ end
36
+
37
+ #
38
+ # ログイン状態かどうかを返します
39
+ #
40
+ def login?
41
+ return !@session.nil? && !@spread_sheet.nil?
42
+ end
43
+
44
+ #worksheet
45
+
46
+ def current_worksheet_title
47
+ return nil if @worksheet.nil?
48
+
49
+ @worksheet.title
50
+ end
51
+
52
+ def change_worksheet_by_title(title)
53
+ @worksheet = @spread_sheet.worksheet_by_title(title)
54
+ @worksheet = @spread_sheet.add_worksheet(title) if @worksheet.nil?
55
+
56
+ @worksheet
57
+ end
58
+
59
+ # editing
60
+
61
+ #
62
+ # インデクサを使用して値にアクセスします
63
+ #
64
+ def [](i, j)
65
+ check_worksheet_seleced_or_raise_error()
66
+
67
+ return @worksheet[i+1, j+1]
68
+ end
69
+
70
+ #
71
+ # インデクサを使用して値をアサインします
72
+ #
73
+ def []=(i, j, val)
74
+ check_worksheet_seleced_or_raise_error()
75
+
76
+ return @worksheet[i+1, j+1] = val
77
+ end
78
+
79
+ #
80
+ # Tableクラスの内容を、スプレッドシートに書き出します。
81
+ #
82
+ def set_value_table(table)
83
+ check_worksheet_seleced_or_raise_error()
84
+
85
+ raise 'can receive Table class only' unless table.kind_of? MetricTools::Table
86
+ table.each_with_index{|cell, i, j|
87
+ self[i, j] = cell
88
+ }
89
+ end
90
+
91
+ #
92
+ # スプレッドシートにここまでの変更を反映します。
93
+ # saveを呼ぶまでは、実際にスプレッドシートには書き込まれません。
94
+ #
95
+ def save
96
+ check_worksheet_seleced_or_raise_error()
97
+
98
+ @worksheet.synchronize
99
+ end
100
+
101
+ def check_worksheet_seleced_or_raise_error
102
+ raise "call 'change_worksheet_by_title' before." if @worksheet.nil?
103
+ end
104
+ end
105
+
106
+ end
107
+
108
+ end
@@ -0,0 +1,244 @@
1
+ require 'Hirb'
2
+
3
+ module MetricTools
4
+
5
+ #
6
+ # 2次元配列のデータ構造を簡単に扱うためのクラス
7
+ #
8
+ class Table
9
+
10
+ def initialize
11
+ @_inner_data = {}
12
+ end
13
+
14
+ class << self
15
+ # Tableクラスのインスタンスを生成します
16
+ #
17
+ # 表の幅、高さを指定し、内容をブロックで指定します。
18
+ # ブロックの返り値が、表の(i, j)の位置に入ります。
19
+ #
20
+ # Table.create(10, 5) {|i, j|
21
+ # return "set to (#{i}, #{j})"
22
+ # }
23
+ def create(rows, cols, &proc)
24
+ table = Table.new
25
+ table.build(rows, cols, &proc)
26
+ end
27
+
28
+ # Tableクラスのインスタンスを生成します
29
+ #
30
+ # 2次元配列を元にTableクラスに変換します。
31
+ #
32
+ # array = [[1, 2, 3], [4, 5, 6], [9, 0, '#']]
33
+ # Table.create_with_array(array)
34
+ def create_with_array(array)
35
+ Table.create(array[0].length, array.length) {|i, j|
36
+ array[j][i]
37
+ }
38
+ end
39
+ end
40
+
41
+ public
42
+ #
43
+ # インデクサを用いてアクセスします
44
+ # 表の大きさを超えていると nilが返ります。
45
+ #
46
+ # table[1, 10]
47
+ def [](i, j)
48
+ @_inner_data[index_to_key(i, j)]
49
+ end
50
+
51
+ #
52
+ # インデクサを用いてアクセスします
53
+ # 表の大きさを超えているとき、自動的に拡張します
54
+ #
55
+ # table[1, 10] = val
56
+ def []=(i, j, val)
57
+ raise "can't specify negative number for position." if i < 0 || j < 0
58
+
59
+ @_inner_data[index_to_key(i, j)] = val
60
+ end
61
+
62
+ #
63
+ # tableの幅(列数)を取得します
64
+ #
65
+ def width
66
+ max = 0
67
+ for key in @_inner_data.keys
68
+ i, j = key_to_index(key)
69
+ max = j if max < j
70
+ end
71
+ return max + 1
72
+ end
73
+
74
+ #
75
+ # tableの幅(列数)を取得します
76
+ #
77
+ def cols
78
+ self.width
79
+ end
80
+
81
+ #
82
+ # tableの高さ(行数)を取得します
83
+ #
84
+ def height
85
+ max = 0
86
+ for key in @_inner_data.keys
87
+ i, j = key_to_index(key)
88
+ max = i if max < i
89
+ end
90
+ return max + 1
91
+ end
92
+
93
+ #
94
+ # tableの高さ(行数)を取得します
95
+ #
96
+ def rows
97
+ self.height
98
+ end
99
+
100
+ def add_below(table)
101
+ table.each_with_index{|cell, i, j|
102
+ self[i, j+self.height] = cell
103
+ }
104
+ self
105
+ end
106
+
107
+ #
108
+ # 2次元配列を返します。自身は変更されません。
109
+ #
110
+ # table.to_a => [[1,2,3], [4,5,6], [9,0,'#']]
111
+ def to_a
112
+ ret = []
113
+ @_inner_data.each{|key, val|
114
+ i, j = key_to_index(key)
115
+
116
+ ret[i] ||= []
117
+ ret[i][j] = val
118
+ }
119
+ ret
120
+ end
121
+
122
+ #
123
+ # 全データに対して処理を行います
124
+ #
125
+ # table.each {|cell|
126
+ # cell += 10
127
+ # }
128
+ def each(&proc)
129
+ @_inner_data.keys.each{|key|
130
+ proc.call(@_inner_data[key])
131
+ }
132
+ end
133
+
134
+ #
135
+ # 全データに対して処理を行います。(i, j)にデータの座標が入ります。
136
+ #
137
+ # table.each {|cell, i, j|
138
+ # cell = i + j * table.width
139
+ # }
140
+ def each_with_index(&proc)
141
+ @_inner_data.keys.each{|key|
142
+ i, j = key_to_index(key)
143
+ proc.call(@_inner_data[key], i, j)
144
+ }
145
+ end
146
+
147
+ def collect(&proc)
148
+ new_one = Table.create(self.rows, self.cols){|i, j|
149
+ proc.call(self[i, j], i, j)
150
+ }
151
+ new_one
152
+ end
153
+
154
+ # output console methods
155
+
156
+ #
157
+ # コンソールに綺麗な表形式で出力します(Hirbを使用)
158
+ #
159
+ def print_pretty
160
+ puts Hirb::Helpers::Table.render @data, :headers => @headers, :resize => false
161
+ end
162
+
163
+ #
164
+ # コンソールにcsv形式で出力します
165
+ #
166
+ def print_csv
167
+ print_with_seperator(",")
168
+ end
169
+
170
+ #
171
+ # コンソールにtsv形式で出力します
172
+ #
173
+ def print_for_docs
174
+ print_with_seperator("\t")
175
+ end
176
+
177
+ def print_with_seperator(s)
178
+ to_a.each{|row|
179
+ puts row.join(s)
180
+ }
181
+ end
182
+
183
+ #
184
+ # csvファイルとして出力します
185
+ #
186
+ def output_csv_file(path)
187
+ output_file_with_seperator(",", path)
188
+ end
189
+
190
+ #
191
+ # tsvファイルとして出力します
192
+ #
193
+ def output_tsv_file(path)
194
+ output_file_with_seperator("\t", path)
195
+ end
196
+
197
+ def output_file_with_seperator(s, path)
198
+ puts "start output >> #{path}..."
199
+
200
+ ret = ''
201
+ to_a.each{|row|
202
+ ret << row.join(s) + "\n"
203
+ }
204
+
205
+ File.open(path, 'w') {|fp|
206
+ fp.write ret
207
+ }
208
+ puts "finish"
209
+ end
210
+
211
+ def build(rows, cols, &proc)
212
+ for i in 0..rows-1
213
+ for j in 0..cols-1
214
+ @_inner_data[index_to_key(i, j)] = proc.call(i, j)
215
+ end
216
+ end
217
+ self
218
+ end
219
+
220
+
221
+ private
222
+
223
+ def index_to_key(i, j)
224
+ "#{i}-#{j}"
225
+ end
226
+
227
+ def key_to_index(key)
228
+ i, j = key.split('-')
229
+ [i.to_i, j.to_i]
230
+ end
231
+
232
+ def move_cell(i, j, delta_x, delta_y)
233
+ raise "can't specify negative number for position." if i < 0 || j < 0
234
+ raise "can't move to negative position." if i + delta_x < 0 || j + delta_y < 0
235
+
236
+ src_key = index_to_key(i, j)
237
+ dst_key = index_to_key(i + delta_x, j + delta_y)
238
+
239
+ @_inner_data[dst_key] = @_inner_data[src_key]
240
+ @_inner_data.delete(src_key)
241
+ end
242
+ end
243
+
244
+ end
metadata ADDED
@@ -0,0 +1,53 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: metric_tools
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Masaori Hirono
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2010-04-28 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Utilities for analyzing metrics
15
+ email: masaori@pankaku.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - lib/metric_tools/index_tree.rb
21
+ - lib/metric_tools/s3.rb
22
+ - lib/metric_tools/skype.rb
23
+ - lib/metric_tools/spread_sheet.rb
24
+ - lib/metric_tools/table.rb
25
+ - lib/metric_tools.rb
26
+ - Gemfile
27
+ - Gemfile.lock
28
+ - README.md
29
+ homepage: http://google.com/
30
+ licenses: []
31
+ post_install_message:
32
+ rdoc_options: []
33
+ require_paths:
34
+ - lib
35
+ required_ruby_version: !ruby/object:Gem::Requirement
36
+ none: false
37
+ requirements:
38
+ - - ! '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ required_rubygems_version: !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ! '>='
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ requirements: []
48
+ rubyforge_project:
49
+ rubygems_version: 1.8.25
50
+ signing_key:
51
+ specification_version: 3
52
+ summary: Utilities for analyzing metrics
53
+ test_files: []