Permalink
Browse files

initial commit

  • Loading branch information...
1 parent 2a6cf13 commit adbbfa95df8ccbdda9f22b0cedce2743a5715526 @bobbysmith007 bobbysmith007 committed May 18, 2011
Showing with 778 additions and 0 deletions.
  1. +20 −0 LICENSE
  2. +26 −0 README.mediawiki
  3. +138 −0 examples/examples.lisp
  4. +50 −0 group-by.asd
  5. +357 −0 group-by.lisp
  6. +187 −0 tests/group-by.lisp
View
20 LICENSE
@@ -0,0 +1,20 @@
+;; Copyright (c) 2011 Russ Tyndall , Acceleration.net http://www.acceleration.net
+
+;; Permission is hereby granted, free of charge, to any person obtaining
+;; a copy of this software and associated documentation files (the
+;; "Software"), to deal in the Software without restriction, including
+;; without limitation the rights to use, copy, modify, merge, publish,
+;; distribute, sublicense, and/or sell copies of the Software, and to
+;; permit persons to whom the Software is furnished to do so, subject to
+;; the following conditions:
+
+;; The above copyright notice and this permission notice shall be
+;; included in all copies or substantial portions of the Software.
+
+;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+;; LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+;; OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+;; WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
View
@@ -0,0 +1,26 @@
+= group-by =
+A Common Lisp library to help group data into trees (of various
+formats) based on common/shared values
+
+
+== API ==
+=== group-by ===
+groups the list into an alist using the key function and value function to group by key,
+with a list of all values for that key.
+
+key is used to determine the key in the a-list <br />
+value is used to determin the value in the a-list <br />
+key-fn is passed as the :key to assoc (essentially the key of your key) <br />
+test is passed as the :test to assoc <br />
+
+eg: (group-by '((a 1 2) (a 3 4) (b 5 6)))
+ => ((A (1 2) (3 4)) (B (5 6)))
+
+eg: (group-by '((a 1 2) (a 3 4) (b 5 6)) :value #'identity)
+ => ((A (A 1 2) (A 3 4)) (B (B 5 6)))
+
+
+=== grouped-list ===
+
+== Examples ==
+See the examples file and the tests for running examples
View
@@ -0,0 +1,138 @@
+(in-package :group-by)
+
+(defparameter +example-timeclock-data+
+ `(("russ" 1 :proj-a)
+ ("russ" 2 :proj-a)
+ ("bob" 1 :proj-a)
+ ("russ" 2 :proj-b)
+ ("bob" 1 :proj-b)
+ ("bob" 1 :proj-b)
+ ("russ" 2 :proj-b)
+ ("bob" 1 :proj-c)
+ ("russ" 4 :proj-c)))
+
+(group-by +example-timeclock-data+)
+;; results in
+'(("russ"
+ (1 :proj-a) (2 :proj-a) (2 "time on proj b")
+ (2 "time on proj b") (4 :proj-c))
+ ("bob"
+ (1 :proj-a) (1 "time on proj b") (1 "time on proj b")
+ (1 :proj-c)))
+
+(defparameter +example-multiple-grouped-timeclock-data+
+ (group-by-repeated
+ +example-timeclock-data+
+ :keys (list #'first #'third)
+ :tests (list #'string-equal #'eql)))
+;; results in
+'(("bob"
+ (:proj-c ("bob" 1 :proj-c))
+ (:proj-b ("bob" 1 :proj-b) ("bob" 1 :proj-b))
+ (:proj-a ("bob" 1 :proj-a)))
+ ("russ"
+ (:proj-c ("russ" 4 :proj-c))
+ (:proj-b ("russ" 2 :proj-b) ("russ" 2 :proj-b))
+ (:proj-a ("russ" 2 :proj-a) ("russ" 1 :proj-a))))
+
+(defparameter +example-grouped-list-timeclock-data-alist+
+ (make-grouped-list
+ +example-timeclock-data+
+ :keys (list #'first #'third)
+ :tests (list #'string-equal #'eql)))
+
+(defclass example-timeclock-record ()
+ ((name :accessor name :initarg :name :initform nil)
+ (hours :accessor hours :initarg :hours :initform 0)
+ (proj :accessor proj :initarg :proj :initform nil)))
+
+(defun example-tcr (name hours proj)
+ (make-instance 'example-timeclock-record :name name :hours hours :proj proj))
+
+(defparameter +example-timeclock-objs+
+ (iter top (for i from 0 to 10)
+ (iter (for rec in +example-timeclock-data+)
+ (in top (collect (apply #'example-tcr rec))))))
+
+(defun print-timeclock-report ()
+ (labels ((print-results (gl &optional (spaces ""))
+ (let ((further-groups (child-groupings gl)))
+ (if further-groups
+ (iter
+ (with hours = 0)
+ (for group in further-groups)
+ (format T "~?~A~%" spaces () (key-value group) )
+ (incf hours (print-results group (concatenate 'string spaces "~2,1@T")))
+ (finally
+ (format T "~?Total: ~D~%" spaces () hours )
+ (return hours)))
+ (iter (for kid in (items-in-group gl))
+ (sum (hours kid) into hours)
+ (finally
+ (format T "~?Total: ~D~%" spaces () hours )
+ (return hours)))))))
+
+ (let ((by-person-project
+ (make-grouped-list
+ +example-timeclock-objs+
+ :keys (list #'name #'proj)
+ :tests (list #'string-equal #'eql)
+ :grouping-implementation :hash-table))
+ (by-project-person
+ (make-grouped-list
+ +example-timeclock-objs+
+ :keys (list #'proj #'name)
+ :tests (list #'eql #'string-equal)
+ :grouping-implementation :tree)))
+
+ (format T "Hours BY Project > Person~%-----------~%")
+ (print-results by-project-person)
+ (format T "~%~%Hours BY Person > Project~%-----------~%")
+ (print-results by-person-project)
+ )))
+
+#|
+Hours BY Project > Person
+-----------
+PROJ-C
+ russ
+ Total: 44
+ bob
+ Total: 11
+ Total: 55
+PROJ-B
+ bob
+ Total: 22
+ russ
+ Total: 44
+ Total: 66
+PROJ-A
+ bob
+ Total: 11
+ russ
+ Total: 33
+ Total: 44
+Total: 165
+
+
+Hours BY Person > Project
+-----------
+russ
+ PROJ-A
+ Total: 33
+ PROJ-B
+ Total: 44
+ PROJ-C
+ Total: 44
+ Total: 121
+bob
+ PROJ-A
+ Total: 11
+ PROJ-B
+ Total: 22
+ PROJ-C
+ Total: 11
+ Total: 44
+Total: 165
+|#
+
View
@@ -0,0 +1,50 @@
+;; -*- lisp -*-
+
+(eval-when (:compile-toplevel :load-toplevel :execute)
+ (unless (find-package :group-by.system)
+ (defpackage :group-by.system
+ (:use :common-lisp :asdf))))
+
+(in-package group-by.system)
+
+(defsystem :group-by
+ :description "A Common Lisp library to help group data into trees (of various
+formats) based on common/shared values"
+ :licence "BSD"
+ :version "0.1"
+ :components ((:file "group-by"))
+ :depends-on (:iterate :alexandria))
+
+(defsystem :group-by-test
+ :description "A Common Lisp library to help group data into trees (of various
+formats) based on common/shared values"
+ :licence "BSD"
+ :version "0.1"
+ :components ((:module :tests
+ :serial t
+ :components ((:file "group-by"))))
+ :depends-on (:group-by :lisp-unit))
+
+(defmethod asdf:perform ((o asdf:test-op) (c (eql (find-system :group-by))))
+ (asdf:oos 'asdf:load-op :group-by-test))
+
+;; Copyright (c) 2011 Russ Tyndall , Acceleration.net http://www.acceleration.net
+
+;; Permission is hereby granted, free of charge, to any person obtaining
+;; a copy of this software and associated documentation files (the
+;; "Software"), to deal in the Software without restriction, including
+;; without limitation the rights to use, copy, modify, merge, publish,
+;; distribute, sublicense, and/or sell copies of the Software, and to
+;; permit persons to whom the Software is furnished to do so, subject to
+;; the following conditions:
+
+;; The above copyright notice and this permission notice shall be
+;; included in all copies or substantial portions of the Software.
+
+;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+;; LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+;; OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+;; WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Oops, something went wrong.

0 comments on commit adbbfa9

Please sign in to comment.