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.

137 lines
5.6KB

  1. #|
  2. Conceptually, The Label Maker is very similar to the DRAW component of The Deck Builder.
  3. We currently support Avery 5160 and ULINE S-20246 labels.
  4. |#
  5. (in-package #:cl-user)
  6. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  7. ;; This package doesn't touch the DB ... yet
  8. (defpackage #:cl-deck-builder2.models.label-maker
  9. (:use :cl)
  10. (:import-from #:cl-deck-builder2.toolkit
  11. #:latex-escape)
  12. (:export #:latex-label
  13. #:latex-label-page
  14. #:latex-label-uline-s-20247
  15. #:latex-label-avery-5160
  16. #:render-page))
  17. (in-package #:cl-deck-builder2.models.label-maker)
  18. (defclass latex-label ()
  19. ((barcode :accessor latex-label-barcode
  20. :initform nil
  21. :initarg :barcode)
  22. (description :accessor latex-label-description
  23. :initform nil
  24. :initarg :description)
  25. (price :accessor latex-label-price
  26. :initform nil
  27. :initarg :price))
  28. (:documentation "An individual LaTeX label. Encapsulate metadata for a particular label."))
  29. (defclass latex-label-page ()
  30. ((;; List of LATEX-LABEL content
  31. labels :accessor latex-label-page-labels
  32. :initarg :page-labels
  33. :initform '())
  34. (;; Number of Labels this page thinks it has
  35. labels-length :accessor latex-label-page-labels-length
  36. :initarg :labels-length
  37. :initform 0)
  38. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  39. ;; Templates
  40. (;; Template for this page
  41. label-template :accessor latex-label-label-template
  42. :initform nil
  43. :initarg :label-template)
  44. (;; Header template for this page
  45. header-template :accessor latex-label-header-template
  46. :initform #P"latex/header.tex"
  47. :initarg :header-template))
  48. (:documentation "Class for a LaTeX Label Page, which encapsulates label information and additional output templating information."))
  49. (defclass latex-label-uline-s-20247 (latex-label-page)
  50. ((labels-length :initform 32)
  51. (label-template :initform #P"latex/ULINE-S-20247.tpl.tex")))
  52. (defclass latex-label-avery-5160 (latex-label-page)
  53. ((labels-length :initform 30)
  54. (label-template :initform #P"latex/Avery-5160.tpl.tex")))
  55. (defmethod initialize-instance :after ((page latex-label-page) &rest initargs &key csv &allow-other-keys)
  56. (declare (ignore initargs))
  57. (when csv
  58. (initialize-with-csv page csv)))
  59. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  60. (defmethod add-label ((page latex-label-page) (label latex-label))
  61. "Add a LABEL to PAGE."
  62. (push label (latex-label-page-labels page)))
  63. (defmethod initialize-with-csv ((page latex-label-page) pathspec)
  64. "Create LATEX-LABEL information for this LATEX-LABEL-PAGE by reading CSV information from PATHSPEC."
  65. (let ((csv (cl-csv:read-csv pathspec)))
  66. (loop for i from 1 upto (latex-label-page-labels-length page) do
  67. (destructuring-bind (label-no description price barcode)
  68. (elt csv i)
  69. (declare (ignore label-no))
  70. (when (> (length description) 0)
  71. (barcode-png barcode)
  72. (let ((label (ignore-errors
  73. (make-instance 'latex-label
  74. :barcode barcode
  75. :description (latex-escape description)
  76. :price (cl-ppcre:regex-replace "\\$" price "\\\\$")))))
  77. (add-label page label)))))))
  78. (defmethod render-page ((page latex-label-page))
  79. "Use Djula to render the LATEX-LABEL-LABEL-TEMPLATE."
  80. (cl-deck-builder2.view:render (latex-label-label-template page)
  81. (list :labels (latex-label-page-labels page))))
  82. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  83. (defun label-info (&optional t-or-nil)
  84. (let ((arg (if t-or-nil "true" "false")))
  85. (format nil "\LabelGrid~a\LabelInfo~a%%~%" arg arg)))
  86. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  87. ;; TODO (defclass barcode () ())
  88. (defun barcode-png (barcode &optional (directory #P"/tmp/labels/") (size "1x30"))
  89. (ensure-directories-exist directory)
  90. (let* ((barcode (etypecase barcode
  91. (string barcode)
  92. (integer (princ-to-string barcode))))
  93. (output (merge-pathnames
  94. (make-pathname :name barcode :type "png")
  95. (probe-file directory))))
  96. (unless (probe-file output)
  97. (and
  98. (> (length barcode) 0)
  99. (multiple-value-bind (stdout stderr rc)
  100. (inferior-shell:run
  101. `("ZXingWriter" -size ,size
  102. ,(case (length barcode)
  103. ;; 12 and 11 digit barcodes for products in store on the shelves usually - UPC-A
  104. ((12 11) 'UPC-A)
  105. ;; 10 digit barcodes for "fake" Amazon ASIN "X0037THWV7"
  106. (10 'Code128)
  107. ;; Not sure why we have UPC-E in here
  108. ;; but presumbly we have encountered
  109. ;; products with a 6 digit barcode...
  110. (6 'UPC-E)
  111. ;; Treat everything else as 13 digit
  112. ;; international EAN-13 barcodes like
  113. ;; stuff from Pokemon Stores:
  114. ;; 8206508090648
  115. (t 'EAN-13))
  116. ,barcode
  117. ,output))
  118. (declare (ignore stdout stderr))
  119. (eq rc 0))
  120. (probe-file output)))))