working new users per day
[kspaans/nntp-to-dot] / userstats.ss
index b765f3c..1f2416d 100644 (file)
 #lang scheme
 
 (require "common.ss")
+(require srfi/19)
 
-(provide count-users)
+(provide count-users new-u-vs-time)
 
 ;; User Statistics Struct
-;; String, int, date, date...
-(define-struct ustats (user nump firstp lastp))
+;; String - usename in the form of an email address, possibility of duplicates
+;; int    - total number of posts in newsgroup
+;; date   - SRFI-19 date struct, date of first post to group
+;; date   - "     "    ", date of last post to struct
+;; int    - number of days in range from first post day to past post day
+;; real   - number of posts / number of days
+(define-struct ustats (user nump firstp lastp days avgppd))
 
 ;; Collect stats in the form of '(USERNAME ustats)
 (define users (make-hash))
 ;; print-stats: void -> void
 ;; Pretty print the contents of the user statistics table to stdout
 (define (print-stats)
+  (printf "Total number of users: ~a~n~n" (hash-count users))
   (hash-for-each
     users
     (lambda (k v)
-      (printf "User: ~a~nUser: ~a~nCount: ~a~nLast: ~a~nFirst: ~a~n~n"
-              k
+      (printf "User: ~a~nCount: ~a~nFirst: ~a~nLast:  ~a~nAvgPPD: ~a~n~n"
               (ustats-user v)
               (ustats-nump v)
+              (ustats-firstp v)
               (ustats-lastp v)
-              (ustats-firstp v)))))
+              (ustats-avgppd v)))))
 
 ;; count-users: int int newsgroup -> void
 ;; build a hash table with each user from the group collecting stats:
 ;; - number of posts
 ;; - first/last post
-;; So if "last" post is empty, then user has only 1 post - veryify this?
+;; So if "last" post is empty, then user has only 1 post
 (define (count-users first last newsd)
   (cond
     [(= first last) (print-stats)]
-    [else (letrec [(message (message-getter uwnews first (list from-regexp date-regexp)))
-                   (mesg-from (car message))
-                   (mesg-date (cadr message))]
-                        ;; Fudge, should factor out date-getting code from ppd
+    [else (letrec [(message (message-getter newsd first (list from-regexp date-regexp)))
+                   (mesg-from (if (boolean? message) message (car message)))
+                   (mesg-date (if (boolean? message) message (cadr message)))]
             (cond
               [(boolean? message) (void)]
               [else
                (let [(result (hash-ref users mesg-from #f))]
                  (cond
                    [(boolean? result)
-                    (hash-set! users mesg-from (make-ustats mesg-from 1 mesg-date '()))]
+                    ;(printf "First post ~a ::@:: ~a~n" mesg-from mesg-date)
+                    (hash-set! users mesg-from (make-ustats mesg-from 1 (get-date mesg-date) '() 1 1))]
                    [else
+                                     ;; Calculate the ordinal day of the year (1-365) of the given date
+                                     ;; then subtract. Alternatively date->time and time-difference
+                                     ;; functions can be used to calculate this
+                    (let [(pdays (if (empty? (ustats-lastp result))
+                                     1
+                                     (+ 1 (- (date-year-day (ustats-lastp result))
+                                             (date-year-day (ustats-firstp result))))))
+                          (new-nump (+ 1 (ustats-nump result)))]
                     (hash-set! users mesg-from (make-ustats
                                                  mesg-from
-                                                 (+ 1 (ustats-nump result))
+                                                 new-nump
                                                  (ustats-firstp result)
-                                                 mesg-date))]))]))
-          (read-all (+ first 1) last newsd)]))
+                                                 (get-date mesg-date)
+                                                 pdays
+                                                 (/ new-nump pdays))))]))]))
+          (count-users (+ first 1) last newsd)]))
+
+;; new-u-vs-time: void -> void
+;; Prints out info (similar to PPD) representing the number of new users showing up
+;; on the newsgroup (e.g. first posts) plotted versus time. This will be plottable with GNUPLOT.
+;; First map all first post instances to a new hash table that will count the number of first
+;; posts on each day. Then map over that hash table to print them out appropriately.
+(define (new-u-vs-time)
+  (let [(new-u-hash (make-hash))]
+    (hash-for-each
+      users
+      (lambda (k v)
+        (letrec [(ndate (date->string (ustats-firstp v) "~D"))
+                 (result (hash-ref new-u-hash ndate #f))]
+          (cond
+            [(boolean? result) (hash-set! new-u-hash ndate 1)]
+            [else (hash-set! new-u-hash ndate (+ 1 result))]))))
+    (hash-for-each new-u-hash
+                   (lambda (k v) (printf "~a ~a~n" k v)))))