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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +3 -3
- data/Manifest.txt +0 -3
- data/README.md +666 -526
- data/Rakefile +40 -32
- data/bin/cryptopunk +17 -17
- data/bin/punk +17 -17
- data/lib/cryptopunks/attributes.rb +147 -147
- data/lib/cryptopunks/colors.rb +162 -162
- data/lib/cryptopunks/composite.rb +38 -38
- data/lib/cryptopunks/contract/punksdata-assets.rb +338 -338
- data/lib/cryptopunks/contract/punksdata-contract.rb +55 -55
- data/lib/cryptopunks/contract/punksdata-meta.rb +2107 -2107
- data/lib/cryptopunks/dataset.rb +67 -67
- data/lib/cryptopunks/image.rb +35 -33
- data/lib/cryptopunks/structs.rb +161 -161
- data/lib/cryptopunks/tool.rb +382 -275
- data/lib/cryptopunks/version.rb +27 -23
- data/lib/cryptopunks.rb +66 -109
- metadata +16 -19
- data/config/spritesheet.csv +0 -402
- data/config/spritesheet.png +0 -0
- data/lib/cryptopunks/generator.rb +0 -223
data/lib/cryptopunks/dataset.rb
CHANGED
@@ -1,67 +1,67 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
module
|
4
|
-
module Dataset
|
5
|
-
|
6
|
-
def self.read( path='./datasets/punks/*.csv' )
|
7
|
-
|
8
|
-
datasets = Dir.glob( path )
|
9
|
-
#=> ["./datasets/punks/0-999.csv",
|
10
|
-
# "./datasets/punks/1000-1999.csv",
|
11
|
-
# "./datasets/punks/2000-2999.csv",
|
12
|
-
# "./datasets/punks/3000-3999.csv",
|
13
|
-
# "./datasets/punks/4000-4999.csv",
|
14
|
-
# "./datasets/punks/5000-5999.csv",
|
15
|
-
# "./datasets/punks/6000-6999.csv",
|
16
|
-
# "./datasets/punks/7000-7999.csv",
|
17
|
-
# "./datasets/punks/8000-8999.csv",
|
18
|
-
# "./datasets/punks/9000-9999.csv"]
|
19
|
-
|
20
|
-
rows = []
|
21
|
-
datasets.each do |dataset|
|
22
|
-
rows += CsvHash.read( dataset )
|
23
|
-
end
|
24
|
-
|
25
|
-
# puts " #{rows.size} rows(s)"
|
26
|
-
#=> 10000 rows(s)
|
27
|
-
|
28
|
-
### wrap in punk struct for easier access
|
29
|
-
punks = []
|
30
|
-
rows.each do |row|
|
31
|
-
id = row['id'].to_i
|
32
|
-
type_q = row['type']
|
33
|
-
count = row['count'].to_i
|
34
|
-
accessories_q = row['accessories'].split( %r{[ ]*/[ ]*} )
|
35
|
-
|
36
|
-
if count != accessories_q.size
|
37
|
-
puts "!! ERROR - punk data assertion failed - expected accessories count #{count}; got #{accessories_q.size}"
|
38
|
-
pp row
|
39
|
-
exit 1
|
40
|
-
end
|
41
|
-
|
42
|
-
type = Metadata::Type.find( type_q )
|
43
|
-
if type.nil?
|
44
|
-
puts "!! ERROR - punk data assertion failed - unknown punk type >#{type_q}<"
|
45
|
-
pp row
|
46
|
-
exit 1
|
47
|
-
end
|
48
|
-
|
49
|
-
accessories = []
|
50
|
-
accessories_q.each do |acc_q|
|
51
|
-
acc = Metadata::Accessory.find( acc_q )
|
52
|
-
if acc.nil?
|
53
|
-
puts "!! ERROR - punk data assertion failed - unknown punk accessory type >#{acc_q}<"
|
54
|
-
pp row
|
55
|
-
exit 1
|
56
|
-
end
|
57
|
-
accessories << acc
|
58
|
-
end
|
59
|
-
|
60
|
-
punks << Metadata.new( id, type, accessories )
|
61
|
-
end
|
62
|
-
punks
|
63
|
-
end
|
64
|
-
end # module Dataset
|
65
|
-
end # module
|
66
|
-
|
67
|
-
|
1
|
+
|
2
|
+
|
3
|
+
module Punk
|
4
|
+
module Dataset
|
5
|
+
|
6
|
+
def self.read( path='./datasets/punks/*.csv' )
|
7
|
+
|
8
|
+
datasets = Dir.glob( path )
|
9
|
+
#=> ["./datasets/punks/0-999.csv",
|
10
|
+
# "./datasets/punks/1000-1999.csv",
|
11
|
+
# "./datasets/punks/2000-2999.csv",
|
12
|
+
# "./datasets/punks/3000-3999.csv",
|
13
|
+
# "./datasets/punks/4000-4999.csv",
|
14
|
+
# "./datasets/punks/5000-5999.csv",
|
15
|
+
# "./datasets/punks/6000-6999.csv",
|
16
|
+
# "./datasets/punks/7000-7999.csv",
|
17
|
+
# "./datasets/punks/8000-8999.csv",
|
18
|
+
# "./datasets/punks/9000-9999.csv"]
|
19
|
+
|
20
|
+
rows = []
|
21
|
+
datasets.each do |dataset|
|
22
|
+
rows += CsvHash.read( dataset )
|
23
|
+
end
|
24
|
+
|
25
|
+
# puts " #{rows.size} rows(s)"
|
26
|
+
#=> 10000 rows(s)
|
27
|
+
|
28
|
+
### wrap in punk struct for easier access
|
29
|
+
punks = []
|
30
|
+
rows.each do |row|
|
31
|
+
id = row['id'].to_i
|
32
|
+
type_q = row['type']
|
33
|
+
count = row['count'].to_i
|
34
|
+
accessories_q = row['accessories'].split( %r{[ ]*/[ ]*} )
|
35
|
+
|
36
|
+
if count != accessories_q.size
|
37
|
+
puts "!! ERROR - punk data assertion failed - expected accessories count #{count}; got #{accessories_q.size}"
|
38
|
+
pp row
|
39
|
+
exit 1
|
40
|
+
end
|
41
|
+
|
42
|
+
type = Metadata::Type.find( type_q )
|
43
|
+
if type.nil?
|
44
|
+
puts "!! ERROR - punk data assertion failed - unknown punk type >#{type_q}<"
|
45
|
+
pp row
|
46
|
+
exit 1
|
47
|
+
end
|
48
|
+
|
49
|
+
accessories = []
|
50
|
+
accessories_q.each do |acc_q|
|
51
|
+
acc = Metadata::Accessory.find( acc_q )
|
52
|
+
if acc.nil?
|
53
|
+
puts "!! ERROR - punk data assertion failed - unknown punk accessory type >#{acc_q}<"
|
54
|
+
pp row
|
55
|
+
exit 1
|
56
|
+
end
|
57
|
+
accessories << acc
|
58
|
+
end
|
59
|
+
|
60
|
+
punks << Metadata.new( id, type, accessories )
|
61
|
+
end
|
62
|
+
punks
|
63
|
+
end
|
64
|
+
end # module Dataset
|
65
|
+
end # module Punk
|
66
|
+
|
67
|
+
|
data/lib/cryptopunks/image.rb
CHANGED
@@ -1,33 +1,35 @@
|
|
1
|
-
module
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
class Image
|
6
|
-
|
7
|
-
def self.read( path ) ## convenience helper
|
8
|
-
img = ChunkyPNG::Image.from_file( path )
|
9
|
-
new( img )
|
10
|
-
end
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
1
|
+
module Punk
|
2
|
+
|
3
|
+
|
4
|
+
|
5
|
+
class Image
|
6
|
+
|
7
|
+
def self.read( path ) ## convenience helper
|
8
|
+
img = ChunkyPNG::Image.from_file( path )
|
9
|
+
new( img )
|
10
|
+
end
|
11
|
+
|
12
|
+
|
13
|
+
|
14
|
+
=begin
|
15
|
+
|
16
|
+
### keep design & colors keyword args in c'tor here
|
17
|
+
## or use parse() like in pixelart - why? why not?
|
18
|
+
|
19
|
+
def initialize( initial=nil, design: nil,
|
20
|
+
colors: nil )
|
21
|
+
if initial
|
22
|
+
## pass image through as-is
|
23
|
+
img = initial
|
24
|
+
else
|
25
|
+
## note: unwrap inner image before passing on to super c'tor
|
26
|
+
img = Pixelart::Image.parse( design, colors: colors ).image
|
27
|
+
end
|
28
|
+
|
29
|
+
super( img.width, img.height, img )
|
30
|
+
end
|
31
|
+
=end
|
32
|
+
|
33
|
+
|
34
|
+
end # class Image
|
35
|
+
end # module Punk
|
data/lib/cryptopunks/structs.rb
CHANGED
@@ -1,161 +1,161 @@
|
|
1
|
-
|
2
|
-
module
|
3
|
-
### wrap metadata (e.g. punk types, accessories, etc.
|
4
|
-
## in structs for easy/easier access)
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
class Metadata
|
9
|
-
|
10
|
-
## nested class
|
11
|
-
class Type ## todo/check: use alias family or such?
|
12
|
-
attr_reader :name,
|
13
|
-
:limit
|
14
|
-
def initialize( name, limit )
|
15
|
-
@name = name
|
16
|
-
@limit = limit
|
17
|
-
end
|
18
|
-
## def to_s() @name; end
|
19
|
-
|
20
|
-
def inspect
|
21
|
-
%Q{<Type "#{@name}", limit: #{@limit}>}
|
22
|
-
end
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
def self.build
|
27
|
-
TYPES.reduce( {} ) do |h, rec|
|
28
|
-
type = Type.new( rec[:name], rec[:limit ] )
|
29
|
-
h[ rec[:name].downcase ] = type
|
30
|
-
h
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def self.registry
|
35
|
-
## auto-build registry (hash table) lookup (by name)
|
36
|
-
@@types ||= build
|
37
|
-
@@types
|
38
|
-
end
|
39
|
-
|
40
|
-
def self.all() registry.values; end
|
41
|
-
|
42
|
-
def self.find( q ) registry[ q.to_s.downcase ]; end
|
43
|
-
end ## (nested) class Type
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
## nested class
|
48
|
-
class AccessoryType
|
49
|
-
attr_reader :name,
|
50
|
-
:accessories
|
51
|
-
def initialize( name, accessories=[] )
|
52
|
-
@name = name
|
53
|
-
@accessories = accessories
|
54
|
-
end
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
def self.build
|
59
|
-
ACCESSORY_TYPES.reduce( {} ) do |h, rec|
|
60
|
-
type = AccessoryType.new( rec[:name] )
|
61
|
-
## add all accessories
|
62
|
-
rec[:accessories].each do |rec_acc|
|
63
|
-
type.accessories << Accessory.new( rec_acc[:name],
|
64
|
-
type,
|
65
|
-
rec_acc[:limit].to_i )
|
66
|
-
end
|
67
|
-
h[ rec[:name].downcase ] = type
|
68
|
-
h
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
def self.registry
|
73
|
-
## auto-build registry (hash table) lookup (by name)
|
74
|
-
@@types ||= build
|
75
|
-
@@types
|
76
|
-
end
|
77
|
-
|
78
|
-
def self.all() registry.values; end
|
79
|
-
|
80
|
-
def self.find( q ) registry[ q.to_s.downcase ]; end
|
81
|
-
end ## (nested) class AccessoryType
|
82
|
-
|
83
|
-
|
84
|
-
## nested class
|
85
|
-
class Accessory
|
86
|
-
|
87
|
-
attr_reader :name,
|
88
|
-
:type,
|
89
|
-
:limit
|
90
|
-
def initialize( name, type, limit )
|
91
|
-
@name = name
|
92
|
-
@type = type
|
93
|
-
@limit = limit
|
94
|
-
end
|
95
|
-
|
96
|
-
|
97
|
-
def inspect
|
98
|
-
%Q{<Accessory "#{@name}", type: "#{@type.name}", limit: #{@limit}>}
|
99
|
-
end
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
def self.build
|
104
|
-
AccessoryType.all.reduce( {} ) do |h, type|
|
105
|
-
type.accessories.each do |acc|
|
106
|
-
h[ acc.name.downcase ] = acc
|
107
|
-
end
|
108
|
-
h
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
def self.registry
|
113
|
-
## auto-build registry (hash table) lookup (by name)
|
114
|
-
@@types ||= build
|
115
|
-
@@types
|
116
|
-
end
|
117
|
-
|
118
|
-
def self.all() registry.values; end
|
119
|
-
|
120
|
-
def self.find( q ) registry[ q.to_s.downcase ]; end
|
121
|
-
end ## (nested) class Accessory
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
attr_reader :id,
|
129
|
-
:type,
|
130
|
-
:accessories,
|
131
|
-
:birthday ## todo/check: use minted or such?
|
132
|
-
|
133
|
-
def initialize( id, type, accessories )
|
134
|
-
@id = id
|
135
|
-
@type = type
|
136
|
-
@accessories = accessories
|
137
|
-
@birthday = Date.new( 2017, 6, 23) ## all 10,000 minted on June 23, 2017
|
138
|
-
end
|
139
|
-
|
140
|
-
def is_type?( name ) @type.name == name; end
|
141
|
-
alias_method :is?, :is_type?
|
142
|
-
|
143
|
-
## convenience helpers for "classic" (5) types
|
144
|
-
def alien?() is_type?( 'Alien'); end
|
145
|
-
def ape?() is_type?( 'Ape' ); end
|
146
|
-
def zombie?() is_type?( 'Zombie' ); end
|
147
|
-
def female?() is_type?( 'Female' ); end
|
148
|
-
def male?() is_type?( 'Male' ); end
|
149
|
-
|
150
|
-
## convenience helpers to lookup attributes
|
151
|
-
def has_attribute?( name )
|
152
|
-
accessories.each do |acc|
|
153
|
-
return true if acc.name == name
|
154
|
-
end
|
155
|
-
false
|
156
|
-
end
|
157
|
-
alias_method :has?, :has_attribute?
|
158
|
-
alias_method :include?, :has_attribute?
|
159
|
-
end # class Metadata
|
160
|
-
|
161
|
-
end # module
|
1
|
+
|
2
|
+
module Punk
|
3
|
+
### wrap metadata (e.g. punk types, accessories, etc.
|
4
|
+
## in structs for easy/easier access)
|
5
|
+
|
6
|
+
|
7
|
+
|
8
|
+
class Metadata
|
9
|
+
|
10
|
+
## nested class
|
11
|
+
class Type ## todo/check: use alias family or such?
|
12
|
+
attr_reader :name,
|
13
|
+
:limit
|
14
|
+
def initialize( name, limit )
|
15
|
+
@name = name
|
16
|
+
@limit = limit
|
17
|
+
end
|
18
|
+
## def to_s() @name; end
|
19
|
+
|
20
|
+
def inspect
|
21
|
+
%Q{<Type "#{@name}", limit: #{@limit}>}
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
|
26
|
+
def self.build
|
27
|
+
TYPES.reduce( {} ) do |h, rec|
|
28
|
+
type = Type.new( rec[:name], rec[:limit ] )
|
29
|
+
h[ rec[:name].downcase ] = type
|
30
|
+
h
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.registry
|
35
|
+
## auto-build registry (hash table) lookup (by name)
|
36
|
+
@@types ||= build
|
37
|
+
@@types
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.all() registry.values; end
|
41
|
+
|
42
|
+
def self.find( q ) registry[ q.to_s.downcase ]; end
|
43
|
+
end ## (nested) class Type
|
44
|
+
|
45
|
+
|
46
|
+
|
47
|
+
## nested class
|
48
|
+
class AccessoryType
|
49
|
+
attr_reader :name,
|
50
|
+
:accessories
|
51
|
+
def initialize( name, accessories=[] )
|
52
|
+
@name = name
|
53
|
+
@accessories = accessories
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
|
58
|
+
def self.build
|
59
|
+
ACCESSORY_TYPES.reduce( {} ) do |h, rec|
|
60
|
+
type = AccessoryType.new( rec[:name] )
|
61
|
+
## add all accessories
|
62
|
+
rec[:accessories].each do |rec_acc|
|
63
|
+
type.accessories << Accessory.new( rec_acc[:name],
|
64
|
+
type,
|
65
|
+
rec_acc[:limit].to_i )
|
66
|
+
end
|
67
|
+
h[ rec[:name].downcase ] = type
|
68
|
+
h
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.registry
|
73
|
+
## auto-build registry (hash table) lookup (by name)
|
74
|
+
@@types ||= build
|
75
|
+
@@types
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.all() registry.values; end
|
79
|
+
|
80
|
+
def self.find( q ) registry[ q.to_s.downcase ]; end
|
81
|
+
end ## (nested) class AccessoryType
|
82
|
+
|
83
|
+
|
84
|
+
## nested class
|
85
|
+
class Accessory
|
86
|
+
|
87
|
+
attr_reader :name,
|
88
|
+
:type,
|
89
|
+
:limit
|
90
|
+
def initialize( name, type, limit )
|
91
|
+
@name = name
|
92
|
+
@type = type
|
93
|
+
@limit = limit
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
def inspect
|
98
|
+
%Q{<Accessory "#{@name}", type: "#{@type.name}", limit: #{@limit}>}
|
99
|
+
end
|
100
|
+
|
101
|
+
|
102
|
+
|
103
|
+
def self.build
|
104
|
+
AccessoryType.all.reduce( {} ) do |h, type|
|
105
|
+
type.accessories.each do |acc|
|
106
|
+
h[ acc.name.downcase ] = acc
|
107
|
+
end
|
108
|
+
h
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def self.registry
|
113
|
+
## auto-build registry (hash table) lookup (by name)
|
114
|
+
@@types ||= build
|
115
|
+
@@types
|
116
|
+
end
|
117
|
+
|
118
|
+
def self.all() registry.values; end
|
119
|
+
|
120
|
+
def self.find( q ) registry[ q.to_s.downcase ]; end
|
121
|
+
end ## (nested) class Accessory
|
122
|
+
|
123
|
+
|
124
|
+
|
125
|
+
|
126
|
+
|
127
|
+
|
128
|
+
attr_reader :id,
|
129
|
+
:type,
|
130
|
+
:accessories,
|
131
|
+
:birthday ## todo/check: use minted or such?
|
132
|
+
|
133
|
+
def initialize( id, type, accessories )
|
134
|
+
@id = id
|
135
|
+
@type = type
|
136
|
+
@accessories = accessories
|
137
|
+
@birthday = Date.new( 2017, 6, 23) ## all 10,000 minted on June 23, 2017
|
138
|
+
end
|
139
|
+
|
140
|
+
def is_type?( name ) @type.name == name; end
|
141
|
+
alias_method :is?, :is_type?
|
142
|
+
|
143
|
+
## convenience helpers for "classic" (5) types
|
144
|
+
def alien?() is_type?( 'Alien'); end
|
145
|
+
def ape?() is_type?( 'Ape' ); end
|
146
|
+
def zombie?() is_type?( 'Zombie' ); end
|
147
|
+
def female?() is_type?( 'Female' ); end
|
148
|
+
def male?() is_type?( 'Male' ); end
|
149
|
+
|
150
|
+
## convenience helpers to lookup attributes
|
151
|
+
def has_attribute?( name )
|
152
|
+
accessories.each do |acc|
|
153
|
+
return true if acc.name == name
|
154
|
+
end
|
155
|
+
false
|
156
|
+
end
|
157
|
+
alias_method :has?, :has_attribute?
|
158
|
+
alias_method :include?, :has_attribute?
|
159
|
+
end # class Metadata
|
160
|
+
|
161
|
+
end # module Punk
|