ix-cli 0.0.10 → 0.0.14
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.
- checksums.yaml +4 -4
- data/bin/ix-json-stats +57 -28
- data/bin/ix-json-to-html-table-2 +52 -0
- data/bin/ix-prepend +0 -0
- data/bin/ix-string-similarity +178 -108
- metadata +10 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d054eabc68581f7a85447e44ce7471bd3bfd361fec428cd6f52b07bc23d99f61
|
4
|
+
data.tar.gz: ef9b8158e1a5282d68956f9188f47d2e0753a7e42606b8fd48a8e684f2379d1a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 312c40f4c85f2c8919ddaa1ea33a9306dfc2be0eecf51782d18abaaabf4a5d1cc8fd00507674081ecf5598e694d9c28f4c31783b7416afd11a6d86024b096904
|
7
|
+
data.tar.gz: 4f7d68947f74467984e028a8d66460d662b8a32d57cc2e0072bb63454b325b3ce7abaa7600ea02f7a8bf64b4e6c8355bb1a51d8b5be8c0b5bf3d095e11716cee
|
data/bin/ix-json-stats
CHANGED
@@ -13,7 +13,12 @@ OptionParser.new do |opts|
|
|
13
13
|
opts.banner = "Usage: #{$0} [OPTIONS]"
|
14
14
|
|
15
15
|
opts.on('-k', '--keys [KEYS]', 'List of keys to parse from json separated by :.') do |value|
|
16
|
-
|
16
|
+
unless value
|
17
|
+
$stderr.puts "Please provide valid --keys got: #{value.inspect}"
|
18
|
+
STDIN.each_line {}
|
19
|
+
exit 1
|
20
|
+
end
|
21
|
+
options[:keys] = value.split(':')
|
17
22
|
end
|
18
23
|
|
19
24
|
opts.on('-c', '--count [NUMBER]', 'Number of top N items to show.') do |value|
|
@@ -26,7 +31,7 @@ OptionParser.new do |opts|
|
|
26
31
|
|
27
32
|
end.parse!
|
28
33
|
|
29
|
-
required_options = [
|
34
|
+
required_options = []
|
30
35
|
required_options.each do |option|
|
31
36
|
unless options[option]
|
32
37
|
$stderr.puts "Can not run #{option.to_s} was not given."
|
@@ -35,13 +40,17 @@ required_options.each do |option|
|
|
35
40
|
end
|
36
41
|
|
37
42
|
map = {}
|
38
|
-
keys = options[:keys].split(':')
|
39
43
|
|
40
44
|
STDIN.each_line do |line|
|
41
45
|
begin
|
42
46
|
object = JSON.parse(line)
|
47
|
+
unless options[:keys]
|
48
|
+
options[:keys] == object.keys
|
49
|
+
end
|
43
50
|
object.each do |k, v|
|
44
|
-
|
51
|
+
if options[:keys]
|
52
|
+
next unless options[:keys].include?(k)
|
53
|
+
end
|
45
54
|
submap = map[k] ||= {}
|
46
55
|
submap[v] ||= 0
|
47
56
|
submap[v] += 1
|
@@ -53,36 +62,56 @@ STDIN.each_line do |line|
|
|
53
62
|
end
|
54
63
|
end
|
55
64
|
|
56
|
-
def
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
65
|
+
def print_value(result, total)
|
66
|
+
percentage = "%2.2f" % (result[:incidents] / total.to_f * 100)
|
67
|
+
h_percentage = (percentage.to_s + '%').rjust(6, ' ').to_ansi.yellow.to_s
|
68
|
+
value = result[:incidents].to_s.rjust(10, ' ').to_ansi.green.to_s
|
69
|
+
key = result[:label]
|
70
|
+
puts "%s %s %s" % [value, h_percentage, key]
|
71
|
+
end
|
72
|
+
|
73
|
+
class GroupObject
|
74
|
+
attr_accessor :category
|
75
|
+
attr_accessor :results
|
76
|
+
def initialize(category)
|
77
|
+
@category = category
|
78
|
+
@results = []
|
79
|
+
end
|
80
|
+
def add_result(label, incidents)
|
81
|
+
@results.push({ :label => label, :incidents => incidents })
|
82
|
+
end
|
83
|
+
def total
|
84
|
+
results.sum do |result|
|
85
|
+
result[:incidents]
|
71
86
|
end
|
87
|
+
end
|
88
|
+
end
|
72
89
|
|
73
|
-
|
74
|
-
|
90
|
+
def get_group_objects(map)
|
91
|
+
group_objects = []
|
75
92
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
key = object[:key]
|
81
|
-
puts "%s %s %s" % [value, h_percentage, key]
|
93
|
+
map.each do |category, hash|
|
94
|
+
group_object = GroupObject.new(category)
|
95
|
+
hash.each do |k, v|
|
96
|
+
group_object.add_result(k, v)
|
82
97
|
end
|
98
|
+
group_objects.push(group_object)
|
99
|
+
end
|
83
100
|
|
101
|
+
group_objects.sort do |a, b|
|
102
|
+
a.category <=> b.category
|
84
103
|
end
|
85
104
|
end
|
86
105
|
|
87
|
-
print_map(map,
|
106
|
+
def print_map(map, sample)
|
107
|
+
get_group_objects(map).each do |group_object|
|
108
|
+
puts "\n#{group_object.category.to_s.to_ansi.cyan.to_s} (#{group_object.total})"
|
109
|
+
group_object.results.sort do |a, b|
|
110
|
+
a[:incidents] <=> b[:incidents]
|
111
|
+
end.reverse.first(sample).each do |result|
|
112
|
+
print_value(result, group_object.total)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
88
116
|
|
117
|
+
print_map(map, options[:count])
|
@@ -0,0 +1,52 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'json'
|
5
|
+
|
6
|
+
def tag(name, content)
|
7
|
+
"<#{name}>#{content}</#{name}>"
|
8
|
+
end
|
9
|
+
|
10
|
+
def row(name, array)
|
11
|
+
array.map do |value|
|
12
|
+
tag(name, value)
|
13
|
+
end * ' '
|
14
|
+
end
|
15
|
+
|
16
|
+
table_header = false
|
17
|
+
|
18
|
+
puts '
|
19
|
+
<style>
|
20
|
+
tr:nth-child(even) {
|
21
|
+
background-color: whitesmoke;
|
22
|
+
}
|
23
|
+
th {
|
24
|
+
background: darkgray;
|
25
|
+
font-color: white;
|
26
|
+
padding: 1mm;
|
27
|
+
}
|
28
|
+
td {
|
29
|
+
padding: 1mm;
|
30
|
+
}
|
31
|
+
</style>
|
32
|
+
'
|
33
|
+
|
34
|
+
STDIN.each_line do |line|
|
35
|
+
begin
|
36
|
+
object = JSON.parse(line)
|
37
|
+
unless table_header
|
38
|
+
puts '<table>'
|
39
|
+
table_header_row = row('th', object.keys.sort)
|
40
|
+
puts tag('tr', table_header_row)
|
41
|
+
table_header = true
|
42
|
+
end
|
43
|
+
copy = object.keys.sort.map do |key|
|
44
|
+
object[key]
|
45
|
+
end
|
46
|
+
table_body_row = row('td', copy)
|
47
|
+
puts tag('tr', table_body_row)
|
48
|
+
rescue => error
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
puts '</table>'
|
data/bin/ix-prepend
CHANGED
File without changes
|
data/bin/ix-string-similarity
CHANGED
@@ -1,152 +1,222 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
class Chunk
|
4
|
+
attr_accessor :char_1
|
5
|
+
attr_accessor :char_2
|
6
|
+
attr_accessor :index_1
|
7
|
+
attr_accessor :index_2
|
8
|
+
|
9
|
+
def initialize(c1, c2, i1, i2)
|
10
|
+
@char_1 = c1
|
11
|
+
@char_2 = c2
|
12
|
+
@index_1 = i1
|
13
|
+
@index_2 = i2
|
14
|
+
end
|
5
15
|
|
6
|
-
|
16
|
+
def to_s
|
17
|
+
"#{char_1} #{char_2} #{index_1} #{index_2}"
|
18
|
+
end
|
19
|
+
end
|
7
20
|
|
8
|
-
|
21
|
+
class Similarity
|
22
|
+
CHAR_REGEX = /./
|
9
23
|
|
10
|
-
|
11
|
-
|
12
|
-
opts.separator "Usage: #{File.basename($0)} [OPTIONS]"
|
13
|
-
opts.separator ''
|
24
|
+
attr_accessor :string_1
|
25
|
+
attr_accessor :string_2
|
14
26
|
|
15
|
-
|
16
|
-
|
17
|
-
|
27
|
+
def initialize(string_1, string_2)
|
28
|
+
@string_1 = string_1
|
29
|
+
@string_2 = string_2
|
30
|
+
end
|
18
31
|
|
19
|
-
|
20
|
-
|
21
|
-
|
32
|
+
def tokens
|
33
|
+
chunks = []
|
34
|
+
string_1.scan(CHAR_REGEX).each_with_index do |char_1, index_1|
|
35
|
+
string_2.scan(CHAR_REGEX).each_with_index do |char_2, index_2|
|
36
|
+
next if char_1 != char_2
|
37
|
+
chunks.push(Chunk.new(char_1, char_2, index_1, index_2))
|
38
|
+
end
|
39
|
+
end
|
40
|
+
chunks
|
22
41
|
end
|
23
42
|
|
24
|
-
|
25
|
-
|
26
|
-
|
43
|
+
def count
|
44
|
+
counter = 0
|
45
|
+
prev = false
|
46
|
+
tokens.each_with_index do |chunk, index|
|
47
|
+
|
48
|
+
unless prev
|
49
|
+
prev = chunk.index_1
|
50
|
+
next
|
51
|
+
end
|
52
|
+
|
53
|
+
if prev == (chunk.index_1 - 1)
|
54
|
+
counter += 1
|
55
|
+
end
|
56
|
+
|
57
|
+
prev = chunk.index_1
|
58
|
+
end
|
59
|
+
|
60
|
+
counter
|
27
61
|
end
|
28
62
|
|
29
|
-
|
30
|
-
|
31
|
-
|
63
|
+
def score
|
64
|
+
desired = (string_1.size + string_2.size) / 2
|
65
|
+
size_thresh = ([string_1.size, string_2.size].sort.first.to_f / desired)
|
66
|
+
compatibility_thresh = (count.to_f + 1) / string_1.size
|
67
|
+
(size_thresh + compatibility_thresh).to_f / 2
|
32
68
|
end
|
69
|
+
end
|
70
|
+
|
71
|
+
require 'optparse'
|
72
|
+
|
73
|
+
options = {}
|
74
|
+
options[:threshold] = 0.8
|
33
75
|
|
76
|
+
OptionParser.new do |opts|
|
34
77
|
|
35
|
-
opts.
|
78
|
+
opts.banner = "Usage: #{$0} [OPTIONS]"
|
79
|
+
|
80
|
+
opts.on('-t', '--threshold [NUMBER]', 'Threshold default value is 0.8.') do |value|
|
81
|
+
options[:threshold] = value.to_f
|
82
|
+
end
|
83
|
+
|
84
|
+
opts.on('-s', '--summary', 'Print Summarized version.') do |value|
|
85
|
+
options[:summary] = value
|
86
|
+
end
|
36
87
|
|
37
88
|
end.parse!
|
38
89
|
|
39
|
-
|
90
|
+
required_options = [:threshold]
|
91
|
+
required_options.each do |option|
|
92
|
+
unless options[option]
|
93
|
+
$stderr.puts "Can not run #{option.to_s} was not given."
|
94
|
+
exit 1
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
# hash = {
|
99
|
+
# 'line' => [
|
100
|
+
# { :line => 'line', :score => 1 },
|
101
|
+
# ]
|
102
|
+
# }
|
103
|
+
|
104
|
+
hash = {}
|
105
|
+
lines = 0
|
40
106
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
107
|
+
STDIN.each_line do |line|
|
108
|
+
line.chomp!
|
109
|
+
next if line == ''
|
110
|
+
lines += 1
|
111
|
+
resolved = false
|
112
|
+
hash.keys.each do |registered_line|
|
113
|
+
score = Similarity.new(line, registered_line).score
|
114
|
+
if score > options[:threshold]
|
115
|
+
hash[registered_line].push({
|
116
|
+
:line => line,
|
117
|
+
:score => score
|
118
|
+
})
|
119
|
+
resolved = true
|
45
120
|
end
|
46
121
|
end
|
122
|
+
next if resolved
|
123
|
+
hash[line] ||= []
|
47
124
|
end
|
48
125
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
126
|
+
module Template
|
127
|
+
|
128
|
+
class Banner < Struct.new(:lines, :groups, :threshold, :datetime)
|
129
|
+
def to_s
|
130
|
+
format(template, to_h)
|
131
|
+
end
|
132
|
+
def template
|
133
|
+
'
|
134
|
+
Total Lines Parsed: %<lines>s
|
135
|
+
Total Groups Generated: %<groups>s
|
136
|
+
Similarity Theshold at: %<threshold>s
|
137
|
+
Generated on: %<datetime>s
|
138
|
+
'
|
54
139
|
end
|
55
|
-
array
|
56
140
|
end
|
57
141
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
longest_string = other_string
|
62
|
-
shortest_string = self
|
63
|
-
else
|
64
|
-
longest_string = self
|
65
|
-
shortest_string = other_string
|
66
|
-
end
|
67
|
-
scores = longest_string.to_a.map do |char|
|
68
|
-
0
|
142
|
+
class Group < Struct.new(:number, :percent, :items, :line)
|
143
|
+
def to_s
|
144
|
+
format(template, to_h)
|
69
145
|
end
|
70
|
-
|
71
|
-
|
72
|
-
scores[index] = 1
|
73
|
-
end
|
146
|
+
def template
|
147
|
+
'Group %<number>s represents %<percent>s and has %<items>s items similar to: %<line>s'
|
74
148
|
end
|
75
|
-
scores
|
76
149
|
end
|
77
150
|
|
78
|
-
|
79
|
-
|
151
|
+
class Item < Struct.new(:count, :total, :score, :line)
|
152
|
+
def to_s
|
153
|
+
format(template, to_h)
|
154
|
+
end
|
155
|
+
def template
|
156
|
+
' %<count>s/%<total>s %<score>s %<line>s'
|
157
|
+
end
|
80
158
|
end
|
81
|
-
end
|
82
159
|
|
83
|
-
class TargetString
|
84
|
-
attr_accessor :evaluated
|
85
|
-
attr_accessor :data
|
86
|
-
def to_s
|
87
|
-
data
|
88
|
-
end
|
89
160
|
end
|
90
161
|
|
91
|
-
|
162
|
+
require 'isna'
|
92
163
|
|
93
|
-
|
164
|
+
summary_output = []
|
165
|
+
detailed_output = []
|
94
166
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
167
|
+
banner = Template::Banner.new
|
168
|
+
banner.lines = lines.to_s.to_ansi.yellow.to_s
|
169
|
+
banner.groups = hash.keys.size.to_s.to_ansi.yellow.to_s
|
170
|
+
banner.threshold = options[:threshold].to_s.to_ansi.yellow.to_s
|
171
|
+
banner.datetime = Time.now.to_s.to_ansi.yellow.to_s
|
172
|
+
summary_output.push(banner.to_s)
|
99
173
|
|
100
|
-
|
101
|
-
|
174
|
+
groups = []
|
175
|
+
|
176
|
+
hash.each do |category_name, records|
|
177
|
+
groups.push([category_name, records.size])
|
102
178
|
end
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
target_string.evaluated = false
|
109
|
-
target_string.data = string
|
110
|
-
target_string
|
179
|
+
|
180
|
+
sorted_groups_by_n_records_asc = groups.sort do |array_a, array_b|
|
181
|
+
number_of_records_in_a = array_a[1]
|
182
|
+
number_of_records_in_b = array_b[1]
|
183
|
+
number_of_records_in_a <=> number_of_records_in_b
|
111
184
|
end
|
112
185
|
|
113
|
-
|
114
|
-
|
115
|
-
|
186
|
+
sorted_groups_by_n_records_asc.reverse.each_with_index do |key, index|
|
187
|
+
line, records = key[0], hash[key[0]]
|
188
|
+
|
189
|
+
detailed_output.push('')
|
190
|
+
|
191
|
+
group = Template::Group.new
|
192
|
+
group.percent = ('%2.2f%%' % ((records.size.to_f / lines) * 100)).to_s.to_ansi.red.to_s
|
193
|
+
group.number = (index + 1).to_s.to_ansi.red.to_s
|
194
|
+
group.items = records.size.to_s.to_ansi.cyan.to_s
|
195
|
+
group.line = line.chomp.to_ansi.green.to_s
|
196
|
+
summary_output.push(group.to_s)
|
197
|
+
detailed_output.push(group.to_s)
|
198
|
+
|
199
|
+
sorted_items_in_group = records.sort do |a, b|
|
200
|
+
a[:score] <=> b[:score]
|
116
201
|
end
|
117
|
-
else
|
118
|
-
groups = { 0 => strings }
|
119
|
-
end
|
120
202
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
else
|
129
|
-
puts "****>>" + string_1.to_s
|
130
|
-
end
|
131
|
-
end
|
132
|
-
string_1.evaluated = true
|
133
|
-
group.each do |string_2|
|
134
|
-
next if string_2.evaluated
|
135
|
-
similarity = string_1.to_s.similarity(string_2.to_s)
|
136
|
-
scores = string_1.to_s.scores(string_2.to_s).inspect
|
137
|
-
template = "%5.f %s"
|
138
|
-
bindings = [similarity, string_2, scores]
|
139
|
-
if similarity >= configuration.threshold
|
140
|
-
string_2.evaluated = true
|
141
|
-
counter += 1
|
142
|
-
unless configuration.summary
|
143
|
-
puts template % bindings
|
144
|
-
end
|
145
|
-
end
|
146
|
-
end
|
147
|
-
if counter > 0
|
148
|
-
puts "#{counter} #{summary_string}"
|
149
|
-
end
|
203
|
+
sorted_items_in_group.reverse.each_with_index do |record, index|
|
204
|
+
item = Template::Item.new
|
205
|
+
item.count = (index + 1).to_s.rjust(4, ' ').to_ansi.cyan.to_s
|
206
|
+
item.total = records.size.to_s.ljust(4, ' ').to_ansi.cyan.to_s
|
207
|
+
item.score = ('%4.2f%%' % (record[:score] * 100)).rjust(7, ' ').to_ansi.green.to_s
|
208
|
+
item.line = record[:line]
|
209
|
+
detailed_output.push(item.to_s)
|
150
210
|
end
|
211
|
+
|
151
212
|
end
|
152
213
|
|
214
|
+
summary_output.each do |output_line|
|
215
|
+
puts output_line
|
216
|
+
end
|
217
|
+
|
218
|
+
unless options[:summary]
|
219
|
+
detailed_output.each do |output_line|
|
220
|
+
puts output_line
|
221
|
+
end
|
222
|
+
end
|
metadata
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ix-cli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.14
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kazuyoshi Tlacaelel
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
date: 2020-02-05 00:00:00.000000000 Z
|
@@ -24,8 +24,8 @@ dependencies:
|
|
24
24
|
- - '='
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 0.0.4
|
27
|
-
description:
|
28
|
-
email:
|
27
|
+
description:
|
28
|
+
email:
|
29
29
|
executables:
|
30
30
|
- ix
|
31
31
|
- ix-acronym
|
@@ -151,6 +151,7 @@ executables:
|
|
151
151
|
- ix-json-to-csv
|
152
152
|
- ix-json-to-dot
|
153
153
|
- ix-json-to-html-table
|
154
|
+
- ix-json-to-html-table-2
|
154
155
|
- ix-json-to-ruby-hash
|
155
156
|
- ix-json-to-table
|
156
157
|
- ix-json-to-table-2
|
@@ -431,6 +432,7 @@ files:
|
|
431
432
|
- bin/ix-json-to-csv
|
432
433
|
- bin/ix-json-to-dot
|
433
434
|
- bin/ix-json-to-html-table
|
435
|
+
- bin/ix-json-to-html-table-2
|
434
436
|
- bin/ix-json-to-ruby-hash
|
435
437
|
- bin/ix-json-to-table
|
436
438
|
- bin/ix-json-to-table-2
|
@@ -582,10 +584,10 @@ files:
|
|
582
584
|
- bin/ix-wrap
|
583
585
|
- bin/ix-xy
|
584
586
|
- bin/ix-zebra
|
585
|
-
homepage:
|
587
|
+
homepage:
|
586
588
|
licenses: []
|
587
589
|
metadata: {}
|
588
|
-
post_install_message:
|
590
|
+
post_install_message:
|
589
591
|
rdoc_options: []
|
590
592
|
require_paths:
|
591
593
|
- lib
|
@@ -600,8 +602,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
600
602
|
- !ruby/object:Gem::Version
|
601
603
|
version: '0'
|
602
604
|
requirements: []
|
603
|
-
rubygems_version: 3.
|
604
|
-
signing_key:
|
605
|
+
rubygems_version: 3.0.3
|
606
|
+
signing_key:
|
605
607
|
specification_version: 4
|
606
608
|
summary: ix - string manipulation tools
|
607
609
|
test_files: []
|