(in-package :lispostory) (define-data-source drop) (defparameter *chronostory-drops-sheet-url* "https://docs.google.com/spreadsheets/d/e/2PACX-1vRpKuZGJQIFFxSi6kzYx4ALI0MQborpLEkh3J1qIGSd0Bw7U4NYg5CK-3ESzyK580z4D8NO59SUeC3k/pub?gid=1888753114&single=true&output=csv") (defun cleanup-data (hm) (dolist (key '("DropperID" "ItemID" "Chance" "MinQTY" "MaxQTY")) (update-hash hm key (lambda (x) (string-replace-all "," x ""))) (update-hash hm key #'parse-integer)) (update-hash hm "AvgQty" #'parse-float) (dolist (key '("isBoss" "Enable" "InGame")) (update-hash hm key #'string->bool)) hm) (defmethod refresh ((ds drop-data-source)) (let* ((data (drakma:http-request *chronostory-drops-sheet-url*)) (csv (cl-csv:read-csv data)) (header (car csv)) (num-fields-to-keep (position "" header :test #'equal)) (keys (mapcar #'string-to-hash-table-key (subseq header 0 num-fields-to-keep))) (drops (map 'vector (lambda (row) (cleanup-data (pairhash keys (subseq row 0 num-fields-to-keep) (dict)))) (cdr csv)))) (setf (cache ds) drops) (write-string-into-file (shasht:write-json drops nil) (file-path ds) :if-exists :overwrite :if-does-not-exist :create))) (defun get-mobs-that-drop-item (item-id &optional (drop-ds (make-drop-data-source)) (mob-ds (make-mob-data-source))) (loop for drop across (data drop-ds) when (equal (href drop "ItemID") item-id) append (loop for mob across (data mob-ds) when (equal (parse-integer (href mob "mob" "mob_id")) (href drop "DropperID")) collect mob))) (defun get-drops-by-item-name (item-name &optional (ds (make-drop-data-source))) (loop for drop across (data ds) when (string-equal (href drop "ItemName") item-name) collect drop)) (comment (defvar drops (make-drop-data-source)) (get-drops-by-item-name "Blue Goldrunners") (data (make-drop-data-source)) (refresh drops) (reload drops))