tsentiment 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: d80410d8503a5422608cb682bb2171f2773820ff88ac61af641e72cd57916a98
4
+ data.tar.gz: 8bea388530d44ac283f71cf7596973f3cbb2bd96842d1c3bd359cb3e161a233b
5
+ SHA512:
6
+ metadata.gz: 2ce85e4acfb17c5f3242532e8cf16b0e34aadaa4633a1de1762f9b00b4d6c330393ec73779aa0740132ff35194b0bb25a752489c3d73cde9b587de5fd927b77d
7
+ data.tar.gz: 1109c009239c97cd4f168fec680c4429de0739b9301cbf1ac66f89f92b4587b0bba84755d92b5ca876e72083f6157d7e99319a7ab401112e49c03f71ccaea579
@@ -0,0 +1,35 @@
1
+ require_relative 'task'
2
+
3
+ class CompositeTask < Task
4
+
5
+ def initialize(name)
6
+ super(name)
7
+ @sub_tasks = []
8
+ end
9
+
10
+ def <<(task)
11
+ @sub_tasks << task
12
+ end
13
+
14
+ def [](index)
15
+ @sub_tasks[index]
16
+ end
17
+
18
+ def []=(index, new_value)
19
+ @sub_tasks[index] = new_value
20
+ end
21
+
22
+ def size
23
+ @sub_tasks.size
24
+ end
25
+
26
+ def remove_sub_task(task)
27
+ @sub_tasks.delete(task)
28
+ end
29
+
30
+ def sentiment_value
31
+ time=0.0
32
+ @sub_tasks.each { |task| time += task.sentiment_value}
33
+ time
34
+ end
35
+ end
@@ -0,0 +1,118 @@
1
+ #Version with median library, negated sentiment calculation and overall sentiment calculation with composite
2
+
3
+ require 'json'
4
+ require 'net/http'
5
+ require_relative 'median'
6
+ require_relative 'negativity'
7
+ require_relative 'positivity'
8
+ require_relative 'negated'
9
+ require_relative 'composite_pattern'
10
+ require_relative 'total_sentiment'
11
+
12
+
13
+ class FindSentiment
14
+
15
+ def self.value(reviews, rating)
16
+
17
+ sentiment = Array.new
18
+ lexicon_sentiment = Array.new
19
+ review_sentiment = Array.new
20
+ overall_sentiment = Array.new
21
+ composite = CompositeTask.new('Sentiment')
22
+ negated = FindNegation.instance
23
+
24
+ i = 0
25
+
26
+ reviews.each do
27
+ string = reviews[i]
28
+
29
+ phrase_sentiment = Array.new
30
+
31
+ j = 0
32
+
33
+ sentence = string.split(".")
34
+
35
+ sentence.each do
36
+
37
+ phrase = sentence[j]
38
+
39
+ length = phrase.gsub(/\s+/, "").size
40
+
41
+ # Do not analyse the sentence if it's just an empty or just has one character
42
+
43
+ if length <= 1
44
+ j+=1
45
+ else
46
+
47
+ #Split the phrase into lexicons based on no. of negators and see if there are any
48
+
49
+ lexicon = phrase.split(/not|no|never/)
50
+ k = 0
51
+
52
+ if lexicon.count > 1 # If block handles the sentiment calculation of a phrase if the it has any negator
53
+ lexicon.each do
54
+ #lexicon_value = FindNegation.value(lexicon[k])
55
+ negated.sentiment(lexicon[k])
56
+ lexicon_value = negated.sentiment_value
57
+ lexicon_sentiment.push(lexicon_value)
58
+ k+=1
59
+ end
60
+
61
+ #sentiment value of each phrase separated by a full stop with negated sentiment calculation
62
+ sentiment_value = lexicon_sentiment.sum
63
+
64
+ else
65
+
66
+ # This block handles the sentiment calculation of a single phrase if it has no negator at all
67
+
68
+ #Finding total sentiment using composite design pattern
69
+
70
+ composite << TotalSentiment.new(phrase)
71
+
72
+
73
+
74
+ #sentiment value of each phrase separated by a full stop without negative words
75
+ sentiment_value = composite.sentiment_value
76
+
77
+ end
78
+
79
+ #stores sentiment value of each phrase of a review into the array phrase_sentiment
80
+ phrase_sentiment.push(sentiment_value)
81
+
82
+ j += 1
83
+
84
+ end
85
+ end
86
+
87
+ #Store sentiment of a single review - median of all phrases in a review
88
+
89
+ review_sentiment.push(FindMedian.value(phrase_sentiment))
90
+
91
+ i += 1
92
+
93
+ end
94
+
95
+ #Overall sentiment of all reviews - median of sentiment of all reviews
96
+
97
+ overall_sentiment = FindMedian.value(review_sentiment)
98
+
99
+ #Total sentiment of average of overall sentiment value of all user reviews + overall user rating
100
+
101
+ total_sentiment = (rating.to_f + overall_sentiment.to_f) / 2
102
+
103
+ return total_sentiment.to_f.round(2)
104
+
105
+ end
106
+
107
+ end
108
+
109
+ string = Array.new
110
+
111
+ string[0] = 'This product is not bad, it is good'
112
+ #string[1] = 'This product is. This product is good'
113
+ #string[2] = 'This product is good'
114
+ #string[3] = 'This is a rotten product'
115
+ #string[4] = 'This is a goodcp product'
116
+
117
+ weight = FindSentiment.value(string, 3)
118
+ puts weight
data/lib/median.rb ADDED
@@ -0,0 +1,19 @@
1
+
2
+ class FindMedian
3
+
4
+ def self.value(array)
5
+
6
+ sorted = array.sort
7
+ len = sorted.length
8
+
9
+ if len != 0
10
+ median = ((sorted[(len - 1) / 2] + sorted[len / 2]) / 2.0)
11
+ else
12
+ median = 0
13
+ end
14
+
15
+ return median
16
+
17
+ end
18
+
19
+ end
data/lib/negated.rb ADDED
@@ -0,0 +1,137 @@
1
+ require_relative 'task'
2
+ require_relative 'median'
3
+ require 'singleton'
4
+ require 'json'
5
+ require 'net/http'
6
+ require_relative 'negativity'
7
+ require_relative 'positivity'
8
+
9
+ class FindNegation < Task
10
+
11
+ include Singleton
12
+
13
+ def initialize
14
+ end
15
+
16
+ def sentiment(comment)
17
+
18
+ @phrase = comment
19
+ @sentiment
20
+
21
+ positive = FindPositivity.instance
22
+ negative = FindNegativity.instance
23
+
24
+ uri = URI('http://18.221.169.60/results')
25
+ params = { :limit => 10, :page => 3 }
26
+ uri.query = URI.encode_www_form(params)
27
+ res = Net::HTTP.get_response(uri)
28
+ adjectives = JSON.parse(res.body)
29
+
30
+ positives = adjectives[0]['positives']
31
+ negatives = adjectives[0]['negatives']
32
+
33
+ words = @phrase.split(/\W+/)
34
+
35
+ array1 = Array.new
36
+ output1 = Hash.new
37
+ array2 = Array.new
38
+ output2 = Hash.new
39
+
40
+ words.each do
41
+ |ws| ws.scan(/[\w']+/) do
42
+ |w| if positives.key?(w)
43
+ output1[ws] = positives[w]
44
+ array1.push(output1)
45
+ end
46
+
47
+ if negatives.key?(w)
48
+ output2[ws] = negatives[w]
49
+ array2.push(output2)
50
+ end
51
+ end
52
+ end
53
+
54
+ if array1.count == 0 && array2.count == 0
55
+ #puts "In case 0"
56
+ @sentiment = 0
57
+ end
58
+
59
+ if array1.count == 0 && array2.count != 0
60
+ #puts "In case 1"
61
+ positivity_sentiment = 0
62
+ negative.sentiment(@phrase)
63
+ negativity_sentiment = negative.sentiment_value
64
+ @sentiment = positivity_sentiment - negativity_sentiment
65
+ end
66
+
67
+ if array1.count != 0 && array2.count == 0
68
+ #puts "In case 2"
69
+ negativity_sentiment = 0
70
+ positive.sentiment(@phrase)
71
+ positivity_sentiment = positive.sentiment_value
72
+ @sentiment = negativity_sentiment - positivity_sentiment
73
+ end
74
+
75
+ if array1.count != 0 && array2.count != 0
76
+
77
+ #puts "In case 3"
78
+
79
+ first_positive = output1
80
+ first_negative = output2
81
+
82
+ index1 = @phrase.index("#{first_positive.keys[0]}")
83
+ index2 = @phrase.index("#{first_negative.keys[0]}")
84
+
85
+ if index1 < index2
86
+ #puts "The word #{first_positive.keys[0]} appears first"
87
+ negated_adj = first_positive
88
+ negated_sentiment = (negated_adj.values[0] * -1) # Negation only changes positive sentiment to negative
89
+ else
90
+ # puts "The word #{first_negative.keys[0]} appears first"
91
+ negated_adj = first_negative
92
+ #puts negated_adj
93
+ negated_sentiment = (negated_adj.values[0]) # Double negativity already
94
+ end
95
+
96
+ #Fetch the words after the first adjective and store it in remainder[1]
97
+
98
+ remainder = @phrase.split(/#{negated_adj.keys[0]}/)
99
+
100
+ # Find the sentiment of remainder[1]
101
+
102
+ positive.sentiment(remainder[1])
103
+ positivity_sentiment = positive.sentiment_value
104
+
105
+ negative.sentiment(remainder[1])
106
+ negativity_sentiment = negative.sentiment_value
107
+
108
+ #Now total sentiment = negated sentiment of first adjective + sentiment of the remainder[1]
109
+
110
+ if index1 < index2
111
+ #puts "I am in first positive"
112
+ fraction = Array[negated_sentiment, negativity_sentiment]
113
+ values = FindMedian.value(fraction)
114
+ @sentiment = positivity_sentiment + values
115
+ else
116
+ #puts "I am in first negative"
117
+ fraction = Array[negated_sentiment, positivity_sentiment]
118
+ values = FindMedian.value(fraction)
119
+ @sentiment = values + negativity_sentiment
120
+ end
121
+
122
+ end
123
+
124
+ end
125
+
126
+ def sentiment_value
127
+ @sentiment
128
+ end
129
+
130
+ end
131
+
132
+ #string = "This product is bad"
133
+
134
+ #weight = FindNegation.instance
135
+ #weight.sentiment(string)
136
+ #puts weight.sentiment_value
137
+
data/lib/negativity.rb ADDED
@@ -0,0 +1,59 @@
1
+ require_relative 'task'
2
+ require_relative 'median'
3
+ require 'json'
4
+ require 'net/http'
5
+ require 'singleton'
6
+
7
+ class FindNegativity < Task
8
+
9
+ include Singleton
10
+
11
+ def initialize
12
+ end
13
+
14
+ def sentiment(comment)
15
+
16
+ @phrase = comment
17
+ @sentiment
18
+ uri = URI('http://18.221.169.60/results')
19
+ params = { :limit => 10, :page => 3 }
20
+ uri.query = URI.encode_www_form(params)
21
+ res = Net::HTTP.get_response(uri)
22
+ adjectives = JSON.parse(res.body)
23
+
24
+ negatives = adjectives[0]['negatives']
25
+
26
+ words = @phrase.split(/\W+/)
27
+
28
+ array = Array.new
29
+ output = Hash.new
30
+
31
+ words.each do
32
+ |ws| ws.scan(/[\w']+/) do
33
+ |w| if negatives.key?(w)
34
+ output[ws] = negatives[w]
35
+ array.push(output)
36
+ end
37
+ end
38
+ end
39
+
40
+ @sentiment = FindMedian.value(output.values)
41
+ #puts negativity_sentiment
42
+
43
+ end
44
+
45
+ def sentiment_value
46
+ (@sentiment * -1)
47
+ end
48
+
49
+ end
50
+
51
+
52
+
53
+
54
+ #string = "This product is bad"
55
+
56
+ #weight = FindNegativity.instance
57
+ #weight.sentiment(string)
58
+ #puts weight.sentiment_value
59
+
data/lib/positivity.rb ADDED
@@ -0,0 +1,58 @@
1
+ require_relative 'task'
2
+ require_relative 'median'
3
+ require 'json'
4
+ require 'net/http'
5
+ require 'singleton'
6
+
7
+ class FindPositivity < Task
8
+
9
+ include Singleton
10
+
11
+ def initialize
12
+ end
13
+
14
+ def sentiment(comment)
15
+
16
+ @phrase = comment
17
+ @sentiment
18
+ uri = URI('http://18.221.169.60/results')
19
+ params = { :limit => 10, :page => 3 }
20
+ uri.query = URI.encode_www_form(params)
21
+ res = Net::HTTP.get_response(uri)
22
+ adjectives = JSON.parse(res.body)
23
+
24
+ positives = adjectives[0]['positives']
25
+
26
+ words = @phrase.split(/\W+/)
27
+
28
+ array = Array.new
29
+ output = Hash.new
30
+
31
+ words.each do
32
+ |ws| ws.scan(/[\w']+/) do
33
+ |w| if positives.key?(w)
34
+ output[ws] = positives[w]
35
+ array.push(output)
36
+ end
37
+ end
38
+ end
39
+
40
+ @sentiment = FindMedian.value(output.values)
41
+ #puts positivity_sentiment
42
+
43
+ end
44
+
45
+ def sentiment_value
46
+ @sentiment
47
+ end
48
+
49
+ end
50
+
51
+
52
+
53
+ #string = "This product is good"
54
+
55
+ #weight = FindPositivity.instance
56
+ #weight.sentiment(string)
57
+ #puts weight.sentiment_value
58
+
data/lib/task.rb ADDED
@@ -0,0 +1,11 @@
1
+ class Task
2
+ attr_reader :name
3
+
4
+ def initialize(name)
5
+ @name = name
6
+ end
7
+
8
+ def sentiment_value
9
+ 0.0
10
+ end
11
+ end
@@ -0,0 +1,24 @@
1
+ require_relative 'composite_pattern'
2
+ require_relative 'positivity'
3
+ require_relative 'negativity'
4
+ require_relative 'negated'
5
+
6
+
7
+
8
+ class TotalSentiment < CompositeTask
9
+
10
+ def initialize(phrase)
11
+ super ('Find total sentiment')
12
+
13
+ positive = FindPositivity.instance
14
+ negative = FindNegativity.instance
15
+ negated = FindNegation.instance
16
+ positive.sentiment(phrase)
17
+ negative.sentiment(phrase)
18
+ #negated.sentiment(phrase)
19
+
20
+ self << positive
21
+ self << negative
22
+ #self << negated
23
+ end
24
+ end
@@ -0,0 +1,36 @@
1
+ {
2
+ "results": [{
3
+ "positives": {
4
+ "good": 3,
5
+ "terrific": 4,
6
+ "brilliant": 4,
7
+ "awesome": 4,
8
+ "perfect": 4,
9
+ "amazing": 4,
10
+ "tasty": 3,
11
+ "yummy": 3,
12
+ "great": 4,
13
+ "best": 5,
14
+ "marvellous": 5,
15
+ "crazy": 5,
16
+ "wonderful": 4,
17
+ "commendable": 5
18
+ },
19
+ "negatives": {
20
+ "bad": 3,
21
+ "worst": 4,
22
+ "ridiculous": 4,
23
+ "pathetic": 5,
24
+ "poor": 4,
25
+ "hopeless": 4,
26
+ "useless": 4,
27
+ "late": 4,
28
+ "rotten": 5,
29
+ "spoilt": 5,
30
+ "tasteless": 4,
31
+ "flavorless": 4
32
+
33
+ }
34
+ }]
35
+
36
+ }
metadata ADDED
@@ -0,0 +1,52 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tsentiment
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Surya Kumar Govindan
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-12-09 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Return the sentiment value on a scale of -5 being the lowest feedback
14
+ to +5 highest feedback
15
+ email: suryajapan@gmail.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - lib/composite_pattern.rb
21
+ - lib/findSentiment.rb
22
+ - lib/median.rb
23
+ - lib/negated.rb
24
+ - lib/negativity.rb
25
+ - lib/positivity.rb
26
+ - lib/task.rb
27
+ - lib/total_sentiment.rb
28
+ - source/adjectives.json
29
+ homepage: http://rubygems.org/gems/tsentiment
30
+ licenses: []
31
+ metadata: {}
32
+ post_install_message:
33
+ rdoc_options: []
34
+ require_paths:
35
+ - lib
36
+ required_ruby_version: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ required_rubygems_version: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ requirements: []
47
+ rubygems_version: 3.0.6
48
+ signing_key:
49
+ specification_version: 4
50
+ summary: Analyses the overall mood or sentiment from the customer reviews and the
51
+ overall rating of a product
52
+ test_files: []