class Eco::API::UseCases::DefaultCases::CsvToTree module NodesCleaner def repeated_tags @repeated_tags ||= [] end def done_tags @done_tags ||= [] end def fill_in_parents(nodes) nodes.tap do |nodes| prev_nodes = Array(1..11).zip(Array.new(11, nil)).to_h nodes.each do |node| if parent_node = prev_nodes[node.raw_level - 1] node.parentId = parent_node.id end prev_nodes[node.raw_level] = node end end end def tidy_nodes(nodes, prev_level: 0, main: true) out = nodes.each_with_object([]) do |node, out| if done_tags.include?(tag = node.tag) repeated_tags << "#{tag} (level: #{node.level})" else level = node.actual_level if level > prev_level + 1 gap = level - (prev_level + 1) puts "(Row: #{node.row_num}) Tag '#{tag}' (lev #{level}) jumps #{gap} level(s) (expected #{prev_level + 1})." #puts " " + node.tags_array.pretty_inspect missing_nodes = node.decouple(gap) puts " Adding missing upper level(s): " + missing_nodes.map(&:raw_tag).pretty_inspect out.push(*tidy_nodes(missing_nodes, prev_level: prev_level, main: false)) # puts node.actual_level # pp node.tags_array level = prev_level + 1 end out << node done_tags << tag prev_level = level end end if main unless repeated_tags.empty? puts "There were #{repeated_tags.length} repeated tags. Only one included. These excluded:" pp repeated_tags end end fill_in_parents(out) end def to_rows(nodes, prev_level: 0, main: true) out = tidy_nodes(nodes).each_with_object([]) do |node, out| tag = node.tag level = node.actual_level out << (row = Array.new(level, nil)) row[-1..-1] = [tag.upcase] prev_level = level end if main # Normalize length max_row = out.max {|a, b| a.length <=> b.length} holder = Array.new(max_row.length, nil) out = out.map do |row| row.dup.concat(holder)[0..max_row.length-1] end end out end end end