Yu-Gi-Oh! Deck Building and Card Inventory Management web interface written in Common Lisp, utilizing HTMX.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

473 lines
18KB

  1. #|
  2. src/models/ygoprodeck-classes.lisp
  3. Yu-Gi-Oh! Pro Deck Database Interface v2
  4. TODO Documentation; The diagram from schemacrawler would be nice.
  5. |#
  6. (in-package #:cl-deck-builder2.models.ygoprodeck.classes)
  7. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  8. ;; This is part of cardsv3 now.
  9. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  10. (defclass ygo-name-mixin ()
  11. ((name :accessor name-of
  12. :col-type :text
  13. :initarg :name))
  14. (:unique-keys name)
  15. (:documentation "A table for the names of all Yu-Gi-Oh! card properties.")
  16. (:metaclass registered-table-class))
  17. (defclass ygo-card-name (ygo-name-mixin)
  18. ()
  19. (:documentation "A table for the names of all Yu-Gi-Oh! card names. Dark Magician, Red-Eyes Black Dragon, and so on.")
  20. (:metaclass registered-table-class))
  21. (defclass ygo-card-type (ygo-name-mixin)
  22. ()
  23. (:documentation "A table for the types of Yu-Gi-Oh! cards. Spell, Flip Effect Monster, and so on.")
  24. (:metaclass registered-table-class))
  25. (defclass ygo-card-frame-type (ygo-name-mixin)
  26. ()
  27. (:documentation "A table for the frame types of Yu-Gi-Oh! cards. spell, effect_pendulum, and so on.")
  28. (:metaclass registered-table-class))
  29. (defclass ygo-card-race (ygo-name-mixin)
  30. ()
  31. (:documentation "A table for the races of Yu-Gi-Oh! cards. Insect, Beast, and so on.
  32. YGOProDeck stores the kind of spell card here too, like Equip or Continuous.")
  33. (:metaclass registered-table-class))
  34. (defclass ygo-card-archetype (ygo-name-mixin)
  35. ()
  36. (:documentation "A table for the archetypes of Yu-Gi-Oh! cards. Archfiend, Elemental HERO, A.I, and so on.")
  37. (:metaclass registered-table-class))
  38. (defclass ygo-card-attribute (ygo-name-mixin)
  39. ()
  40. (:documentation "A table for the attributes of Yu-Gi-Oh! cards. FIRE, WIND, EARTH, DARK, and so on.")
  41. (:metaclass registered-table-class))
  42. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  43. ;; YGO-CARD uses the PASSCODE as its UNIQUE ID, so you don't see it in
  44. ;; here, because it's added implicitly by MITO as ID slot.
  45. (defclass ygo-card ()
  46. ((id :accessor ygo-passcode-of
  47. :col-type :integer
  48. :primary-key t
  49. :initarg :id)
  50. (;; Cards *always* have a UNIQUE Name, and a description. Description isn't necessarily unique.
  51. name :accessor name-of
  52. :col-type :text
  53. :initarg :name)
  54. (desc :accessor ygo-desc-of
  55. :col-type :text
  56. :initarg :desc)
  57. ;; Some cards pre-date Archetype (e.g. Normal Monsters)
  58. (archetype :accessor ygo-archetype-of
  59. :col-type (or ygo-card-archetype :null)
  60. :initarg :archetype)
  61. ;; Some cards don't have Attribute/ATK/DEF/Level/Scale:
  62. ;; - Skill
  63. ;; - Spell
  64. ;; - Trap
  65. (attribute :accessor ygo-attribute-of
  66. :col-type (or ygo-card-attribute :null)
  67. :initarg :attribute)
  68. (atk :accessor ygo-atk-of
  69. :col-type (or :integer :null)
  70. :initarg :atk)
  71. (def :accessor ygo-def-of
  72. :col-type (or :integer :null)
  73. :initarg :def)
  74. (scale :accessor ygo-scale-of
  75. :col-type (or :integer :null)
  76. :initarg :scale)
  77. (level :accessor ygo-level-of
  78. :col-type (or :integer :null)
  79. :initarg :level)
  80. ;; Every card has a Frame-Type and a Race; Even Spell and Trap cards have a Race.
  81. ;; YGOProDeck uses this field to keep "Continuous", or "Field" ... yuck.
  82. (frame-type :accessor ygo-frame-type-of
  83. :col-type ygo-card-frame-type
  84. :initarg :frame-type)
  85. (race :accessor ygo-race-of
  86. :col-type ygo-card-race
  87. :initarg :race)
  88. ;; There's a conflict with the existing lisp builtin TYPE-OF. Call
  89. ;; it CARD-TYPE and access with CARD-TYPE-OF.
  90. (card-type :accessor ygo-card-type-of
  91. :col-type ygo-card-type
  92. :initarg :type))
  93. (:primary-key id)
  94. (:auto-pk nil)
  95. (:documentation "A table for most info of Yu-Gi-Oh! cards.
  96. This corresponds to the top level data for each card in the YGOProDeck API export.")
  97. (:metaclass registered-table-class))
  98. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  99. ;; From here onward, the code depends on YGO-CARD.
  100. (defclass ygo-card-misc-info ()
  101. ((passcode :accessor ygo-passcode-of
  102. :col-type ygo-card
  103. :initarg :passcode)
  104. (views :accessor ygo-views-of
  105. :col-type :integer
  106. :initform 0
  107. :initarg :views)
  108. (viewsweek :accessor ygo-viewsweek-of
  109. :col-type :integer
  110. :initform 0
  111. :initarg :viewsweek)
  112. (upvotes :accessor ygo-upvotes-of
  113. :col-type :integer
  114. :initform 0
  115. :initarg :upvotes)
  116. (downvotes :accessor ygo-downvotes-of
  117. :col-type :integer
  118. :initform 0
  119. :initarg :downvotes)
  120. (beta-id :accessor ygo-beta-id-of
  121. :col-type (or :integer :null)
  122. :initarg :beta--id)
  123. (beta-name :accessor ygo-beta-name-of
  124. :col-type (or ygo-name-mixin :null)
  125. :initarg :beta--name)
  126. (staple :accessor ygo-is-staple
  127. :col-type (or :integer :null)
  128. :initarg :staple)
  129. (konami-id :accessor ygo-konami-id-of
  130. :col-type :integer
  131. :initarg :konami--id)
  132. ;; This :INTEGER is just an index into this table, YGO-CARDS.
  133. (treated-as :accessor ygo-treated-as
  134. :col-type (or :null ygo-name-mixin)
  135. :initarg :treated--as)
  136. (has-effect :accessor ygo-has-effect
  137. :col-type (or :integer :null)
  138. :initarg :has--effect)
  139. (question-atk :accessor ygo-question-atk
  140. :col-type (or :integer :null)
  141. :initarg :question--atk)
  142. (question-def :accessor ygo-question-def
  143. :col-type (or :integer :null)
  144. :initarg :question--def)
  145. ;; When the TCG-DATE or OCG-DATE is NULL, that means it hasn't been released in TCG/OCG...
  146. (tcg-date :accessor ygo-tcg-date-of
  147. :col-type (or :timestamp :null)
  148. :initarg :tcg--date)
  149. (ocg-date :accessor ygo-ocg-date-of
  150. :col-type (or :timestamp :null)
  151. :initarg :ocg--date))
  152. (:metaclass registered-table-class)
  153. (:documentation "This corresponds to the \"misc_info\" data for each card in the YGOProDeck API export."))
  154. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  155. ;; Now Card Set Stuff
  156. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  157. (defclass ygo-set-name (ygo-name-mixin)
  158. ()
  159. (:documentation "A table for the sets of Yu-Gi-Oh! cards. Lightning Overdrive, 2021 Tin of Ancient Battles, and so on.")
  160. (:metaclass registered-table-class))
  161. (defclass ygo-set-code (ygo-name-mixin)
  162. ()
  163. (:documentation "A table for the set codes of Yu-Gi-Oh! cards. LOB-001, LOB-002, and so on.
  164. SET-CODE is the full code, e.g. \"LOB-001\".
  165. CODE is just \"001\" part, SET is just \"LOB\" part, both of which can be accessed by SPLIT-CODE.")
  166. (:metaclass registered-table-class))
  167. ;; Rarity => "Common", "Ghost Rare", "Ultra Rare", "Secret Rare"
  168. (defclass ygo-set-rarity (ygo-name-mixin)
  169. ()
  170. (:documentation "A table for the rarities of Yu-Gi-Oh! cards. Common, Secret Rare, Ghost Rare, and so on.")
  171. (:metaclass registered-table-class))
  172. ;; jq '.[]?.card_sets[]?.set_rarity_code' < /tmp/cardinfo.json | sort -h | uniq
  173. (defclass ygo-set-rarity-code (ygo-name-mixin)
  174. ()
  175. (:documentation "A table for the rarity codes of Yu-Gi-Oh! cards. (C), (SR), (GUR), etc.")
  176. (:metaclass registered-table-class))
  177. (defclass ygo-set-edition (ygo-name-mixin)
  178. ()
  179. (:documentation "A table for the editions of Yu-Gi-Oh! cards. 1st Edition, Unlimited, and so on.")
  180. (:metaclass registered-table-class))
  181. (defclass ygo-set ()
  182. ((passcode :accessor ygo-passcode-of
  183. :col-type ygo-card
  184. :initarg :passcode)
  185. (name :accessor name-of
  186. :col-type ygo-set-name
  187. :initarg :name)
  188. (code :accessor ygo-code-of
  189. :col-type ygo-set-code
  190. :initarg :code)
  191. (rarity :accessor ygo-rarity-of
  192. :col-type ygo-set-rarity
  193. :initarg :rarity)
  194. (rarity-code :accessor ygo-rarity-code--of
  195. :col-type ygo-set-rarity-code
  196. :initarg :rarity-code)
  197. (edition :accessor ygo-edition-of
  198. :col-type ygo-set-edition
  199. :initarg :edition)
  200. (url :accessor ygo-url-of
  201. :col-type :text
  202. :initarg :url)
  203. ;; PRICE is $X,XX * 100 => XXX,00 That way we don't have to store floats at all.
  204. ;;
  205. ;; Default set price is Half a Doll Hair (0.50$) if none supplied
  206. (price :accessor ygo-price-of
  207. :col-type :integer
  208. :initarg :price
  209. :initform 0.50
  210. :inflate #'currency-inflate
  211. :deflate #'currency-deflate))
  212. (:documentation "A table for the sets of Yu-Gi-Oh! cards.
  213. This corresponds to the \"card_sets\" field in the YGOProDeck API export.")
  214. (:metaclass registered-table-class))
  215. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  216. (defclass ygo-linkmarker ()
  217. ((passcode :accessor ygo-passcode-of
  218. :col-type ygo-card
  219. :initarg :passcode)
  220. (bottom :accessor ygo-linkmarker-bottom
  221. :col-type (or :null ygo-linkmarker-name)
  222. :initarg :bottom)
  223. (bottom-left :accessor ygo-linkmarker-bottom-left
  224. :col-type (or :null ygo-linkmarker-name)
  225. :initarg :bottom-left)
  226. (bottom-right :accessor ygo-linkmarker-bottom-right
  227. :col-type (or :null ygo-linkmarker-name)
  228. :initarg :bottom-right)
  229. (left :accessor ygo-linkmarker-left
  230. :col-type (or :null ygo-linkmarker-name)
  231. :initarg :left)
  232. (right :accessor ygo-linkmarker-right
  233. :col-type (or :null ygo-linkmarker-name)
  234. :initarg :right)
  235. (top :accessor ygo-linkmarker-top
  236. :col-type (or :null ygo-linkmarker-name)
  237. :initarg :top)
  238. (top-left :accessor ygo-linkmarker-top-left
  239. :col-type (or :null ygo-linkmarker-name)
  240. :initarg :top-left)
  241. (top-right :accessor ygo-linkmarker-top-right
  242. :col-type (or :null ygo-linkmarker-name)
  243. :initarg :top-right))
  244. (:metaclass registered-table-class)
  245. (:documentation "A table for Yu-Gi-Oh! Link Monster Link markers.
  246. This corresponds to the \"linkmarkers\" field in each card."))
  247. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  248. (defclass ygo-format ()
  249. ((passcode :accessor ygo-passcode-of
  250. :col-type (or :null ygo-format-name)
  251. :initarg :passcode)
  252. (common-charity :accessor ygo-common-charity-format
  253. :col-type (or :null ygo-format-name)
  254. :initarg :common-charity)
  255. (duel-links :accessor ygo-duel-links-format
  256. :col-type (or :null ygo-format-name)
  257. :initarg :duel-links)
  258. (edison :accessor ygo-edison-format
  259. :col-type (or :null ygo-format-name)
  260. :initarg :edison)
  261. (goat :accessor ygo-goat-format
  262. :col-type (or :null ygo-format-name)
  263. :initarg :goat)
  264. (ocg :accessor ygo-ocg-format
  265. :col-type (or :null ygo-format-name)
  266. :initarg :ocg)
  267. (ocg-goat :accessor ygo-ocg-goat-format
  268. :col-type (or :null ygo-format-name)
  269. :initarg :ocg-goat)
  270. (speed-duel :accessor ygo-speed-duel-format
  271. :col-type (or :null ygo-format-name)
  272. :initarg :speed-duel)
  273. (tcg :accessor ygo-tcg-format
  274. :col-type (or :null ygo-format-name)
  275. :initarg :tcg))
  276. (:metaclass registered-table-class)
  277. (:documentation "A table for Yu-Gi-Oh! rule formats.
  278. This corresponds to the \"formats\" field in the \"misc_info\" for each card.
  279. If the card is available in this format, e.g. listed under misc_info.formats \"TCG\", that means the card is allowed in TCG games. The YGO-TCG-FORMAT slot for this object would have a non-NIL YGO-FORMAT-NAME value."))
  280. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  281. (defclass ygo-banlist ()
  282. ((passcode :accessor ygo-passcode-of
  283. :col-type ygo-card
  284. :initarg :passcode)
  285. (ban-goat :accessor ygo-ban-goat
  286. :col-type (or :null ygo-banlist-name)
  287. :initarg :ban--goat)
  288. (ban-ocg :accessor ygo-ban-ocg
  289. :col-type (or :null ygo-banlist-name)
  290. :initarg :ban--ocg)
  291. (ban-tcg :accessor ygo-ban-tcg
  292. :col-type (or :null ygo-banlist-name)
  293. :initarg :ban--tcg))
  294. (:unique-keys passcode)
  295. (:metaclass registered-table-class)
  296. (:documentation "A table for Yu-Gi-Oh! rule banlist.
  297. This corresponds to the \"banlist_info\" field for each card."))
  298. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  299. (defclass ygo-alternative-artwork ()
  300. ((passcode :accessor ygo-passcode-of
  301. :col-type ygo-card
  302. :initarg :passcode)
  303. (alternate :accessor ygo-alternate-id-of
  304. :col-type ygo-card
  305. :initarg :alternate))
  306. (:metaclass registered-table-class)
  307. (:documentation "A table for Yu-Gi-Oh! alternative artwork.
  308. This corresponds to the \"card_images\" array for each card."))
  309. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  310. (defclass ygo-price ()
  311. ((passcode :accessor ygo-passcode-of
  312. :col-type ygo-card
  313. :initarg :passcode
  314. :deflate #'currency-deflate
  315. :inflate #'currency-inflate)
  316. (cardmarket-price :accessor ygo-cardmarket-price-of
  317. :col-type :integer
  318. :initarg :cardmarket--price
  319. :deflate #'currency-deflate
  320. :inflate #'currency-inflate)
  321. (tcgplayer-price :accessor ygo-tcgplayer-price-of
  322. :col-type :integer
  323. :initarg :tcgplayer--price
  324. :deflate #'currency-deflate
  325. :inflate #'currency-inflate)
  326. (ebay-price :accessor ygo-ebay-price-of
  327. :col-type :integer
  328. :initarg :ebay--price
  329. :deflate #'currency-deflate
  330. :inflate #'currency-inflate)
  331. (amazon-price :accessor ygo-amazon-price-of
  332. :col-type :integer
  333. :initarg :amazon--price
  334. :deflate #'currency-deflate
  335. :inflate #'currency-inflate)
  336. (coolstuffinc-price :accessor ygo-coolstuffinc-price-of
  337. :col-type :integer
  338. :initarg :coolstuffinc--price
  339. :deflate #'currency-deflate
  340. :inflate #'currency-inflate))
  341. (:metaclass registered-table-class)
  342. (:documentation "A table for Yu-Gi-Oh! pricing information. Represents the API information about Card Pricing. Encapsulates the following fields:
  343. - Passcode
  344. - CardMarket
  345. - TCGPlayer
  346. - eBay
  347. - Amazon
  348. - CoolStuffInc
  349. This corresponds to the \"card_prices\" array for each card."))
  350. ;; YGO-FORMAT-NAME, YGO-LINKMARKER-NAME, YGO-BANLIST-NAME,
  351. ;; YGO-SET-RARITY-CODE, and the like have moved to YGOPRODECK.FIELDS.
  352. (defclass ygo-set-item ()
  353. ((item :accessor item-of
  354. :initarg :item
  355. :col-type ygo-set)
  356. (variant :accessor variant-of
  357. :initarg :variant
  358. :col-type variant-condition)
  359. (qty :accessor qty-of
  360. :col-type :integer
  361. :initform 0
  362. :initarg :qty)
  363. (opt-qty :accessor opt-qty-of
  364. :col-type :integer
  365. :initform 0
  366. :initarg :opt-qty)
  367. (;; 10 cent buy price
  368. buy-price :accessor buy-price-of
  369. :col-type :integer
  370. :initform 0.10
  371. :initarg :buy-price
  372. :inflate #'currency-inflate
  373. :deflate #'currency-deflate)
  374. (;; 50 cent sell price
  375. sell-price :accessor sell-price-of
  376. :col-type :integer
  377. :initform 0.50
  378. :initarg :sell-price
  379. :inflate #'currency-inflate
  380. :deflate #'currency-deflate))
  381. (:metaclass registered-table-class)
  382. (:documentation "YGO-SET + VARIANT-CONDITION relationship table."))
  383. #|
  384. ;;;; models/ygoprodeck.lisp
  385. (defstruct ygoprodeck-item
  386. (:documentation "Represents the top level API information queried from YGOProDeck. Encapsulates the following fields: ~Passcode~,~Name~,~Type~, ~Frame Type~, ~Documentation~,~Race~,~ATK~, ~DEF~,~Level~,~Attribute~, and ~Archetype~."))
  387. (defstruct ygoprodeck-card-set
  388. (:documentation "Represents the API information about Card Sets. Encapsulates the following fields: ~Passcode~,~Name~,~Code~, ~Rarity~, ~Rarity-code~, and ~Price~."))
  389. (defstruct ygoprodeck-card-image
  390. (:documentation "Card images. We don't use this much."))
  391. (defstruct ygoprodeck-card-price
  392. (defun drop-table-ygoprodeck-data
  393. (:documentation "Destroy the table for this data."))
  394. (defun create-table-ygoprodeck-data
  395. (:documentation "Create the corresponding database structure for the YGOProDeck API data import."))
  396. (defun json-import-ygoprodeck-data
  397. (:arguments
  398. ((data "The data to be imported."))
  399. :documentation "Import the base API data (ATK, DEF,Level, ...) information from the Card Info API data."))
  400. (defun json-import-ygoprodeck-card-images
  401. (:arguments
  402. ((data "The data to be imported."))
  403. :documentation "Import the images information from the Card Info API data."))
  404. (defun json-import-ygoprodeck-card-prices
  405. (:arguments
  406. ((data "The data to be imported."))
  407. :documentation "Import the pricing information from the Card Info API data."))
  408. (defun json-import-ygoprodeck-card-sets
  409. (:arguments
  410. ((data "The data to be imported."))
  411. :documentation "Import the card set information from the Card Info API data."))
  412. (defun json-import-ygoprodeck-banlist-info
  413. (:arguments
  414. ((data "The data to be imported."))
  415. :documentation "Import the banlist information from the Card Info API data."))
  416. (defun json-import-ygoprodeck
  417. (:arguments
  418. ((json "The JSON query to iterate over. Response from YGOProDeck API."))
  419. :documentation "Import YGOProDeck data. Wraps the ~JSON-IMPORT-*~ functions."))
  420. (defun card-rarity-list
  421. (:documentation "List all card rarities."))
  422. (defun card-code-list
  423. (:documentation "List all card set codes."))
  424. |#