Skip to content

Commit

Permalink
Merge pull request #4 from evangelion1204/1-add-sort-by-priority
Browse files Browse the repository at this point in the history
Added tests and sorting of children based on priority
  • Loading branch information
evangelion1204 committed Jan 7, 2016
2 parents 990c24d + 672cc97 commit 763aec4
Show file tree
Hide file tree
Showing 7 changed files with 103 additions and 35 deletions.
3 changes: 2 additions & 1 deletion .babelrc
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"babel-plugin-transform-es2015-block-scoping",
"babel-plugin-check-es2015-constants",
"babel-plugin-transform-es2015-classes",
"babel-plugin-transform-es2015-template-literals"
"babel-plugin-transform-es2015-template-literals",
"babel-plugin-transform-es2015-arrow-functions"
]
}
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,20 @@ console.log(instance.find('/my_path').data) // will output "data"

The second parameter in `Tree.add()` can be anything, a string, a function or an object. The stored path, data and contained parameters will be returned via `Tree.find()`.

### Priority

With version 0.2.0 routes are internally sorted by priority and no longer handled FIFO, routes with many childs have a higher priority and are scanned earlier.

Adding first `/users` and then `/cart/add` and `/cart/remove` will result in reordering of the children and place cart before users.Expl

```
(3) /
(2) cart/
(1) add
(1) remove
(1) users
```

### Static routes

A static route can be any type of endpoint of a service, valid examples are:
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "radix-tree",
"version": "0.1.4",
"version": "0.2.0",
"description": "Node.js version of a radix tree usable for routers or url path based storage.",
"main": "index.js",
"engines": {
Expand Down Expand Up @@ -32,6 +32,7 @@
"devDependencies": {
"babel-cli": "^6.3.17",
"babel-plugin-check-es2015-constants": "^6.3.13",
"babel-plugin-transform-es2015-arrow-functions": "^6.4.0",
"babel-plugin-transform-es2015-block-scoping": "^6.3.13",
"babel-plugin-transform-es2015-classes": "^6.3.15",
"babel-plugin-transform-es2015-modules-commonjs": "^6.3.16",
Expand Down
5 changes: 5 additions & 0 deletions src/node.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export class Node {

append(node) {
this.children.push(node)
this.sort()
}

remove(node) {
Expand All @@ -23,6 +24,10 @@ export class Node {

this.children.splice(position, 1)
}

sort() {
this.children.sort((a, b) => b.priority - a.priority)
}
}

Node.DEFAULT = 0
Expand Down
17 changes: 12 additions & 5 deletions src/tree.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ export class Tree {
const fullPath = path
let node = this.root

node.priority++

node_loop:
while (node) {
path = path.substr(node.path.length)
Expand All @@ -30,8 +32,6 @@ export class Tree {
return this
}

node.priority++

if (node.children.length) {
for (let nodeIndex = 0; nodeIndex < node.children.length; nodeIndex++) {
if ( node.children[nodeIndex].path[0] === path[0] ) {
Expand All @@ -44,30 +44,38 @@ export class Tree {
}
}

// go further down the tree
if (pathCompareIndex >= selectedNode.path.length) {
node.children[nodeIndex].priority++
node.sort()

node = selectedNode
continue node_loop
// we inject a new node, cause the new path is part of this one
} else if (pathCompareIndex >= path.length) {
let newChild = new Node(path, fullPath, data)

selectedNode.path = selectedNode.path.replace(path, '')

node.remove(selectedNode)
node.append(newChild)

newChild.priority = selectedNode.priority + 1
newChild.append(selectedNode)

node.append(newChild)

return this
// we match partly, generate a new edge
} else if (pathCompareIndex > 0) {
let newEdge = new Node(path.substr(0, pathCompareIndex), '', null)

selectedNode.path = selectedNode.path.substr(pathCompareIndex)

newEdge.priority = selectedNode.priority + 1

node.remove(selectedNode)
node.append(newEdge)

newEdge.priority = selectedNode.priority + 1
newEdge.append(selectedNode)

node = newEdge
Expand All @@ -84,7 +92,6 @@ export class Tree {
return this
}


return this
}

Expand Down
44 changes: 32 additions & 12 deletions test/node.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,20 +33,40 @@ describe('Node', function() {
expect(parent.children.length).to.be.equal(1)
})

it.skip('updatePriority should increase priority for every child', function () {
it('appending should order children based by their priority', function () {
let parent = new Node('/parent', '/parent')
let child = new Node('/child', '/parent/child')
let grandChild = new Node('/grandchild', '/parent/child/grandchild')
let child1 = new Node('/child1', '/parent/child1')
let child2 = new Node('/child2', '/parent/child2')

expect(parent.priority).to.be.equal(1)
parent.append(child)
parent.updatePriority()
expect(parent.priority).to.be.equal(1)
child.append(grandChild)
child.updatePriority()
parent.updatePriority()
expect(child.priority).to.be.equal(1)
expect(parent.priority).to.be.equal(2)
child1.priority = 1
child2.priority = 2

parent.append(child1)
parent.append(child2)

expect(parent.children).to.deep.equal([child2, child1])
})

it('sort should order children based by their priority', function () {
let parent = new Node('/parent', '/parent')
let child1 = new Node('/child1', '/parent/child1')
let child2 = new Node('/child2', '/parent/child2')

child1.priority = 1
child2.priority = 1

parent.append(child1)
parent.append(child2)

expect(parent.children).to.deep.equal([child1, child2])

child2.priority = 2

parent.sort()

expect(parent.children).to.deep.equal([child2, child1])
})



})
52 changes: 36 additions & 16 deletions test/tree.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,22 +36,6 @@ describe('Tree', function() {
expect(instance.root.priority).to.be.equal(4)
})

it('should be possible to add new plain entries', function () {
let instance = new Tree()

instance.add('/account')
instance.add('/account/users')
instance.add('/account/users/add')
instance.add('/account/users/change')
instance.add('/account/users/delete')
instance.add('/account/addresses')
instance.add('/account/addresses/add')
instance.add('/account/addresses/change')
instance.add('/account/addresses/delete')

expect(instance.root.priority).to.be.equal(10)
})

it('should be possible to add new plain entries', function () {
let instance = new Tree()

Expand All @@ -69,6 +53,42 @@ describe('Tree', function() {
expect(instance.root.priority).to.be.equal(11)
})

it('the order should be based on the priority', function () {
let instance = new Tree()

instance.add('/path2')
instance.add('/path1')
instance.add('/path1/subpath')

expect(instance.root.priority).to.be.equal(4)
expect(instance.root.children[0].children[0].fullPath).to.be.equal('/path1')
expect(instance.root.children[0].children[1].fullPath).to.be.equal('/path2')
})

it('the order should be based on the priority, even when splitting and adding an edge', function () {
let instance = new Tree()

instance.add('/path2')
instance.add('/path1/subpath')
instance.add('/path1')

expect(instance.root.priority).to.be.equal(4)
expect(instance.root.children[0].children[0].fullPath).to.be.equal('/path1')
expect(instance.root.children[0].children[1].fullPath).to.be.equal('/path2')
})

it('the order should be based on the priority, even when adding a longer path', function () {
let instance = new Tree()

instance.add('/path2')
instance.add('/path1/subpath')

expect(instance.root.priority).to.be.equal(3)
expect(instance.root.children[0].children[0].fullPath).to.be.equal('/path2')
expect(instance.root.children[0].children[1].fullPath).to.be.equal('/path1/subpath')
})


it('should return the node on exact match of the path', function () {
let instance = new Tree()

Expand Down

0 comments on commit 763aec4

Please sign in to comment.