Files
lispostory/spawns.lisp

116 lines
4.3 KiB
Common Lisp

(in-package :lispostory)
(defparameter *chronostory-spawns-url-format* "https://docs.google.com/spreadsheets/d/e/2PACX-1vSIUj-72ADgwMqShxt4Dn7OP7dBN54l0wda1IPwlIVTZUN_ZtTlRx5DDidr43VXv2HYQ5RNqccLbbGS/pub?gid=~a&output=csv&single=true")
(defparameter *chronostory-spawn-gids*
(alist
:maple-island 415330053
:lith-harbor 486394009
:kerning-city 0
:henesys 898655980
:perion 1754196543
:ellinia 508846815
:nautilus 714441637
:sleepywood 615729202
:orbis 350970245
:el-nath 1897049096
:ludibrium 1290087592))
(defvar *chronostory-spawns* nil)
(defun chronostory-spawn-url (gid)
(format nil *chronostory-spawns-url-format* gid))
(defun find-first-empty-field (line)
"Upon receiving the csvs from google sheets, we need to find the first
'empty' header column. That column is the delimiter between two
separate csvs."
(loop for i from 0 below (- (length line) 1)
with comma-count = 0
when (char= (char line i) #\,)
do (incf comma-count)
when (and (char= (char line i) #\,)
(char= (char line (+ i 1)) #\,))
return comma-count))
(defun find-char-index-of-field (line field)
"Could be an off by one here?"
(loop for i from 0 below (length line)
with comma-count = 0
when (char= (char line i) #\,)
do (incf comma-count)
when (= comma-count field)
return i))
(defun second-half (line field)
(let* ((index (find-char-index-of-field line field))
(second-half (subseq line (+ 2 index))))
second-half))
(defun string-to-number-p (str)
(handler-case
(progn
(parse-integer str)
t)
(parse-error () nil)))
(defun csv-to-hash-tables (csv)
(let* ((keys (mapcar #'string-to-hash-table-key
(car csv)))
(result (make-array 0 :adjustable t :fill-pointer 0)))
(loop for row in csv
with mapname = ""
for hm = (pairhash keys row (dict))
when (let ((name (gethash "Monster" hm)))
(and (string-not-equal "" name)
(string-not-equal "-" name)
(string-not-equal "Monster" name)))
do (progn
(if (and (string-not-equal mapname "") (string-equal (gethash "MapName" hm) ""))
(setf (gethash "MapName" hm) mapname)
(setf mapname (gethash "MapName" hm)))
(vector-push-extend hm result)))
result))
(defun parse-sheet (sheet)
(let* ((lines (lines sheet))
(field (find-first-empty-field (car lines)))
(first-half (loop for line in lines
when (not (uiop:string-prefix-p ",,," line))
collect (let ((index (find-char-index-of-field line field)))
(subseq line 0 index))))
(second-half (loop for line in lines
for second-half = (second-half line field)
when (not (uiop:string-prefix-p ",,," second-half))
collect second-half))
(joined (string-join (concatenate 'list first-half second-half) #\Newline)))
(csv-to-hash-tables (cl-csv:read-csv joined))))
(defun refresh-spawn-data ()
(let ((spawn-data (pairhash
(mapcar #'car *chronostory-spawn-gids*)
(mapcar (lambda (pair)
(let* ((gid (cdr pair))
(data (drakma:http-request (chronostory-spawn-url gid))))
(uiop:println (concat "Requesting data for " (symbol-name (car pair))))
(parse-sheet data)))
*chronostory-spawn-gids*))))
(setf *chronostory-spawns* spawn-data)
(write-string-into-file
(shasht:write-json spawn-data nil)
"spawns.json"
:if-exists :overwrite
:if-does-not-exist :create)
spawn-data))
(defun reload-spawn-data ()
(let ((spawn-data (shasht:read-json (uiop:read-file-string "spawns.json" :if-does-not-exist nil))))
(setf *chronostory-spawns* spawn-data)
spawn-data))
(defun load-spawn-data ()
(if-not *chronostory-spawns*
(reload-spawn-data)
*chronostory-spawns*))