cryptopunks 2.0.1 → 3.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.
@@ -1,275 +1,382 @@
1
- module Cryptopunks
2
-
3
-
4
-
5
- class Tool
6
- def run( args )
7
- Toolii.run( args )
8
- end
9
- end
10
-
11
-
12
-
13
- class Opts
14
- def merge_gli_options!( options = {} )
15
- # puts " update options:"
16
- # puts options.inspect
17
-
18
- @file = options[:file] if options[:file]
19
- @outdir = options[:dir] if options[:dir]
20
-
21
- @zoom = options[:zoom] if options[:zoom]
22
- @offset = options[:offset] if options[:offset]
23
-
24
- @verbose = true if options[:verbose] == true
25
- end
26
-
27
-
28
- def verbose=(boolean) # add: alias for debug ??
29
- @verbose = boolean
30
- end
31
-
32
- def verbose?
33
- return false if @verbose.nil? # default verbose/debug flag is false
34
- @verbose == true
35
- end
36
-
37
- def file() @file || './punks.png'; end
38
- def file?() @file; end ## note: let's you check if file is set (or "untouched")
39
-
40
- def zoom() @zoom || 1; end
41
- def zoom?() @zoom; end
42
-
43
- def offset() @offset || 0; end
44
- def offset?() @offset; end
45
-
46
- def outdir() @outdir || '.'; end
47
- def outdir?() @outdir; end
48
- end # class Opts
49
-
50
-
51
-
52
- ## note: use gli "dsl" inside a class / namespace
53
- class Toolii
54
- extend GLI::App
55
-
56
- opts = Opts.new
57
-
58
-
59
- program_desc 'punk (or cryptopunk) command line tool'
60
-
61
- version Cryptopunks::VERSION
62
-
63
-
64
- desc "Zoom factor x2, x4, x8, etc."
65
- arg_name 'ZOOM'
66
- default_value opts.zoom
67
- flag [:z, :zoom], type: Integer
68
-
69
- desc "Start counting at offset"
70
- arg_name 'NUM'
71
- default_value opts.offset
72
- flag [:offset], type: Integer
73
-
74
- desc "Output directory"
75
- arg_name 'DIR'
76
- default_value opts.outdir
77
- flag [:d, :dir,
78
- :o, :out, :outdir], type: String
79
-
80
- ### todo/check: move option to -t/--tile command only - why? why not?
81
- desc "True Official Genuine CryptoPunks™ all-in-one composite image"
82
- arg_name 'FILE'
83
- default_value opts.file
84
- flag [:f, :file], type: String
85
-
86
-
87
-
88
- ### global option (required)
89
- ## todo: add check that path is valid?? possible?
90
- desc '(Debug) Show debug messages'
91
- switch [:verbose], negatable: false ## todo: use -w for short form? check ruby interpreter if in use too?
92
-
93
-
94
-
95
- desc "Get punk characters via image tiles from all-in-one punk series composite (#{opts.file}) - for IDs use 0 to 9999"
96
- command [:t, :tile] do |c|
97
- c.action do |g,o,args|
98
-
99
- # puts "opts:"
100
- # puts opts.inspect
101
-
102
- puts "==> reading >#{opts.file}<..."
103
- punks = ImageComposite.read( opts.file )
104
-
105
-
106
- puts " setting zoom to #{opts.zoom}x" if opts.zoom != 1
107
-
108
- ## make sure outdir exits (default is current working dir e.g. .)
109
- FileUtils.mkdir_p( opts.outdir ) unless Dir.exist?( opts.outdir )
110
-
111
- args.each_with_index do |arg,index|
112
- punk_index = arg.to_i( 10 ) ## assume base 10 decimal
113
-
114
- punk = punks[ punk_index ]
115
-
116
- punk_name = "punk-" + "%04d" % (punk_index + opts.offset)
117
-
118
- ## if zoom - add x2,x4 or such
119
- if opts.zoom != 1
120
- punk = punk.zoom( opts.zoom )
121
- punk_name << "@#{opts.zoom}x"
122
- end
123
-
124
- path = "#{opts.outdir}/#{punk_name}.png"
125
- puts "==> (#{index+1}/#{args.size}) saving punk ##{punk_index+opts.offset} to >#{path}<..."
126
-
127
- punk.save( path )
128
- end
129
- puts 'Done.'
130
- end # action
131
- end # command tile
132
-
133
-
134
-
135
- desc 'Generate punk characters from text attributes (from scratch / zero) via builtin punk spritesheet'
136
- command [:g, :gen, :generate] do |c|
137
- c.action do |g,o,args|
138
-
139
- puts "==> generating >#{args.join( ' + ' )}<..."
140
- punk = Image.generate( *args )
141
-
142
- puts " setting zoom to #{opts.zoom}x" if opts.zoom != 1
143
-
144
- ## make sure outdir exits (default is current working dir e.g. .)
145
- FileUtils.mkdir_p( opts.outdir ) unless Dir.exist?( opts.outdir )
146
-
147
- punk_index = 0 ## assume base 10 decimal
148
- punk_name = "punk-" + "%04d" % (punk_index + opts.offset)
149
-
150
- ## if zoom - add x2,x4 or such
151
- if opts.zoom != 1
152
- punk = punk.zoom( opts.zoom )
153
- punk_name << "@#{opts.zoom}x"
154
- end
155
-
156
- path = "#{opts.outdir}/#{punk_name}.png"
157
- puts "==> saving punk ##{punk_index+opts.offset} to >#{path}<..."
158
-
159
- punk.save( path )
160
- puts 'Done.'
161
- end # action
162
- end # command generate
163
-
164
-
165
- desc 'Query (builtin off-chain) punk contract for punk text attributes by IDs - use 0 to 9999'
166
- command [:q, :query] do |c|
167
- c.action do |g,o,args|
168
-
169
- # puts "opts:"
170
- # puts opts.inspect
171
-
172
- args.each_with_index do |arg,index|
173
- punk_index = arg.to_i( 10 ) ## assume base 10 decimal
174
-
175
- puts "==> (#{index+1}/#{args.size}) punk ##{punk_index}..."
176
-
177
- attribute_names = CryptopunksData.punk_attributes( punk_index )
178
- ## downcase name and change spaces to underscore
179
- attribute_names = attribute_names.map do |name|
180
- name.downcase.gsub( ' ', '_' )
181
- end
182
-
183
- print " "
184
- print attribute_names.join( ' ' )
185
- print "\n"
186
- end
187
- puts 'Done.'
188
- end
189
- end
190
-
191
-
192
-
193
- desc 'List all punk archetype and attribute names from builtin punk spritesheet'
194
- command [:l, :ls, :list] do |c|
195
- c.action do |g,o,args|
196
-
197
- generator = Cryptopunks.generator
198
-
199
- puts "==> Archetypes"
200
- generator.meta.each do |rec|
201
- next unless rec.archetype?
202
-
203
- print " "
204
- print "%-30s" % "#{rec.name} / (#{rec.gender})"
205
- print " - #{rec.type}"
206
- print "\n"
207
- end
208
-
209
- puts ""
210
- puts "==> Attributes"
211
- generator.meta.each do |rec|
212
- next unless rec.attribute?
213
-
214
- print " "
215
- print "%-30s" % "#{rec.name} / (#{rec.gender})"
216
- print " - #{rec.type}"
217
- print "\n"
218
- end
219
-
220
- puts ""
221
- puts " See github.com/cryptopunksnotdead/punks.spritesheet for more."
222
- puts ""
223
-
224
- puts 'Done.'
225
- end # action
226
- end # command list
227
-
228
-
229
-
230
- pre do |g,c,o,args|
231
- opts.merge_gli_options!( g )
232
- opts.merge_gli_options!( o )
233
-
234
- if opts.verbose?
235
- ## LogUtils::Logger.root.level = :debug
236
- end
237
-
238
- ## logger.debug "Executing #{c.name}"
239
- true
240
- end
241
-
242
- post do |global,c,o,args|
243
- ## logger.debug "Executed #{c.name}"
244
- true
245
- end
246
-
247
-
248
- on_error do |e|
249
-
250
- if opts.verbose?
251
- puts e.backtrace
252
- end
253
-
254
- if e.is_a?( SystemExit )
255
- puts
256
- puts "*** error: system exit with status code ( #{e.status} )"
257
- exit( e.status ) ## try exit again to make sure error code gets passed along!!!
258
- else
259
- puts
260
- puts "*** error: #{e.message}"
261
- end
262
-
263
- ## note: was false # skip default error handling
264
-
265
- ## note: try true - false WILL SWALLOW exit codes and such
266
- ## - looks like it's still returning 0 (e.g. on unknown option or such)!!!!
267
- true
268
- end
269
-
270
-
271
- ### exit run(ARGV) ## note: use Toolii.run( ARGV ) outside of class
272
- end # class Toolii
273
- end # module Cryptopunks
274
-
275
-
1
+
2
+ module Punk
3
+
4
+
5
+ class Tool
6
+ def run( args )
7
+ Toolii.run( args )
8
+ end
9
+ end
10
+
11
+
12
+
13
+ class Opts
14
+ def merge_gli_options!( options = {} )
15
+ # puts " update options:"
16
+ # puts options.inspect
17
+
18
+ @file = options[:file] if options[:file]
19
+ @outdir = options[:dir] if options[:dir]
20
+
21
+ @zoom = options[:zoom] if options[:zoom]
22
+ @offset = options[:offset] if options[:offset]
23
+
24
+ @seed = options[:seed] if options[:seed]
25
+
26
+ @verbose = true if options[:verbose] == true
27
+ end
28
+
29
+
30
+ def verbose=(boolean) # add: alias for debug ??
31
+ @verbose = boolean
32
+ end
33
+
34
+ def verbose?
35
+ return false if @verbose.nil? # default verbose/debug flag is false
36
+ @verbose == true
37
+ end
38
+
39
+ def file() @file || './punks.png'; end
40
+ def file?() @file; end ## note: let's you check if file is set (or "untouched")
41
+
42
+ def zoom() @zoom || 1; end
43
+ def zoom?() @zoom; end
44
+
45
+ def offset() @offset || 0; end
46
+ def offset?() @offset; end
47
+
48
+ def outdir() @outdir || '.'; end
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
+
57
+ end # class Opts
58
+
59
+
60
+
61
+ ## note: use gli "dsl" inside a class / namespace
62
+ class Toolii
63
+ extend GLI::App
64
+
65
+ opts = Opts.new
66
+
67
+
68
+ program_desc 'punk (or cryptopunk) command line tool'
69
+
70
+ version Pixelart::Module::Cryptopunks::VERSION
71
+
72
+
73
+ desc "Zoom factor x2, x4, x8, etc."
74
+ arg_name 'ZOOM'
75
+ default_value opts.zoom
76
+ flag [:z, :zoom], type: Integer
77
+
78
+ desc "Start counting at offset"
79
+ arg_name 'NUM'
80
+ default_value opts.offset
81
+ flag [:offset], type: Integer
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
+
91
+ desc "Output directory"
92
+ arg_name 'DIR'
93
+ default_value opts.outdir
94
+ flag [:d, :dir,
95
+ :o, :out, :outdir], type: String
96
+
97
+
98
+ ### todo/check: move option to -t/--tile command only - why? why not?
99
+ # desc "True Official Genuine CryptoPunks™ all-in-one composite image"
100
+ desc "All-in-one composite image"
101
+ arg_name 'FILE'
102
+ default_value opts.file
103
+ flag [:f, :file], type: String
104
+
105
+
106
+
107
+ ### global option (required)
108
+ ## todo: add check that path is valid?? possible?
109
+ desc '(Debug) Show debug messages'
110
+ switch [:verbose], negatable: false ## todo: use -w for short form? check ruby interpreter if in use too?
111
+
112
+
113
+
114
+ desc "Flip (vertically) all punk characters in all-in-one punk series composite (#{opts.file})"
115
+ command [:f, :flip] do |c|
116
+ c.action do |g,o,args|
117
+ puts "==> reading >#{opts.file}<..."
118
+ punks = ImageComposite.read( opts.file )
119
+
120
+ ## note: for now always assume 24x24
121
+ cols = punks.width / 24
122
+ rows = punks.height / 24
123
+ tile_width = 24
124
+ tile_height = 24
125
+
126
+ phunks = ImageComposite.new( cols, rows,
127
+ width: tile_width,
128
+ height: tile_height )
129
+
130
+ punks.each do |punk|
131
+ phunks << punk.flip_vertically
132
+ end
133
+
134
+ ## make sure outdir exits (default is current working dir e.g. .)
135
+ FileUtils.mkdir_p( opts.outdir ) unless Dir.exist?( opts.outdir )
136
+
137
+ ## note: allways assume .png extension for now
138
+ basename = File.basename( opts.file, File.extname( opts.file ) )
139
+ path = "#{opts.outdir}/#{basename}-flipped.png"
140
+ puts "==> saving phunks flipped one-by-one by hand to >#{path}<..."
141
+
142
+ phunks.save( path )
143
+ puts 'Done.'
144
+ end # action
145
+ end # command flip
146
+
147
+
148
+ desc "Shuffle all punk characters (randomly) in all-in-one punk series composite (#{opts.file})"
149
+ command [:s, :shuffle] do |c|
150
+ c.action do |g,o,args|
151
+ puts "==> reading >#{opts.file}<..."
152
+ punks = ImageComposite.read( opts.file )
153
+
154
+ ## note: for now always assume 24x24
155
+ cols = punks.width / 24
156
+ rows = punks.height / 24
157
+ tile_width = 24
158
+ tile_height = 24
159
+
160
+ phunks = ImageComposite.new( cols, rows,
161
+ width: tile_width,
162
+ height: tile_height )
163
+
164
+ tiles = cols * rows
165
+ indexes = (0..tiles-1).to_a
166
+ srand( opts.seed ) ## note: for new reset **global** random seed and use (builtin) Array#shuffle
167
+ puts " using random generation number seed >#{opts.seed}< for shuffle"
168
+ indexes = indexes.shuffle
169
+
170
+ ###
171
+ # seed 4142 ends in [..., 7566, 828, 8987, 9777]
172
+ # 333 ends in [..., 6067, 9635, 973, 8172]
173
+
174
+
175
+ indexes.each_with_index do |old_index,new_index|
176
+ puts " ##{old_index} now ##{new_index}"
177
+ phunks << punks[old_index]
178
+ end
179
+
180
+ puts " all #{tiles} old index numbers (zero-based) for reference using seed #{opts.seed}:"
181
+ puts indexes.inspect
182
+
183
+ ## make sure outdir exits (default is current working dir e.g. .)
184
+ FileUtils.mkdir_p( opts.outdir ) unless Dir.exist?( opts.outdir )
185
+
186
+ ## note: allways assume .png extension for now
187
+ basename = File.basename( opts.file, File.extname( opts.file ) )
188
+ path = "#{opts.outdir}/#{basename}-#{opts.seed}.png"
189
+ puts "==> saving p(h)unks shuffled one-by-one by hand to >#{path}<..."
190
+
191
+ phunks.save( path )
192
+ puts 'Done.'
193
+ end # action
194
+ end # command shuffle
195
+
196
+
197
+
198
+
199
+
200
+
201
+
202
+ desc "Get punk characters via image tiles from all-in-one punk series composite (#{opts.file}) - for IDs use 0 to 9999"
203
+ command [:t, :tile] do |c|
204
+ c.action do |g,o,args|
205
+
206
+ # puts "opts:"
207
+ # puts opts.inspect
208
+
209
+ puts "==> reading >#{opts.file}<..."
210
+ punks = ImageComposite.read( opts.file )
211
+
212
+
213
+ puts " setting zoom to #{opts.zoom}x" if opts.zoom != 1
214
+
215
+ ## make sure outdir exits (default is current working dir e.g. .)
216
+ FileUtils.mkdir_p( opts.outdir ) unless Dir.exist?( opts.outdir )
217
+
218
+ args.each_with_index do |arg,index|
219
+ punk_index = arg.to_i( 10 ) ## assume base 10 decimal
220
+
221
+ punk = punks[ punk_index ]
222
+
223
+ punk_name = "punk-" + "%04d" % (punk_index + opts.offset)
224
+
225
+ ## if zoom - add x2,x4 or such
226
+ if opts.zoom != 1
227
+ punk = punk.zoom( opts.zoom )
228
+ punk_name << "@#{opts.zoom}x"
229
+ end
230
+
231
+ path = "#{opts.outdir}/#{punk_name}.png"
232
+ puts "==> (#{index+1}/#{args.size}) saving punk ##{punk_index+opts.offset} to >#{path}<..."
233
+
234
+ punk.save( path )
235
+ end
236
+ puts 'Done.'
237
+ end # action
238
+ end # command tile
239
+
240
+
241
+
242
+ desc 'Generate punk characters from text attributes (from scratch / zero) via builtin punk spritesheet'
243
+ command [:g, :gen, :generate] do |c|
244
+ c.action do |g,o,args|
245
+
246
+ puts "==> generating >#{args.join( ' + ' )}<..."
247
+ punk = Image.generate( *args )
248
+
249
+ puts " setting zoom to #{opts.zoom}x" if opts.zoom != 1
250
+
251
+ ## make sure outdir exits (default is current working dir e.g. .)
252
+ FileUtils.mkdir_p( opts.outdir ) unless Dir.exist?( opts.outdir )
253
+
254
+ punk_index = 0 ## assume base 10 decimal
255
+ punk_name = "punk-" + "%04d" % (punk_index + opts.offset)
256
+
257
+ ## if zoom - add x2,x4 or such
258
+ if opts.zoom != 1
259
+ punk = punk.zoom( opts.zoom )
260
+ punk_name << "@#{opts.zoom}x"
261
+ end
262
+
263
+ path = "#{opts.outdir}/#{punk_name}.png"
264
+ puts "==> saving punk ##{punk_index+opts.offset} to >#{path}<..."
265
+
266
+ punk.save( path )
267
+ puts 'Done.'
268
+ end # action
269
+ end # command generate
270
+
271
+
272
+ desc 'Query (builtin off-chain) punk contract for punk text attributes by IDs - use 0 to 9999'
273
+ command [:q, :query] do |c|
274
+ c.action do |g,o,args|
275
+
276
+ # puts "opts:"
277
+ # puts opts.inspect
278
+
279
+ args.each_with_index do |arg,index|
280
+ punk_index = arg.to_i( 10 ) ## assume base 10 decimal
281
+
282
+ puts "==> (#{index+1}/#{args.size}) punk ##{punk_index}..."
283
+
284
+ attribute_names = CryptopunksData.punk_attributes( punk_index )
285
+ ## downcase name and change spaces to underscore
286
+ attribute_names = attribute_names.map do |name|
287
+ name.downcase.gsub( ' ', '_' )
288
+ end
289
+
290
+ print " "
291
+ print attribute_names.join( ' ' )
292
+ print "\n"
293
+ end
294
+ puts 'Done.'
295
+ end
296
+ end
297
+
298
+
299
+
300
+ desc 'List all punk archetype and attribute names from builtin punk spritesheet'
301
+ command [:l, :ls, :list] do |c|
302
+ c.action do |g,o,args|
303
+
304
+ generator = Image.generator
305
+
306
+ puts "==> Archetypes"
307
+ generator.meta.each do |rec|
308
+ next unless rec.archetype?
309
+
310
+ print " "
311
+ print "%-30s" % "#{rec.name} / (#{rec.gender})"
312
+ print " - #{rec.type}"
313
+ print "\n"
314
+ end
315
+
316
+ puts ""
317
+ puts "==> Attributes"
318
+ generator.meta.each do |rec|
319
+ next unless rec.attribute?
320
+
321
+ print " "
322
+ print "%-30s" % "#{rec.name} / (#{rec.gender})"
323
+ print " - #{rec.type}"
324
+ print "\n"
325
+ end
326
+
327
+ puts ""
328
+ puts " See github.com/cryptopunksnotdead/punks.spritesheet for more."
329
+ puts ""
330
+
331
+ puts 'Done.'
332
+ end # action
333
+ end # command list
334
+
335
+
336
+
337
+ pre do |g,c,o,args|
338
+ opts.merge_gli_options!( g )
339
+ opts.merge_gli_options!( o )
340
+
341
+ if opts.verbose?
342
+ ## LogUtils::Logger.root.level = :debug
343
+ end
344
+
345
+ ## logger.debug "Executing #{c.name}"
346
+ true
347
+ end
348
+
349
+ post do |global,c,o,args|
350
+ ## logger.debug "Executed #{c.name}"
351
+ true
352
+ end
353
+
354
+
355
+ on_error do |e|
356
+
357
+ if opts.verbose?
358
+ puts e.backtrace
359
+ end
360
+
361
+ if e.is_a?( SystemExit )
362
+ puts
363
+ puts "*** error: system exit with status code ( #{e.status} )"
364
+ exit( e.status ) ## try exit again to make sure error code gets passed along!!!
365
+ else
366
+ puts
367
+ puts "*** error: #{e.message}"
368
+ end
369
+
370
+ ## note: was false # skip default error handling
371
+
372
+ ## note: try true - false WILL SWALLOW exit codes and such
373
+ ## - looks like it's still returning 0 (e.g. on unknown option or such)!!!!
374
+ true
375
+ end
376
+
377
+
378
+ ### exit run(ARGV) ## note: use Toolii.run( ARGV ) outside of class
379
+ end # class Toolii
380
+ end # module Punk
381
+
382
+