speedrun-timer/speedrun.lisp
2022-06-04 13:09:39 -07:00

74 lines
2.9 KiB
Common Lisp

(defclass speedrun ()
((state
;; RUNNING, STOPPED
:initarg :state
:accessor speedrun-state)
(title
:initarg :title
:accessor speedrun-title)
(start-timestamp
:initarg :start-timestamp
:accessor speedrun-start-timestamp)
(elapsed ;; milliseconds
:initarg :elapsed
:accessor speedrun-elapsed)
(splits
:initarg :splits
:accessor speedrun-splits)
(run-dao
:initarg :run-dao
:accessor speedrun-run-dao)
(current-split-index
:initarg :current-split-index
:accessor speedrun-current-split-index)))
(defun make-speedrun (category)
(let* ((run (make-instance 'run :category category))
(splits (mapcar (lambda (category-split)
(make-instance 'run-split :category-split category-split :run run))
(category-splits category))))
(make-instance 'speedrun
:state 'STOPPED
:title (category-name category)
:splits splits
:current-split-index 0
:elapsed 0.0
:run-dao run)))
(defun current-split (speedrun)
(nth (speedrun-current-split-index speedrun) (speedrun-splits speedrun)))
;; Updates the current total elapsed time of the speedrun if it's running
(defun update-time (speedrun)
(if (eq (speedrun-state speedrun) 'RUNNING)
(setf (speedrun-elapsed speedrun) (millis-since-internal-timestamp (speedrun-start-timestamp speedrun)))))
;; Initializes a speedrun to start running the timer
(defun start-speedrun (speedrun)
(let ((now (get-internal-real-time)))
(setf (speedrun-state speedrun) 'RUNNING
(speedrun-start-timestamp speedrun) now
(run-split-start-timestamp (current-split speedrun)) now)))
;; Saves the speedrun into the database
(defun save-speedrun (speedrun)
(mapcar #'mito:save-dao (cons (speedrun-run-dao speedrun) (speedrun-splits speedrun))))
;; Set the state of the speedrun to be stopped if there are no more splits.
;; Or, set the current split to the next one in the list.
(defun next-split (speedrun)
(let ((now (get-internal-real-time)))
(unless (equal (speedrun-state speedrun) 'STOPPED)
(setf (run-split-end-timestamp (current-split speedrun)) now)
(if (equal (speedrun-current-split-index speedrun) (1- (length (speedrun-splits speedrun))))
(progn
(setf
;; Since timer computation can get +-0.02 seconds out of sync of splits, just set it to the sum of the splits' elapsed time
(speedrun-elapsed speedrun) (millis-since-internal-timestamp 0 (apply '+ (mapcar 'run-split-elapsed-time (speedrun-splits speedrun))))
(speedrun-state speedrun) 'STOPPED)
(save-speedrun speedrun))
(progn
(inc (speedrun-current-split-index speedrun))
(setf (run-split-start-timestamp (current-split speedrun)) now))))))