kittyverse 0.4.0 → 0.4.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/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
|