artbase 0.2.2 → 0.3.0

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 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