cvsuser 02/04/09 13:00:35
Modified: P5EEx/Blue/P5EEx/Blue Repository.pm
Log:
added core sorting and grouping support for physical repositories which don't
support it natively
Revision Changes Path
1.12 +211 -1 p5ee/P5EEx/Blue/P5EEx/Blue/Repository.pm
Index: Repository.pm
===================================================================
RCS file: /cvs/public/p5ee/P5EEx/Blue/P5EEx/Blue/Repository.pm,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -w -r1.11 -r1.12
--- Repository.pm 5 Apr 2002 22:00:12 -0000 1.11
+++ Repository.pm 9 Apr 2002 20:00:34 -0000 1.12
@@ -1,6 +1,6 @@
#############################################################################
-## $Id: Repository.pm,v 1.11 2002/04/05 22:00:12 spadkins Exp $
+## $Id: Repository.pm,v 1.12 2002/04/09 20:00:34 spadkins Exp $
#############################################################################
package P5EEx::Blue::Repository;
@@ -2133,6 +2133,162 @@
=cut
#############################################################################
+# summarize()
+#############################################################################
+
+=head2 summarize()
+
+ * Signature: $summarized_rows = $rep->summarize($rows, $columns, $summcolidx,
$formulas);
+ * Param: $rows [][]
+ * Param: $columns []
+ * Param: $summcolidx []
+ * Param: $formulas {}
+ * Return: $summarized_rows []
+ * Throws: P5EEx::Blue::Exception::Repository
+ * Since: 0.01
+
+ Sample Usage:
+
+ @rows = (
+ [ 5, "Jim", "Green", 13.5, 320, ],
+ [ 3, "Bob", "Green", 4.2, 230, ],
+ [ 9, "Ken", "Green", 27.4, 170, ],
+ [ 2, "Kim", "Blue", 11.7, 440, ],
+ [ 7, "Jan", "Blue", 55.1, 90, ],
+ [ 1, "Ben", "Blue", 22.6, 195, ],
+ );
+ @columns = ( "id", "name", "team", "rating", "score" );
+ @summcolidx = ( 2 ); # "team"
+ %formulas = (
+ rating => "{sum(rating)}/{count(rating)}",
+ );
+
+ $summarized_rows = $rep->summarize(\@rows, \@columns, \@summcolidx, \%formulas);
+
+=cut
+
+sub summarize {
+ my ($self, $rows, $columns, $summcolidx, $formulas) = @_;
+
+ my (@summary_rows, $summary_row, $create_summary);
+ my ($key, $nextkey, $row, $rowidx, $colidx, $numcols, $column, $elem);
+ my (%total, $formula);
+
+ $numcols = $#$columns + 1;
+
+ for ($rowidx = 0; $rowidx <= $#$rows; $rowidx++) {
+ $row = $rows->[$rowidx];
+
+ $key = "Total";
+ $key = join(",", @{$row->[$rowidx]}[@$summcolidx])
+ if (defined $summcolidx);
+
+ # accumulate totals
+ for ($colidx = 0; $colidx < $numcols; $colidx++) {
+ $column = $columns->[$colidx];
+ $elem = $rows->[$rowidx][$colidx];
+ if (defined $elem && $elem ne "") {
+ if (defined $total{$column}) {
+ $total{"sum($column)"} += ($elem+0);
+ }
+ else {
+ $total{"sum($column)"} = ($elem+0);
+ }
+ $total{"$column"} = $elem;
+ }
+ }
+ if (defined $total{"count(*)"}) {
+ $total{"count(*)"} ++;
+ }
+ else {
+ $total{"count(*)"} = 1;
+ }
+
+ # look ahead to see if we need to produce a summary row yet
+ $create_summary = 0;
+ if ($rowidx == $#$rows) {
+ $create_summary = 1;
+ }
+ else {
+ $nextkey = "Total";
+ $nextkey = join(",", @{$rows->[$rowidx+1]}[@$summcolidx])
+ if (defined $summcolidx);
+ $create_summary = 1 if ($nextkey ne $key);
+ }
+
+ if ($create_summary) {
+
+ $summary_row = [];
+
+ for ($colidx = 0; $colidx < $numcols; $colidx++) {
+ $column = $columns->[$colidx];
+ $formula = $formulas->{$column};
+
+ $elem = "";
+ if (defined $formula) { # match {
+ $formula =~ s/\{([^\}]+)\}/\$total{"$1"}/g;
+ $formula = "\$elem = $formula;";
+ eval $formula;
+ #$elem = "[$formula] $@" if ($@);
+ }
+ else {
+ $elem = $total{"sum($column)"};
+ }
+ }
+
+ push (@summary_rows, $summary_row);
+ }
+ }
+ \@summary_rows;
+}
+
+#############################################################################
+# sort()
+#############################################################################
+
+=head2 sort()
+
+ * Signature: $sorted_rows = $rep->sort($rows, $sortcolidx);
+ * Signature: $sorted_rows = $rep->sort($rows, $sortcolidx, $sorttype);
+ * Signature: $sorted_rows = $rep->sort($rows, $sortcolidx, $sorttype, $sortdir);
+ * Param: $rows [][]
+ * Param: $sortcolidx []
+ * Param: $sorttype []
+ * Param: $sortdir []
+ * Return: $sorted_rows []
+ * Throws: P5EEx::Blue::Exception::Repository
+ * Since: 0.01
+
+ Sample Usage:
+
+ @rows = (
+ [ 5, "Jim", "Green", 13.5, 320, ],
+ [ 3, "Bob", "Green", 4.2, 230, ],
+ [ 9, "Ken", "Green", 27.4, 170, ],
+ [ 2, "Kim", "Blue", 11.7, 440, ],
+ [ 7, "Jan", "Blue", 55.1, 90, ],
+ [ 1, "Ben", "Blue", 22.6, 195, ],
+ );
+ # @columns = ( "id", "name", "team", "rating", "score" ); # not needed
+ @sortcolidx = ( 2, 4 ); # "team", "score" (descending)
+ @sorttype = ( "C", "N" ); # Character, Numeric
+ @sortdir = ( "UP", "DOWN" );
+
+ $sorted_rows = $rep->sort(\@rows, \@sortcolidx, \@sorttype, \@sortdir);
+
+=cut
+
+sub sort {
+ my ($self, $rows, $sortcolidx, $sorttype, $sortdir) = @_;
+
+ @P5EEx::Blue::Repository::sort_keys = @$sortcolidx;
+ @P5EEx::Blue::Repository::sort_types = ($sorttype ? @$sorttype : ());
+ @P5EEx::Blue::Repository::sort_dirs = ($sortdir ? @$sortdir : ());
+
+ return [ sort rows_by_indexed_values @$rows ];
+}
+
+#############################################################################
# serial()
#############################################################################
@@ -2533,6 +2689,60 @@
=cut
sub service_type () { 'Repository'; }
+
+#############################################################################
+# rows_by_indexed_values()
+#############################################################################
+
+=head2 rows_by_indexed_values()
+
+ * Signature: &P5EEx::Blue::Repository::rows_by_indexed_values($a,$b);
+ * Param: $a []
+ * Param: $b []
+ * Return: void
+ * Throws: P5EEx::Blue::Exception::Repository
+ * Since: 0.01
+
+ Sample Usage:
+
+ @data = (
+ [ 5, "Jim", "Red", 13.5, ],
+ [ 3, "Bob", "Green", 4.2, ],
+ [ 9, "Ken", "Blue", 27.4, ],
+ [ 2, "Kim", "Yellow", 11.7, ],
+ [ 7, "Jan", "Purple", 55.1, ],
+ );
+
+ @P5EEx::Blue::Repository::sort_keys = ( 1, 3, 2 );
+ @P5EEx::Blue::Repository::sort_types = ("C", "N", "C");
+ @P5EEx::Blue::Repository::sort_dirs = ("UP", "DOWN", "DOWN");
+
+ @sorted_data = sort rows_by_indexed_values @data;
+
+The rows_by_indexed_values() function is used to sort rows of data
+based on indexes, data types, and directions.
+
+=cut
+
+sub rows_by_indexed_values {
+ my ($pos, $key, $type, $dir, $sign);
+ for ($pos = 0; $pos <= $#P5EEx::Blue::Repository::sort_keys; $pos++) {
+ $key = $P5EEx::Blue::Repository::sort_keys[$pos];
+ $type = $P5EEx::Blue::Repository::sort_types[$pos];
+ $dir = $P5EEx::Blue::Repository::sort_dirs[$pos];
+ if (defined $type && $type eq "N") {
+ $sign = ($a->[$key] <=> $b->[$key]);
+ }
+ else {
+ $sign = ($a->[$key] cmp $b->[$key]);
+ }
+ if ($sign) {
+ $sign = -$sign if (defined $dir && $dir eq "DOWN");
+ return ($sign);
+ }
+ }
+ return 0;
+}
#############################################################################
# DESTROY()