This repository has been archived on 2022-05-13. You can view files and clone it, but cannot push or open issues or pull requests.
chronometrist/elisp/chronometrist-third.org

214 lines
8.8 KiB
Org Mode
Raw Permalink Normal View History

2022-02-10 11:33:08 +00:00
#+TITLE: chronometrist-third
#+SUBTITLE: Third Time System extension for Chronometrist
#+PROPERTY: header-args :tangle yes :load yes :comments link
* Program source
2022-02-10 16:25:28 +00:00
** Library headers and commentary
2022-02-10 16:35:31 +00:00
#+BEGIN_SRC emacs-lisp :comments no
2022-02-10 16:25:28 +00:00
;;; chronometrist-third.el --- Third Time support for Chronometrist -*- lexical-binding: t; -*-
;; Author: contrapunctus <xmpp:contrapunctus@jabjab.de>
;; Maintainer: contrapunctus <xmpp:contrapunctus@jabjab.de>
;; Keywords: calendar
;; Homepage: https://tildegit.org/contrapunctus/chronometrist
;; Package-Requires: ((emacs "25.1") (alert "1.2") (chronometrist "0.6.0"))
;; Version: 0.0.1
;; This is free and unencumbered software released into the public domain.
;;
;; Anyone is free to copy, modify, publish, use, compile, sell, or
;; distribute this software, either in source code form or as a compiled
;; binary, for any purpose, commercial or non-commercial, and by any
;; means.
;;
;; For more information, please refer to <https://unlicense.org>
;;; Commentary:
2022-02-10 16:35:31 +00:00
;; Add support for the Third Time system to Chronometrist. In Third
2022-02-10 16:25:28 +00:00
;; Time, you work for any length of time you like, and "earn" a third
2022-02-10 16:35:31 +00:00
;; of the work time as break time. For a more detailed explanation,
2022-02-10 16:25:28 +00:00
;; see
;; https://www.lesswrong.com/posts/RWu8eZqbwgB9zaerh/third-time-a-better-way-to-work
;; For information on usage and customization, see https://tildegit.org/contrapunctus/chronometrist-goal/src/branch/production/README.md
#+END_SRC
** Dependencies
2022-02-10 16:35:31 +00:00
#+BEGIN_SRC emacs-lisp :comments no
2022-02-10 16:25:28 +00:00
;;; Code:
(require 'chronometrist)
(require 'alert)
#+END_SRC
** group :custom:group:
#+BEGIN_SRC emacs-lisp
(defgroup chronometrist-third nil
"Third Time support for Chronometrist."
:group 'chronometrist)
#+END_SRC
** divisor :custom:variable:
2022-02-10 11:33:08 +00:00
#+BEGIN_SRC emacs-lisp
(defcustom chronometrist-third-divisor 3
2022-02-10 16:35:31 +00:00
"Number to determine accumulation of break time relative to work time."
:type 'number)
2022-02-10 11:33:08 +00:00
#+END_SRC
2022-02-10 16:25:28 +00:00
** duration-format :custom:variable:
#+BEGIN_SRC emacs-lisp
2022-02-24 10:17:06 +00:00
(defcustom chronometrist-third-duration-format "%H, %M and %S%z"
2022-02-10 16:35:31 +00:00
"Format string for durations, passed to `format-seconds'."
:type 'string)
2022-02-10 16:25:28 +00:00
#+END_SRC
** break-time :variable:
2022-02-10 11:33:08 +00:00
#+BEGIN_SRC emacs-lisp
(defvar chronometrist-third-break-time 0
"Accumulated break time in seconds.")
#+END_SRC
2022-02-11 06:26:33 +00:00
** alert-functions :custom:variable:
2022-02-10 13:47:04 +00:00
#+BEGIN_SRC emacs-lisp
2022-02-10 16:25:28 +00:00
(defcustom chronometrist-third-alert-functions '(chronometrist-third-half-alert chronometrist-third-quarter-alert chronometrist-third-break-over-alert)
2022-02-10 13:47:04 +00:00
"List of timed alerts for the Third Time system.
2022-02-10 16:25:28 +00:00
Typically, each function in this list should call
`chronometrist-third-run-at-time' to run another function, which
2022-02-11 06:26:33 +00:00
in turn should call `alert' to notify the user.
All functions in this list are started when the user clocks out,
and stopped when they clock in."
2022-02-10 13:47:04 +00:00
:group 'chronometrist-third
:type 'hook)
#+END_SRC
2022-02-11 06:26:33 +00:00
** timer-list :variable:
2022-02-10 13:47:04 +00:00
#+BEGIN_SRC emacs-lisp
2022-02-10 16:25:28 +00:00
(defvar chronometrist-third-timer-list nil)
2022-02-11 06:26:33 +00:00
#+END_SRC
2022-02-10 16:25:28 +00:00
2022-02-11 06:26:33 +00:00
** run-at-time :procedure:
#+BEGIN_SRC emacs-lisp
2022-02-10 16:25:28 +00:00
(defun chronometrist-third-run-at-time (time repeat function &rest args)
2022-02-11 06:26:33 +00:00
"Like `run-at-time', but store timer objects in `chronometrist-third-timer-list'."
2022-02-10 16:25:28 +00:00
(cl-pushnew (apply #'run-at-time time repeat function args) chronometrist-third-timer-list))
2022-02-11 06:26:33 +00:00
#+END_SRC
2022-02-10 16:25:28 +00:00
2022-02-11 06:26:33 +00:00
** half-alert :procedure:
#+BEGIN_SRC emacs-lisp
2022-02-10 13:47:04 +00:00
(defun chronometrist-third-half-alert ()
2022-02-11 06:26:33 +00:00
"Display an alert when half the break time is consumed."
(let ((half-time (/ chronometrist-third-break-time 2.0)))
(and (not (zerop chronometrist-third-break-time))
(chronometrist-third-run-at-time
half-time nil
2022-02-12 18:20:34 +00:00
(lambda (half-time)
2022-02-11 06:26:33 +00:00
(alert
(format "%s left on your break."
2022-02-12 18:20:34 +00:00
(format-seconds chronometrist-third-duration-format half-time))))
half-time))))
2022-02-11 06:26:33 +00:00
#+END_SRC
2022-02-10 16:25:28 +00:00
2022-02-11 06:26:33 +00:00
** quarter-alert :procedure:
#+BEGIN_SRC emacs-lisp
2022-02-10 16:25:28 +00:00
(defun chronometrist-third-quarter-alert ()
"Display an alert when 3/4ths of the break time is consumed."
2022-02-11 06:26:33 +00:00
(let ((three-fourths (* chronometrist-third-break-time 7.5)))
(and (not (zerop chronometrist-third-break-time))
(chronometrist-third-run-at-time
three-fourths nil
2022-02-12 18:20:34 +00:00
(lambda (three-fourths)
2022-02-11 06:26:33 +00:00
(alert
(format "%s left on your break."
2022-02-11 07:05:56 +00:00
(format-seconds chronometrist-third-duration-format
2022-02-12 18:20:34 +00:00
(- chronometrist-third-break-time three-fourths)))))
three-fourths))))
2022-02-11 06:26:33 +00:00
#+END_SRC
2022-02-10 16:25:28 +00:00
2022-02-11 06:26:33 +00:00
** break-over-alert :procedure:
#+BEGIN_SRC emacs-lisp
2022-02-10 16:25:28 +00:00
(defun chronometrist-third-break-over-alert ()
"Display an alert when break time is over."
2022-02-10 13:47:04 +00:00
(and (not (zerop chronometrist-third-break-time))
2022-02-10 16:25:28 +00:00
(chronometrist-third-run-at-time
chronometrist-third-break-time nil
(lambda () (alert (format "Break time is over!"))))))
#+END_SRC
2022-02-11 06:26:33 +00:00
** start-alert-timers :procedure:
2022-02-10 16:25:28 +00:00
#+BEGIN_SRC emacs-lisp
(defun chronometrist-third-start-alert-timers ()
2022-02-11 06:26:33 +00:00
"Run functions in `chronometrist-third-alert-functions'."
2022-02-10 16:25:28 +00:00
(mapc #'funcall chronometrist-third-alert-functions))
#+END_SRC
2022-02-11 06:26:33 +00:00
** stop-alert-timers :procedure:
2022-02-10 16:25:28 +00:00
#+BEGIN_SRC emacs-lisp
(defun chronometrist-third-stop-alert-timers ()
2022-02-11 06:26:33 +00:00
"Stop timers in `chronometrist-third-timer-list'."
2022-02-10 16:25:28 +00:00
(mapc (lambda (timer) (cancel-timer timer)) chronometrist-third-timer-list))
2022-02-10 13:47:04 +00:00
#+END_SRC
2022-02-11 06:26:33 +00:00
** clock-in :hook:procedure:
2022-02-10 11:33:08 +00:00
#+BEGIN_SRC emacs-lisp
2022-02-10 16:35:31 +00:00
(defun chronometrist-third-clock-in (&optional _arg)
2022-02-11 06:26:33 +00:00
"Stop alert timers and update break time."
2022-02-10 16:25:28 +00:00
(chronometrist-third-stop-alert-timers)
(unless (zerop chronometrist-third-break-time)
(-let* (((&plist :stop stop) (cl-second (chronometrist-to-list (chronometrist-active-backend))))
(used-break (ts-diff (ts-now) (chronometrist-iso-to-ts stop)))
(used-break-string (format-seconds chronometrist-third-duration-format used-break))
(new-break (- chronometrist-third-break-time used-break))
(old-break chronometrist-third-break-time))
(setq chronometrist-third-break-time (if (> new-break 0) new-break 0))
(alert
(if (zerop chronometrist-third-break-time)
(format "You have used up all %s of your break time (%s break)"
(format-seconds chronometrist-third-duration-format old-break)
used-break-string)
(format "You have used %s of your break time (%s left)"
used-break-string
(format-seconds chronometrist-third-duration-format chronometrist-third-break-time)))))))
2022-02-10 11:33:08 +00:00
#+END_SRC
2022-02-11 06:26:33 +00:00
** clock-out :hook:procedure:
2022-02-10 11:33:08 +00:00
#+BEGIN_SRC emacs-lisp
2022-02-10 16:35:31 +00:00
(defun chronometrist-third-clock-out (&optional _arg)
2022-02-11 06:26:33 +00:00
"Update break time based on the latest work interval.
Run `chronometrist-third-alert-functions' to alert user when
break time is up."
2022-02-10 16:25:28 +00:00
(let* ((latest-work-duration (chronometrist-interval (chronometrist-latest-record (chronometrist-active-backend))))
(break-time-increment (/ latest-work-duration chronometrist-third-divisor)))
(cl-incf chronometrist-third-break-time break-time-increment)
(alert (format "You have gained %s of break time (%s total)"
(format-seconds chronometrist-third-duration-format break-time-increment)
(format-seconds chronometrist-third-duration-format chronometrist-third-break-time)))
2022-02-10 13:47:04 +00:00
;; start alert timer(s)
2022-02-10 16:25:28 +00:00
(chronometrist-third-start-alert-timers)))
2022-02-10 11:33:08 +00:00
#+END_SRC
2022-02-11 06:26:33 +00:00
** third-minor-mode :minor:mode:
2022-02-10 13:47:04 +00:00
#+BEGIN_SRC emacs-lisp
2022-02-11 16:31:24 +00:00
;;;###autoload
2022-02-10 13:47:04 +00:00
(define-minor-mode chronometrist-third-minor-mode
nil nil nil nil
(cond (chronometrist-third-minor-mode
(add-hook 'chronometrist-after-in-functions #'chronometrist-third-clock-in)
(add-hook 'chronometrist-after-out-functions #'chronometrist-third-clock-out))
(t (remove-hook 'chronometrist-after-in-functions #'chronometrist-third-clock-in)
(remove-hook 'chronometrist-after-out-functions #'chronometrist-third-clock-out))))
#+END_SRC
2022-02-10 16:35:31 +00:00
** Provide
#+BEGIN_SRC emacs-lisp :comments no
(provide 'chronometrist-third)
;;; chronometrist-third.el ends here
#+END_SRC
2022-02-14 19:56:15 +00:00
* Local variables :noexport:
2022-02-10 11:33:08 +00:00
# Local Variables:
# my-org-src-default-lang: "emacs-lisp"
2022-02-10 13:23:06 +00:00
# eval: (when (package-installed-p 'literate-elisp) (require 'literate-elisp) (literate-elisp-load (buffer-file-name)))
2022-02-10 11:33:08 +00:00
# End: