sentimental 1.0.4 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- ZGEzZGRjMmQ3NDk2Y2NlMzYwNWRkZWU2OTZmNzI1YTlmNmRiMGFiOQ==
4
+ NTM5MTBkMzdiNWY0NzdiYzliOWJlZWNmZDIyMzVjMDM1ZWJjNDYxYw==
5
5
  data.tar.gz: !binary |-
6
- NDAxMDFmNzZlMTQ3M2RmZGMzN2U4MjQwOGIzYTYyNDg0NzYzZWNjYQ==
6
+ NTVlYWNhNDIxZmE3ZDUyZjQ4N2ZlMGYxYWY0NzYxYmIxYWY2ZDZjNg==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- MjgzZDQ0MTFjOGM0Y2ZjZjAwYjg1NTlhOTRjMTZlZTM2ODkwMjY2MDFjYWU0
10
- ZjNlNDA4NGM3NThiZmEwNjRkYWQ5YWZiZDE1YjM2OGZjYzJiMTM2NDMxZmNl
11
- OTdmNGNhOTBjMjFmZjkxNmRhYjc4MDg5YWZmZjY1YjdjMDczOGI=
9
+ YjM0OTc1MzYyMDdlMmYyMWIyOTgwNmYyYThiMDhjZjkzMDFkYmFiNGNjYjBl
10
+ OWY3Zjg1NmFkZTgxY2YzY2I2OGMxZjBhNzhlZjEwNjkzNDQxNTRhNTQxYzFj
11
+ Yjc2NDBmZjk0OWZkYTc3ODMyMjFjN2RlY2FjMDFlNWMzMjRhM2M=
12
12
  data.tar.gz: !binary |-
13
- YjRhNzA3ZmJhOTdmMzIzMTU1MzcyM2ZlYThhOTM4MzdmYThhYzc0NDUxNTNm
14
- ZjM4MzBjMmE3Y2E2YTlmOTgyZjc3N2E2MTcxOTgxOWQ5ZmE4MTlhNTkwYzI5
15
- NTI0ZmVjNGY3MTFhNmFjMmUyYmQwOWVkZjcwYzg0NGM2NWQwNWU=
13
+ Nzg5YzMwMjM3MjU3YzJhOTU4NGIzN2NkZTY4ZjhkMGVmOWY5ZjcyNmMxYzdm
14
+ YzlkOGM5MDNhMzBiMjhkMmIyZThiMzAxYzA3Y2UxYTc2N2JlYmMzODE3MDFk
15
+ MDhhZjkwYTNmMGU1NDE1MTY0ZDUzNGZkYmRmM2JkMzVjM2M3Y2Y=
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ *.gem
2
+ *.DS_Store
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,32 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ sentimental (1.0.4)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ diff-lcs (1.2.5)
10
+ rake (10.5.0)
11
+ rspec (3.4.0)
12
+ rspec-core (~> 3.4.0)
13
+ rspec-expectations (~> 3.4.0)
14
+ rspec-mocks (~> 3.4.0)
15
+ rspec-core (3.4.1)
16
+ rspec-support (~> 3.4.0)
17
+ rspec-expectations (3.4.0)
18
+ diff-lcs (>= 1.2.0, < 2.0)
19
+ rspec-support (~> 3.4.0)
20
+ rspec-mocks (3.4.0)
21
+ diff-lcs (>= 1.2.0, < 2.0)
22
+ rspec-support (~> 3.4.0)
23
+ rspec-support (3.4.1)
24
+
25
+ PLATFORMS
26
+ ruby
27
+
28
+ DEPENDENCIES
29
+ bundler (~> 1.3)
30
+ rake
31
+ rspec (>= 3.0.0)
32
+ sentimental!
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+
2
+ The MIT License (MIT)
3
+ Copyright © 2015 Jeff Emminger <jeff@7compass.com>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the “Software”), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md CHANGED
@@ -73,6 +73,10 @@ scores and tokens, e.g.:
73
73
 
74
74
  gem install sentimental
75
75
 
76
+ ## License
77
+
78
+ MIT License
79
+
76
80
  ## Credits
77
81
 
78
82
  Based largely on Christopher MacLellan's script:
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task default: :spec
File without changes
File without changes
data/lib/sentimental.rb CHANGED
@@ -1,116 +1,52 @@
1
-
2
- # Based on code from https://github.com/cmaclell/Basic-Tweet-Sentiment-Analyzer
3
-
4
-
5
- #############################################################################
6
- # Copyright: Christopher MacLellan 2010
7
- # Description: This code adds functions to the string class for calculating
8
- # the sentivalue of strings. It is not called directly by the
9
- # tweet-search-sentiment.rb program but is included for possible
10
- # future use.
11
- #
12
- # This program is free software: you can redistribute it and/or modify
13
- # it under the terms of the GNU General Public License as published by
14
- # the Free Software Foundation, either version 3 of the License, or
15
- # (at your option) any later version.
16
- #
17
- # This program is distributed in the hope that it will be useful,
18
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
19
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20
- # GNU General Public License for more details.
21
- #
22
- # You should have received a copy of the GNU General Public License
23
- # along with this program. If not, see <http://www.gnu.org/licenses/>.
24
- #############################################################################
25
-
26
- #
27
- # In an initializer, you can initialize some global defaults:
28
- #
29
- # Sentimental.load_defaults
30
- # Sentimental.threshold = 0.1
31
- #
32
- # Then create an instance for usage:
33
- #
34
- # analyzer = Sentimental.new
35
- # analyzer.get_sentiment('I love your service')
36
- # => :positive
37
- #
38
- # You can make new analyzers with individual thresholds:
39
- #
40
- # analyzer = Sentimental.new(0.9)
41
- # analyzer.get_sentiment('I love your service')
42
- # => :positive
43
- # analyzer.get_sentiment('I like your service')
44
- # => :neutral
45
- #
46
1
  class Sentimental
47
- @@sentihash = Hash.new(0.0)
48
- @@threshold = 0.0
2
+ attr_accessor :threshold, :word_scores, :neutral_regexps
49
3
 
50
- def initialize(threshold = nil)
51
- @threshold = threshold || @@threshold
4
+ def initialize(threshold: 0, word_scores: nil, neutral_regexps: [])
5
+ @word_scores = Hash.new(0.0) || word_scores
6
+ @threshold = threshold
7
+ @neutral_regexps = neutral_regexps
52
8
  end
53
9
 
54
- #####################################################################
55
- # Function that returns the sentiment value for a given string.
56
- # This value is the sum of the sentiment values of each of the words.
57
- # Stop words are NOT removed.
58
- #
59
- # return:float -- sentiment value of the current string
60
- #####################################################################
61
- def get_score(string)
62
- sentiment_total = 0.0
10
+ def score(string)
11
+ return 0 if neutral_regexps.any? {|regexp| string =~ regexp}
63
12
 
64
- #tokenize the string, also throw away some punctuation
65
- tokens = string.to_s.downcase.split(/\W*\s+\W*|^\W+|\W+$/)
66
-
67
- tokens.each do |token|
68
- sentiment_total += @@sentihash[token]
13
+ extract_words(string).inject(0) do |score, token|
14
+ score += word_scores[token]
69
15
  end
70
- sentiment_total
71
16
  end
72
17
 
73
- def get_sentiment(string)
74
- score = get_score(string)
18
+ def sentiment(string)
19
+ score = score(string)
75
20
 
76
- # if less then the negative threshold classify negative
77
- if score < (-1 * @threshold)
21
+ if score < (-1 * threshold)
78
22
  :negative
79
- # if greater then the positive threshold classify positive
80
- elsif score > @threshold
23
+ elsif score > threshold
81
24
  :positive
82
25
  else
83
26
  :neutral
84
27
  end
85
28
  end
86
29
 
87
- # Loads the default sentiment files
88
- def self.load_defaults
89
- load_senti_file(File.dirname(__FILE__) + '/sentiwords.txt')
90
- load_senti_file(File.dirname(__FILE__) + '/sentislang.txt')
30
+ def load_defaults
31
+ ['sentiwords', 'sentislang'].each do |filename|
32
+ load_senti_file(File.dirname(__FILE__) + "/../data/#{filename}.txt")
33
+ end
91
34
  end
92
35
 
93
- #####################################################################
94
- # load the specified sentiment file into a hash
95
- #
96
- # filename:string -- name of file to load
97
- # sentihash:hash -- hash to load data into
98
- # return:hash -- hash with data loaded
99
- #####################################################################
100
- def self.load_senti_file(filename)
101
- # load the word file
102
- file = File.new(filename)
103
- while (line = file.gets)
104
- parsedline = line.chomp.split(/\s/)
105
- sentiscore = parsedline[0]
106
- text = parsedline[1]
107
- @@sentihash[text] = sentiscore.to_f
36
+ def load_senti_file(filename)
37
+ File.open(filename) do |file|
38
+ file.each_line do |line|
39
+ parsed_line = line.chomp.split(/\s+/)
40
+ sentiscore = parsed_line[0]
41
+ text = parsed_line[1]
42
+ word_scores[text] = sentiscore.to_f
43
+ end
108
44
  end
109
- file.close
110
45
  end
111
46
 
112
- def self.threshold=(threshold)
113
- @@threshold = threshold
114
- end
47
+ private
115
48
 
49
+ def extract_words(string)
50
+ string.to_s.downcase.scan(/([\w']+|\S{2,})/).flatten
51
+ end
116
52
  end
@@ -0,0 +1,19 @@
1
+ Gem::Specification.new do |spec|
2
+ spec.name = 'sentimental'
3
+ spec.version = '1.1.0'
4
+ spec.summary = 'Simple sentiment analysis'
5
+ spec.description = 'A simple sentiment analysis gem'
6
+ spec.authors = ['Jeff Emminger', 'Christopher MacLellan', 'Denis Pasin']
7
+ spec.email = ['jeff@7compass.com', 'denis@hellojam.fr']
8
+ spec.homepage = 'https://github.com/7compass/sentimental'
9
+ spec.license = 'MIT'
10
+
11
+ spec.files = `git ls-files`.split($/)
12
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
13
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
14
+ spec.require_paths = ['lib']
15
+
16
+ spec.add_development_dependency "bundler", "~> 1.3"
17
+ spec.add_development_dependency "rake"
18
+ spec.add_development_dependency "rspec", ">= 3.0.0"
19
+ end
@@ -0,0 +1,72 @@
1
+ require_relative "../lib/sentimental"
2
+
3
+ describe Sentimental do
4
+
5
+ before :each do
6
+ analyzer.load_defaults
7
+ end
8
+
9
+ let(:analyzer) { Sentimental.new(threshold: 0.1) }
10
+
11
+ describe "#score" do
12
+ subject do
13
+ analyzer.score(text)
14
+ end
15
+
16
+ context "when the text is postive" do
17
+ let(:text) {'I love ruby'}
18
+
19
+ it 'returns a positive score' do
20
+ expect(subject).to be > 0
21
+ end
22
+ end
23
+
24
+ context "when the text is neutral" do
25
+ let(:text) {'I like ruby'}
26
+
27
+ it 'returns a neutral score' do
28
+ expect(subject).to eq 0
29
+ end
30
+ end
31
+
32
+ context "when the text is negative" do
33
+ let(:text) {'I hate ruby'}
34
+
35
+ it 'returns a negative score' do
36
+ expect(subject).to be < 0
37
+ end
38
+ end
39
+
40
+ context "when the text has smiley" do
41
+ let(:text) {'I love ruby'}
42
+ let(:text_with_smiley) {'I love ruby :-)'}
43
+
44
+ it 'scores it' do
45
+ expect(analyzer.score(text_with_smiley)).to be > analyzer.score(text)
46
+ end
47
+ end
48
+
49
+ context "when the text has punctuation" do
50
+ let(:text) {'I love ruby'}
51
+ let(:text_with_punctuation) {'I love, ruby'}
52
+
53
+ it 'removes it' do
54
+ expect(analyzer.score(text_with_punctuation)).to eq analyzer.score(text)
55
+ end
56
+ end
57
+
58
+ context "when there is some neutral regexp" do
59
+ let(:text_neutral) {"Do you love ruby?"}
60
+ let(:text) {"I love ruby"}
61
+
62
+ before do
63
+ analyzer.neutral_regexps << /\?\s*$/
64
+ end
65
+
66
+ it "scores it to 0" do
67
+ expect(analyzer.score(text_neutral)).to eq 0
68
+ expect(analyzer.score(text)).not_to eq 0
69
+ end
70
+ end
71
+ end
72
+ end
metadata CHANGED
@@ -1,26 +1,78 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sentimental
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.4
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeff Emminger
8
8
  - Christopher MacLellan
9
+ - Denis Pasin
9
10
  autorequire:
10
11
  bindir: bin
11
12
  cert_chain: []
12
- date: 2015-11-12 00:00:00.000000000 Z
13
- dependencies: []
13
+ date: 2016-03-10 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: bundler
17
+ requirement: !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '1.3'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - ~>
27
+ - !ruby/object:Gem::Version
28
+ version: '1.3'
29
+ - !ruby/object:Gem::Dependency
30
+ name: rake
31
+ requirement: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - ! '>='
34
+ - !ruby/object:Gem::Version
35
+ version: '0'
36
+ type: :development
37
+ prerelease: false
38
+ version_requirements: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ! '>='
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ - !ruby/object:Gem::Dependency
44
+ name: rspec
45
+ requirement: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ! '>='
48
+ - !ruby/object:Gem::Version
49
+ version: 3.0.0
50
+ type: :development
51
+ prerelease: false
52
+ version_requirements: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ! '>='
55
+ - !ruby/object:Gem::Version
56
+ version: 3.0.0
14
57
  description: A simple sentiment analysis gem
15
- email: jeff@7compass.com
58
+ email:
59
+ - jeff@7compass.com
60
+ - denis@hellojam.fr
16
61
  executables: []
17
62
  extensions: []
18
63
  extra_rdoc_files: []
19
64
  files:
65
+ - .gitignore
66
+ - Gemfile
67
+ - Gemfile.lock
68
+ - LICENSE.txt
20
69
  - README.md
70
+ - Rakefile
71
+ - data/sentislang.txt
72
+ - data/sentiwords.txt
21
73
  - lib/sentimental.rb
22
- - lib/sentislang.txt
23
- - lib/sentiwords.txt
74
+ - sentimental.gemspec
75
+ - spec/sentimental_spec.rb
24
76
  homepage: https://github.com/7compass/sentimental
25
77
  licenses:
26
78
  - MIT
@@ -28,7 +80,6 @@ metadata: {}
28
80
  post_install_message:
29
81
  rdoc_options: []
30
82
  require_paths:
31
- - .
32
83
  - lib
33
84
  required_ruby_version: !ruby/object:Gem::Requirement
34
85
  requirements:
@@ -46,4 +97,5 @@ rubygems_version: 2.4.8
46
97
  signing_key:
47
98
  specification_version: 4
48
99
  summary: Simple sentiment analysis
49
- test_files: []
100
+ test_files:
101
+ - spec/sentimental_spec.rb