From b4ea4046fa0fb8b437a9363b5d16501011de5347 Mon Sep 17 00:00:00 2001
From: Sebastian Steiner <e1029038@student.tuwien.ac.at>
Date: Fri, 18 Jan 2019 16:29:56 +0100
Subject: [PATCH] issue #62 implemented

---
 service-analysis/Dockerfile            |  2 ++
 service-analysis/README.md             | 32 +++++++++++++++++++++-----
 service-analysis/analysis.py           |  2 +-
 service-analysis/offline_analysis.py   | 26 +++++++++++++++++++++
 service-analysis/requirements.txt      |  1 +
 service-analysis/sentiment_analysis.py |  2 ++
 6 files changed, 58 insertions(+), 7 deletions(-)
 create mode 100644 service-analysis/offline_analysis.py

diff --git a/service-analysis/Dockerfile b/service-analysis/Dockerfile
index ad239ec..be70c7c 100644
--- a/service-analysis/Dockerfile
+++ b/service-analysis/Dockerfile
@@ -6,6 +6,8 @@ COPY	. /app/
 
 RUN		pip install -r requirements.txt
 
+RUN		python -m textblob.download_corpora
+
 RUN		chmod a+x *.py
 
 CMD		["python3.7", "./sentiment_analysis.py"]
diff --git a/service-analysis/README.md b/service-analysis/README.md
index 1572beb..57c6b0c 100644
--- a/service-analysis/README.md
+++ b/service-analysis/README.md
@@ -9,7 +9,7 @@ The service uses the the sentiment analysis service indico.
 
 `GET`: `/health` Returns HTTP Status 200 if service is running
 
-`POST`: `/` Calculates the average sentiment for a given list of texts
+`POST`: `/` Calculates the average sentiment for a given list of texts using the online sentiment analysis tool indico (https://www.indico.io).
 - param: Term[ ] as Content-Tye: `application/json`
 example body of request:
 ```json
@@ -25,6 +25,22 @@ example body of request:
 	}
 ]
 ```
+`POST`: `/offline_analysis` Calculates the average sentiment for a given list of texts using TextBlob (https://textblob.readthedocs.io)
+- param:  Term[ ] as Content-Tye: `application/json`
+example body of request:
+```json
+[
+	{
+		'text': 'sample text 1',
+	},
+	{	
+		'text': 'sample text 2',
+	},
+	{	
+		'text': 'sample text 3',
+	}
+]
+```
 JSON string may contain more value-key pairs than 'text', but 'text' is needed for the sentiment analysis. Everything else will be ignored.
 For more examples see curl commands in local -> commands.
 
@@ -33,8 +49,9 @@ For more examples see curl commands in local -> commands.
 - `503`: indico sentiment analysis not available
 
 ## external services
-This sentiment analysis service uses and relies on the online sentiment analysis indico (https://www.indico.io).
-The api key can be set in the file indico_api_key.txt. The current key does work, however excessive use of this service will require you to provide your own key, since the amount of requests for this key is limited.
+This sentiment analysis service uses the online sentiment analysis indico (https://www.indico.io).
+The indico api key can be set in the file indico_api_key.txt. The current key does work, however excessive use of this service will require you to provide your own key, since the amount of requests for this key is limited.
+In case of an 503 error, you can use the `/offline_analysis`.
 
 ## run with docker
 - `docker build -t sentiment_analysis .`
@@ -46,8 +63,11 @@ The api key can be set in the file indico_api_key.txt. The current key does work
 - pip: indicoio
 - pip: flask
 - pip: flask_restful
+- pip: textblob
 ### commands
-- `python3.7 sentiment_analysis.py`
-- positive sentiment test example: `curl -v -H 'content-type: application/json' -X POST http://localhost:8081 -d '[{"text":"happy birthday, i love you"}]'`
-- negative sentiment test example: `curl -v -H 'content-type: application/json' -X POST http://localhost:8081 -d '[{"text":"i hate you, please die"}]'`
+- `python3.7 sentiment_analysis.py` to start the service
+- positive online sentiment test example: `curl -v -H 'content-type: application/json' -X POST http://localhost:8081 -d '[{"text":"happy birthday, i love you"}]'`
+- negative online sentiment test example: `curl -v -H 'content-type: application/json' -X POST http://localhost:8081 -d '[{"text":"i hate you, please die"}]'`
+- positive offline sentiment test example: `curl -v -H 'content-type: application/json' -X POST http://localhost:8081/offline_analysis -d '[{"text":"happy birthday, i love you"}]'`
+- negative offline sentiment test example: `curl -v -H 'content-type: application/json' -X POST http://localhost:8081/offline_analysis -d '[{"text":"i hate you, please die"}]'`
 - health check test example: `curl -v -X GET http://localhost:8081/health`
diff --git a/service-analysis/analysis.py b/service-analysis/analysis.py
index 291b8e0..b0c43b2 100644
--- a/service-analysis/analysis.py
+++ b/service-analysis/analysis.py
@@ -10,7 +10,7 @@ service_error_503 = 'The sentiment analysis service is currently unavailable.'
 
 class Analysis(Resource):
 	def get(self):
-		return "POST a list of JSON objects as content-type: application/json. JSON objects must contain key 'text'.", 405, {'Allow': 'GET'}
+		return "POST a list of JSON objects as content-type: application/json. JSON objects must contain key 'text'.", 405
 		
 	def post(self):
 		if not request.json or not isinstance(request.json, (list,)):
diff --git a/service-analysis/offline_analysis.py b/service-analysis/offline_analysis.py
new file mode 100644
index 0000000..9c9da3a
--- /dev/null
+++ b/service-analysis/offline_analysis.py
@@ -0,0 +1,26 @@
+# -*- coding: utf-8 -*-
+import json
+
+from flask import request
+from flask_restful import Resource, abort
+from textblob import TextBlob
+
+input_error_409 = 'Input must be a list of JSON objects. JSON objects must contain contain key text.'
+
+class Offline_Analysis(Resource):
+	def get(self):
+		return "POST a list of JSON objects as content-type: application/json. JSON objects must contain key 'text'.", 405
+		
+	def post(self):
+		if not request.json or not isinstance(request.json, (list,)):
+			return abort(409, message=input_error_409)
+		texts = request.json
+		value = 0
+		for text in texts:
+			if 'text' not in text:
+				return abort(409, message=input_error_409)
+			analysis = TextBlob(text['text'])
+			value += (analysis.sentiment.polarity/2) + 0.5
+		sentiment = value/len(texts)
+		data = {'sentiment': sentiment}
+		return data
diff --git a/service-analysis/requirements.txt b/service-analysis/requirements.txt
index 206be2f..65e5420 100644
--- a/service-analysis/requirements.txt
+++ b/service-analysis/requirements.txt
@@ -1,3 +1,4 @@
 flask
 flask_restful
 indicoio
+textblob
diff --git a/service-analysis/sentiment_analysis.py b/service-analysis/sentiment_analysis.py
index e27b0af..055a48d 100644
--- a/service-analysis/sentiment_analysis.py
+++ b/service-analysis/sentiment_analysis.py
@@ -3,6 +3,7 @@ import json
 import indicoio
 
 from analysis import Analysis
+from offline_analysis import Offline_Analysis
 from health_check import Health_Check
 
 from flask import Flask
@@ -15,6 +16,7 @@ with open('indico_api_key.txt', 'r') as key:
 	indicoio.config.api_key = key.read().replace('\n','')
 
 api.add_resource(Analysis, '/')
+api.add_resource(Offline_Analysis, '/offline_analysis')
 api.add_resource(Health_Check, '/health')
 
 if __name__ == '__main__':
-- 
2.43.0