Skip to content

Commit

Permalink
Merge branch 'dev' into feature-47-exceptions
Browse files Browse the repository at this point in the history
  • Loading branch information
Oliver Esser committed Nov 29, 2016
2 parents 795f113 + d5e13ea commit 7006f88
Show file tree
Hide file tree
Showing 7 changed files with 167 additions and 55 deletions.
44 changes: 42 additions & 2 deletions config/index.js
@@ -1,18 +1,58 @@
const aggregator = require('../lib/score-aggregator')

const config = {}

/**
* Default config for scoreManager
*
* similar-title: compare titles if file and tasks
* context-file-timestamp-tasks-timestamp: compares timestamps of file and tasks - timeLimit = 600s (default in plugin)
* context-file-timestamp-tasks-timestamp: compares keywords of file title with keywords of description of tasks
* context-file-description-task-title: compares keywords of file description with keywords of description of tasks
* context-file-description-task-description: compares keywords of file description with keywords of description of tasks
*/
config.scoreManager = {
aggregator: new aggregator.Mean(),
plugins: {
// similar-title-plugin pulls file.name from file and tasks[].name from tasks[] itself
'similar-title': {
use: 'similar-title-plugin',
inputs: ['file', 'tasks[]']
},
'close-time': {
// timestamp comparison defaults to 600 sec
'context-file-timestamp-tasks-timestamp': {
use: 'close-timestamp-plugin',
inputs: ['file.created_at', 'tasks[].created_at'],
params: { 'time-limit': 1234 }
},
'context-file-title-task-description': {
use: 'similar-context-plugin',
inputs: ['file.name', 'tasks[].description'],
params: { 'extractKeywords': true }
},
'context-file-description-task-title': {
use: 'similar-context-plugin',
inputs: ['file.description', 'tasks[].name'],
params: { 'extractKeywords': true }
},
'context-file-description-task-description': {
use: 'similar-context-plugin',
inputs: ['file.description', 'tasks[].description'],
params: { 'extractKeywords': true }
},
'similar-file-title-task-description': {
use: 'similar-context-plugin',
inputs: ['file.name', 'tasks[].description'],
params: { 'extractKeywords': false }
},
'similar-file-description-task-title': {
use: 'similar-context-plugin',
inputs: ['file.description', 'tasks[].name'],
params: { 'extractKeywords': false }
},
'similar-file-description-task-description': {
use: 'similar-context-plugin',
inputs: ['file.description', 'tasks[].description'],
params: { 'extractKeywords': false }
}
}
}
Expand Down
47 changes: 25 additions & 22 deletions docs/rest-api.md
Expand Up @@ -7,30 +7,33 @@ 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",
"file": {
"title": "(required) string ",
"type": "(required) string png/jpeg",
"created_at": "(required) unix timestamp",
"user": "(required) id string",
"assignees": ["userid1", "userid2", "..."],
"description": "string",
"location": "..."
},
"..."]
"description": "string that was sent with the upload",
"context": {
"chat": "...",
"more stuff": "...",
"to be defined later": "..."
}
},
"tasks": [
{
"title": "(required) string",
"created_at": "(required) unix timestamp",
"due_date": "unix timestamp",
"created_by": "(required) id string",
"last_updated_by": "id string",
"last_updated_at": "unix timestamp",
"assignees": ["userid1", "userid2", "..."],
"description": "string",
"location": "..."
},
"..."]
}

```

## Output Schema
Expand Down
32 changes: 24 additions & 8 deletions lib/plugins/similar-context-plugin.js
Expand Up @@ -3,18 +3,34 @@ 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 'extractKeywords' by default false:
* Returns a comparing score of two strings based on Dice's Coefficient using the stringSimilarity module.
*
* If param 'extractKeywords' is true: 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
* @param params - object with attribute extractKeywords as parameter for extracting the keywords (true - extract keyword before calculating similarity score, false - whithout extraction)
*/
function similarContextPlugin (sString1, sString2) {
utils.isString(sString1)
utils.isString(sString2)
const sKeywords1 = getKeywords(sString1)
const sKeywords2 = getKeywords(sString2)
function similarityPlugin (sString1, sString2, params) {
let extractKeywords = (params && params['extractKeywords']) || false

if ((typeof sString1 === 'undefined') || (typeof sString2 === 'undefined')) {
throw new Error(`Two Strings as input are needed.`)
}

utils.isValidString(sString1)
utils.isValidString(sString2)

if (typeof extractKeywords !== 'boolean') {
throw new Error(`Boolean expected, found ${extractKeywords}`)
}

return stringSimilarity.compareTwoStrings(sKeywords1, sKeywords2)
if (extractKeywords) {
sString1 = getKeywords(sString1)
sString2 = getKeywords(sString2)
}
return stringSimilarity.compareTwoStrings(sString1, sString2)
}

/**
Expand All @@ -31,4 +47,4 @@ function getKeywords (description) {
}).join(' ')
}

module.exports = similarContextPlugin
module.exports = similarityPlugin
11 changes: 0 additions & 11 deletions lib/plugins/similar-string-plugin.js

This file was deleted.

11 changes: 7 additions & 4 deletions lib/utils.js
Expand Up @@ -23,9 +23,12 @@ function cloneObject (obj) {
*
* @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`)
function isValidString (sString) {
if (typeof (sString) !== 'string') {
throw new Error(`String expected, found ${sString}`)
}
if (sString === '') {
throw new Error(`Non-empty string expected.`)
}
}

Expand All @@ -38,4 +41,4 @@ function isInRange (n, min, max) {
return typeof n === 'number' && n >= min && n <= max
}

module.exports = { basename, cloneObject, isString, isInRange }
module.exports = { basename, cloneObject, isValidString, isInRange }
2 changes: 1 addition & 1 deletion test/load-plugin-test.js
Expand Up @@ -3,7 +3,7 @@ const loadPlugin = require('../lib/load-plugin')

buster.testCase('loadPlugin', {
'should load and return a plugin module': function () {
let plugin = loadPlugin('similar-string-plugin')
let plugin = loadPlugin('similar-context-plugin')
buster.assert(plugin)
let result = plugin('Hello', 'Gello')
buster.assert.equals(result, 0.75)
Expand Down
75 changes: 68 additions & 7 deletions test/plugins/similar-context-test.js
@@ -1,25 +1,86 @@
const buster = require('buster')
const stringSimilarity = require('string-similarity')
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 () {
'test1 - with Keywordsextraction: should return 1.0 when both strings matches': 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)
let keywordExtraction = { extractKeywords: true }
let result = plugin(sString1, sString2, keywordExtraction)
buster.assert.near(1.0, result, 1e-3)
},

'should return 0.0 when the keywords of file description and task description dont match at all': function () {
'test2 - with Keywordsextraction: should return 0.0 when both strings 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)
let keywordExtraction = { extractKeywords: true }
let result = plugin(sString1, sString2, keywordExtraction)
buster.assert.equals(0.0, result)
},

'should throw an error if called with a non-string parameter': function () {
'test4 - without Keywordsextraction: should return 1.0 when both strings matches': function () {
let sString1 = 'president obama'
let sString2 = 'president obama'
let keywordExtraction = { extractKeywords: false }
let result = plugin(sString1, sString2, keywordExtraction)
buster.assert.near(1.0, result, 1e-3)
},

'test5 - without Keywordsextraction: should return 0.0 both strings 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 keywordExtraction = { extractKeywords: false }
let result = plugin(sString1, sString2, keywordExtraction)
buster.assert.equals(0.0, result)
},

'test6 - without Keywordsextraction: should return the same value as Stringsimilarity compare method': function () {
this.stub(stringSimilarity, 'compareTwoStrings').returns(1.0)
let sString1 = 'healed.jpeg'
let sString2 = 'sealed'
let keywordExtraction = { extractKeywords: false }

let result = plugin(sString1, sString2, keywordExtraction)
buster.assert.near(result, 1.0, 1e-3)
},

'test7 - should call Stringsimilarity compare method': function () {
let compare = this.stub(stringSimilarity, 'compareTwoStrings')
let sString1 = 'healed.jpeg'
let sString2 = 'sealed'
let keywordExtraction = { extractKeywords: false }

plugin(sString1, sString2, keywordExtraction)
buster.assert.called(compare)
},

'test8 - 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))
},

'test9 - should throw an error if only 1 string is passed for comparison to the plugin': function () {
let sString = 'test'
buster.assert.exception(() => plugin(sString))
},

'test10 - should throw an error if a string is empty': function () {
let sString1 = 'test'
let sString2 = ''
buster.assert.exception(() => plugin(sString1, sString2))
},

'test11 - should throw an error if no strings are passed for comparison': function () {
buster.assert.exception(() => plugin())
},

'test12 - should throw an error if the last parameter - extractKeywords - has a non boolean attribute - extractKeywords': function () {
let sString1 = 'test'
let sString2 = 'test'
let keywordExtraction = { extractKeywords: 'test' }
buster.assert.exception(() => plugin(sString1, sString2, keywordExtraction))
}

})

0 comments on commit 7006f88

Please sign in to comment.