eco-helpers 2.0.18 → 2.0.24
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/CHANGELOG.md +80 -1
- data/eco-helpers.gemspec +4 -1
- data/lib/eco/api/common/base_loader.rb +9 -5
- data/lib/eco/api/common/loaders/parser.rb +1 -0
- data/lib/eco/api/common/people/default_parsers.rb +1 -0
- data/lib/eco/api/common/people/default_parsers/xls_parser.rb +53 -0
- data/lib/eco/api/common/people/entries.rb +1 -0
- data/lib/eco/api/common/people/entry_factory.rb +88 -23
- data/lib/eco/api/common/people/person_entry.rb +1 -0
- data/lib/eco/api/common/people/person_parser.rb +1 -1
- data/lib/eco/api/common/session.rb +1 -0
- data/lib/eco/api/common/session/base_session.rb +2 -0
- data/lib/eco/api/common/session/helpers.rb +30 -0
- data/lib/eco/api/common/session/helpers/prompt_user.rb +34 -0
- data/lib/eco/api/common/version_patches/ecoportal_api/external_person.rb +1 -1
- data/lib/eco/api/common/version_patches/ecoportal_api/internal_person.rb +7 -4
- data/lib/eco/api/common/version_patches/exception.rb +5 -2
- data/lib/eco/api/microcases/with_each.rb +67 -6
- data/lib/eco/api/microcases/with_each_present.rb +4 -2
- data/lib/eco/api/microcases/with_each_starter.rb +4 -2
- data/lib/eco/api/organization.rb +1 -1
- data/lib/eco/api/organization/people.rb +94 -25
- data/lib/eco/api/organization/people_similarity.rb +272 -0
- data/lib/eco/api/organization/person_schemas.rb +5 -1
- data/lib/eco/api/organization/policy_groups.rb +5 -1
- data/lib/eco/api/organization/tag_tree.rb +33 -0
- data/lib/eco/api/session.rb +19 -8
- data/lib/eco/api/session/batch.rb +7 -5
- data/lib/eco/api/session/batch/job.rb +34 -9
- data/lib/eco/api/usecases.rb +2 -2
- data/lib/eco/api/usecases/base_case.rb +2 -2
- data/lib/eco/api/usecases/base_io.rb +17 -4
- data/lib/eco/api/usecases/default_cases.rb +1 -0
- data/lib/eco/api/usecases/default_cases/analyse_people_case.rb +179 -32
- data/lib/eco/api/usecases/default_cases/clean_unknown_tags_case.rb +37 -0
- data/lib/eco/api/usecases/default_cases/to_csv_case.rb +81 -36
- data/lib/eco/api/usecases/default_cases/to_csv_detailed_case.rb +3 -4
- data/lib/eco/api/usecases/ooze_samples/ooze_update_case.rb +3 -2
- data/lib/eco/cli/config/default/input.rb +61 -8
- data/lib/eco/cli/config/default/options.rb +47 -2
- data/lib/eco/cli/config/default/people.rb +18 -24
- data/lib/eco/cli/config/default/usecases.rb +33 -2
- data/lib/eco/cli/config/default/workflow.rb +12 -7
- data/lib/eco/cli/scripting/args_helpers.rb +2 -2
- data/lib/eco/csv.rb +4 -2
- data/lib/eco/csv/table.rb +121 -21
- data/lib/eco/data/fuzzy_match.rb +109 -27
- data/lib/eco/data/fuzzy_match/chars_position_score.rb +3 -2
- data/lib/eco/data/fuzzy_match/ngrams_score.rb +19 -10
- data/lib/eco/data/fuzzy_match/pairing.rb +12 -19
- data/lib/eco/data/fuzzy_match/result.rb +22 -2
- data/lib/eco/data/fuzzy_match/results.rb +30 -6
- data/lib/eco/data/fuzzy_match/score.rb +12 -7
- data/lib/eco/data/fuzzy_match/string_helpers.rb +14 -1
- data/lib/eco/version.rb +1 -1
- metadata +67 -3
- data/lib/eco/api/organization/people_analytics.rb +0 -60
@@ -12,8 +12,9 @@ module Eco
|
|
12
12
|
def chars_position_score(str1, str2, max_distance: 3, normalized: false)
|
13
13
|
str1, str2 = normalize_string([str1, str2]) unless normalized
|
14
14
|
len1 = str1 && str1.length; len2 = str2 && str2.length
|
15
|
-
Score.new(0,
|
16
|
-
next if !str1 ||
|
15
|
+
Score.new(0, 0).tap do |score|
|
16
|
+
next if !str2 || !str1 || str2.empty? || str1.empty?
|
17
|
+
score.total = len1
|
17
18
|
next score.increase(score.total) if str1 == str2
|
18
19
|
next if len1 < 2
|
19
20
|
pos = 0
|
@@ -16,13 +16,19 @@ module Eco
|
|
16
16
|
|
17
17
|
Score.new(0, 0).tap do |score|
|
18
18
|
next if !str2 || !str1
|
19
|
-
next score.
|
20
|
-
|
19
|
+
next score.increase_total(len1) if str2.empty? || str1.empty?
|
20
|
+
if str1 == str2
|
21
|
+
score.total = len1
|
22
|
+
score.increase(score.total)
|
23
|
+
end
|
24
|
+
if str1.length < 2 || str1.length < 2
|
25
|
+
score.increase_total(len1)
|
26
|
+
end
|
21
27
|
|
22
|
-
paired_words(str1, str2, normalized: true) do |needle, item|
|
28
|
+
pairs = paired_words(str1, str2, normalized: true) do |needle, item|
|
23
29
|
ngrams_score(needle, item, range: range, normalized: true)
|
24
|
-
end.each do |sub_str1,
|
25
|
-
|
30
|
+
end.each do |sub_str1, data|
|
31
|
+
item, iscore = data
|
26
32
|
score.merge!(iscore)
|
27
33
|
end
|
28
34
|
end
|
@@ -39,14 +45,17 @@ module Eco
|
|
39
45
|
|
40
46
|
Score.new(0, len1 || 0).tap do |score|
|
41
47
|
next if !str2 || !str1
|
48
|
+
next if str2.empty? || str1.empty?
|
49
|
+
score.total = len1
|
42
50
|
next score.increase(score.total) if str1 == str2
|
43
51
|
next if str1.length < 2 || str2.length < 2
|
44
52
|
|
45
|
-
grams
|
46
|
-
|
53
|
+
grams = word_ngrams(str2, range, normalized: true)
|
54
|
+
grams_count = grams.length
|
55
|
+
next unless grams_count > 0
|
47
56
|
|
48
57
|
if range.is_a?(Integer)
|
49
|
-
item_weight = score.total.to_f /
|
58
|
+
item_weight = score.total.to_f / grams_count
|
50
59
|
matches = grams.select {|res| str1.include?(gram)}.length
|
51
60
|
score.increase(matches * item_weight)
|
52
61
|
else
|
@@ -57,9 +66,9 @@ module Eco
|
|
57
66
|
|
58
67
|
groups.each do |len, grams|
|
59
68
|
len_max_score = score.total * group_weight
|
60
|
-
item_weight = len_max_score /
|
69
|
+
item_weight = len_max_score / grams_count
|
61
70
|
matches = grams.select {|gram| str1.include?(gram)}.length
|
62
|
-
#pp "#{len} match: #{matches} (
|
71
|
+
#pp "(#{len}) match: #{matches} (of #{grams.length} of total #{grams_count}) || max_score: #{len_max_score} (over #{score.total})"
|
63
72
|
score.increase(matches * item_weight)
|
64
73
|
end
|
65
74
|
end
|
@@ -15,20 +15,12 @@ module Eco
|
|
15
15
|
# @yieldreturn [Eco::Data::FuzzyMatch::Score] the `Score` object with the results of comparing `str1` and `str2`
|
16
16
|
# @param str1 [String] the string of reference.
|
17
17
|
# @param str2 [String] one of the haystack items.
|
18
|
-
# @param format [Symbol] determines the `values` of the returned `Hash`::
|
19
|
-
# 1. `:pair` for just pair
|
20
|
-
# 2. `:score` for just score
|
21
|
-
# 2. `[:pair, :score]` for `Array`
|
22
18
|
# @normalized [Boolean] to avoid double ups in normalizing.
|
23
|
-
# @return [Hash] where `keys` are the **words** of `str1` and their `values
|
24
|
-
|
25
|
-
# 2. if `format` is `:score` => the `Score` words with highest match.
|
26
|
-
# 3. if `format` is `[:pair, :score]` => both in an `Array`.
|
27
|
-
def paired_words(str1, str2, format: [:pair, :score], normalized: false)
|
19
|
+
# @return [Hash] where `keys` are the **words** of `str1` and their `values` a pair array of `pair` and `Score`
|
20
|
+
def paired_words(str1, str2, normalized: false)
|
28
21
|
str1, str2 = normalize_string([str1, str2]) unless normalized
|
29
|
-
return {} if !str2 || !str1
|
30
|
-
return
|
31
|
-
return {str1 => nil} if str1.length < 2 || str1.length < 2
|
22
|
+
return {nil => [nil, Score.new(0, 0)]} if !str2 || !str1
|
23
|
+
return {str1 => [nil, Score.new(0, 0)]} if str1.length < 2 || str1.length < 2
|
32
24
|
|
33
25
|
needles = get_words(str1, normalized: true)
|
34
26
|
haystack = get_words(str2, normalized: true)
|
@@ -59,6 +51,9 @@ module Eco
|
|
59
51
|
result[:score].ratio
|
60
52
|
end.reverse
|
61
53
|
if result = sorted.shift
|
54
|
+
unless result[:score].is_a?(Eco::Data::FuzzyMatch::Score)
|
55
|
+
raise "Parining ('#{str1}' vs '#{str2}') -> Something got sour with needle '#{result[:needle]}' and item #{item}"
|
56
|
+
end
|
62
57
|
paired[result[:needle]] = {
|
63
58
|
pair: item,
|
64
59
|
score: result[:score]
|
@@ -74,6 +69,9 @@ module Eco
|
|
74
69
|
pending_items.include?(result[:pair]) && result[:score].ratio > 0.05
|
75
70
|
end
|
76
71
|
if result = results.shift
|
72
|
+
unless result[:score].is_a?(Eco::Data::FuzzyMatch::Score)
|
73
|
+
raise "Parining ('#{str1}' vs '#{str2}') -> Something got sour with needle '#{needle}' and item #{result[:pair]}"
|
74
|
+
end
|
77
75
|
paired[needle] = result
|
78
76
|
pending_items.delete(result[:pair])
|
79
77
|
end
|
@@ -86,13 +84,8 @@ module Eco
|
|
86
84
|
score: Score.new(0, needle.length)
|
87
85
|
}
|
88
86
|
end
|
89
|
-
paired.
|
90
|
-
|
91
|
-
when Array
|
92
|
-
result.values_at(*format)
|
93
|
-
else
|
94
|
-
restult[format]
|
95
|
-
end
|
87
|
+
paired.each_with_object({}) do |(needle, data), out|
|
88
|
+
out[needle] = data.values_at(:pair, :score)
|
96
89
|
end
|
97
90
|
end
|
98
91
|
|
@@ -1,9 +1,11 @@
|
|
1
1
|
module Eco
|
2
2
|
module Data
|
3
3
|
module FuzzyMatch
|
4
|
-
class Result < Struct.new(:match, :value, :dice, :levenshtein, :jaro_winkler, :ngrams, :words_ngrams, :chars_position)
|
4
|
+
class Result < Struct.new(:match, :value, :needle_value, :dice, :levenshtein, :jaro_winkler, :ngrams, :words_ngrams, :chars_position)
|
5
5
|
ALL_METHODS = [:dice, :levenshtein, :jaro_winkler, :ngrams, :words_ngrams, :chars_position]
|
6
6
|
|
7
|
+
attr_accessor :pivot
|
8
|
+
|
7
9
|
def dice; super&.round(3); end
|
8
10
|
def levenshtein; super&.round(3); end
|
9
11
|
def jaro_winkler; super&.round(3); end
|
@@ -11,12 +13,24 @@ module Eco
|
|
11
13
|
def words_ngrams; super&.round(3); end
|
12
14
|
def chars_position; super&.round(3); end
|
13
15
|
|
16
|
+
#Shortcuts
|
17
|
+
def lev; levenshtein; end
|
18
|
+
def jaro; jaro_winkler; end
|
19
|
+
def wngrams; words_ngrams; end
|
20
|
+
def pos; chars_position; end
|
21
|
+
|
22
|
+
def average
|
23
|
+
values = [dice, levenshtein, jaro_winkler, ngrams, words_ngrams, chars_position]
|
24
|
+
(values.inject(0.0, :+) / values.length).round(3)
|
25
|
+
end
|
26
|
+
|
14
27
|
# TODO: print in the order of `order`
|
15
28
|
def print
|
16
29
|
msg = "(Dice: #{dice}) (Lev Dst: #{levenshtein}) "
|
17
30
|
msg << "(Jaro: #{jaro_winkler}) "
|
18
31
|
msg << "(Ngram: #{ngrams}) (WNgrams: #{words_ngrams}) "
|
19
32
|
msg << "(C Pos: #{chars_position}) "
|
33
|
+
msg << "(Avg: #{average}) "
|
20
34
|
msg << "'#{value}'"
|
21
35
|
end
|
22
36
|
|
@@ -37,7 +51,7 @@ module Eco
|
|
37
51
|
|
38
52
|
def order=(values)
|
39
53
|
@order = [values].flatten.compact.tap do |o|
|
40
|
-
o
|
54
|
+
o << [:words_ngrams, :dice] if o.empty?
|
41
55
|
end
|
42
56
|
end
|
43
57
|
|
@@ -49,6 +63,12 @@ module Eco
|
|
49
63
|
compare(result)
|
50
64
|
end
|
51
65
|
|
66
|
+
def values_at(*keys)
|
67
|
+
keys.map do |key|
|
68
|
+
self.send(key) if self.respond_to?(key)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
52
72
|
private
|
53
73
|
|
54
74
|
def compare(other, order: self.order)
|
@@ -2,24 +2,48 @@ module Eco
|
|
2
2
|
module Data
|
3
3
|
module FuzzyMatch
|
4
4
|
class Results < Struct.new(:needle, :value, :raw_results)
|
5
|
+
include Enumerable
|
6
|
+
|
7
|
+
attr_accessor :threshold
|
8
|
+
|
9
|
+
def empty?
|
10
|
+
count < 1
|
11
|
+
end
|
12
|
+
|
13
|
+
def each(&block)
|
14
|
+
return to_enum(:each) unless block
|
15
|
+
raw_results.each(&block)
|
16
|
+
end
|
17
|
+
|
18
|
+
# Merges the results of both Results object
|
19
|
+
def merge(res)
|
20
|
+
unless self.needle == res.needle
|
21
|
+
raise "To merge 2 Results, needle should be the same ('#{value}'). Given '#{res.value}'"
|
22
|
+
end
|
23
|
+
self.class.new(needle, value, raw_results.concat(res.raw_results))
|
24
|
+
end
|
5
25
|
|
6
26
|
def results_with_false_positives
|
7
|
-
relevant_results(
|
27
|
+
relevant_results(order: :jaro_winkler, threshold: 0.5)
|
8
28
|
end
|
9
29
|
|
10
|
-
def relevant_results(
|
30
|
+
def relevant_results(**options)
|
31
|
+
options = {order: order, threshold: threshold || 0.5}.merge(options)
|
11
32
|
raw_results.select do |result|
|
12
|
-
result.all_threshold?(
|
33
|
+
result.all_threshold?(options[:order], options[:threshold])
|
13
34
|
end.yield_self do |filtered|
|
14
35
|
self.class.new(needle, value, filtered).tap do |results|
|
15
|
-
results.order =
|
36
|
+
results.order = options[:order]
|
16
37
|
end
|
17
38
|
end
|
18
39
|
end
|
19
40
|
|
41
|
+
# @param values[Array<Symbol>] the algorithms' results it should be ordered by
|
42
|
+
# * Possible values: `:dice`, `:levenshtein`, `:jaro_winkler`, `:ngrams`, `:words_ngrams`, `:chars_position`, `:average`
|
20
43
|
def order=(values)
|
21
|
-
@order = [values].flatten.compact
|
22
|
-
|
44
|
+
@order = [values].flatten.compact.tap do |o|
|
45
|
+
raw_results.each {|r| r.order = o}
|
46
|
+
end
|
23
47
|
end
|
24
48
|
|
25
49
|
def order
|
@@ -4,7 +4,10 @@ module Eco
|
|
4
4
|
class Score < Struct.new(:score, :total)
|
5
5
|
|
6
6
|
def ratio(decimals = 6)
|
7
|
-
|
7
|
+
tot = self.total; sc = self.score
|
8
|
+
tot = tot && tot > 0 ? tot : 1
|
9
|
+
sc = sc && sc > 0 ? sc : 0
|
10
|
+
(sc.to_f / tot).round(decimals)
|
8
11
|
end
|
9
12
|
|
10
13
|
def percent(decimals = 3)
|
@@ -13,6 +16,8 @@ module Eco
|
|
13
16
|
|
14
17
|
def increase(value = 1)
|
15
18
|
self.score += value
|
19
|
+
raise "Score #{self.score} (increase: #{value}) can't be greater than total #{self.total}" if self.score > self.total
|
20
|
+
self.score
|
16
21
|
end
|
17
22
|
|
18
23
|
def increase_total(value)
|
@@ -26,14 +31,14 @@ module Eco
|
|
26
31
|
end
|
27
32
|
|
28
33
|
# Merges 2 Score instance objects
|
29
|
-
def merge(
|
30
|
-
Score.new(*values_at(:score, :total)).merge!(
|
34
|
+
def merge(scr)
|
35
|
+
Score.new(*values_at(:score, :total)).merge!(scr)
|
31
36
|
end
|
32
37
|
|
33
|
-
def merge!(
|
34
|
-
raise "Expecting Score object. Given: #{
|
35
|
-
|
36
|
-
|
38
|
+
def merge!(scr)
|
39
|
+
raise "Expecting Score object. Given: #{scr.class}" unless scr.is_a?(Score)
|
40
|
+
increase_total(scr.total)
|
41
|
+
increase(scr.score)
|
37
42
|
self
|
38
43
|
end
|
39
44
|
|
@@ -17,7 +17,7 @@ module Eco
|
|
17
17
|
def get_words(str, normalized: false)
|
18
18
|
return [] unless str
|
19
19
|
str = normalize_string(str) unless normalized
|
20
|
-
str.scan(/[a-zA-Z'-]+/)
|
20
|
+
str.scan(/[a-zA-Z'-]+/).compact
|
21
21
|
end
|
22
22
|
|
23
23
|
# Keeps the start order of the `words` and consecutive `words` together/consecutive.
|
@@ -63,6 +63,19 @@ module Eco
|
|
63
63
|
str.tr(' ', '')
|
64
64
|
end
|
65
65
|
|
66
|
+
# Deletes the words of `str1` and `str2` that match
|
67
|
+
# @return [Array<String>] pair of words.
|
68
|
+
def remove_matching_words(str1, str2, normalized: false)
|
69
|
+
unless normalized
|
70
|
+
str1 = normalize_string(str1)
|
71
|
+
str2 = normalize_string(str2)
|
72
|
+
end
|
73
|
+
return [str1, str2] if !str1 || !str2 || str1.empty? || str2.empty?
|
74
|
+
ws1 = get_words(str1)
|
75
|
+
ws2 = get_words(str2)
|
76
|
+
[(ws1 - ws2).join(" "), (ws2 - ws1).join(" ")]
|
77
|
+
end
|
78
|
+
|
66
79
|
end
|
67
80
|
end
|
68
81
|
end
|
data/lib/eco/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: eco-helpers
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.24
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Oscar Segura
|
@@ -230,6 +230,26 @@ dependencies:
|
|
230
230
|
- - "<"
|
231
231
|
- !ruby/object:Gem::Version
|
232
232
|
version: '3.1'
|
233
|
+
- !ruby/object:Gem::Dependency
|
234
|
+
name: hashdiff
|
235
|
+
requirement: !ruby/object:Gem::Requirement
|
236
|
+
requirements:
|
237
|
+
- - ">="
|
238
|
+
- !ruby/object:Gem::Version
|
239
|
+
version: 1.0.1
|
240
|
+
- - "<"
|
241
|
+
- !ruby/object:Gem::Version
|
242
|
+
version: '1.1'
|
243
|
+
type: :runtime
|
244
|
+
prerelease: false
|
245
|
+
version_requirements: !ruby/object:Gem::Requirement
|
246
|
+
requirements:
|
247
|
+
- - ">="
|
248
|
+
- !ruby/object:Gem::Version
|
249
|
+
version: 1.0.1
|
250
|
+
- - "<"
|
251
|
+
- !ruby/object:Gem::Version
|
252
|
+
version: '1.1'
|
233
253
|
- !ruby/object:Gem::Dependency
|
234
254
|
name: fuzzy_match
|
235
255
|
requirement: !ruby/object:Gem::Requirement
|
@@ -290,6 +310,46 @@ dependencies:
|
|
290
310
|
- - "<"
|
291
311
|
- !ruby/object:Gem::Version
|
292
312
|
version: '1.6'
|
313
|
+
- !ruby/object:Gem::Dependency
|
314
|
+
name: roo
|
315
|
+
requirement: !ruby/object:Gem::Requirement
|
316
|
+
requirements:
|
317
|
+
- - ">="
|
318
|
+
- !ruby/object:Gem::Version
|
319
|
+
version: 2.8.3
|
320
|
+
- - "<"
|
321
|
+
- !ruby/object:Gem::Version
|
322
|
+
version: '2.9'
|
323
|
+
type: :runtime
|
324
|
+
prerelease: false
|
325
|
+
version_requirements: !ruby/object:Gem::Requirement
|
326
|
+
requirements:
|
327
|
+
- - ">="
|
328
|
+
- !ruby/object:Gem::Version
|
329
|
+
version: 2.8.3
|
330
|
+
- - "<"
|
331
|
+
- !ruby/object:Gem::Version
|
332
|
+
version: '2.9'
|
333
|
+
- !ruby/object:Gem::Dependency
|
334
|
+
name: roo-xls
|
335
|
+
requirement: !ruby/object:Gem::Requirement
|
336
|
+
requirements:
|
337
|
+
- - ">="
|
338
|
+
- !ruby/object:Gem::Version
|
339
|
+
version: 1.2.0
|
340
|
+
- - "<"
|
341
|
+
- !ruby/object:Gem::Version
|
342
|
+
version: '1.3'
|
343
|
+
type: :runtime
|
344
|
+
prerelease: false
|
345
|
+
version_requirements: !ruby/object:Gem::Requirement
|
346
|
+
requirements:
|
347
|
+
- - ">="
|
348
|
+
- !ruby/object:Gem::Version
|
349
|
+
version: 1.2.0
|
350
|
+
- - "<"
|
351
|
+
- !ruby/object:Gem::Version
|
352
|
+
version: '1.3'
|
293
353
|
description:
|
294
354
|
email:
|
295
355
|
- oscar@ecoportal.co.nz
|
@@ -332,6 +392,7 @@ files:
|
|
332
392
|
- lib/eco/api/common/people/default_parsers/policy_groups_parser.rb
|
333
393
|
- lib/eco/api/common/people/default_parsers/select_parser.rb
|
334
394
|
- lib/eco/api/common/people/default_parsers/send_invites_parser.rb
|
395
|
+
- lib/eco/api/common/people/default_parsers/xls_parser.rb
|
335
396
|
- lib/eco/api/common/people/entries.rb
|
336
397
|
- lib/eco/api/common/people/entry_factory.rb
|
337
398
|
- lib/eco/api/common/people/person_attribute_parser.rb
|
@@ -345,6 +406,8 @@ files:
|
|
345
406
|
- lib/eco/api/common/session/base_session.rb
|
346
407
|
- lib/eco/api/common/session/environment.rb
|
347
408
|
- lib/eco/api/common/session/file_manager.rb
|
409
|
+
- lib/eco/api/common/session/helpers.rb
|
410
|
+
- lib/eco/api/common/session/helpers/prompt_user.rb
|
348
411
|
- lib/eco/api/common/session/logger.rb
|
349
412
|
- lib/eco/api/common/session/logger/cache.rb
|
350
413
|
- lib/eco/api/common/session/logger/log.rb
|
@@ -397,7 +460,7 @@ files:
|
|
397
460
|
- lib/eco/api/organization.rb
|
398
461
|
- lib/eco/api/organization/login_providers.rb
|
399
462
|
- lib/eco/api/organization/people.rb
|
400
|
-
- lib/eco/api/organization/
|
463
|
+
- lib/eco/api/organization/people_similarity.rb
|
401
464
|
- lib/eco/api/organization/person_schemas.rb
|
402
465
|
- lib/eco/api/organization/policy_groups.rb
|
403
466
|
- lib/eco/api/organization/preferences.rb
|
@@ -441,6 +504,7 @@ files:
|
|
441
504
|
- lib/eco/api/usecases/default_cases/analyse_people_case.rb
|
442
505
|
- lib/eco/api/usecases/default_cases/append_usergroups_case.rb
|
443
506
|
- lib/eco/api/usecases/default_cases/change_email_case.rb
|
507
|
+
- lib/eco/api/usecases/default_cases/clean_unknown_tags_case.rb
|
444
508
|
- lib/eco/api/usecases/default_cases/codes_to_tags_case.rb
|
445
509
|
- lib/eco/api/usecases/default_cases/create_case.rb
|
446
510
|
- lib/eco/api/usecases/default_cases/create_details_case.rb
|
@@ -545,7 +609,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
545
609
|
requirements:
|
546
610
|
- - ">="
|
547
611
|
- !ruby/object:Gem::Version
|
548
|
-
version: 2.
|
612
|
+
version: 2.5.0
|
549
613
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
550
614
|
requirements:
|
551
615
|
- - ">="
|
@@ -1,60 +0,0 @@
|
|
1
|
-
module Eco
|
2
|
-
module API
|
3
|
-
module Organization
|
4
|
-
class PeopleAnalytics < Eco::API::Organization::People
|
5
|
-
include Eco::Data::FuzzyMatch
|
6
|
-
|
7
|
-
# @!group Helpers
|
8
|
-
|
9
|
-
# @!endgroup
|
10
|
-
|
11
|
-
# @!group Searchers
|
12
|
-
|
13
|
-
# It gathers those that have the same `email`
|
14
|
-
# @return [Hash] where `keys` are `email`s and `values` an `Array<Person>`
|
15
|
-
def repeated_emails
|
16
|
-
init_caches
|
17
|
-
@by_email.select do |email, people|
|
18
|
-
people.count > 1
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
# @!endgroup
|
23
|
-
|
24
|
-
# @!group Analysers
|
25
|
-
|
26
|
-
# TODO: Sort results by `results.first.methods`
|
27
|
-
def similarity(**options)
|
28
|
-
each_with_object({}) do |person, results|
|
29
|
-
results[person.id] = find_all_with_score(person, **options)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
|
34
|
-
def print_analysis(threshold)
|
35
|
-
similarity.each do |id, results|
|
36
|
-
msg = results.results.select do |result|
|
37
|
-
result.threshold?(threshold)
|
38
|
-
end.map do |result|
|
39
|
-
result.print
|
40
|
-
end.join("\n ")
|
41
|
-
|
42
|
-
puts "'#{self[id].identify}':\n " + msg
|
43
|
-
end
|
44
|
-
end
|
45
|
-
# @!endgroup
|
46
|
-
|
47
|
-
protected
|
48
|
-
|
49
|
-
def on_change
|
50
|
-
remove_instance_variable(@fuzzy_match)
|
51
|
-
super
|
52
|
-
end
|
53
|
-
|
54
|
-
private
|
55
|
-
|
56
|
-
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|