1 (in-package #:metatilities)
7 (defclass* delicious-post ()
8 ((post-time nil ia :initarg :time)
9 (tags nil ia :initarg :tag)
13 (post-href nil ia :initarg :href)))
15 ;;; ---------------------------------------------------------------------------
17 (defmethod initialize-instance :after ((object delicious-post) &key)
18 (setf (tags object) (make-tags-canonical (tags object))))
20 ;;; ---------------------------------------------------------------------------
22 (defgeneric make-tags-canonical (tags)
23 (:documentation "Help convert del.icio.us tags into a canonicl form."))
25 ;;; ---------------------------------------------------------------------------
27 (defgeneric make-tag-canonical (tag)
28 (:documentation "Help convert del.icio.us tags into a canonicl form."))
30 ;;; ---------------------------------------------------------------------------
32 (defmethod make-tags-canonical ((tags list))
33 (mapcar #'make-tag-canonical tags))
35 ;;; ---------------------------------------------------------------------------
37 (defmethod make-tags-canonical ((tags string))
38 (make-tags-canonical (tokenize-string tags :delimiter #\ )))
40 ;;; ---------------------------------------------------------------------------
42 (defmethod make-tag-canonical ((tag symbol))
45 ;;; ---------------------------------------------------------------------------
47 (defmethod make-tag-canonical ((tag string))
48 (form-keyword (string-upcase tag)))
50 ;;; ---------------------------------------------------------------------------
52 (defun determine-tag-counts (delicious-post-file)
53 "Returns a list of tags and their counts from a delicious-post-file."
54 (bind ((posts (xmls::parse delicious-post-file))
55 (tags (collect-elements
56 ;; the first two elements of posts aren't tags
60 (let ((tags (find "tag" (second post-info)
64 (tokenize-string (second tags) :delimiter #\ )))))))
72 ;; this is what a post looks like after it's been transformed by xmls
74 (("time" "2005-11-21T15:25:47Z")
75 ("tag" "yoga health exercise amherst")
76 ("hash" "9aad47baf972813c8202b43a56e95a61")
77 ("description" "Yoga Center Amherst, Massachusetts")
78 ("href" "http://www.yogacenteramherst.com/")))
80 (defun parse-delicious-posts (delicious-post-file)
81 "Transform a delicious post file into a list of post objects."
83 (cddr (xmls::parse delicious-post-file))
86 (apply #'make-instance
88 (loop for (name value) in (second post-info) nconc
89 (list (form-keyword (string-upcase name)) value))))))
91 ;;; ---------------------------------------------------------------------------
93 (defun create-bipartite-tag/post-graph (delicious-post-file)
94 "Creates a bipartite graph of tags, posts and the links between them from
95 a delicious post file."
96 (bind ((posts (parse-delicious-posts delicious-post-file))
97 (g (cl-graph:make-graph 'cl-graph:graph-container)))
104 (cl-graph:add-edge-between-vertexes g post tag)))))
107 ;;; ---------------------------------------------------------------------------
112 (cl-graph:project-bipartite-graph
113 (cl-graph:make-graph 'cl-graph:graph-container
114 :default-edge-class 'cl-graph:weighted-edge)
115 (create-bipartite-tag/post-graph #P"user-home:temporary;all-posts.xml")
117 (compose 'type-of 'element))
118 "user-home:temporary;all-tags.dot"
119 :vertex-labeler (lambda (vertex stream)
120 (format stream "~(~A~)" (symbol-name (element vertex))))
121 :edge-formatter (lambda (edge stream)
122 (format stream "weight=~D" (cl-graph:weight edge))))
124 ;;; ---------------------------------------------------------------------------
128 (cl-graph:make-filtered-graph
129 (cl-graph:project-bipartite-graph
130 (cl-graph:make-graph 'cl-graph:graph-container
131 :default-edge-class 'cl-graph:weighted-edge)
132 (create-bipartite-tag/post-graph #P"user-home:temporary;all-posts.xml")
134 (compose 'type-of 'element))
136 (search "lisp" (symbol-name (element v)) :test #'string-equal))
137 :complete-closure-with-links
139 "user-home:temporary;lisp-tags-20051125.dot"
140 :vertex-labeler (lambda (vertex stream)
141 (format stream "~(~A~)" (symbol-name (element vertex))))
142 :edge-formatter (lambda (edge stream)
143 (format stream "weight=~D" (cl-graph:weight edge))))