kittyverse 0.4.5 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +3 -3
- data/Manifest.txt +3 -2
- data/README.md +428 -240
- data/Rakefile +30 -30
- data/lib/kittyverse.rb +47 -47
- data/lib/kittyverse/api/client.rb +147 -147
- data/lib/kittyverse/api/versions.rb +91 -91
- data/lib/kittyverse/cattributes.rb +131 -131
- data/lib/kittyverse/config/colors.rb +146 -146
- data/lib/kittyverse/config/fancies.rb +84 -6
- data/lib/kittyverse/config/purrstiges.rb +225 -215
- data/lib/kittyverse/config/traits_timeline.rb +288 -288
- data/lib/kittyverse/fancies.rb +205 -205
- data/lib/kittyverse/gene.rb +55 -55
- data/lib/kittyverse/genome.rb +236 -236
- data/lib/kittyverse/mewtations.rb +120 -120
- data/lib/kittyverse/version.rb +23 -23
- data/test/helper.rb +10 -10
- data/test/test_fancies.rb +16 -0
- data/test/test_genome.rb +62 -0
- data/test/test_traits.rb +174 -174
- metadata +13 -6
data/lib/kittyverse/fancies.rb
CHANGED
@@ -1,205 +1,205 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
|
4
|
-
class Fancy
|
5
|
-
|
6
|
-
def self.fancies_by_key() @@fancies_by_key ||= {}; end
|
7
|
-
def self.fancies_by_name() @@fancies_by_name ||= {}; end
|
8
|
-
|
9
|
-
def self.find_by_key( key )
|
10
|
-
## note: use (always) a **symbol** for key lookup for now
|
11
|
-
@@fancies_by_key[ key.downcase.to_sym ]
|
12
|
-
end
|
13
|
-
|
14
|
-
def self.find_by_name( name )
|
15
|
-
## note: allow string AND symbols (thus, use .to_s !!!)
|
16
|
-
## allow spaces e.g. Bug Cat is the same as BugCat
|
17
|
-
## note: downcase name e.g. allow BugCat too (not just Bug Cat)
|
18
|
-
@@fancies_by_name[ name.gsub( / /, '' ).downcase.to_s ]
|
19
|
-
end
|
20
|
-
|
21
|
-
## add "generic" convenience find helper
|
22
|
-
def self.find_by( **kwargs )
|
23
|
-
if kwargs[ :key ]
|
24
|
-
find_by_key( kwargs[ :key ] )
|
25
|
-
elsif kwargs[ :name ]
|
26
|
-
find_by_name( kwargs[ :name] )
|
27
|
-
else
|
28
|
-
## todo/fix: throw argument except!!!
|
29
|
-
nil
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
def self.[]( key )
|
34
|
-
if key.is_a? Symbol ## e.g. :genesis, :bugcat, etc.
|
35
|
-
f = find_by_key( key )
|
36
|
-
f = find_by_name( key ) if f.nil? ## try fancy name next - why? why not?
|
37
|
-
f
|
38
|
-
else ## assume string
|
39
|
-
f = find_by_name( key ) ## search by key next - why? why not?
|
40
|
-
f
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
|
45
|
-
def self.each
|
46
|
-
@@fancies_by_key.each do |(key,fancy)|
|
47
|
-
yield( fancy )
|
48
|
-
end
|
49
|
-
end
|
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
|
-
|
68
|
-
def self.size() @@fancies_by_key.size; end ## todo: add length alias too? why? why not?
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
attr_accessor :key,
|
75
|
-
:name,
|
76
|
-
:name_cn,
|
77
|
-
:date,
|
78
|
-
:desc,
|
79
|
-
:exclusive,
|
80
|
-
:specialedition,
|
81
|
-
:recipe,
|
82
|
-
:count,
|
83
|
-
:limit,
|
84
|
-
:ids,
|
85
|
-
:time_start,
|
86
|
-
:time_end
|
87
|
-
|
88
|
-
def initialize( **kwargs )
|
89
|
-
@exclusive = @specialedition = @recipe = nil
|
90
|
-
update( kwargs )
|
91
|
-
end
|
92
|
-
|
93
|
-
def update( **kwargs )
|
94
|
-
kwargs.each do |name,value|
|
95
|
-
send( "#{name}=", value ) ## use "regular" plain/classic attribute setter
|
96
|
-
end
|
97
|
-
self ## return self for chaining
|
98
|
-
end
|
99
|
-
|
100
|
-
def exclusive?() @exclusive.nil? == false; end
|
101
|
-
def specialedition?() @specialedition.nil? == false; end
|
102
|
-
alias_method :special_edition?, :specialedition?
|
103
|
-
def recipe?() @recipe.nil? == false; end
|
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
|
138
|
-
|
139
|
-
|
140
|
-
###########################################
|
141
|
-
## auto-fill fancies
|
142
|
-
FANCIES.each do |key,h|
|
143
|
-
|
144
|
-
name = h[:name]
|
145
|
-
name_cn = h[:name_cn] # add chinese name if present
|
146
|
-
|
147
|
-
date_str = h[:date]
|
148
|
-
date_str = h[:recipe][:time][:start] if date_str.nil? && h[:recipe]
|
149
|
-
date_str = h[:specialedition][:time][:start] if date_str.nil? && h[:specialedition]
|
150
|
-
|
151
|
-
date = Date.strptime( date_str, '%Y-%m-%d' )
|
152
|
-
|
153
|
-
attribs = {
|
154
|
-
key: key,
|
155
|
-
name: name,
|
156
|
-
name_cn: name_cn,
|
157
|
-
date: date,
|
158
|
-
desc: h[:desc]
|
159
|
-
}
|
160
|
-
|
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
|
192
|
-
|
193
|
-
|
194
|
-
fancy = Fancy.new( **attribs )
|
195
|
-
## pp fancy
|
196
|
-
|
197
|
-
## note: key MUST be a symbol (NOT a string)
|
198
|
-
fancies_by_key[key] = fancy
|
199
|
-
|
200
|
-
## note: downcase name and remove all spaces e.g. Bug Cat => bugcat
|
201
|
-
fancies_by_name[name.gsub( / /, '' ).downcase] = fancy
|
202
|
-
fancies_by_name[name_cn] = fancy if name_cn ## add chinese name too if present
|
203
|
-
end
|
204
|
-
|
205
|
-
end # class Fancy
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
|
4
|
+
class Fancy
|
5
|
+
|
6
|
+
def self.fancies_by_key() @@fancies_by_key ||= {}; end
|
7
|
+
def self.fancies_by_name() @@fancies_by_name ||= {}; end
|
8
|
+
|
9
|
+
def self.find_by_key( key )
|
10
|
+
## note: use (always) a **symbol** for key lookup for now
|
11
|
+
@@fancies_by_key[ key.downcase.to_sym ]
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.find_by_name( name )
|
15
|
+
## note: allow string AND symbols (thus, use .to_s !!!)
|
16
|
+
## allow spaces e.g. Bug Cat is the same as BugCat
|
17
|
+
## note: downcase name e.g. allow BugCat too (not just Bug Cat)
|
18
|
+
@@fancies_by_name[ name.gsub( / /, '' ).downcase.to_s ]
|
19
|
+
end
|
20
|
+
|
21
|
+
## add "generic" convenience find helper
|
22
|
+
def self.find_by( **kwargs )
|
23
|
+
if kwargs[ :key ]
|
24
|
+
find_by_key( kwargs[ :key ] )
|
25
|
+
elsif kwargs[ :name ]
|
26
|
+
find_by_name( kwargs[ :name] )
|
27
|
+
else
|
28
|
+
## todo/fix: throw argument except!!!
|
29
|
+
nil
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.[]( key )
|
34
|
+
if key.is_a? Symbol ## e.g. :genesis, :bugcat, etc.
|
35
|
+
f = find_by_key( key )
|
36
|
+
f = find_by_name( key ) if f.nil? ## try fancy name next - why? why not?
|
37
|
+
f
|
38
|
+
else ## assume string
|
39
|
+
f = find_by_name( key ) ## search by key next - why? why not?
|
40
|
+
f
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
def self.each
|
46
|
+
@@fancies_by_key.each do |(key,fancy)|
|
47
|
+
yield( fancy )
|
48
|
+
end
|
49
|
+
end
|
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
|
+
|
68
|
+
def self.size() @@fancies_by_key.size; end ## todo: add length alias too? why? why not?
|
69
|
+
|
70
|
+
|
71
|
+
|
72
|
+
|
73
|
+
|
74
|
+
attr_accessor :key,
|
75
|
+
:name,
|
76
|
+
:name_cn,
|
77
|
+
:date,
|
78
|
+
:desc,
|
79
|
+
:exclusive,
|
80
|
+
:specialedition,
|
81
|
+
:recipe,
|
82
|
+
:count,
|
83
|
+
:limit,
|
84
|
+
:ids,
|
85
|
+
:time_start,
|
86
|
+
:time_end
|
87
|
+
|
88
|
+
def initialize( **kwargs )
|
89
|
+
@exclusive = @specialedition = @recipe = nil
|
90
|
+
update( kwargs )
|
91
|
+
end
|
92
|
+
|
93
|
+
def update( **kwargs )
|
94
|
+
kwargs.each do |name,value|
|
95
|
+
send( "#{name}=", value ) ## use "regular" plain/classic attribute setter
|
96
|
+
end
|
97
|
+
self ## return self for chaining
|
98
|
+
end
|
99
|
+
|
100
|
+
def exclusive?() @exclusive.nil? == false; end
|
101
|
+
def specialedition?() @specialedition.nil? == false; end
|
102
|
+
alias_method :special_edition?, :specialedition?
|
103
|
+
def recipe?() @recipe.nil? == false; end
|
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
|
138
|
+
|
139
|
+
|
140
|
+
###########################################
|
141
|
+
## auto-fill fancies
|
142
|
+
FANCIES.each do |key,h|
|
143
|
+
|
144
|
+
name = h[:name]
|
145
|
+
name_cn = h[:name_cn] # add chinese name if present
|
146
|
+
|
147
|
+
date_str = h[:date]
|
148
|
+
date_str = h[:recipe][:time][:start] if date_str.nil? && h[:recipe]
|
149
|
+
date_str = h[:specialedition][:time][:start] if date_str.nil? && h[:specialedition]
|
150
|
+
|
151
|
+
date = Date.strptime( date_str, '%Y-%m-%d' )
|
152
|
+
|
153
|
+
attribs = {
|
154
|
+
key: key,
|
155
|
+
name: name,
|
156
|
+
name_cn: name_cn,
|
157
|
+
date: date,
|
158
|
+
desc: h[:desc]
|
159
|
+
}
|
160
|
+
|
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
|
192
|
+
|
193
|
+
|
194
|
+
fancy = Fancy.new( **attribs )
|
195
|
+
## pp fancy
|
196
|
+
|
197
|
+
## note: key MUST be a symbol (NOT a string)
|
198
|
+
fancies_by_key[key] = fancy
|
199
|
+
|
200
|
+
## note: downcase name and remove all spaces e.g. Bug Cat => bugcat
|
201
|
+
fancies_by_name[name.gsub( / /, '' ).downcase] = fancy
|
202
|
+
fancies_by_name[name_cn] = fancy if name_cn ## add chinese name too if present
|
203
|
+
end
|
204
|
+
|
205
|
+
end # class Fancy
|
data/lib/kittyverse/gene.rb
CHANGED
@@ -1,55 +1,55 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
|
4
|
-
class Gene
|
5
|
-
|
6
|
-
### todo/check:
|
7
|
-
## find a better name for Slice(incl.4 genes)
|
8
|
-
## e.g. GeneFour, Gene4, GeneGroup, GeneSlice,TraitGenes,... - why? why not?
|
9
|
-
|
10
|
-
class Slice ## Gene::Slice (nested class)
|
11
|
-
|
12
|
-
attr_reader :type # trait type (tt)
|
13
|
-
attr_reader :d, :r1, :r2, :r3
|
14
|
-
# d (dominant gene) -- todo/check: rename to just d instead of d0 - why? why not?
|
15
|
-
# r1 (1st order recessive gene)
|
16
|
-
# r2 (2nd order recessive gene)
|
17
|
-
# r3 (3rd order recessive gene)
|
18
|
-
alias_method :d0, :d # allow "classic" alias for d too
|
19
|
-
|
20
|
-
## compat: add alias for ("new/modern") p, h1, h2, h3
|
21
|
-
## p(rimary), h(idden) 1, h(idden) 2, h(idden) 3
|
22
|
-
alias_method :p, :d
|
23
|
-
alias_method :h1, :r1
|
24
|
-
alias_method :h2, :r2
|
25
|
-
alias_method :h3, :r3
|
26
|
-
|
27
|
-
|
28
|
-
def initialize( type, d, r1, r2, r3 )
|
29
|
-
@type = TraitType[type] ## lookup trait type by key (e.g. :body, :pattern, etc.)
|
30
|
-
@d = @type[d] ## lookup trait (from trait type) by kai code (e.g. "1", "a", etc.)
|
31
|
-
@r1 = @type[r1]
|
32
|
-
@r2 = @type[r2]
|
33
|
-
@r3 = @type[r3]
|
34
|
-
end
|
35
|
-
|
36
|
-
def [](index)
|
37
|
-
case index
|
38
|
-
when 0 then @d
|
39
|
-
when 1 then @r1
|
40
|
-
when 2 then @r2
|
41
|
-
when 3 then @r3
|
42
|
-
else nil ## return nil for unknown index for now (raise except - why? why not?)
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
def purebred?() @d == @r1 && @d == @r2 && @d == @r3; end
|
47
|
-
alias_method :pure?, :purebred?
|
48
|
-
|
49
|
-
|
50
|
-
def to_kai
|
51
|
-
@r3.kai + @r2.kai + @r1.kai + @d.kai
|
52
|
-
end ## return a string in kai/base32 notation
|
53
|
-
|
54
|
-
end # class Slice
|
55
|
-
end # class Gene
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
|
4
|
+
class Gene
|
5
|
+
|
6
|
+
### todo/check:
|
7
|
+
## find a better name for Slice(incl.4 genes)
|
8
|
+
## e.g. GeneFour, Gene4, GeneGroup, GeneSlice,TraitGenes,... - why? why not?
|
9
|
+
|
10
|
+
class Slice ## Gene::Slice (nested class)
|
11
|
+
|
12
|
+
attr_reader :type # trait type (tt)
|
13
|
+
attr_reader :d, :r1, :r2, :r3
|
14
|
+
# d (dominant gene) -- todo/check: rename to just d instead of d0 - why? why not?
|
15
|
+
# r1 (1st order recessive gene)
|
16
|
+
# r2 (2nd order recessive gene)
|
17
|
+
# r3 (3rd order recessive gene)
|
18
|
+
alias_method :d0, :d # allow "classic" alias for d too
|
19
|
+
|
20
|
+
## compat: add alias for ("new/modern") p, h1, h2, h3
|
21
|
+
## p(rimary), h(idden) 1, h(idden) 2, h(idden) 3
|
22
|
+
alias_method :p, :d
|
23
|
+
alias_method :h1, :r1
|
24
|
+
alias_method :h2, :r2
|
25
|
+
alias_method :h3, :r3
|
26
|
+
|
27
|
+
|
28
|
+
def initialize( type, d, r1, r2, r3 )
|
29
|
+
@type = TraitType[type] ## lookup trait type by key (e.g. :body, :pattern, etc.)
|
30
|
+
@d = @type[d] ## lookup trait (from trait type) by kai code (e.g. "1", "a", etc.)
|
31
|
+
@r1 = @type[r1]
|
32
|
+
@r2 = @type[r2]
|
33
|
+
@r3 = @type[r3]
|
34
|
+
end
|
35
|
+
|
36
|
+
def [](index)
|
37
|
+
case index
|
38
|
+
when 0 then @d
|
39
|
+
when 1 then @r1
|
40
|
+
when 2 then @r2
|
41
|
+
when 3 then @r3
|
42
|
+
else nil ## return nil for unknown index for now (raise except - why? why not?)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def purebred?() @d == @r1 && @d == @r2 && @d == @r3; end
|
47
|
+
alias_method :pure?, :purebred?
|
48
|
+
|
49
|
+
|
50
|
+
def to_kai
|
51
|
+
@r3.kai + @r2.kai + @r1.kai + @d.kai
|
52
|
+
end ## return a string in kai/base32 notation
|
53
|
+
|
54
|
+
end # class Slice
|
55
|
+
end # class Gene
|