# cl-deck-builder2

## About

This is a project to...

- Build TCG decks: "The Deck Builder"
- Keep track of TCG inventory: "The Inventory Manager"
- Support sale of TCG Inventory via "The Deck Builder"

It's a [Caveman2](https://github.com/fukamachi/caveman) web app, written in [Common Lisp](https://lisp-lang.org/).

The entire application may be built and run inside a [Docker](https://www.docker.com/) container.

You may access a live instance at [https://phntsm.ddns.net/](https://phntsm.ddns.net/).

## Usage

There are three components to this project. "The Inventory Manager",
"The Deck Builder," and "The User Interface". The Deck Builder sources
in-stock products from the Inventory Manager. When the Deck Builder
constructs a Deck, it keeps a record of which cards are located in
which decks. When a Deck is purchased, this information can be updated
via a web interface. The User Interface is a convenient front-end.

The project may be used by loading a Docker image, loading the code
directly into a Lisp sytem like [SBCL](http://sbcl.org/), or using a
development environment like [Portacle](https://portacle.github.io/).

Once loaded, follow the code below to start the development
environment, or, if you're using the Docker image, simply type:

```bash
% make docker-build
% make docker-run
```

## Installation

First, set up [SBCL](http://sbcl.org/) and [Quicklisp](https://www.quicklisp.org/beta/).

If you're using [Portacle](https://portacle.github.io/), you should be all set already, just clone the repository.

Clone the master repository from
[http://phntsm.ddns.net/git/cl-deck-builder.git/](http://phntsm.ddns.net/git/cl-deck-builder.git/):

```bash
% cd ~/quicklisp/local-projects/
git clone http://phntsm.ddns.net/git/cl-deck-builder.git/
```

```lisp
;; You may have to push whatever directory you're in to *LOCAL-PROJECT-DIRECTORIES*
(push #P"~/code/cl-deck-builder2/" ql:*local-project-directories*)

;; Load cl-deck-builder2 and tests
(ql:quickload '(:cl-deck-builder2 :cl-deck-builder2-test))

;; cl-deck-builder2.asd finds src/package.lisp which contains package
;; definition - switch to this package for development.
(in-package :cl-deck-builder2)

;; Start the server:
;; in src/main.lisp we define a custom function, MY/START, that will
;; INVOKE-RESTART if the server is already running.
;;
;; IPv4
(my/start :address "0.0.0.0" :port 5001 :server :woo)
;; IPv6
(my/start :address "::" :port 5001 :server :woo)

;; For development session:
(use-package '(:cl-deck-builder2.db
               :cl-deck-builder2.draw
               :cl-deck-builder2.models
               :cl-deck-builder2.toolkit
               :cl-deck-builder2-test))
```

### Requirements

You'll need Quicklisp, and the dependencies listed in the ASDF System
Definition file, as well as the following system libraries installed.

```bash
  # Install Software
  % apt install build-essential git jq sbcl
  % apt install nginx fcgiwrap libev-dev sqlite3 libsqlite3-dev collectd imagemagick ruby ruby-sidekiq

  # For source code hosting
  % apt install cgit python3-pygments python3-markdown
```

- [What is build-essential Ubuntu, how to install and use it?](https://linuxhint.com/install-build-essential-ubuntu/)
- [git](https://git-scm.com/): Version Control
- [jq](https://jqlang.github.io/jq/): Parsin JSON files on the command line
- [SBCL](http://sbcl.org/): Lisp Implementation
- [NGINX](https://www.nginx.com/): Web Server for HTTP, HTTPS, IPv4, IPv6, other services can be forwarded behind NGINX as well
- [fcgiwrap](https://www.nginx.com/resources/wiki/start/topics/examples/fcgiwrap/): Simple FastCGI wrapper for CGI scripts (The project runs as a CGI script)
- [libev](http://software.schmorp.de/pkg/libev.html): Event loop used by [woo](https://github.com/fukamachi/woo)
- [sqlite3](https://www.sqlite.org/index.html): In-memory database store
- [collectd](https://collectd.org/): collectd is a daemon which collects system and application performance metrics periodically and provides mechanisms to store the values in a variety of ways, for example in RRD files. This also nets us [RRDtool](https://oss.oetiker.ch/rrdtool/) which we can use for charts and graphs.
- [ImageMagick](https://www.imagemagick.org/): We use this to generate deck images and other various image manipulations.
- [Ruby](https://www.ruby-lang.org/en/): We use the [Sidekiq](https://sidekiq.org/) job scheduler, which is written in Ruby.

You may want to set up [cgit](https://git.zx2c4.com/cgit/) git web.

There is also a `Dockerfile` with a `Makefile`.

## Author

_Bubblegumdrop <staticsunn@gmail.com>_

## Copyright

Copyright (c) 2024 Bubblegumdrop

## License

GPLv3+

## Localization Workflow

`lisp.pot` contains the string to translate that were extracted from
the `.lisp` files.

`djula.pot` contains the strings to transtlate that were extracted
from the djula templates.

gettext is the default translation engine.

### Update Translations

To build the translations:

    # Extract all {_ ... _} sequences from Djula templates
    make locale/templates/LC_MESSAGES/djula.pot

    # Extract all (_ ... _) sequences from LISP code
    make locale/templates/LC_MESSAGES/lisp.pot

    # Produce combined project template for translation
    make locale/templates/LC_MESSAGES/cl-deck-builder2.pot

    ... make your translation edits to cl-deck-builder2.pot ...

### Compile Translations

To Produce the `.mo` files, add your language to `LOCALES` in the
`Makefile` then update the translations with the `tr` target:

    LOCALES := en_US ja_JP

    # Produce the translations
    make tr

The default `LANG` is currently `en_US` in `view.lisp`:

    (defun render (template-path &optional env (lang "en_US"))
    "Use Djula to render a template."
    (let ((template (gethash template-path *template-registry*)))
        (unless template
        (setf template (djula:compile-template* (princ-to-string template-path)))
        (setf (gethash template-path *template-registry*) template))
        (with-locale (lang)
        (apply #'djula:render-template*
                template nil
                env))))

## TODO

See [todo.md](doc/todo.md)
