cryptopunks 2.0.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,264 +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
- puts
250
- puts "*** error: #{e.message}"
251
-
252
- if opts.verbose?
253
- puts e.backtrace
254
- end
255
-
256
- false # skip default error handling
257
- end
258
-
259
-
260
- ### exit run(ARGV) ## note: use Toolii.run( ARGV ) outside of class
261
- end # class Toolii
262
- end # module Cryptopunks
263
-
264
-
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
+