..

The DEADCON system

For the past few months, I have restructured my productivity around a system I developed: the DEADCON system. As most people might have guessed from the name, it's a parody of the Defense Readiness Condition (DEFCON) system used by the United States Armed Forces.

The idea

The DEFCON system is used to indicate levels of military readiness in response to imminent threats. When no significant threats are present and normal peacetime conditions apply, the DEFCON level is set to 5. If the U.S. is on the verge of launching nuclear weapons, it is likely at DEFCON 1. The exact details of the actions taken by the Armed Forces at each DEFCON level are classified, but it is known that specific rules and procedures are in place. This is exactly what I needed in my own life. In order to prevent nucleair war (i.e. not getting my work done) I would need to grasp the seriousness of a deadline at hand and what to do about it.

The problem I had with all other systems up to that point was that they didn't truly account for workload. Having a deadline for a task is a good idea, but if I give myself 100 days to complete a task that only takes 10 minutes, I know I'll wait until the last possible moment to do it. On the other hand, giving myself seven days to finish a project that realistically requires two weeks is also unhelpful, as it leads me to ignore the plan entirely and hyperfocus out of sheer panic until it's done. This approach might work, but it harms my work-life balance and leaves me feeling guilty whenever I choose to have fun before completing the project.

When I learned about the DEFCON system, an idea popped into my mind: What if I could automatically calculate the 'threat' level of a deadline and determine the appropriate policies and actions to take at any given moment? Instead of waiting until the last minute to act, timely measures could be implemented that scale with the urgency of the task. A Deadline Readiness Condition (DEADCON), if you will…

The rules

After some experimentation, I came up with a formula to determine the DEADCON level for any project:

Every task marked as a project is assumed to take 14 days to complete. If the task has subtasks, each subtask is also assumed to take 14 days. Therefore, if a task has three subtasks, the total estimated time to complete the project will be 32 days (the main task is considered complete only when all subtasks are finished).

The number of days until the deadline is then divided by the total estimated days required, resulting in a decimal fraction that represents the proportion of required time remaining.

Based on that proportion, a DEADCON level is determined:

  • If 100% or more of the needed time is still available, we are at DEADCON 5
  • If less than 100% but more than 75% of the needed time is still available, we are at DEADCON 4
  • If less than 75% but more than 50% of the needed time is still available, we are at DEADCON 3
  • If less than 50% but more than 25% of the needed time is still available, we are at DEADCON 2
  • If less than 25% of the needed time is still available, we are at DEADCON 1

In order not to overcomplicate the system (yes, I know), I've decided to keep the policies for each DEADCON level simple and assign fibonacci increments for the minimal required time one should spend on the project:

  • At DEADCON 5, spend at least 43 minutes working on the project
  • At DEADCON 4, spend at least 70 minutes working on the project
  • At DEADCON 3, spend at least 114 minutes working on the project
  • At DEADCON 2, spend at least 185 minutes working on the project
  • At DEADCON 1, spend at least 300 minutes working on the project

This way, if you correctly assume that every (sub)task takes less than two weeks to complete, you can safely assume that the DEADCON level gives you a reasonable amount of time to work on a project and an objective way to measure whether you've 'done enough' for the day. There's no cheating the system, either. Doing fake work doesn't help, as (sub)tasks determine the DEADCON level. Not doing anything useful for days will lower the DEADCON level until one has to come to terms with the fact that they must seriously step up to still finish on time.

The 300 minutes (or 5 hours) weren't chosen arbitrarily, either. Research has shown that the average knowledge worker can only perform their job efficiently, without hitting diminishing returns, for somewhere between 3 to 5 hours. If someone finds themselves in a DEADCON 1 situation, they can choose to work more than 5 hours, but only if they are willing to risk overworking and burnout.

The implementation

In order for my idea to work I needed a few things:

  • A way to track tasks and their deadlines
  • A way to dynamically edit the properties of those tasks
  • An implementation of the formula that calculates the DEADCON level

Tracking tasks, deadlines and dynamically modifying their properties would be a piece of cake for my editor of choice: emacs. Especially doom emacs makes it incredibly straightforward (there's an emacs joke in there). The following code takes the DEADLINE of any task and calculates its DEADCON level based on the amount of subtasks:

;; New DEADCON calculation function
(defun calculate-deadcon ()
  "Calculate DEADCON level based on time left and required time, with thresholds."
  (let* ((due-date (org-entry-get nil "DEADLINE"))
         (current-time (current-time))
         ;; Extract the progress indicator, e.g., [0/2], from the heading
         (progress (save-excursion
                     (org-back-to-heading)
                     (when (re-search-forward "\\[\\([0-9]+\\)/\\([0-9]+\\)\\]" (line-end-position) t)
                       (list (string-to-number (match-string 1)) ; Completed subtasks
                             (string-to-number (match-string 2)))))) ; Total subtasks
         (sub-tasks-done (or (nth 0 progress) 0))
         (sub-tasks-total (or (nth 1 progress) 1)) ;; Default to 1 if no progress info
         ;; Calculate total required days (2 weeks per subtask)
         (total-required-days (* sub-tasks-total 14))
         ;; Scale required days based on the number of completed subtasks
         (effective-required-days (* total-required-days
                                     (- 1.0 (/ (float sub-tasks-done) sub-tasks-total))))
         ;; Calculate days until the deadline, rounding up
         (days-until-deadline (if due-date
                                  (ceiling (- (time-to-days (org-time-string-to-time due-date))
                                              (time-to-days current-time)))
                                0))
         ;; Calculate remaining time as a percentage of effective required days
         (remaining-time-percentage (/ (float days-until-deadline) effective-required-days))
         ;; Determine DEADCON level based on the provided logic
         (deadcon (cond
                   ((>= remaining-time-percentage 1) "DEADCON 5")   ;; More time left than required
                   ((>= remaining-time-percentage 0.75) "DEADCON 4") ;; 75-100% time left
                   ((>= remaining-time-percentage 0.5) "DEADCON 3")  ;; 50-75% time left
                   ((>= remaining-time-percentage 0.25) "DEADCON 2") ;; 25-50% time left
                   (t "DEADCON 1")))) ;; Less than 25% time left
    deadcon))

Then there's the function that runs the DEADCON calculation and updates it for any task that is tagged with the :proj: tag and a TODO keyword. I've also added some hooks and recalculation functions to do this automatically, but that's optional of course.

;; Function to update DEADCON property for the current task
(defun update-deadcon ()
  "Update or remove the DEADCON property for tasks with the :proj: tag and a TODO keyword."
  (let ((todo-keyword (org-get-todo-state))
        (tags (org-get-tags)))
    ;; Check if the task has the :proj: tag and a valid TODO keyword
    (if (and (member "proj" tags)
             (member todo-keyword org-todo-keywords-1))  ; Check for active TODO keyword
        (let ((deadcon (calculate-deadcon)))
          (when (org-entry-get nil "DEADLINE")  ; Ensure the task has a DEADLINE
            (when deadcon
              (org-set-property "DEADCON" deadcon))))
      ;; Remove the DEADCON property if the task is DONE, KILL, or lacks the :proj: tag
      (org-delete-property "DEADCON"))))

;; Hooks to update DEADCON when TODO state, schedule, or deadline changes
(add-hook 'org-after-todo-state-change-hook 'update-deadcon)
(add-hook 'org-schedule-hook 'update-deadcon)
(add-hook 'org-deadline-hook 'update-deadcon)

;; Recalculate DEADCON for all tasks in the current buffer
(defun recalculate-deadcon-for-buffer ()
  "Recalculate DEADCON levels for all tasks in the current buffer."
  (interactive)
  (org-map-entries
   (lambda ()
     (update-deadcon))
   nil 'file))

;; Recalculate DEADCON for a specific file
(defun recalculate-deadcon-for-specific-file ()
  "Recalculate DEADCON levels for all tasks in the specific file."
  (let ((file "/home/oscar/Notes/Journal/projects.org"))
    (with-current-buffer (find-file-noselect file)
      (recalculate-deadcon-for-buffer)
      (save-buffer))))

(defun run-deadcon-recalculation-before-agenda (&rest args)
  "Run recalculate-deadcon-for-specific-file before org-agenda is prepared."
  (recalculate-deadcon-for-specific-file))

(advice-add 'org-agenda :before 'run-deadcon-recalculation-before-agenda)

;; Run DEADCON recalculation when Emacs daemon starts, and close buffer
(defun recalculate-deadcon-and-close-buffer ()
  "Recalculate DEADCON levels for all tasks in the specific file and close the buffer."
  (let ((file "/home/oscar/Notes/Journal/projects.org"))
    (with-current-buffer (find-file-noselect file)
      (recalculate-deadcon-for-buffer)
      (save-buffer)
      (kill-buffer))))

(add-hook 'emacs-startup-hook 'recalculate-deadcon-and-close-buffer)

Whilst horribly written, it just works!

The results

After working with this system for a few months, I can honestly say that it has cured my tendency to procrastinate. The DEADCON level clearly shows how much work I should be doing and rewards me for putting in a little effort every day. The system is quite forgiving but ruthless when it needs to be.

I hope that whoever finds this article can develop their own DEADCON policies to help them get more work done without feeling guilty when taking time off. Maybe you want to increase or decrease the 14 day default to make it work better for your use case. Maybe you can limit your screen time based on your DEADCON level or have your favourite food delivered automatically when you reach DEADCON 1, motivating you to put in a few more hours of work. The possibilities are endless, of course. The way I’ve personally managed to track my progress and reward myself is a topic for another time.

Want to contact me? You can! E-mail me at: blog@oscar.cc