about summary refs log tree commit diff stats
path: root/app/models
diff options
context:
space:
mode:
authorStar Rauchenberger <fefferburbia@gmail.com>2024-12-07 11:49:49 -0500
committerStar Rauchenberger <fefferburbia@gmail.com>2024-12-07 11:49:49 -0500
commit56f5841d4b9c12296cdfcaeff174b2627d59afc8 (patch)
tree4f7da4ebbe5ee15a1594b26466ed78e2cf10de35 /app/models
parentc1b0443ba2aebdbd39291ddab0c189f3f4831320 (diff)
downloadpokeviewer-56f5841d4b9c12296cdfcaeff174b2627d59afc8.tar.gz
pokeviewer-56f5841d4b9c12296cdfcaeff174b2627d59afc8.tar.bz2
pokeviewer-56f5841d4b9c12296cdfcaeff174b2627d59afc8.zip
Migrate to full rails app
Diffstat (limited to 'app/models')
-rw-r--r--app/models/ability.rb5
-rw-r--r--app/models/application_record.rb3
-rw-r--r--app/models/concerns/.keep0
-rw-r--r--app/models/gift_ribbon.rb3
-rw-r--r--app/models/item.rb41
-rw-r--r--app/models/location.rb5
-rw-r--r--app/models/move.rb31
-rw-r--r--app/models/pokedex_entry.rb4
-rw-r--r--app/models/pokemon.rb165
-rw-r--r--app/models/pokeviewer/ability.rb7
-rw-r--r--app/models/pokeviewer/application_record.rb5
-rw-r--r--app/models/pokeviewer/gift_ribbon.rb5
-rw-r--r--app/models/pokeviewer/item.rb43
-rw-r--r--app/models/pokeviewer/location.rb7
-rw-r--r--app/models/pokeviewer/move.rb33
-rw-r--r--app/models/pokeviewer/pokedex_entry.rb6
-rw-r--r--app/models/pokeviewer/pokemon.rb167
-rw-r--r--app/models/pokeviewer/revision.rb496
-rw-r--r--app/models/pokeviewer/species.rb26
-rw-r--r--app/models/pokeviewer/trainer.rb95
-rw-r--r--app/models/revision.rb494
-rw-r--r--app/models/species.rb24
-rw-r--r--app/models/trainer.rb93
23 files changed, 868 insertions, 890 deletions
diff --git a/app/models/ability.rb b/app/models/ability.rb new file mode 100644 index 0000000..5b7e8b4 --- /dev/null +++ b/app/models/ability.rb
@@ -0,0 +1,5 @@
1class Ability < ApplicationRecord
2 validates :name, presence: true, uniqueness: true
3
4 validates :description, presence: true
5end
diff --git a/app/models/application_record.rb b/app/models/application_record.rb new file mode 100644 index 0000000..b63caeb --- /dev/null +++ b/app/models/application_record.rb
@@ -0,0 +1,3 @@
1class ApplicationRecord < ActiveRecord::Base
2 primary_abstract_class
3end
diff --git a/app/models/concerns/.keep b/app/models/concerns/.keep new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/app/models/concerns/.keep
diff --git a/app/models/gift_ribbon.rb b/app/models/gift_ribbon.rb new file mode 100644 index 0000000..dbf3c6f --- /dev/null +++ b/app/models/gift_ribbon.rb
@@ -0,0 +1,3 @@
1class GiftRibbon < ApplicationRecord
2 validates :description, presence: true
3end
diff --git a/app/models/item.rb b/app/models/item.rb new file mode 100644 index 0000000..269cf97 --- /dev/null +++ b/app/models/item.rb
@@ -0,0 +1,41 @@
1class Item < ApplicationRecord
2 validates :name, presence: true
3
4 belongs_to :move, optional: true
5 validates :move, presence: true, if: :tm?
6
7 validates :rs_description, presence: true, unless: :tm?
8 validates :frlg_description, presence: true, unless: :tm?
9
10 def description(game)
11 if game == :emerald
12 if not emerald_description.nil?
13 emerald_description
14 elsif not rs_description.nil?
15 rs_description
16 else
17 move.description game
18 end
19 elsif game == :firered or game == :leafgreen
20 if not frlg_description.nil?
21 frlg_description
22 else
23 move.description game
24 end
25 else
26 if not rs_description.nil?
27 rs_description
28 else
29 move.description game
30 end
31 end
32 end
33
34 def icon_path
35 if tm?
36 "items/tms/#{move.move_type}.png"
37 else
38 "items/#{id}.png"
39 end
40 end
41end
diff --git a/app/models/location.rb b/app/models/location.rb new file mode 100644 index 0000000..57e193f --- /dev/null +++ b/app/models/location.rb
@@ -0,0 +1,5 @@
1class Location < ApplicationRecord
2 has_many :pokemon, dependent: :nullify
3
4 validates :name, presence: true
5end
diff --git a/app/models/move.rb b/app/models/move.rb new file mode 100644 index 0000000..cbc8422 --- /dev/null +++ b/app/models/move.rb
@@ -0,0 +1,31 @@
1class Move < ApplicationRecord
2 extend Enumerize
3
4 has_many :revision_moves
5 has_many :revisions, through: :revision_moves
6
7 validates :name, presence: true, uniqueness: true
8
9 validates :pp, presence: true,
10 numericality: { greater_than_or_equal_to: 1, only_integer: true }
11
12 TYPES = [:normal, :fighting, :flying, :poison, :ground,
13 :rock, :bug, :ghost, :steel, :mystery, :fire, :water, :grass, :electric,
14 :psychic, :ice, :dragon, :dark]
15
16 validates :move_type, presence: true
17 enumerize :move_type, in: TYPES, predicates: true
18
19 validates :rs_description, presence: true
20 validates :frlg_description, presence: true
21
22 def description(game)
23 if game == :emerald and not emerald_description.nil?
24 emerald_description
25 elsif game == :firered or game == :leafgreen
26 frlg_description
27 else
28 rs_description
29 end
30 end
31end
diff --git a/app/models/pokedex_entry.rb b/app/models/pokedex_entry.rb new file mode 100644 index 0000000..9200896 --- /dev/null +++ b/app/models/pokedex_entry.rb
@@ -0,0 +1,4 @@
1class PokedexEntry < ApplicationRecord
2 belongs_to :trainer
3 belongs_to :species
4end
diff --git a/app/models/pokemon.rb b/app/models/pokemon.rb new file mode 100644 index 0000000..7db74ee --- /dev/null +++ b/app/models/pokemon.rb
@@ -0,0 +1,165 @@
1class Pokemon < ApplicationRecord
2 extend Enumerize
3 extend ActiveModel::Naming
4
5 has_many :revisions, -> { order "sequential_id ASC" }, dependent: :destroy
6
7 belongs_to :current, class_name: "Revision", optional: true
8 validate :current_is_cached
9
10 belongs_to :trainer, optional: true
11
12 validates :box, numericality: {
13 greater_than_or_equal_to: 1,
14 less_than_or_equal_to: 14,
15 only_integer: true },
16 allow_nil: true
17
18 validates :slot, presence: true,
19 uniqueness: { scope: [:trainer_id, :box] },
20 numericality: {
21 greater_than_or_equal_to: 0,
22 only_integer: true },
23 unless: Proc.new { |a| a.trainer_id.nil? }
24
25 validates :slot,
26 numericality: { less_than: 30 },
27 unless: Proc.new { |a| a.trainer_id.nil? or a.box.nil? }
28
29 validates :slot,
30 numericality: { less_than: 6 },
31 unless: Proc.new { |a| a.trainer_id.nil? or not a.box.nil? }
32
33 scope :party, -> { where(box: nil) }
34 scope :box, ->(n) { where(box: n) }
35 scope :unaccounted, -> { where(trainer_id: nil) }
36
37 validate :uuid_is_constant, on: :update
38 before_create :set_uuid
39
40 validates :ot_name, presence: true
41
42 validates :ot_number, presence: true,
43 numericality: { greater_than_or_equal_to: 0, only_integer: true }
44
45 validates :ot_gender, presence: true
46 enumerize :ot_gender, in: [:female, :male]
47
48 validates :met_level, presence: true,
49 numericality: { greater_than_or_equal_to: 1, only_integer: true },
50 if: Proc.new { |a| a.met_type == :normal }
51
52 validates :met_type, presence: true
53 enumerize :met_type,
54 in: [:normal, :hatched, :npc_trade, :fateful_encounter, :orre]
55
56 belongs_to :location, optional: true
57 validates :location, presence: true,
58 if: Proc.new { |c| c.met_type == :normal or c.met_type == :hatched}
59
60 validates :gender, presence: true
61 enumerize :gender, in: [:genderless, :female, :male]
62
63 validates :nature, presence: true
64 enumerize :nature, in: [:hardy, :lonely, :brave, :adamant, :naughty, :bold,
65 :docile, :relaxed, :impish, :lax, :timid, :hasty, :serious, :jolly,
66 :naive, :modest, :mild, :quiet, :bashful, :rash, :calm, :gentle, :sassy,
67 :careful, :quirky]
68
69 enumerize :unown_letter, in: [:a, :b, :c, :d, :e, :f, :g, :h, :i, :j, :k,
70 :l, :m, :n, :o, :p, :q, :r, :s, :t, :u, :v, :w, :x, :y, :z,
71 :question, :exclamation]
72
73 validates :pokeball, presence: true
74 enumerize :pokeball, in: [:master, :ultra, :great, :poke, :safari, :net,
75 :dive, :nest, :repeat, :timer, :luxury, :premier]
76
77 def to_param
78 uuid
79 end
80
81 def outsider?
82 (trainer.nil?) or (ot_name != trainer.name) or (ot_number != trainer.number)
83 end
84
85 def display_ot_number
86 ot_number.to_s.rjust(5, '0')
87 end
88
89 def nature_benefits?(stat)
90 if stat == :attack
91 [:lonely, :brave, :adamant, :naughty].include? nature.intern
92 elsif stat == :defense
93 [:bold, :relaxed, :impish, :lax].include? nature.intern
94 elsif stat == :speed
95 [:timid, :hasty, :jolly, :naive].include? nature.intern
96 elsif stat == :special_attack
97 [:modest, :mild, :quiet, :rash].include? nature.intern
98 elsif stat == :special_defense
99 [:calm, :gentle, :sassy, :careful].include? nature.intern
100 else
101 false
102 end
103 end
104
105 def nature_hinders?(stat)
106 if stat == :attack
107 [:bold, :timid, :modest, :calm].include? nature.intern
108 elsif stat == :defense
109 [:lonely, :hasty, :mild, :gentle].include? nature.intern
110 elsif stat == :speed
111 [:brave, :relaxed, :quiet, :sassy].include? nature.intern
112 elsif stat == :special_attack
113 [:adamant, :impish, :jolly, :careful].include? nature.intern
114 elsif stat == :special_defense
115 [:naughty, :lax, :naive, :rash].include? nature.intern
116 else
117 false
118 end
119 end
120
121 def pokeball_icon_path
122 "items/#{Pokemon.pokeball.values.find_index(pokeball) + 1}.png"
123 end
124
125 def gift_ribbon_description(ribbon)
126 if trainer.nil?
127 ""
128 else
129 trainer.gift_ribbon_description(ribbon)
130 end
131 end
132
133 def gender_symbol
134 case gender.intern
135 when :female
136 "♀"
137 when :male
138 "♂"
139 when :genderless
140 ""
141 end
142 end
143
144 private
145
146 def set_uuid
147 self.uuid = SecureRandom.uuid
148 end
149
150 def uuid_is_constant
151 errors.add(:uuid, "can't be changed") if self.uuid_changed?
152 end
153
154 def current_is_cached
155 if self.revisions.empty?
156 unless self.current_id.nil?
157 errors.add(:current, "must be null when there are no revisions")
158 end
159 else
160 unless self.current_id = self.revisions.last.id
161 errors.add(:current, "is not up-to-date")
162 end
163 end
164 end
165end
diff --git a/app/models/pokeviewer/ability.rb b/app/models/pokeviewer/ability.rb deleted file mode 100644 index 594b18c..0000000 --- a/app/models/pokeviewer/ability.rb +++ /dev/null
@@ -1,7 +0,0 @@
1module Pokeviewer
2 class Ability < ApplicationRecord
3 validates :name, presence: true, uniqueness: true
4
5 validates :description, presence: true
6 end
7end
diff --git a/app/models/pokeviewer/application_record.rb b/app/models/pokeviewer/application_record.rb deleted file mode 100644 index 6d07f27..0000000 --- a/app/models/pokeviewer/application_record.rb +++ /dev/null
@@ -1,5 +0,0 @@
1module Pokeviewer
2 class ApplicationRecord < ActiveRecord::Base
3 self.abstract_class = true
4 end
5end
diff --git a/app/models/pokeviewer/gift_ribbon.rb b/app/models/pokeviewer/gift_ribbon.rb deleted file mode 100644 index f8f4fa5..0000000 --- a/app/models/pokeviewer/gift_ribbon.rb +++ /dev/null
@@ -1,5 +0,0 @@
1module Pokeviewer
2 class GiftRibbon < ApplicationRecord
3 validates :description, presence: true
4 end
5end
diff --git a/app/models/pokeviewer/item.rb b/app/models/pokeviewer/item.rb deleted file mode 100644 index d03c584..0000000 --- a/app/models/pokeviewer/item.rb +++ /dev/null
@@ -1,43 +0,0 @@
1module Pokeviewer
2 class Item < ApplicationRecord
3 validates :name, presence: true
4
5 belongs_to :move, optional: true
6 validates :move, presence: true, if: :tm?
7
8 validates :rs_description, presence: true, unless: :tm?
9 validates :frlg_description, presence: true, unless: :tm?
10
11 def description(game)
12 if game == :emerald
13 if not emerald_description.nil?
14 emerald_description
15 elsif not rs_description.nil?
16 rs_description
17 else
18 move.description game
19 end
20 elsif game == :firered or game == :leafgreen
21 if not frlg_description.nil?
22 frlg_description
23 else
24 move.description game
25 end
26 else
27 if not rs_description.nil?
28 rs_description
29 else
30 move.description game
31 end
32 end
33 end
34
35 def icon_path
36 if tm?
37 "pokeviewer/items/tms/#{move.move_type}.png"
38 else
39 "pokeviewer/items/#{id}.png"
40 end
41 end
42 end
43end
diff --git a/app/models/pokeviewer/location.rb b/app/models/pokeviewer/location.rb deleted file mode 100644 index db37df2..0000000 --- a/app/models/pokeviewer/location.rb +++ /dev/null
@@ -1,7 +0,0 @@
1module Pokeviewer
2 class Location < ApplicationRecord
3 has_many :pokemon, dependent: :nullify
4
5 validates :name, presence: true
6 end
7end
diff --git a/app/models/pokeviewer/move.rb b/app/models/pokeviewer/move.rb deleted file mode 100644 index c63493a..0000000 --- a/app/models/pokeviewer/move.rb +++ /dev/null
@@ -1,33 +0,0 @@
1module Pokeviewer
2 class Move < ApplicationRecord
3 extend Enumerize
4
5 has_many :revision_moves
6 has_many :revisions, through: :revision_moves
7
8 validates :name, presence: true, uniqueness: true
9
10 validates :pp, presence: true,
11 numericality: { greater_than_or_equal_to: 1, only_integer: true }
12
13 TYPES = [:normal, :fighting, :flying, :poison, :ground,
14 :rock, :bug, :ghost, :steel, :mystery, :fire, :water, :grass, :electric,
15 :psychic, :ice, :dragon, :dark]
16
17 validates :move_type, presence: true
18 enumerize :move_type, in: TYPES, predicates: true
19
20 validates :rs_description, presence: true
21 validates :frlg_description, presence: true
22
23 def description(game)
24 if game == :emerald and not emerald_description.nil?
25 emerald_description
26 elsif game == :firered or game == :leafgreen
27 frlg_description
28 else
29 rs_description
30 end
31 end
32 end
33end
diff --git a/app/models/pokeviewer/pokedex_entry.rb b/app/models/pokeviewer/pokedex_entry.rb deleted file mode 100644 index 9be6a6a..0000000 --- a/app/models/pokeviewer/pokedex_entry.rb +++ /dev/null
@@ -1,6 +0,0 @@
1module Pokeviewer
2 class PokedexEntry < ApplicationRecord
3 belongs_to :trainer
4 belongs_to :species
5 end
6end
diff --git a/app/models/pokeviewer/pokemon.rb b/app/models/pokeviewer/pokemon.rb deleted file mode 100644 index 77ee89a..0000000 --- a/app/models/pokeviewer/pokemon.rb +++ /dev/null
@@ -1,167 +0,0 @@
1module Pokeviewer
2 class Pokemon < ApplicationRecord
3 extend Enumerize
4 extend ActiveModel::Naming
5
6 has_many :revisions, -> { order "sequential_id ASC" }, dependent: :destroy
7
8 belongs_to :current, class_name: "Revision", optional: true
9 validate :current_is_cached
10
11 belongs_to :trainer, optional: true
12
13 validates :box, numericality: {
14 greater_than_or_equal_to: 1,
15 less_than_or_equal_to: 14,
16 only_integer: true },
17 allow_nil: true
18
19 validates :slot, presence: true,
20 uniqueness: { scope: [:trainer_id, :box] },
21 numericality: {
22 greater_than_or_equal_to: 0,
23 only_integer: true },
24 unless: Proc.new { |a| a.trainer_id.nil? }
25
26 validates :slot,
27 numericality: { less_than: 30 },
28 unless: Proc.new { |a| a.trainer_id.nil? or a.box.nil? }
29
30 validates :slot,
31 numericality: { less_than: 6 },
32 unless: Proc.new { |a| a.trainer_id.nil? or not a.box.nil? }
33
34 scope :party, -> { where(box: nil) }
35 scope :box, ->(n) { where(box: n) }
36 scope :unaccounted, -> { where(trainer_id: nil) }
37
38 validate :uuid_is_constant, on: :update
39 before_create :set_uuid
40
41 validates :ot_name, presence: true
42
43 validates :ot_number, presence: true,
44 numericality: { greater_than_or_equal_to: 0, only_integer: true }
45
46 validates :ot_gender, presence: true
47 enumerize :ot_gender, in: [:female, :male]
48
49 validates :met_level, presence: true,
50 numericality: { greater_than_or_equal_to: 1, only_integer: true },
51 if: Proc.new { |a| a.met_type == :normal }
52
53 validates :met_type, presence: true
54 enumerize :met_type,
55 in: [:normal, :hatched, :npc_trade, :fateful_encounter, :orre]
56
57 belongs_to :location, optional: true
58 validates :location, presence: true,
59 if: Proc.new { |c| c.met_type == :normal or c.met_type == :hatched}
60
61 validates :gender, presence: true
62 enumerize :gender, in: [:genderless, :female, :male]
63
64 validates :nature, presence: true
65 enumerize :nature, in: [:hardy, :lonely, :brave, :adamant, :naughty, :bold,
66 :docile, :relaxed, :impish, :lax, :timid, :hasty, :serious, :jolly,
67 :naive, :modest, :mild, :quiet, :bashful, :rash, :calm, :gentle, :sassy,
68 :careful, :quirky]
69
70 enumerize :unown_letter, in: [:a, :b, :c, :d, :e, :f, :g, :h, :i, :j, :k,
71 :l, :m, :n, :o, :p, :q, :r, :s, :t, :u, :v, :w, :x, :y, :z,
72 :question, :exclamation]
73
74 validates :pokeball, presence: true
75 enumerize :pokeball, in: [:master, :ultra, :great, :poke, :safari, :net,
76 :dive, :nest, :repeat, :timer, :luxury, :premier]
77
78 def to_param
79 uuid
80 end
81
82 def outsider?
83 (trainer.nil?) or (ot_name != trainer.name) or (ot_number != trainer.number)
84 end
85
86 def display_ot_number
87 ot_number.to_s.rjust(5, '0')
88 end
89
90 def nature_benefits?(stat)
91 if stat == :attack
92 [:lonely, :brave, :adamant, :naughty].include? nature.intern
93 elsif stat == :defense
94 [:bold, :relaxed, :impish, :lax].include? nature.intern
95 elsif stat == :speed
96 [:timid, :hasty, :jolly, :naive].include? nature.intern
97 elsif stat == :special_attack
98 [:modest, :mild, :quiet, :rash].include? nature.intern
99 elsif stat == :special_defense
100 [:calm, :gentle, :sassy, :careful].include? nature.intern
101 else
102 false
103 end
104 end
105
106 def nature_hinders?(stat)
107 if stat == :attack
108 [:bold, :timid, :modest, :calm].include? nature.intern
109 elsif stat == :defense
110 [:lonely, :hasty, :mild, :gentle].include? nature.intern
111 elsif stat == :speed
112 [:brave, :relaxed, :quiet, :sassy].include? nature.intern
113 elsif stat == :special_attack
114 [:adamant, :impish, :jolly, :careful].include? nature.intern
115 elsif stat == :special_defense
116 [:naughty, :lax, :naive, :rash].include? nature.intern
117 else
118 false
119 end
120 end
121
122 def pokeball_icon_path
123 "pokeviewer/items/#{Pokemon.pokeball.values.find_index(pokeball) + 1}.png"
124 end
125
126 def gift_ribbon_description(ribbon)
127 if trainer.nil?
128 ""
129 else
130 trainer.gift_ribbon_description(ribbon)
131 end
132 end
133
134 def gender_symbol
135 case gender.intern
136 when :female
137 "♀"
138 when :male
139 "♂"
140 when :genderless
141 ""
142 end
143 end
144
145 private
146
147 def set_uuid
148 self.uuid = SecureRandom.uuid
149 end
150
151 def uuid_is_constant
152 errors.add(:uuid, "can't be changed") if self.uuid_changed?
153 end
154
155 def current_is_cached
156 if self.revisions.empty?
157 unless self.current_id.nil?
158 errors.add(:current, "must be null when there are no revisions")
159 end
160 else
161 unless self.current_id = self.revisions.last.id
162 errors.add(:current, "is not up-to-date")
163 end
164 end
165 end
166 end
167end
diff --git a/app/models/pokeviewer/revision.rb b/app/models/pokeviewer/revision.rb deleted file mode 100644 index 05d2838..0000000 --- a/app/models/pokeviewer/revision.rb +++ /dev/null
@@ -1,496 +0,0 @@
1require 'active_record/diff'
2
3module Pokeviewer
4 class Revision < ApplicationRecord
5 include ActiveRecord::Diff
6
7 diff :species_id, :nickname, :level, :hp, :attack, :defense,
8 :special_attack, :special_defense, :speed, :coolness, :beauty, :cuteness,
9 :smartness, :toughness, :sheen, :item_id, :move_1_id, :move_2_id,
10 :move_3_id, :move_4_id, :move_1_pp_bonuses, :move_2_pp_bonuses,
11 :move_3_pp_bonuses, :move_4_pp_bonuses, :cool_ribbons, :beauty_ribbons,
12 :cute_ribbons, :smart_ribbons, :tough_ribbons, :champion_ribbon,
13 :winning_ribbon, :victory_ribbon, :artist_ribbon, :effort_ribbon,
14 :marine_ribbon, :land_ribbon, :sky_ribbon, :country_ribbon,
15 :national_ribbon, :earth_ribbon, :world_ribbon
16
17 belongs_to :pokemon
18 acts_as_sequenced scope: :pokemon_id
19
20 after_create :cache_pokemon_current
21
22 belongs_to :species
23
24 validates :nickname, presence: true
25
26 validates :experience, presence: true,
27 numericality: { greater_than_or_equal_to: 1, only_integer: true }
28
29 validates :level, presence: true,
30 numericality: { greater_than_or_equal_to: 1, only_integer: true }
31
32 validates :hp, presence: true,
33 numericality: { greater_than_or_equal_to: 1, only_integer: true }
34
35 validates :attack, presence: true,
36 numericality: { greater_than_or_equal_to: 1, only_integer: true }
37
38 validates :defense, presence: true,
39 numericality: { greater_than_or_equal_to: 1, only_integer: true }
40
41 validates :special_attack, presence: true,
42 numericality: { greater_than_or_equal_to: 1, only_integer: true }
43
44 validates :special_defense, presence: true,
45 numericality: { greater_than_or_equal_to: 1, only_integer: true }
46
47 validates :speed, presence: true,
48 numericality: { greater_than_or_equal_to: 1, only_integer: true }
49
50 validates :coolness, presence: true,
51 numericality: {
52 greater_than_or_equal_to: 0,
53 less_than_or_equal_to: 10,
54 only_integer: true }
55
56 validates :beauty, presence: true,
57 numericality: {
58 greater_than_or_equal_to: 0,
59 less_than_or_equal_to: 10,
60 only_integer: true }
61
62 validates :cuteness, presence: true,
63 numericality: {
64 greater_than_or_equal_to: 0,
65 less_than_or_equal_to: 10,
66 only_integer: true }
67
68 validates :smartness, presence: true,
69 numericality: {
70 greater_than_or_equal_to: 0,
71 less_than_or_equal_to: 10,
72 only_integer: true }
73
74 validates :toughness, presence: true,
75 numericality: {
76 greater_than_or_equal_to: 0,
77 less_than_or_equal_to: 10,
78 only_integer: true }
79
80 validates :sheen, presence: true,
81 numericality: {
82 greater_than_or_equal_to: 0,
83 less_than_or_equal_to: 10,
84 only_integer: true }
85
86 belongs_to :item, optional: true
87
88 belongs_to :move_1, class_name: "Move"
89 belongs_to :move_2, class_name: "Move", optional: true
90 belongs_to :move_3, class_name: "Move", optional: true
91 belongs_to :move_4, class_name: "Move", optional: true
92
93 validates :move_1_pp_bonuses, presence: true,
94 numericality: {
95 greater_than_or_equal_to: 0,
96 less_than_or_equal_to: 3,
97 only_integer: true}
98
99 validates :move_2_pp_bonuses, presence: true,
100 numericality: {
101 greater_than_or_equal_to: 0,
102 less_than_or_equal_to: 3,
103 only_integer: true}
104
105 validates :move_3_pp_bonuses, presence: true,
106 numericality: {
107 greater_than_or_equal_to: 0,
108 less_than_or_equal_to: 3,
109 only_integer: true}
110
111 validates :move_4_pp_bonuses, presence: true,
112 numericality: {
113 greater_than_or_equal_to: 0,
114 less_than_or_equal_to: 3,
115 only_integer: true}
116
117 validates :cool_ribbons, presence: true,
118 numericality: {
119 greater_than_or_equal_to: 0,
120 less_than_or_equal_to: 4,
121 only_integer: true}
122
123 validates :beauty_ribbons, presence: true,
124 numericality: {
125 greater_than_or_equal_to: 0,
126 less_than_or_equal_to: 4,
127 only_integer: true}
128
129 validates :cute_ribbons, presence: true,
130 numericality: {
131 greater_than_or_equal_to: 0,
132 less_than_or_equal_to: 4,
133 only_integer: true}
134
135 validates :smart_ribbons, presence: true,
136 numericality: {
137 greater_than_or_equal_to: 0,
138 less_than_or_equal_to: 4,
139 only_integer: true}
140
141 validates :tough_ribbons, presence: true,
142 numericality: {
143 greater_than_or_equal_to: 0,
144 less_than_or_equal_to: 4,
145 only_integer: true}
146
147 def icon_path
148 form = ""
149 if species_id == 201
150 # Handle Unown form
151 form = "-#{pokemon.unown_letter}"
152 elsif species_id == 386
153 # Handle Deoxys forms
154 if pokemon.trainer.firered?
155 form = "-attack"
156 elsif pokemon.trainer.leafgreen?
157 form = "-defense"
158 elsif pokemon.trainer.emerald?
159 form = "-speed"
160 end
161 end
162
163 "pokeviewer/icons/#{species_id}#{form}.png"
164 end
165
166 def sprite_path
167 shininess = "normal"
168 if pokemon.shiny
169 shininess = "shiny"
170 end
171
172 game = "ruby-sapphire"
173 unless pokemon.trainer.nil?
174 if (pokemon.trainer.firered? or pokemon.trainer.leafgreen?) and (species_id <= 151 or species_id == 216 or species_id == 386)
175 game = "firered-leafgreen"
176 elsif pokemon.trainer.emerald?
177 game = "emerald"
178 end
179 end
180
181 form = ""
182 if species_id == 201
183 # Handle Unown forms
184 form = "-#{pokemon.unown_letter}"
185 elsif species_id == 386
186 # Handle Deoxys forms
187 if pokemon.trainer.firered?
188 form = "-attack"
189 elsif pokemon.trainer.leafgreen?
190 form = "-defense"
191 elsif pokemon.trainer.emerald?
192 form = "-speed"
193 end
194 end
195
196 if game == "emerald"
197 "pokeviewer/sprites/emerald/#{shininess}/#{species_id}#{form}.gif"
198 else
199 "pokeviewer/sprites/#{game}/#{shininess}/#{species_id}#{form}.png"
200 end
201 end
202
203 def ability
204 if pokemon.second_ability
205 species.ability_2
206 else
207 species.ability_1
208 end
209 end
210
211 def move_1_pp
212 move_1.pp * (5 + move_1_pp_bonuses) / 5
213 end
214
215 def move_2_pp
216 move_2.pp * (5 + move_2_pp_bonuses) / 5
217 end
218
219 def move_3_pp
220 move_3.pp * (5 + move_3_pp_bonuses) / 5
221 end
222
223 def move_4_pp
224 move_4.pp * (5 + move_4_pp_bonuses) / 5
225 end
226
227 def ribbons
228 result = []
229
230 if cool_ribbons >= 1
231 result << {
232 filename: "cool-ribbon.png",
233 name: "Cool Ribbon",
234 description: "Cool Contest Normal Rank Winner!"
235 }
236 end
237
238 if cool_ribbons >= 2
239 result << {
240 filename: "cool-ribbon-super.png",
241 name: "Cool Ribbon Super",
242 description: "Cool Contest Super Rank Winner!"
243 }
244 end
245
246 if cool_ribbons >= 3
247 result << {
248 filename: "cool-ribbon-hyper.png",
249 name: "Cool Ribbon Hyper",
250 description: "Cool Contest Hyper Rank Winner!"
251 }
252 end
253
254 if cool_ribbons == 4
255 result << {
256 filename: "cool-ribbon-master.png",
257 name: "Cool Ribbon Master",
258 description: "Cool Contest Master Rank Winner!"
259 }
260 end
261
262 if beauty_ribbons >= 1
263 result << {
264 filename: "beauty-ribbon.png",
265 name: "Beauty Ribbon",
266 description: "Beauty Contest Normal Rank Winner!"
267 }
268 end
269
270 if beauty_ribbons >= 2
271 result << {
272 filename: "beauty-ribbon-super.png",
273 name: "Beauty Ribbon Super",
274 description: "Beauty Contest Super Rank Winner!"
275 }
276 end
277
278 if beauty_ribbons >= 3
279 result << {
280 filename: "beauty-ribbon-hyper.png",
281 name: "Beauty Ribbon Hyper",
282 description: "Beauty Contest Hyper Rank Winner!"
283 }
284 end
285
286 if beauty_ribbons == 4
287 result << {
288 filename: "beauty-ribbon-master.png",
289 name: "Beauty Ribbon Master",
290 description: "Beauty Contest Master Rank Winner!"
291 }
292 end
293
294 if cute_ribbons >= 1
295 result << {
296 filename: "cute-ribbon.png",
297 name: "Cute Ribbon",
298 description: "Cute Contest Normal Rank Winner!"
299 }
300 end
301
302 if cute_ribbons >= 2
303 result << {
304 filename: "cute-ribbon-super.png",
305 name: "Cute Ribbon Super",
306 description: "Cute Contest Super Rank Winner!"
307 }
308 end
309
310 if cute_ribbons >= 3
311 result << {
312 filename: "cute-ribbon-hyper.png",
313 name: "Cute Ribbon Hyper",
314 description: "Cute Contest Hyper Rank Winner!"
315 }
316 end
317
318 if cute_ribbons == 4
319 result << {
320 filename: "cute-ribbon-master.png",
321 name: "Cute Ribbon Master",
322 description: "Cute Contest Master Rank Winner!"
323 }
324 end
325
326 if smart_ribbons >= 1
327 result << {
328 filename: "smart-ribbon.png",
329 name: "Smart Ribbon",
330 description: "Smart Contest Normal Rank Winner!"
331 }
332 end
333
334 if smart_ribbons >= 2
335 result << {
336 filename: "smart-ribbon-super.png",
337 name: "Smart Ribbon Super",
338 description: "Smart Contest Super Rank Winner!"
339 }
340 end
341
342 if smart_ribbons >= 3
343 result << {
344 filename: "smart-ribbon-hyper.png",
345 name: "Smart Ribbon Hyper",
346 description: "Smart Contest Hyper Rank Winner!"
347 }
348 end
349
350 if smart_ribbons == 4
351 result << {
352 filename: "smart-ribbon-master.png",
353 name: "Smart Ribbon Master",
354 description: "Smart Contest Master Rank Winner!"
355 }
356 end
357
358 if tough_ribbons >= 1
359 result << {
360 filename: "tough-ribbon.png",
361 name: "Tough Ribbon",
362 description: "Tough Contest Normal Rank Winner!"
363 }
364 end
365
366 if tough_ribbons >= 2
367 result << {
368 filename: "tough-ribbon-super.png",
369 name: "Tough Ribbon Super",
370 description: "Tough Contest Super Rank Winner!"
371 }
372 end
373
374 if tough_ribbons >= 3
375 result << {
376 filename: "tough-ribbon-hyper.png",
377 name: "Tough Ribbon Hyper",
378 description: "Tough Contest Hyper Rank Winner!"
379 }
380 end
381
382 if tough_ribbons == 4
383 result << {
384 filename: "tough-ribbon-master.png",
385 name: "Tough Ribbon Master",
386 description: "Tough Contest Master Rank Winner!"
387 }
388 end
389
390 if champion_ribbon
391 result << {
392 filename: "champion-ribbon.png",
393 name: "Champion Ribbon",
394 description: "Champion-beating, Hall of Fame Member Ribbon"
395 }
396 end
397
398 if winning_ribbon
399 result << {
400 filename: "winning-ribbon.png",
401 name: "Winning Ribbon",
402 description: "Ribbon for clearing LV50 at the Battle Tower."
403 }
404 end
405
406 if victory_ribbon
407 result << {
408 filename: "victory-ribbon.png",
409 name: "Victory Ribbon",
410 description: "Won for clearing LV100 at the Battle Tower."
411 }
412 end
413
414 if artist_ribbon
415 result << {
416 filename: "artist-ribbon.png",
417 name: "Artist Ribbon",
418 description: "Ribbon for being chosen as a super sketch model."
419 }
420 end
421
422 if effort_ribbon
423 result << {
424 filename: "effort-ribbon.png",
425 name: "Effort Ribbon",
426 description: "Ribbon awarded for being a hard worker."
427 }
428 end
429
430 if marine_ribbon
431 result << {
432 filename: "marine-ribbon.png",
433 name: "Marine Ribbon",
434 description: pokemon.gift_ribbon_description(:marine_ribbon)
435 }
436 end
437
438 if land_ribbon
439 result << {
440 filename: "land-ribbon.png",
441 name: "Land Ribbon",
442 description: pokemon.gift_ribbon_description(:land_ribbon)
443 }
444 end
445
446 if sky_ribbon
447 result << {
448 filename: "sky-ribbon.png",
449 name: "Sky Ribbon",
450 description: pokemon.gift_ribbon_description(:sky_ribbon)
451 }
452 end
453
454 if country_ribbon
455 result << {
456 filename: "country-ribbon.png",
457 name: "Country Ribbon",
458 description: pokemon.gift_ribbon_description(:country_ribbon)
459 }
460 end
461
462 if national_ribbon
463 result << {
464 filename: "national-ribbon.png",
465 name: "National Ribbon",
466 description: pokemon.gift_ribbon_description(:national_ribbon)
467 }
468 end
469
470 if earth_ribbon
471 result << {
472 filename: "earth-ribbon.png",
473 name: "Earth Ribbon",
474 description: pokemon.gift_ribbon_description(:earth_ribbon)
475 }
476 end
477
478 if world_ribbon
479 result << {
480 filename: "world-ribbon.png",
481 name: "World Ribbon",
482 description: pokemon.gift_ribbon_description(:world_ribbon)
483 }
484 end
485
486 result
487 end
488
489 private
490
491 def cache_pokemon_current
492 self.pokemon.current_id = self.id
493 self.pokemon.save!
494 end
495 end
496end
diff --git a/app/models/pokeviewer/species.rb b/app/models/pokeviewer/species.rb deleted file mode 100644 index 400d679..0000000 --- a/app/models/pokeviewer/species.rb +++ /dev/null
@@ -1,26 +0,0 @@
1module Pokeviewer
2 class Species < ApplicationRecord
3 extend Enumerize
4
5 has_many :revisions, dependent: :restrict_with_exception
6
7 has_many :pokedex_entries, dependent: :destroy
8
9 validates :name, presence: true, uniqueness: true
10
11 validates :type_1, presence: true
12
13 enumerize :type_1, in: Move::TYPES
14 enumerize :type_2, in: Move::TYPES
15
16 belongs_to :ability_1, class_name: "Ability"
17 belongs_to :ability_2, class_name: "Ability", optional: true
18
19 def current_revisions
20 revisions.
21 where("pokeviewer_pokemon.current_id = pokeviewer_revisions.id").
22 includes(:pokemon).
23 references(:pokemon)
24 end
25 end
26end
diff --git a/app/models/pokeviewer/trainer.rb b/app/models/pokeviewer/trainer.rb deleted file mode 100644 index 950dac0..0000000 --- a/app/models/pokeviewer/trainer.rb +++ /dev/null
@@ -1,95 +0,0 @@
1module Pokeviewer
2 class Trainer < ApplicationRecord
3 extend Enumerize
4
5 has_many :pokemon, dependent: :nullify
6
7 has_many :pokedex_entries, dependent: :destroy
8
9 validates :number, presence: true,
10 numericality: { greater_than_or_equal_to: 0, only_integer: true }
11
12 validates :name, presence: true, uniqueness: {
13 scope: :number,
14 message: "and number should be pairwise unique" }
15
16 validates :game, presence: true
17 enumerize :game, in: [:ruby, :sapphire, :firered, :leafgreen, :emerald],
18 predicates: true
19
20 belongs_to :marine_ribbon, class_name: "GiftRibbon", optional: true
21 belongs_to :land_ribbon, class_name: "GiftRibbon", optional: true
22 belongs_to :sky_ribbon, class_name: "GiftRibbon", optional: true
23 belongs_to :country_ribbon, class_name: "GiftRibbon", optional: true
24 belongs_to :national_ribbon, class_name: "GiftRibbon", optional: true
25 belongs_to :earth_ribbon, class_name: "GiftRibbon", optional: true
26 belongs_to :world_ribbon, class_name: "GiftRibbon", optional: true
27
28 validates :box_1_name, presence: true
29 validates :box_2_name, presence: true
30 validates :box_3_name, presence: true
31 validates :box_4_name, presence: true
32 validates :box_5_name, presence: true
33 validates :box_6_name, presence: true
34 validates :box_7_name, presence: true
35 validates :box_8_name, presence: true
36 validates :box_9_name, presence: true
37 validates :box_10_name, presence: true
38 validates :box_11_name, presence: true
39 validates :box_12_name, presence: true
40 validates :box_13_name, presence: true
41 validates :box_14_name, presence: true
42
43 def party
44 pokemon.party.includes(current: [:species])
45 end
46
47 def box(n)
48 pokemon.box(n).includes(current: [:species])
49 end
50
51 def box_name(n)
52 if n > 0 and n <= 14
53 send "box_#{n}_name".intern
54 else
55 nil
56 end
57 end
58
59 def box_contents(n)
60 pokes = box(n).to_a
61
62 result = []
63 (0..29).each do |i|
64 if pokes.empty? or (pokes.first.slot == i)
65 result << pokes.shift
66 else
67 result << nil
68 end
69 end
70
71 result
72 end
73
74 def boxes
75 (1..14).map { |n| {
76 name: box_name(n),
77 pokemon: box_contents(n)
78 }}
79 end
80
81 def display_number
82 number.to_s.rjust(5, '0')
83 end
84
85 def gift_ribbon_description(ribbon)
86 gift_ribbon = send ribbon
87
88 if gift_ribbon.nil?
89 ""
90 else
91 gift_ribbon.description
92 end
93 end
94 end
95end
diff --git a/app/models/revision.rb b/app/models/revision.rb new file mode 100644 index 0000000..477a042 --- /dev/null +++ b/app/models/revision.rb
@@ -0,0 +1,494 @@
1require 'active_record/diff'
2
3class Revision < ApplicationRecord
4 include ActiveRecord::Diff
5
6 diff :species_id, :nickname, :level, :hp, :attack, :defense,
7 :special_attack, :special_defense, :speed, :coolness, :beauty, :cuteness,
8 :smartness, :toughness, :sheen, :item_id, :move_1_id, :move_2_id,
9 :move_3_id, :move_4_id, :move_1_pp_bonuses, :move_2_pp_bonuses,
10 :move_3_pp_bonuses, :move_4_pp_bonuses, :cool_ribbons, :beauty_ribbons,
11 :cute_ribbons, :smart_ribbons, :tough_ribbons, :champion_ribbon,
12 :winning_ribbon, :victory_ribbon, :artist_ribbon, :effort_ribbon,
13 :marine_ribbon, :land_ribbon, :sky_ribbon, :country_ribbon,
14 :national_ribbon, :earth_ribbon, :world_ribbon
15
16 belongs_to :pokemon
17 acts_as_sequenced scope: :pokemon_id
18
19 after_create :cache_pokemon_current
20
21 belongs_to :species
22
23 validates :nickname, presence: true
24
25 validates :experience, presence: true,
26 numericality: { greater_than_or_equal_to: 1, only_integer: true }
27
28 validates :level, presence: true,
29 numericality: { greater_than_or_equal_to: 1, only_integer: true }
30
31 validates :hp, presence: true,
32 numericality: { greater_than_or_equal_to: 1, only_integer: true }
33
34 validates :attack, presence: true,
35 numericality: { greater_than_or_equal_to: 1, only_integer: true }
36
37 validates :defense, presence: true,
38 numericality: { greater_than_or_equal_to: 1, only_integer: true }
39
40 validates :special_attack, presence: true,
41 numericality: { greater_than_or_equal_to: 1, only_integer: true }
42
43 validates :special_defense, presence: true,
44 numericality: { greater_than_or_equal_to: 1, only_integer: true }
45
46 validates :speed, presence: true,
47 numericality: { greater_than_or_equal_to: 1, only_integer: true }
48
49 validates :coolness, presence: true,
50 numericality: {
51 greater_than_or_equal_to: 0,
52 less_than_or_equal_to: 10,
53 only_integer: true }
54
55 validates :beauty, presence: true,
56 numericality: {
57 greater_than_or_equal_to: 0,
58 less_than_or_equal_to: 10,
59 only_integer: true }
60
61 validates :cuteness, presence: true,
62 numericality: {
63 greater_than_or_equal_to: 0,
64 less_than_or_equal_to: 10,
65 only_integer: true }
66
67 validates :smartness, presence: true,
68 numericality: {
69 greater_than_or_equal_to: 0,
70 less_than_or_equal_to: 10,
71 only_integer: true }
72
73 validates :toughness, presence: true,
74 numericality: {
75 greater_than_or_equal_to: 0,
76 less_than_or_equal_to: 10,
77 only_integer: true }
78
79 validates :sheen, presence: true,
80 numericality: {
81 greater_than_or_equal_to: 0,
82 less_than_or_equal_to: 10,
83 only_integer: true }
84
85 belongs_to :item, optional: true
86
87 belongs_to :move_1, class_name: "Move"
88 belongs_to :move_2, class_name: "Move", optional: true
89 belongs_to :move_3, class_name: "Move", optional: true
90 belongs_to :move_4, class_name: "Move", optional: true
91
92 validates :move_1_pp_bonuses, presence: true,
93 numericality: {
94 greater_than_or_equal_to: 0,
95 less_than_or_equal_to: 3,
96 only_integer: true}
97
98 validates :move_2_pp_bonuses, presence: true,
99 numericality: {
100 greater_than_or_equal_to: 0,
101 less_than_or_equal_to: 3,
102 only_integer: true}
103
104 validates :move_3_pp_bonuses, presence: true,
105 numericality: {
106 greater_than_or_equal_to: 0,
107 less_than_or_equal_to: 3,
108 only_integer: true}
109
110 validates :move_4_pp_bonuses, presence: true,
111 numericality: {
112 greater_than_or_equal_to: 0,
113 less_than_or_equal_to: 3,
114 only_integer: true}
115
116 validates :cool_ribbons, presence: true,
117 numericality: {
118 greater_than_or_equal_to: 0,
119 less_than_or_equal_to: 4,
120 only_integer: true}
121
122 validates :beauty_ribbons, presence: true,
123 numericality: {
124 greater_than_or_equal_to: 0,
125 less_than_or_equal_to: 4,
126 only_integer: true}
127
128 validates :cute_ribbons, presence: true,
129 numericality: {
130 greater_than_or_equal_to: 0,
131 less_than_or_equal_to: 4,
132 only_integer: true}
133
134 validates :smart_ribbons, presence: true,
135 numericality: {
136 greater_than_or_equal_to: 0,
137 less_than_or_equal_to: 4,
138 only_integer: true}
139
140 validates :tough_ribbons, presence: true,
141 numericality: {
142 greater_than_or_equal_to: 0,
143 less_than_or_equal_to: 4,
144 only_integer: true}
145
146 def icon_path
147 form = ""
148 if species_id == 201
149 # Handle Unown form
150 form = "-#{pokemon.unown_letter}"
151 elsif species_id == 386
152 # Handle Deoxys forms
153 if pokemon.trainer.firered?
154 form = "-attack"
155 elsif pokemon.trainer.leafgreen?
156 form = "-defense"
157 elsif pokemon.trainer.emerald?
158 form = "-speed"
159 end
160 end
161
162 "icons/#{species_id}#{form}.png"
163 end
164
165 def sprite_path
166 shininess = "normal"
167 if pokemon.shiny
168 shininess = "shiny"
169 end
170
171 game = "ruby-sapphire"
172 unless pokemon.trainer.nil?
173 if (pokemon.trainer.firered? or pokemon.trainer.leafgreen?) and (species_id <= 151 or species_id == 216 or species_id == 386)
174 game = "firered-leafgreen"
175 elsif pokemon.trainer.emerald?
176 game = "emerald"
177 end
178 end
179
180 form = ""
181 if species_id == 201
182 # Handle Unown forms
183 form = "-#{pokemon.unown_letter}"
184 elsif species_id == 386
185 # Handle Deoxys forms
186 if pokemon.trainer.firered?
187 form = "-attack"
188 elsif pokemon.trainer.leafgreen?
189 form = "-defense"
190 elsif pokemon.trainer.emerald?
191 form = "-speed"
192 end
193 end
194
195 if game == "emerald"
196 "sprites/emerald/#{shininess}/#{species_id}#{form}.gif"
197 else
198 "sprites/#{game}/#{shininess}/#{species_id}#{form}.png"
199 end
200 end
201
202 def ability
203 if pokemon.second_ability
204 species.ability_2
205 else
206 species.ability_1
207 end
208 end
209
210 def move_1_pp
211 move_1.pp * (5 + move_1_pp_bonuses) / 5
212 end
213
214 def move_2_pp
215 move_2.pp * (5 + move_2_pp_bonuses) / 5
216 end
217
218 def move_3_pp
219 move_3.pp * (5 + move_3_pp_bonuses) / 5
220 end
221
222 def move_4_pp
223 move_4.pp * (5 + move_4_pp_bonuses) / 5
224 end
225
226 def ribbons
227 result = []
228
229 if cool_ribbons >= 1
230 result << {
231 filename: "cool-ribbon.png",
232 name: "Cool Ribbon",
233 description: "Cool Contest Normal Rank Winner!"
234 }
235 end
236
237 if cool_ribbons >= 2
238 result << {
239 filename: "cool-ribbon-super.png",
240 name: "Cool Ribbon Super",
241 description: "Cool Contest Super Rank Winner!"
242 }
243 end
244
245 if cool_ribbons >= 3
246 result << {
247 filename: "cool-ribbon-hyper.png",
248 name: "Cool Ribbon Hyper",
249 description: "Cool Contest Hyper Rank Winner!"
250 }
251 end
252
253 if cool_ribbons == 4
254 result << {
255 filename: "cool-ribbon-master.png",
256 name: "Cool Ribbon Master",
257 description: "Cool Contest Master Rank Winner!"
258 }
259 end
260
261 if beauty_ribbons >= 1
262 result << {
263 filename: "beauty-ribbon.png",
264 name: "Beauty Ribbon",
265 description: "Beauty Contest Normal Rank Winner!"
266 }
267 end
268
269 if beauty_ribbons >= 2
270 result << {
271 filename: "beauty-ribbon-super.png",
272 name: "Beauty Ribbon Super",
273 description: "Beauty Contest Super Rank Winner!"
274 }
275 end
276
277 if beauty_ribbons >= 3
278 result << {
279 filename: "beauty-ribbon-hyper.png",
280 name: "Beauty Ribbon Hyper",
281 description: "Beauty Contest Hyper Rank Winner!"
282 }
283 end
284
285 if beauty_ribbons == 4
286 result << {
287 filename: "beauty-ribbon-master.png",
288 name: "Beauty Ribbon Master",
289 description: "Beauty Contest Master Rank Winner!"
290 }
291 end
292
293 if cute_ribbons >= 1
294 result << {
295 filename: "cute-ribbon.png",
296 name: "Cute Ribbon",
297 description: "Cute Contest Normal Rank Winner!"
298 }
299 end
300
301 if cute_ribbons >= 2
302 result << {
303 filename: "cute-ribbon-super.png",
304 name: "Cute Ribbon Super",
305 description: "Cute Contest Super Rank Winner!"
306 }
307 end
308
309 if cute_ribbons >= 3
310 result << {
311 filename: "cute-ribbon-hyper.png",
312 name: "Cute Ribbon Hyper",
313 description: "Cute Contest Hyper Rank Winner!"
314 }
315 end
316
317 if cute_ribbons == 4
318 result << {
319 filename: "cute-ribbon-master.png",
320 name: "Cute Ribbon Master",
321 description: "Cute Contest Master Rank Winner!"
322 }
323 end
324
325 if smart_ribbons >= 1
326 result << {
327 filename: "smart-ribbon.png",
328 name: "Smart Ribbon",
329 description: "Smart Contest Normal Rank Winner!"
330 }
331 end
332
333 if smart_ribbons >= 2
334 result << {
335 filename: "smart-ribbon-super.png",
336 name: "Smart Ribbon Super",
337 description: "Smart Contest Super Rank Winner!"
338 }
339 end
340
341 if smart_ribbons >= 3
342 result << {
343 filename: "smart-ribbon-hyper.png",
344 name: "Smart Ribbon Hyper",
345 description: "Smart Contest Hyper Rank Winner!"
346 }
347 end
348
349 if smart_ribbons == 4
350 result << {
351 filename: "smart-ribbon-master.png",
352 name: "Smart Ribbon Master",
353 description: "Smart Contest Master Rank Winner!"
354 }
355 end
356
357 if tough_ribbons >= 1
358 result << {
359 filename: "tough-ribbon.png",
360 name: "Tough Ribbon",
361 description: "Tough Contest Normal Rank Winner!"
362 }
363 end
364
365 if tough_ribbons >= 2
366 result << {
367 filename: "tough-ribbon-super.png",
368 name: "Tough Ribbon Super",
369 description: "Tough Contest Super Rank Winner!"
370 }
371 end
372
373 if tough_ribbons >= 3
374 result << {
375 filename: "tough-ribbon-hyper.png",
376 name: "Tough Ribbon Hyper",
377 description: "Tough Contest Hyper Rank Winner!"
378 }
379 end
380
381 if tough_ribbons == 4
382 result << {
383 filename: "tough-ribbon-master.png",
384 name: "Tough Ribbon Master",
385 description: "Tough Contest Master Rank Winner!"
386 }
387 end
388
389 if champion_ribbon
390 result << {
391 filename: "champion-ribbon.png",
392 name: "Champion Ribbon",
393 description: "Champion-beating, Hall of Fame Member Ribbon"
394 }
395 end
396
397 if winning_ribbon
398 result << {
399 filename: "winning-ribbon.png",
400 name: "Winning Ribbon",
401 description: "Ribbon for clearing LV50 at the Battle Tower."
402 }
403 end
404
405 if victory_ribbon
406 result << {
407 filename: "victory-ribbon.png",
408 name: "Victory Ribbon",
409 description: "Won for clearing LV100 at the Battle Tower."
410 }
411 end
412
413 if artist_ribbon
414 result << {
415 filename: "artist-ribbon.png",
416 name: "Artist Ribbon",
417 description: "Ribbon for being chosen as a super sketch model."
418 }
419 end
420
421 if effort_ribbon
422 result << {
423 filename: "effort-ribbon.png",
424 name: "Effort Ribbon",
425 description: "Ribbon awarded for being a hard worker."
426 }
427 end
428
429 if marine_ribbon
430 result << {
431 filename: "marine-ribbon.png",
432 name: "Marine Ribbon",
433 description: pokemon.gift_ribbon_description(:marine_ribbon)
434 }
435 end
436
437 if land_ribbon
438 result << {
439 filename: "land-ribbon.png",
440 name: "Land Ribbon",
441 description: pokemon.gift_ribbon_description(:land_ribbon)
442 }
443 end
444
445 if sky_ribbon
446 result << {
447 filename: "sky-ribbon.png",
448 name: "Sky Ribbon",
449 description: pokemon.gift_ribbon_description(:sky_ribbon)
450 }
451 end
452
453 if country_ribbon
454 result << {
455 filename: "country-ribbon.png",
456 name: "Country Ribbon",
457 description: pokemon.gift_ribbon_description(:country_ribbon)
458 }
459 end
460
461 if national_ribbon
462 result << {
463 filename: "national-ribbon.png",
464 name: "National Ribbon",
465 description: pokemon.gift_ribbon_description(:national_ribbon)
466 }
467 end
468
469 if earth_ribbon
470 result << {
471 filename: "earth-ribbon.png",
472 name: "Earth Ribbon",
473 description: pokemon.gift_ribbon_description(:earth_ribbon)
474 }
475 end
476
477 if world_ribbon
478 result << {
479 filename: "world-ribbon.png",
480 name: "World Ribbon",
481 description: pokemon.gift_ribbon_description(:world_ribbon)
482 }
483 end
484
485 result
486 end
487
488 private
489
490 def cache_pokemon_current
491 self.pokemon.current_id = self.id
492 self.pokemon.save!
493 end
494end
diff --git a/app/models/species.rb b/app/models/species.rb new file mode 100644 index 0000000..0623f11 --- /dev/null +++ b/app/models/species.rb
@@ -0,0 +1,24 @@
1class Species < ApplicationRecord
2 extend Enumerize
3
4 has_many :revisions, dependent: :restrict_with_exception
5
6 has_many :pokedex_entries, dependent: :destroy
7
8 validates :name, presence: true, uniqueness: true
9
10 validates :type_1, presence: true
11
12 enumerize :type_1, in: Move::TYPES
13 enumerize :type_2, in: Move::TYPES
14
15 belongs_to :ability_1, class_name: "Ability"
16 belongs_to :ability_2, class_name: "Ability", optional: true
17
18 def current_revisions
19 revisions.
20 where("pokemon.current_id = revisions.id").
21 includes(:pokemon).
22 references(:pokemon)
23 end
24end
diff --git a/app/models/trainer.rb b/app/models/trainer.rb new file mode 100644 index 0000000..930dbaf --- /dev/null +++ b/app/models/trainer.rb
@@ -0,0 +1,93 @@
1class Trainer < ApplicationRecord
2 extend Enumerize
3
4 has_many :pokemon, dependent: :nullify
5
6 has_many :pokedex_entries, dependent: :destroy
7
8 validates :number, presence: true,
9 numericality: { greater_than_or_equal_to: 0, only_integer: true }
10
11 validates :name, presence: true, uniqueness: {
12 scope: :number,
13 message: "and number should be pairwise unique" }
14
15 validates :game, presence: true
16 enumerize :game, in: [:ruby, :sapphire, :firered, :leafgreen, :emerald],
17 predicates: true
18
19 belongs_to :marine_ribbon, class_name: "GiftRibbon", optional: true
20 belongs_to :land_ribbon, class_name: "GiftRibbon", optional: true
21 belongs_to :sky_ribbon, class_name: "GiftRibbon", optional: true
22 belongs_to :country_ribbon, class_name: "GiftRibbon", optional: true
23 belongs_to :national_ribbon, class_name: "GiftRibbon", optional: true
24 belongs_to :earth_ribbon, class_name: "GiftRibbon", optional: true
25 belongs_to :world_ribbon, class_name: "GiftRibbon", optional: true
26
27 validates :box_1_name, presence: true
28 validates :box_2_name, presence: true
29 validates :box_3_name, presence: true
30 validates :box_4_name, presence: true
31 validates :box_5_name, presence: true
32 validates :box_6_name, presence: true
33 validates :box_7_name, presence: true
34 validates :box_8_name, presence: true
35 validates :box_9_name, presence: true
36 validates :box_10_name, presence: true
37 validates :box_11_name, presence: true
38 validates :box_12_name, presence: true
39 validates :box_13_name, presence: true
40 validates :box_14_name, presence: true
41
42 def party
43 pokemon.party.includes(current: [:species])
44 end
45
46 def box(n)
47 pokemon.box(n).includes(current: [:species])
48 end
49
50 def box_name(n)
51 if n > 0 and n <= 14
52 send "box_#{n}_name".intern
53 else
54 nil
55 end
56 end
57
58 def box_contents(n)
59 pokes = box(n).to_a
60
61 result = []
62 (0..29).each do |i|
63 if pokes.empty? or (pokes.first.slot == i)
64 result << pokes.shift
65 else
66 result << nil
67 end
68 end
69
70 result
71 end
72
73 def boxes
74 (1..14).map { |n| {
75 name: box_name(n),
76 pokemon: box_contents(n)
77 }}
78 end
79
80 def display_number
81 number.to_s.rjust(5, '0')
82 end
83
84 def gift_ribbon_description(ribbon)
85 gift_ribbon = send ribbon
86
87 if gift_ribbon.nil?
88 ""
89 else
90 gift_ribbon.description
91 end
92 end
93end