cryptopunks 2.0.1 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +108 -1
- data/Rakefile +1 -1
- data/config/spritesheet.csv +762 -402
- data/config/spritesheet.png +0 -0
- data/lib/cryptopunks/generator.rb +108 -22
- data/lib/cryptopunks/tool.rb +107 -1
- data/lib/cryptopunks/version.rb +2 -2
- data/lib/cryptopunks.rb +90 -5
- metadata +4 -4
data/config/spritesheet.png
CHANGED
Binary file
|
@@ -5,18 +5,20 @@ module Cryptopunks
|
|
5
5
|
### todo/fix:
|
6
6
|
## move into Punks::Metadata or such
|
7
7
|
class Sprite
|
8
|
-
attr_reader :id, :name, :type, :gender, :more_names
|
8
|
+
attr_reader :id, :name, :type, :gender, :size, :more_names
|
9
9
|
|
10
10
|
|
11
11
|
def initialize( id:,
|
12
12
|
name:,
|
13
13
|
type:,
|
14
14
|
gender:,
|
15
|
+
size:,
|
15
16
|
more_names: [] )
|
16
17
|
@id = id # zero-based index eg. 0,1,2,3, etc.
|
17
18
|
@name = name
|
18
19
|
@type = type
|
19
20
|
@gender = gender
|
21
|
+
@size = size
|
20
22
|
@more_names = more_names
|
21
23
|
end
|
22
24
|
|
@@ -24,6 +26,15 @@ module Cryptopunks
|
|
24
26
|
## use (alternate name/alias) base or face for archetypes? any others?
|
25
27
|
def attribute?() @type.downcase.start_with?( 'attribute' ); end
|
26
28
|
def archetype?() @type.downcase.start_with?( 'archetype' ); end
|
29
|
+
|
30
|
+
def small?() @size == 's'; end
|
31
|
+
def large?() @size == 'l'; end
|
32
|
+
def universal?() @size == 'u'; end
|
33
|
+
alias_method :unisize?, :universal? ## add unisize or allsizes or such - why? why not?
|
34
|
+
|
35
|
+
def male?() @gender == 'm'; end
|
36
|
+
def female?() @gender == 'f'; end
|
37
|
+
def unisex?() @gender == 'u'; end
|
27
38
|
end # class Metadata::Sprite
|
28
39
|
end # class Metadata
|
29
40
|
|
@@ -35,32 +46,49 @@ module Cryptopunks
|
|
35
46
|
######
|
36
47
|
# static helpers - (turn into "true" static self.class methods - why? why not?)
|
37
48
|
#
|
38
|
-
def normalize_key( str )
|
39
|
-
|
49
|
+
def self.normalize_key( str )
|
50
|
+
## add & e.g. B&W
|
51
|
+
str.downcase.gsub(/[ ()&°_-]/, '').strip
|
40
52
|
end
|
41
53
|
|
42
|
-
def normalize_gender( str )
|
54
|
+
def self.normalize_gender( str )
|
43
55
|
## e.g. Female => f
|
44
56
|
## F => f
|
45
|
-
## always return f
|
57
|
+
## always return f/m
|
58
|
+
str.downcase[0]
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.normalize_size( str )
|
62
|
+
## e.g. U or Unisize or Univeral => u
|
63
|
+
## S or Small => s
|
64
|
+
## L or Large => l
|
65
|
+
## always return u/l/s
|
46
66
|
str.downcase[0]
|
47
67
|
end
|
48
68
|
|
49
|
-
def normalize_name( str )
|
69
|
+
def self.normalize_name( str )
|
50
70
|
## normalize spaces in more names
|
51
71
|
str.strip.gsub( /[ ]{2,}/, ' ' )
|
52
72
|
end
|
53
73
|
|
74
|
+
def normalize_key( str ) self.class.normalize_key( str ); end
|
75
|
+
def normalize_gender( str ) self.class.normalize_gender( str ); end
|
76
|
+
def normalize_size( str ) self.class.normalize_size( str ); end
|
77
|
+
def normalize_name( str ) self.class.normalize_name( str ); end
|
78
|
+
|
79
|
+
|
80
|
+
|
81
|
+
|
54
82
|
|
55
83
|
|
56
84
|
def build_attributes_by_name( recs )
|
57
85
|
h = {}
|
58
86
|
recs.each_with_index do |rec|
|
59
87
|
names = [rec.name] + rec.more_names
|
60
|
-
names.each do |name|
|
61
88
|
|
89
|
+
names.each do |name|
|
62
90
|
key = normalize_key( name )
|
63
|
-
key << "_(#{rec.gender})" if rec.attribute?
|
91
|
+
key << "_(#{rec.gender}+#{rec.size})" if rec.attribute?
|
64
92
|
|
65
93
|
if h[ key ]
|
66
94
|
puts "!!! ERROR - attribute name is not unique:"
|
@@ -98,6 +126,7 @@ module Cryptopunks
|
|
98
126
|
id = rec['id'].to_i( 10 )
|
99
127
|
name = normalize_name( rec['name'] )
|
100
128
|
gender = normalize_gender( rec['gender'] )
|
129
|
+
size = normalize_size( rec['size'] )
|
101
130
|
type = rec['type']
|
102
131
|
|
103
132
|
more_names = (rec['more_names'] || '').split( '|' )
|
@@ -108,6 +137,7 @@ module Cryptopunks
|
|
108
137
|
name: name,
|
109
138
|
type: type,
|
110
139
|
gender: gender,
|
140
|
+
size: size,
|
111
141
|
more_names: more_names )
|
112
142
|
end
|
113
143
|
recs
|
@@ -138,24 +168,74 @@ module Cryptopunks
|
|
138
168
|
|
139
169
|
|
140
170
|
|
141
|
-
def find_meta( q, gender: nil
|
171
|
+
def find_meta( q, gender: nil,
|
172
|
+
size: nil,
|
173
|
+
style: nil ) ## note: gender (m/f) required for attributes!!!
|
142
174
|
|
143
175
|
key = normalize_key( q ) ## normalize q(uery) string/symbol
|
144
|
-
key << "_(#{normalize_gender( gender )})" if gender
|
145
176
|
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
177
|
+
keys = [] ## note allow lookup by more than one keys
|
178
|
+
## e.g. if gender set try f/m first and than try unisex as fallback
|
179
|
+
if gender
|
180
|
+
gender = normalize_gender( gender )
|
181
|
+
## auto-fill size if not passed in
|
182
|
+
## for f(emale) => s(mall)
|
183
|
+
## m(ale) => l(arge)
|
184
|
+
size = if size.nil?
|
185
|
+
gender == 'f' ? 's' : 'l'
|
186
|
+
else
|
187
|
+
normalize_size( size )
|
188
|
+
end
|
189
|
+
|
190
|
+
###
|
191
|
+
# try (auto-add) style-specific version first (fallback to "regular" if not found)
|
192
|
+
if style
|
193
|
+
## for now only support natural series
|
194
|
+
style_key = if style.downcase.start_with?( 'natural' )
|
195
|
+
'natural'
|
196
|
+
else
|
197
|
+
puts "!! ERROR - unknown attribute style #{style}; sorry"
|
198
|
+
exit 1
|
199
|
+
end
|
200
|
+
|
201
|
+
keys << "#{key}#{style_key}_(#{gender}+#{size})"
|
202
|
+
## auto-add (u)niversal size as fallback
|
203
|
+
keys << "#{key}#{style_key}_(#{gender}+u)" if size == 's' || size == 'l'
|
204
|
+
## auto-add u(nisex) as fallback
|
205
|
+
keys << "#{key}#{style_key}_(u+#{size})" if gender == 'f' || gender == 'm'
|
206
|
+
end
|
207
|
+
|
208
|
+
|
209
|
+
keys << "#{key}_(#{gender}+#{size})"
|
210
|
+
## auto-add (u)niversal size as fallback
|
211
|
+
keys << "#{key}_(#{gender}+u)" if size == 's' || size == 'l'
|
212
|
+
## auto-add u(nisex) as fallback
|
213
|
+
keys << "#{key}_(u+#{size})" if gender == 'f' || gender == 'm'
|
150
214
|
else
|
151
|
-
|
215
|
+
keys << key
|
216
|
+
end
|
217
|
+
|
218
|
+
|
219
|
+
rec = nil
|
220
|
+
keys.each do |key|
|
221
|
+
rec = @attributes_by_name[ key ]
|
222
|
+
if rec
|
223
|
+
puts " lookup >#{key}< => #{rec.id}: #{rec.name} / #{rec.type} (#{rec.gender}+#{rec.size})"
|
224
|
+
# pp rec
|
225
|
+
break
|
226
|
+
end
|
152
227
|
end
|
228
|
+
|
229
|
+
if rec.nil?
|
230
|
+
puts "!! WARN - no lookup found for #{keys.size} key(s) >#{keys.inspect}<"
|
231
|
+
end
|
232
|
+
|
153
233
|
rec
|
154
234
|
end
|
155
235
|
|
156
236
|
|
157
|
-
def find( q, gender: nil ) ## gender (m/f) required for attributes!!!
|
158
|
-
rec = find_meta( q, gender: gender )
|
237
|
+
def find( q, gender: nil, size: nil, style: nil ) ## gender (m/f) required for attributes!!!
|
238
|
+
rec = find_meta( q, gender: gender, size: size, style: style )
|
159
239
|
|
160
240
|
## return image if record found
|
161
241
|
rec ? @sheet[ rec.id ] : nil
|
@@ -164,10 +244,11 @@ module Cryptopunks
|
|
164
244
|
|
165
245
|
|
166
246
|
|
167
|
-
def to_recs( *values )
|
247
|
+
def to_recs( *values, style: nil )
|
168
248
|
archetype_name = values[0]
|
169
249
|
|
170
250
|
### todo/fix: check for nil/not found!!!!
|
251
|
+
## todo/check/fix: assert meta record returned is archetype NOT attribute!!!!
|
171
252
|
archetype = find_meta( archetype_name )
|
172
253
|
if archetype.nil?
|
173
254
|
puts "!! ERROR - archetype >#{archetype}< not found; sorry"
|
@@ -179,11 +260,15 @@ module Cryptopunks
|
|
179
260
|
attribute_names = values[1..-1]
|
180
261
|
## note: attribute lookup requires gender from archetype!!!!
|
181
262
|
attribute_gender = archetype.gender
|
263
|
+
attribute_size = archetype.size
|
182
264
|
|
183
265
|
attribute_names.each do |attribute_name|
|
184
|
-
attribute = find_meta( attribute_name,
|
266
|
+
attribute = find_meta( attribute_name,
|
267
|
+
gender: attribute_gender,
|
268
|
+
size: attribute_size,
|
269
|
+
style: style )
|
185
270
|
if attribute.nil?
|
186
|
-
puts "!! ERROR - attribute >#{attribute_name}< for (#{attribute_gender}) not found; sorry"
|
271
|
+
puts "!! ERROR - attribute >#{attribute_name}< for (#{attribute_gender}+#{attribute_size}) not found; sorry"
|
187
272
|
exit 1
|
188
273
|
end
|
189
274
|
recs << attribute
|
@@ -195,12 +280,13 @@ module Cryptopunks
|
|
195
280
|
|
196
281
|
|
197
282
|
|
198
|
-
def generate_image( *values,
|
283
|
+
def generate_image( *values, style: nil,
|
284
|
+
background: nil )
|
199
285
|
|
200
286
|
ids = if values[0].is_a?( Integer ) ## assume integer number (indexes)
|
201
287
|
values
|
202
288
|
else ## assume strings (names)
|
203
|
-
to_recs( *values ).map { |rec| rec.id }
|
289
|
+
to_recs( *values, style: style ).map { |rec| rec.id }
|
204
290
|
end
|
205
291
|
|
206
292
|
|
data/lib/cryptopunks/tool.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
module Cryptopunks
|
2
1
|
|
2
|
+
module Cryptopunks
|
3
3
|
|
4
4
|
|
5
5
|
class Tool
|
@@ -21,6 +21,8 @@ class Opts
|
|
21
21
|
@zoom = options[:zoom] if options[:zoom]
|
22
22
|
@offset = options[:offset] if options[:offset]
|
23
23
|
|
24
|
+
@seed = options[:seed] if options[:seed]
|
25
|
+
|
24
26
|
@verbose = true if options[:verbose] == true
|
25
27
|
end
|
26
28
|
|
@@ -45,6 +47,13 @@ class Opts
|
|
45
47
|
|
46
48
|
def outdir() @outdir || '.'; end
|
47
49
|
def outdir?() @outdir; end
|
50
|
+
|
51
|
+
### use a standard (default) seed - why? why not?
|
52
|
+
def seed() @seed || 4142; end
|
53
|
+
def seed?() @seed; end
|
54
|
+
|
55
|
+
|
56
|
+
|
48
57
|
end # class Opts
|
49
58
|
|
50
59
|
|
@@ -71,12 +80,21 @@ arg_name 'NUM'
|
|
71
80
|
default_value opts.offset
|
72
81
|
flag [:offset], type: Integer
|
73
82
|
|
83
|
+
|
84
|
+
desc "Seed for random number generation / shuffle"
|
85
|
+
arg_name 'NUM'
|
86
|
+
default_value opts.seed
|
87
|
+
flag [:seed], type: Integer
|
88
|
+
|
89
|
+
|
90
|
+
|
74
91
|
desc "Output directory"
|
75
92
|
arg_name 'DIR'
|
76
93
|
default_value opts.outdir
|
77
94
|
flag [:d, :dir,
|
78
95
|
:o, :out, :outdir], type: String
|
79
96
|
|
97
|
+
|
80
98
|
### todo/check: move option to -t/--tile command only - why? why not?
|
81
99
|
desc "True Official Genuine CryptoPunks™ all-in-one composite image"
|
82
100
|
arg_name 'FILE'
|
@@ -92,6 +110,94 @@ switch [:verbose], negatable: false ## todo: use -w for short form? check rub
|
|
92
110
|
|
93
111
|
|
94
112
|
|
113
|
+
desc "Flip (vertically) all punk characters in all-in-one punk series composite (#{opts.file})"
|
114
|
+
command [:f, :flip] do |c|
|
115
|
+
c.action do |g,o,args|
|
116
|
+
puts "==> reading >#{opts.file}<..."
|
117
|
+
punks = ImageComposite.read( opts.file )
|
118
|
+
|
119
|
+
## note: for now always assume 24x24
|
120
|
+
cols = punks.width / 24
|
121
|
+
rows = punks.height / 24
|
122
|
+
tile_width = 24
|
123
|
+
tile_height = 24
|
124
|
+
|
125
|
+
phunks = ImageComposite.new( cols, rows,
|
126
|
+
width: tile_width,
|
127
|
+
height: tile_height )
|
128
|
+
|
129
|
+
punks.each do |punk|
|
130
|
+
phunks << punk.flip_vertically
|
131
|
+
end
|
132
|
+
|
133
|
+
## make sure outdir exits (default is current working dir e.g. .)
|
134
|
+
FileUtils.mkdir_p( opts.outdir ) unless Dir.exist?( opts.outdir )
|
135
|
+
|
136
|
+
## note: allways assume .png extension for now
|
137
|
+
basename = File.basename( opts.file, File.extname( opts.file ) )
|
138
|
+
path = "#{opts.outdir}/#{basename}-flipped.png"
|
139
|
+
puts "==> saving phunks flipped one-by-one by hand to >#{path}<..."
|
140
|
+
|
141
|
+
phunks.save( path )
|
142
|
+
puts 'Done.'
|
143
|
+
end # action
|
144
|
+
end # command flip
|
145
|
+
|
146
|
+
|
147
|
+
desc "Shuffle all punk characters (randomly) in all-in-one punk series composite (#{opts.file})"
|
148
|
+
command [:s, :shuffle] do |c|
|
149
|
+
c.action do |g,o,args|
|
150
|
+
puts "==> reading >#{opts.file}<..."
|
151
|
+
punks = ImageComposite.read( opts.file )
|
152
|
+
|
153
|
+
## note: for now always assume 24x24
|
154
|
+
cols = punks.width / 24
|
155
|
+
rows = punks.height / 24
|
156
|
+
tile_width = 24
|
157
|
+
tile_height = 24
|
158
|
+
|
159
|
+
phunks = ImageComposite.new( cols, rows,
|
160
|
+
width: tile_width,
|
161
|
+
height: tile_height )
|
162
|
+
|
163
|
+
tiles = cols * rows
|
164
|
+
indexes = (0..tiles-1).to_a
|
165
|
+
srand( opts.seed ) ## note: for new reset **global** random seed and use (builtin) Array#shuffle
|
166
|
+
puts " using random generation number seed >#{opts.seed}< for shuffle"
|
167
|
+
indexes = indexes.shuffle
|
168
|
+
|
169
|
+
###
|
170
|
+
# seed 4142 ends in [..., 7566, 828, 8987, 9777]
|
171
|
+
# 333 ends in [..., 6067, 9635, 973, 8172]
|
172
|
+
|
173
|
+
|
174
|
+
indexes.each_with_index do |old_index,new_index|
|
175
|
+
puts " ##{old_index} now ##{new_index}"
|
176
|
+
phunks << punks[old_index]
|
177
|
+
end
|
178
|
+
|
179
|
+
puts " all #{tiles} old index numbers (zero-based) for reference using seed #{opts.seed}:"
|
180
|
+
puts indexes.inspect
|
181
|
+
|
182
|
+
## make sure outdir exits (default is current working dir e.g. .)
|
183
|
+
FileUtils.mkdir_p( opts.outdir ) unless Dir.exist?( opts.outdir )
|
184
|
+
|
185
|
+
## note: allways assume .png extension for now
|
186
|
+
basename = File.basename( opts.file, File.extname( opts.file ) )
|
187
|
+
path = "#{opts.outdir}/#{basename}-#{opts.seed}.png"
|
188
|
+
puts "==> saving p(h)unks shuffled one-by-one by hand to >#{path}<..."
|
189
|
+
|
190
|
+
phunks.save( path )
|
191
|
+
puts 'Done.'
|
192
|
+
end # action
|
193
|
+
end # command shuffle
|
194
|
+
|
195
|
+
|
196
|
+
|
197
|
+
|
198
|
+
|
199
|
+
|
200
|
+
|
95
201
|
desc "Get punk characters via image tiles from all-in-one punk series composite (#{opts.file}) - for IDs use 0 to 9999"
|
96
202
|
command [:t, :tile] do |c|
|
97
203
|
c.action do |g,o,args|
|
data/lib/cryptopunks/version.rb
CHANGED
data/lib/cryptopunks.rb
CHANGED
@@ -50,24 +50,103 @@ module Cryptopunks
|
|
50
50
|
end
|
51
51
|
|
52
52
|
class Image
|
53
|
-
|
54
|
-
|
53
|
+
def self.generate( *values, style: nil )
|
54
|
+
|
55
|
+
##### add style option / hack - why? why not?
|
56
|
+
if style
|
57
|
+
values = if style.downcase.index( 'natural') && style.downcase.index( '2')
|
58
|
+
["#{values[0]} (N2)"] + values[1..-1]
|
59
|
+
elsif style.downcase[0] == 'n' ## starting with n - always assume natural(s)
|
60
|
+
## auto-add (N) for Natural to archetype
|
61
|
+
["#{values[0]} (N)"] + values[1..-1]
|
62
|
+
else
|
63
|
+
puts "!! ERROR - unknown punk style #{style}; sorry"
|
64
|
+
exit 1
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
###### hack for black&white
|
70
|
+
## auto-add b&w (black&white) to all attribute names e.g.
|
71
|
+
## Eyes => Eyes B&W
|
72
|
+
## Smile => Smile B&W
|
73
|
+
## ....
|
74
|
+
|
75
|
+
archetype_key = Generator.normalize_key( values[0] )
|
76
|
+
if archetype_key.end_with?( 'bw' ) || ## e.g. B&W
|
77
|
+
archetype_key.end_with?( '1bit') ## e.g. 1-Bit or 1Bit
|
78
|
+
|
79
|
+
values = [values[0]] + values[1..-1].map do |attribute|
|
80
|
+
attribute_key = Generator.normalize_key( attribute )
|
81
|
+
if ['wildhair'].include?( attribute_key ) ## pass through known b&w attributes by "default"
|
82
|
+
attribute
|
83
|
+
elsif attribute_key.index( "black" )
|
84
|
+
attribute ## pass through as-is
|
85
|
+
else
|
86
|
+
"#{attribute} B&W"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
pp values
|
91
|
+
end
|
92
|
+
|
93
|
+
|
94
|
+
# note: female mouth by default has "custom" colors (not black)
|
95
|
+
# for every 1/2/3/4 (human) skin tone and for zombie
|
96
|
+
# auto-"magically" add mapping
|
97
|
+
#
|
98
|
+
# todo/check/fix - add more "contraints"
|
99
|
+
# for mapping to only kick-in for "basic" versions
|
100
|
+
# and not "colored" e.g. golden and such - why? why not?
|
101
|
+
#
|
102
|
+
# move this mapping here to "post-lookup" processing
|
103
|
+
# to get/incl. more "meta" attribute info - why? why not?
|
104
|
+
if archetype_key.index( 'female1' ) ||
|
105
|
+
archetype_key.index( 'female2' ) ||
|
106
|
+
archetype_key.index( 'female3' ) ||
|
107
|
+
archetype_key.index( 'female4' ) ||
|
108
|
+
archetype_key.index( 'zombiefemale' )
|
109
|
+
|
110
|
+
values = [values[0]] + values[1..-1].map do |attribute|
|
111
|
+
attribute_key = Generator.normalize_key( attribute )
|
112
|
+
|
113
|
+
if attribute_key == 'smile' || attribute_key == 'frown'
|
114
|
+
attribute += if archetype_key.index( 'zombiefemale' ) then ' Zombie'
|
115
|
+
elsif archetype_key.index( 'female1' ) then ' 1'
|
116
|
+
elsif archetype_key.index( 'female2' ) then ' 2'
|
117
|
+
elsif archetype_key.index( 'female3' ) then ' 3'
|
118
|
+
elsif archetype_key.index( 'female4' ) then ' 4'
|
119
|
+
else
|
120
|
+
puts "!! ERROR - smile or frown (mouth expression) not supported for archetype:"
|
121
|
+
pp values
|
122
|
+
exit 1
|
123
|
+
end
|
124
|
+
end
|
125
|
+
attribute
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
img = Cryptopunks.generator.generate( *values, style: style )
|
55
130
|
## note: unwrap inner image before passing on to c'tor (requires ChunkyPNG image for now)
|
56
131
|
new( img.image )
|
57
|
-
end
|
132
|
+
end # method Image.generate
|
133
|
+
|
58
134
|
end # class Image
|
59
135
|
|
60
136
|
|
61
137
|
class Spritesheet
|
62
138
|
## note: for now class used for "namespace" only
|
63
|
-
def self.find_by( name:, gender: nil ) ## return archetype/attribute image by name
|
139
|
+
def self.find_by( name:, gender: nil, size: nil ) ## return archetype/attribute image by name
|
64
140
|
# note: pass along name as q (query string)
|
65
|
-
Cryptopunks.generator.find( name,
|
141
|
+
Cryptopunks.generator.find( name,
|
142
|
+
gender: gender,
|
143
|
+
size: size )
|
66
144
|
end
|
67
145
|
end # class Spritesheet
|
68
146
|
## add convenience (alternate spelling) alias - why? why not?
|
69
147
|
SpriteSheet = Spritesheet
|
70
148
|
Sheet = Spritesheet
|
149
|
+
Sprite = Spritesheet
|
71
150
|
end # module Cryptopunks
|
72
151
|
|
73
152
|
|
@@ -98,6 +177,12 @@ end ## module Cryptopunks
|
|
98
177
|
### add some convenience shortcuts
|
99
178
|
CryptoPunks = Cryptopunks
|
100
179
|
Punks = Cryptopunks
|
180
|
+
## add singular too -why? why not?
|
181
|
+
Cryptopunk = Cryptopunks
|
182
|
+
CryptoPunk = Cryptopunks
|
183
|
+
Punk = Cryptopunks
|
184
|
+
|
185
|
+
|
101
186
|
|
102
187
|
|
103
188
|
###
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cryptopunks
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gerald Bauer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-01-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: pixelart
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 1.2.1
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 1.2.1
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: csvreader
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|