squib_plus 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 19f2f11b51db065d28f3be11cbc30293202dac9c1e9bee8b77408ab9b07d255b
4
+ data.tar.gz: 6ee1c5d23a051ff4341ddd6957e4e80f000c1ac94909e7beb3a1cfba3babce9f
5
+ SHA512:
6
+ metadata.gz: ff9ebe8819ff49e08f99dd6d6054e86f62297748341280c4ca291f84fde4a772cff2bd42f222f8fd0513d0c9b337c86740e6f8cb5624466c44a296292d54302f
7
+ data.tar.gz: 4b2d3ab40628d117c1c138f04d5170efb5d82fa32e43ca1479d8da48672a7018629aa64ecfc7df7ce91dd2f6973969f6afc18c6a619f2531bec01fb35743db7e
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ _output
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+ gemspec
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Squib
4
+ # Default card sizes for use like
5
+ # Squib::Deck.new(**Squib.card_size(:bridge))
6
+ #
7
+ # Note that each of these has 0.25in extra compared
8
+ # to the real-world dimensions of the card in order
9
+ # to account for bleed.
10
+ @@card_sizes = {
11
+ bridge: { width: '2.5in', height: '3.75in' },
12
+ business: { width: '2.25in', height: '3.75in' },
13
+ divider: { width: '3.25in', height: '3.75in' },
14
+ domino: { width: '2in', height: '3.75in' },
15
+ euro_poker: { width: '2.73in', height: '3.71in' },
16
+ euro_square: { width: '3.01in', height: '3.01in' },
17
+ jumbo: { width: '3.75in', height: '5.75in' },
18
+ micro: { width: '1.5in', height: '2in' },
19
+ mini: { width: '2in', height: '2.75in' },
20
+ poker: { width: '2.75in', height: '3.75in' },
21
+ mint_tin: { width: '2.3in', height: '3.71in' },
22
+ small_square: { width: '2.75in', height: '2.75in' },
23
+ square: { width: '3.75in', height: '3.75in' },
24
+ tarot: { width: '2.75in', height: '5in' },
25
+ us_game: { width: '2.45in', height: '3.68in' }
26
+ }
27
+
28
+ def card_size(name, landscape: false)
29
+ dimensions = @@card_sizes.fetch name
30
+ dimensions = { width: dimensions[:height], height: dimensions[:width] } if landscape
31
+
32
+ { dpi: 300 }.merge dimensions
33
+ end
34
+ module_function :card_size
35
+ end
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'fileutils'
4
+ require 'mechanize'
5
+
6
+ module Squib
7
+ class Deck
8
+ def avatar(opts = {})
9
+ DSL::Avatar.new(self, __callee__).run(opts)
10
+ end
11
+ end
12
+
13
+ module DSL
14
+ # Add an avatar for placeholder art in your games
15
+ # using https://avatars.dicebear.com/. The image will
16
+ # be downloaded to your configured image directory if
17
+ # it doesn't already exist.
18
+ #
19
+ # Library can be male, female, human, identicon, initials,
20
+ # bottts, avataaars, jdenticon, gridy or micah.
21
+ #
22
+ # Seed can be any random string
23
+ #
24
+ # Example:
25
+ # avatar library: 'micah', seed: '1234'
26
+ class Avatar
27
+ attr_reader :dsl_method, :deck
28
+
29
+ def initialize(deck, dsl_method)
30
+ @deck = deck
31
+ @dsl_method = dsl_method
32
+ end
33
+
34
+ def self.accepted_params
35
+ %i[
36
+ library seed
37
+ x y width height
38
+ blend mask
39
+ crop_x crop_y crop_width crop_height
40
+ crop_corner_radius crop_corner_x_radius crop_corner_y_radius
41
+ flip_horizontal flip_vertical angle
42
+ id force_id data
43
+ range layout
44
+ placeholder
45
+ ]
46
+ end
47
+
48
+ def run(opts)
49
+ Dir.chdir(deck.img_dir) do
50
+ defaults = { library: 'avataaars' }
51
+ options = defaults.merge opts
52
+
53
+ # Extract the default svg options
54
+ range = Args.extract_range opts, deck
55
+ svg_args = Args.extract_svg_special opts, deck
56
+ paint = Args.extract_paint opts, deck
57
+ box = Args.extract_scale_box opts, deck
58
+ trans = Args.extract_transform opts, deck
59
+
60
+ deck.progress_bar.start('Loading Avatar(s)', range.size) do |bar|
61
+ range.each do |i|
62
+ library = options[:library]
63
+ seed = options[:seed][i]
64
+ next if seed.nil?
65
+
66
+ file = "avatar-#{library}-#{seed}.svg"
67
+
68
+ # Check if we need to download the image
69
+ unless File.exist?(file)
70
+ agent = Mechanize.new
71
+ agent.follow_meta_refresh = true
72
+ agent.keep_alive = false
73
+ agent.history.max_size = 10
74
+
75
+ response = agent.get_file("https://avatars.dicebear.com/api/#{library}/#{seed}.svg")
76
+ response = response.encode('ascii-8bit').force_encoding('utf-8')
77
+
78
+ File.open(file, 'w') { |f| f.write(response) }
79
+ end
80
+
81
+ deck.cards[i].svg(file, svg_args[i], box[i], paint[i], trans[i])
82
+ bar.increment
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'fileutils'
4
+
5
+ module Squib
6
+ class Deck
7
+ # Adds a card number to the bottom right of the card by default.
8
+ # Helps with tracking down a specific card in your spreadsheet in
9
+ # games with many unique cards.
10
+ def card_num(opts = {})
11
+ defaults = {
12
+ x: width - 100,
13
+ y: height - 100,
14
+ width: 50,
15
+ height: 50,
16
+ font: 'sans-serif',
17
+ font_size: 9,
18
+ color: '#000',
19
+ align: :center,
20
+ valign: :middle
21
+ }
22
+ range = Args.extract_range opts, self
23
+
24
+ # Index from 1
25
+ text(str: range.map { |i| i + 1 }, **(defaults.merge opts))
26
+ end
27
+
28
+ # Shortcut for save_sheet with defaults that make sense for Tabletop Simulator
29
+ def tts(opts = {})
30
+ defaults = { columns: 10, rows: 7, trim: 37.5 }
31
+ save_sheet(defaults.merge(opts))
32
+ end
33
+
34
+ # Shortcut for creating a Print-n-Play sheet using poker-sized cards
35
+ def pnp(opts = {})
36
+ cut_zone stroke_color: '#888'
37
+ defaults = {
38
+ trim: 37.5,
39
+ sprue: if opts[:rtl]
40
+ "#{File.dirname(__FILE__)}/sprues/letter_poker_tight_reverse.yml"
41
+ else
42
+ "#{File.dirname(__FILE__)}/sprues/letter_poker_tight.yml"
43
+ end
44
+ }
45
+ save_pdf(defaults.merge(opts))
46
+ end
47
+ end
48
+
49
+ require_relative 'deck/avatar'
50
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'mechanize'
4
+
5
+ module Squib
6
+ # gsheet allows you to load Deck data using Google Sheets.
7
+ #
8
+ # First, share your sheet using File > Publish to the web
9
+ # Select 'Entire document' and '.csv' as the format
10
+ # Copy the URL like
11
+ # https://docs.google.com/spreadsheets/d/e/2PACX-.../pub?output=csv
12
+ # ^^^^^^^^^
13
+ # The code you need to pass is the long ID after /d/e.
14
+ #
15
+ # If the sheet has multiple tabs, you can specify a later tab using the gid from
16
+ # the non-share URL like
17
+ # https://docs.google.com/spreadsheets/d/.../edit#gid=123456
18
+ # ^^^^^^
19
+ # The gid is at the end of the URL after #gid=
20
+ #
21
+ # Example:
22
+ # deck = Squib.gsheet('2PACX-...', 123456)
23
+ #
24
+ # Squib::Deck.new(cards: deck['name'].size) do
25
+ # ...
26
+ # end
27
+ #
28
+ # You can optionally specify the tab to use with the second argument
29
+ def gsheet(sheet_id, index = 0)
30
+ agent = Mechanize.new
31
+ response = agent.get_file("https://docs.google.com/spreadsheets/d/e/#{sheet_id}/pub?gid=#{index}&output=csv")
32
+ response = response.encode('ascii-8bit').force_encoding('utf-8')
33
+
34
+ Squib.csv data: response
35
+ end
36
+ module_function :gsheet
37
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'combine_pdf'
4
+
5
+ module Squib
6
+ # Merge PDFs together, collated for front/back printing
7
+ # Example:
8
+ # # Deck front
9
+ # Squib::Deck.new(cards: deck['name'].size) do
10
+ # ...
11
+
12
+ # pnp file: 'front.pdf'
13
+ # end
14
+
15
+ # # Deck back
16
+ # Squib::Deck.new(cards: deck['name'].size) do
17
+ # ...
18
+
19
+ # pnp file: 'back.pdf'
20
+ # end
21
+
22
+ # # Combine PnP
23
+ # Squib.combine_pdfs([
24
+ # { :front => "_output/front.pdf", :back => "_output/back.pdf" },
25
+ # ], "_output/pnp.pdf")
26
+ def combine_pdfs(sheets, file)
27
+ pdf = CombinePDF.new
28
+
29
+ sheets.each do |sheet|
30
+ front = CombinePDF.load(sheet[:front])
31
+
32
+ # Collate the back pages immediately after the relevant page,
33
+ # if a back-side is provided.
34
+ back = CombinePDF.load(sheet[:back]) if sheet.key?(:back)
35
+
36
+ i = 0
37
+ front.pages.each do |page|
38
+ pdf << page
39
+ pdf << back.pages[i] if sheet.key?(:back)
40
+
41
+ break if i == front.pages.count - 1
42
+
43
+ i += 1
44
+ end
45
+ end
46
+
47
+ pdf.save file
48
+ end
49
+ module_function :combine_pdfs
50
+ end
@@ -0,0 +1,42 @@
1
+ ---
2
+ sheet_width: 8.5in
3
+ sheet_height: 11in
4
+ card_width: 2.5in
5
+ card_height: 3.5in
6
+ cards:
7
+ - x: 0.5in
8
+ y: 0.225in
9
+ - x: 3in
10
+ y: 0.225in
11
+ - x: 5.5in
12
+ y: 0.225in
13
+ - x: 0.5in
14
+ y: 3.725in
15
+ - x: 3in
16
+ y: 3.725in
17
+ - x: 5.5in
18
+ y: 3.725in
19
+ - x: 0.5in
20
+ y: 7.225in
21
+ - x: 3in
22
+ y: 7.225in
23
+ - x: 5.5in
24
+ y: 7.225in
25
+ crop_line:
26
+ lines:
27
+ - type: :vertical
28
+ position: 0.5in
29
+ - type: :vertical
30
+ position: 3in
31
+ - type: :vertical
32
+ position: 5.5in
33
+ - type: :vertical
34
+ position: 8in
35
+ - type: :horizontal
36
+ position: 0.225in
37
+ - type: :horizontal
38
+ position: 3.725in
39
+ - type: :horizontal
40
+ position: 7.225in
41
+ - type: :horizontal
42
+ position: 10.725in
@@ -0,0 +1,42 @@
1
+ ---
2
+ sheet_width: 8.5in
3
+ sheet_height: 11in
4
+ card_width: 2.5in
5
+ card_height: 3.5in
6
+ cards:
7
+ - x: 5.5in
8
+ y: 0.225in
9
+ - x: 3in
10
+ y: 0.225in
11
+ - x: 0.5in
12
+ y: 0.225in
13
+ - x: 5.5in
14
+ y: 3.725in
15
+ - x: 3in
16
+ y: 3.725in
17
+ - x: 0.5in
18
+ y: 3.725in
19
+ - x: 5.5in
20
+ y: 7.225in
21
+ - x: 3in
22
+ y: 7.225in
23
+ - x: 0.5in
24
+ y: 7.225in
25
+ crop_line:
26
+ lines:
27
+ - type: :vertical
28
+ position: 0.5in
29
+ - type: :vertical
30
+ position: 3in
31
+ - type: :vertical
32
+ position: 5.5in
33
+ - type: :vertical
34
+ position: 8in
35
+ - type: :horizontal
36
+ position: 0.225in
37
+ - type: :horizontal
38
+ position: 3.725in
39
+ - type: :horizontal
40
+ position: 7.225in
41
+ - type: :horizontal
42
+ position: 10.725in
@@ -0,0 +1,5 @@
1
+ class String
2
+ def slug
3
+ downcase.strip.gsub(' ', '-').gsub(/[^\w-]/, '')
4
+ end
5
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Squib
4
+ # Subset a selection of cards based on some criteria. Can be passed
5
+ # directly into the range argument of other DSL functions.
6
+ #
7
+ # Example:
8
+ # gems = Squib.subset(deck['category'], -> (c) { c === 'gem' })
9
+ # text range: gems, str: deck['gem_num'], layout: 'gem_label'
10
+ #
11
+ # You can invert the match using matching: false
12
+ # This allows you to use a single criteria function for positive/negative
13
+ # matches.
14
+ def subset(column, criteria, matching: true)
15
+ sub = {}
16
+ column.each_with_index { |c, i| (sub[criteria.call(c)] ||= []) << i }
17
+
18
+ sub[matching]
19
+ end
20
+ module_function :subset
21
+ end
data/lib/squib_plus.rb ADDED
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'squib_plus/card_size'
4
+ require_relative 'squib_plus/deck'
5
+ require_relative 'squib_plus/string'
6
+ require_relative 'squib_plus/subset'
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = 'squib_plus'
5
+ s.version = '0.0.1'
6
+ s.files = `git ls-files -z`.split("\x0")
7
+
8
+ s.authors = ['Rob Newton']
9
+ s.summary = 'Extensions for Squib'
10
+ s.description = 'Helper functions extending the functionality of Squib'
11
+ s.email = 'robert@coinflip.games'
12
+ s.homepage = 'https://rubygems.org/gems/squib_plus'
13
+ s.license = 'MIT'
14
+ end
metadata ADDED
@@ -0,0 +1,55 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: squib_plus
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Rob Newton
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-11-05 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Helper functions extending the functionality of Squib
14
+ email: robert@coinflip.games
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - ".gitignore"
20
+ - Gemfile
21
+ - lib/squib_plus.rb
22
+ - lib/squib_plus/card_size.rb
23
+ - lib/squib_plus/deck.rb
24
+ - lib/squib_plus/deck/avatar.rb
25
+ - lib/squib_plus/google_sheets.rb
26
+ - lib/squib_plus/pdf.rb
27
+ - lib/squib_plus/sprues/letter_poker_tight.yml
28
+ - lib/squib_plus/sprues/letter_poker_tight_reverse.yml
29
+ - lib/squib_plus/string.rb
30
+ - lib/squib_plus/subset.rb
31
+ - squib_plus.gemspec
32
+ homepage: https://rubygems.org/gems/squib_plus
33
+ licenses:
34
+ - MIT
35
+ metadata: {}
36
+ post_install_message:
37
+ rdoc_options: []
38
+ require_paths:
39
+ - lib
40
+ required_ruby_version: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
45
+ required_rubygems_version: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: '0'
50
+ requirements: []
51
+ rubygems_version: 3.2.22
52
+ signing_key:
53
+ specification_version: 4
54
+ summary: Extensions for Squib
55
+ test_files: []