inci_score 3.0.3 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
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