artbase 0.2.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 28781910e6461bf7c03b8c27a1845633c07681798180edd50f873ec029b9921f
4
- data.tar.gz: c19bf7185dfbfe51c0f7ab14b25f4dbecd29314b0ca6088660ab55b4a4c5d40c
3
+ metadata.gz: a1060552f98ae102ea9d98593be2cb3dafd13d07e7d5ef20eb77cc4176c7fd94
4
+ data.tar.gz: 239322b6fcab84714305f14c2bfc91a488dba35b653b906f484f7690a99abec4
5
5
  SHA512:
6
- metadata.gz: 17b24d4328ba8fac495134954a686b59324e7f635d878c2b1ce1c085ad9b21a3a767f87773d7dfccdb7516c47a9cf57621bec10e11daab16ae8610c2670f7ed3
7
- data.tar.gz: e009b91051805e13358b6cb172e32ce256f04d03d0eda912dc7f6b73c35a58c6d556c4e9cb301ac8f4f88aa8d9d6e43bf6b376e2509ae856689d7224584f6bee
6
+ metadata.gz: 5c99a8d16e494bf0572db121c2b19843d2db20b8084df874ce123c10a99cfc39a3508733f9b7eb8da450cf95bea019fe8de66cbbb7771f8e007fbaf828bcb65b
7
+ data.tar.gz: aadfdb81650d27d1f8830755b41c5ab314b2b3de9efe54c76a2b2afa121809123f686438d415d0fb55df02b5fdf498ba6bd9333a8b9e8db4fd4d6dc60e7fad44
data/Manifest.txt CHANGED
@@ -4,15 +4,5 @@ README.md
4
4
  Rakefile
5
5
  bin/artbase
6
6
  lib/artbase.rb
7
- lib/artbase/attributes.rb
8
- lib/artbase/collection.rb
9
- lib/artbase/collection/base.rb
10
- lib/artbase/collection/image.rb
11
- lib/artbase/collection/opensea.rb
12
- lib/artbase/collection/token.rb
13
- lib/artbase/helper.rb
14
- lib/artbase/image.rb
15
- lib/artbase/image/sample.rb
16
- lib/artbase/retry.rb
17
7
  lib/artbase/tool.rb
18
8
  lib/artbase/version.rb
data/Rakefile CHANGED
@@ -26,9 +26,10 @@ Hoe.spec 'artbase' do
26
26
  self.history_file = 'CHANGELOG.md'
27
27
 
28
28
  self.extra_deps = [
29
- ['cocos', '>= 0.1.2'],
30
- ['webclient', '>= 0.2.2'],
31
- ['pixelart', '>= 1.3.6'],
29
+ ['artbase-cocos', '>= 0.0.1'],
30
+ # ['artbase-importers', '>= 0.0.1'], ## note: make "heavy" sql/sqlite db support "soft" dependency
31
+ ['artserve'],
32
+ ['artq'],
32
33
  ]
33
34
 
34
35
  self.licenses = ['Public Domain']
data/lib/artbase/tool.rb CHANGED
@@ -74,19 +74,7 @@ class Tool
74
74
  if File.exist?( "./#{name}/collection.yml" )
75
75
  path = "./#{name}/collection.yml"
76
76
  puts "==> reading collection config >#{path}<..."
77
- config = read_yaml( path )
78
-
79
- ## todo - use TokenCollection.read( ) or such -- why? why not?
80
- ## or TokenCollection.build( hash ) ?? - why? why not?
81
- self.collection = TokenCollection.new(
82
- config['slug'],
83
- config['count'],
84
- token_base: config['token_base'],
85
- image_base: config['image_base'],
86
- format: config['format'],
87
- source: config['source'],
88
- offset: config['offset'] || 0
89
- )
77
+ self.collection = TokenCollection.read( path )
90
78
  else
91
79
  ## todo/check: keep config.rb alternate name - why? why not?
92
80
  ## or use collection.rb only ???
@@ -131,6 +119,8 @@ class Tool
131
119
  dump_attributes
132
120
  elsif ['x', 'exp', 'export'].include?( command )
133
121
  export_attributes
122
+ elsif ['b', 'build'].include?( command )
123
+ build_database
134
124
  elsif ['c', 'composite'].include?( command )
135
125
  make_composite( limit: options[ :limit],
136
126
  mirror: options[ :mirror ])
@@ -145,6 +135,31 @@ class Tool
145
135
  puts "bye"
146
136
  end
147
137
 
138
+
139
+
140
+ def self.build_database
141
+ puts "===> build database"
142
+
143
+ ### note. load database "heavy" machinery only on-demand
144
+ ## make it a "soft" dependency for now - why? why not?
145
+ require 'artbase-importers'
146
+
147
+
148
+ slug = @collection.slug
149
+
150
+ importer = Importer.read( "./#{slug}/build.rb" )
151
+
152
+ columns = importer.metadata_columns
153
+ pp columns
154
+
155
+ Database.connect( "./#{slug}/artbase.db" )
156
+ Database.auto_migrate!( columns )
157
+
158
+ @collection.import( importer )
159
+ end
160
+
161
+
162
+
148
163
  def self.make_composite( limit: nil, mirror: false )
149
164
  puts "==> make composite"
150
165
  @collection.make_composite( limit: limit, mirror: mirror )
@@ -2,8 +2,8 @@
2
2
 
3
3
  module Artbase
4
4
  MAJOR = 0
5
- MINOR = 2
6
- PATCH = 2
5
+ MINOR = 3
6
+ PATCH = 0
7
7
  VERSION = [MAJOR,MINOR,PATCH].join('.')
8
8
 
9
9
  def self.version
data/lib/artbase.rb CHANGED
@@ -1,78 +1,12 @@
1
- require 'cocos'
2
-
3
-
4
-
5
- ## 3rd party gems
6
- require 'pixelart'
7
-
8
-
9
-
10
-
11
- ## our own code
12
- require_relative 'artbase/version' # note: let version always go first
13
-
14
-
15
- ### add (shared) "global" config
16
- module Artbase
17
- class Configuration
18
-
19
- #######################
20
- ## accessors
21
-
22
- ## todo/check: keep trailing / in ipfs_gateway - why? why not?
23
- def ipfs_gateway() @ipfs_gateway || 'https://ipfs.io/ipfs/'; end
24
- def ipfs_gateway=(value) @ipfs_gateway = value; end
25
- end # class Configuration
26
-
27
-
28
- ## lets you use
29
- ## Artbase.configure do |config|
30
- ## config.ipfs_gateway = 'https://cloudflare-ipfs.com/ipfs/'
31
- ## end
32
- def self.configure() yield( config ); end
33
- def self.config() @config ||= Configuration.new; end
34
- end # module Artbase
35
-
36
-
37
- require_relative 'artbase/image'
38
-
39
-
40
- require_relative 'artbase/helper'
41
- require_relative 'artbase/retry' ## (global) retry_on_error helper
42
-
43
- require_relative 'artbase/collection'
44
- require_relative 'artbase/attributes'
45
-
46
-
47
- require_relative 'artbase/tool'
48
-
49
-
50
-
51
- ######
52
- ## move to helper - why? why not?
53
-
54
-
55
-
56
- ## quick ipfs (interplanetary file system) hack
57
- ## - make more reuseable
58
- ## - different name e.g. ipfs_to_http or such - why? why not?
59
- ## change/rename parameter str to url or suc - why? why not?
60
- def handle_ipfs( str, normalize: true,
61
- ipfs_gateway: Artbase.config.ipfs_gateway )
62
-
63
- if normalize && str.start_with?( 'https://ipfs.io/ipfs/' )
64
- str = str.sub( 'https://ipfs.io/ipfs/', 'ipfs://' )
65
- end
66
-
67
- if str.start_with?( 'ipfs://' )
68
- str = str.sub( 'ipfs://', ipfs_gateway ) # use/replace with public gateway
69
- end
70
- str
71
- end
72
-
73
-
74
-
75
-
76
-
77
- puts Artbase.banner
78
- puts Artbase.root
1
+
2
+ require 'artbase-cocos'
3
+
4
+
5
+
6
+ ## our own code
7
+ require_relative 'artbase/version'
8
+ require_relative 'artbase/tool'
9
+
10
+
11
+
12
+ puts Artbase.banner # say hello
metadata CHANGED
@@ -1,57 +1,57 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: artbase
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.3.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: 2022-09-01 00:00:00.000000000 Z
11
+ date: 2022-11-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: cocos
14
+ name: artbase-cocos
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 0.1.2
19
+ version: 0.0.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: 0.1.2
26
+ version: 0.0.1
27
27
  - !ruby/object:Gem::Dependency
28
- name: webclient
28
+ name: artserve
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 0.2.2
33
+ version: '0'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: 0.2.2
40
+ version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: pixelart
42
+ name: artq
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: 1.3.6
47
+ version: '0'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: 1.3.6
54
+ version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rdoc
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -102,16 +102,6 @@ files:
102
102
  - Rakefile
103
103
  - bin/artbase
104
104
  - lib/artbase.rb
105
- - lib/artbase/attributes.rb
106
- - lib/artbase/collection.rb
107
- - lib/artbase/collection/base.rb
108
- - lib/artbase/collection/image.rb
109
- - lib/artbase/collection/opensea.rb
110
- - lib/artbase/collection/token.rb
111
- - lib/artbase/helper.rb
112
- - lib/artbase/image.rb
113
- - lib/artbase/image/sample.rb
114
- - lib/artbase/retry.rb
115
105
  - lib/artbase/tool.rb
116
106
  - lib/artbase/version.rb
117
107
  homepage: https://github.com/pixelartexchange/artbase
@@ -1,83 +0,0 @@
1
-
2
-
3
- def counter_to_text( counter )
4
-
5
- counter = counter.to_a
6
-
7
- attribute_counter = counter[0]
8
- more_counter = counter[1..-1]
9
-
10
-
11
- puts "Attribute Counts\n"
12
- trait_type, h = attribute_counter
13
-
14
- total = h[:by_type].values.reduce(0) { |sum,count| sum+count }
15
-
16
-
17
- types = h[:by_type]
18
- types = types.sort { |l,r| l[0]<=>r[0] } ## sort by name
19
-
20
- puts "\n"
21
- puts "|Name|Total (%)|"
22
- puts "|--------|----------:|"
23
-
24
- types.each do |rec|
25
- name = rec[0]
26
- count = rec[1]
27
- percent = Float(count*100)/Float(total)
28
-
29
- puts "| **#{name} Attributes** | #{count} (#{'%.2f' % percent}) |"
30
- end
31
- puts "\n"
32
-
33
- more_counter.each_with_index do |(trait_type, h),i|
34
- print " · " if i > 0 ## add separator
35
- print "#{trait_type } (#{h[:by_type].size})"
36
- end
37
- puts "\n\n"
38
-
39
-
40
-
41
- more_counter.each do |trait_type, h|
42
- print "### #{trait_type } (#{h[:by_type].size}) - "
43
- print "∑Total #{h[:count]}/#{total}\n"
44
-
45
- puts "\n"
46
- puts "|Name|Total (%)|"
47
- puts "|--------|----------:|"
48
-
49
- types = h[:by_type]
50
- types = types.sort do |l,r|
51
- # sort by 1) by count
52
- # 2) by name a-z
53
- res = r[1] <=> l[1]
54
- res = l[0] <=> r[0] if res == 0
55
- res
56
- end ## sort by count
57
- types.each do |rec|
58
- name = rec[0]
59
- count = rec[1]
60
- percent = Float(count*100)/Float(total)
61
-
62
- puts "| **#{name}** | #{count} (#{'%.2f' % percent}) |"
63
- end
64
- puts "\n\n"
65
- end
66
- end
67
-
68
-
69
-
70
-
71
- def counter_to_csv( counter )
72
-
73
- puts "type, name, count"
74
- counter.each do |trait_type, h|
75
- puts "#{trait_type}, ∑ Total, #{h[:count]}"
76
- h[:by_type].each do |trait_value, count|
77
- puts "#{trait_type}, #{trait_value}, #{count}"
78
- end
79
- end
80
- end
81
-
82
-
83
-
@@ -1,329 +0,0 @@
1
-
2
- module Artbase
3
- class Base ## "abstract" Base collection - check -use a different name - why? why not?
4
-
5
-
6
- def convert_images( overwrite: )
7
- image_dir = "./#{slug}/token-i"
8
- Image.convert( image_dir, from: 'jpg', to: 'png', overwrite: overwrite )
9
- Image.convert( image_dir, from: 'gif', to: 'png', overwrite: overwrite )
10
- Image.convert( image_dir, from: 'svg', to: 'png', overwrite: overwrite )
11
- end
12
-
13
-
14
-
15
- def make_strip
16
- composite_count = @count - @excludes.size
17
-
18
- composite = ImageComposite.new( 9, 1,
19
- width: @width,
20
- height: @height )
21
-
22
- i = 0
23
- each_image do |img, id|
24
- puts "==> [#{i+1}/9] #{id}"
25
- composite << img
26
-
27
- i += 1
28
- break if i >= 9
29
- end
30
-
31
-
32
- composite.save( "./#{@slug}/tmp/#{@slug}-strip.png" )
33
- end
34
-
35
-
36
-
37
- def make_composite( limit: nil,
38
- mirror: false )
39
- ### use well-known / pre-defined (default) grids
40
- ## (cols x rows) for now - why? why not?
41
-
42
- composite_count = if limit
43
- limit
44
- else
45
- @count - @excludes.size
46
- end
47
-
48
- cols, rows = case composite_count
49
- when 99 then [10, 10]
50
- when 100 then [10, 10]
51
- when 150 then [15, 10]
52
- when 314 then [15, 21]
53
- when 500 then [25, 20]
54
- when 1000 then [25, 40]
55
- when 2200 then [50, 44]
56
- when 2222 then [50, 45]
57
- when 2469 then [50, 50]
58
- when 3000 then [100, 30] ## or use 50*60 - why? why not?
59
- when 3500 then [100, 35] ## or use 50*x ??
60
- when 3979 then [100, 40]
61
- when 4000 then [100, 40] ## or use 50x80 - why? why not?
62
- when 4444 then [100, 45] ## or use 50x??
63
- when 5000 then [100, 50] ## or use 50x100 - why? why not?
64
- when 5555 then [100, 56] # 5600 (45 left empty)
65
- when 6666 then [100, 67] # 6700 (34 left empty)
66
- when 6688 then [100, 67] # 6700 (12 left empty)
67
- when 6969 then [100, 70] # 7000 (31 left empty)
68
- when 7500 then [100, 75]
69
- when 8888 then [100, 89]
70
- when 9969 then [100,100]
71
- when 10000 then [100,100]
72
- else
73
- raise ArgumentError, "sorry - unknown composite count #{composite_count}/#{@count} for now"
74
- end
75
-
76
- composite = ImageComposite.new( cols, rows,
77
- width: @width,
78
- height: @height )
79
-
80
-
81
- count = 0
82
- each_image do |img, id|
83
- puts "==> #{id}"
84
- composite << if mirror
85
- img.mirror
86
- else
87
- img
88
- end
89
-
90
- count += 1
91
- break if limit && count >= limit
92
- end
93
-
94
-
95
- slug = "#{@slug}"
96
- slug += "#{limit}" if limit
97
- slug += "_left" if mirror
98
-
99
- path = "./#{@slug}/tmp/#{slug}-#{@width}x#{@height}.png"
100
- puts " saving #{path}..."
101
- composite.save( path )
102
-
103
- if composite_count < 1000
104
- path = "./#{@slug}/tmp/#{slug}-#{@width}x#{@height}@2x.png"
105
- puts " saving 2x #{path}..."
106
- composite.zoom(2).save( path )
107
- end
108
- end
109
-
110
-
111
-
112
-
113
- def calc_attribute_counters ## todo/check: use a different name _counts/_stats etc - why? why not?
114
-
115
- attributes_by_count = { count: 0,
116
- by_count: Hash.new(0)
117
- }
118
- counter = {}
119
-
120
-
121
- each_meta do |meta, id| ## todo/fix: change id to index
122
- traits = meta.traits
123
- # print "#{traits.size} - "
124
- # pp traits
125
-
126
- print "#{id}.." if id % 100 == 0 ## print progress report
127
-
128
- attributes_by_count[ :count ] +=1
129
- attributes_by_count[ :by_count ][ traits.size ] += 1
130
-
131
- traits.each do |trait_type, trait_value|
132
- trait_type = _normalize_trait_type( trait_type )
133
- trait_value = _normalize_trait_value( trait_value )
134
-
135
-
136
- rec = counter[ trait_type ] ||= { count: 0,
137
- by_type: Hash.new(0)
138
- }
139
- rec[ :count ] +=1
140
- rec[ :by_type ][ trait_value ] += 1
141
- end
142
- end
143
-
144
- print "\n"
145
- puts
146
-
147
- ## return all-in-one hash
148
- {
149
- total: attributes_by_count,
150
- traits: counter,
151
- }
152
- end
153
-
154
-
155
- def dump_attributes
156
- stats = calc_attribute_counters
157
-
158
- total = stats[:total]
159
- counter = stats[:traits]
160
-
161
- puts
162
- puts "attribute usage / counts:"
163
- pp total
164
- puts
165
-
166
- puts "#{counter.size} attribute(s):"
167
- counter.each do |trait_name, trait_rec|
168
- puts " #{trait_name} #{trait_rec[:count]} (#{trait_rec[:by_type].size} uniques)"
169
- end
170
-
171
- puts
172
- pp counter
173
- end
174
-
175
-
176
-
177
-
178
- ## order - allow "custom" attribute order export
179
- ## renames - allow renames of attributes
180
- def export_attributes(
181
- order: [],
182
- renames: {}
183
- )
184
-
185
- ## step 1: get counters
186
- stats = calc_attribute_counters
187
-
188
- total = stats[:total]
189
- counter = stats[:traits]
190
-
191
- puts
192
- puts "attribute usage / counts:"
193
- pp total
194
- puts
195
-
196
- puts "#{counter.size} attribute(s):"
197
- counter.each do |trait_name, trait_rec|
198
- puts " #{trait_name} #{trait_rec[:count]} (#{trait_rec[:by_type].size} uniques)"
199
- end
200
-
201
-
202
- trait_names = []
203
- trait_names += order ## get attributes if any in pre-defined order
204
- counter.each do |trait_name, _|
205
- if trait_names.include?( trait_name )
206
- next ## skip already included
207
- else
208
- trait_names << trait_name
209
- end
210
- end
211
-
212
-
213
- recs = []
214
-
215
-
216
- ## step 2: get tabular data
217
- each_meta do |meta, id| ## todo/fix: change id to index
218
-
219
- traits = meta.traits
220
- # print "#{traits.size} - "
221
- # pp traits
222
-
223
- print "#{id}.." if id % 100 == 0 ## print progress report
224
-
225
- ## setup empty hash table (with all attributes)
226
- rec = {}
227
-
228
- ## note: use __Slug__& __Name__
229
- ## to avoid conflict with attribute names
230
- ## e.g. attribute with "Name" will overwrite built-in and so on
231
-
232
- rec['__Slug__'] = if respond_to?( :_meta_slugify )
233
- _meta_slugify( meta, id )
234
- else
235
- ## default to id (six digits) as string with leading zeros
236
- ## for easy sorting using strings
237
- ## e.g. 1 => '000001'
238
- ## 2 => '000002'
239
- '%06d' % id
240
- end
241
-
242
- rec['__Name__'] = meta.name
243
-
244
- ## add all attributes/traits names/keys
245
- trait_names.reduce( rec ) { |h,value| h[value] = []; h }
246
- ## pp rec
247
-
248
- ## note: use an array (to allow multiple values for attributes)
249
- traits.each do |trait_type, trait_value|
250
- trait_type = _normalize_trait_type( trait_type )
251
- trait_value = _normalize_trait_value( trait_value )
252
-
253
- values = rec[ trait_type ]
254
- values << trait_value
255
- end
256
- recs << rec
257
- end
258
- print "\n"
259
-
260
- ## pp recs
261
-
262
- ## flatten recs
263
- data = []
264
- recs.each do |rec|
265
- row = rec.values.map do |value|
266
- if value.is_a?( Array )
267
- value.join( ' / ' )
268
- else
269
- value
270
- end
271
- end
272
- data << row
273
- end
274
-
275
-
276
- ## sort by slug
277
- data = data.sort {|l,r| l[0] <=> r[0] }
278
- pp data
279
-
280
- ### save dataset
281
- ## note: change first colum Slug to ID - only used for "internal" sort etc.
282
- headers = ['ID', 'Name']
283
- headers += trait_names.map do |trait_name| ## check for renames
284
- renames[trait_name] || trait_name
285
- end
286
-
287
-
288
- path = "./#{@slug}/tmp/#{@slug}.csv"
289
- dirname = File.dirname( path )
290
- FileUtils.mkdir_p( dirname ) unless Dir.exist?( dirname )
291
-
292
- File.open( path, 'w:utf-8' ) do |f|
293
- f.write( headers.join( ', ' ))
294
- f.write( "\n" )
295
- ## note: replace ID with our own internal running (zero-based) counter
296
- data.each_with_index do |row,i|
297
- f.write( ([i]+row[1..-1]).join( ', '))
298
- f.write( "\n" )
299
- end
300
- end
301
- end
302
-
303
-
304
-
305
-
306
- #############
307
- # "private" helpers
308
-
309
- def _normalize_trait_type( trait_type )
310
- if @patch && @patch[:trait_types]
311
- @patch[:trait_types][ trait_type ] || trait_type
312
- else
313
- trait_type
314
- end
315
- end
316
-
317
- def _normalize_trait_value( trait_value )
318
- if @patch && @patch[:trait_values]
319
- @patch[:trait_values][ trait_value ] || trait_value
320
- else
321
- trait_value
322
- end
323
- end
324
-
325
-
326
-
327
-
328
- end # class Base
329
- end # module Artbase