kittyverse 0.4.5 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,236 +1,236 @@
1
- # encoding: utf-8
2
-
3
-
4
- class Genome
5
-
6
- def initialize( arg )
7
- if arg.is_a? Integer ## use Integer (Fixnum+Bignum??) - why? why not?
8
- num = arg
9
- kai = Kai.encode( num )
10
- else
11
- if arg.downcase.start_with?( '0x' ) ## assume hexstring( base16 )
12
- kai = Kai.encode( arg.to_i(16) )
13
- else # else assume string in kai/base32 format
14
- kai = arg
15
- kai = kai.gsub( ' ', '' ) ## allow spaces (strip/remove)
16
- end
17
- end
18
- ## puts "Genome.initialize #{kai}"
19
-
20
- @kai = kai ## note: store/save kai without any spaces ("compact" format)
21
- @genes = build_genes( kai ) ## array of (sliced) genes (block of four genes)
22
- end
23
-
24
-
25
- def kai() Kai.fmt( @kai ); end # return formatted in blocks of 4
26
- def bytes() Kai.bytes( @kai ); end
27
-
28
- def num() Kai.decode( @kai ); end
29
- alias_method :to_i, :num
30
-
31
- def electrologica() Electrologica.fmt( Electrologica.encode( num ) ); end # return formatted in electrologica base32 format
32
- alias_method :codes, :electrologica
33
-
34
- def binary
35
- @kai.chars.each_slice(4).map do |slice|
36
- buf = ""
37
- buf << Kai::BINARY[slice[0]]
38
- buf << "-"
39
- buf << Kai::BINARY[slice[1]]
40
- buf << "-"
41
- buf << Kai::BINARY[slice[2]]
42
- buf << "-"
43
- buf << Kai::BINARY[slice[3]]
44
- buf
45
- end.join( " " )
46
- end
47
- alias_method :bin, :binary
48
-
49
-
50
- def build_genes( kai )
51
- kai = kai.reverse ## note: reserve for easy left-to-right access
52
- genes = [] ## array of (sliced) genes (block of four genes)
53
- ## fix/todo: use as_json for "official" api order
54
- ## note: use insert order from "official" api
55
-
56
- ## genes << Gene::Slice.new( :body, kai[0],
57
- ## kai[1],
58
- ## kai[2],
59
- ## kai[3] )
60
- ## genes << Gene::Slice.new( :pattern, kai[4+0],
61
- ## kai[4+1],
62
- ## kai[4+2],
63
- ## kai[4+3]] )
64
-
65
- keys.each_with_index do |key,i|
66
- genes << Gene::Slice.new( key, kai[4*i+0],
67
- kai[4*i+1],
68
- kai[4*i+2],
69
- kai[4*i+3])
70
- end
71
- genes
72
- end
73
-
74
-
75
- def body() @genes[0]; end ## Fur (FU)
76
- def pattern() @genes[1]; end ## Pattern (PA)
77
- def coloreyes() @genes[2]; end ## Eyes Color (EC)
78
- def eyes() @genes[3]; end ## Eyes Shape (ES)
79
- def colorprimary() @genes[4]; end ## Base Color (BC)
80
- def colorsecondary() @genes[5]; end ## Highlight Color (HC)
81
- def colortertiary() @genes[6]; end ## Accent Color (AC)
82
- def wild() @genes[7]; end ## Wild Element (WE)
83
- def mouth() @genes[8]; end ## Mouth (MO)
84
- def environment() @genes[9]; end ## Environment (EN)
85
- def secret() @genes[10]; end ## Secret (SE)
86
- def prestige() @genes[11]; end ## Purrstige (PU)
87
-
88
- alias_method :color1, :colorprimary
89
- alias_method :color2, :colorsecondary
90
- alias_method :color3, :colortertiary
91
- ## todo: add more alias(es) - why? why not?
92
-
93
- ## add (convenience) alias for two-letter (trait type) codes too
94
- alias_method :fu, :body
95
- alias_method :pa, :pattern
96
- alias_method :ec, :coloreyes
97
- alias_method :es, :eyes
98
- alias_method :bc, :colorprimary
99
- alias_method :hc, :colorsecondary
100
- alias_method :ac, :colortertiary
101
- alias_method :we, :wild
102
- alias_method :mo, :mouth
103
- alias_method :en, :environment
104
- alias_method :se, :secret
105
- alias_method :pu, :prestige
106
-
107
-
108
- def each() @genes.each { |slice| yield(slice) }; end
109
- def each_with_index() @genes.each_with_index { |slice,i| yield(slice,i) }; end
110
- alias_method :each_slice, :each
111
- alias_method :each_slice_with_index, :each_with_index
112
-
113
- def each_gene
114
- @genes.each do |slice|
115
- yield(slice.p)
116
- yield(slice.r1)
117
- yield(slice.r2)
118
- yield(slice.r3)
119
- end
120
- end
121
- def each_gene_with_index
122
- @genes.each_with_index do |slice,i|
123
- yield(slice.p, 4*i+0)
124
- yield(slice.r1, 4*i+1)
125
- yield(slice.r2, 4*i+2)
126
- yield(slice.r3, 4*i+3)
127
- end
128
- end
129
-
130
- def keys ## rename to trait_type_keys - why? why not?
131
- [:body, ### todo/fix: use TRAITS.keys or something - why? why not?
132
- :pattern,
133
- :coloreyes,
134
- :eyes,
135
- :colorprimary,
136
- :colorsecondary,
137
- :colortertiary,
138
- :wild,
139
- :mouth,
140
- :environment,
141
- :secret,
142
- :prestige]
143
- end
144
-
145
- def index( key )
146
- if key.size == 2 && key =~ /^[A-Za-z]{2}$/ ## check for codes e.g. FU, PA, ... (or fu, pa,...)
147
- key = key.upcase.to_sym
148
- @@codes_by_index ||= %w(FU PA EC ES BC HC AC WE MO EN SE PU)
149
- .each_with_index.reduce({}) do |h,(code,i)|
150
- h[code.to_sym]=i; h
151
- end
152
- @@codes_by_index[ key ]
153
- else
154
- key = key.downcase.to_sym
155
- key = ALT_TRAIT_TYPE_KEYS[ key ] if ALT_TRAIT_TYPE_KEYS[ key ]
156
-
157
- @@keys_by_index ||= keys.each_with_index.reduce({}) do |h,(key,i)|
158
- h[key]=i; h
159
- end
160
- @@keys_by_index[ key ]
161
- end
162
- end
163
-
164
-
165
- def [](key)
166
- if key.is_a? Integer ## assume 0,1,2,3,.. index
167
- q , r = key.divmod(4) ## q=quotient, r=rest/modulus
168
- ## e.g. 3.divmod(4) => [0,3]
169
- ## 4.divmod(4) => [1,0]
170
- ## 5.divmod(4) => [1,1] etc.
171
- @genes[q][r]
172
- else ## assume trait type key / symbol
173
- @genes[index(key)]
174
- end
175
- end
176
-
177
-
178
- def build_tables() GenomeTables.new( self ).build; end
179
- end # class Genome
180
-
181
-
182
-
183
-
184
- class GenomeTables
185
- def initialize( genome )
186
- @genome = genome
187
- end
188
-
189
- def build
190
- pos = 0
191
- buf = ""
192
- buf << "Genes (256-Bit Integer Number):\n"
193
- buf << "- Base 10 (Decimal): #{@genome.num}\n"
194
- buf << "- Base 2 (Binary): #{@genome.binary}\n"
195
- buf << "- Base 2⁵ = 32\n"
196
- buf << " - (Kai): #{@genome.kai}\n"
197
- buf << " - (Codes): #{@genome.codes}\n"
198
- buf << "\n\n"
199
-
200
- @genome.each do |slice|
201
- tt = slice.type
202
-
203
- buf << "#{tt.name} (#{tt.code}) - Genes #{tt.genes}\n\n"
204
-
205
- ###
206
- ## fix/todo: add stars for purity?
207
- ## **** - all traits the same
208
- ## *** - two same pairs of traits
209
- ## ** - one pair of same traits
210
-
211
- buf << "|Gene |Binary |Kai |Code | Name | |\n"
212
- buf << "|------|---------|-----|-----|----------|---|\n"
213
- buf << "| #{pos} | #{slice.d.binary} | #{slice.d.kai} | #{slice.d.code} |**#{fmt_trait(slice.d)}** | d |\n"; pos+=1
214
- buf << "| #{pos} | #{slice.r1.binary} | #{slice.r1.kai} | #{slice.r1.code} |#{fmt_trait(slice.r1)} | r1 |\n"; pos+=1
215
- buf << "| #{pos} | #{slice.r2.binary} | #{slice.r2.kai} | #{slice.r2.code} |#{fmt_trait(slice.r2)} | r2 |\n"; pos+=1
216
- buf << "| #{pos} | #{slice.r3.binary} | #{slice.r3.kai} | #{slice.r3.code} |#{fmt_trait(slice.r3)} | r3 |\n"; pos+=1
217
- buf << "\n"
218
-
219
- if tt.key == :body ## add legend for first entry
220
- buf << "d = dominant, r1 = 1st order recessive, r2 = 2nd order recessive, r3 = 3rd order recessive\n\n"
221
- end
222
- end
223
-
224
- buf
225
- end
226
-
227
- ####################
228
- ## helpers
229
-
230
- def fmt_trait( trait )
231
- buf = ""
232
- buf << (trait.name || '∅')
233
- buf << " #{trait.tier_roman}" if trait.tier > 0
234
- buf
235
- end
236
- end # class GenomeTables
1
+ # encoding: utf-8
2
+
3
+
4
+ class Genome
5
+
6
+ def initialize( arg )
7
+ if arg.is_a? Integer ## use Integer (Fixnum+Bignum??) - why? why not?
8
+ num = arg
9
+ kai = Kai.encode( num )
10
+ else
11
+ if arg.downcase.start_with?( '0x' ) ## assume hexstring( base16 )
12
+ kai = Kai.encode( arg.to_i(16) )
13
+ else # else assume string in kai/base32 format
14
+ kai = arg
15
+ kai = kai.gsub( ' ', '' ) ## allow spaces (strip/remove)
16
+ end
17
+ end
18
+ ## puts "Genome.initialize #{kai}"
19
+
20
+ @kai = kai ## note: store/save kai without any spaces ("compact" format)
21
+ @genes = build_genes( kai ) ## array of (sliced) genes (block of four genes)
22
+ end
23
+
24
+
25
+ def kai() Kai.fmt( @kai ); end # return formatted in blocks of 4
26
+ def bytes() Kai.bytes( @kai ); end
27
+
28
+ def num() Kai.decode( @kai ); end
29
+ alias_method :to_i, :num
30
+
31
+ def electrologica() Electrologica.fmt( Electrologica.encode( num ) ); end # return formatted in electrologica base32 format
32
+ alias_method :codes, :electrologica
33
+
34
+ def binary
35
+ @kai.chars.each_slice(4).map do |slice|
36
+ buf = ""
37
+ buf << Kai::BINARY[slice[0]]
38
+ buf << "-"
39
+ buf << Kai::BINARY[slice[1]]
40
+ buf << "-"
41
+ buf << Kai::BINARY[slice[2]]
42
+ buf << "-"
43
+ buf << Kai::BINARY[slice[3]]
44
+ buf
45
+ end.join( " " )
46
+ end
47
+ alias_method :bin, :binary
48
+
49
+
50
+ def build_genes( kai )
51
+ kai = kai.reverse ## note: reserve for easy left-to-right access
52
+ genes = [] ## array of (sliced) genes (block of four genes)
53
+ ## fix/todo: use as_json for "official" api order
54
+ ## note: use insert order from "official" api
55
+
56
+ ## genes << Gene::Slice.new( :body, kai[0],
57
+ ## kai[1],
58
+ ## kai[2],
59
+ ## kai[3] )
60
+ ## genes << Gene::Slice.new( :pattern, kai[4+0],
61
+ ## kai[4+1],
62
+ ## kai[4+2],
63
+ ## kai[4+3]] )
64
+
65
+ keys.each_with_index do |key,i|
66
+ genes << Gene::Slice.new( key, kai[4*i+0],
67
+ kai[4*i+1],
68
+ kai[4*i+2],
69
+ kai[4*i+3])
70
+ end
71
+ genes
72
+ end
73
+
74
+
75
+ def body() @genes[0]; end ## Fur (FU)
76
+ def pattern() @genes[1]; end ## Pattern (PA)
77
+ def coloreyes() @genes[2]; end ## Eyes Color (EC)
78
+ def eyes() @genes[3]; end ## Eyes Shape (ES)
79
+ def colorprimary() @genes[4]; end ## Base Color (BC)
80
+ def colorsecondary() @genes[5]; end ## Highlight Color (HC)
81
+ def colortertiary() @genes[6]; end ## Accent Color (AC)
82
+ def wild() @genes[7]; end ## Wild Element (WE)
83
+ def mouth() @genes[8]; end ## Mouth (MO)
84
+ def environment() @genes[9]; end ## Environment (EN)
85
+ def secret() @genes[10]; end ## Secret (SE)
86
+ def prestige() @genes[11]; end ## Purrstige (PU)
87
+
88
+ alias_method :color1, :colorprimary
89
+ alias_method :color2, :colorsecondary
90
+ alias_method :color3, :colortertiary
91
+ ## todo: add more alias(es) - why? why not?
92
+
93
+ ## add (convenience) alias for two-letter (trait type) codes too
94
+ alias_method :fu, :body
95
+ alias_method :pa, :pattern
96
+ alias_method :ec, :coloreyes
97
+ alias_method :es, :eyes
98
+ alias_method :bc, :colorprimary
99
+ alias_method :hc, :colorsecondary
100
+ alias_method :ac, :colortertiary
101
+ alias_method :we, :wild
102
+ alias_method :mo, :mouth
103
+ alias_method :en, :environment
104
+ alias_method :se, :secret
105
+ alias_method :pu, :prestige
106
+
107
+
108
+ def each() @genes.each { |slice| yield(slice) }; end
109
+ def each_with_index() @genes.each_with_index { |slice,i| yield(slice,i) }; end
110
+ alias_method :each_slice, :each
111
+ alias_method :each_slice_with_index, :each_with_index
112
+
113
+ def each_gene
114
+ @genes.each do |slice|
115
+ yield(slice.p)
116
+ yield(slice.r1)
117
+ yield(slice.r2)
118
+ yield(slice.r3)
119
+ end
120
+ end
121
+ def each_gene_with_index
122
+ @genes.each_with_index do |slice,i|
123
+ yield(slice.p, 4*i+0)
124
+ yield(slice.r1, 4*i+1)
125
+ yield(slice.r2, 4*i+2)
126
+ yield(slice.r3, 4*i+3)
127
+ end
128
+ end
129
+
130
+ def keys ## rename to trait_type_keys - why? why not?
131
+ [:body, ### todo/fix: use TRAITS.keys or something - why? why not?
132
+ :pattern,
133
+ :coloreyes,
134
+ :eyes,
135
+ :colorprimary,
136
+ :colorsecondary,
137
+ :colortertiary,
138
+ :wild,
139
+ :mouth,
140
+ :environment,
141
+ :secret,
142
+ :prestige]
143
+ end
144
+
145
+ def index( key )
146
+ if key.size == 2 && key =~ /^[A-Za-z]{2}$/ ## check for codes e.g. FU, PA, ... (or fu, pa,...)
147
+ key = key.upcase.to_sym
148
+ @@codes_by_index ||= %w(FU PA EC ES BC HC AC WE MO EN SE PU)
149
+ .each_with_index.reduce({}) do |h,(code,i)|
150
+ h[code.to_sym]=i; h
151
+ end
152
+ @@codes_by_index[ key ]
153
+ else
154
+ key = key.downcase.to_sym
155
+ key = ALT_TRAIT_TYPE_KEYS[ key ] if ALT_TRAIT_TYPE_KEYS[ key ]
156
+
157
+ @@keys_by_index ||= keys.each_with_index.reduce({}) do |h,(key,i)|
158
+ h[key]=i; h
159
+ end
160
+ @@keys_by_index[ key ]
161
+ end
162
+ end
163
+
164
+
165
+ def [](key)
166
+ if key.is_a? Integer ## assume 0,1,2,3,.. index
167
+ q , r = key.divmod(4) ## q=quotient, r=rest/modulus
168
+ ## e.g. 3.divmod(4) => [0,3]
169
+ ## 4.divmod(4) => [1,0]
170
+ ## 5.divmod(4) => [1,1] etc.
171
+ @genes[q][r]
172
+ else ## assume trait type key / symbol
173
+ @genes[index(key)]
174
+ end
175
+ end
176
+
177
+
178
+ def build_tables() GenomeTables.new( self ).build; end
179
+ end # class Genome
180
+
181
+
182
+
183
+
184
+ class GenomeTables
185
+ def initialize( genome )
186
+ @genome = genome
187
+ end
188
+
189
+ def build
190
+ pos = 0
191
+ buf = ""
192
+ buf << "Genes (256-Bit Integer Number):\n"
193
+ buf << "- Base 10 (Decimal): #{@genome.num}\n"
194
+ buf << "- Base 2 (Binary): #{@genome.binary}\n"
195
+ buf << "- Base 2⁵ = 32\n"
196
+ buf << " - (Kai): #{@genome.kai}\n"
197
+ buf << " - (Codes): #{@genome.codes}\n"
198
+ buf << "\n\n"
199
+
200
+ @genome.each do |slice|
201
+ tt = slice.type
202
+
203
+ buf << "#{tt.name} (#{tt.code}) - Genes #{tt.genes}\n\n"
204
+
205
+ ###
206
+ ## fix/todo: add stars for purity?
207
+ ## **** - all traits the same
208
+ ## *** - two same pairs of traits
209
+ ## ** - one pair of same traits
210
+
211
+ buf << "|Gene |Binary |Kai |Code | Name | |\n"
212
+ buf << "|------|---------|-----|-----|----------|---|\n"
213
+ buf << "| #{pos} | #{slice.d.binary} | #{slice.d.kai} | #{slice.d.code} |**#{fmt_trait(slice.d)}** | d |\n"; pos+=1
214
+ buf << "| #{pos} | #{slice.r1.binary} | #{slice.r1.kai} | #{slice.r1.code} |#{fmt_trait(slice.r1)} | r1 |\n"; pos+=1
215
+ buf << "| #{pos} | #{slice.r2.binary} | #{slice.r2.kai} | #{slice.r2.code} |#{fmt_trait(slice.r2)} | r2 |\n"; pos+=1
216
+ buf << "| #{pos} | #{slice.r3.binary} | #{slice.r3.kai} | #{slice.r3.code} |#{fmt_trait(slice.r3)} | r3 |\n"; pos+=1
217
+ buf << "\n"
218
+
219
+ if tt.key == :body ## add legend for first entry
220
+ buf << "d = dominant, r1 = 1st order recessive, r2 = 2nd order recessive, r3 = 3rd order recessive\n\n"
221
+ end
222
+ end
223
+
224
+ buf
225
+ end
226
+
227
+ ####################
228
+ ## helpers
229
+
230
+ def fmt_trait( trait )
231
+ buf = ""
232
+ buf << (trait.name || '∅')
233
+ buf << " #{trait.tier_roman}" if trait.tier > 0
234
+ buf
235
+ end
236
+ end # class GenomeTables