diff --git a/lecture_4/homework/app/controllers/mercenaries_controller.rb b/lecture_4/homework/app/controllers/mercenaries_controller.rb index 9fb11193..4cfe2c59 100644 --- a/lecture_4/homework/app/controllers/mercenaries_controller.rb +++ b/lecture_4/homework/app/controllers/mercenaries_controller.rb @@ -1,61 +1,43 @@ # frozen_string_literal: true -# This controller is written badly on purpose. Please refactor this class MercenariesController < ApplicationController def index - render json: Mercenary.where('available_from < ?', Time.now).all + render json: MercenaryQueries.available.all end def show render json: mercenary, include: [:warrior] end + def employ_worst + mercenary = MercenariesQuery.sort_available_price_ascending.first + mercenary_employer.call(mercenary) + render json: mercenary, include: [:warrior], status: 201 + end + def employ_best - mercenary = Mercenary.where('available_from < ?', Time.now).order(price: :asc).first # TODO: what about experience? - clan = find_clan - building = find_building - warrior_class = clan.warriors.select('type, count(type) as warriors_count').group(:type).order('warriors_count ASC').first.class - warrior = warrior_class.create!(name: mercenary.name, clan: clan, building: building, preferred_weapon_kind: mercenary.preferred_weapon_kind, mercenary: mercenary) - create_good_weapon(mercenary) + mercenary = MercenariesQuery.sort_available_exp_descending.first + mercenary_employer.call(mercenary) render json: warrior, include: [:mercenary], status: 201 end def employ - return unless mercenary.available_from < Time.now - clan = find_clan - building = find_building - warrior_class = clan.warriors.select('type, count(type) as warriors_count').group(:type).order('warriors_count ASC').first.class - warrior = warrior_class.create!(name: mercenary.name, clan: clan, building: building, preferred_weapon_kind: mercenary.preferred_weapon_kind, mercenary: mercenary) - create_good_weapon(mercenary) + mercenary = MercenariesQuery.available.sample + mercenary_employer.call(mercenary) render json: warrior, include: [:mercenary], status: 201 end private - def mercenary - @mercenary ||= Mercenary.find(params[:id]) - end - - def find_building - Building.find(params[:building_id]) if params[:building_id] + def mercenary_params + params.permit(:name, :expirience, :price, :clan_id, :building_id, :warrior_id) end - def find_clan - if params[:clan_id] - Clan.find(params[:clan_id]) - else - Clan.order(warriors_count: :desc).first - end + def mercenary_employer + MercenaryEmployer.new(mercenary_params) end - def create_good_weapon(mercenary) - case mercenary.preferred_weapon_kind - when :melee - Weapons::Katana.create!(warrior: mercenary.warrior, range: 2, damage: 25) - when :ranged - Weapons::Musket.create!(warrior: mercenary.warrior, range: 40, damage: 10) - else - # TODO: some default? - end + def mercenary + @mercenary ||= MercenaryQueries.find_by_id(params[:id]) end end diff --git a/lecture_4/homework/app/models/warrior.rb b/lecture_4/homework/app/models/warrior.rb index e1c06a8f..04c12742 100644 --- a/lecture_4/homework/app/models/warrior.rb +++ b/lecture_4/homework/app/models/warrior.rb @@ -22,4 +22,8 @@ def attack def null_weapon_check weapon || NullWeapon.new end + + def mercenary_null_check + mercenary || NullMercenary.new + end end diff --git a/lecture_4/homework/app/nulls/null_mercenary.rb b/lecture_4/homework/app/nulls/null_mercenary.rb new file mode 100644 index 00000000..2610d8cb --- /dev/null +++ b/lecture_4/homework/app/nulls/null_mercenary.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +class NullMercenary + def name + 'Name has not been initialized' + end + + def preffered_weapon_kind + 'melee' + end + + def available_from + nil + end + + def price + nil + end +end diff --git a/lecture_4/homework/app/queries/buildings_query.rb b/lecture_4/homework/app/queries/buildings_query.rb new file mode 100644 index 00000000..24ea7579 --- /dev/null +++ b/lecture_4/homework/app/queries/buildings_query.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +class BuildingsQuery + def self.find_by_id(id = nil, relation: Building) + id.nil? ? relation.first : relation.find(id) + end +end diff --git a/lecture_4/homework/app/queries/clans_query.rb b/lecture_4/homework/app/queries/clans_query.rb new file mode 100644 index 00000000..60e4c213 --- /dev/null +++ b/lecture_4/homework/app/queries/clans_query.rb @@ -0,0 +1,7 @@ +# frozen_literal_string: true + +class ClansQuery + def self.find_by_id(id = nil, relation: Clan) + id.nil? ? relation.order(warriors_count: :desc).first : relation.find(id) + end +end diff --git a/lecture_4/homework/app/queries/mercenaries_query.rb b/lecture_4/homework/app/queries/mercenaries_query.rb new file mode 100644 index 00000000..c32ad7b0 --- /dev/null +++ b/lecture_4/homework/app/queries/mercenaries_query.rb @@ -0,0 +1,19 @@ +# frozen_literal_string: true + +class MercenariesQuery + def self.find_by_id(id = nil, relation: Mercenary) + id.nil? ? relation.first : relation.find(id) + end + + def self.sort_exp_descending(relation: Mercenary) + relation.order(expirience: :desc) + end + + def self.sort_available_exp_descending(relation: available) + relation.order(expirience: :desc) + end + + def self.sort_available_price_ascending(relation: available) + relation.order(price: :asc) + end +end diff --git a/lecture_4/homework/app/queries/warriors_query.rb b/lecture_4/homework/app/queries/warriors_query.rb new file mode 100644 index 00000000..57302e68 --- /dev/null +++ b/lecture_4/homework/app/queries/warriors_query.rb @@ -0,0 +1,16 @@ +# frozen_string_literal :true + +class WarriorsQuery + def self.find_by_id(id = nil, relation: Warrior) + id.nil? ? relation.first : relation.find(id) + end + + def self.belonging_to_clan(clan_id:, relation: Warrior) + relation.where(clan_id: clan_id) + end + + def self.get_class(relation: Warrior) + relation.warriors.select('type, count(type) as warriors_count') + .group(:type).oreder('warriors_count ASC').first.class + end +end diff --git a/lecture_4/homework/app/queries/weapons_query.rb b/lecture_4/homework/app/queries/weapons_query.rb new file mode 100644 index 00000000..59782348 --- /dev/null +++ b/lecture_4/homework/app/queries/weapons_query.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +class WeaponsQuery + def self.find_by_id(id = nil, relation: Weapon) + id.nil? ? relation.first : relation.find(id) + end +end diff --git a/lecture_4/homework/app/services/mercenary_employer.rb b/lecture_4/homework/app/services/mercenary_employer.rb new file mode 100644 index 00000000..4aee584d --- /dev/null +++ b/lecture_4/homework/app/services/mercenary_employer.rb @@ -0,0 +1,42 @@ +# frozen_literal_string: true + +class MercenaryEmployer + def initialize(mercenary_params) + @params = mercenary_params + end + + def self.call(mercenary) + clan = find_clan + building = find_building + warrior_class = WarriorQuery.get_class + warrior_class.create(name: mercenary.name, + clan: clan, + building: building, + preffered_weapon_kind: preffered_weapon_kind, + mercenary: mercenary) + create_good_weapon(mercenary) + end + + private + + attr_reader :params + + def find_building + BuildingsQuery.find_by_id(params[:building_id]) + end + + def find_clan + ClansQuery.find_by_id(params[:clan_id]) + end + + def create_good_weapon(mercenary) + case mercenary.preferred_weapon_kind + when :melee + Weapons::Katana.create!(warrior: mercenary.warrior, range: 2, damage: 25) + when :ranged + Weapons::Musket.create!(warrior: mercenary.warrior, range: 40, damage: 10) + else + NullWeapon.new + end + end +end