copycats 0.5.1 → 0.6.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 +4 -4
- data/README.md +131 -1
- data/lib/copycats/data.rb +144 -22
- data/lib/copycats/gene.rb +5 -0
- data/lib/copycats/models/kitty.rb +47 -1
- data/lib/copycats/reports/kitty.rb +1 -1
- data/lib/copycats/reports/mix.rb +2 -2
- data/lib/copycats/schema.rb +58 -4
- data/lib/copycats/tool.rb +65 -20
- data/lib/copycats/traits.rb +4 -2
- data/lib/copycats/version.rb +2 -2
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 30ab48ee0c735efb58576dbe0a5d3551bf75cf8b
|
|
4
|
+
data.tar.gz: 36b71fec5e5d77dcef7b7fd6bdfe49a9eac0faf4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6c4d1b2aa013871c099267ad5f37ea487c659c5863b4a00410b85a66b6b1095309386143d073f73f2e675248db6902a7b136217f0102fa3478be247f6a9ddae1
|
|
7
|
+
data.tar.gz: 77670aa204f204e0a82a3eb122d0a3b9ef4009d111af67fa37b2407b10a8606a530dda12619097131fb298a79938da12b596e965792335ba8d686ae085dd260a
|
data/README.md
CHANGED
|
@@ -33,7 +33,6 @@ get (auto-)read. Use the `-i/--include` option to change the data directory.
|
|
|
33
33
|
|
|
34
34
|
|
|
35
35
|
|
|
36
|
-
|
|
37
36
|
### Kitty Genes Reader / Report
|
|
38
37
|
|
|
39
38
|
Pass in the id (e.g. `1`, `43`, etc.) of the kitty to print a genes report.
|
|
@@ -239,6 +238,137 @@ Mouth (Genes 32-35)
|
|
|
239
238
|
|
|
240
239
|
|
|
241
240
|
|
|
241
|
+
## Database Tables
|
|
242
|
+
|
|
243
|
+
Table Diagram
|
|
244
|
+
|
|
245
|
+

|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
## Database Queries
|
|
249
|
+
|
|
250
|
+
### SQL
|
|
251
|
+
|
|
252
|
+
#### Find all kitties with a trait
|
|
253
|
+
|
|
254
|
+
Let's use the trait savannah (fur) with the id 0:
|
|
255
|
+
|
|
256
|
+
``` sql
|
|
257
|
+
SELECT id FROM kitties WHERE body_id = 0
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
#### Find all kitties with two traits
|
|
261
|
+
|
|
262
|
+
Let's use the trait savannah (fur) with the id 0
|
|
263
|
+
and the trait tiger (pattern) with the id 33:
|
|
264
|
+
|
|
265
|
+
``` sql
|
|
266
|
+
SELECT id FROM kitties
|
|
267
|
+
WHERE body_id = 0 AND pattern_id = 33
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
#### Find all kitties with a trait (in any gene d/r1/r2/r3)
|
|
272
|
+
|
|
273
|
+
Note: All traits (12 x 32 = 384) are numbered with ids from 0 to 383 in the traits database table.
|
|
274
|
+
Let's use the trait savannah (fur) with the id 0:
|
|
275
|
+
|
|
276
|
+
``` sql
|
|
277
|
+
SELECT kitty_id FROM genes WHERE trait_id = 0
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
#### Find all kitties with a dominant (visible) trait
|
|
282
|
+
|
|
283
|
+
Note: Use `gene` column (`d`/`r1`/`r2`/`r3`) or the numeric `gene_n`
|
|
284
|
+
column (0/1/2/3): Let's use the trait savannah (fur) with the id 0
|
|
285
|
+
and a dominant (d) gene:
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
``` sql
|
|
289
|
+
SELECT kitty_id FROM genes
|
|
290
|
+
WHERE trait_id = 0 AND gene='d'
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
#### Find all kitties with two traits (in any gene d/r1/r2/r3)
|
|
295
|
+
|
|
296
|
+
Use two query with "intersect" the result. Let's
|
|
297
|
+
use the trait savannah (fur) with the id 0
|
|
298
|
+
and the trait tiger (pattern) with the id 33:
|
|
299
|
+
|
|
300
|
+
``` sql
|
|
301
|
+
SELECT kitty_id FROM genes WHERE trait_id = 0
|
|
302
|
+
INTERSECT
|
|
303
|
+
SELECT kitty_id FROM genes WHERE trait_id = 33
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
### Using Models w/ ActiveRecord in Ruby
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
#### Find all kitties with a trait
|
|
311
|
+
|
|
312
|
+
Let's use the trait savannah (fur) with the id 0:
|
|
313
|
+
|
|
314
|
+
``` ruby
|
|
315
|
+
Kitty.find_by( body: Trait.find_by( name: 'savannah' ))
|
|
316
|
+
# -or -
|
|
317
|
+
Kitty.find_by( body_id: 0)
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
#### Find all kitties with two traits
|
|
321
|
+
|
|
322
|
+
Let's use the trait savannah (fur) with the id 0
|
|
323
|
+
and the trait tiger (pattern) with the id 33:
|
|
324
|
+
|
|
325
|
+
``` ruby
|
|
326
|
+
Kitty.find_by( body: Trait.find_by( name: 'savannah' ),
|
|
327
|
+
pattern: Trait.find_by( name: 'tiger' ))
|
|
328
|
+
# -or -
|
|
329
|
+
Kitty.find_by( body_id: 0, pattern_id: 33 )
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
#### Find all kitties with a trait (in any gene d/r1/r2/r3)
|
|
334
|
+
|
|
335
|
+
Let's use the trait savannah (fur) with the id 0:
|
|
336
|
+
|
|
337
|
+
``` ruby
|
|
338
|
+
genes = Gene.find_by( trait: Trait.find_by( name: 'savannah' )) # query
|
|
339
|
+
#-or-
|
|
340
|
+
genes = Gene.find_by( trait_id: 0 )
|
|
341
|
+
genes.map { |gene| gene.kitty } # get kitties (from gene)
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
#### Find all kitties with a dominant (visible) trait
|
|
346
|
+
|
|
347
|
+
Let's use the trait savannah (fur) with the id 0 and a dominant (d) gene:
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
``` ruby
|
|
351
|
+
genes = Gene.find_by( trait: Trait.find_by( name: 'savannah' ),
|
|
352
|
+
d: 'd' ) #query
|
|
353
|
+
#-or-
|
|
354
|
+
genes = Gene.find_by( trait_id: 0, d: 'd' )
|
|
355
|
+
genes.map { |gene| gene.kitty } # get kitties (from gene)
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
#### Find all kitties with two traits
|
|
360
|
+
|
|
361
|
+
Use two query with "intersect" the result. Let's
|
|
362
|
+
use the trait savannah (fur)
|
|
363
|
+
and the trait tiger (pattern):
|
|
364
|
+
|
|
365
|
+
``` ruby
|
|
366
|
+
genes = Gene.select('kitty_id').where( trait: Trait.find_by( name: 'savannah' )).intersect(
|
|
367
|
+
Gene.select('kitty_id').where( trait: Trait.find_by( name: 'pattern' )))
|
|
368
|
+
genes.map { |gene| gene.kitty } # get kitties (from gene)
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
|
|
242
372
|
|
|
243
373
|
## Quick References / Cheat Sheets
|
|
244
374
|
|
data/lib/copycats/data.rb
CHANGED
|
@@ -32,46 +32,95 @@ def connect( config={} )
|
|
|
32
32
|
database: db.path[1..-1],
|
|
33
33
|
encoding: 'utf8'
|
|
34
34
|
}
|
|
35
|
-
|
|
35
|
+
else # assume sqlite3
|
|
36
36
|
config = {
|
|
37
37
|
adapter: db.scheme, # sqlite3
|
|
38
38
|
database: db.path[1..-1] # world.db (NB: cut off leading /, thus 1..-1)
|
|
39
|
-
|
|
40
|
-
end
|
|
39
|
+
}
|
|
41
40
|
end
|
|
42
|
-
|
|
43
|
-
puts "Connecting to db using settings: "
|
|
44
|
-
pp config
|
|
45
|
-
ActiveRecord::Base.establish_connection( config )
|
|
46
|
-
# ActiveRecord::Base.logger = Logger.new( STDOUT )
|
|
47
41
|
end
|
|
48
42
|
|
|
49
43
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
44
|
+
puts "Connecting to db using settings: "
|
|
45
|
+
pp config
|
|
46
|
+
ActiveRecord::Base.establish_connection( config )
|
|
47
|
+
ActiveRecord::Base.logger = Logger.new( STDOUT )
|
|
54
48
|
## ActiveRecord::Base.colorize_logging = false - no longer exists - check new api/config setting?
|
|
55
49
|
|
|
56
|
-
|
|
57
|
-
|
|
50
|
+
## if sqlite3 add (use) some pragmas for speedups
|
|
51
|
+
if config[:adapter] == 'sqlite3'
|
|
52
|
+
## check/todo: if in memory e.g. ':memory:' no pragma needed!!
|
|
53
|
+
con = ActiveRecord::Base.connection
|
|
54
|
+
con.execute( 'PRAGMA synchronous=OFF;' )
|
|
55
|
+
con.execute( 'PRAGMA journal_mode=OFF;' )
|
|
56
|
+
con.execute( 'PRAGMA temp_store=MEMORY;' )
|
|
57
|
+
end
|
|
58
|
+
end ## method connect
|
|
59
|
+
|
|
58
60
|
|
|
61
|
+
def setup_db
|
|
59
62
|
## build schema
|
|
60
63
|
CreateDb.new.up
|
|
61
|
-
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
### todo/fix:
|
|
69
|
+
## make trait_ids_cache more (re)usable - fix global!!!!
|
|
70
|
+
TRAIT_IDS_CACHE = {}
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def setup_traits
|
|
74
|
+
## for speed - turn off logging for info/debug/etc. levels
|
|
75
|
+
ActiveRecord::Base.logger.level = :warn
|
|
76
|
+
|
|
77
|
+
### add traits
|
|
78
|
+
TRAITS.each do |trait_key, trait_hash|
|
|
79
|
+
|
|
80
|
+
trait_t = Copycats::Model::TraitType.new
|
|
81
|
+
trait_t.name = trait_hash[:name]
|
|
82
|
+
trait_t.key = trait_key.to_s
|
|
83
|
+
trait_t.save!
|
|
84
|
+
|
|
85
|
+
cache = {}
|
|
86
|
+
|
|
87
|
+
Kai::ALPHABET.each_char.with_index do |kai,n|
|
|
88
|
+
name = trait_hash[:kai][kai]
|
|
89
|
+
name = '?' if name.nil? || name.empty?
|
|
62
90
|
|
|
91
|
+
tier = Kai::TIER[kai]
|
|
63
92
|
|
|
93
|
+
puts "Kai: #{kai} (#{n}) /#{tier}, Cattribute: #{name}"
|
|
94
|
+
trait = Copycats::Model::Trait.new
|
|
95
|
+
trait.name = name
|
|
96
|
+
trait.kai = kai
|
|
97
|
+
trait.n = n
|
|
98
|
+
trait.tier = tier
|
|
99
|
+
trait.trait_type_id = trait_t.id
|
|
100
|
+
trait.save!
|
|
64
101
|
|
|
65
|
-
|
|
102
|
+
cache[ kai ] = trait.id
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
TRAIT_IDS_CACHE[ trait_key ] = { id: trait_t.id,
|
|
106
|
+
kai: cache }
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def read_datafiles( data_dir: './data' )
|
|
66
112
|
files = find_datafiles( data_dir )
|
|
67
113
|
pp files
|
|
68
114
|
|
|
69
|
-
## check if files found
|
|
115
|
+
## todo: check if files found
|
|
116
|
+
|
|
70
117
|
|
|
71
|
-
##
|
|
72
|
-
|
|
118
|
+
## for speed - turn off logging for info/debug/etc. levels
|
|
119
|
+
ActiveRecord::Base.logger.level = :warn
|
|
73
120
|
|
|
74
121
|
|
|
122
|
+
## pp TRAIT_IDS_CACHE
|
|
123
|
+
|
|
75
124
|
## add / read / load all datafiles
|
|
76
125
|
files.each_with_index do |file,i|
|
|
77
126
|
|
|
@@ -82,17 +131,90 @@ def setup( data_dir: './data' )
|
|
|
82
131
|
|
|
83
132
|
## note: for now use first 5 rows for testing
|
|
84
133
|
## kitties[0..4].each do |row|
|
|
134
|
+
|
|
135
|
+
## start of kitties blockchain / genesis
|
|
136
|
+
genesisdate = Date.new( 2017, 11, 23) ## 2017-11-23
|
|
137
|
+
|
|
85
138
|
kitties.each do |row|
|
|
86
139
|
## puts row['id'] + '|' + row['gen'] + '|' + row['genes_kai']
|
|
87
140
|
k = Copycats::Model::Kitty.new
|
|
88
|
-
k.id
|
|
89
|
-
k.gen
|
|
90
|
-
k.
|
|
141
|
+
k.id = row['id'].to_i
|
|
142
|
+
k.gen = row['gen'].to_i
|
|
143
|
+
k.matron_id = row['matron_id'] unless row['matron_id'].blank?
|
|
144
|
+
k.sire_id = row['sire_id'] unless row['sire_id'].blank?
|
|
145
|
+
k.name = row['name'] unless row['name'].blank?
|
|
146
|
+
|
|
147
|
+
## todo: pretty print (format genes_kai !!!!)
|
|
148
|
+
k.genes_kai = row['genes'] || row['genes_kai'] ### .gsub( ' ', '' ) ## remove all spaces - why? why not?
|
|
149
|
+
|
|
150
|
+
## pp row['birthdate']
|
|
151
|
+
birthdate = DateTime.strptime( row['birthdate'], '%Y-%m-%d %H:%M:%S' )
|
|
152
|
+
k.birthdate = birthdate
|
|
153
|
+
k.day_count = (birthdate.to_date.jd - genesisdate.jd)+1
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
genome = Genome.new( k.genes_kai )
|
|
157
|
+
genes = genome.genes
|
|
158
|
+
|
|
159
|
+
k.body_id = TRAIT_IDS_CACHE[:body][:kai][genes[:body].d]
|
|
160
|
+
k.pattern_id = TRAIT_IDS_CACHE[:pattern][:kai][genes[:pattern].d]
|
|
161
|
+
k.coloreyes_id = TRAIT_IDS_CACHE[:coloreyes][:kai][genes[:coloreyes].d]
|
|
162
|
+
k.eyes_id = TRAIT_IDS_CACHE[:eyes][:kai][genes[:eyes].d]
|
|
163
|
+
k.color1_id = TRAIT_IDS_CACHE[:color1][:kai][genes[:color1].d]
|
|
164
|
+
k.color2_id = TRAIT_IDS_CACHE[:color2][:kai][genes[:color2].d]
|
|
165
|
+
k.color3_id = TRAIT_IDS_CACHE[:color3][:kai][genes[:color3].d]
|
|
166
|
+
k.wild_id = TRAIT_IDS_CACHE[:wild][:kai][genes[:wild].d]
|
|
167
|
+
k.mouth_id = TRAIT_IDS_CACHE[:mouth][:kai][genes[:mouth].d]
|
|
168
|
+
|
|
91
169
|
## pp k
|
|
92
170
|
|
|
93
171
|
## print ids for progress report - why? why not?
|
|
94
172
|
print "#{k.id}."
|
|
95
173
|
k.save!
|
|
174
|
+
|
|
175
|
+
## add genes
|
|
176
|
+
TRAITS.each_with_index do |(trait_key, trait_hash),i|
|
|
177
|
+
gene = genes[trait_key]
|
|
178
|
+
next if gene.nil? ## skip future_1, future_2, etc. for now - add - why? why not?
|
|
179
|
+
|
|
180
|
+
## puts "#{trait_hash[:name]} (Genes #{trait_hash[:genes]})\n\n"
|
|
181
|
+
|
|
182
|
+
## note: start counting for d.n with 1 (NOT 0)
|
|
183
|
+
## use idx for zero-based counting - why? why not?
|
|
184
|
+
|
|
185
|
+
d = Copycats::Model::Gene.new
|
|
186
|
+
d.kitty_id = k.id
|
|
187
|
+
d.n = (i*4) # gene number/pos 0-47 (start w/ 1 why? why not?)
|
|
188
|
+
d.gene = 'd' # d (0), r1 (1), r2 (2), r3 (3)
|
|
189
|
+
d.gene_n = 0 # 0-3 (0=d,1=r1,2=r2,3=r3)
|
|
190
|
+
d.trait_id = TRAIT_IDS_CACHE[trait_key][:kai][gene.d]
|
|
191
|
+
d.save!
|
|
192
|
+
|
|
193
|
+
r1 = Copycats::Model::Gene.new
|
|
194
|
+
r1.kitty_id = k.id
|
|
195
|
+
r1.n = (i*4)+1 # gene number/pos 0-47 (start w/ 1 why? why not?)
|
|
196
|
+
r1.gene = 'r1' # d (0), r1 (1), r2 (2), r3 (3)
|
|
197
|
+
r1.gene_n = 1 # 0-3 (0=d,1=r1,2=r2,3=r3)
|
|
198
|
+
r1.trait_id = TRAIT_IDS_CACHE[trait_key][:kai][gene.r1]
|
|
199
|
+
r1.save!
|
|
200
|
+
|
|
201
|
+
r2 = Copycats::Model::Gene.new
|
|
202
|
+
r2.kitty_id = k.id
|
|
203
|
+
r2.n = (i*4)+2 # gene number/pos 0-47 (start w/ 1 why? why not?)
|
|
204
|
+
r2.gene = 'r2' # d (0), r1 (1), r2 (2), r3 (3)
|
|
205
|
+
r2.gene_n = 2 # 0-3 (0=d,1=r1,2=r2,3=r3)
|
|
206
|
+
r2.trait_id = TRAIT_IDS_CACHE[trait_key][:kai][gene.r2]
|
|
207
|
+
r2.save!
|
|
208
|
+
|
|
209
|
+
r3 = Copycats::Model::Gene.new
|
|
210
|
+
r3.kitty_id = k.id
|
|
211
|
+
r3.n = (i*4)+3 # gene number/pos 0-47 (start w/ 1 why? why not?)
|
|
212
|
+
r3.gene = 'r3' # d (0), r1 (1), r2 (2), r3 (3)
|
|
213
|
+
r3.gene_n = 3 # 0-3 (0=d,1=r1,2=r2,3=r3)
|
|
214
|
+
r3.trait_id = TRAIT_IDS_CACHE[trait_key][:kai][gene.r3]
|
|
215
|
+
r3.save!
|
|
216
|
+
end
|
|
217
|
+
|
|
96
218
|
end
|
|
97
219
|
print "\n"
|
|
98
220
|
end
|
data/lib/copycats/gene.rb
CHANGED
|
@@ -1,13 +1,59 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
2
|
|
|
3
|
+
##
|
|
4
|
+
# todo: rename file from kitty.rb to models.rb - why? why not?
|
|
5
|
+
# keep all models together in a single file? - why? why not?
|
|
6
|
+
|
|
7
|
+
|
|
3
8
|
module Copycats
|
|
4
9
|
module Model
|
|
5
10
|
|
|
6
11
|
class Kitty < ActiveRecord::Base
|
|
7
|
-
self.table_name = 'kitties'
|
|
12
|
+
## self.table_name = 'kitties'
|
|
13
|
+
|
|
14
|
+
has_many :genes
|
|
15
|
+
|
|
16
|
+
belongs_to :sire, class_name: 'Kitty', foreign_key: 'sire_id'
|
|
17
|
+
belongs_to :matron, class_name: 'Kitty', foreign_key: 'matron_id'
|
|
8
18
|
|
|
19
|
+
## convenience shortcuts for gene (d) traits
|
|
20
|
+
belongs_to :body, class_name: 'Trait', foreign_key: 'body_id'
|
|
21
|
+
belongs_to :pattern, class_name: 'Trait', foreign_key: 'pattern_id'
|
|
22
|
+
belongs_to :coloreyes, class_name: 'Trait', foreign_key: 'coloreyes_id'
|
|
23
|
+
belongs_to :eyes, class_name: 'Trait', foreign_key: 'eyes_id'
|
|
24
|
+
belongs_to :color1, class_name: 'Trait', foreign_key: 'color1_id'
|
|
25
|
+
belongs_to :color2, class_name: 'Trait', foreign_key: 'color2_id'
|
|
26
|
+
belongs_to :color3, class_name: 'Trait', foreign_key: 'color3_id'
|
|
27
|
+
belongs_to :wild, class_name: 'Trait', foreign_key: 'wild_id'
|
|
28
|
+
belongs_to :mouth, class_name: 'Trait', foreign_key: 'mouth_id'
|
|
29
|
+
|
|
30
|
+
## todo: add more genes convenience shortcuts
|
|
31
|
+
## has_many :genes_body
|
|
32
|
+
## has_many :genes_pattern
|
|
9
33
|
end # class Kitty
|
|
10
34
|
|
|
11
35
|
|
|
36
|
+
class TraitType < ActiveRecord::Base
|
|
37
|
+
## self.table_name = 'trait_types'
|
|
38
|
+
|
|
39
|
+
has_many :traits
|
|
40
|
+
end # class TraitType
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class Trait < ActiveRecord::Base
|
|
44
|
+
## self.table_name = 'traits'
|
|
45
|
+
|
|
46
|
+
belongs_to :trait_types
|
|
47
|
+
end # class Trait
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class Gene < ActiveRecord::Base
|
|
51
|
+
## self.table_name = 'genes'
|
|
52
|
+
|
|
53
|
+
belongs_to :kitty
|
|
54
|
+
end # class Gene
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
|
|
12
58
|
end # module Model
|
|
13
59
|
end # module Copycats
|
|
@@ -11,7 +11,7 @@ class KittyReport
|
|
|
11
11
|
## for now alsways assume ActiveRecord - Kitty::Model
|
|
12
12
|
kitty = args[0]
|
|
13
13
|
@id = kitty.id
|
|
14
|
-
@kai = fmt_kai( kitty.
|
|
14
|
+
@kai = fmt_kai( kitty.genes_kai ) ## pretty print in groups of four (4)
|
|
15
15
|
end
|
|
16
16
|
end
|
|
17
17
|
|
data/lib/copycats/reports/mix.rb
CHANGED
|
@@ -5,8 +5,8 @@ class MixReport
|
|
|
5
5
|
def initialize( matron, sire )
|
|
6
6
|
@matron_id = matron.id
|
|
7
7
|
@sire_id = sire.id
|
|
8
|
-
@matron_kai = fmt_kai( matron.
|
|
9
|
-
@sire_kai = fmt_kai( sire.
|
|
8
|
+
@matron_kai = fmt_kai( matron.genes_kai ) ## pretty print in groups of four (4)
|
|
9
|
+
@sire_kai = fmt_kai( sire.genes_kai )
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
|
data/lib/copycats/schema.rb
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
2
|
|
|
3
|
+
#######################
|
|
4
|
+
## yuml.me diagram:
|
|
5
|
+
|
|
6
|
+
=begin
|
|
7
|
+
[Kitties|id;gen;birthdate;day_count;genes_kai;name]1-<>48 (12x4)[Genes|n;gene;gene_n],
|
|
8
|
+
[Genes]0..*<>-1[Traits|n;kai;tier;name],
|
|
9
|
+
[Traits]32<>-1[Trait Types|name;key],
|
|
10
|
+
[Kitties]<-parents (matron x sire) [Kitties],
|
|
11
|
+
=end
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
3
16
|
class CreateDb
|
|
4
17
|
|
|
5
18
|
def up
|
|
@@ -9,10 +22,51 @@ ActiveRecord::Schema.define do
|
|
|
9
22
|
create_table :kitties do |t|
|
|
10
23
|
### t.integer :ref, null: false ## reference id - todo - find a better name e.g. uid (for unique id?) or gid?
|
|
11
24
|
## note: use built-in id for id!!!!
|
|
12
|
-
|
|
13
|
-
t.string
|
|
14
|
-
t.string
|
|
15
|
-
t.integer
|
|
25
|
+
|
|
26
|
+
t.string :name ## optional name e.g. Genesis, Galaxy Cat, etc.
|
|
27
|
+
t.string :genes_kai, null: false ## genes in kai format
|
|
28
|
+
t.integer :gen, null: false ## generation e.g. 0,1,2,etc.
|
|
29
|
+
t.datetime :birthdate, null: false
|
|
30
|
+
t.integer :day_count, null: false ## day 1, day 2, running day counter since 2017-11-23
|
|
31
|
+
|
|
32
|
+
t.references :matron ## optional references kitty (with matron id)
|
|
33
|
+
t.references :sire ## optional references kitty (with sire id)
|
|
34
|
+
|
|
35
|
+
## for easy queries add convenience gene-d for all traits
|
|
36
|
+
t.references :body, null: false ## gene 0 (d)
|
|
37
|
+
t.references :pattern, null: false ## gene 4 (d)
|
|
38
|
+
t.references :coloreyes, null: false ## gene 8 (d)
|
|
39
|
+
t.references :eyes, null: false ## gene 12 (d)
|
|
40
|
+
t.references :color1, null: false ## gene 16 (d)
|
|
41
|
+
t.references :color2, null: false ## gene 20 (d)
|
|
42
|
+
t.references :color3, null: false ## gene 24 (d)
|
|
43
|
+
t.references :wild, null: false ## gene 28 (d)
|
|
44
|
+
t.references :mouth, null: false ## gene 32 (d)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
create_table :genes do |t|
|
|
49
|
+
t.references :kitty, null: false
|
|
50
|
+
t.integer :n, null: false # gene number/pos 0-47 (start w/ 1 why? why not?)
|
|
51
|
+
|
|
52
|
+
t.string :gene, null: false # d, r1, r2, r3
|
|
53
|
+
t.integer :gene_n, null: false # 0-3 (0=d,1=r1,2=r2,3=r3 - start w/ 1 why? why not?)
|
|
54
|
+
|
|
55
|
+
t.references :trait, null: false
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
create_table :traits do |t|
|
|
60
|
+
t.references :trait_type, null: false
|
|
61
|
+
t.string :name, null: false
|
|
62
|
+
t.integer :n, null: false # 0-31 (decimal/base10)
|
|
63
|
+
t.string :kai, null: false # 1-x (kai/base32)
|
|
64
|
+
t.integer :tier # 1,2,3,4 - note: is nil (for x/31) for now (thus, optinal)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
create_table :trait_types do |t|
|
|
68
|
+
t.string :name, null: false # use "pretty" name e.g. fur, highlight color, etc.
|
|
69
|
+
t.string :key, null: false # use key/ lowercase name from "official json api"
|
|
16
70
|
end
|
|
17
71
|
|
|
18
72
|
|
data/lib/copycats/tool.rb
CHANGED
|
@@ -10,10 +10,21 @@ def run( args )
|
|
|
10
10
|
parser = OptionParser.new do |cmd|
|
|
11
11
|
cmd.banner = "Usage: kitty [options]"
|
|
12
12
|
|
|
13
|
+
cmd.separator ""
|
|
14
|
+
cmd.separator " Database options:"
|
|
15
|
+
|
|
16
|
+
cmd.on("-n", "--dbname=NAME", "Database name (default: kitties.db)") do |name|
|
|
17
|
+
opts[:db_name] = name
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
cmd.on("-d", "--dbpath=PATH", "Database path (default: .)") do |path|
|
|
21
|
+
opts[:db_path] = path
|
|
22
|
+
end
|
|
23
|
+
|
|
13
24
|
cmd.separator ""
|
|
14
25
|
cmd.separator " Data options:"
|
|
15
26
|
|
|
16
|
-
cmd.on("-i", "--include=DIR", "Data directory (default: ./data)") do |name|
|
|
27
|
+
cmd.on("-i", "--include=DIR", "Data directory (default: ./data for in-memory queries and . for setup)") do |name|
|
|
17
28
|
opts[:data_dir] = name
|
|
18
29
|
end
|
|
19
30
|
|
|
@@ -28,35 +39,69 @@ def run( args )
|
|
|
28
39
|
|
|
29
40
|
parser.parse!( args )
|
|
30
41
|
pp opts
|
|
42
|
+
pp args
|
|
31
43
|
|
|
32
44
|
|
|
33
|
-
|
|
45
|
+
db_path = opts[:db_path] || '.'
|
|
46
|
+
db_name = opts[:db_name] || 'kitties.db'
|
|
47
|
+
database = "#{db_path}/#{db_name}"
|
|
34
48
|
|
|
35
|
-
setup( data_dir: data_dir )
|
|
36
49
|
|
|
37
|
-
|
|
50
|
+
if args.size == 1 && args[0] == 'setup' ## setup database
|
|
51
|
+
connect( adapter: 'sqlite3',
|
|
52
|
+
database: database )
|
|
38
53
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
kitty = Copycats::Model::Kitty.find( id )
|
|
42
|
-
## pp k
|
|
54
|
+
setup_db
|
|
55
|
+
setup_traits # note: also builds TRAIT_IDS_CACHE for read_datafiles for now
|
|
43
56
|
|
|
44
|
-
|
|
57
|
+
data_dir = opts[:data_dir] || '.' ## for setup assume local dir for data
|
|
58
|
+
read_datafiles( data_dir: data_dir )
|
|
59
|
+
else
|
|
60
|
+
## check if (local) database exists?
|
|
61
|
+
if File.exist?( database ) ## if yes, use "cached" local database
|
|
62
|
+
connect( adapter: 'sqlite3',
|
|
63
|
+
database: database )
|
|
64
|
+
else ## otherwise use (new) on-demand in-memory database
|
|
65
|
+
puts "note: database >#{database}<; setting up in-memory database"
|
|
66
|
+
connect( adapter: 'sqlite3',
|
|
67
|
+
database: ':memory:' )
|
|
68
|
+
|
|
69
|
+
setup_db
|
|
70
|
+
setup_traits # note: also builds TRAIT_IDS_CACHE for read_datafiles for now
|
|
71
|
+
|
|
72
|
+
data_dir = opts[:data_dir] || './data'
|
|
73
|
+
read_datafiles( data_dir: data_dir )
|
|
74
|
+
end
|
|
45
75
|
|
|
46
|
-
puts buf
|
|
47
|
-
elsif args.size == 2
|
|
48
|
-
matron_id = args[0].to_i
|
|
49
|
-
sire_id = args[1].to_i
|
|
50
76
|
|
|
51
|
-
matron = Copycats::Model::Kitty.find( matron_id )
|
|
52
|
-
sire = Copycats::Model::Kitty.find( sire_id )
|
|
53
|
-
## pp matron
|
|
54
77
|
|
|
55
|
-
|
|
78
|
+
if args.size == 1
|
|
79
|
+
id = args[0].to_i
|
|
80
|
+
kitty = Copycats::Model::Kitty.find( id )
|
|
56
81
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
82
|
+
## pp kitty
|
|
83
|
+
## pp kitty.genes
|
|
84
|
+
## pp kitty.body
|
|
85
|
+
## pp kitty.pattern
|
|
86
|
+
## pp kitty.genes.to_a
|
|
87
|
+
|
|
88
|
+
buf = KittyReport.new( kitty ).build
|
|
89
|
+
|
|
90
|
+
puts buf
|
|
91
|
+
elsif args.size == 2
|
|
92
|
+
matron_id = args[0].to_i
|
|
93
|
+
sire_id = args[1].to_i
|
|
94
|
+
|
|
95
|
+
matron = Copycats::Model::Kitty.find( matron_id )
|
|
96
|
+
sire = Copycats::Model::Kitty.find( sire_id )
|
|
97
|
+
## pp matron
|
|
98
|
+
|
|
99
|
+
buf = MixReport.new( matron, sire ).build
|
|
100
|
+
|
|
101
|
+
puts buf
|
|
102
|
+
else
|
|
103
|
+
puts "error: too many arguments (expected setup or one or two kitty ids / names / genes)"
|
|
104
|
+
end
|
|
60
105
|
end
|
|
61
106
|
end ## method run
|
|
62
107
|
|
data/lib/copycats/traits.rb
CHANGED
|
@@ -5,9 +5,11 @@
|
|
|
5
5
|
# see https://cryptokittydex.com/kaittributes
|
|
6
6
|
# https://docs.google.com/spreadsheets/d/1ShiBKSglFAB2vJe4Uow3iF09FBVq6ZAaOzTCIECf4iA
|
|
7
7
|
# http://www.rolldice.club/cryptokitties/wkt_tree.php
|
|
8
|
+
# https://www.cryptokitties.co/cattributes (official cattributes list)
|
|
8
9
|
#
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
#
|
|
11
|
+
# for latest updates on new cattributes see:
|
|
12
|
+
# https://updates.cryptokitties.co (official latest updates/timeline)
|
|
11
13
|
|
|
12
14
|
## ordered by gene position (0,1,3.4,5,... etc.)
|
|
13
15
|
## 12 traits (4 genes each)
|
data/lib/copycats/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: copycats
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.6.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: 2018-03-
|
|
11
|
+
date: 2018-03-16 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activerecord
|