User can create new category on the CLI

This commit is contained in:
Logan Hunt 2022-05-31 23:23:58 -07:00
parent 10d7a20a79
commit a76bfbf944
Signed by untrusted user who does not match committer: simponic
GPG Key ID: 52B3774857EB24B1
5 changed files with 70 additions and 57 deletions

View File

@ -24,12 +24,16 @@
(if start
(floor (* 100 (local-time:timestamp-difference end start))))))
(defun format-elapsed-time (run-split)
(defun run-split-format-elapsed-time (run-split)
(let ((elapsed (run-split-elapsed-time run-split)))
(if elapsed
(format-time (make-time-alist elapsed))
"-")))
;;(defun best-split (category-split)
;; (mito:select-dao 'run-split
;; (sxql:order-by (:- V
;; Returns stuff like PB, best of each split, etc.
(defun run-statistics (category)
`((asdf . 1)))

View File

@ -1,25 +1,24 @@
(asdf:defsystem "lispruns"
:description "A speedrun timer using n-curses written in lisp"
:version "0.1"
:author "Simponic"
:depends-on (:unix-opts
:mito
:sxql
:cl-ppcre
:croatoan
:local-time)
:components ((:file "util") ;; Miscellaneous helpers
(:file "config") ;; For importing category configuration files
(:file "digits") ;; Lisp file with cool ascii digits
(:file "text" :depends-on ("digits")) ;; Helper functions for performing figlet-like actions and such
(:file "time") ;; Custom time forms
(:file "ui" :depends-on ("util" "text" "time")) ;; Functions to draw the UI
(:file "speedrun" :depends-on ("util")) ;; The actual timer logic
(:file "database/category") ;; Category DAO
(:file "database/run") ;; Run DAO
(:file "main" :depends-on ("database/category"
"database/run"
"util"
"config"
"ui"
"speedrun"))))
:description "A speedrun timer using n-curses written in lisp"
:version "0.1"
:author "Simponic"
:depends-on (:mito
:sxql
:cl-ppcre
:croatoan
:local-time)
:components ((:file "util") ;; Miscellaneous helpers
(:file "config") ;; For importing category configuration files
(:file "digits") ;; Lisp file with cool ascii digits
(:file "text" :depends-on ("digits")) ;; Helper functions for performing figlet-like actions and such
(:file "time") ;; Custom time forms
(:file "ui" :depends-on ("util" "text" "time")) ;; Functions to draw the UI
(:file "speedrun" :depends-on ("util")) ;; The actual timer logic
(:file "database/category") ;; Category DAO
(:file "database/run") ;; Run DAO
(:file "main" :depends-on ("database/category"
"database/run"
"util"
"config"
"ui"
"speedrun"))))

View File

@ -20,7 +20,7 @@
(if (ignore-errors (funcall validator input))
input
(progn
(format t "E: Invalid input. Try again.")
(format t "E: Invalid input. Try again.~%")
(get-input prompt validator)))))
;; Options is an alist with the prompt string as the car and the value as the cdr
@ -53,6 +53,29 @@
(progn (format t "E: Could not find option that matched query.~%")
(select-option options)))))))
(defun user-create-new-category ()
(let* ((name (get-input "Category Name (e.g. \"SM64\"): " 'empty-p))
(percentage (get-input "Percentage (e.g. \"16 Star\"): " 'empty-p))
(category (mito:insert-dao (make-instance 'category :name name :percentage percentage)))
(splits (do ((spliti 1 (1+ spliti))
(inputs '() (push (get-input (format nil "Split Name [~a]~a: " spliti (if (<= spliti 1) " (blank when done adding)" ""))) inputs)))
((equal (car inputs) "")
(mapcar (lambda
(category-split-name)
(mito:insert-dao
(make-instance 'category-split
:name category-split-name
:category category)))
(reverse (cdr inputs)))))))))
(defun with-selected-category (f)
(let* ((categories (mito:select-dao 'category))
(category-alist (mapcar (lambda (category) `(,(format nil "~a - ~a" (category-name category) (category-percentage category)) . ,category)) categories)))
(if categories
(funcall f (select-option category-alist))
(format t "E: There are no categories. Try creating one or importing one"))))
(defun main ()
(let ((choice (select-option '(("Help" . HELP)
("Import a category" . IMPORT-CATEGORY)
@ -62,6 +85,7 @@
("Exit" . EXIT)))))
(case choice
('HELP
(format t "~%")
(mapcar #'(lambda (x) (format t "~a~%" x)) *lispruns-logo*))
('IMPORT-CATEGORY
(import-category (get-input
@ -69,25 +93,9 @@
(uiop/os:getcwd))
'probe-file)))
('NEW-CATEGORY
(let* ((name (get-input "Category Name (e.g. \"SM64\"): " 'not-empty-string))
(percentage (get-input "Percentage (e.g. \"16 Star\"): " 'not-empty-string))
(category (mito:insert-dao (make-instance 'category :name name :percentage percentage)))
(splits (do ((spliti 1 (1+ spliti))
(inputs '() (push (get-input (format nil "Split [~a]: " spliti)) inputs)))
((equal (car inputs) "")
(mapcar (lambda
(category-split-name)
(mito:insert-dao
(make-instance 'category-split
:name category-split-name
:category category)))
(reverse (cdr inputs)))))))))
(user-create-new-category))
('START-SPEEDRUN
(let* ((categories (mito:select-dao 'category))
(category-alist (mapcar (lambda (category) `(,(format nil "~a - ~a" (category-name category) (category-percentage category)) . ,category)) categories)))
(if categories
(speedrun-ui (select-option category-alist))
(format t "E: There are no categories. Try creating one or importing one"))))
(with-selected-category 'speedrun-ui))
('EXIT
(quit))))
(format t "~%")

24
ui.lisp
View File

@ -18,6 +18,12 @@
(inc yi))
slices)))
;; Formats a category split and a run split for the splits window
(defun make-split-line (csplit speedrun-split)
`((,(category-split-name csplit) . ,(/ 4 12))
("" . ,(/ 1 12))
(,(run-split-format-elapsed-time speedrun-split) . ,(/ 3 12))))
;; Creates a window with the total time and statistics
(defun timer-window (speedrun pos width height)
(let* ((timerglet (lispglet (format-time (make-time-alist (speedrun-elapsed speedrun)))))
@ -82,6 +88,7 @@
(subseq elements (car elements-to-draw-subseq) (cadr elements-to-draw-subseq))))
highlight-menu))
;; The big bad monolithic UI loop
(defun speedrun-ui (category)
(croatoan:with-screen (scr :input-blocking nil :input-echoing nil :cursor-visible nil :enable-colors t :input-buffering nil :input-blocking nil)
(setf (croatoan:background scr) (make-instance 'croatoan:complex-char :color-pair (cdr (assoc 'main *colors*))))
@ -90,7 +97,9 @@
(state 'TITLE)
(redraws '(title-instance))
(speedrun (make-speedrun category))
(csplits (category-splits category)))
(csplits (category-splits category))
;; TODO
(pbs ()))
(flet ((render ()
(case state
('TITLE
@ -124,16 +133,8 @@
:current-element-index (speedrun-current-split-index speedrun)
:height splits-height
:width max-width
:elements (mapcar (lambda (csplit speedrun-split)
`(
(,(category-split-name csplit) . ,(/ 4 12))
("" . ,(/ 1 12))
(,(format-elapsed-time speedrun-split) . ,(/ 3 12))
))
csplits
(speedrun-splits speedrun))))
;; :elements (mapcar #'category-split-name csplits)))
;; :elements `((("FIRST SPLIT IS EPIC" . ,(/ 4 12)) ("" . ,(/ 1 12)) ("10:10:00.22" . ,(/ 3 12)) ("" . ,(/ 1 12)) ("20:00.00" . ,(/ 3 12))))))
;; Todo: add personal bests to elements
:elements (mapcar 'make-split-line csplits (speedrun-splits speedrun))))
(splits-instance (highlight-list-window split-list `(0 ,centered-x)))
(timer-instance (timer-window speedrun `(,splits-height ,centered-x) max-width timer-height)))
(croatoan:refresh splits-instance)
@ -143,6 +144,7 @@
(if (zerop (mod frame 30))
(inc scroll))
(sleep (/ 1 60))))
(croatoan:event-case (scr event)
(#\q (return-from croatoan:event-case))
(#\space

View File

@ -10,5 +10,5 @@
(defun max-length (lists)
(reduce (lambda (a x) (max a x)) (mapcar #'length lists)))
(defun not-empty-string (str)
(not (zerop (length str))))
(defun empty-p (s)
(not (zerop (length s))))