Browse Source

Added fn to filter posts by ratings for graphing

master
Yotsubaaa 6 months ago
parent
commit
13ee76976e
1 changed files with 53 additions and 35 deletions
  1. +53
    -35
      src/cl-kiwi.lisp

+ 53
- 35
src/cl-kiwi.lisp View File

@@ -136,9 +136,12 @@

(defun extract-number (dom-element)
"Extract the post number from HTML/DOM."
(let ((trim-chars '(#\Space #\Linefeed #\Return #\#)))
(parse-integer
(string-trim trim-chars (elt (lquery:$ dom-element "li a" (text)) 1)))))
;; TODO: Need to fix this up! The highlight specifier messes with it.
(parse-integer
(cl-ppcre:scan-to-strings "(\\d+)"
(reduce (lambda (s1 s2)
(concatenate 'string s1 s2))
(lquery:$ dom-element "li a" (text))))))

(defun extract-ratings (dom-element)
"Extract the post ratings from HTML/DOM. (Requires another HTTP call.)"
@@ -192,7 +195,7 @@
;;;Also, echo everything as we go!
(defparameter *start-page* 1)
;;;upto whatever page
(defparameter *end-page* 19)
(defparameter *end-page* 30)

;;; Collect the specified thread posts into a list
(defparameter *collected-posts*
@@ -350,7 +353,18 @@
"Return only those posts designated as 'Highlight' posts."
(remove-if-not #'get-post-highlightp *collected-posts*))


;;; e.g. filter only the Informative posts?
(defun filter-posts-by-rating (rating &optional (greater-than 0))
"Return only those posts with the given amount of RATINGs."
(remove-if-not (lambda (post)
(let ((rating (getf (get-post-ratings post)
(intern (string rating) :keyword))))
(> (if rating
rating
0)
greater-than)))
*collected-posts*))
;;; e.g.
(filter-posts-between "Dec 1, 2018 at 7:00 PM"
"Dec 1, 2019 at 7:00 PM")
@@ -360,35 +374,39 @@

;;; Now for a pretty graph! First, we keep track of the post authors and
;;; the number of times they've posted in a plist
(defparameter *number-of-posts* nil)
(loop for post in *collected-posts* do
(let ((post-author (intern (string (get-post-author post)) :keyword)))
;; TODO: This bugs me to look at: too much repeated (getf ..) !
;; Not sure what to do about it though. setf/incf need their
;; argument to be 'getf-able', so a variable/let binding
;; doesn't work. Well, whatever.
(if (getf *number-of-posts* post-author)
(incf (getf *number-of-posts* post-author))
(setf (getf *number-of-posts* post-author) 1))))

;;; Make a pretty pie chart!
(net.acceleration.charting:with-chart (:pie 600 370)
(loop for (label value) in
(sort
(loop for (author post-count) on *number-of-posts* by #'cddr collect
(let ((post-percentage
(float (* 100 (/ post-count
(length *collected-posts*))))))
(list (format nil
"~a ~5,2f\%"
(string author)
post-percentage)
post-count)))
#'>
:key (lambda (pair) (cadr pair)))
do
(net.acceleration.charting:add-slice label value))
(net.acceleration.charting:save-file "piechart.png"))
(defun graph-piechart-posts-by-author (posts)
"Draw a pretty pie-chart of the percentage of POSTS by author."
(let ((number-of-posts nil))
(loop
for post in posts
for post-author = (intern (string (get-post-author post)) :keyword)
do
;; TODO: This bugs me to look at: too much repeated (getf ..) !
;; Not sure what to do about it though. setf/incf need their
;; argument to be 'getf-able', so a variable/let binding
;; doesn't work. Well, whatever.
(if (getf number-of-posts post-author)
(incf (getf number-of-posts post-author))
(setf (getf number-of-posts post-author) 1)))
;; Make a pretty pie chart!
(net.acceleration.charting:with-chart (:pie 600 370)
(loop for (label value) in
(sort
(loop for (author post-count) on number-of-posts by #'cddr
collect
(let ((post-percentage
(float (* 100 (/ post-count
(length posts))))))
(list (format nil
"~a ~5,2f\%"
(string author)
post-percentage)
post-count)))
#'>
:key (lambda (pair) (cadr pair)))
do
(net.acceleration.charting:add-slice label value))
(net.acceleration.charting:save-file "piechart.png"))))

;;; More list sorting/analytics for fun
@@ -444,7 +462,7 @@
(universal-time-to-timestamp time)
(universal-time-to-timestamp (increment-day time)))))))

(with-open-file (stream "freq.csv" :direction :output)
(with-open-file (stream "freq.csv" :direction :output :if-exists :overwrite)
;; Header
(format stream "~a,~a,~a~%" "universal time" "day timestamp" "post count")
(loop for post-count-pair in *binned-frequency* do


Loading…
Cancel
Save