;;;; arclade.lisp (in-package #:arclade) ;;; CONFIGURATION (defvar *config* nil) (defclass/std config () ((datastore-directory :ir :std (local-store-path)) (swank-port :std nil :doc "If set, swank is started on this port.") (host :std "0.0.0.0") (port :ir :std 8888) (steam-key :ia :std "") (steam-user-id :ia :std ""))) (defun config-from-file (path) "PATH should be a path to a file containing a PLIST suitable for passing as the keyword arguments to (MAKE-INSTANCE 'CONFIG ...)" (apply #'make-instance 'config (read-from-file path))) ;;; DATASTORE (defun local-store-path () (merge-pathnames "store/" (asdf:system-source-directory :arclade))) (defun init-db (config) "Initializes the data store with values from the CONFIG." (ensure-directories-exist (datastore-directory config)) (unless (boundp 'db:*store*) (make-instance 'db:mp-store :directory (datastore-directory config) :subsystems (list (make-instance 'db:store-object-subsystem))))) ;;; WEB SERVER (defvar *server* nil "The instance of the HTTP server") (lzb:provision-app () :title "Arclade" :version "0.1.0" :content-type "text/html") (defun start () (setf *config* (config-from-file #P"config.lisp")) (init-db *config*) (setf *server* (lzb:create-server)) (lzb:install-app *server* (lzb:app 'arclade)) (lzb:start-server *server*)) (defendpoint* :get "/" () () (with-page (:title "Records of Raditude") (:div :class "container" (dolist (game (all-games)) (let ((feats (feats-fulfilled game))) (unless (null feats) (:div :class "game" (:h2 (name game)) (:div :class "feats" (dolist (feat feats) (render feat)))))))))) (defendpoint* :get "/css/style.css" () () (pathname "./style.css"))