Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Zad4 #141

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open

Zad4 #141

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions lecture_4/homework/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,17 @@ W kontrolerze najemników pracy będzie trochę więcej. Niestaranny kod powoduj

Powodzenia


# Solution

- przeniesienie metody attack z modeli samurai i hussar do klasy bazowej warrior
Metoda miała bardzo podobną treść wiadomości - żeby nie naruszać DRY.

- NullObjecty dla broni i najemnika, tak aby nie było błędów.

- QueryObjecty - w większości do wyszukiwania po id, przy mercenaries jeszcze do
sortowania najemników w zależności od preferencji zakupy - najlepsi/najgorsi

- kontroler mercenaries: akcja index pokazuje dostępnych najemników,
akcja show pokazuje najemników wraz z wojownikami, akcja employ worst zatrudnia
najtańszego najemnika, a employ best najbardziej doświadczonego, employ - losowego
54 changes: 17 additions & 37 deletions lecture_4/homework/app/controllers/mercenaries_controller.rb
Original file line number Diff line number Diff line change
@@ -1,63 +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
if params[:building_id]
Building.find(params[:building_id])
end
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
12 changes: 12 additions & 0 deletions lecture_4/homework/app/models/warrior.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,16 @@ class Warrior < ApplicationRecord

scope :alive, -> { where('death_date IS NULL') }
scope :dead, -> { where('death_date IS NOT NULL') }

def attack
"#{type.demodulize} #{name} attacked with #{weapon_null_check.type.demodulize}"
end

def null_weapon_check
weapon || NullWeapon.new
end

def mercenary_null_check
mercenary || NullMercenary.new
end
end
4 changes: 0 additions & 4 deletions lecture_4/homework/app/models/warriors/hussar.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,5 @@
module Warriors
class Hussar < Warrior
attribute :preferred_weapon_kind, :string, default: :ranged

def attack
"Hussar #{name} charged while yielding #{weapon.type.demodulize}"
end
end
end
4 changes: 0 additions & 4 deletions lecture_4/homework/app/models/warriors/samurai.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,5 @@
module Warriors
class Samurai < Warrior
attribute :preferred_weapon_kind, :string, default: :melee

def attack
"Samurai #{name} attacked with #{weapon.type.demodulize}"
end
end
end
19 changes: 19 additions & 0 deletions lecture_4/homework/app/nulls/null_mercenary.rb
Original file line number Diff line number Diff line change
@@ -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
15 changes: 15 additions & 0 deletions lecture_4/homework/app/nulls/null_weapon.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# frozen_literal_string: true

class NullWeapon
def type
'Oops, no weapon.'
end

def range
nil
end

def damage
nil
end
end
7 changes: 7 additions & 0 deletions lecture_4/homework/app/queries/buildings_query.rb
Original file line number Diff line number Diff line change
@@ -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
7 changes: 7 additions & 0 deletions lecture_4/homework/app/queries/clans_query.rb
Original file line number Diff line number Diff line change
@@ -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
19 changes: 19 additions & 0 deletions lecture_4/homework/app/queries/mercenaries_query.rb
Original file line number Diff line number Diff line change
@@ -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
16 changes: 16 additions & 0 deletions lecture_4/homework/app/queries/warriors_query.rb
Original file line number Diff line number Diff line change
@@ -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
7 changes: 7 additions & 0 deletions lecture_4/homework/app/queries/weapons_query.rb
Original file line number Diff line number Diff line change
@@ -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
42 changes: 42 additions & 0 deletions lecture_4/homework/app/services/mercenary_employer.rb
Original file line number Diff line number Diff line change
@@ -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