From e5c1f3e3da086391b8e5b3dce77ef15fa7e6bd6f Mon Sep 17 00:00:00 2001 From: rkh Date: Thu, 10 Jun 2010 12:19:21 +0000 Subject: [PATCH] table datastructure now creates gaps git-svn-id: https://dev.finn.de/svn/cockpit/branches/reporting_merge@1193 7926756e-e54e-46e6-9721-ed318f58905e --- app/models/cost_query/table.rb | 85 ++++++++++++++++++++++++++++++---- init.rb | 4 ++ 2 files changed, 80 insertions(+), 9 deletions(-) diff --git a/app/models/cost_query/table.rb b/app/models/cost_query/table.rb index fc51b1323d..ece7ecc211 100644 --- a/app/models/cost_query/table.rb +++ b/app/models/cost_query/table.rb @@ -1,8 +1,9 @@ # encoding: UTF-8 +require 'enumerator' ## # @example -# CostQuery::Table.new query, :rows => [:project_id, :user_id], :columns => [:spent_on, :tweak] +# CostQuery::Table.new query, :rows => [:project_id, :user_id], :columns => [:tweak, :spent_on] class CostQuery::Table attr_accessor :query @@ -14,16 +15,82 @@ class CostQuery::Table end end - def rows(*rows) - return @rows if rows.empty? - @rows = rows + def row_index + get_index :row end - def columns(*rows) - return @rows if rows.empty? - @rows = rows + def column_index + get_index :column + end + + def row_fields + fields_for :row + end + + def column_fields + fields_for :column + end + + def rows_for(result) fields_for result, :row end + def columns_for(result) fields_for result, :column end + + def fields_from(result, type) + fields_for(type).map { |k| result[k] } + end + + ## + # @param [Array] expected Fields expected + # @param [Array,Hash,Resul] given Fields/result to be tested + # @return [TrueClass,FalseClass] + def satisfies?(type, expected, given) + given = fields_from(result, type) if given.respond_to? :to_hash + zipped = expected.zip given + zipped.all? { |a,b| a == b or b.nil? } + end + + def fields_for(type) + @fields_for ||= begin + child, fields = query.chain, Hash.new { |h,k| h[k] = [] } + fields[child.type].push(*child.group_fields) until child.filter? + end + @fields_for[type] + end + + def get_row(*args) + @query.each_row { |result| return with_gaps_for(type, result) if satisfies? :row, args, result } + [] + end + + def with_gaps_for(type, result) + return enum_for(:with_gaps_for, type, result) unless block_given? + stack = get_index(type).dup + result.each do |subresult| + yield nil until satisfies? type, stack.shift, subresult + yield subresult + end + end + + def [](x,y) + get_row(row_index[y]).first(x).last + end + + def all_types(&block) + return [:row, :column] unless block + all_types.each(&block) + end + + def get_index(type) + @indexes ||= begin + indexes = Hash.new(&method(:compare_fields)) + query.each_direct_result { |result| all_types { |t| indexes[t] = fields_from result, t } + indexes.keys.each { |k| indexes[k] = indexes[k].to_a.uniq } + end + @indexes[type] + end + + def compare_fields(a, b) + a.zip(b).each { |x,y| return x > y unless x == y } + true end - def rows_for(result) rows.map { |k| result[k] } end - def columns_for(result) columns.map { |k| result[k] } end end diff --git a/init.rb b/init.rb index 9cbe98b0d2..86b0d1f282 100644 --- a/init.rb +++ b/init.rb @@ -2,6 +2,10 @@ require 'redmine' fail "upgrade ruby version, ruby < 1.8.7 suffers from Hash#hash bug" if {:a => 10}.hash != {:a => 10}.hash +Rails.configuration.after_initialize do + Rails.configuration.gem 'algorithms' +end + Redmine::Plugin.register :redmine_reporting do name 'Reporting Plugin' author 'Konstantin Haase, Philipp Tessenow @ finnlabs'