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 +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +4 -5
- data/config/catalog.yml +1 -0
- data/lib/inci_score/api.rb +1 -2
- data/lib/inci_score/cli.rb +2 -7
- data/lib/inci_score/computer.rb +3 -8
- data/lib/inci_score/ingredient.rb +3 -7
- data/lib/inci_score/recognizer.rb +7 -8
- data/lib/inci_score/recognizer_rules.rb +2 -2
- data/lib/inci_score/refinements.rb +0 -5
- data/lib/inci_score/version.rb +1 -1
- data/spec/integration/api_spec.rb +1 -1
- data/spec/stubs.rb +1 -1
- data/spec/unit/cli_spec.rb +1 -1
- data/spec/unit/ingredient_spec.rb +0 -6
- data/spec/unit/recognizer_spec.rb +6 -8
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8aab0ebc926de421bb3aaecf7c52a8522c8f47e4
|
4
|
+
data.tar.gz: 1306f8fd4375384c4c2965155759cfe251b515fb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0ce833b953c31f2097356e87c2c33fbbe49e866e26e541b836b8bfba7b2b999ef7cd5ae3d3e81b92ad05e473aabdfec7fb0c45496f7cd3aa096103e3b9fac8a1
|
7
|
+
data.tar.gz: 046d1e9c4a481919546f27287442401ee05d9d2265cd1413eff5bcfb5f75b6de1619439bba3aaeef78b6fb6f8173a93ca70737a165d311c7614990242f46d88b
|
data/Gemfile.lock
CHANGED
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"
|
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
|
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 |
|
140
|
-
| agua,porfum,zeolithe |
|
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
data/lib/inci_score/api.rb
CHANGED
@@ -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
|
-
|
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
|
data/lib/inci_score/cli.rb
CHANGED
@@ -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
|
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"
|
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
|
data/lib/inci_score/computer.rb
CHANGED
@@ -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 ||=
|
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
|
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
|
18
|
+
def call
|
19
19
|
return if @ingredient.to_s.empty?
|
20
|
-
component = find_component
|
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
|
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
|
29
|
+
apply(rule)
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
|
-
private def apply(rule
|
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.
|
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 }.
|
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
|
data/lib/inci_score/version.rb
CHANGED
@@ -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
|
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
data/spec/unit/cli_spec.rb
CHANGED
@@ -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\"
|
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
|
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-
|
11
|
+
date: 2017-10-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: puma
|