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,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