106 lines
3.9 KiB
Common Lisp
106 lines
3.9 KiB
Common Lisp
(in-package :lispostory)
|
|
|
|
(define-data-source spawn)
|
|
|
|
(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))
|
|
|
|
(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))))
|
|
|
|
(defmethod refresh ((ds spawn-data-source))
|
|
(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 (cache ds) spawn-data)
|
|
(write-string-into-file
|
|
(shasht:write-json spawn-data nil)
|
|
(file-path ds)
|
|
:if-exists :overwrite
|
|
:if-does-not-exist :create)
|
|
spawn-data))
|