Loading lib/jsduck/categories.rb +5 −43 Original line number Diff line number Diff line Loading @@ -2,6 +2,7 @@ require 'jsduck/logger' require 'jsduck/file_categories' require 'jsduck/auto_categories' require 'jsduck/categories_class_name' require 'jsduck/columns' module JsDuck Loading @@ -19,6 +20,7 @@ module JsDuck def initialize(categories, doc_formatter, relations={}) @categories = categories @class_name = CategoriesClassName.new(doc_formatter, relations) @columns = Columns.new("classes") end # Returns HTML listing of classes divided into categories Loading @@ -40,10 +42,12 @@ module JsDuck EOHTML end private def render_columns(groups) align = ["left-column", "middle-column", "right-column"] i = -1 return split(groups, 3).map do |col| return @columns.split(groups, 3).map do |col| i += 1 [ "<div class='#{align[i]}'>", Loading @@ -64,48 +68,6 @@ module JsDuck end end # Splits the array of items into n chunks so that the sum of # largest chunk is as small as possible. # # This is a brute-force implementation - we just try all the # combinations and choose the best one. def split(items, n) if n == 1 [items] elsif items.length <= n Array.new(n) {|i| items[i] ? [items[i]] : [] } else min_max = nil min_arr = nil i = 0 while i <= items.length-n i += 1 # Try placing 1, 2, 3, ... items to first chunk. # Calculate the remaining chunks recursively. cols = [items[0,i]] + split(items[i, items.length], n-1) max = max_sum(cols) # Is this the optimal solution so far? Remember it. if !min_max || max < min_max min_max = max min_arr = cols end end min_arr end end def max_sum(cols) cols.map {|col| sum(col) }.max end # Finds the total size of items in array # # The size of one item is it's number of classes + the space for header def sum(arr) header_size = 3 arr.reduce(0) {|sum, item| sum + item["classes"].length + header_size } end end end lib/jsduck/columns.rb 0 → 100644 +56 −0 Original line number Diff line number Diff line module JsDuck # Splits array of items with subitems into roughly equal size groups. class Columns # Initialized with the name of subitems field. def initialize(subitems_field) @header_size = 3 @subitems_field = subitems_field end # Splits the array of items into n chunks so that the sum of # largest chunk is as small as possible. # # This is a brute-force implementation - we just try all the # combinations and choose the best one. def split(items, n) if n == 1 [items] elsif items.length <= n Array.new(n) {|i| items[i] ? [items[i]] : [] } else min_max = nil min_arr = nil i = 0 while i <= items.length-n i += 1 # Try placing 1, 2, 3, ... items to first chunk. # Calculate the remaining chunks recursively. cols = [items[0,i]] + split(items[i, items.length], n-1) max = max_sum(cols) # Is this the optimal solution so far? Remember it. if !min_max || max < min_max min_max = max min_arr = cols end end min_arr end end private def max_sum(cols) cols.map {|col| sum(col) }.max end # Finds the total size of items in array # # The size of one item is it's number of classes + the space for header def sum(arr) arr.reduce(0) {|sum, item| sum + item[@subitems_field].length + @header_size } end end end spec/categories_spec.rb→spec/columns_spec.rb +11 −11 Original line number Diff line number Diff line require "jsduck/categories" require "jsduck/columns" describe JsDuck::Categories do describe JsDuck::Columns do # Small helper to check the sums def sum(arr) Loading @@ -9,7 +9,7 @@ describe JsDuck::Categories do # Replace the sum method with the one that simply sums the numbers, # so we can use simpler test-data. class JsDuck::Categories class JsDuck::Columns def sum(arr) arr.reduce(0) {|sum,x| sum + x } end Loading @@ -17,30 +17,30 @@ describe JsDuck::Categories do describe "#split" do before do @categories = JsDuck::Categories.new([], {}, {}) @columns = JsDuck::Columns.new("classes") end it "split(1 item by 1)" do @cols = @categories.split([2], 1) @cols = @columns.split([2], 1) @cols.length.should == 1 sum(@cols[0]).should == 2 end it "split(3 items by 1)" do @cols = @categories.split([1, 2, 3], 1) @cols = @columns.split([1, 2, 3], 1) @cols.length.should == 1 sum(@cols[0]).should == 6 end it "split(3 items to two equal-height columns)" do @cols = @categories.split([1, 2, 3], 2) @cols = @columns.split([1, 2, 3], 2) @cols.length.should == 2 sum(@cols[0]).should == 3 sum(@cols[1]).should == 3 end it "split(1 item by 3)" do @cols = @categories.split([2], 3) @cols = @columns.split([2], 3) @cols.length.should == 3 sum(@cols[0]).should == 2 sum(@cols[1]).should == 0 Loading @@ -48,7 +48,7 @@ describe JsDuck::Categories do end it "split(3 items by 3)" do @cols = @categories.split([1, 2, 3], 3) @cols = @columns.split([1, 2, 3], 3) @cols.length.should == 3 sum(@cols[0]).should == 1 sum(@cols[1]).should == 2 Loading @@ -56,7 +56,7 @@ describe JsDuck::Categories do end it "split(6 items by 3)" do @cols = @categories.split([5, 8, 4, 2, 1, 3], 3) @cols = @columns.split([5, 8, 4, 2, 1, 3], 3) @cols.length.should == 3 sum(@cols[0]).should <= 10 sum(@cols[1]).should <= 10 Loading @@ -64,7 +64,7 @@ describe JsDuck::Categories do end it "split(8 items by 3)" do @cols = @categories.split([1, 3, 5, 2, 1, 4, 2, 3], 3) @cols = @columns.split([1, 3, 5, 2, 1, 4, 2, 3], 3) @cols.length.should == 3 sum(@cols[0]).should <= 9 sum(@cols[1]).should <= 9 Loading Loading
lib/jsduck/categories.rb +5 −43 Original line number Diff line number Diff line Loading @@ -2,6 +2,7 @@ require 'jsduck/logger' require 'jsduck/file_categories' require 'jsduck/auto_categories' require 'jsduck/categories_class_name' require 'jsduck/columns' module JsDuck Loading @@ -19,6 +20,7 @@ module JsDuck def initialize(categories, doc_formatter, relations={}) @categories = categories @class_name = CategoriesClassName.new(doc_formatter, relations) @columns = Columns.new("classes") end # Returns HTML listing of classes divided into categories Loading @@ -40,10 +42,12 @@ module JsDuck EOHTML end private def render_columns(groups) align = ["left-column", "middle-column", "right-column"] i = -1 return split(groups, 3).map do |col| return @columns.split(groups, 3).map do |col| i += 1 [ "<div class='#{align[i]}'>", Loading @@ -64,48 +68,6 @@ module JsDuck end end # Splits the array of items into n chunks so that the sum of # largest chunk is as small as possible. # # This is a brute-force implementation - we just try all the # combinations and choose the best one. def split(items, n) if n == 1 [items] elsif items.length <= n Array.new(n) {|i| items[i] ? [items[i]] : [] } else min_max = nil min_arr = nil i = 0 while i <= items.length-n i += 1 # Try placing 1, 2, 3, ... items to first chunk. # Calculate the remaining chunks recursively. cols = [items[0,i]] + split(items[i, items.length], n-1) max = max_sum(cols) # Is this the optimal solution so far? Remember it. if !min_max || max < min_max min_max = max min_arr = cols end end min_arr end end def max_sum(cols) cols.map {|col| sum(col) }.max end # Finds the total size of items in array # # The size of one item is it's number of classes + the space for header def sum(arr) header_size = 3 arr.reduce(0) {|sum, item| sum + item["classes"].length + header_size } end end end
lib/jsduck/columns.rb 0 → 100644 +56 −0 Original line number Diff line number Diff line module JsDuck # Splits array of items with subitems into roughly equal size groups. class Columns # Initialized with the name of subitems field. def initialize(subitems_field) @header_size = 3 @subitems_field = subitems_field end # Splits the array of items into n chunks so that the sum of # largest chunk is as small as possible. # # This is a brute-force implementation - we just try all the # combinations and choose the best one. def split(items, n) if n == 1 [items] elsif items.length <= n Array.new(n) {|i| items[i] ? [items[i]] : [] } else min_max = nil min_arr = nil i = 0 while i <= items.length-n i += 1 # Try placing 1, 2, 3, ... items to first chunk. # Calculate the remaining chunks recursively. cols = [items[0,i]] + split(items[i, items.length], n-1) max = max_sum(cols) # Is this the optimal solution so far? Remember it. if !min_max || max < min_max min_max = max min_arr = cols end end min_arr end end private def max_sum(cols) cols.map {|col| sum(col) }.max end # Finds the total size of items in array # # The size of one item is it's number of classes + the space for header def sum(arr) arr.reduce(0) {|sum, item| sum + item[@subitems_field].length + @header_size } end end end
spec/categories_spec.rb→spec/columns_spec.rb +11 −11 Original line number Diff line number Diff line require "jsduck/categories" require "jsduck/columns" describe JsDuck::Categories do describe JsDuck::Columns do # Small helper to check the sums def sum(arr) Loading @@ -9,7 +9,7 @@ describe JsDuck::Categories do # Replace the sum method with the one that simply sums the numbers, # so we can use simpler test-data. class JsDuck::Categories class JsDuck::Columns def sum(arr) arr.reduce(0) {|sum,x| sum + x } end Loading @@ -17,30 +17,30 @@ describe JsDuck::Categories do describe "#split" do before do @categories = JsDuck::Categories.new([], {}, {}) @columns = JsDuck::Columns.new("classes") end it "split(1 item by 1)" do @cols = @categories.split([2], 1) @cols = @columns.split([2], 1) @cols.length.should == 1 sum(@cols[0]).should == 2 end it "split(3 items by 1)" do @cols = @categories.split([1, 2, 3], 1) @cols = @columns.split([1, 2, 3], 1) @cols.length.should == 1 sum(@cols[0]).should == 6 end it "split(3 items to two equal-height columns)" do @cols = @categories.split([1, 2, 3], 2) @cols = @columns.split([1, 2, 3], 2) @cols.length.should == 2 sum(@cols[0]).should == 3 sum(@cols[1]).should == 3 end it "split(1 item by 3)" do @cols = @categories.split([2], 3) @cols = @columns.split([2], 3) @cols.length.should == 3 sum(@cols[0]).should == 2 sum(@cols[1]).should == 0 Loading @@ -48,7 +48,7 @@ describe JsDuck::Categories do end it "split(3 items by 3)" do @cols = @categories.split([1, 2, 3], 3) @cols = @columns.split([1, 2, 3], 3) @cols.length.should == 3 sum(@cols[0]).should == 1 sum(@cols[1]).should == 2 Loading @@ -56,7 +56,7 @@ describe JsDuck::Categories do end it "split(6 items by 3)" do @cols = @categories.split([5, 8, 4, 2, 1, 3], 3) @cols = @columns.split([5, 8, 4, 2, 1, 3], 3) @cols.length.should == 3 sum(@cols[0]).should <= 10 sum(@cols[1]).should <= 10 Loading @@ -64,7 +64,7 @@ describe JsDuck::Categories do end it "split(8 items by 3)" do @cols = @categories.split([1, 3, 5, 2, 1, 4, 2, 3], 3) @cols = @columns.split([1, 3, 5, 2, 1, 4, 2, 3], 3) @cols.length.should == 3 sum(@cols[0]).should <= 9 sum(@cols[1]).should <= 9 Loading