1
0

more robust and future-proof architecture

This commit is contained in:
Ninjananas
2024-09-03 20:05:42 +02:00
parent 7bdea04111
commit 677906b5a7
18 changed files with 416 additions and 84 deletions

10
.gitignore vendored
View File

@@ -1,7 +1,7 @@
_output/*.png
_output/*.pdf
_output/
~$*
.DS_Store
._graphics_compute_touch
layout.yml
_graphics
._graphics_extract_touch
._graphics_copy_touch
._graphics
._layouts

View File

@@ -1,9 +1,56 @@
all: deck.rb cards.xlsx ._graphics_compute_touch layout.yml config.yml
rake
common_deps := src/deck.rb data/cards.xlsx ._graphics_copy_touch ._graphics_extract_touch config.yml ._layouts/poker.yml
._graphics_compute_touch: graphics.svg
python extract.py
touch ._graphics_compute_touch
pnp := _output/pnp_A4.pdf
debug := _output/debug.pdf
showcase := _output/hand.png
full := _output/full/front/card_00.png
layout.yml: compute_layout.py
python compute_layout.py
.PHONY: all
all: $(pnp) $(debug) $(showcase) $(full)
.PHONY: pnp
pnp: $(pnp)
.PHONY: debug
debug: $(debug)
.PHONY: showcase
showcase: $(showcase)
.PHONY: full
full: $(full)
.PHONY: clean
clean:
rake clean
rm -r _output/*
rm -r ._layouts
rm -r ._graphics
rm ._graphics_copy_touch ._graphics_extract_touch
$(pnp): $(common_deps)
rake pnp
$(debug): $(common_deps)
rake debug
$(showcase): $(common_deps)
rake showcase
$(full): $(common_deps)
rake full
._graphics_extract_touch: $(wildcard graphics/bundled/*)
@ mkdir -p ._graphics
python scripts/extract_graphics.py $^
@ touch ._graphics_extract_touch
._graphics_copy_touch: $(wildcard graphics/stand-alone/*)
@ mkdir -p ._graphics
cp $^ ./._graphics/
@ touch ._graphics_copy_touch
._layouts/poker.yml: scripts/generate_layouts.py
python scripts/generate_layouts.py

View File

@@ -1,7 +1,33 @@
require 'squib'
require 'rake/clean'
task default: [:deck]
CLEAN.include('_output/*').exclude('_output/gitkeep.txt')
CLEAN.include('_graphics/*')
task :deck do
load 'deck.rb'
task default: [:pnp]
task all: [:debug, :showcase, :pnp, :full]
task :pnp do
Squib.enable_build_globally :pnp
load 'src/deck.rb'
Squib.disable_build_globally :pnp
end
task :debug do
Squib.enable_build_globally :debug
load 'src/deck.rb'
Squib.disable_build_globally :debug
end
task :showcase do
Squib.enable_build_globally :showcase
load 'src/deck.rb'
Squib.disable_build_globally :showcase
end
task :full do
Squib.enable_build_globally :full
load 'src/deck.rb'
Squib.disable_build_globally :full
end

View File

@@ -1 +0,0 @@
Keep this here so that Git knows to keep the _output directory on a fresh clone

View File

@@ -1,8 +1,6 @@
# Settings in the config.yml are overriding Squib's defaults. Anything in the main script will override this.
# Looking for DPI? It needs to be a parameter to Squib::Deck.new
#antialias: best #recommended. Only about 10% slower than fast
antialias: best #recommended. Only about 10% slower than fast
#antialias: default # set the anti-aliasing algorithm. default defers to the underlying graphics device. See http://www.cairographics.org/manual/cairo-cairo-t.html#cairo-antialias-t
# Text hints are used to show the boundaries of text boxes.
@@ -13,15 +11,15 @@
progress_bars: true
#Enable some custom colors that can be used in any color
#custom_colors:
# foo: '#abc'
custom_colors:
foo: '#abc'
# TODO party colors
#For reading image file command (e.g. png and svg), read from this directory instead
img_dir: _graphics
img_dir: ._graphics
# Use a SVG cairo back end, instead of an in-memory buffer
# backend: :memory # default
# backend: :svg # can create scalable pdfs, but rendering done at the printer level is not as good as Cairo.
backend: :memory
# Configure what text markup uses replace characters
# Below are the defaults
@@ -33,17 +31,7 @@ img_dir: _graphics
# en_dash: "\u2013"
# ellipsis: "\u2026"
# We can also disallow smart quotes and only allow explicit replacements with ``LaTeX-style'' quotes.
# smart_quotes: false
# By default, Squib warns when a text box is ellipsized. This can get verbose
# and can be turned off here
# warn_ellipsize: true # default
# warn_ellipsize: false # turn off entirely
# By default, Squib will warn if a PNG is being up-scaled.
# warn_png_scale: true # default
# warn_png_scale: false # turn off entirely
# How many pixels are in a "cell"?
# cell_px: 37.5 # default
smart_quotes: true
warn_ellipsize: true
warn_png_scale: true
# cell_px: <Defined in Ruby>

37
deck.rb
View File

@@ -1,37 +0,0 @@
require 'squib'
data = Squib.xlsx file: 'cards.xlsx', explode: 'quantite'
def icon_to_svg(icon)
icon.nil? ? nil : "icone_#{icon}.svg"
end
def rank_to_banner_svg(rank)
rank.nil? ? nil : (rank.start_with?('+') || rank.start_with?('-')) ? "banniere_mod.svg" : "banniere_rang.svg"
end
Squib::Deck.new(cards: data['nom'].size, layout: 'layout.yml') do
background color: 'white'
rect layout: 'cut'
#rect layout: 'safe'
icon_file = data['icone'].map { |icon| icon_to_svg(icon) }
svg file: icon_file, layout: 'icon'
banner_file = data['rang'].map { |rank| rank_to_banner_svg(rank) }
svg file: banner_file, layout: 'banner'
text str: data['rang'], layout: 'banner_text'
text str: data['nom'], layout: banner_file.map { |banner| banner.nil? ? 'name' : 'name_with_banner'}
alt_icon_file = data['icone_alt'].map { |icon| icon_to_svg(icon) }
svg file: alt_icon_file, layout: 'alt_icon'
alt_banner_file = data['rang_alt'].map { |rank| rank_to_banner_svg(rank) }
svg file: alt_banner_file, layout: 'alt_banner'
text str: data['rang_alt'], layout: 'alt_banner_text'
save_sheet columns: 4
save_pdf trim: 37.5, file: 'sheet.pdf'
hand range: [0, 7, 15, 25, 38, 17], trim: 37.5
end

5
docs/INSTALL.md Normal file
View File

@@ -0,0 +1,5 @@
# On Windows
- install Ruby https://rubyinstaller.org/
- install Squib with `gem install squib`
- install GNU Make

View File

Before

Width:  |  Height:  |  Size: 544 KiB

After

Width:  |  Height:  |  Size: 544 KiB

View File

View File

@@ -67,7 +67,7 @@ banner_text:
x: {BANNER_TEXT_X}
y: {BANNER_TEXT_Y}
width: {BANNER_TEXT_WIDTH}
height: 70
height: 2c
font: {BANNER_TEXT_FONT}
align: center
# hint: blue
@@ -105,14 +105,16 @@ cut:
y: {BLEED_MARGIN}
width: {TOTAL_WIDTH - (2 * BLEED_MARGIN)}
height: {TOTAL_HEIGHT - (2 * BLEED_MARGIN)}
stroke_color: gray
stroke_width: 2
safe:
x: {SAFE_MARGIN}
y: {SAFE_MARGIN}
width: {TOTAL_WIDTH - (2 * SAFE_MARGIN)}
height: {TOTAL_HEIGHT - (2 * SAFE_MARGIN)}
radius: 16
dash: 3 3
radius: 0.5c
dash: 3mm 3mm
"""
if __name__ == "__main__":

View File

@@ -2,10 +2,10 @@ from typing import *
import os
import subprocess
import re
import sys
GRAPHICS_FILE: str = "graphics.svg"
OUTPUT_DIR: str = "_graphics"
OUTPUT_DIR: str = "._graphics"
ID_REGEX: re.Pattern = re.compile("rbk_.*")
@@ -52,7 +52,9 @@ def export_objects(svg_file: str, object_ids: Iterable[str]) -> None:
if __name__ == "__main__":
if not os.path.isdir(OUTPUT_DIR):
os.mkdir(OUTPUT_DIR)
for graphics_file in sys.argv[1:]:
export_objects(
GRAPHICS_FILE,
filter(id_filter, get_all_ids(GRAPHICS_FILE)),
graphics_file,
filter(id_filter, get_all_ids(graphics_file)),
)

130
scripts/generate_layouts.py Normal file
View File

@@ -0,0 +1,130 @@
import os
from typing import *
OUTPUT_DIR = "._layouts"
# Card size info
TOTAL_HEIGHT = 30
TOTAL_WIDTH = 22
BLEED_MARGIN = 1
SAFE_MARGIN = 2
MAX_SAFE_X = TOTAL_WIDTH - SAFE_MARGIN
MAX_SAFE_Y = TOTAL_HEIGHT - SAFE_MARGIN
# Icon info
ICON_SIZE = 3.7
ICON_MARGIN_LEFT = 0
ICON_MARGIN_TOP = 0
ICON_X = ICON_MARGIN_LEFT + SAFE_MARGIN
ICON_Y = ICON_MARGIN_TOP + SAFE_MARGIN
# Banner info
BANNER_WIDTH = 2
BANNER_HEIGHT = 6
BANNER_X = ICON_X + ICON_SIZE + 0.3
BANNER_Y = 0
BANNER_TEXT_FONT = "\"ethnocentric 12\""
BANNER_TEXT_X = BANNER_X - 0.3
BANNER_TEXT_Y = BANNER_HEIGHT / 3
BANNER_TEXT_WIDTH = BANNER_WIDTH + 0.6
# Name info
NAME_X = ICON_X + ICON_SIZE
NAME_Y = SAFE_MARGIN + 0.1
NAME_WIDTH = MAX_SAFE_X - NAME_X
NAME_HEIGHT = 3.4
NAME_FONT = "\"ethnocentric 11\""
NAME_WITH_BANNER_X = BANNER_X + BANNER_WIDTH
NAME_WITH_BANNER_WIDTH = NAME_WIDTH - (NAME_WITH_BANNER_X - NAME_X)
def central_sym(x: int, y: int) -> Tuple[int, int]:
return TOTAL_WIDTH - x, TOTAL_HEIGHT - y
# Alternative objects
ALT_ICON_X, ALT_ICON_Y = central_sym(ICON_X, ICON_Y)
ALT_BANNER_X, ALT_BANNER_Y = central_sym(BANNER_X, BANNER_Y)
ALT_BANNER_TEXT_X, ALT_BANNER_TEXT_Y = central_sym(BANNER_TEXT_X, BANNER_TEXT_Y)
POKER_LAYOUT: str = f"""
icon:
x: {ICON_X}c
y: {ICON_Y}c
width: {ICON_SIZE}c
height: {ICON_SIZE}c
alt_icon:
extends: icon
x: {ALT_ICON_X}c
y: {ALT_ICON_Y}c
angle: 3.14159
banner:
x: {BANNER_X}c
y: {BANNER_Y}c
width: {BANNER_WIDTH}c
height: {BANNER_HEIGHT}c
banner_text:
x: {BANNER_TEXT_X}c
y: {BANNER_TEXT_Y}c
width: {BANNER_TEXT_WIDTH}c
height: 1c
font: {BANNER_TEXT_FONT}
align: center
# hint: blue
alt_banner:
extends: banner
x: {ALT_BANNER_X}c
y: {ALT_BANNER_Y}c
angle: 3.14159
alt_banner_text:
extends: banner_text
angle: 3.14159
x: {ALT_BANNER_TEXT_X}c
y: {ALT_BANNER_TEXT_Y}c
name:
x: {NAME_X}c
y: {NAME_Y}c
width: {NAME_WIDTH}c
height: {NAME_HEIGHT}c
align: center
valign: middle
font: {NAME_FONT}
# hint: red
name_with_banner:
extends: name
x: {NAME_WITH_BANNER_X}c
width: {NAME_WITH_BANNER_WIDTH}c
border:
x: 0
y: 0
width: {TOTAL_WIDTH}c
height: {TOTAL_HEIGHT}c
cut:
x: {BLEED_MARGIN}c
y: {BLEED_MARGIN}c
width: {TOTAL_WIDTH - (2 * BLEED_MARGIN)}c
height: {TOTAL_HEIGHT - (2 * BLEED_MARGIN)}c
stroke_color: gray
safe:
x: {SAFE_MARGIN}c
y: {SAFE_MARGIN}c
width: {TOTAL_WIDTH - (2 * SAFE_MARGIN)}c
height: {TOTAL_HEIGHT - (2 * SAFE_MARGIN)}c
radius: 0.4c
dash: 0.5mm 0.5mm
"""
if __name__ == "__main__":
if not os.path.isdir(OUTPUT_DIR):
os.mkdir(OUTPUT_DIR)
open(f"{OUTPUT_DIR}/poker.yml", "w").write(POKER_LAYOUT)

18
sprues/A4_debug.yml Normal file
View File

@@ -0,0 +1,18 @@
---
sheet_width: 11.692913385826772in
sheet_height: 8.267716535433072in
card_width: 2.75in
card_height: 3.75in
cards:
- x: 1.596456692913386in
"y": 0.25in
- x: 4.471456692913386in
"y": 0.25in
- x: 7.346456692913386in
"y": 0.25in
- x: 1.596456692913386in
"y": 4.125in
- x: 4.471456692913386in
"y": 4.125in
- x: 7.346456692913386in
"y": 4.125in

42
sprues/A4_poker.yml Normal file
View File

@@ -0,0 +1,42 @@
---
sheet_width: 8.267716535433072in
sheet_height: 11.692913385826772in
card_width: 2.5in
card_height: 3.5in
cards:
- x: 0.3838582677165361in
"y": 0.125in
- x: 2.883858267716536in
"y": 0.125in
- x: 5.383858267716536in
"y": 0.125in
- x: 0.3838582677165361in
"y": 3.625in
- x: 2.883858267716536in
"y": 3.625in
- x: 5.383858267716536in
"y": 3.625in
- x: 0.3838582677165361in
"y": 7.125in
- x: 2.883858267716536in
"y": 7.125in
- x: 5.383858267716536in
"y": 7.125in
crop_line:
lines:
- type: :vertical
position: 0.3838582677165361in
- type: :vertical
position: 2.883858267716536in
- type: :vertical
position: 5.383858267716536in
- type: :vertical
position: 7.883858267716536in
- type: :horizontal
position: 0.125in
- type: :horizontal
position: 3.625in
- type: :horizontal
position: 7.125in
- type: :horizontal
position: 10.625in

40
sprues/A4_poker_old.yml Normal file
View File

@@ -0,0 +1,40 @@
---
sheet_width: 11.692913385826772in
sheet_height: 8.267716535433072in
card_width: 2.5in
card_height: 3.5in
cards:
- x: 0.8464566929133861in
"y": 0.0in
- x: 3.346456692913386in
"y": 0.0in
- x: 5.846456692913386in
"y": 0.0in
- x: 8.346456692913385in
"y": 0.0in
- x: 0.8464566929133861in
"y": 3.5in
- x: 3.346456692913386in
"y": 3.5in
- x: 5.846456692913386in
"y": 3.5in
- x: 8.346456692913385in
"y": 3.5in
crop_line:
lines:
- type: :vertical
position: 0.8464566929133861in
- type: :vertical
position: 3.346456692913386in
- type: :vertical
position: 5.846456692913386in
- type: :vertical
position: 8.346456692913385in
- type: :vertical
position: 10.846456692913385in
- type: :horizontal
position: 0.0in
- type: :horizontal
position: 3.5in
- type: :horizontal
position: 7.0in

70
src/deck.rb Normal file
View File

@@ -0,0 +1,70 @@
require 'squib'
data = Squib.xlsx file: 'data/cards.xlsx', explode: 'quantite'
def icon_to_svg(icon)
icon.nil? ? nil : "icone_#{icon}.svg"
end
def rank_to_banner_svg(rank)
rank.nil? ? nil : (rank.start_with?('+') || rank.start_with?('-')) ? "banniere_mod.svg" : "banniere_rang.svg"
end
DPI = 300
CELL_PX = DPI / 8.0
BLEED = 0.125 # In inches
WIDTH = (2.5 + 2*BLEED) * DPI
HEIGHT = (3.5 + 2*BLEED) * DPI
Squib.configure cell_px: CELL_PX
Squib::Deck.new(
cards: data['nom'].size,
layout: '._layouts/poker.yml',
width: WIDTH,
height: HEIGHT,
dpi: DPI,
) do
background color: 'white'
build :debug do
rect layout: 'border', stroke_color: 'black'
rect layout: 'cut', dash: '0.5mm 0.5mm', stroke_color: 'red'
rect layout: 'safe', dash: '0.5mm 0.5mm', stroke_color: 'green'
end
icon_file = data['icone'].map { |icon| icon_to_svg(icon) }
svg file: icon_file, layout: 'icon'
banner_file = data['rang'].map { |rank| rank_to_banner_svg(rank) }
svg file: banner_file, layout: 'banner'
text str: data['rang'], layout: 'banner_text'
text str: data['nom'], layout: banner_file.map { |banner| banner.nil? ? 'name' : 'name_with_banner'}
alt_icon_file = data['icone_alt'].map { |icon| icon_to_svg(icon) }
svg file: alt_icon_file, layout: 'alt_icon'
alt_banner_file = data['rang_alt'].map { |rank| rank_to_banner_svg(rank) }
svg file: alt_banner_file, layout: 'alt_banner'
text str: data['rang_alt'], layout: 'alt_banner_text'
build :debug do
save_pdf sprue: 'sprues/A4_debug.yml', file: 'debug.pdf'
end
build :pnp do
rect layout: 'cut'
save_pdf sprue: 'sprues/A4_poker.yml', trim: inches(BLEED), file: 'pnp_A4.pdf'
end
build :showcase do
hand range: [0, 7, 15, 25, 38, 17], trim: inches(BLEED), trim_radius: inches(0.125), fill_color: 'black'
showcase range: [0, 7, 15, 25, 38, 17], trim: inches(BLEED), trim_radius: inches(0.125), fill_color: 'black'
end
build :full do
save_png dir: '_output/full/front'
end
end