;;;; model.lisp (in-package :arclade) (defclass player () ((name :initarg :name :reader name) (games :accessor games))) (defclass game (db:store-object) ((name :initarg :name :reader name :index-type idx:string-unique-index :index-reader game-with-name :index-values all-games) (rating :accessor rating) (playtime :accessor playtime) (icon-url :accessor icon-url) (last-played :accessor last-played)) (:metaclass db:persistent-class)) (defmethod print-object ((object game) stream) (print-unreadable-object (object stream :type t :identity t) (princ (name object) stream))) (defclass steam-game (game) ((appid :initarg :appid :reader appid :index-type idx:unique-index :index-initargs (:test #'equal) :index-reader steam-game-with-appid)) (:metaclass db:persistent-class)) (defclass feat (db:store-object) ((game :reader game :initarg :game :initform (error "Feats must belong to a GAME.") :type game :index-type idx:hash-index :index-reader feats-for-game :documentation "Game object to which this feat belongs.") (name :initarg :name :reader name :type string :initform "" :documentation "Optional name of the feat.") (fulfillment :initarg :fulfillment :initform nil :accessor fulfillment :documentation "Ideally a universal time when the feat was fulfilled. If nil, implies the feat is yet to be fulfilled.") (description :initarg :description :accessor description :initform "" :type string :documentation "Free text feat flattery.")) (:metaclass db:persistent-class) (:documentation "Base class for a notable event performed in GAME. Example: Castlevania - 2003-10-31 (guess) Defeated Dracula and finished the game!")) (defclass score (feat) ((points :initarg :points :accessor points)) (:metaclass db:persistent-class) (:documentation "Feat subclass specific to score based games.")) (defclass steam-achievement (feat) ((icongray :accessor icongray) (icon :accessor icon) (apiname :accessor apiname)) (:metaclass db:persistent-class) (:documentation "Feat with Steam specific slots.")) (defmethod print-object ((object steam-achievement) stream) (print-unreadable-object (object stream :type t :identity t) (princ (name object) stream))) (defgeneric render (obj) (:documentation "make html for thing")) (defmethod render ((obj steam-achievement)) (with-slots (name description fulfillment icon icongray) obj (with-html (:div :class "feat" (:div (:img :src icon)) (:div (:div (:b name)) (:div description) (:div (:i (format-time fulfillment)))))))) ;;; "queries" (defun feats-fulfilled (game) (remove-if-not #'fulfillment (feats-for-game game)))