module Underpass
class WayChain
MERGE_STRATEGIES = [
->(cur, seq) { cur.last == seq.first ? cur + seq[1..] : nil },
->(cur, seq) { cur.last == seq.last ? cur + seq.reverse[1..] : nil },
->(cur, seq) { cur.first == seq.last ? seq + cur[1..] : nil },
->(cur, seq) { cur.first == seq.first ? seq.reverse + cur[1..] : nil }
].freeze
def initialize(way_ids, ways)
@sequences = way_ids.filter_map do |way_id|
way = ways[way_id]
next unless way
way[:nodes].dup
end
end
def merged_sequences
return @sequences if @sequences.empty?
remaining = @sequences.dup
current = remaining.shift
current, remaining = merge_all(current, remaining)
[current, *remaining]
end
private
def merge_all(current, remaining)
until remaining.empty?
found = find_connection(current, remaining)
break unless found
remaining.delete(found[:seq])
current = found[:merged]
end
[current, remaining]
end
def find_connection(current, sequences)
sequences.each do |seq|
merged = try_merge(current, seq)
return { seq: seq, merged: merged } if merged
end
nil
end
def try_merge(current, seq)
MERGE_STRATEGIES.each do |strategy|
result = strategy.call(current, seq)
return result if result
end
nil
end
end
end