kittyverse 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Manifest.txt +5 -3
- data/README.md +69 -10
- data/lib/kittyverse.rb +9 -268
- data/lib/kittyverse/cattributes.rb +29 -22
- data/lib/kittyverse/config/fancies.rb +550 -0
- data/lib/kittyverse/{purrstige.rb → config/purrstiges.rb} +1 -1
- data/lib/kittyverse/config/traits.rb +377 -0
- data/lib/kittyverse/{traits_timeline.rb → config/traits_timeline.rb} +0 -0
- data/lib/kittyverse/fancies.rb +158 -550
- data/lib/kittyverse/links.rb +6 -9
- data/lib/kittyverse/traits.rb +262 -374
- data/lib/kittyverse/version.rb +1 -1
- data/test/test_cattributes.rb +22 -34
- data/test/test_fancies.rb +52 -0
- data/test/test_traits.rb +66 -169
- metadata +7 -5
- data/lib/kittyverse/catalog.rb +0 -27
data/lib/kittyverse/links.rb
CHANGED
@@ -16,19 +16,16 @@ end
|
|
16
16
|
|
17
17
|
|
18
18
|
|
19
|
-
def kitties_fancy_search_url(
|
20
|
-
## todo/fix: add h[:name] to hash (no need for key)
|
19
|
+
def kitties_fancy_search_url( fancy ) ## todo: find a better name - why? why not?
|
21
20
|
|
22
21
|
## note: use (official) chinese name for search param if present
|
23
|
-
param =
|
22
|
+
param = fancy.name_cn ? fancy.name_cn : fancy.key
|
24
23
|
|
25
|
-
if
|
24
|
+
if fancy.special_edition?
|
26
25
|
q = "specialedition:#{param}" ## todo: urlescape param - why? why not?
|
27
|
-
elsif
|
26
|
+
elsif fancy.exclusive? ## just use fancy too - why? why not?
|
28
27
|
q = "exclusive:#{param}"
|
29
|
-
|
30
|
-
q = "purrstige:#{param}"
|
31
|
-
else ## assume fancy
|
28
|
+
else ## assume "normal/regular" fancy
|
32
29
|
q = "fancy:#{param}"
|
33
30
|
end
|
34
31
|
|
@@ -36,7 +33,7 @@ def kitties_fancy_search_url( key, h ) ## todo: find a better name - why? why
|
|
36
33
|
end
|
37
34
|
|
38
35
|
## alias :kitties_special_search_url :kitties_fancy_search_url
|
39
|
-
def
|
36
|
+
def kitties_specialedition_search_url( fancy ) kitties_fancy_search_url( fancy ); end
|
40
37
|
|
41
38
|
|
42
39
|
|
data/lib/kittyverse/traits.rb
CHANGED
@@ -1,377 +1,265 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
'e' => 'mittens',
|
74
|
-
'f' => 'totesbasic 1', ## use totesbasic_f or totesbasic (14) - why? why not?
|
75
|
-
'g' => 'totesbasic 2', ## use totesbasic_g or totesbasic (15)
|
76
|
-
'h' => 'splat',
|
77
|
-
'i' => 'thunderstruck',
|
78
|
-
'j' => 'dippedcone',
|
79
|
-
'k' => 'highsociety',
|
80
|
-
'm' => 'tigerpunk',
|
81
|
-
'n' => 'henna',
|
82
|
-
'o' => 'arcreactor',
|
83
|
-
'p' => 'totesbasic 3', ## use totesbasic_p or totesbasic (23) - why? why not?
|
84
|
-
'q' => 'scorpius',
|
85
|
-
'r' => 'razzledazzle',
|
86
|
-
's' => 'hotrod',
|
87
|
-
't' => 'allyouneed',
|
88
|
-
'u' => 'avatar',
|
89
|
-
'v' => 'gyre',
|
90
|
-
'w' => 'moonrise',
|
91
|
-
'x' => ''
|
92
|
-
}
|
93
|
-
},
|
94
|
-
coloreyes: {
|
95
|
-
genes: '8-11',
|
96
|
-
name: 'Eye Color', code: 'EC',
|
97
|
-
kai: {
|
98
|
-
'1' => 'thundergrey',
|
99
|
-
'2' => 'gold',
|
100
|
-
'3' => 'topaz',
|
101
|
-
'4' => 'mintgreen',
|
102
|
-
'5' => 'isotope',
|
103
|
-
'6' => 'sizzurp',
|
104
|
-
'7' => 'chestnut',
|
105
|
-
'8' => 'strawberry',
|
106
|
-
'9' => 'sapphire',
|
107
|
-
'a' => 'forgetmenot',
|
108
|
-
'b' => 'dahlia',
|
109
|
-
'c' => 'coralsunrise',
|
110
|
-
'd' => 'olive',
|
111
|
-
'e' => 'doridnudibranch',
|
112
|
-
'f' => 'parakeet',
|
113
|
-
'g' => 'cyan',
|
114
|
-
'h' => 'pumpkin',
|
115
|
-
'i' => 'limegreen',
|
116
|
-
'j' => 'bridesmaid',
|
117
|
-
'k' => 'bubblegum',
|
118
|
-
'm' => 'twilightsparkle',
|
119
|
-
'n' => 'palejade',
|
120
|
-
'o' => 'pinefresh',
|
121
|
-
'p' => 'eclipse',
|
122
|
-
'q' => 'babypuke',
|
123
|
-
'r' => 'downbythebay',
|
124
|
-
's' => 'autumnmoon',
|
125
|
-
't' => 'oasis',
|
126
|
-
'u' => 'gemini',
|
127
|
-
'v' => 'dioscuri',
|
128
|
-
'w' => 'kaleidoscope',
|
129
|
-
'x' => ''
|
130
|
-
}
|
131
|
-
},
|
132
|
-
eyes: {
|
133
|
-
genes: '12-15',
|
134
|
-
name: 'Eye Shape', code: 'ES', ## eye type
|
135
|
-
kai: {
|
136
|
-
'1' => 'swarley',
|
137
|
-
'2' => 'wonky',
|
138
|
-
'3' => 'serpent',
|
139
|
-
'4' => 'googly',
|
140
|
-
'5' => 'otaku',
|
141
|
-
'6' => 'simple',
|
142
|
-
'7' => 'crazy',
|
143
|
-
'8' => 'thicccbrowz',
|
144
|
-
'9' => 'caffeine',
|
145
|
-
'a' => 'wowza',
|
146
|
-
'b' => 'baddate',
|
147
|
-
'c' => 'asif',
|
148
|
-
'd' => 'chronic',
|
149
|
-
'e' => 'slyboots',
|
150
|
-
'f' => 'wiley',
|
151
|
-
'g' => 'stunned',
|
152
|
-
'h' => 'chameleon',
|
153
|
-
'i' => 'alien',
|
154
|
-
'j' => 'fabulous',
|
155
|
-
'k' => 'raisedbrow',
|
156
|
-
'm' => 'tendertears',
|
157
|
-
'n' => 'hacker',
|
158
|
-
'o' => 'sass',
|
159
|
-
'p' => 'sweetmeloncakes',
|
160
|
-
'q' => 'oceanid',
|
161
|
-
'r' => 'wingtips',
|
162
|
-
's' => 'firedup',
|
163
|
-
't' => 'buzzed',
|
164
|
-
'u' => 'bornwithit',
|
165
|
-
'v' => 'candyshoppe',
|
166
|
-
'w' => 'drama',
|
167
|
-
'x' => ''
|
168
|
-
}
|
169
|
-
},
|
170
|
-
colorprimary: {
|
171
|
-
genes: '16-19',
|
172
|
-
name: 'Base Color', code: 'BC', ## color1 / colorprimary / body color
|
173
|
-
kai: {
|
174
|
-
'1' => 'shadowgrey',
|
175
|
-
'2' => 'salmon',
|
176
|
-
'3' => 'meowgarine',
|
177
|
-
'4' => 'orangesoda',
|
178
|
-
'5' => 'cottoncandy',
|
179
|
-
'6' => 'mauveover',
|
180
|
-
'7' => 'aquamarine',
|
181
|
-
'8' => 'nachocheez',
|
182
|
-
'9' => 'harbourfog',
|
183
|
-
'a' => 'cinderella',
|
184
|
-
'b' => 'greymatter',
|
185
|
-
'c' => 'tundra',
|
186
|
-
'd' => 'brownies',
|
187
|
-
'e' => 'dragonfruit',
|
188
|
-
'f' => 'hintomint',
|
189
|
-
'g' => 'bananacream',
|
190
|
-
'h' => 'cloudwhite',
|
191
|
-
'i' => 'cornflower',
|
192
|
-
'j' => 'oldlace',
|
193
|
-
'k' => 'koala',
|
194
|
-
'm' => 'lavender',
|
195
|
-
'n' => 'glacier',
|
196
|
-
'o' => 'redvelvet',
|
197
|
-
'p' => 'verdigris',
|
198
|
-
'q' => 'icicle',
|
199
|
-
'r' => 'onyx',
|
200
|
-
's' => 'hyacinth',
|
201
|
-
't' => 'martian',
|
202
|
-
'u' => 'hotcocoa',
|
203
|
-
'v' => 'shamrock',
|
204
|
-
'w' => 'firstblush',
|
205
|
-
'x' => ''
|
206
|
-
}
|
207
|
-
},
|
208
|
-
colorsecondary: {
|
209
|
-
genes: '20-23',
|
210
|
-
name: 'Highlight Color', code: 'HC', ## color2 / colorsecondary / sec color / pattern color
|
211
|
-
kai: {
|
212
|
-
'1' => 'cyborg',
|
213
|
-
'2' => 'springcrocus',
|
214
|
-
'3' => 'egyptiankohl',
|
215
|
-
'4' => 'poisonberry',
|
216
|
-
'5' => 'lilac',
|
217
|
-
'6' => 'apricot',
|
218
|
-
'7' => 'royalpurple',
|
219
|
-
'8' => 'padparadscha',
|
220
|
-
'9' => 'swampgreen',
|
221
|
-
'a' => 'violet',
|
222
|
-
'b' => 'scarlet',
|
223
|
-
'c' => 'barkbrown',
|
224
|
-
'd' => 'coffee',
|
225
|
-
'e' => 'lemonade',
|
226
|
-
'f' => 'chocolate',
|
227
|
-
'g' => 'butterscotch',
|
228
|
-
'h' => 'ooze',
|
229
|
-
'i' => 'safetyvest',
|
230
|
-
'j' => 'turtleback',
|
231
|
-
'k' => 'rosequartz',
|
232
|
-
'm' => 'wolfgrey',
|
233
|
-
'n' => 'cerulian',
|
234
|
-
'o' => 'skyblue',
|
235
|
-
'p' => 'garnet',
|
236
|
-
'q' => 'peppermint',
|
237
|
-
'r' => 'universe',
|
238
|
-
's' => 'royalblue',
|
239
|
-
't' => 'mertail',
|
240
|
-
'u' => 'inflatablepool',
|
241
|
-
'v' => 'pearl',
|
242
|
-
'w' => 'prairierose',
|
243
|
-
'x' => ''
|
244
|
-
}
|
245
|
-
},
|
246
|
-
colortertiary: {
|
247
|
-
genes: '24-27',
|
248
|
-
name: 'Accent Color', code: 'AC', ## color3 / colortertiary
|
249
|
-
kai: {
|
250
|
-
'1' => 'belleblue',
|
251
|
-
'2' => 'sandalwood',
|
252
|
-
'3' => 'peach',
|
253
|
-
'4' => 'icy',
|
254
|
-
'5' => 'granitegrey',
|
255
|
-
'6' => 'cashewmilk',
|
256
|
-
'7' => 'kittencream',
|
257
|
-
'8' => 'emeraldgreen',
|
258
|
-
'9' => 'kalahari',
|
259
|
-
'a' => 'shale',
|
260
|
-
'b' => 'purplehaze',
|
261
|
-
'c' => 'hanauma',
|
262
|
-
'd' => 'azaleablush',
|
263
|
-
'e' => 'missmuffett',
|
264
|
-
'f' => 'morningglory',
|
265
|
-
'g' => 'frosting',
|
266
|
-
'h' => 'daffodil',
|
267
|
-
'i' => 'flamingo',
|
268
|
-
'j' => 'buttercup',
|
269
|
-
'k' => 'bloodred',
|
270
|
-
'm' => 'atlantis',
|
271
|
-
'n' => 'summerbonnet',
|
272
|
-
'o' => 'periwinkle',
|
273
|
-
'p' => 'patrickstarfish',
|
274
|
-
'q' => 'seafoam',
|
275
|
-
'r' => 'cobalt',
|
276
|
-
's' => 'mallowflower',
|
277
|
-
't' => 'mintmacaron',
|
278
|
-
'u' => 'sully',
|
279
|
-
'v' => 'fallspice',
|
280
|
-
'w' => 'dreamboat',
|
281
|
-
'x' => ''
|
282
|
-
}
|
283
|
-
},
|
284
|
-
wild: {
|
285
|
-
genes: '28-31',
|
286
|
-
name: 'Wild Element', code: 'WE',
|
287
|
-
kai: {
|
288
|
-
'h' => 'littlefoot',
|
289
|
-
'i' => 'elk',
|
290
|
-
'j' => 'ducky',
|
291
|
-
'k' => 'trioculus',
|
292
|
-
'm' => 'daemonwings',
|
293
|
-
'n' => 'featherbrain',
|
294
|
-
'o' => 'flapflap',
|
295
|
-
'p' => 'daemonhorns',
|
296
|
-
'q' => 'dragontail',
|
297
|
-
'r' => 'aflutter',
|
298
|
-
's' => 'foghornpawhorn',
|
299
|
-
't' => 'unicorn',
|
300
|
-
'u' => 'dragonwings',
|
301
|
-
'v' => 'alicorn',
|
302
|
-
'w' => 'wyrm',
|
303
|
-
'x' => ''
|
304
|
-
}
|
305
|
-
},
|
306
|
-
mouth: {
|
307
|
-
genes: '32-35',
|
308
|
-
name: 'Mouth', code: 'MO',
|
309
|
-
kai: {
|
310
|
-
'1' => 'whixtensions',
|
311
|
-
'2' => 'wasntme',
|
312
|
-
'3' => 'wuvme',
|
313
|
-
'4' => 'gerbil',
|
314
|
-
'5' => 'confuzzled',
|
315
|
-
'6' => 'impish',
|
316
|
-
'7' => 'belch',
|
317
|
-
'8' => 'rollercoaster',
|
318
|
-
'9' => 'beard',
|
319
|
-
'a' => 'pouty',
|
320
|
-
'b' => 'saycheese',
|
321
|
-
'c' => 'grim',
|
322
|
-
'd' => 'fangtastic',
|
323
|
-
'e' => 'moue',
|
324
|
-
'f' => 'happygokitty',
|
325
|
-
'g' => 'soserious',
|
326
|
-
'h' => 'cheeky',
|
327
|
-
'i' => 'starstruck',
|
328
|
-
'j' => 'samwise',
|
329
|
-
'k' => 'ruhroh',
|
330
|
-
'm' => 'dali',
|
331
|
-
'n' => 'grimace',
|
332
|
-
'o' => 'majestic',
|
333
|
-
'p' => 'tongue',
|
334
|
-
'q' => 'yokel',
|
335
|
-
'r' => 'topoftheworld',
|
336
|
-
's' => 'neckbeard',
|
337
|
-
't' => 'satiated',
|
338
|
-
'u' => 'walrus',
|
339
|
-
'v' => 'struck',
|
340
|
-
'w' => 'delite',
|
341
|
-
'x' => ''
|
342
|
-
}
|
343
|
-
},
|
344
|
-
environment: {
|
345
|
-
genes: '36-39',
|
346
|
-
name: 'Environment', code: 'EN',
|
347
|
-
kai: {
|
348
|
-
'h' => 'salty',
|
349
|
-
'i' => 'dune',
|
350
|
-
'j' => 'juju',
|
351
|
-
'k' => 'tinybox',
|
352
|
-
'm' => 'myparade',
|
353
|
-
'n' => 'finalfrontier',
|
354
|
-
'o' => 'metime',
|
355
|
-
'p' => 'drift',
|
356
|
-
'q' => 'secretgarden',
|
357
|
-
'r' => 'frozen',
|
358
|
-
's' => 'roadtogold',
|
359
|
-
't' => 'jacked',
|
360
|
-
'u' => 'floorislava',
|
361
|
-
'v' => 'prism',
|
362
|
-
'w' => 'junglebook',
|
363
|
-
'x' => ''
|
364
|
-
}
|
365
|
-
},
|
366
|
-
secret: {
|
367
|
-
genes: '40-43',
|
368
|
-
name: 'Secret Y Gene', code: 'SE', ## todo: change to Y Gene or Y (see https://guide.cryptokitties.co/guide/cat-features/genes)
|
369
|
-
kai: { }
|
370
|
-
},
|
371
|
-
prestige: {
|
372
|
-
genes: '44-47',
|
373
|
-
name: 'Purrstige', code: 'PU',
|
374
|
-
kai: { }
|
375
|
-
## prune, furball, duckduckcat, or thatsawrap - more like fancies (not really traits)
|
3
|
+
|
4
|
+
class Trait
|
5
|
+
|
6
|
+
def self.traits_by_name() @@traits_by_name ||= {}; end
|
7
|
+
def self.traits_by_code() @@traits_by_code ||= {}; end
|
8
|
+
|
9
|
+
def self.find_by_code( code )
|
10
|
+
## note: allow string AND symbols (thus, use .to_s)
|
11
|
+
## e.g. allow 'FU01', 'fu01', :fu01, :FU01, etc.
|
12
|
+
@@traits_by_code[ code.upcase.to_s ]
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.find_by_name( name )
|
16
|
+
## note: allow string AND symbols (thus, use .to_s !!!)
|
17
|
+
## note: downcase name e.g. allow Savannah too (not just savannah)
|
18
|
+
@@traits_by_name[ name.downcase.to_s ]
|
19
|
+
end
|
20
|
+
|
21
|
+
## add "generic" convenience find helper
|
22
|
+
def self.find_by( **kwargs )
|
23
|
+
if kwargs[ :name ]
|
24
|
+
find_by_name( kwargs[ :name ] )
|
25
|
+
elsif kwargs[ :code ]
|
26
|
+
find_by_code( kwargs[ :code] )
|
27
|
+
else
|
28
|
+
## todo/fix: throw argument except!!!
|
29
|
+
nil
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
|
35
|
+
attr_accessor :type,
|
36
|
+
:name,
|
37
|
+
:kai # kai char e.g. '1', '2', etc.
|
38
|
+
|
39
|
+
def initialize( **kwargs )
|
40
|
+
update( kwargs )
|
41
|
+
end
|
42
|
+
|
43
|
+
def update( **kwargs )
|
44
|
+
kwargs.each do |name,value|
|
45
|
+
send( "#{name}=", value ) ## use "regular" plain/classic attribute setter
|
46
|
+
end
|
47
|
+
self ## return self for chaining
|
48
|
+
end
|
49
|
+
|
50
|
+
def num() Kai::NUMBER[@kai]; end
|
51
|
+
def code() @type.code + Kai::CODE[@kai]; end
|
52
|
+
end # class Trait
|
53
|
+
|
54
|
+
|
55
|
+
|
56
|
+
class TraitType
|
57
|
+
|
58
|
+
def self.trait_types_by_key() @@trait_types_by_key ||= {}; end
|
59
|
+
def self.trait_types_by_code() @@trait_types_by_code ||= {}; end
|
60
|
+
def self.trait_types_by_name() @@trait_types_by_name ||= {}; end
|
61
|
+
|
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
|
376
73
|
}
|
377
|
-
|
74
|
+
|
75
|
+
|
76
|
+
def self.find_by_key( key )
|
77
|
+
## note: allow string AND symbols (thus, use .to_sym !!!)
|
78
|
+
## note: allow known alternative mappings/key (e.g. "internal" cryptokitties keys if different)
|
79
|
+
key = ALT_TRAIT_TYPE_KEYS[ key.to_sym ] if ALT_TRAIT_TYPE_KEYS[ key.to_sym ]
|
80
|
+
|
81
|
+
@@trait_types_by_key[ key.to_sym ]
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.find_by_code( code )
|
85
|
+
## note: allow string AND symbols (thus, use .to_s)
|
86
|
+
## e.g. allow 'FU', 'fu', :fu, :FU, etc.
|
87
|
+
@@trait_types_by_code[ code.upcase.to_s ]
|
88
|
+
end
|
89
|
+
|
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
|
+
def self.find_by_name( name )
|
109
|
+
## note: downcase name e.g. allow fur too (not just Fur)
|
110
|
+
## note: allow known alternative mappings/key (e.g. "internal" cryptokitties keys if different)
|
111
|
+
name = ALT_TRAIT_TYPE_NAMES[ name.downcase ] if ALT_TRAIT_TYPE_NAMES[ name.downcase ]
|
112
|
+
|
113
|
+
@@trait_types_by_name[ name.downcase ]
|
114
|
+
end
|
115
|
+
|
116
|
+
|
117
|
+
## add "generic" convenience find helper
|
118
|
+
def self.find_by( **kwargs )
|
119
|
+
if kwargs[ :key ]
|
120
|
+
find_by_key( kwargs[ :key ] )
|
121
|
+
elsif kwargs[ :code ]
|
122
|
+
find_by_code( kwargs[ :code ] )
|
123
|
+
elsif kwargs[ :name ]
|
124
|
+
find_by_name( kwargs[ :name ] )
|
125
|
+
else
|
126
|
+
## todo/fix: throw argument except!!!
|
127
|
+
nil
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def self.each
|
132
|
+
@@trait_types_by_key.each do |(key,type)|
|
133
|
+
yield( type )
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def self.each_with_index
|
138
|
+
@@trait_types_by_key.each_with_index do |(key,type),i|
|
139
|
+
yield( type,i )
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
|
144
|
+
attr_accessor :key,
|
145
|
+
:name,
|
146
|
+
:code,
|
147
|
+
:genes,
|
148
|
+
:traits, ## array of 32 traits
|
149
|
+
:cattributes ## array of 29/31/x cattributes
|
150
|
+
|
151
|
+
def initialize( **kwargs )
|
152
|
+
update( kwargs )
|
153
|
+
end
|
154
|
+
|
155
|
+
def update( **kwargs )
|
156
|
+
kwargs.each do |name,value|
|
157
|
+
send( "#{name}=", value ) ## use "regular" plain/classic attribute setter
|
158
|
+
end
|
159
|
+
self ## return self for chaining
|
160
|
+
end
|
161
|
+
|
162
|
+
def [](key)
|
163
|
+
if key.is_a? Integer ## assume 0,1,2,3,.. index
|
164
|
+
traits[ key ]
|
165
|
+
elsif key.size == 2 && key =~ /^[0-9]{2}$/ ## assume code e.g. '00', '01', .. etc.
|
166
|
+
traits[ key.to_i(10) ]
|
167
|
+
else ## assume kai char
|
168
|
+
traits[ Kai::NUMBER[key] ]
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
|
173
|
+
TRAITS.reduce( TraitType.trait_types_by_key ) do |types, (key, h)|
|
174
|
+
|
175
|
+
type = TraitType.new(
|
176
|
+
key: key,
|
177
|
+
name: h[:name], # e.g. 'Fur'
|
178
|
+
code: h[:code], # e.g. 'FU'
|
179
|
+
genes: h[:genes] # e.g. '0-3'
|
180
|
+
)
|
181
|
+
|
182
|
+
# auto-fill kai mapping
|
183
|
+
## note: to keep "insertion" order - recreate new hash mapping
|
184
|
+
hash_kai = h[:kai]
|
185
|
+
hash_kai2 = {}
|
186
|
+
Kai::ALPHABET.each do |kai|
|
187
|
+
name = hash_kai[kai]
|
188
|
+
if name.nil?
|
189
|
+
## puts "#{key} - #{kai} is missing"
|
190
|
+
## hash_kai2[kai] = "#{key}_#{kai}"
|
191
|
+
hash_kai2[kai] = nil
|
192
|
+
elsif name.empty?
|
193
|
+
## puts "#{key} - #{kai} is empty"
|
194
|
+
## hash_kai2[kai] = "#{key}_#{kai}"
|
195
|
+
hash_kai2[kai] = nil
|
196
|
+
else
|
197
|
+
hash_kai2[kai] = name
|
198
|
+
end
|
199
|
+
end
|
200
|
+
h[:kai] = hash_kai2
|
201
|
+
|
202
|
+
type.traits = h[:kai].reduce([]) do |traits, (kai,name)| # array of 32 traits
|
203
|
+
trait = Trait.new(
|
204
|
+
type: type,
|
205
|
+
name: name,
|
206
|
+
kai: kai
|
207
|
+
)
|
208
|
+
|
209
|
+
## (auto-)add traits for lookup by name, code, etc. via (hash) mapping
|
210
|
+
Trait.traits_by_name[ trait.name.downcase ] = trait if trait.name ## note: traits without name (nil) exist!!
|
211
|
+
Trait.traits_by_code[ trait.code ] = trait
|
212
|
+
|
213
|
+
traits << trait
|
214
|
+
traits
|
215
|
+
end
|
216
|
+
|
217
|
+
types[key] = type
|
218
|
+
types
|
219
|
+
end
|
220
|
+
|
221
|
+
TraitType.trait_types_by_key.reduce( TraitType.trait_types_by_code ) do |types, (key, type)|
|
222
|
+
types[type.code] = type
|
223
|
+
types
|
224
|
+
end
|
225
|
+
|
226
|
+
TraitType.trait_types_by_key.reduce( TraitType.trait_types_by_name ) do |types, (key, type)|
|
227
|
+
## note: downcase Fur to fur and so on (for case insensitive match)
|
228
|
+
types[type.name.downcase] = type
|
229
|
+
types
|
230
|
+
end
|
231
|
+
|
232
|
+
end # class TraitType
|
233
|
+
|
234
|
+
|
235
|
+
|
236
|
+
|
237
|
+
class Traits
|
238
|
+
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
|
+
## check for codes e.g. FU, PA, ... (or fu, pa,...).
|
245
|
+
if key.size == 2 && key =~ /^[A-Za-z]{2}$/
|
246
|
+
TraitType.find_by_code( key )
|
247
|
+
## check for codes e.g. FU00, FU01 ... (or fu00, fu01, ...)
|
248
|
+
elsif key.size == 4 && key =~ /^[A-Za-z]{2}[0-9]{2}$/
|
249
|
+
Trait.find_by_code( key )
|
250
|
+
else
|
251
|
+
if key.is_a? Symbol ## e.g. :body, :pattern, etc.
|
252
|
+
t = TraitType.find_by_key( key )
|
253
|
+
t = Trait.find_by_name( key ) if t.nil? ## try trait name next - why? why not?
|
254
|
+
t
|
255
|
+
else ## assume string
|
256
|
+
t = TraitType.find_by_name( key )
|
257
|
+
t = Trait.find_by_name( key ) if t.nil? ## try trait name next
|
258
|
+
t
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
def self.each() TraitType.each { |type| yield(type) }; end
|
264
|
+
def self.each_with_index() TraitType.each_with_index { |type,i| yield(type,i) }; end
|
265
|
+
end # class Traits
|