ordlite 0.1.2 → 0.2.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 +1 -1
- data/Manifest.txt +5 -0
- data/README.md +125 -54
- data/Rakefile +3 -1
- data/lib/ordlite/base.rb +45 -5
- data/lib/ordlite/cache.rb +46 -105
- data/lib/ordlite/factory.rb +132 -0
- data/lib/ordlite/importer.rb +218 -0
- data/lib/ordlite/models/blob.rb +4 -0
- data/lib/ordlite/models/collection.rb +14 -0
- data/lib/ordlite/models/factory.rb +25 -0
- data/lib/ordlite/models/forward.rb +22 -3
- data/lib/ordlite/models/generative.rb +12 -0
- data/lib/ordlite/models/inscribe.rb +232 -5
- data/lib/ordlite/schema.rb +105 -2
- data/lib/ordlite/version.rb +2 -2
- data/lib/ordlite.rb +12 -2
- metadata +36 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6f1f6f768a785a0badc768db45c1c8ca831958f983b673fe48990846f3d4260e
|
4
|
+
data.tar.gz: 234d31cabdc7ed109144487792da9f77c39821f935e3d7d91a151b91e817d511
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 403e1addf0b974af179de293a26c5f1f47da8d0f665da1ca1a44a89cbcfb025a642a04930f49f6df35681527b2cbcaae855f87de4b7ce09e6cd88b4cffab1472
|
7
|
+
data.tar.gz: ab359d39d1dcdf307e8b3239ed61e2f10f8fc6bfc4316c3f9f5554a9fbc2d88b0d1c24f120afcab9b035c675d82d22e0292c6d1202db7219d64f5e8f2c214b54
|
data/CHANGELOG.md
CHANGED
data/Manifest.txt
CHANGED
@@ -5,8 +5,13 @@ Rakefile
|
|
5
5
|
lib/ordlite.rb
|
6
6
|
lib/ordlite/base.rb
|
7
7
|
lib/ordlite/cache.rb
|
8
|
+
lib/ordlite/factory.rb
|
9
|
+
lib/ordlite/importer.rb
|
8
10
|
lib/ordlite/models/blob.rb
|
11
|
+
lib/ordlite/models/collection.rb
|
12
|
+
lib/ordlite/models/factory.rb
|
9
13
|
lib/ordlite/models/forward.rb
|
14
|
+
lib/ordlite/models/generative.rb
|
10
15
|
lib/ordlite/models/inscribe.rb
|
11
16
|
lib/ordlite/schema.rb
|
12
17
|
lib/ordlite/version.rb
|
data/README.md
CHANGED
@@ -4,8 +4,8 @@
|
|
4
4
|
ordlite - ordinals inscription (on bitcoin & co) database let's you query via sql and more
|
5
5
|
|
6
6
|
|
7
|
-
* home :: [github.com/ordbase/
|
8
|
-
* bugs :: [github.com/ordbase/
|
7
|
+
* home :: [github.com/ordbase/ordbase](https://github.com/ordbase/ordbase)
|
8
|
+
* bugs :: [github.com/ordbase/ordbase/issues](https://github.com/ordbase/ordbase/issues)
|
9
9
|
* gem :: [rubygems.org/gems/ordlite](https://rubygems.org/gems/ordlite)
|
10
10
|
* rdoc :: [rubydoc.info/gems/ordlite](http://rubydoc.info/gems/ordlite)
|
11
11
|
|
@@ -13,7 +13,7 @@ ordlite - ordinals inscription (on bitcoin & co) database let's you query via sq
|
|
13
13
|
|
14
14
|
## SQL Database Model
|
15
15
|
|
16
|
-
|
16
|
+
Inscribes • Blobs • Collections • Factories • Generatives
|
17
17
|
|
18
18
|
|
19
19
|
Table Inscribes
|
@@ -62,97 +62,165 @@ OrdDb.create_all # build table schema
|
|
62
62
|
puts
|
63
63
|
puts " #{Inscribe.count} inscribe(s)"
|
64
64
|
puts " #{Blob.count} blob(s)"
|
65
|
+
puts " #{Collection.count} collection(s)"
|
66
|
+
puts " #{Factory.count} factories"
|
67
|
+
puts " #{Generative.count} generative(s)"
|
65
68
|
|
66
69
|
#=> 0 inscribe(s)
|
67
70
|
#=> 0 blob(s)
|
71
|
+
#=> 0 collection(s)
|
72
|
+
#=> 0 generative(s)
|
68
73
|
```
|
69
74
|
|
70
75
|
|
71
76
|
|
72
77
|
|
73
|
-
### Example No 1 -
|
78
|
+
### Example No 1 - Auto-Add (Via Ordinals.com) First Thousand Inscriptions (Sub 1k)
|
74
79
|
|
75
80
|
``` ruby
|
76
81
|
require 'ordlite'
|
77
82
|
|
78
83
|
|
79
|
-
OrdDb.
|
80
|
-
database: './ord.db' )
|
84
|
+
OrdDb.open( './ord.db' )
|
81
85
|
|
82
86
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
## e.g. sql where clause like
|
87
|
-
## content LIKE '%deploy%'
|
88
|
-
## AND ( content LIKE '%orc-721%'
|
89
|
-
## OR content LIKE '%og%')
|
90
|
-
##
|
87
|
+
1000.times do |num| # auto-add inscription 0-999
|
88
|
+
OrdDb.import( num )
|
89
|
+
end
|
91
90
|
|
92
|
-
|
93
|
-
puts "
|
91
|
+
puts
|
92
|
+
puts " #{Inscribe.count} inscribe(s)"
|
93
|
+
puts " #{Blob.count} blob(s)"
|
94
|
+
#=> 1000 inscribe(s)
|
95
|
+
#=> 1000 blob(s)
|
96
|
+
```
|
94
97
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
+
Let's query for the ten biggest (by bytes) inscriptions
|
99
|
+
(and pretty print the result):
|
100
|
+
|
101
|
+
```ruby
|
102
|
+
Inscribe.biggest.limit(10).each do |rec|
|
103
|
+
print "#{number_to_human_size(rec.bytes)} (#{rec.bytes} bytes) - "
|
104
|
+
print "Inscribe №#{rec.num} (#{rec.content_type}) - "
|
105
|
+
print "#{rec.date} - #{rec.fee} fee in sats"
|
106
|
+
print "\n"
|
98
107
|
end
|
108
|
+
```
|
99
109
|
|
110
|
+
resulting in:
|
100
111
|
|
101
|
-
|
102
|
-
|
112
|
+
```
|
113
|
+
3.73 MB (3915537 bytes) - Inscribe №652 (image/jpeg) - 2023-02-01 20:38:33 - 0 fee in sats
|
114
|
+
385 KB (394718 bytes) - Inscribe №978 (application/epub+zip) - 2023-02-02 06:46:04 - 109325 fee in sats
|
115
|
+
385 KB (394479 bytes) - Inscribe №546 (image/gif) - 2023-02-01 10:41:50 - 1489860 fee in sats
|
116
|
+
385 KB (394440 bytes) - Inscribe №833 (image/png) - 2023-02-02 01:13:51 - 99314 fee in sats
|
117
|
+
381 KB (389858 bytes) - Inscribe №388 (image/jpeg) - 2023-01-31 14:01:38 - 981620 fee in sats
|
118
|
+
379 KB (388417 bytes) - Inscribe №291 (image/gif) - 2023-01-30 17:58:54 - 586794 fee in sats
|
119
|
+
378 KB (386858 bytes) - Inscribe №857 (image/png) - 2023-02-02 01:17:54 - 97407 fee in sats
|
120
|
+
374 KB (383322 bytes) - Inscribe №538 (image/jpeg) - 2023-02-01 10:20:28 - 96519 fee in sats
|
121
|
+
367 KB (375414 bytes) - Inscribe №378 (image/gif) - 2023-01-31 09:47:55 - 945300 fee in sats
|
122
|
+
365 KB (373504 bytes) - Inscribe №288 (image/jpeg) - 2023-01-30 16:51:46 - 94050 fee in sats
|
123
|
+
```
|
103
124
|
|
104
125
|
|
126
|
+
Let's query for all inscriptions grouped by date (day) and dump the results:
|
105
127
|
|
106
|
-
|
107
|
-
##
|
108
|
-
|
109
|
-
## e.g. sql where clause like
|
110
|
-
## content LIKE '%mint%'
|
111
|
-
## AND ( content LIKE '%orc-721%'
|
112
|
-
## OR content LIKE '%og%')
|
128
|
+
```ruby
|
129
|
+
pp Inscribe.counts_by_date ## or count_by_day
|
130
|
+
```
|
113
131
|
|
114
|
-
|
115
|
-
puts " #{mints.size} mint candidate(s)"
|
132
|
+
resulting in:
|
116
133
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
134
|
+
```
|
135
|
+
{"2022-12-14" => 1,
|
136
|
+
"2022-12-17" => 1,
|
137
|
+
"2022-12-19" => 1,
|
138
|
+
"2023-01-05" => 1,
|
139
|
+
"2023-01-10" => 1,
|
140
|
+
"2023-01-12" => 1,
|
141
|
+
"2023-01-13" => 2,
|
142
|
+
"2023-01-15" => 1,
|
143
|
+
"2023-01-16" => 1,
|
144
|
+
"2023-01-19" => 5,
|
145
|
+
"2023-01-20" => 3,
|
146
|
+
"2023-01-21" => 5,
|
147
|
+
"2023-01-22" => 34,
|
148
|
+
"2023-01-23" => 23,
|
149
|
+
"2023-01-24" => 4,
|
150
|
+
"2023-01-25" => 9,
|
151
|
+
"2023-01-26" => 12,
|
152
|
+
"2023-01-27" => 19,
|
153
|
+
"2023-01-28" => 16,
|
154
|
+
"2023-01-29" => 128,
|
155
|
+
"2023-01-30" => 82,
|
156
|
+
"2023-01-31" => 98,
|
157
|
+
"2023-02-01" => 220,
|
158
|
+
"2023-02-02" => 332}
|
159
|
+
```
|
122
160
|
|
161
|
+
Let's query for all inscriptions grouped by month and dump the results:
|
123
162
|
|
124
|
-
|
125
|
-
|
163
|
+
```ruby
|
164
|
+
pp Inscribe.counts_by_month
|
165
|
+
```
|
126
166
|
|
167
|
+
resulting in:
|
168
|
+
|
169
|
+
```
|
170
|
+
{"2022-12" => 3,
|
171
|
+
"2023-01" => 445,
|
172
|
+
"2023-02" => 552}
|
173
|
+
```
|
174
|
+
|
175
|
+
|
176
|
+
Let's query for all content types and group by count (descending) and dump the results:
|
127
177
|
|
128
|
-
puts " #{deploys.size} deploy candidate(s)"
|
129
|
-
puts " #{mints.size} mint candidate(s)"
|
130
178
|
|
131
|
-
|
132
|
-
|
179
|
+
```ruby
|
180
|
+
pp Inscribe.counts_by_content_type
|
181
|
+
```
|
182
|
+
|
183
|
+
resulting in:
|
184
|
+
|
185
|
+
```
|
186
|
+
{"image/png" => 475,
|
187
|
+
"image/jpeg" => 188,
|
188
|
+
"image/webp" => 117,
|
189
|
+
"text/plain;charset=utf-8" => 112,
|
190
|
+
"image/svg+xml" => 62,
|
191
|
+
"text/html;charset=utf-8" => 18,
|
192
|
+
"image/gif" => 11,
|
193
|
+
"audio/mpeg" => 6,
|
194
|
+
"application/pdf" => 2,
|
195
|
+
"image/avif" => 2,
|
196
|
+
"video/webm" => 2,
|
197
|
+
"application/epub+zip" => 1,
|
198
|
+
"application/pgp-signature" => 1,
|
199
|
+
"audio/midi" => 1,
|
200
|
+
"audio/mod" => 1,
|
201
|
+
"video/mp4" => 1}
|
133
202
|
```
|
134
203
|
|
204
|
+
and so on.
|
135
205
|
|
136
206
|
|
137
207
|
|
138
|
-
|
208
|
+
|
209
|
+
### Bonus: Import (Cached) Inscription Meta Datafiles (& Content Blobs)
|
139
210
|
|
140
211
|
Let's import all cached
|
141
|
-
inscriptions metadata datafiles (& content)
|
142
|
-
from [/ordinals.cache](https://github.com/ordbase/ordinals.cache)
|
212
|
+
inscriptions metadata datafiles (& content blobs)
|
213
|
+
from [/ordinals.cache](https://github.com/ordbase/ordinals.cache)
|
143
214
|
into an (sql) database e.g. `ord.db`:
|
144
215
|
|
145
216
|
|
146
217
|
``` ruby
|
147
218
|
require 'ordlite'
|
148
219
|
|
149
|
-
OrdDb.
|
150
|
-
database: './ord.db' )
|
151
|
-
|
152
|
-
OrdDb.create_all # build table schema
|
220
|
+
OrdDb.open( './ord.db' )
|
153
221
|
|
154
|
-
cache_dir = './ordinals.cache/
|
155
|
-
cache =
|
222
|
+
cache_dir = './ordinals.cache/inscription'
|
223
|
+
cache = Ordinals::Cache.new( cache_dir )
|
156
224
|
cache.import_all
|
157
225
|
|
158
226
|
|
@@ -171,9 +239,12 @@ The scripts are dedicated to the public domain.
|
|
171
239
|
Use it as you please with no restrictions whatsoever.
|
172
240
|
|
173
241
|
|
242
|
+
## Questions? Comments?
|
243
|
+
|
244
|
+
Join us in the [Ordgen / ORC-721 discord (chat server)](https://discord.gg/dDhvHKjm2t). Yes you can.
|
245
|
+
Your questions and commetary welcome.
|
246
|
+
|
247
|
+
|
248
|
+
Or post them over at the [Help & Support](https://github.com/geraldb/help) page. Thanks.
|
174
249
|
|
175
|
-
Please post in the #generative-orc-721 channel
|
176
|
-
in the ordinal punks discord.
|
177
|
-
For an invite
|
178
|
-
see <https://twitter.com/OrdinalPunks/status/1620230583711576068>.
|
179
250
|
|
data/Rakefile
CHANGED
@@ -9,7 +9,7 @@ Hoe.spec 'ordlite' do
|
|
9
9
|
self.summary = "ordlite - ordinals inscription (on bitcoin & co) database let's you query via sql and more"
|
10
10
|
self.description = summary
|
11
11
|
|
12
|
-
self.urls = { home: 'https://github.com/ordbase/
|
12
|
+
self.urls = { home: 'https://github.com/ordbase/ordbase' }
|
13
13
|
|
14
14
|
self.author = 'Gerald Bauer'
|
15
15
|
self.email = 'gerald.bauer@gmail.com'
|
@@ -19,6 +19,7 @@ Hoe.spec 'ordlite' do
|
|
19
19
|
self.history_file = 'CHANGELOG.md'
|
20
20
|
|
21
21
|
self.extra_deps = [
|
22
|
+
['ordinals'],
|
22
23
|
['activerecord'],
|
23
24
|
['activerecord-utils'],
|
24
25
|
['logutils'],
|
@@ -26,6 +27,7 @@ Hoe.spec 'ordlite' do
|
|
26
27
|
['props'],
|
27
28
|
['props-activerecord'],
|
28
29
|
['sqlite3'],
|
30
|
+
['pixelart'], ## required for factory (ordgen/orc-721) support for now
|
29
31
|
]
|
30
32
|
|
31
33
|
self.licenses = ['Public Domain']
|
data/lib/ordlite/base.rb
CHANGED
@@ -1,10 +1,6 @@
|
|
1
1
|
# core and stlibs
|
2
|
+
require 'ordinals' ## will pull-in cocos & friends
|
2
3
|
|
3
|
-
require 'pp'
|
4
|
-
require 'fileutils'
|
5
|
-
require 'uri'
|
6
|
-
require 'json'
|
7
|
-
require 'yaml'
|
8
4
|
|
9
5
|
require 'logger' # Note: use for ActiveRecord::Base.logger -- remove/replace later w/ LogUtils::Logger ???
|
10
6
|
|
@@ -31,6 +27,9 @@ require_relative 'models/forward'
|
|
31
27
|
|
32
28
|
require_relative 'models/inscribe'
|
33
29
|
require_relative 'models/blob'
|
30
|
+
require_relative 'models/collection'
|
31
|
+
require_relative 'models/factory'
|
32
|
+
require_relative 'models/generative'
|
34
33
|
|
35
34
|
|
36
35
|
require_relative 'schema'
|
@@ -38,6 +37,10 @@ require_relative 'schema'
|
|
38
37
|
require_relative 'cache'
|
39
38
|
|
40
39
|
|
40
|
+
require_relative 'importer' ## note: require (soft dep) ordinals gems!!!
|
41
|
+
|
42
|
+
|
43
|
+
|
41
44
|
|
42
45
|
module OrdDb
|
43
46
|
|
@@ -53,6 +56,35 @@ module OrdDb
|
|
53
56
|
OrdDb.create
|
54
57
|
end
|
55
58
|
|
59
|
+
def self.auto_migrate!
|
60
|
+
### todo/fix:
|
61
|
+
## check props table and versions!!!!!
|
62
|
+
|
63
|
+
# first time? - auto-run db migratation, that is, create db tables
|
64
|
+
unless LogDb::Model::Log.table_exists?
|
65
|
+
LogDb.create # add logs table
|
66
|
+
end
|
67
|
+
|
68
|
+
unless ConfDb::Model::Prop.table_exists?
|
69
|
+
ConfDb.create # add props table
|
70
|
+
end
|
71
|
+
|
72
|
+
unless OrdDb::Model::Inscribe.table_exists?
|
73
|
+
OrdDb.create
|
74
|
+
end
|
75
|
+
end # method auto_migrate!
|
76
|
+
|
77
|
+
|
78
|
+
def self.open( database='./ord.db' ) ## convenience helper for sqlite only
|
79
|
+
connect( adapter: 'sqlite3',
|
80
|
+
database: database )
|
81
|
+
|
82
|
+
## build schema if database new/empty
|
83
|
+
auto_migrate!
|
84
|
+
end
|
85
|
+
|
86
|
+
|
87
|
+
|
56
88
|
def self.connect( config={} )
|
57
89
|
|
58
90
|
if config.empty?
|
@@ -102,5 +134,13 @@ module OrdDb
|
|
102
134
|
end # module OrdDb
|
103
135
|
|
104
136
|
|
137
|
+
|
138
|
+
####
|
139
|
+
# add factory (ordgen/orc-721) support here for now - why? why not?
|
140
|
+
require 'pixelart'
|
141
|
+
require_relative 'factory'
|
142
|
+
|
143
|
+
|
144
|
+
|
105
145
|
# say hello
|
106
146
|
puts Ordlite.banner ## if defined?($RUBYCOCOS_DEBUG) && $RUBCOCOS_DEBUG
|
data/lib/ordlite/cache.rb
CHANGED
@@ -1,123 +1,64 @@
|
|
1
|
+
###
|
2
|
+
## add (database) import machinery to cache
|
1
3
|
|
2
|
-
module
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
Inscribe = Model::Inscribe
|
8
|
-
Blob = Model::Blob
|
9
|
-
|
10
|
-
def initialize( dir='.' )
|
11
|
-
@dir = dir
|
12
|
-
end
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
def import_all
|
17
|
-
paths = Dir.glob( "#{@dir}/**.json" )
|
18
|
-
puts " #{paths.size} inscribe datafile(s) found"
|
4
|
+
module Ordinals
|
5
|
+
class Cache
|
6
|
+
Inscribe = OrdDb::Model::Inscribe
|
7
|
+
Blob = OrdDb::Model::Blob
|
19
8
|
|
9
|
+
def import_all
|
10
|
+
paths = _find_meta
|
11
|
+
puts " #{paths.size} inscribe metaddatafile(s) found"
|
20
12
|
paths.each_with_index do |path, i|
|
21
|
-
puts "==> inscribe #{i+1}/#{paths.size}..."
|
13
|
+
## puts "==> inscribe #{i+1}/#{paths.size}..."
|
22
14
|
data = _read_inscribe( path )
|
23
|
-
|
24
|
-
|
15
|
+
id = data['id']
|
16
|
+
|
17
|
+
## skip if exists (use update later - why? why not?)
|
18
|
+
rec = Inscribe.find_by( id: id )
|
19
|
+
if rec
|
20
|
+
## skip - already in db
|
21
|
+
print '.'
|
22
|
+
else
|
23
|
+
print " #{id}" # NEW - add / insert into db"
|
24
|
+
rec = Inscribe.create_from_cache( data )
|
25
|
+
end
|
25
26
|
end
|
27
|
+
puts
|
26
28
|
|
27
29
|
|
28
|
-
paths =
|
29
|
-
puts " #{paths.size}
|
30
|
-
|
30
|
+
paths = _find_blobs
|
31
|
+
puts " #{paths.size} inscribe blob(s) found"
|
31
32
|
paths.each_with_index do |path, i|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
33
|
+
## puts "==> blob #{i+1}/#{paths.size}..."
|
34
|
+
content = read_blob( path )
|
35
|
+
id = File.basename( File.dirname(path)) +
|
36
|
+
File.basename( path, File.extname( path ))
|
37
|
+
|
38
|
+
rec = Blob.find_by( id: id )
|
39
|
+
if rec
|
40
|
+
## skip - already in db
|
41
|
+
print '.'
|
42
|
+
else
|
43
|
+
print " #{id}" # NEW - add / insert into db"
|
44
|
+
rec = Blob.create( id: id,
|
45
|
+
content: content )
|
46
|
+
end
|
38
47
|
end
|
48
|
+
puts
|
39
49
|
end
|
40
50
|
|
41
|
-
|
42
51
|
def import( id )
|
43
|
-
data = read( id )
|
44
|
-
rec = Inscribe.
|
45
|
-
rec
|
46
|
-
|
47
|
-
|
48
|
-
def read( id )
|
49
|
-
_read_inscribe( "#{@dir}/#{id}.json" )
|
50
|
-
end
|
51
|
-
|
52
|
-
def _read_inscribe( path )
|
53
|
-
JSON.parse( _read_text( path ))
|
54
|
-
end
|
55
|
-
|
56
|
-
def _read_blob( path )
|
57
|
-
blob = File.open( path, 'rb' ) { |f| f.read }
|
58
|
-
## auto force to ASCII-7BIT if not already - why? why not?
|
59
|
-
blob
|
60
|
-
end
|
61
|
-
|
62
|
-
|
63
|
-
def _read_text( path )
|
64
|
-
File.open( path, 'r:utf-8' ){ |f| f.read }
|
65
|
-
end
|
66
|
-
|
67
|
-
def _parse_inscribe( data )
|
68
|
-
## num via title
|
69
|
-
attributes = {
|
70
|
-
id: data['id'],
|
71
|
-
num: _title_to_num( data['title'] ),
|
72
|
-
bytes: _content_length_to_bytes( data['content length'] ),
|
73
|
-
sat: data['sat'].to_i(10),
|
74
|
-
content_type: data['content type'],
|
75
|
-
block: data['genesis height'].to_i(10),
|
76
|
-
fee: data['genesis fee'].to_i(10),
|
77
|
-
tx: data['genesis transaction'],
|
78
|
-
address: data['address'],
|
79
|
-
output: data['output'],
|
80
|
-
value: data['output value'].to_i(10),
|
81
|
-
offset: data['offset'].to_i(10),
|
82
|
-
# "2023-06-01 05:00:57 UTC"
|
83
|
-
date: DateTime.strptime( data['timestamp'],
|
84
|
-
'%Y-%m-%d %H:%M:%S %z')
|
85
|
-
}
|
86
|
-
|
87
|
-
attributes
|
88
|
-
end
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
## "title": "Inscription 9992615",
|
93
|
-
TITLE_RX = /^Inscription (?<num>[0-9]+)$/i
|
94
|
-
|
95
|
-
def _title_to_num( str )
|
96
|
-
if m=TITLE_RX.match( str )
|
97
|
-
m[:num].to_i(10) ## use base 10
|
52
|
+
data = read( id )
|
53
|
+
rec = Inscribe.find_by( id: id )
|
54
|
+
if rec
|
55
|
+
# skip - already in db
|
98
56
|
else
|
99
|
-
|
100
|
-
exit 1 ## not found - raise exception - why? why not?
|
57
|
+
rec = Inscribe.create_from_cache( data )
|
101
58
|
end
|
102
59
|
end
|
103
60
|
|
104
|
-
CONTENT_LENGTH_RX = /^(?<num>[0-9]+) bytes$/i
|
105
|
-
|
106
|
-
def _content_length_to_bytes( str )
|
107
|
-
if m=CONTENT_LENGTH_RX.match( str )
|
108
|
-
m[:num].to_i(10) ## use base 10
|
109
|
-
else
|
110
|
-
puts "!! ERROR - bytes found in content lenght >#{str}<"
|
111
|
-
exit 1 ## not found - raise exception - why? why not?
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
end # class Cache
|
119
|
-
end # module OrdDb
|
120
|
-
|
121
|
-
|
122
61
|
|
62
|
+
end # class Cache
|
63
|
+
end # module Ordinals
|
123
64
|
|
@@ -0,0 +1,132 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
class FactorySpritesheet ## check - rename to catalog or atlas NOT spritesheet - why? why not?
|
4
|
+
def self.read_inscribes( *inscribes, width:,
|
5
|
+
height: )
|
6
|
+
## map inscribes to images
|
7
|
+
images = inscribes.map {|inscribe| Pixelart::Image.blob( inscribe.content ) }
|
8
|
+
## puts " #{images.size} image(s)"
|
9
|
+
|
10
|
+
new( *images, width: width,
|
11
|
+
height: height)
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize( *images, width:,
|
15
|
+
height: )
|
16
|
+
@tile_width = width
|
17
|
+
@tile_height = height
|
18
|
+
@tiles = []
|
19
|
+
images.each {|img| add(img) }
|
20
|
+
end
|
21
|
+
|
22
|
+
def count() @tiles.size; end
|
23
|
+
alias_method :size, :count
|
24
|
+
alias_method :tile_count, :count ## add tile_count - why? why not?
|
25
|
+
def tile_width() @tile_width; end ## use width - why? why not?
|
26
|
+
def tile_height() @tile_height; end ## use height - why? why not?
|
27
|
+
|
28
|
+
def tile( index ) @tiles[ index ]; end
|
29
|
+
alias_method :[], :tile
|
30
|
+
|
31
|
+
def add_inscribe( inscribe ) _add( Pixelart::Image.blob( inscribe.content )); end
|
32
|
+
def add( img )
|
33
|
+
## 1:1 tile; use as is
|
34
|
+
if img.width == @tile_width && img.height == @tile_height
|
35
|
+
@tiles << img
|
36
|
+
else ## assume spritesheet??
|
37
|
+
## wrap into composite image
|
38
|
+
composite = Pixelart::ImageComposite.new( img.image, width: @tile_width,
|
39
|
+
height: @tile_height )
|
40
|
+
cols = img.width / composite.tile_width
|
41
|
+
rows = img.height / composite.tile_height
|
42
|
+
puts " #{composite.count} tile(s) in #{cols}x#{rows} grid"
|
43
|
+
composite.each {|tile| @tiles << tile }
|
44
|
+
end
|
45
|
+
end
|
46
|
+
alias_method :<<, :add
|
47
|
+
end ## class Spritesheet
|
48
|
+
|
49
|
+
|
50
|
+
class FactoryGenerator
|
51
|
+
###################
|
52
|
+
## convenience setup helper(s)
|
53
|
+
def self.read_inscribes( *inscribes, width:,
|
54
|
+
height: )
|
55
|
+
new( FactorySpritesheet.read_inscribes( *inscribes,
|
56
|
+
width: width,
|
57
|
+
height: height ))
|
58
|
+
end
|
59
|
+
|
60
|
+
def initialize( spritesheet )
|
61
|
+
@spritesheet = spritesheet
|
62
|
+
end
|
63
|
+
|
64
|
+
def _parse( spec )
|
65
|
+
## for delimiter allow for now: - why? why not?
|
66
|
+
## (multiple) space ( )
|
67
|
+
## command or semicolon
|
68
|
+
spec.strip.split( %r{[ ,;/_-]+} ).map {|v| v.to_i(10) }
|
69
|
+
end
|
70
|
+
|
71
|
+
def parse( spec )
|
72
|
+
## convenience helper
|
73
|
+
## parses g spec in various (delimited) formats
|
74
|
+
g = _parse( spec )
|
75
|
+
generate( *g )
|
76
|
+
end
|
77
|
+
|
78
|
+
def generate( *attributes )
|
79
|
+
img = Pixelart::Image.new( width, height )
|
80
|
+
attributes.each do |num|
|
81
|
+
img.compose!( @spritesheet[ num ] )
|
82
|
+
end
|
83
|
+
img
|
84
|
+
end
|
85
|
+
alias_method :g, :generate
|
86
|
+
|
87
|
+
def width() @spritesheet.tile_width; end
|
88
|
+
def height() @spritesheet.tile_height; end
|
89
|
+
def count() @spritesheet.count; end
|
90
|
+
end # class FactoryGenerator
|
91
|
+
|
92
|
+
|
93
|
+
|
94
|
+
module OrdDb
|
95
|
+
module Model
|
96
|
+
|
97
|
+
class Factory
|
98
|
+
|
99
|
+
## use id/slug to cache generators / spritesheets - why? why not?
|
100
|
+
def self.generators
|
101
|
+
@generators ||= {}
|
102
|
+
end
|
103
|
+
|
104
|
+
def generator
|
105
|
+
generators = self.class.generators
|
106
|
+
if generators.has_key?( id )
|
107
|
+
generators[ id ]
|
108
|
+
else
|
109
|
+
## auto-add generator on first-time/hit/demand
|
110
|
+
width, height = _parse_dimension( dim )
|
111
|
+
inscribes = layers.to_a ## get layer inscribe records
|
112
|
+
generator = FactoryGenerator.read_inscribes( *inscribes,
|
113
|
+
width: width,
|
114
|
+
height: height )
|
115
|
+
generators[ id ] = generator
|
116
|
+
generator
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def generate( *attributes ) ## add g shortcut alias - why? why not?
|
121
|
+
generator.generate( *attributes )
|
122
|
+
end
|
123
|
+
|
124
|
+
|
125
|
+
## e.g. convert dimension (width x height) "24x24" or "24 x 24" to [24,24]
|
126
|
+
def _parse_dimension( str )
|
127
|
+
str.split( /x/i ).map { |str| str.strip.to_i(10) }
|
128
|
+
end
|
129
|
+
|
130
|
+
end # class Factory
|
131
|
+
end # module Model
|
132
|
+
end # module OrdDb
|