Skip to content

Commit

Permalink
Merge pull request #29 from amos-ws16/dev
Browse files Browse the repository at this point in the history
Sprint 05 Release
  • Loading branch information
Oliver committed Nov 24, 2016
2 parents a982aaa + 0817d9f commit b9a7aa4
Show file tree
Hide file tree
Showing 17 changed files with 220 additions and 19 deletions.
12 changes: 10 additions & 2 deletions CHANGELOG.md
@@ -1,9 +1,17 @@
# Change Log
All notable changes to this project will be documented in this file.

## [Unrelease](https://github.com/amos-ws16/amos-ws16-arrowjs/compare/sprint-04-release...dev)
## [Unreleased](https://github.com/amos-ws16/amos-ws16-arrowjs/compare/sprint-05-release...dev)

## [1.1.0]https://github.com/amos-ws16/amos-ws16-arrowjs/releases/tag/sprint-04-release) - 2016-11-17
## [1.2.0](https://github.com/amos-ws16/amos-ws16-arrowjs/releases/tag/sprint-05-release) - 2016-11-24

### Added
- Error detection and graceful failure in Plugins and reporting to user ([PR](https://github.com/amos-ws16/amos-ws16-arrowjs/pull/25))
- Documentation of REST [input schema](https://github.com/amos-ws16/amos-ws16-arrowjs/blob/master/docs/rest-api.md)
- Validation of successful deployment ([PR](https://github.com/amos-ws16/amos-ws16-arrowjs/pull/26))
- Scoring Plugin by [similar context](https://github.com/amos-ws16/amos-ws16-arrowjs/blob/master/lib/plugins/similar-context-plugin.js)

## [1.1.0](https://github.com/amos-ws16/amos-ws16-arrowjs/releases/tag/sprint-04-release) - 2016-11-17

### Added
- [Changelog](https://github.com/amos-ws16/amos-ws16-arrowjs/blob/master/CHANGELOG.md)
Expand Down
4 changes: 2 additions & 2 deletions bin/start-server.js
Expand Up @@ -2,9 +2,9 @@

const server = require('../lib/server')

const port = process.env.PORT || 3000
const cliPort = process.argv.length > 2 && process.argv[2] || undefined
const port = cliPort || process.env.PORT || 3000

server.listen(port, () => {
console.log(`Server started on Port: ${port}`)
})

1 change: 1 addition & 0 deletions deployment-scripts/config-dev.cfg
Expand Up @@ -2,3 +2,4 @@
INSTALL_DIR=/home/ubuntu/amos-dev
STOP_CMD="/home/ubuntu/dev-stop-cmd.sh"
START_CMD="/home/ubuntu/dev-start-cmd.sh"
AMOS_PORT=3000
1 change: 1 addition & 0 deletions deployment-scripts/config-master.cfg
Expand Up @@ -2,3 +2,4 @@
INSTALL_DIR=/home/ubuntu/amos-master
STOP_CMD="/home/ubuntu/master-stop-cmd.sh"
START_CMD="/home/ubuntu/master-start-cmd.sh"
AMOS_PORT=4000
4 changes: 1 addition & 3 deletions deployment-scripts/create-zip.sh
@@ -1,8 +1,6 @@
#!/bin/bash
mkdir deployment-build
mkdir deployment-build/temp
mkdir -p deployment-build/temp
cp -R $(git ls-tree --name-only HEAD) deployment-scripts/config.cfg appspec.yml deployment-build/temp/
cd deployment-build/temp
zip -r ../latest.zip ./
cd ../..
rm -R deployment-build/temp
12 changes: 11 additions & 1 deletion deployment-scripts/validate-service.sh
Expand Up @@ -2,4 +2,14 @@
my_dir="$(dirname "$0")"
source $my_dir/config.cfg

echo "validate that amos app is working..."
echo "validate that amos server is running ..."
output="$(curl -I -sS --request GET http://localhost:${AMOS_PORT}/api/welcome)"

if [[ ${output[0]} == "HTTP/1.1 200 OK"* ]]
then
echo "Server is started!"
exit 0
else
echo "Server is not started!"
exit 1
fi
12 changes: 6 additions & 6 deletions docs/aws-codedeploy.md
Expand Up @@ -55,11 +55,11 @@ Unter der EC2-Instanz in der AWS Console unter Description muss bei IAM role etw
--application-name APP
--s3-location bucket=amos-deploy-dev,key=deployment,bundleType=zip,eTAG=<ETAG>
--deployment-group-name amos-deployment-group
* APP: amos-master | amos-dev

* APP: amos-app-master | amos-app-dev



## Integration mit Travis:
Die Integration mit Travis umfasst mehrere Dateien, die je nach branch unterschiedliche Konfigurationen aufruft:
* .travis.yml: Deployment-Konfiguration für travis
Expand All @@ -70,7 +70,7 @@ Die Integration mit Travis umfasst mehrere Dateien, die je nach branch unterschi
Die Integration funktioniert automatisch für alle Änderungen auf dem dev und master branch. Die erreichbaren Welcome-Endpunkte sind:
* dev: http://ec2-52-212-74-103.eu-west-1.compute.amazonaws.com:3000/api/welcome
* master: http://ec2-52-212-74-103.eu-west-1.compute.amazonaws.com:4000/api/welcome

Bei einer Änderung der branches oder weiteren Einschränkungen müssen folgende Dateien angepasst werden:
* .travis.yml (branch-Spezifizikation unter deploy.codedeploy)
* deployment-scripts/before-deploy.sh
53 changes: 53 additions & 0 deletions docs/rest-api.md
@@ -0,0 +1,53 @@
# REST API Reference
This file documents the REST API input and output schemata for the route
`/api/score`.

## Input Schema
All fields are optional unless specified as required.

```json
{
"file": {
"name": "(required) string ",
"filetype": "(required) string png/jpeg",
"timestamp": "(required) number",
"user": "(required) id string",
"description": "string that was sent with the upload",
"context": {
"chat": "...",
"more stuff": "...",
"to be defined later": "..."
}
},
"tasks": [
{
"name": "(required) string",
"timestamp": "(required) number",
"due_date": "number",
"user": "(required) id string",
"assignees": ["userid1", "userid2", "..."],
"description": "string",
"location": "..."
},
"..."]
}
```

## Output Schema
Not yet finished.

```json
{
"tasks": [
{
"name": "string",
"score": 1.0,
"subscores": {
"plugin-a": 1.0,
"...": "..."
}
},
"..."
]
}
```
7 changes: 7 additions & 0 deletions docs/start-api.md
@@ -0,0 +1,7 @@
# Start the API on local or external server


1. Open the command line
2. Go to the main directory of the project
3. Type 'npm start' to start the API on standard port 3000
4. To configure the port type 'npm start -- your_port'
3 changes: 3 additions & 0 deletions lib/plugins/close-time-plugin.js
Expand Up @@ -9,6 +9,9 @@ const timeLimit = 600
* than timeLimit will result in a score of 0.0.
*/
function closeTimePlugin (file, task) {
if (file.timestamp === undefined) {
throw new Error('file.timestamp not found')
}
let difference = Math.abs(file.timestamp - task.timestamp)
return difference > timeLimit ? 0.0 : 1.0 - difference / timeLimit
}
Expand Down
34 changes: 34 additions & 0 deletions lib/plugins/similar-context-plugin.js
@@ -0,0 +1,34 @@
const stringSimilarity = require('string-similarity')
const keywordExtractor = require('keyword-extractor')
const utils = require('../utils.js')

/**
* First uses the keyword-extractor to get the keywords, then compares the keywords with stringSimilarity to get a context score
*
* @param file - the file with its description
* @param task - the task with its description
*/
function similarContextPlugin (sString1, sString2) {
utils.isString(sString1)
utils.isString(sString2)
const sKeywords1 = getKeywords(sString1)
const sKeywords2 = getKeywords(sString2)

return stringSimilarity.compareTwoStrings(sKeywords1, sKeywords2)
}

/**
* Uses the keyword-extractor module to get the keywords from the description and then joins the array to a string
*
* @param description - as string
*/
function getKeywords (description) {
return keywordExtractor.extract(description, {
language: 'english',
remove_digits: true,
return_changed_case: true,
remove_duplicates: false
}).join(' ')
}

module.exports = similarContextPlugin
6 changes: 5 additions & 1 deletion lib/score-manager.js
Expand Up @@ -3,7 +3,11 @@ function applyPlugins (plugins, file, task) {
let scores = {}

Object.keys(plugins).forEach((key, idx) => {
scores[key] = plugins[key](file, task)
try {
scores[key] = plugins[key](file, task)
} catch (err) {
scores[key] = 'failure: ' + err.message
}
})

return scores
Expand Down
13 changes: 12 additions & 1 deletion lib/utils.js
Expand Up @@ -10,4 +10,15 @@ function basename (filename) {
return dotPosition === -1 ? filename : filename.substring(0, dotPosition)
}

module.exports = { basename }
/**
* Check if a given string is a valid string
*
* @param sString - the string that needs to be checked
*/
function isString (sString) {
if (typeof (sString) !== 'string' || sString === '') {
throw new Error(`${sString} is not a valid string`)
}
}

module.exports = { basename, isString }
7 changes: 4 additions & 3 deletions package.json
@@ -1,6 +1,6 @@
{
"name": "arrow",
"version": "1.1.0",
"version": "1.2.0",
"description": "Description that needs to be changed some time soon",
"license": "AGPL-3.0",
"repository": "https://github.com/amos-ws16/amos-ws16-arrowjs",
Expand All @@ -14,7 +14,6 @@
"eslint-plugin-standard": "^2.0.1",
"istanbul": "^0.4.5",
"nyc": "^8.4.0",
"string-similarity": "^1.1.0",
"supertest": "^2.0.1"
},
"scripts": {
Expand All @@ -27,6 +26,8 @@
},
"dependencies": {
"body-parser": "^1.15.2",
"express": "^4.14.0"
"express": "^4.14.0",
"string-similarity": "^1.1.0",
"keyword-extractor": "0.0.13"
}
}
7 changes: 7 additions & 0 deletions test/plugins/close-time-plugin-test.js
Expand Up @@ -50,6 +50,13 @@ buster.testCase('Input Scorer', {
let task = { timestamp: taskTimestamp }
let result = plugin(file, task)
buster.assert.equals(result, 0.25)
},

'should throw \'no timestamp exception\' if no timestamp is present in file': function () {
const taskTimestamp = uploadTimestamp
let file = { }
let task = { timestamp: taskTimestamp }
buster.assert.exception(() => plugin(file, task))
}

})
25 changes: 25 additions & 0 deletions test/plugins/similar-context-test.js
@@ -0,0 +1,25 @@
const buster = require('buster')
const plugin = require('../../lib/plugins/similar-context-plugin.js')

buster.testCase('similar-context-plugin', {
'should return 1.0 when the keywords of file description and task description match exactly': function () {
let sString1 = 'president obama woke monday facing congressional defeat parties believed hobble presidency'
let sString2 = 'President Obama woke up Monday facing a Congressional defeat that many in both parties believed could hobble his presidency.'
let result = plugin(sString1, sString2)
buster.assert.near(1.0, result, 0)
},

'should return 0.0 when the keywords of file description and task description dont match at all': function () {
let sString1 = '123 3415i 02387564'
let sString2 = 'President Obama woke up Monday facing a Congressional defeat that many in both parties believed could hobble his presidency.'
let result = plugin(sString1, sString2)
buster.assert.near(0.0, result, 0)
},

'should throw an error if called with a non-string parameter': function () {
let iNumber = 12
let sString = 'President Obama woke up Monday facing a Congressional defeat that many in both parties believed could hobble his presidency.'
buster.assert.exception(() => plugin(iNumber, sString))
}

})
38 changes: 38 additions & 0 deletions test/score-manager-test.js
Expand Up @@ -157,6 +157,44 @@ buster.testCase('Score Manager with aggregator', {

var meanScoreResult = meanScoreManager.score(blob)
buster.assert.near(meanScoreResult[0].score, 0.45, 1e-3)
},

'plugin failures': {
'should be caught and returned as a special value': function () {
let aggregator = { combine: this.stub().returns(1.0) }
let manager = new ScoreManager(aggregator)
let plugA = () => 1.0
let plugB = () => { throw new Error() }
manager.registerPlugin('plugin-a', plugA)
manager.registerPlugin('plugin-b', plugB)

let blob = {
file: {},
tasks: [{}]
}

let result = manager.score(blob)

buster.assert.match(result[0].scores['plugin-b'], /failure/)
},

'should be caught and returned as error message with description': function () {
let aggregator = { combine: this.stub().returns(1.0) }
let manager = new ScoreManager(aggregator)
let plugA = () => 1.0
let plugC = () => { throw new Error('this is the error description') }
manager.registerPlugin('plugin-a', plugA)
manager.registerPlugin('plugin-c', plugC)

let blob = {
file: {},
tasks: [{}]
}

let result = manager.score(blob)

buster.assert.match(result[0].scores['plugin-c'], /this is the error description/)
}
}
})

Expand Down

0 comments on commit b9a7aa4

Please sign in to comment.