Skip to content

Commit

Permalink
Add custom comparator to path tree, test and fix.
Browse files Browse the repository at this point in the history
  • Loading branch information
Darrick Wiebe committed Oct 1, 2012
1 parent 16c5930 commit 921be8a
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 13 deletions.
36 changes: 23 additions & 13 deletions lib/pacer/transform/path_tree.rb
Expand Up @@ -10,39 +10,43 @@ module PathRoute
# -- becomes --
# [a [b [c]
# [d]]
# [e [f
# g]]]
def tree
wrapped.chain_route transform: :path_tree, element_type: :object
# [e [f]
# [g]]]

# The default comparator block is { |prev, current| prev == current }
def tree(&block)
wrapped.chain_route transform: :path_tree, element_type: :object, compare: block
end
end
end
end

module Transform
module PathTree
attr_accessor :compare

protected

def attach_pipe(end_pipe)
pipe = PathTreePipe.new
pipe = PathTreePipe.new compare
pipe.setStarts end_pipe
pipe
end


class PathTreePipe < Pacer::Pipes::RubyPipe
def initialize
super
def initialize(compare = nil)
super()
self.building_path = nil
self.prev_path = nil
self.compare = compare || proc { |a, b| a == b }
end

# NOTE: doesn't handle variable length paths yet...
def processNextStart()
while true
path = starts.next
if building_path
if path.first == building_path.first
if compare.call path.first, building_path.first
add_path path
else
return next_path(path)
Expand All @@ -63,18 +67,24 @@ def processNextStart()

private

attr_accessor :building_path, :prev_path
attr_accessor :building_path, :prev_path, :compare

def make(path)
path.reverse.inject(nil) { |inner, e| [e, inner].compact }
path.reverse.inject(nil) do |inner, e|
if inner
[e, inner]
else
[e]
end
end
end

def add_path(path)
working = building_path
(1..path.length).each do |pos|
(1..path.length - 1).each do |pos|
current = path[pos]
prev = prev_path[pos]
if current == prev
if compare.call current, prev
working = working.last
else
if pos < path.length
Expand Down
97 changes: 97 additions & 0 deletions spec/pacer/transform/path_tree_spec.rb
@@ -0,0 +1,97 @@
require 'spec_helper'

Run.tg :read_only do
use_pacer_graphml_data :read_only

describe Pacer::Transform::PathTree do
let(:first) do
graph.v(type: 'person').payload do |p|
{ pos: 'first',
type: p[:type],
name: p[:name] }
end.lookahead { |v| v.out_e.in_v(type: 'project') }
end
let(:second) do
first.out_e.in_v(type: 'project').payload do |prj|
{ pos: 'second',
type: 'project',
name: prj[:name] }
end
end
let(:paths) { second.paths }
let(:payloads) { paths.payloads }
let(:compacted) { payloads.compact_paths }

describe 'basic paths' do
subject { paths }

its(:count) { should == 4 }

it 'should have 3 elements' do
paths.each { |x| x.length.should == 3 }
end
end

describe 'tree of paths' do
subject { paths.tree }

its(:count) { should == first.count }
its(:first) { should be_a Array }

it 'should be a tree' do
(pangloss, wrote, pacer), (a2, e2, b2), (_, e3, b3), (_, e4, b4) = paths.to_a
subject.to_a.should == [
[pangloss, [wrote, [pacer]]],
[a2, [e2, [b2]],
[e3, [b3]],
[e4, [b4]]]
]
end
end

describe 'tree of payloads' do
subject { payloads.tree }

its(:count) { should == first.count }
its(:first) { should be_a Array }

it 'should be a tree' do
(pangloss, wrote, pacer), (a2, _, b2), (_, _, b3), (_, _, b4) = payloads.to_a
subject.to_a.should == [
[pangloss, [wrote, [pacer]]],
[a2, [nil, [b2],
[b3],
[b4]]]
]
end
end

describe 'tree of compacted payloads' do
subject { compacted.tree }

its(:count) { should == first.count }
its(:first) { should be_a Array }

it 'should be a tree' do
(pangloss, pacer), (a2, b2), (_, b3), (_, b4) = compacted.to_a
subject.to_a.should == [
[pangloss, [pacer]],
[a2, [b2],
[b3],
[b4]]
]
end
end

describe 'tree of compacted payloads by type' do
subject { compacted.tree { |a, b| a[:type] == b[:type] } }

it 'should be a tree, taking the first match' do
pangloss, pacer = compacted.first
subject.to_a.should == [
[pangloss, [pacer]]
]
end
end
end
end

0 comments on commit 921be8a

Please sign in to comment.