Browse Source

Initial Commit

Simon Watson 2 years ago
commit
c06f5908c1
2 changed files with 77 additions and 0 deletions
  1. 1 0
      .gitignore
  2. 76 0
      fin-lisp.lisp

+ 1 - 0
.gitignore

@@ -0,0 +1 @@
+records.txt

+ 76 - 0
fin-lisp.lisp

@@ -0,0 +1,76 @@
+(ql:quickload "cl-store")
+
+;;;; Reimplementation of my bills tracker in Lisp
+(defun reload ()
+  (load "/Users/swatson/Repos/lisp-files/fin-lisp/fin-lisp.lisp"))
+
+;;; All records exist in this data structure
+;;; nil on start and loaded in from file
+;;; *records* represents as hash of months,
+;;; where the key is the month stamp, eg 20210701
+;;; and the value is the monthly expenses hash
+(defvar *records* (make-hash-table :test 'equalp))
+
+;; Called like: (add-month '202107)
+(defun add-month (month-key)
+  (setf (gethash month-key *records*) (make-hash-table :test 'equalp))
+  month-key)
+
+;;; Taken from practical common lisp
+(defun prompt-read (prompt)
+  (format *query-io* "~a: " prompt)
+  (force-output *query-io*)
+  (read-line *query-io*))
+
+(defun prompt-for-expense ()
+  (list
+   (prompt-read "Enter expense name")
+   (parse-integer
+    (prompt-read "Enter expense value"))))
+
+(defun add-expense-to-month (month)
+  (if (gethash month *records*)
+      (let ((innerhash (gethash month *records*))
+	    (exp-l (prompt-for-expense)))
+	(format t "Expense name is: ~a" (first exp-l))
+	(terpri)
+	(format t "Expense value is: ~a"(second exp-l))
+	(terpri)
+	(setf (gethash (first exp-l) innerhash) (second exp-l)))
+      ;;NIL))
+      (add-expense-to-month (add-month month))))
+
+;;; Given key for *records* hash,
+;;; print expenses/values for month
+(defun dump-month (month-key)
+  (format t "~a~C" month-key #\linefeed)
+  (let ((month-hash)
+	(exp-keys))
+    (setf month-hash (gethash month-key *records*))
+    (setf exp-keys (loop for key being the hash-keys of month-hash collect key))
+    (dolist (exp-key exp-keys)
+      (format t "~a : ~a~C" exp-key (gethash exp-key month-hash) #\linefeed))))
+
+;;; Dump all records.
+;;; This will also be used for data serialization at some point
+(defun dump-records ()
+  (let ((record-key-list (loop for key being the hash-keys of *records* collect key)))
+    (dolist (month-key record-key-list) (dump-month month-key))))
+
+(defun serialize-records (filename)
+  (cl-store:store *records* filename))
+
+(defun deserialize-records (filename)
+  ;(setf *records* (cl-store:restore (pathname filename))))
+  (setf *records* (cl-store:restore filename)))
+
+;; Entry point
+(defun main ()
+  (format t "Available options:")(terpri)
+  (format t "1. Enter expense")(terpri)
+  (format t "2. Display month")(terpri)
+  (format t "3. Write records")(terpri)
+  (let
+      ((answer (prompt-read "Select an option")))
+    answer))
+