---
Davin Pearson http://davin.50webs.com
(require 'd-time)
(defvar rsi-period (* 5 60)
  "The time (in seconds) between the mandatory rsi-breaks.")
(defvar rsi-break  10
  "The time (in seconds) of the mandatory rsi-breaks.")
(defvar rsi-last-break nil
  "String containing the time of the last rsi-break.")
(defvar rsi-keystroke-count 60
  "How many keystrokes per minute")
(defun rsi-start-timer ()
  "Starts the rsi-break system in operation.  Cannot call this twice without errors."
  (if (boundp 'rsi-timer)
      (cancel-timer rsi-timer))
  (setq rsi-timer (run-with-timer 0 rsi-period 'rsi-timer-function))
  (setq rsi-last-plugged-in (current-time-string))
  (add-hook 'post-command-hook 'rsi-increment-keycount)
  )
(defun rsi-stop-timer ()
  "Stops the rsi-break system."
  (cancel-timer rsi-timer)
  (remove-hook 'post-command-hook 'rsi-increment-keycount))
(setq rsi-on nil)
(defun rsi-timer-function ()
  (interactive)
  (save-match-data
    (let ((timer-idle-list nil)
          (keys-per-minute (/ rsi-keystroke-count (/ rsi-period 60.0)))
          (d-message-on t))
      (let* ((message-log-max nil)
             (pad-size (max 0 (/ (- (frame-width) (+ (* 2 (length "TYPING break..."))
                                                     (length "12345  keys-per-minute")
                                                     (length "abcdefgh")
                                                     )) 2)))
             (padding (make-string pad-size ? )))
        (setq rsi-last-break (current-time))
        (when (and rsi-on (> keys-per-minute 0))
          (let ((i rsi-break))
            (while (> i 0)
                            (let ((visible-bell t))
                (beep))
                                          (let ((j 8))
                (while (> j 0)
                  (message (format (concat
                                    "%s %3d"
                                    padding
                                    "%5d  keys-per-minute"
                                    padding
                                    "%3d %s")
                                   (cond ((= 0 (mod j 2))
                                          "TYPING break...")
                                         (t
                                          "               "))
                                   i keys-per-minute i
                                   (cond ((= 0 (mod j 2))
                                          "...TYPING break")
                                         (t
                                          "               "))))
                  (sleep-for 0.1)
                  (decf j)))
              (decf i))
            (message ""))))
      (setq rsi-keystroke-count 0)
      (setq rsi-on t)
      (if (and rsi-log-time-worked (> keys-per-minute 0))
          (progn
            (message "Last rsi-brk commencing at %s keys-per-minute=%d time to get off computer!" (d-decode-time) keys-per-minute)
            (rsi-log (format "%s %d" (d-decode-time rsi-last-break) keys-per-minute)))
        (message "Last rsi-brk commencing at %s keys-per-minute=%d"
                 (d-decode-time rsi-last-break)
                 keys-per-minute)
        )
      )
    )
  )
(defvar rsi-log-time-worked nil
  "Whether or not to record hours worked")
(defvar rsi-log-file (concat "~/rsi-log-"
                             (d-time--get-stamp d-emacs-start-time)
                             ".txt")
  "Log file #1 for recording rsi-brk timestamps")
(defvar rsi-log-file-2 (concat "~/rsi-hours-worked-"
                               (d-time--get-stamp d-emacs-start-time)
                               ".txt")
  "Log file #2 for recording hours worked")
(defun rsi-log (str)
  (save-excursion
    (setq buf (find-file rsi-log-file))
    (read-only-mode -1)
    (end-of-buffer)
    (insert str "\n")
    (let ((d-message-on t))
      (message str))
    (save-buffer 'NO-QUESTIONS)
    (kill-buffer buf))
  (if (fboundp 'd-speedbar)
      (d-speedbar)))
(defun rsi-compute-time ()
  (interactive)
  (save-excursion
    (let (line t1 start-time done line2 t2 buf)
      (progn
        (progn
          (find-file rsi-log-file-2)
          (read-only-mode -1)
          (erase-buffer))
        (progn
          (find-file rsi-log-file)
          (read-only-mode -1)
          (goto-char (point-min))
                    (flush-lines "^[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]-[0-9][0-9][0-9][0-9][0-9][0-9][ \t]+0[ \t]*$")
          )
        (goto-char (point-min))
                (setq line (d-time--current-line-as-string))
        (if (string= "" line)
            (setq done t)
          (setq line (substring line 0 (length "YYYYMMDD-HHMMSS")))
          (setq start-time (d-time--yyyymmdd-hhmmss-to-time line))
          (setq done nil)
          (setq count 0)
                    (while (not done)
            (incf count)
            (setq line (d-time--current-line-as-string))
            (if (string= "" line)
                (setq done t)
              (setq line (substring line 0 (length "YYYYMMDD-HHMMSS")))
              (setq t1 (d-time--yyyymmdd-hhmmss-to-time line))
              (forward-line 1)
              (beginning-of-line)
              (setq line2 (d-time--current-line-as-string))
              (if (string= "" line2)
                  (setq done t)
                (setq line2 (substring line2 0 (length "YYYYMMDD-HHMMSS")))
                (setq t2 (d-time--yyyymmdd-hhmmss-to-time line2))
                (if (> (d-seconds-of-time-difference t1 t2) (* 2 rsi-period))
                    (save-excursion
                      (find-file rsi-log-file-2)
                      (read-only-mode -1)
                      (goto-char (point-max))
                      (insert (format "%s %3d minutes t1=%s, t2=%s\n"
                                      (d-time--get-stamp start-time)
                                      (/ (d-seconds-of-time-difference start-time t1) 60)
                                      (d-time--get-stamp t1)
                                      (d-time--get-stamp t2)
                                      ))
                      (setq start-time t2)
                                            )
                  ))))
          (save-excursion
            (find-file rsi-log-file-2)
            (read-only-mode -1)
            (goto-char (point-max))
            (insert (format "%s %3d minutes t1=%s, t2=%s\n"
                            (d-time--get-stamp start-time)
                            (/ (d-seconds-of-time-difference start-time t1) 60)
                            (d-time--get-stamp t1)
                            (d-time--get-stamp t2)))))
                (save-excursion
          (setq buf (find-file rsi-log-file-2))
                    (save-buffer)
          (kill-buffer buf)
          (message "Time to get off computer!")
          )
        )       )
    )
  )
(setq rsi-last-command-keys nil)
(defun rsi-increment-keycount ()
  (let ((tck (this-command-keys)))
    (if (not (equal rsi-last-command-keys (this-command-keys)))
        (setq rsi-keystroke-count (+ rsi-keystroke-count (length (this-command-keys)))))
    (setq rsi-last-command-keys tck)))
(byte-compile 'rsi-increment-keycount)
(if (not noninteractive)
    (rsi-start-timer))
(provide 'rsi-brk)