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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9356248fcc4f5fe5c83fedeb01e13166a9764bed70c39fe06132963141f394d9
4
- data.tar.gz: c7676df3c6b0e8427888882bc02fa609e6aa987816f76ef90e656ca6ce196ed7
3
+ metadata.gz: d054eabc68581f7a85447e44ce7471bd3bfd361fec428cd6f52b07bc23d99f61
4
+ data.tar.gz: ef9b8158e1a5282d68956f9188f47d2e0753a7e42606b8fd48a8e684f2379d1a
5
5
  SHA512:
6
- metadata.gz: 21233826e4b716857231aa89c0abc3263702cf0347b71a2bfc40e3502b79946b98a7b3ae5496bf1975121ef1f3c44952bedd0415d817ac7eee34246ec91007b6
7
- data.tar.gz: fbee1010c9fda5caf7144b8855c6ff8f502413ba3dbee2b81c630340d6c429299878b9b20cc34bc6d9fe2912e3b5e4cee44159f0b31fc947d0467957f7cf6802
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
- options[:keys] = value
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 = [:keys]
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
- next unless keys.include?(k)
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 print_map(map, sample)
57
- map.each do |category, stats|
58
- values = []
59
- total = 0
60
-
61
- counter = 0
62
- stats.values.sort.reverse.each do |value_1|
63
- stats.each do |key, value_2|
64
- if value_1 == value_2
65
- counter += 1
66
- break if counter > sample
67
- total += value_1
68
- values.push({ :value => value_1, :key => key })
69
- end
70
- end
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
- puts ""
74
- puts "#{category.to_s.to_ansi.cyan.to_s} (#{total})"
90
+ def get_group_objects(map)
91
+ group_objects = []
75
92
 
76
- values.each do |object|
77
- percentage = "%2.2f" % (object[:value] / total.to_f * 100)
78
- h_percentage = (percentage.to_s + '%').rjust(6, ' ').to_ansi.yellow.to_s
79
- value = object[:value].to_s.rjust(10, ' ').to_ansi.green.to_s
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, options[:count])
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
@@ -1,152 +1,222 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'optparse'
4
- require 'ostruct'
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
- configuration = OpenStruct.new
16
+ def to_s
17
+ "#{char_1} #{char_2} #{index_1} #{index_2}"
18
+ end
19
+ end
7
20
 
8
- OptionParser.new do |opts|
21
+ class Similarity
22
+ CHAR_REGEX = /./
9
23
 
10
- opts.banner = "Find similarity in a set of strings."
11
- opts.separator ''
12
- opts.separator "Usage: #{File.basename($0)} [OPTIONS]"
13
- opts.separator ''
24
+ attr_accessor :string_1
25
+ attr_accessor :string_2
14
26
 
15
- configuration.group = false
16
- configuration.threshold = 50
17
- configuration.summary = false
27
+ def initialize(string_1, string_2)
28
+ @string_1 = string_1
29
+ @string_2 = string_2
30
+ end
18
31
 
19
- description = "Group input in batches and process each individually (faster)"
20
- opts.on("-g", "--group", description) do |v|
21
- configuration.group = v
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
- description = "Limit the number of results by threshold, default is 50"
25
- opts.on("-t", "--threshhold [NUMBER]", OptionParser::DecimalNumeric, description) do |v|
26
- configuration.threshold = v
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
- description = "Print a Summary of the groups found"
30
- opts.on("-s", "--summary", description) do |v|
31
- configuration.summary = v
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.separator ''
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
- # puts configuration.inspect
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
- class Array
42
- def product
43
- inject do |cumulative, value|
44
- cumulative += value
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
- class String
50
- def to_a
51
- array = []
52
- size.times do |n|
53
- array << self[n]
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
- def scores(other_string)
59
- longest_string = nil
60
- if other_string.size > self.size
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
- shortest_string.size.times do |index|
71
- if shortest_string[index] == longest_string[index]
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
- def similarity(other_string)
79
- scores(other_string).product * 100.0 / size
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
- # client
162
+ require 'isna'
92
163
 
93
- strings = []
164
+ summary_output = []
165
+ detailed_output = []
94
166
 
95
- STDIN.each_line do |line|
96
- next if line.chomp == ''
97
- strings << line.chomp
98
- end
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
- strings.sort! do |n1, n2|
101
- n1.size <=> n2.size
174
+ groups = []
175
+
176
+ hash.each do |category_name, records|
177
+ groups.push([category_name, records.size])
102
178
  end
103
-
104
- strings.reverse!
105
-
106
- strings.map! do |string|
107
- target_string = TargetString.new
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
- if configuration.group
114
- groups = strings.group_by do |string|
115
- string.data.size
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
- counter = 0
122
- groups.each do |key, group|
123
- group.each do |string_1|
124
- counter = 0
125
- unless string_1.evaluated
126
- if configuration.summary
127
- summary_string = string_1.to_s
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.10
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.1.2
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: []