ソースを参照

Add pings clj-session (brain-dump).

It parses my ~/.pings file which contains minute-wise
`date --rfc-3339=seconds` lines. It's been quite interesting to see what
I've been up to.

However, to be actually useful the data would have to be combined with
some "was working" state, such as #key-events, name of the application
running or a combination of this.

This is definitively inspired by [Steven Wolfram's Quantified Self
post](http://blog.stephenwolfram.com/2012/03/the-personal-analytics-of-my-life/).
Lucas Stadler 13 年 前
コミット
33cc9a6b5f
共有1 個のファイルを変更した104 個の追加0 個の削除を含む
  1. 104 0
      clj/pings.clj

+ 104 - 0
clj/pings.clj

@ -0,0 +1,104 @@
1
(ns pings
2
  (:use clojure.repl)
3
  (:use hello-clojure)
4
  (:require [datomic.api :as d])
5
  (:import java.util.Date)
6
  (:import java.text.SimpleDateFormat))
7
8
(.getMethods Date)
9
(.getMethods java.lang.reflect.Method)
10
11
(map #(.getName %) (.getMethods Date))
12
13
(def rfc-3339-format (SimpleDateFormat. "yyyy-MM-dd HH:mm:ssXXX"))
14
(defn parse-date [s]
15
  "Parse a date (RFC3339 format with seconds). Returns nil if no date can be parsed."
16
  (try (.parse rfc-3339-format s)
17
    (catch java.text.ParseException pe nil)))
18
19
(parse-date "2013-02-14 15:52:14+01:00")
20
(doc-ns 'clojure.core)
21
22
(def pings
23
  "Minute-wise 'pings' that are generated when my laptop is running."
24
  (map #(-> % second parse-date)
25
       (re-seq #"(.*)\n" (slurp "/home/lu/.pings"))))
26
27
(defn diff-seconds [d1 d2]
28
  (Math/abs (/ (- (.getTime d1) (.getTime d2)) 1000)))
29
30
(defn usual-ping? [diff] (< (/ diff 60) 10))
31
32
(filter #(-> % usual-ping? not) (map #(->> % (apply diff-seconds)) (partition 2 1 pings)))
33
34
(def unusual
35
  (filter #(not (usual-ping? (nth % 2)))
36
          (map (fn [[d1 d2]] [d1 d2 (diff-seconds d1 d2)])
37
               (partition 2 1 pings))))
38
39
(doseq [[d1 d2 diff] unusual] (println d1 d2 (float (/ diff 60 60))))
40
41
; avg unusual
42
(let [[c s] (reduce (fn [[c s] [_ _ d]] [(inc c) (+ s d)]) [0 0] unusual)]
43
  (float (/ s c 60 60)))
44
45
(defn avg
46
  "Calculate the average of the values in coll, choosing values using
47
   keyfn (defaults to identity)."
48
  ([coll]
49
    (avg identity coll))
50
  ([keyfn coll]
51
   (let [[c s] (reduce (fn [[c s] v] [(inc c) (+ s (keyfn v))]) [0 0] coll)]
52
     (/ s c))))
53
54
(doseq [[d1 d2 diff] (take 10 (sort-by (fn [[_ _ d]] d) > unusual))]
55
  (println d1 d2 (float (/ diff 60 60))))
56
57
; avg unusual #2
58
(float (/ (avg #(nth % 2) unusual) 60 60))
59
60
;; interesting data (for pings):
61
;;  * min/max/avg/daily (graph) 'uptime'
62
;;  * distribution throughout the day
63
;;  * stretches/pauses/'busy times'
64
65
(take 10 (sort-by (fn [[_ _ d]] d) < unusual))
66
(take 10 (map #(float (/ (nth % 2) 60 60)) (sort-by (fn [[_ _ d]] d) < unusual)))
67
68
(def day-format (SimpleDateFormat. "yyyy-MM-dd"))
69
70
(def daily-pings (group-by (fn [d] (.format day-format d)) pings))
71
72
(defn stretches [pings]
73
  (first (reduce (fn [[ss start-date last-date] date]
74
            (if (usual-ping? (diff-seconds last-date date))
75
              [ss start-date date]
76
              [(conj ss [start-date last-date]) date date]))
77
          [[] (first pings) (first pings)]
78
          (rest pings))))
79
80
(defn print-stretches [stretches]
81
  (doseq [[from to] stretches]
82
    (println (.format rfc-3339-format from) "to" (.format rfc-3339-format to))))
83
84
(print-stretches (stretches pings))
85
(print-stretches (filter (fn [[from to]] (not= (.getDay from) (.getDay to))) (stretches pings)))
86
87
(def daily-stretches (group-by (fn [[d _]] (.format day-format d)) (stretches pings)))
88
(daily-stretches "2012-12-07")
89
90
(defn daily-total [stretches-for-day]
91
  (reduce (fn [s [f t]] (+ s (diff-seconds f t)))
92
          0
93
          stretches-for-day))
94
95
(def hours-per-day (map (fn [[_ v]] (float (/ (daily-total v) 60 60))) daily-stretches))
96
97
(take 10 (sort-by identity > hours-per-day))
98
(reduce #(conj %1 %2) #{} (map #(Math/round %) hours-per-day))
99
(avg hours-per-day)
100
101
(def hour-distribution
102
  (map (fn [[k v]] [k (count v)]) (group-by #(.getHours %) pings)))
103
104
(sort-by second > (map (fn [[h c]] [h (float (/ c 60))]) hour-distribution))