copycats 0.5.1 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
![](copycats-tables.png)
|
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
|