Skip to content

Commit

Permalink
feat(en): Adding repeating graph builder
Browse files Browse the repository at this point in the history
  • Loading branch information
aholstenson committed Oct 20, 2018
1 parent b37f557 commit a6f6e09
Show file tree
Hide file tree
Showing 6 changed files with 208 additions and 15 deletions.
4 changes: 4 additions & 0 deletions src/language/en/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import dateTime from './date-time';

import dateInterval from './date-interval';

import repeating from './repeating';

import stemmer from 'talisman/stemmers/porter';
import { similarity } from 'talisman/metrics/distance/jaro-winkler';
import treebank from 'talisman/tokenizers/words/treebank';
Expand Down Expand Up @@ -134,4 +136,6 @@ language.dateInterval = dateInterval(language);

language.temperature = temperature(language);

language.repeating = repeating(language);

export default language;
27 changes: 27 additions & 0 deletions src/language/en/repeating.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import GraphBuilder from '../../graph/builder';

export default function(language) {
return function(graph) {
const builder = new GraphBuilder(language)
.name('repeating[' + graph.options.name + ']')

.skipPunctuation();

// If the value supports partial matching so does this repeating value
if(graph.options.supportsPartial) {
builder.allowPartial();
}

if(graph.options.mapper) {
// If the graph has requested that matches are mapped - map each match
builder.mapResults(values => values.map(graph.options.mapper));
}

// Add the value and how it can be repeated
return builder
.add(graph, v => [ v[0] ])

.add([ GraphBuilder.result(), GraphBuilder.result() ], v => v[0].concat(v[1]))
.add([ GraphBuilder.result(), 'and', GraphBuilder.result() ], v => v[0].concat(v[1]));
};
}
13 changes: 10 additions & 3 deletions src/resolver/builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,22 @@ export default class Builder {
}

build() {
function makePrettyResult(result) {
function makePrettyResult(result, data) {
if(result.isPartialData()) {
result.data = new ResolvedIntent(data);

} else {
result.data._refreshExpression();
}

result.data.score = result.score;
result.data._refreshExpression();
return result.data;
}

this.parser.finalizer((results, encounter) => {
// Map so that only the data is made available
results = results.map(makePrettyResult);
results = results
.map(match => makePrettyResult(match, this.data));

return {
best: results[0] || null,
Expand Down
23 changes: 11 additions & 12 deletions src/values/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class Builder {
const instance = new ResolverBuilder(language, id);

// Set the name of the parser - for easier debugging
instance.parser._name = (this.name || 'options') + ':opt:' + id;
instance.parser._name = (parent._name || 'options') + '[' + id + ']';

// Transfer all of the values
for(const valueKey of Object.keys(option.values)) {
Expand All @@ -62,21 +62,20 @@ class Builder {
}

const parser = instance.build();
parent.add(parser, v => [ v[0] ]);
parent.add(parser, v => v[0]);
}

parent.add([ GraphBuilder.result(), GraphBuilder.result() ], v => v[0].concat(v[1]));
parent.add([ GraphBuilder.result(), 'and', GraphBuilder.result() ], v => v[0].concat(v[1]));
parent.mapResults(v => ({
option: v.intent,
values: v.values,
expression: v.expression
}));

parent.mapResults(v => {
return v.filter(v => !! v).map(o => ({
option: o.intent,
values: o.values,
expression: o.expression
}));
});
const repeating = language.repeating(parent.toMatcher())
.onlyBest()
.toMatcher();

return new ParsingValue(parent.toMatcher(), Object.assign({
return new ParsingValue(repeating, Object.assign({
supportsPartial: true
}, this.options));
});
Expand Down
46 changes: 46 additions & 0 deletions test/language/en/repeating.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import en from '../../../src/language/en';
import { testRunner } from '../helpers';
import GraphBuilder from '../../../src/graph/builder';

const phrase = new GraphBuilder(en)
.name('phrase')

.allowPartial()

.add('Hello', () => 1)
.add('World', () => 2)

.toMatcher();

const test = testRunner(en.repeating(phrase)
.onlyBest()
.toMatcher()
);

describe('English', function() {

describe('Repeating', function() {
test('Hello', {}, [ 1 ]);

test('World', {}, [ 2 ]);

test('Hello and World', {}, [ 1, 2 ]);

test('Hello World', {}, [ 1, 2 ]);

test('World, Hello', {}, [ 2, 1 ]);

test('Hello and World Hello', {}, [ 1, 2, 1 ]);

test('Hel', { partial: false }, null);

test('Hel', { partial: true }, [ 1 ]);

test('Hello Wo', { partial: true }, [ 1, 2 ]);

test('Hello and Wo', { partial: true }, [ 1, 2 ]);

test('He and Wo', { partial: true }, null);
});

});
110 changes: 110 additions & 0 deletions test/value-options.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,116 @@ import { options, dateInterval } from '../src/values';

describe('Value: Options', function() {

describe('Standalone option', () => {
const matcher = options()
.option('deadline')
.add('with deadline')
.done()
.build()
.matcher(lang);

it('with deadline [partial=false]', () => matcher('with deadline')
.then(v => {
expect(v).to.deep.equal([
{
option: 'deadline',
values: {},
expression: [
{
type: 'text',
value: 'with deadline',
source: { start: 0, end: 13 }
}
]
}
]);
})
);

it('with deadline [partial=true]', () => matcher('with deadline', { partial: true })
.then(v => {
expect(v).to.deep.equal([
{
option: 'deadline',
values: {},
expression: [
{
type: 'text',
value: 'with deadline',
source: { start: 0, end: 13 }
}
]
}
]);
})
);

it('with [partial=true]', () => matcher('with', { partial: true })
.then(v => {
expect(v).to.deep.equal([
{
option: 'deadline',
values: {},
expression: [
{
type: 'text',
value: 'with deadline',
source: { start: 0, end: 4 }
}
]
}
]);
})
);

it('with d [partial=true]', () => matcher('with d', { partial: true })
.then(v => {
expect(v).to.deep.equal([
{
option: 'deadline',
values: {},
expression: [
{
type: 'text',
value: 'with deadline',
source: { start: 0, end: 6 }
}
]
}
]);
})
);

it('with deadline and wi [partial=true]', () => matcher('with deadline and wi', { partial: true })
.then(v => {
expect(v).to.deep.equal([
{
option: 'deadline',
values: {},
expression: [
{
type: 'text',
value: 'with deadline',
source: { start: 0, end: 13 }
}
]
},
{
option: 'deadline',
values: {},
expression: [
{
type: 'text',
value: 'with deadline',
source: { start: 18, end: 20 }
}
]
}
]);
})
);
});

describe('Single option - no value', () => {
const queryOptions = options()
.option('deadline')
Expand Down

0 comments on commit a6f6e09

Please sign in to comment.