inci_score 3.0.3 → 3.1.0

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
  SHA1:
3
- metadata.gz: 3acb19f9ac522f6a50378ec318c6466ae9b67257
4
- data.tar.gz: 3d46458825c9d1fb3ff74db0779b329b63c5f97a
3
+ metadata.gz: 8aab0ebc926de421bb3aaecf7c52a8522c8f47e4
4
+ data.tar.gz: 1306f8fd4375384c4c2965155759cfe251b515fb
5
5
  SHA512:
6
- metadata.gz: 9ab029ca732a8605502a7263fa3d7fc96ad20be2ca6aaf9b142e599746eae8216bd326ae318b92aed19a24e157456fe63dd99642d52f536c0a3ea0a4cd59e5bd
7
- data.tar.gz: 6d23d330b4267abc0d2ba4241c52d0f55d94922bc1dbb776842e3266afd699f366ade1c648f2e76c3ba2a85db7a680aac59257f683d9d85b5fb2b9b352eae536
6
+ metadata.gz: 0ce833b953c31f2097356e87c2c33fbbe49e866e26e541b836b8bfba7b2b999ef7cd5ae3d3e81b92ad05e473aabdfec7fb0c45496f7cd3aa096103e3b9fac8a1
7
+ data.tar.gz: 046d1e9c4a481919546f27287442401ee05d9d2265cd1413eff5bcfb5f75b6de1619439bba3aaeef78b6fb6f8173a93ca70737a165d311c7614990242f46d88b
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- inci_score (3.0.1)
4
+ inci_score (3.1.0)
5
5
  RubyInline (~> 3)
6
6
  puma (~> 3)
7
7
 
data/README.md CHANGED
@@ -105,9 +105,8 @@ curl http://127.0.0.1:9292?src=aqua,dimethicone
105
105
  ### Getting help
106
106
  You can get CLI interface help by:
107
107
  ```shell
108
- Usage: inci_score --src="aqua, parfum, etc" --precise
108
+ Usage: inci_score --src="aqua, parfum, etc"
109
109
  -s, --src=SRC The INCI list: "aqua, parfum, etc"
110
- -p, --precise Compute components more precisely (slower)
111
110
  --http=PORT Start HTTP server on the specified port
112
111
  -h, --help Prints this help
113
112
  ```
@@ -130,12 +129,12 @@ I registered these benchmarks with a MacBook PRO 15 mid 2015 having these specs:
130
129
  As always i used [wrk](https://github.com/wg/wrk) as the loading tool.
131
130
  I measured the library three times, picking the best lap.
132
131
  ```shell
133
- wrk -t 4 -c 100 -d 30s --timeout 2000 "http://0.0.0.0:9292/?src=<source>&precise=true"
132
+ wrk -t 4 -c 100 -d 30s --timeout 2000 "http://0.0.0.0:9292/?src=<source>"
134
133
  ```
135
134
 
136
135
  ### Results
137
136
  | Source | Throughput (req/s) |
138
137
  | --------------------------: | -----------------: |
139
- | aqua,parfum,zeolite | 18784.21 |
140
- | agua,porfum,zeolithe | 1087.88 |
138
+ | aqua,parfum,zeolite | 20296.75 |
139
+ | agua,porfum,zeolithe | 1098.45 |
141
140
  | agua/water,porfum/fragrance | 1599.47 |
data/config/catalog.yml CHANGED
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  aqua: 0
3
+ water: 0
3
4
  parfum: 3
4
5
  fragrance: 3
5
6
  phosphatidylcholine: 1
@@ -12,8 +12,7 @@ module InciScore
12
12
  def call(env)
13
13
  req = Rack::Request.new(env)
14
14
  src = req.params["src"]
15
- precise = req.params["precise"]
16
- json = src ? Computer.new(src: src, catalog: catalog, precise: !!precise).call.to_json : %q({"error": "no valid source"})
15
+ json = src ? Computer.new(src: src, catalog: catalog).call.to_json : %q({"error": "no valid source"})
17
16
  ["200", {"Content-Type" => "application/json"}, [json]]
18
17
  end
19
18
  end
@@ -10,28 +10,23 @@ module InciScore
10
10
  @catalog = catalog
11
11
  @src = nil
12
12
  @port = nil
13
- @precise = nil
14
13
  end
15
14
 
16
15
  def call(server_klass: Server, computer_klass: Computer)
17
16
  parser.parse!(@args)
18
17
  return server_klass.new(port: @port, preload: true).run if @port
19
18
  return @io.puts(%q{Specify inci list as: --src="aqua, parfum, etc"}) unless @src
20
- @io.puts computer_klass.new(src: @src, catalog: @catalog, precise: @precise).call
19
+ @io.puts computer_klass.new(src: @src, catalog: @catalog).call
21
20
  end
22
21
 
23
22
  private def parser
24
23
  OptionParser.new do |opts|
25
- opts.banner = %q{Usage: inci_score --src="aqua, parfum, etc" --precise}
24
+ opts.banner = %q{Usage: inci_score --src="aqua, parfum, etc"}
26
25
 
27
26
  opts.on("-sSRC", "--src=SRC", %q{The INCI list: "aqua, parfum, etc"}) do |src|
28
27
  @src = src
29
28
  end
30
29
 
31
- opts.on("-p", "--precise", "Compute components more precisely (slower)") do |precise|
32
- @precise = precise
33
- end
34
-
35
30
  opts.on("--http=PORT", "Start HTTP server on the specified port") do |port|
36
31
  @port = port
37
32
  end
@@ -12,14 +12,12 @@ module InciScore
12
12
  def initialize(src:,
13
13
  catalog: Catalog.fetch,
14
14
  tolerance: TOLERANCE,
15
- rules: Normalizer::DEFAULT_RULES,
16
- precise: false)
15
+ rules: Normalizer::DEFAULT_RULES)
17
16
  @src = src
18
17
  @catalog = catalog
19
18
  @tolerance = Float(tolerance)
20
19
  @rules = rules
21
20
  @unrecognized = []
22
- @precise = precise
23
21
  end
24
22
 
25
23
  def call
@@ -34,15 +32,12 @@ module InciScore
34
32
  end
35
33
 
36
34
  private def ingredients
37
- @ingredients ||= begin
38
- tokens = Normalizer.new(src: @src, rules: @rules).call
39
- Ingredient.bulk(tokens)
40
- end
35
+ @ingredients ||= Normalizer.new(src: @src, rules: @rules).call
41
36
  end
42
37
 
43
38
  private def components
44
39
  @components ||= ingredients.map do |ingredient|
45
- Recognizer.new(ingredient, @catalog).call(@precise).tap do |component|
40
+ Recognizer.new(ingredient, @catalog).call.tap do |component|
46
41
  @unrecognized << ingredient unless component
47
42
  end
48
43
  end.compact
@@ -5,13 +5,9 @@ module InciScore
5
5
  PARENTHESIS = %w[( ) [ ]]
6
6
  DETAILS_RULE = /(\(.+\)|\[.+\])/
7
7
 
8
- def self.bulk(tokens)
9
- tokens.map { |raw| new(raw) }
10
- end
11
-
12
8
  def initialize(raw)
13
- @raw = raw
14
- @tokens = raw.split(SLASH_RULE).map(&:strip)
9
+ @raw = raw.to_s
10
+ @tokens = @raw.split(SLASH_RULE).map(&:strip)
15
11
  end
16
12
 
17
13
  def to_s
@@ -28,7 +24,7 @@ module InciScore
28
24
  end
29
25
 
30
26
  private def synonims
31
- @tokens[1, @tokens.size]
27
+ @tokens[1, @tokens.size].to_a
32
28
  end
33
29
 
34
30
  private def details
@@ -8,30 +8,29 @@ module InciScore
8
8
 
9
9
  attr_reader :applied
10
10
 
11
- def initialize(ingredient, catalog, rules = DEFAULT_RULES)
12
- @ingredient = ingredient
11
+ def initialize(ingredient, catalog, rules = DEFAULT_RULES, wrapper = Ingredient)
12
+ @ingredient = wrapper.new(ingredient)
13
13
  @catalog = catalog
14
14
  @rules = rules
15
15
  @applied = []
16
16
  end
17
17
 
18
- def call(precise = false)
18
+ def call
19
19
  return if @ingredient.to_s.empty?
20
- component = find_component(precise)
20
+ component = find_component
21
21
  return unless component
22
22
  Component.new(component, @catalog[component])
23
23
  end
24
24
 
25
- private def find_component(precise)
25
+ private def find_component
26
26
  @rules.reduce(nil) do |component, rule|
27
27
  break(component) if component
28
28
  applied << rule
29
- apply(rule, precise)
29
+ apply(rule)
30
30
  end
31
31
  end
32
32
 
33
- private def apply(rule, precise)
34
- return rule.call(@ingredient.to_s, @catalog) unless precise
33
+ private def apply(rule)
35
34
  @ingredient.values.map do |value|
36
35
  rule.call(value, @catalog)
37
36
  end.find(&:itself)
@@ -58,14 +58,14 @@ module InciScore
58
58
  def call(src, catalog)
59
59
  tokens(src).each do |token|
60
60
  catalog.each do |component, _|
61
- return component if component.matches?(/\b#{Regexp.escape(token)}\b/)
61
+ return component if component.include?(token)
62
62
  end
63
63
  end
64
64
  nil
65
65
  end
66
66
 
67
67
  def tokens(src)
68
- (src.split(" ") - UNMATCHABLE).reject { |t| t.size < TOLERANCE }.sort_by!(&:size).reverse!
68
+ (src.split(" ") - UNMATCHABLE).reject { |t| t.size < TOLERANCE }.sort! { |a, b| b.size <=> a.size }
69
69
  end
70
70
  end
71
71
  end
@@ -10,11 +10,6 @@ module InciScore
10
10
  def distance(t)
11
11
  InciScore::LevenshteinC.new.call(self.downcase, self.size, t.downcase, t.size)
12
12
  end
13
-
14
- def matches?(re)
15
- return match?(re) if defined?("".match?)
16
- match(re)
17
- end
18
13
  end
19
14
  end
20
15
  end
@@ -1,3 +1,3 @@
1
1
  module InciScore
2
- VERSION = "3.0.3"
2
+ VERSION = "3.1.0"
3
3
  end
@@ -12,7 +12,7 @@ describe InciScore::Api do
12
12
  status, score = Stubs.statuses[i], Stubs.scores[i]
13
13
 
14
14
  it "cosmetic #{i} must get a proper response" do
15
- get "/", src: src, precise: true
15
+ get "/", src: src
16
16
  assert last_response.ok?
17
17
  last_response.content_type.must_equal "application/json"
18
18
  body = JSON::parse(last_response.body)
data/spec/stubs.rb CHANGED
@@ -48,7 +48,7 @@ END
48
48
  end
49
49
 
50
50
  def scores
51
- [79, 66, 72, 63, 63, 75, 75, 56, 73, 63]
51
+ [79, 64, 72, 63, 61, 82, 75, 56, 75, 62]
52
52
  end
53
53
 
54
54
  def statuses
@@ -12,7 +12,7 @@ describe InciScore::CLI do
12
12
  begin
13
13
  InciScore::CLI.new(args: %w[--help], io: io, catalog: Stubs.catalog).call
14
14
  rescue SystemExit
15
- io.string.must_equal "Usage: inci_score --src=\"aqua, parfum, etc\" --precise\n -s, --src=SRC The INCI list: \"aqua, parfum, etc\"\n -p, --precise Compute components more precisely (slower)\n --http=PORT Start HTTP server on the specified port\n -h, --help Prints this help\n"
15
+ io.string.must_equal "Usage: inci_score --src=\"aqua, parfum, etc\"\n -s, --src=SRC The INCI list: \"aqua, parfum, etc\"\n --http=PORT Start HTTP server on the specified port\n -h, --help Prints this help\n"
16
16
  end
17
17
  end
18
18
 
@@ -1,12 +1,6 @@
1
1
  require "helper"
2
2
 
3
3
  describe InciScore::Ingredient do
4
- it "must create instances in bulk" do
5
- InciScore::Ingredient.bulk(Stubs.ingredients.first).each do |ingredient|
6
- ingredient.must_be_instance_of InciScore::Ingredient
7
- end
8
- end
9
-
10
4
  it "must be represented as a string" do
11
5
  ingredient = InciScore::Ingredient.new("acrylamidopropyltrimonium chloride/acrylates copolymer")
12
6
  ingredient.to_s.must_equal "acrylamidopropyltrimonium chloride/acrylates copolymer"
@@ -1,5 +1,4 @@
1
1
  require "helper"
2
- require "inci_score/recognizer"
3
2
 
4
3
  describe InciScore::Recognizer do
5
4
  let(:rules) { [] }
@@ -22,6 +21,12 @@ describe InciScore::Recognizer do
22
21
  recognizer.applied.must_equal InciScore::Recognizer::DEFAULT_RULES[0,1]
23
22
  end
24
23
 
24
+ it "must recognize by key by using synonim" do
25
+ recognizer = InciScore::Recognizer.new("olio di oliva/olea europea", Stubs.catalog)
26
+ recognizer.call
27
+ recognizer.applied.must_equal InciScore::Recognizer::DEFAULT_RULES[0,1]
28
+ end
29
+
25
30
  it "must recognize by key and levenshtein" do
26
31
  recognizer = InciScore::Recognizer.new("agua", Stubs.catalog)
27
32
  recognizer.call
@@ -39,11 +44,4 @@ describe InciScore::Recognizer do
39
44
  recognizer.call
40
45
  recognizer.applied.must_equal InciScore::Recognizer::DEFAULT_RULES
41
46
  end
42
-
43
- it "must recognize component precisely" do
44
- ingredient = InciScore::Ingredient.new("olio di oliva/olea europea")
45
- recognizer = InciScore::Recognizer.new(ingredient, Stubs.catalog)
46
- recognizer.call(true)
47
- recognizer.applied.must_equal InciScore::Recognizer::DEFAULT_RULES[0,1]
48
- end
49
47
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: inci_score
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.3
4
+ version: 3.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - costajob
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-10-19 00:00:00.000000000 Z
11
+ date: 2017-10-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: puma