Finished CSV feature
parent
501dc417d0
commit
04b55d8b32
|
|
@ -1,5 +1,6 @@
|
|||
# Squib CHANGELOG
|
||||
|
||||
# Added a `csv` command that works just like `xslx`. Uses Ruby's CSV inside, with some extra checking and warnings.
|
||||
# Custom layouts now support loading & merging multiple Yaml files! Updated README, docs, and sample to document it.
|
||||
# Built-in layouts! Currently we support `hand.yml` and `playing-card.yml`. Documented in the `layouts.rb` sample.
|
||||
# `text` now returns the ink extent rectangle of the rendered text. Updated docs and sample to document it.
|
||||
|
|
|
|||
10
README.md
10
README.md
|
|
@ -4,7 +4,7 @@ Squib is a Ruby [DSL](http://en.wikipedia.org/wiki/Domain-specific_language) for
|
|||
* A concise set of rules for laying out your cards
|
||||
* Loading PNGs and SVGs using [Cairo](http://cairographics.org/)
|
||||
* Complex text rendering using [Pango](http://www.pango.org/)
|
||||
* Reading `.xlsx` files
|
||||
* Reading `xlsx` and `csv` files
|
||||
* Basic shape drawing
|
||||
* Rendering decks to PNGs and PDFs
|
||||
* Data-driven layouts
|
||||
|
|
@ -255,6 +255,14 @@ See the `custom_config` sample found [here](https://github.com/andymeneely/squib
|
|||
|
||||
{include:file:samples/custom_config.rb}
|
||||
|
||||
## Importing from Excel and CSV
|
||||
|
||||
Squib supports importing data from `xlsx` files and `csv` files. These methods are column-based, which means that they assume you have a header row in your table, and that header row will define the column. Squib will return a `Hash` of `Arrays` correspoding to each row. Warnings are thrown on things like duplicate columns. See the `excel.rb` and the `csv_import.rb` sample found [here](https://github.com/andymeneely/squib/tree/master/samples/).
|
||||
|
||||
{include:file:samples/excel.rb}
|
||||
|
||||
Of course, you can always import your game data other ways using just Ruby. There's nothing special about Squib's methods other than their convenience.
|
||||
|
||||
## Making Squib Verbose
|
||||
|
||||
By default, Squib's logger is set to WARN, but more fine-grained logging is embedded in the code. To set the logger, just put this at the top of your script:
|
||||
|
|
|
|||
|
|
@ -63,13 +63,26 @@ module Squib
|
|||
def csv(opts = {})
|
||||
opts = Squib::SYSTEM_DEFAULTS.merge(opts)
|
||||
opts = Squib::InputHelpers.fileify(opts)
|
||||
hash = {}
|
||||
csv = CSV.open(opts[:file], headers: true, converters: :numeric).read
|
||||
|
||||
table = CSV.read(opts[:file], headers: true, converters: :numeric)
|
||||
check_duplicate_csv_headers(table)
|
||||
hash = Hash.new
|
||||
table.headers.each do |header|
|
||||
hash[header.to_s] ||= table[header]
|
||||
end
|
||||
return hash
|
||||
end
|
||||
module_function :csv
|
||||
|
||||
# Check if the given CSV table has duplicate columns, and throw a warning
|
||||
# @api private
|
||||
def check_duplicate_csv_headers(table)
|
||||
if table.headers.size != table.headers.uniq.size
|
||||
dups = table.headers.select{|e| table.headers.count(e) > 1 }
|
||||
Squib.logger.warn "CSV duplicated the following column keys: #{dups.join(',')}"
|
||||
end
|
||||
end
|
||||
module_function :check_duplicate_csv_headers
|
||||
|
||||
class Deck
|
||||
|
||||
# Convenience call on deck goes to the module function
|
||||
|
|
|
|||
|
|
@ -13,5 +13,8 @@ Squib::Deck.new(cards: 2) do
|
|||
# You can also specify the sheet, starting at 0
|
||||
data = xlsx file: 'sample.xlsx', sheet: 2
|
||||
|
||||
save format: :png, prefix: 'sample_excel_'
|
||||
save format: :png, prefix: 'sample_csv_'
|
||||
end
|
||||
|
||||
# CSV is also a Squib-module-level function, so this also works:
|
||||
data = Squib.csv file: 'sample.csv'
|
||||
|
|
@ -2,11 +2,30 @@ require 'spec_helper'
|
|||
|
||||
describe Squib::Deck do
|
||||
context '#csv' do
|
||||
# it 'loads basic csv data' do
|
||||
# expect(Squib.csv(file: csv_file('basic.csv'))).to eq({
|
||||
# 'h1' => [1, 3],
|
||||
# 'h2' => [2, 4]
|
||||
# })
|
||||
# end
|
||||
it 'loads basic csv data' do
|
||||
expect(Squib.csv(file: csv_file('basic.csv'))).to eq({
|
||||
'h1' => [1, 3],
|
||||
'h2' => [2, 4]
|
||||
})
|
||||
end
|
||||
|
||||
it 'collapses duplicate columns and warns' do
|
||||
expect(Squib.logger).to receive(:warn)
|
||||
.with('CSV duplicated the following column keys: h1,h1')
|
||||
expect(Squib.csv(file: csv_file('dup_cols.csv'))).to eq({
|
||||
'h1' => [1, 3],
|
||||
'h2' => [5, 7],
|
||||
'H2' => [6, 8],
|
||||
'h3' => [9, 10],
|
||||
})
|
||||
end
|
||||
|
||||
it 'handles spaces properly' do
|
||||
expect(Squib.csv(file: csv_file('with_spaces.csv'))).to eq({
|
||||
'With Spaces' => ['a b c ', 3],
|
||||
'h2' => [2, 4],
|
||||
'h3' => [3, nil]
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
h1,h1,h2,H2,h3
|
||||
1,2,5,6,9
|
||||
3,4,7,8,10
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
With Spaces,h2,h3
|
||||
a b c , 2,3
|
||||
3 ,4
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
cairo: save([])
|
||||
cairo: set_source_color([#<Cairo::Color::RGB: @alpha=1.0, @red=1.0, @green=1.0, @blue=1.0>])
|
||||
cairo: paint([])
|
||||
cairo: restore([])
|
||||
cairo: save([])
|
||||
cairo: set_source_color([#<Cairo::Color::RGB: @alpha=1.0, @red=1.0, @green=1.0, @blue=1.0>])
|
||||
cairo: paint([])
|
||||
cairo: restore([])
|
||||
cairo: save([])
|
||||
cairo: set_source_color([#<Cairo::Color::RGB: @alpha=1.0, @red=0.0, @green=0.0, @blue=0.0>])
|
||||
cairo: translate([250, 55])
|
||||
cairo: rotate([0])
|
||||
cairo: translate([-250, -55])
|
||||
cairo: move_to([250, 55])
|
||||
pango: font_description=([])
|
||||
pango: text=([""])
|
||||
pango: wrap=([#<Pango::Layout::WrapMode word-char>])
|
||||
pango: ellipsize=([#<Pango::Layout::EllipsizeMode end>])
|
||||
pango: alignment=([#<Pango::Layout::Alignment left>])
|
||||
pango: justify=([false])
|
||||
pango: spacing=([0])
|
||||
cairo: update_pango_layout([MockDouble])
|
||||
cairo: update_pango_layout([MockDouble])
|
||||
cairo: show_pango_layout([MockDouble])
|
||||
cairo: restore([])
|
||||
cairo: save([])
|
||||
cairo: set_source_color([#<Cairo::Color::RGB: @alpha=1.0, @red=0.0, @green=0.0, @blue=0.0>])
|
||||
cairo: translate([250, 55])
|
||||
cairo: rotate([0])
|
||||
cairo: translate([-250, -55])
|
||||
cairo: move_to([250, 55])
|
||||
pango: font_description=([])
|
||||
pango: text=([""])
|
||||
pango: wrap=([#<Pango::Layout::WrapMode word-char>])
|
||||
pango: ellipsize=([#<Pango::Layout::EllipsizeMode end>])
|
||||
pango: alignment=([#<Pango::Layout::Alignment left>])
|
||||
pango: justify=([false])
|
||||
pango: spacing=([0])
|
||||
cairo: update_pango_layout([MockDouble])
|
||||
cairo: update_pango_layout([MockDouble])
|
||||
cairo: show_pango_layout([MockDouble])
|
||||
cairo: restore([])
|
||||
cairo: save([])
|
||||
cairo: set_source_color([#<Cairo::Color::RGB: @alpha=1.0, @red=0.0, @green=0.0, @blue=0.0>])
|
||||
cairo: translate([65, 65])
|
||||
cairo: rotate([0])
|
||||
cairo: translate([-65, -65])
|
||||
cairo: move_to([65, 65])
|
||||
pango: font_description=([])
|
||||
pango: text=([""])
|
||||
pango: wrap=([#<Pango::Layout::WrapMode word-char>])
|
||||
pango: ellipsize=([#<Pango::Layout::EllipsizeMode end>])
|
||||
pango: alignment=([#<Pango::Layout::Alignment left>])
|
||||
pango: justify=([false])
|
||||
pango: spacing=([0])
|
||||
cairo: update_pango_layout([MockDouble])
|
||||
cairo: update_pango_layout([MockDouble])
|
||||
cairo: show_pango_layout([MockDouble])
|
||||
cairo: restore([])
|
||||
cairo: save([])
|
||||
cairo: set_source_color([#<Cairo::Color::RGB: @alpha=1.0, @red=0.0, @green=0.0, @blue=0.0>])
|
||||
cairo: translate([65, 65])
|
||||
cairo: rotate([0])
|
||||
cairo: translate([-65, -65])
|
||||
cairo: move_to([65, 65])
|
||||
pango: font_description=([])
|
||||
pango: text=([""])
|
||||
pango: wrap=([#<Pango::Layout::WrapMode word-char>])
|
||||
pango: ellipsize=([#<Pango::Layout::EllipsizeMode end>])
|
||||
pango: alignment=([#<Pango::Layout::Alignment left>])
|
||||
pango: justify=([false])
|
||||
pango: spacing=([0])
|
||||
cairo: update_pango_layout([MockDouble])
|
||||
cairo: update_pango_layout([MockDouble])
|
||||
cairo: show_pango_layout([MockDouble])
|
||||
cairo: restore([])
|
||||
cairo: save([])
|
||||
cairo: set_source_color([#<Cairo::Color::RGB: @alpha=1.0, @red=0.0, @green=0.0, @blue=0.0>])
|
||||
cairo: translate([65, 600])
|
||||
cairo: rotate([0])
|
||||
cairo: translate([-65, -600])
|
||||
cairo: move_to([65, 600])
|
||||
pango: font_description=([])
|
||||
pango: text=([""])
|
||||
pango: wrap=([#<Pango::Layout::WrapMode word-char>])
|
||||
pango: ellipsize=([#<Pango::Layout::EllipsizeMode end>])
|
||||
pango: alignment=([#<Pango::Layout::Alignment left>])
|
||||
pango: justify=([false])
|
||||
pango: spacing=([0])
|
||||
cairo: update_pango_layout([MockDouble])
|
||||
cairo: update_pango_layout([MockDouble])
|
||||
cairo: show_pango_layout([MockDouble])
|
||||
cairo: restore([])
|
||||
cairo: save([])
|
||||
cairo: set_source_color([#<Cairo::Color::RGB: @alpha=1.0, @red=0.0, @green=0.0, @blue=0.0>])
|
||||
cairo: translate([65, 600])
|
||||
cairo: rotate([0])
|
||||
cairo: translate([-65, -600])
|
||||
cairo: move_to([65, 600])
|
||||
pango: font_description=([])
|
||||
pango: text=([""])
|
||||
pango: wrap=([#<Pango::Layout::WrapMode word-char>])
|
||||
pango: ellipsize=([#<Pango::Layout::EllipsizeMode end>])
|
||||
pango: alignment=([#<Pango::Layout::Alignment left>])
|
||||
pango: justify=([false])
|
||||
pango: spacing=([0])
|
||||
cairo: update_pango_layout([MockDouble])
|
||||
cairo: update_pango_layout([MockDouble])
|
||||
cairo: show_pango_layout([MockDouble])
|
||||
cairo: restore([])
|
||||
surface: write_to_png(["_output/sample_csv_0.png"])
|
||||
surface: write_to_png(["_output/sample_csv_1.png"])
|
||||
|
|
@ -54,6 +54,7 @@ describe "Squib samples" do
|
|||
draw_shapes.rb
|
||||
colors.rb
|
||||
excel.rb
|
||||
csv_import.rb
|
||||
portrait-landscape.rb
|
||||
tgc_proofs.rb
|
||||
ranges.rb
|
||||
|
|
|
|||
Loading…
Reference in New Issue