kittyverse 0.4.5 → 0.5.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.
@@ -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
@@ -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