blob: 8849aa3e7ea6385c6e7bdb776d247b23aeaea7e2 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
;;;; 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)))
|