kittyverse 0.4.0 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Manifest.txt +1 -0
- data/README.md +2 -0
- data/lib/kittyverse.rb +2 -2
- data/lib/kittyverse/cattributes.rb +10 -2
- data/lib/kittyverse/config/fancies.rb +38 -14
- data/lib/kittyverse/config/purrstiges.rb +7 -7
- data/lib/kittyverse/config/traits.rb +51 -1
- data/lib/kittyverse/fancies.rb +93 -46
- data/lib/kittyverse/links.rb +9 -1
- data/lib/kittyverse/mewtations.rb +120 -117
- data/lib/kittyverse/pages/genes.rb +30 -37
- data/lib/kittyverse/recipes.rb +29 -0
- data/lib/kittyverse/traits.rb +70 -49
- data/lib/kittyverse/version.rb +1 -1
- data/test/test_fancies.rb +25 -0
- data/test/test_traits.rb +82 -4
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4216c923457a71aed326af9ffa9146848c4866ff
|
4
|
+
data.tar.gz: 4b2063cee7ba1b685581bbe1b915afff47701d5b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: abe587be776050fb01626c8cc4650c069e75c08201f31a847b2cd7e6f0b9bc107e2c1aab09e3e52e0b3d7fb3d1aa459e7280cdeaa7ddb83bb2ea3d4c013daf15
|
7
|
+
data.tar.gz: 8e7a2babf9c0110a75135e41c34f0572d6a4c77b0e64085e64bb309f6a5b8ef7b1f39133e20c0361e2eea3b0a31f7fbe21f452c70375593a78b23ea8b4a4de8f
|
data/Manifest.txt
CHANGED
data/README.md
CHANGED
@@ -206,6 +206,8 @@ end
|
|
206
206
|
Auto-generated CryptoKitties reference pages / cheat sheets include:
|
207
207
|
|
208
208
|
- [**CryptoKitties Cattributes Rarity / Popularity Statistics**](CATTRIBUTES.md)
|
209
|
+
- [**CryptoKitties Genome / Genes Cheat Sheet**](GENES.md) - Fur (FU) • Pattern (PA) • Eye Color (EC) • Eye Shape (ES) • Base Color (BC) • Highlight Color (HC) • Accent Color (AC) • Wild Element (WE) • Mouth (MO) • Environment (EN) • Secret Y Gene (SE) • Purrstige (PU)
|
210
|
+
- [**CryptoKitties Traits Cheat Sheet (with Codes, Mewtation Levels / Tiers, Search Links and More)**](TRAITS.md)
|
209
211
|
- [**CryptoKitties Updates - Fancy / Exclusive / Special Edition Cats - Timeline**](updates/FANCIES.md)
|
210
212
|
- [**CryptoKitties Updates - Purrstige Trait Recipes / Formulas - Timeline**](updates/PURRSTIGES.md)
|
211
213
|
- and others
|
data/lib/kittyverse.rb
CHANGED
@@ -23,7 +23,7 @@ require 'kittyverse/links'
|
|
23
23
|
|
24
24
|
require 'kittyverse/pages/genes'
|
25
25
|
|
26
|
-
|
26
|
+
require 'kittyverse/recipes'
|
27
27
|
require 'kittyverse/traits'
|
28
28
|
require 'kittyverse/cattributes'
|
29
29
|
require 'kittyverse/fancies'
|
@@ -31,4 +31,4 @@ require 'kittyverse/fancies'
|
|
31
31
|
|
32
32
|
|
33
33
|
# say hello
|
34
|
-
puts Kittyverse.banner if defined?($
|
34
|
+
puts Kittyverse.banner if defined?($RUBYCOCO_DEBUG) && $RUBYCOCO_DEBUG
|
@@ -36,7 +36,8 @@ class Cattribute
|
|
36
36
|
:key,
|
37
37
|
:name,
|
38
38
|
:traits,
|
39
|
-
:recipe
|
39
|
+
:recipe,
|
40
|
+
:count
|
40
41
|
|
41
42
|
def initialize( **kwargs )
|
42
43
|
update( kwargs )
|
@@ -107,12 +108,19 @@ class Cattribute
|
|
107
108
|
puts "key: #{key}"
|
108
109
|
pp h
|
109
110
|
|
111
|
+
recipe = Recipe.new(
|
112
|
+
traits: h[:recipe][:traits], ## todo/fix: turn strings into trait objs!!!!
|
113
|
+
limit: h[:recipe][:limit],
|
114
|
+
time_start: h[:recipe][:time] && h[:recipe][:time][:start] ? Date.strptime( h[:recipe][:time][:start], '%Y-%m-%d' ) : nil,
|
115
|
+
time_end: h[:recipe][:time] && h[:recipe][:time][:end] ? Date.strptime( h[:recipe][:time][:end], '%Y-%m-%d' ) : nil )
|
116
|
+
|
110
117
|
cattribute = Cattribute.new(
|
111
118
|
key: key,
|
112
119
|
name: h[:name],
|
113
120
|
type: tt,
|
114
121
|
traits: [], ## empty traits
|
115
|
-
|
122
|
+
count: h[:recipe][:count], # note: add count from recipe hash (NOT incl. in recipe struct)
|
123
|
+
recipe: recipe
|
116
124
|
)
|
117
125
|
tt.cattributes << cattribute
|
118
126
|
|
@@ -30,19 +30,41 @@
|
|
30
30
|
|
31
31
|
FANCIES =
|
32
32
|
{
|
33
|
+
'curdlin': { name: 'Curdlin',
|
34
|
+
recipe: {
|
35
|
+
time: { start: '2019-05-11', end: '2019-11-30' }, count: 4,
|
36
|
+
traits: ['nachocheez', 'saycheese', 'missmuffett', 'dippedcone']},
|
37
|
+
desc: 'Cheeze Wizard Cat - Celebrating the Launch of the Cheeze Wizards on the Blockchain'
|
38
|
+
## see https://www.cryptokitties.co/blog/post/things-are-getting-cheezy-in-cryptokitties
|
39
|
+
},
|
40
|
+
|
41
|
+
'kitt-e': { name: 'KITT-E', date: '2019-05-10',
|
42
|
+
specialedition: {
|
43
|
+
limit: 500 },
|
44
|
+
desc: 'Dapper (Crypto Contract) Wallet Promotion Cat'
|
45
|
+
},
|
46
|
+
'dapp-e': { name: 'DAPP-E', date: '2019-05-10',
|
47
|
+
exclusive: {
|
48
|
+
limit: 50, ids: (1829..1878).to_a },
|
49
|
+
desc: 'Dapper (Crypto Contract) Wallet Promotion Cat'
|
50
|
+
},
|
51
|
+
|
33
52
|
# Apr 27, 2019
|
34
53
|
# Krakitten Fancy Cat is discovered. Fancy Cat
|
35
54
|
krakitten: { name: 'Krakitten',
|
36
55
|
recipe: {
|
37
|
-
time: { start: '2019-04-27', end: '2019-05-06' },
|
38
|
-
traits: ['cobalt', 'ducky', 'salty', 'splat']}
|
56
|
+
time: { start: '2019-04-27', end: '2019-05-06' }, count: 1221,
|
57
|
+
traits: ['cobalt', 'ducky', 'salty', 'splat']},
|
58
|
+
## desc: 'Beware the Krakitten in the briny deep.'
|
39
59
|
},
|
40
60
|
# Apr 13, 2019
|
41
61
|
# Furbeard Fancy Cat is discovered. Fancy Cat
|
42
|
-
furbeard: { name: 'Furbeard',
|
62
|
+
furbeard: { name: 'Furbeard',
|
43
63
|
recipe: {
|
44
|
-
|
45
|
-
traits: ['inflatablepool', 'hanauma', 'neckbeard']}
|
64
|
+
time: { start: '2019-04-13', end: '2019-04-26'}, count: 3733,
|
65
|
+
traits: ['inflatablepool', 'hanauma', 'neckbeard']},
|
66
|
+
desc: 'Dread Pirate Cat' # Avast Ye! This Old Salt knows a few tricks: how to avoid a meowtiny, how to get out of swabbing the litter deck, and just where the captain's log is buried.
|
67
|
+
## see https://www.cryptokitties.co/blog/post/pirate-cats-are-plundering-cryptokitties/
|
46
68
|
},
|
47
69
|
|
48
70
|
# Apr 10, 2019
|
@@ -63,7 +85,7 @@ FANCIES =
|
|
63
85
|
# Glitter Fancy Cat is discovered. Fancy Cat
|
64
86
|
glitter: { name: 'Glitter',
|
65
87
|
recipe: {
|
66
|
-
time: { start: '2019-03-30', end: '2019-11-30'},
|
88
|
+
time: { start: '2019-03-30', end: '2019-11-30'}, count: 658, ## note: ++count NOT FINAL!!!
|
67
89
|
traits: ['rorschach', 'juju', 'unicorn', 'hyacinth'] }
|
68
90
|
},
|
69
91
|
|
@@ -118,14 +140,14 @@ FANCIES =
|
|
118
140
|
# Al Fancy Cat is discovered. Fancy Cat
|
119
141
|
al: { name: 'Al',
|
120
142
|
recipe: {
|
121
|
-
time: { start: '2019-02-17', end: '2019-12-01'},
|
143
|
+
time: { start: '2019-02-17', end: '2019-12-01'}, count: 3209, ## note: count NOT FINAL!!!
|
122
144
|
traits: ['munchkin','moue','cashewmilk','brownies'] }
|
123
145
|
},
|
124
146
|
# Feb 16, 2019
|
125
147
|
# Pizzazz Fancy Cat is discovered.Fancy Cat
|
126
148
|
pizzazz: { name: 'Pizzazz',
|
127
149
|
recipe: {
|
128
|
-
time: { start: '2019-02-16', end: '2019-12-01'},
|
150
|
+
time: { start: '2019-02-16', end: '2019-12-01'}, count: 1438, ## note: count NOT FINAL!!!
|
129
151
|
traits: ['mekong', 'scarlet', 'spangled', 'wonky'] }
|
130
152
|
},
|
131
153
|
|
@@ -138,11 +160,12 @@ FANCIES =
|
|
138
160
|
|
139
161
|
# Feb 9, 2019
|
140
162
|
# Miss Purrfect Fancy Cat is discovered.Fancy Cat
|
141
|
-
misspurrfect: { name: 'Miss Purrfect',
|
163
|
+
misspurrfect: { name: 'Miss Purrfect',
|
142
164
|
recipe: {
|
143
|
-
|
165
|
+
time: { start: '2019-02-09', end: '2019-02-14'}, count: 1298,
|
144
166
|
traits: ['allyouneed', 'butterscotch', 'asif', 'satiated', 'flapflap']},
|
145
167
|
desc: "Celebrating St. Valentine's Day 2019 (Feb/14th)"
|
168
|
+
## see https://www.cryptokitties.co/blog/post/how-to-breed-miss-purrfect/
|
146
169
|
},
|
147
170
|
|
148
171
|
## 2019
|
@@ -152,9 +175,10 @@ FANCIES =
|
|
152
175
|
# Squib Fancy Cat is discovered. Fancy Cat
|
153
176
|
squib: { name: 'Squib', date: '2019-01-26',
|
154
177
|
recipe: {
|
155
|
-
limit: 1443,
|
178
|
+
limit: 1443, ## todo/check: check if time-windows?
|
156
179
|
traits: ['oldlace', 'razzledazzle', 'buzzed', 'rollercoaster']},
|
157
180
|
desc: 'Celebrating American Football Super Bowl LIII in 2019'
|
181
|
+
## see https://www.cryptokitties.co/blog/post/how-to-breed-squib/
|
158
182
|
},
|
159
183
|
|
160
184
|
tallythepurrocious: { name: 'Tally The Purrocious',
|
@@ -195,7 +219,7 @@ FANCIES =
|
|
195
219
|
},
|
196
220
|
pawrula: { name: 'Pawrula the Bright',
|
197
221
|
recipe: {
|
198
|
-
time: { start: '2018-12-15', end: '2019-11-30' },
|
222
|
+
time: { start: '2018-12-15', end: '2019-11-30' }, count: 1952, ## note: count NOT FINAL!!!
|
199
223
|
traits: ['camo', 'butterscotch', 'fox'] },
|
200
224
|
desc: 'Neha Narula - Director of the Digital Currency Initiative at the MIT Media Lab'
|
201
225
|
},
|
@@ -367,7 +391,7 @@ FANCIES =
|
|
367
391
|
## May
|
368
392
|
page: { name: 'Page', date: '2018-05-31',
|
369
393
|
recipe: {
|
370
|
-
limit: 50_000,
|
394
|
+
limit: 50_000, count: 3936, ## note: count NOT FINAL!!!
|
371
395
|
traits: ['rascal', 'peach', 'wasntme' ]}
|
372
396
|
},
|
373
397
|
"schrödingerscat": { name: "Schrödinger's Cat", date: '2018-05-20',
|
@@ -512,7 +536,7 @@ FANCIES =
|
|
512
536
|
santaclaws: { name: 'Santa Claws', date: '2017-12-12',
|
513
537
|
recipe: {
|
514
538
|
limit: 1000, overflow: 2,
|
515
|
-
traits: ['cloudwhite','scarlet','beard','
|
539
|
+
traits: ['cloudwhite','scarlet','beard','WE12'] },
|
516
540
|
desc: 'Ho Ho Ho - Santa Claus Kitty'
|
517
541
|
},
|
518
542
|
mistletoe: { name: 'Mistletoe', date: '2017-12-09',
|
@@ -57,43 +57,43 @@ squelch: { name: 'Squelch',
|
|
57
57
|
# Scratchingpost trait is discovered. Purrstige
|
58
58
|
scratchingpost: { name: 'Scratchingpost',
|
59
59
|
recipe: {
|
60
|
-
time: { start: '2019-04-13', end: '2019-05-10' },
|
60
|
+
time: { start: '2019-04-13', end: '2019-05-10' }, count: 772,
|
61
61
|
traits: ['WE10', 'PU26'] }
|
62
62
|
},
|
63
63
|
# Hooked trait is discovered. Purrstige
|
64
64
|
hooked: { name: 'Hooked',
|
65
65
|
recipe: {
|
66
|
-
time: { start: '2019-04-13', end: '2019-05-10' },
|
66
|
+
time: { start: '2019-04-13', end: '2019-05-10' }, count: 1277,
|
67
67
|
traits: ['WE10', 'PU27'] }
|
68
68
|
},
|
69
69
|
# Landlubber trait is discovered. Purrstige
|
70
70
|
landlubber: { name: 'Landlubber',
|
71
71
|
recipe: {
|
72
|
-
time: { start: '2019-04-13', end: '2019-05-10' },
|
72
|
+
time: { start: '2019-04-13', end: '2019-05-10' }, count: 711,
|
73
73
|
traits: ['WE10', 'PU29'] }
|
74
74
|
},
|
75
75
|
# Wrecked trait is discovered. Purrstige
|
76
76
|
wrecked: { name: 'Wrecked',
|
77
77
|
recipe: {
|
78
|
-
time: { start: '2019-04-13', end: '2019-05-10' },
|
78
|
+
time: { start: '2019-04-13', end: '2019-05-10' }, count: 959,
|
79
79
|
traits: ['EN00', 'PU26'] }
|
80
80
|
},
|
81
81
|
# Purrbados trait is discovered. Purrstige
|
82
82
|
purrbados: { name: 'Purrbados',
|
83
83
|
recipe: {
|
84
|
-
time: { start: '2019-04-13', end: '2019-05-10' },
|
84
|
+
time: { start: '2019-04-13', end: '2019-05-10' }, count: 1344,
|
85
85
|
traits: ['EN01', 'PU26'] }
|
86
86
|
},
|
87
87
|
# Timbers trait is discovered. Purrstige
|
88
88
|
timbers: { name: 'Timbers',
|
89
89
|
recipe: {
|
90
|
-
time: { start: '2019-04-13', end: '2019-05-10' },
|
90
|
+
time: { start: '2019-04-13', end: '2019-05-10' }, count: 472,
|
91
91
|
traits: ['WE10', 'EN00', 'PU26'] }
|
92
92
|
},
|
93
93
|
# Maraud trait is discovered. Purrstige
|
94
94
|
maraud: { name: 'Maraud',
|
95
95
|
recipe: {
|
96
|
-
time: { start: '2019-04-13', end: '2019-05-10' },
|
96
|
+
time: { start: '2019-04-13', end: '2019-05-10' }, count: 620,
|
97
97
|
traits: ['WE10', 'EN01', 'PU26'] }
|
98
98
|
},
|
99
99
|
|
@@ -95,7 +95,7 @@ TRAITS =
|
|
95
95
|
genes: '8-11',
|
96
96
|
name: 'Eye Color', code: 'EC',
|
97
97
|
kai: {
|
98
|
-
'1' => '
|
98
|
+
'1' => 'Thundergrey',
|
99
99
|
'2' => 'Gold',
|
100
100
|
'3' => 'Topaz',
|
101
101
|
'4' => 'Mintgreen',
|
@@ -375,3 +375,53 @@ TRAITS =
|
|
375
375
|
## prune, furball, duckduckcat, or thatsawrap - more like fancies (not really traits)
|
376
376
|
}
|
377
377
|
}
|
378
|
+
|
379
|
+
|
380
|
+
# quick hack - map copycats keys to (internal) cryptokitties trait type keys
|
381
|
+
# note: all keys are the same except:
|
382
|
+
ALT_TRAIT_TYPE_KEYS =
|
383
|
+
{
|
384
|
+
:color1 => :colorprimary,
|
385
|
+
:color2 => :colorsecondary,
|
386
|
+
:color3 => :colortertiary,
|
387
|
+
:purrstige => :prestige,
|
388
|
+
## add :fur, etc. too - why? why not?
|
389
|
+
}
|
390
|
+
|
391
|
+
ALT_TRAIT_TYPE_NAMES =
|
392
|
+
{
|
393
|
+
'body' => 'fur',
|
394
|
+
'eyes' => 'eye shape',
|
395
|
+
'eye type' => 'eye shape',
|
396
|
+
'body color' => 'base color',
|
397
|
+
'primary color' => 'base color',
|
398
|
+
'base colour' => 'base color', # british (canadian) spelling
|
399
|
+
'secondary color' => 'highlight color',
|
400
|
+
'sec color' => 'highlight color',
|
401
|
+
'pattern color' => 'highlight color',
|
402
|
+
'highlight colour' => 'highlight color', # british (canadian) spelling
|
403
|
+
'tertiary color' => 'accent color',
|
404
|
+
'accent colour' => 'accent color', # british (canadian) spelling
|
405
|
+
'wild' => 'wild element',
|
406
|
+
'secret' => 'secret y gene',
|
407
|
+
'prestige' => 'purrstige',
|
408
|
+
}
|
409
|
+
|
410
|
+
ALT_TRAIT_NAMES =
|
411
|
+
{
|
412
|
+
'totesbasic (14)' => 'totesbasic 1',
|
413
|
+
'totesbasic (15)' => 'totesbasic 2',
|
414
|
+
'totesbasic (23)' => 'totesbasic 3',
|
415
|
+
'totesbasic_14' => 'totesbasic 1',
|
416
|
+
'totesbasic_15' => 'totesbasic 2',
|
417
|
+
'totesbasic_23' => 'totesbasic 3',
|
418
|
+
'totesbasic (f)' => 'totesbasic 1',
|
419
|
+
'totesbasic (g)' => 'totesbasic 2',
|
420
|
+
'totesbasic (p)' => 'totesbasic 3',
|
421
|
+
'totesbasic_f' => 'totesbasic 1',
|
422
|
+
'totesbasic_g' => 'totesbasic 2',
|
423
|
+
'totesbasic_p' => 'totesbasic 3',
|
424
|
+
'totesbasic_1' => 'totesbasic 1',
|
425
|
+
'totesbasic_2' => 'totesbasic 2',
|
426
|
+
'totesbasic_3' => 'totesbasic 3',
|
427
|
+
}
|
data/lib/kittyverse/fancies.rb
CHANGED
@@ -3,12 +3,6 @@
|
|
3
3
|
|
4
4
|
class Fancy
|
5
5
|
|
6
|
-
def self.special_editions() @@special_editions ||= []; end # special edition fancies
|
7
|
-
def self.exclusives() @@exclusives ||= []; end # exclusive fancies
|
8
|
-
def self.fancies() @@fancies ||= []; end # "normal" fancies
|
9
|
-
|
10
|
-
|
11
|
-
|
12
6
|
def self.fancies_by_key() @@fancies_by_key ||= {}; end
|
13
7
|
def self.fancies_by_name() @@fancies_by_name ||= {}; end
|
14
8
|
|
@@ -54,6 +48,23 @@ class Fancy
|
|
54
48
|
end
|
55
49
|
end
|
56
50
|
|
51
|
+
|
52
|
+
def self.special_editions # special edition fancies
|
53
|
+
@@fancies_by_key.values.select { |fancy| fancy.special_edition? }
|
54
|
+
end
|
55
|
+
def self.exclusives # exclusive fancies
|
56
|
+
@@fancies_by_key.values.select { |fancy| fancy.exclusive? }
|
57
|
+
end
|
58
|
+
def self.fancies # "normal" fancies
|
59
|
+
@@fancies_by_key.values.select { |fancy| fancy.recipe? }
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.breedable ## todo: find a better name (or add alias) e.g. use unlocked why? why not?
|
63
|
+
today = Date.today
|
64
|
+
@@fancies_by_key.values.select { |fancy| fancy.breedable?( today ) }
|
65
|
+
end
|
66
|
+
|
67
|
+
|
57
68
|
def self.size() @@fancies_by_key.size; end ## todo: add length alias too? why? why not?
|
58
69
|
|
59
70
|
|
@@ -70,9 +81,12 @@ class Fancy
|
|
70
81
|
:recipe,
|
71
82
|
:count,
|
72
83
|
:limit,
|
73
|
-
:ids
|
84
|
+
:ids,
|
85
|
+
:time_start,
|
86
|
+
:time_end
|
74
87
|
|
75
88
|
def initialize( **kwargs )
|
89
|
+
@exclusive = @specialedition = @recipe = nil
|
76
90
|
update( kwargs )
|
77
91
|
end
|
78
92
|
|
@@ -88,64 +102,97 @@ class Fancy
|
|
88
102
|
alias_method :special_edition?, :specialedition?
|
89
103
|
def recipe?() @recipe.nil? == false; end
|
90
104
|
|
105
|
+
def overflow?() @count && @limit && @count > @limit; end
|
106
|
+
def overflow() @count - @limit; end ## todo: check for count limit set - why? why not?
|
107
|
+
def limit?() @limit; end
|
108
|
+
def count?() @count; end
|
109
|
+
|
110
|
+
def time?() @time_start && @time_end; end ## is fancy(recipe,specialedition) time windowed? true/false
|
111
|
+
|
112
|
+
def time_days() (@time_end.jd - @time_start.jd) + 1; end
|
113
|
+
|
114
|
+
|
115
|
+
def unlocked?( today=Date.today )
|
116
|
+
if @recipe
|
117
|
+
if @recipe.time? ## time windowed recipe
|
118
|
+
if @recipe.time_end >= today
|
119
|
+
true
|
120
|
+
else
|
121
|
+
false
|
122
|
+
end
|
123
|
+
else ## assume limit
|
124
|
+
if @count && @count < @limit
|
125
|
+
true
|
126
|
+
else
|
127
|
+
false
|
128
|
+
end
|
129
|
+
end
|
130
|
+
else
|
131
|
+
false
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
alias_method :breedable?, :unlocked?
|
136
|
+
|
137
|
+
def locked?( today=Date.today ) !unlocked?( today ); end
|
91
138
|
|
92
139
|
|
93
|
-
|
140
|
+
###########################################
|
141
|
+
## auto-fill fancies
|
94
142
|
FANCIES.each do |key,h|
|
95
143
|
|
144
|
+
name = h[:name]
|
145
|
+
name_cn = h[:name_cn] # add chinese name if present
|
146
|
+
|
96
147
|
date_str = h[:date]
|
97
148
|
date_str = h[:recipe][:time][:start] if date_str.nil? && h[:recipe]
|
98
149
|
date_str = h[:specialedition][:time][:start] if date_str.nil? && h[:specialedition]
|
99
150
|
|
100
151
|
date = Date.strptime( date_str, '%Y-%m-%d' )
|
101
152
|
|
102
|
-
|
103
|
-
name = h[:name]
|
104
|
-
name_cn = h[:name_cn] # add chinese name if present
|
105
|
-
desc = h[:desc]
|
106
|
-
|
107
|
-
exclusive = h[:exclusive]
|
108
|
-
specialedition = h[:specialedition]
|
109
|
-
recipe = h[:recipe]
|
110
|
-
|
111
153
|
attribs = {
|
112
154
|
key: key,
|
113
|
-
date: date,
|
114
155
|
name: name,
|
115
156
|
name_cn: name_cn,
|
116
|
-
|
117
|
-
|
118
|
-
specialedition: specialedition,
|
119
|
-
recipe: recipe,
|
157
|
+
date: date,
|
158
|
+
desc: h[:desc]
|
120
159
|
}
|
121
160
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
161
|
+
attribs = if h[:exclusive]
|
162
|
+
attribs.merge( exclusive: true,
|
163
|
+
limit: h[:exclusive][:limit],
|
164
|
+
ids: h[:exclusive][:ids] )
|
165
|
+
elsif h[:specialedition]
|
166
|
+
attribs.merge( specialedition: true,
|
167
|
+
limit: h[:specialedition][:limit],
|
168
|
+
time_start: h[:specialedition][:time] && h[:specialedition][:time][:start] ? Date.strptime( h[:specialedition][:time][:start], '%Y-%m-%d' ) : nil,
|
169
|
+
time_end: h[:specialedition][:time] && h[:specialedition][:time][:end] ? Date.strptime( h[:specialedition][:time][:end], '%Y-%m-%d' ) : nil )
|
170
|
+
else ## assume "normal/regular" fancy with recipes
|
171
|
+
pp h[:recipe]
|
172
|
+
recipe = Recipe.new(
|
173
|
+
traits: h[:recipe][:traits], ## todo/fix: turn strings into trait objs!!!!
|
174
|
+
variants: h[:recipe][:variants], ## todo/fix: turn variant hash into variant ??? - why? why not?
|
175
|
+
limit: h[:recipe][:limit],
|
176
|
+
time_start: h[:recipe][:time] && h[:recipe][:time][:start] ? Date.strptime( h[:recipe][:time][:start], '%Y-%m-%d' ) : nil,
|
177
|
+
time_end: h[:recipe][:time] && h[:recipe][:time][:end] ? Date.strptime( h[:recipe][:time][:end], '%Y-%m-%d' ) : nil )
|
178
|
+
|
179
|
+
## note: support overflow "shortcut" - overflow+limit => count
|
180
|
+
count = if h[:recipe][:overflow]
|
181
|
+
recipe.limit + h[:recipe][:overflow]
|
182
|
+
else
|
183
|
+
h[:recipe][:count]
|
184
|
+
end
|
185
|
+
|
186
|
+
attribs.merge( recipe: recipe,
|
187
|
+
limit: recipe.limit,
|
188
|
+
time_start: recipe.time_start,
|
189
|
+
time_end: recipe.time_end,
|
190
|
+
count: count )
|
191
|
+
end
|
136
192
|
|
137
193
|
|
138
194
|
fancy = Fancy.new( **attribs )
|
139
|
-
pp fancy
|
140
|
-
|
141
|
-
if fancy.exclusive?
|
142
|
-
exclusives << fancy
|
143
|
-
elsif fancy.special_edition?
|
144
|
-
special_editions << fancy
|
145
|
-
else ## assume "normal/regular" fancy (with recipe)
|
146
|
-
fancies << fancy
|
147
|
-
end
|
148
|
-
|
195
|
+
## pp fancy
|
149
196
|
|
150
197
|
## note: key MUST be a symbol (NOT a string)
|
151
198
|
fancies_by_key[key] = fancy
|
data/lib/kittyverse/links.rb
CHANGED
@@ -40,10 +40,18 @@ def kitties_specialedition_search_url( fancy ) kitties_fancy_search_url( fancy )
|
|
40
40
|
################################
|
41
41
|
# /media - image links
|
42
42
|
|
43
|
-
def
|
43
|
+
def media_fancy_url( key, variant_key=nil ) ### todo: find a better name - why? why not?
|
44
44
|
if variant_key
|
45
45
|
"https://cryptocopycats.github.io/media/kitties/100x100/fancy-#{key}-#{variant_key}.png"
|
46
46
|
else
|
47
47
|
"https://cryptocopycats.github.io/media/kitties/100x100/fancy-#{key}.png"
|
48
48
|
end
|
49
49
|
end
|
50
|
+
|
51
|
+
## (old) alias for media_fany_url
|
52
|
+
def media_fancy_pic_url( key, variant_key=nil ) media_fancy_url( key, variant_key ); end
|
53
|
+
|
54
|
+
|
55
|
+
def media_icon_url( key ) ## note: use :unlocked, :locked, etc.
|
56
|
+
"https://cryptocopycats.github.io/media/icons/18x18/#{key}.png"
|
57
|
+
end
|
@@ -1,117 +1,120 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
# Tier
|
6
|
-
# Tier
|
7
|
-
# Tier
|
8
|
-
# Tier
|
9
|
-
#
|
10
|
-
|
11
|
-
|
12
|
-
'1' => 0,
|
13
|
-
'2' => 0,
|
14
|
-
'3' => 0,
|
15
|
-
'4' => 0,
|
16
|
-
'5' => 0,
|
17
|
-
'6' => 0,
|
18
|
-
'7' => 0,
|
19
|
-
'8' => 0,
|
20
|
-
'9' => 0,
|
21
|
-
'a' => 0,
|
22
|
-
'b' => 0,
|
23
|
-
'c' => 0,
|
24
|
-
'd' => 0,
|
25
|
-
'e' => 0,
|
26
|
-
'f' => 0,
|
27
|
-
'g' => 0,
|
28
|
-
'h' => 1,
|
29
|
-
'i' => 1,
|
30
|
-
'j' => 1,
|
31
|
-
'k' => 1,
|
32
|
-
'm' => 1,
|
33
|
-
'n' => 1,
|
34
|
-
'o' => 1,
|
35
|
-
'p' => 1,
|
36
|
-
'q' => 2,
|
37
|
-
'r' => 2,
|
38
|
-
's' => 2,
|
39
|
-
't' => 2,
|
40
|
-
'u' => 3,
|
41
|
-
'v' => 3,
|
42
|
-
'w' => 4,
|
43
|
-
'x' => nil
|
44
|
-
}
|
45
|
-
|
46
|
-
## (quick 'n' dirty) kai to mutation/mewtation level (I,II,III,IIII)
|
47
|
-
|
48
|
-
'1' => '',
|
49
|
-
'2' => '',
|
50
|
-
'3' => '',
|
51
|
-
'4' => '',
|
52
|
-
'5' => '',
|
53
|
-
'6' => '',
|
54
|
-
'7' => '',
|
55
|
-
'8' => '',
|
56
|
-
'9' => '',
|
57
|
-
'a' => '',
|
58
|
-
'b' => '',
|
59
|
-
'c' => '',
|
60
|
-
'd' => '',
|
61
|
-
'e' => '',
|
62
|
-
'f' => '',
|
63
|
-
'g' => '',
|
64
|
-
'h' => 'I',
|
65
|
-
'i' => 'I',
|
66
|
-
'j' => 'I',
|
67
|
-
'k' => 'I',
|
68
|
-
'm' => 'I',
|
69
|
-
'n' => 'I',
|
70
|
-
'o' => 'I',
|
71
|
-
'p' => 'I',
|
72
|
-
'q' => 'II',
|
73
|
-
'r' => 'II',
|
74
|
-
's' => 'II',
|
75
|
-
't' => 'II',
|
76
|
-
'u' => 'III',
|
77
|
-
'v' => 'III',
|
78
|
-
'w' => 'IIII',
|
79
|
-
'x' => ''
|
80
|
-
}
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
'
|
85
|
-
'
|
86
|
-
'
|
87
|
-
'
|
88
|
-
'
|
89
|
-
'
|
90
|
-
'
|
91
|
-
'
|
92
|
-
'
|
93
|
-
'
|
94
|
-
'
|
95
|
-
'
|
96
|
-
'
|
97
|
-
'
|
98
|
-
'
|
99
|
-
'
|
100
|
-
'
|
101
|
-
'
|
102
|
-
'
|
103
|
-
'
|
104
|
-
'
|
105
|
-
'
|
106
|
-
'
|
107
|
-
'
|
108
|
-
'
|
109
|
-
'
|
110
|
-
'
|
111
|
-
'
|
112
|
-
'
|
113
|
-
'
|
114
|
-
'
|
115
|
-
|
116
|
-
|
117
|
-
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
##################################
|
4
|
+
# Tier 0 (Base) (1-g)
|
5
|
+
# Tier 1 (Mewtation I) (h-p)
|
6
|
+
# Tier 2 (Mewtation II) (q-t)
|
7
|
+
# Tier 3 (Mewtation III) (u,v)
|
8
|
+
# Tier 4 (Mewtation IIII) (w) # note: use IIII instead of IV
|
9
|
+
#
|
10
|
+
|
11
|
+
MUTATION_TIER = { ## todo/fix: use an algo to calculate - why? why not?
|
12
|
+
'1' => 0,
|
13
|
+
'2' => 0,
|
14
|
+
'3' => 0,
|
15
|
+
'4' => 0,
|
16
|
+
'5' => 0,
|
17
|
+
'6' => 0,
|
18
|
+
'7' => 0,
|
19
|
+
'8' => 0,
|
20
|
+
'9' => 0,
|
21
|
+
'a' => 0,
|
22
|
+
'b' => 0,
|
23
|
+
'c' => 0,
|
24
|
+
'd' => 0,
|
25
|
+
'e' => 0,
|
26
|
+
'f' => 0,
|
27
|
+
'g' => 0,
|
28
|
+
'h' => 1,
|
29
|
+
'i' => 1,
|
30
|
+
'j' => 1,
|
31
|
+
'k' => 1,
|
32
|
+
'm' => 1,
|
33
|
+
'n' => 1,
|
34
|
+
'o' => 1,
|
35
|
+
'p' => 1,
|
36
|
+
'q' => 2,
|
37
|
+
'r' => 2,
|
38
|
+
's' => 2,
|
39
|
+
't' => 2,
|
40
|
+
'u' => 3,
|
41
|
+
'v' => 3,
|
42
|
+
'w' => 4,
|
43
|
+
'x' => nil
|
44
|
+
}
|
45
|
+
|
46
|
+
## (quick 'n' dirty) kai to mutation/mewtation tier level in roman numerals (I,II,III,IIII) - as strings (and nil)
|
47
|
+
MUTATION_TIER_ROMAN = {
|
48
|
+
'1' => '',
|
49
|
+
'2' => '',
|
50
|
+
'3' => '',
|
51
|
+
'4' => '',
|
52
|
+
'5' => '',
|
53
|
+
'6' => '',
|
54
|
+
'7' => '',
|
55
|
+
'8' => '',
|
56
|
+
'9' => '',
|
57
|
+
'a' => '',
|
58
|
+
'b' => '',
|
59
|
+
'c' => '',
|
60
|
+
'd' => '',
|
61
|
+
'e' => '',
|
62
|
+
'f' => '',
|
63
|
+
'g' => '',
|
64
|
+
'h' => 'I',
|
65
|
+
'i' => 'I',
|
66
|
+
'j' => 'I',
|
67
|
+
'k' => 'I',
|
68
|
+
'm' => 'I',
|
69
|
+
'n' => 'I',
|
70
|
+
'o' => 'I',
|
71
|
+
'p' => 'I',
|
72
|
+
'q' => 'II',
|
73
|
+
'r' => 'II',
|
74
|
+
's' => 'II',
|
75
|
+
't' => 'II',
|
76
|
+
'u' => 'III',
|
77
|
+
'v' => 'III',
|
78
|
+
'w' => 'IIII',
|
79
|
+
'x' => '' ## Use nil and NOT empty string "" - why? why not?
|
80
|
+
}
|
81
|
+
|
82
|
+
MUTATION_PAIR = {
|
83
|
+
'1' => '', ## todo: use nil for "" - why? why not?
|
84
|
+
'2' => '',
|
85
|
+
'3' => '',
|
86
|
+
'4' => '',
|
87
|
+
'5' => '',
|
88
|
+
'6' => '',
|
89
|
+
'7' => '',
|
90
|
+
'8' => '',
|
91
|
+
'9' => '',
|
92
|
+
'a' => '',
|
93
|
+
'b' => '',
|
94
|
+
'c' => '',
|
95
|
+
'd' => '',
|
96
|
+
'e' => '',
|
97
|
+
'f' => '',
|
98
|
+
'g' => '',
|
99
|
+
'h' => '1+2',
|
100
|
+
'i' => '3+4',
|
101
|
+
'j' => '5+6',
|
102
|
+
'k' => '7+8',
|
103
|
+
'm' => '9+a',
|
104
|
+
'n' => 'b+c',
|
105
|
+
'o' => 'd+e',
|
106
|
+
'p' => 'f+g',
|
107
|
+
'q' => 'h+i',
|
108
|
+
'r' => 'j+k',
|
109
|
+
's' => 'm+n',
|
110
|
+
't' => 'o+p',
|
111
|
+
'u' => 'q+r',
|
112
|
+
'v' => 's+t',
|
113
|
+
'w' => 'u+v',
|
114
|
+
'x' => ''
|
115
|
+
}
|
116
|
+
|
117
|
+
## add alias(es)
|
118
|
+
MEWTATION_TIER = MUTATION_TIER
|
119
|
+
MEWTATION_TIER_ROMAN = MUTATION_TIER_ROMAN
|
120
|
+
MEWTATION_PAIR = MUTATION_PAIR
|
@@ -5,39 +5,22 @@ class GenesPage
|
|
5
5
|
|
6
6
|
def build
|
7
7
|
buf = ""
|
8
|
-
buf << "# Genes (#{
|
8
|
+
buf << "# Genes (#{TraitType.size} x 4)\n\n"
|
9
9
|
|
10
10
|
headings = []
|
11
|
-
|
12
|
-
|
11
|
+
TraitType.each do |tt|
|
12
|
+
anchor = "#{tt.name} #{tt.code}".downcase.gsub( ' ', '-' )
|
13
|
+
headings << "[#{tt.name} (#{tt.code})](##{anchor})"
|
13
14
|
end
|
14
15
|
|
15
16
|
buf << headings.join( " • " )
|
16
17
|
buf << "\n\n"
|
17
18
|
|
18
19
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
Kai::ALPHABET.each do |kai|
|
24
|
-
value = trait[:kai][kai]
|
25
|
-
code = "#{trait[:code]}%02d" % Kai::NUMBER[kai] ## e.g. FU00, FU01, FU02, etc.
|
26
|
-
if value =~ /_[0-9a-z]$/
|
27
|
-
if value.start_with?( "totesbasic" ) ## note: special case for three totesbasic traits
|
28
|
-
else
|
29
|
-
value = '?'
|
30
|
-
end
|
31
|
-
end
|
32
|
-
items << [kai, code, value]
|
33
|
-
end
|
34
|
-
|
35
|
-
items.each do |item|
|
36
|
-
puts "#{item[0]} #{item[1]} #{item[2]}"
|
37
|
-
end
|
38
|
-
|
39
|
-
buf << "## #{trait[:name]} (#{trait[:code]}) - Genes #{trait[:genes]}\n\n"
|
40
|
-
buf << make_table( items )
|
20
|
+
TraitType.each do |tt|
|
21
|
+
buf << "## #{tt.name} (#{tt.code})\n\n"
|
22
|
+
buf << "_Genes #{tt.genes}_\n\n"
|
23
|
+
buf << make_table( tt.traits )
|
41
24
|
buf << "\n\n"
|
42
25
|
end
|
43
26
|
|
@@ -48,9 +31,9 @@ end ## method build
|
|
48
31
|
|
49
32
|
|
50
33
|
|
51
|
-
def make_table(
|
52
|
-
rows = make_rows(
|
53
|
-
pp rows
|
34
|
+
def make_table( traits )
|
35
|
+
rows = make_rows( traits, columns: 2 ) ## was 4
|
36
|
+
## pp rows
|
54
37
|
|
55
38
|
buf = ""
|
56
39
|
buf << "|Kai|Code|Name |Kai|Code|Name |\n"
|
@@ -59,22 +42,32 @@ def make_table( items )
|
|
59
42
|
rows.each do |row|
|
60
43
|
buf << "| "
|
61
44
|
|
62
|
-
parts = row.map do |
|
63
|
-
kai
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
45
|
+
parts = row.map do |trait|
|
46
|
+
kai = trait.kai
|
47
|
+
## binary = "%05b" % Kai::NUM[kai]
|
48
|
+
code = trait.code
|
49
|
+
name = trait.name
|
50
|
+
tier = trait.tier_roman ## e.g. I,II,III, etc. : String
|
51
|
+
|
52
|
+
if name.nil?
|
53
|
+
## note: so far x/31 trait is unknown/undefined!!!
|
54
|
+
if kai == "x"
|
55
|
+
cattribute = "?"
|
56
|
+
elsif trait.type.key == :secret
|
57
|
+
cattribute = "? #{tier}" ## unknown unknown
|
58
|
+
else ## "anonymous / unnamed" gene / trait
|
59
|
+
cattribute = "∅ #{tier}" ## known unknown :-)
|
60
|
+
end
|
68
61
|
else
|
69
|
-
if name.start_with?( "totesbasic" ) ## note: special case for three totesbasic traits
|
62
|
+
if name.downcase.start_with?( "totesbasic" ) ## note: special case for three totesbasic traits
|
70
63
|
q = "totesbasic"
|
71
64
|
else
|
72
65
|
q = name
|
73
66
|
end
|
74
|
-
cattribute = "**[#{name}](#{kitties_search_url(q)})** #{
|
67
|
+
cattribute = "**[#{name}](#{kitties_search_url(q)})** #{tier}"
|
75
68
|
end
|
76
69
|
|
77
|
-
"#{
|
70
|
+
"#{kai} | #{code} | #{cattribute}"
|
78
71
|
end
|
79
72
|
|
80
73
|
buf << parts.join( " | " )
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
|
4
|
+
|
5
|
+
class Recipe
|
6
|
+
|
7
|
+
attr_accessor :time_start, ## use date_start -why? why not?
|
8
|
+
:time_end,
|
9
|
+
:traits,
|
10
|
+
:variants,
|
11
|
+
:limit
|
12
|
+
|
13
|
+
def initialize( **kwargs )
|
14
|
+
update( kwargs )
|
15
|
+
end
|
16
|
+
|
17
|
+
def update( **kwargs )
|
18
|
+
kwargs.each do |name,value|
|
19
|
+
send( "#{name}=", value ) ## use "regular" plain/classic attribute setter
|
20
|
+
end
|
21
|
+
self ## return self for chaining
|
22
|
+
end
|
23
|
+
|
24
|
+
## is recipe time windowed? true/false
|
25
|
+
def time?() @time_start && @time_end; end
|
26
|
+
|
27
|
+
def time_days() (@time_end.jd - @time_start.jd) + 1; end
|
28
|
+
|
29
|
+
end # class Recipe
|
data/lib/kittyverse/traits.rb
CHANGED
@@ -3,8 +3,8 @@
|
|
3
3
|
|
4
4
|
class Trait
|
5
5
|
|
6
|
-
def self.traits_by_name() @@traits_by_name ||= {}; end
|
7
6
|
def self.traits_by_code() @@traits_by_code ||= {}; end
|
7
|
+
def self.traits_by_name() @@traits_by_name ||= {}; end
|
8
8
|
|
9
9
|
def self.find_by_code( code )
|
10
10
|
## note: allow string AND symbols (thus, use .to_s)
|
@@ -15,21 +15,34 @@ class Trait
|
|
15
15
|
def self.find_by_name( name )
|
16
16
|
## note: allow string AND symbols (thus, use .to_s !!!)
|
17
17
|
## note: downcase name e.g. allow Savannah too (not just savannah)
|
18
|
-
|
18
|
+
|
19
|
+
name = name.to_s.downcase
|
20
|
+
name = ALT_TRAIT_NAMES[ name ] if ALT_TRAIT_NAMES[ name ]
|
21
|
+
|
22
|
+
@@traits_by_name[ name ]
|
19
23
|
end
|
20
24
|
|
21
|
-
|
25
|
+
|
26
|
+
## add "generic" convenience find helpers
|
22
27
|
def self.find_by( **kwargs )
|
23
|
-
if kwargs[ :
|
24
|
-
find_by_name( kwargs[ :name ] )
|
25
|
-
elsif kwargs[ :code ]
|
28
|
+
if kwargs[ :code ]
|
26
29
|
find_by_code( kwargs[ :code] )
|
30
|
+
elsif kwargs[ :name ]
|
31
|
+
find_by_name( kwargs[ :name ] )
|
27
32
|
else
|
28
33
|
## todo/fix: throw argument except!!!
|
29
34
|
nil
|
30
35
|
end
|
31
36
|
end
|
32
37
|
|
38
|
+
def self.[]( key )
|
39
|
+
if key.size == 4 && key =~ /^[A-Za-z]{2}[0-9]{2}$/
|
40
|
+
Trait.find_by_code( key )
|
41
|
+
else
|
42
|
+
Trait.find_by_name( key )
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
33
46
|
|
34
47
|
|
35
48
|
attr_accessor :type,
|
@@ -47,8 +60,34 @@ class Trait
|
|
47
60
|
self ## return self for chaining
|
48
61
|
end
|
49
62
|
|
50
|
-
def num()
|
51
|
-
def code()
|
63
|
+
def num() Kai::NUMBER[@kai]; end
|
64
|
+
def code() "#{@type.code}#{Kai::CODE[@kai]}"; end
|
65
|
+
def binary() "%05b" % num; end
|
66
|
+
alias_method :bin, :binary
|
67
|
+
|
68
|
+
|
69
|
+
def tier( format=:num )
|
70
|
+
## num => 0,1,2,3,4,nil : Integer|Nil
|
71
|
+
## roman => "","I","II","III","IIII",nil : String|Nil
|
72
|
+
|
73
|
+
if format == :roman
|
74
|
+
MUTATION_TIER_ROMAN[@kai]
|
75
|
+
else ## assume integer num(ber)
|
76
|
+
MUTATION_TIER[@kai]
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def tier_roman() tier(:roman); end
|
81
|
+
|
82
|
+
alias_method :level, :tier
|
83
|
+
alias_method :m, :tier # m = mewtation/mutation
|
84
|
+
|
85
|
+
def base?() tier == 0; end # base level 0 - no mutation
|
86
|
+
def m1?() tier == 1; end # m1 - mutation level 1
|
87
|
+
def m2?() tier == 2; end # m2 - mutation level 2
|
88
|
+
def m3?() tier == 3; end # m3 - mutation level 3
|
89
|
+
def m4?() tier == 4; end # m4 - mutation level 4
|
90
|
+
|
52
91
|
end # class Trait
|
53
92
|
|
54
93
|
|
@@ -59,58 +98,30 @@ class TraitType
|
|
59
98
|
def self.trait_types_by_code() @@trait_types_by_code ||= {}; end
|
60
99
|
def self.trait_types_by_name() @@trait_types_by_name ||= {}; end
|
61
100
|
|
62
|
-
# quick hack - map copycats keys to (internal) cryptokitties trait type keys
|
63
|
-
# note: all keys are the same except:
|
64
|
-
ALT_TRAIT_TYPE_KEYS =
|
65
|
-
{
|
66
|
-
# :colorprimary => :color1,
|
67
|
-
# :colorsecondary => :color2,
|
68
|
-
# :colortertiary => :color3
|
69
|
-
|
70
|
-
:color1 => :colorprimary,
|
71
|
-
:color2 => :colorsecondary,
|
72
|
-
:color3 => :colortertiary
|
73
|
-
}
|
74
|
-
|
75
101
|
|
76
102
|
def self.find_by_key( key )
|
77
103
|
## note: allow string AND symbols (thus, use .to_sym !!!)
|
78
104
|
## note: allow known alternative mappings/key (e.g. "internal" cryptokitties keys if different)
|
79
|
-
key =
|
105
|
+
key = key.to_sym
|
106
|
+
key = ALT_TRAIT_TYPE_KEYS[ key ] if ALT_TRAIT_TYPE_KEYS[ key ]
|
80
107
|
|
81
|
-
@@trait_types_by_key[ key
|
108
|
+
@@trait_types_by_key[ key]
|
82
109
|
end
|
83
110
|
|
84
111
|
def self.find_by_code( code )
|
85
112
|
## note: allow string AND symbols (thus, use .to_s)
|
86
113
|
## e.g. allow 'FU', 'fu', :fu, :FU, etc.
|
87
|
-
|
114
|
+
code = code.to_s.upcase
|
115
|
+
@@trait_types_by_code[ code ]
|
88
116
|
end
|
89
117
|
|
90
|
-
ALT_TRAIT_TYPE_NAMES =
|
91
|
-
{
|
92
|
-
'body' => 'fur',
|
93
|
-
'eyes' => 'eye shape',
|
94
|
-
'eye type' => 'eye shape',
|
95
|
-
'body color' => 'base color',
|
96
|
-
'primary color' => 'base color',
|
97
|
-
'base colour' => 'base color', # british (canadian) spelling
|
98
|
-
'secondary color' => 'highlight color',
|
99
|
-
'sec color' => 'highlight color',
|
100
|
-
'pattern color' => 'highlight color',
|
101
|
-
'highlight colour' => 'highlight color', # british (canadian) spelling
|
102
|
-
'tertiary color' => 'accent color',
|
103
|
-
'accent colour' => 'accent color', # british (canadian) spelling
|
104
|
-
'wild' => 'wild element',
|
105
|
-
'secret' => 'secret y gene'
|
106
|
-
}
|
107
|
-
|
108
118
|
def self.find_by_name( name )
|
109
119
|
## note: downcase name e.g. allow fur too (not just Fur)
|
110
120
|
## note: allow known alternative mappings/key (e.g. "internal" cryptokitties keys if different)
|
111
|
-
name =
|
121
|
+
name = name.to_s.downcase
|
122
|
+
name = ALT_TRAIT_TYPE_NAMES[ name ] if ALT_TRAIT_TYPE_NAMES[ name ]
|
112
123
|
|
113
|
-
@@trait_types_by_name[ name
|
124
|
+
@@trait_types_by_name[ name ]
|
114
125
|
end
|
115
126
|
|
116
127
|
|
@@ -128,6 +139,19 @@ class TraitType
|
|
128
139
|
end
|
129
140
|
end
|
130
141
|
|
142
|
+
def self.[]( key )
|
143
|
+
## check for codes e.g. FU, PA, ... (or fu, pa,...).
|
144
|
+
if key.size == 2 && key =~ /^[A-Za-z]{2}$/
|
145
|
+
TraitType.find_by_code( key )
|
146
|
+
else
|
147
|
+
if key.is_a? Symbol ## e.g. :body, :pattern, etc.
|
148
|
+
TraitType.find_by_key( key )
|
149
|
+
else ## assume string
|
150
|
+
TraitType.find_by_name( key )
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
131
155
|
def self.each
|
132
156
|
@@trait_types_by_key.each do |(key,type)|
|
133
157
|
yield( type )
|
@@ -140,6 +164,8 @@ class TraitType
|
|
140
164
|
end
|
141
165
|
end
|
142
166
|
|
167
|
+
def self.size() @@trait_types_by_key.size; end ## todo: add length alias too? why? why not?
|
168
|
+
|
143
169
|
|
144
170
|
attr_accessor :key,
|
145
171
|
:name,
|
@@ -236,11 +262,6 @@ end # class TraitType
|
|
236
262
|
|
237
263
|
class Traits
|
238
264
|
def self.[]( key )
|
239
|
-
|
240
|
-
## todo:
|
241
|
-
## add lookup trait type by alt_names (string)
|
242
|
-
## add lookup trait type by alt_keys (symbol)
|
243
|
-
|
244
265
|
## check for codes e.g. FU, PA, ... (or fu, pa,...).
|
245
266
|
if key.size == 2 && key =~ /^[A-Za-z]{2}$/
|
246
267
|
TraitType.find_by_code( key )
|
data/lib/kittyverse/version.rb
CHANGED
data/test/test_fancies.rb
CHANGED
@@ -37,6 +37,31 @@ def test_bugcat_v2
|
|
37
37
|
end
|
38
38
|
|
39
39
|
|
40
|
+
def test_curdlin
|
41
|
+
fancy = Fancy[ 'Curdlin' ]
|
42
|
+
assert_equal :curdlin, fancy.key
|
43
|
+
assert fancy.exclusive? == false
|
44
|
+
assert fancy.specialedition? == false
|
45
|
+
assert fancy.special_edition? == false
|
46
|
+
|
47
|
+
assert fancy.time?
|
48
|
+
assert fancy.recipe?
|
49
|
+
assert fancy.recipe.time?
|
50
|
+
assert 4, fancy.recipe.traits.size
|
51
|
+
assert 204, fancy.time_days
|
52
|
+
assert 204, fancy.recipe.time_days
|
53
|
+
|
54
|
+
today = Date.new( 2019, 5, 5 )
|
55
|
+
assert fancy.unlocked?( today )
|
56
|
+
assert fancy.breedable?( today )
|
57
|
+
assert fancy.locked?( today ) == false
|
58
|
+
future = Date.new( 2019, 12, 20 )
|
59
|
+
assert fancy.unlocked?( future ) == false
|
60
|
+
assert fancy.breedable?( future ) == false
|
61
|
+
assert fancy.locked?( future )
|
62
|
+
end
|
63
|
+
|
64
|
+
|
40
65
|
def test_misc
|
41
66
|
Fancy.each do |fancy|
|
42
67
|
p fancy.name
|
data/test/test_traits.rb
CHANGED
@@ -12,13 +12,16 @@ class TestTraits < MiniTest::Test
|
|
12
12
|
|
13
13
|
|
14
14
|
def test_savannah
|
15
|
-
[
|
15
|
+
[ Trait[ 'FU00' ],
|
16
16
|
Trait.find_by_code( 'FU00' ),
|
17
17
|
Trait.find_by( code: 'FU00' ),
|
18
|
-
|
19
|
-
|
18
|
+
Trait[ 'savannah' ],
|
19
|
+
Trait[ 'Savannah' ],
|
20
20
|
Trait.find_by_name( 'Savannah' ),
|
21
21
|
Trait.find_by( name: 'Savannah' ),
|
22
|
+
Traits[ 'FU00' ],
|
23
|
+
Traits[ 'savannah' ],
|
24
|
+
Traits[ 'Savannah' ],
|
22
25
|
Traits[ :body ][ '1' ],
|
23
26
|
Traits[ :body ][ '00' ],
|
24
27
|
Traits[ :body ][ 0 ],
|
@@ -33,19 +36,91 @@ def test_savannah
|
|
33
36
|
assert_equal "Fur", t.type.name
|
34
37
|
assert_equal "FU00", t.code
|
35
38
|
assert_equal "1", t.kai
|
39
|
+
assert_equal 0, t.num
|
40
|
+
assert_equal "00000", t.bin
|
41
|
+
assert_equal "00000", t.binary
|
42
|
+
assert_equal 0, t.tier
|
43
|
+
assert_equal "", t.tier_roman
|
44
|
+
assert_equal "", t.tier(:roman)
|
45
|
+
assert t.base?
|
46
|
+
assert t.m1? == false
|
47
|
+
assert t.m2? == false
|
48
|
+
assert t.m3? == false
|
49
|
+
assert t.m4? == false
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_moonrise
|
54
|
+
t = Trait[ 'Moonrise' ]
|
55
|
+
assert_equal "PA30", t.code
|
56
|
+
assert_equal "w", t.kai
|
57
|
+
assert_equal 30, t.num
|
58
|
+
assert_equal "11110", t.bin
|
59
|
+
assert_equal "11110", t.binary
|
60
|
+
assert_equal 4, t.tier
|
61
|
+
assert_equal 4, t.level
|
62
|
+
assert_equal 4, t.m
|
63
|
+
assert_equal "IIII", t.tier_roman
|
64
|
+
assert_equal "IIII", t.tier(:roman)
|
65
|
+
assert_equal "IIII", t.level(:roman)
|
66
|
+
assert_equal "IIII", t.m(:roman)
|
67
|
+
assert t.base? == false
|
68
|
+
assert t.m1? == false
|
69
|
+
assert t.m2? == false
|
70
|
+
assert t.m3? == false
|
71
|
+
assert t.m4?
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
def test_totesbasic
|
76
|
+
[ Trait.find_by_name( 'totesbasic 1' ),
|
77
|
+
Trait.find_by_name( 'totesbasic_1' ),
|
78
|
+
Trait.find_by_name( 'totesbasic (14)' ),
|
79
|
+
Trait.find_by_name( 'totesbasic_14' ),
|
80
|
+
Trait.find_by_name( 'totesbasic (f)' ),
|
81
|
+
Trait.find_by_name( 'totesbasic_f' ),
|
82
|
+
Trait[ 'totesbasic 1' ],
|
83
|
+
Trait[ 'totesbasic_1' ],
|
84
|
+
].each do |t|
|
85
|
+
assert_equal Trait, t.class
|
86
|
+
assert_equal "Totesbasic 1", t.name
|
87
|
+
assert_equal "Pattern", t.type.name
|
88
|
+
assert_equal "PA14", t.code
|
89
|
+
assert_equal "f", t.kai
|
90
|
+
assert_equal 14, t.num
|
91
|
+
assert t.base?
|
92
|
+
assert_equal 0, t.tier
|
93
|
+
assert_equal "", t.tier_roman
|
94
|
+
assert_equal "", t.tier(:roman)
|
36
95
|
end
|
37
96
|
end
|
38
97
|
|
98
|
+
|
39
99
|
def test_fu31
|
40
100
|
[ Traits[ :body ][ 'x' ],
|
41
101
|
Traits[ :body ][ '31' ],
|
42
102
|
Traits[ :body ][ 31 ]
|
43
103
|
].each do |t|
|
44
104
|
assert_equal Trait, t.class
|
45
|
-
|
105
|
+
assert t.name == nil
|
46
106
|
assert_equal "Fur", t.type.name
|
47
107
|
assert_equal "FU31", t.code
|
48
108
|
assert_equal "x", t.kai
|
109
|
+
assert_equal 31, t.num
|
110
|
+
assert_equal "11111", t.bin
|
111
|
+
assert_equal "11111", t.binary
|
112
|
+
assert t.tier == nil
|
113
|
+
assert t.level == nil
|
114
|
+
assert t.m == nil
|
115
|
+
assert_equal "", t.tier_roman
|
116
|
+
assert_equal "", t.tier(:roman)
|
117
|
+
assert_equal "", t.level(:roman)
|
118
|
+
assert_equal "", t.m(:roman)
|
119
|
+
assert t.base? == false
|
120
|
+
assert t.m1? == false
|
121
|
+
assert t.m2? == false
|
122
|
+
assert t.m3? == false
|
123
|
+
assert t.m4? == false
|
49
124
|
end
|
50
125
|
end
|
51
126
|
|
@@ -59,6 +134,7 @@ def test_vigilante
|
|
59
134
|
assert_equal "Pattern", t.type.name
|
60
135
|
assert_equal "PA00", t.code
|
61
136
|
assert_equal "1", t.kai
|
137
|
+
assert_equal 0, t.num
|
62
138
|
end
|
63
139
|
end
|
64
140
|
|
@@ -69,6 +145,8 @@ def test_body
|
|
69
145
|
].each do |tt|
|
70
146
|
assert_equal TraitType, tt.class
|
71
147
|
assert_equal "Fur", tt.name
|
148
|
+
assert_equal :body, tt.key
|
149
|
+
assert_equal 32, tt.traits.size
|
72
150
|
end
|
73
151
|
end
|
74
152
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kittyverse
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gerald Bauer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-05-
|
11
|
+
date: 2019-05-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: base32-alphabets
|
@@ -78,6 +78,7 @@ files:
|
|
78
78
|
- lib/kittyverse/links.rb
|
79
79
|
- lib/kittyverse/mewtations.rb
|
80
80
|
- lib/kittyverse/pages/genes.rb
|
81
|
+
- lib/kittyverse/recipes.rb
|
81
82
|
- lib/kittyverse/traits.rb
|
82
83
|
- lib/kittyverse/version.rb
|
83
84
|
- test/helper.rb
|