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

Zad 4 #140

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

Zad 4 #140

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
2 changes: 2 additions & 0 deletions lecture_4/homework/.rubocop.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
require: rubocop-performance

AllCops:
Exclude:
- bin/**/*
Expand Down
3 changes: 3 additions & 0 deletions lecture_4/homework/Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@ git_source(:github) { |repo| "https://github.com/#{repo}.git" }

ruby '2.6.2'

gem 'awesome_print'
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 5.2.2'
# Use pg as the database for Active Record
gem 'pg'
# Use Puma as the app server
gem 'puma', '~> 3.11'
gem 'rubocop-performance'
gem 'sentry-raven'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
# gem 'jbuilder', '~> 2.5'
# Use Redis adapter to run Action Cable in production
Expand Down
11 changes: 11 additions & 0 deletions lecture_4/homework/Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ GEM
tzinfo (~> 1.1)
arel (9.0.0)
ast (2.4.0)
awesome_print (1.8.0)
bootsnap (1.4.1)
msgpack (~> 1.0)
builder (3.2.3)
Expand All @@ -58,6 +59,8 @@ GEM
concurrent-ruby (1.1.5)
crass (1.0.4)
erubi (1.8.0)
faraday (0.15.4)
multipart-post (>= 1.2, < 3)
ffi (1.10.0)
globalid (0.4.2)
activesupport (>= 4.2.0)
Expand All @@ -82,6 +85,7 @@ GEM
mini_portile2 (2.4.0)
minitest (5.11.3)
msgpack (1.2.9)
multipart-post (2.0.0)
nio4r (2.3.1)
nokogiri (1.10.1)
mini_portile2 (~> 2.4.0)
Expand Down Expand Up @@ -131,8 +135,12 @@ GEM
rainbow (>= 2.2.2, < 4.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 1.6)
rubocop-performance (1.0.0)
rubocop (>= 0.58.0)
ruby-progressbar (1.10.0)
ruby_dep (1.5.0)
sentry-raven (2.9.0)
faraday (>= 0.7.6, < 1.0)
spring (2.0.2)
activesupport (>= 4.2)
spring-watcher-listen (2.0.1)
Expand All @@ -159,13 +167,16 @@ PLATFORMS

DEPENDENCIES
active_model_serializers
awesome_print
bootsnap (>= 1.1.0)
byebug
listen (>= 3.0.5, < 3.2)
pg
puma (~> 3.11)
rails (~> 5.2.2)
rubocop
rubocop-performance
sentry-raven
spring
spring-watcher-listen (~> 2.0.0)
tzinfo-data
Expand Down
9 changes: 9 additions & 0 deletions lecture_4/homework/app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,13 @@

class ApplicationController < ActionController::API
include ErrorsHandler

before_action :set_raven_context

private

def set_raven_context
Raven.user_context(id: session[:current_user_id]) # or anything else in session
Raven.extra_context(params: params.to_unsafe_h, url: request.url)
end
end
18 changes: 9 additions & 9 deletions lecture_4/homework/app/controllers/clans/warriors_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,47 +3,47 @@
module Clans
class WarriorsController < ApplicationController
def show
render json: warrior, include: %i[weapon building]
render json: warrior, include: %i[weapon building mercenary]
end

def index
warriors = clan.warriors
warriors = WarriorsQueries.all_clans_warriors(clan: clan)

if params.key?(:alive)
if params[:alive].to_i == 0
if params[:alive].to_i.zero?
render json: warriors.dead
else
render json: warriors.alive
end
else
render json: warriors
render json: warriors, include: [:mercenary]
end
end

def create
warrior = clan.warriors.create!(warrior_params)
warrior = WarriorsQueries.create_warrior(warrior_params: warrior_params, clan: clan)

render json: warrior.to_json, include: %i[weapon building], status: 201
end

def update
warrior.update!(warrior_params)
WarriorsQueries.update_warrior(warrior: warrior, warrior_params: warrior_params)

render json: warrior, include: %i[weapon building]
end

def destroy
warrior.destroy!
WarriorsQueries.destroy_warrior(warrior: warrior)
end

private

def clan
@clan ||= Clan.find(params[:clan_id])
@clan ||= ClansQueries.find(clan_id: params[:clan_id])
end

def warrior
@warrior ||= clan.warriors.find(params[:id])
@warrior ||= WarriorsQueries.find_warrior(clan: clan, warrior_id: params[:id])
end

def warrior_params
Expand Down
6 changes: 3 additions & 3 deletions lecture_4/homework/app/controllers/clans_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,23 @@

class ClansController < ApplicationController
def index
render json: Clan.all
render json: ClansQueries.all_clans
end

def show
render json: clan, include: [:warriors]
end

def create
clan = Clan.create!(clan_params)
clan = ClansQueries.create_clan(clan_params: clan_params)

render json: clan, include: [:warriors], status: 201
end

private

def clan
@clan ||= Clan.find(params[:id])
@clan ||= ClansQueries.find(clan_id: params[:id])
end

def clan_params
Expand Down
7 changes: 7 additions & 0 deletions lecture_4/homework/app/controllers/errors_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# frozen_string_literal: true

class ErrorsController < ApplicationController
def index
raise Exceptions::SpecificError.new(extra: { date: DateTime.now, another_important_key: 4 })
end
end
56 changes: 20 additions & 36 deletions lecture_4/homework/app/controllers/mercenaries_controller.rb
Original file line number Diff line number Diff line change
@@ -1,63 +1,47 @@
# 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: mercenaries
end

def show
render json: mercenary, include: [:warrior]
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)
render json: warrior, include: [:mercenary], status: 201
mercenary = MercenariesQuery.find_best
render_no_available_mercenary and return unless mercenary

recruit_mercenary(mercenary: mercenary)
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)
render json: warrior, include: [:mercenary], status: 201
render_no_available_mercenary and return unless can_be_hired?

recruit_mercenary(mercenary: mercenary)
end

private

def mercenaries
@mercenaries ||= MercenariesQuery.all_mercenaries
end

def mercenary
@mercenary ||= Mercenary.find(params[:id])
@mercenary ||= MercenariesQuery.mercenary(mercenary_id: params[:id])
end

def find_building
if params[:building_id]
Building.find(params[:building_id])
end
def recruit_mercenary(mercenary:)
MercenaryRecruiter.call(mercenary: mercenary, params: params)
render json: mercenary, include: %i[warrior], status: 201
end

def find_clan
if params[:clan_id]
Clan.find(params[:clan_id])
else
Clan.order(warriors_count: :desc).first
end
def render_no_available_mercenary
render json: { error: NoMercenary.new.employ }
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 can_be_hired?
MercenariesQuery.can_be_hired(mercenary_id: mercenary.id)
end
end
1 change: 1 addition & 0 deletions lecture_4/homework/app/models/mercenary.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ class Mercenary < ApplicationRecord

scope :alive, -> { where('death_date IS NULL') }
scope :dead, -> { where('death_date IS NOT NULL') }
scope :available, -> { where('available_from < ? AND warrior_id IS NULL', Time.now) }
end
4 changes: 4 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,8 @@ class Warrior < ApplicationRecord

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

def mercenary
super || NoMercenary.new.mercenary
end
end
6 changes: 6 additions & 0 deletions lecture_4/homework/app/models/warriors/hussar.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ class Hussar < Warrior
attribute :preferred_weapon_kind, :string, default: :ranged

def attack
weapon && attack_with_gun || NoWeapon.new.attack
end

private

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

def attack
weapon && attack_with_gun || NoWeapon.new.attack
end

private

def attack_with_gun
"Samurai #{name} attacked with #{weapon.type.demodulize}"
end
end
Expand Down
11 changes: 11 additions & 0 deletions lecture_4/homework/app/models/weapons/magic_wand.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# frozen_string_literal: true

module Weapons
class MagicWand < Weapon
attribute :kind, :string, default: :magical

def calculate_damage(distance)
distance < range ? damage * 3 : damage * 0.05
end
end
end
7 changes: 7 additions & 0 deletions lecture_4/homework/app/nulls/no_available_mercenary.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# frozen_string_literal: true

class NoAvailableMercenary
def employ_best
'There is no available mercenary'
end
end
11 changes: 11 additions & 0 deletions lecture_4/homework/app/nulls/no_mercenary.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# frozen_string_literal: true

class NoMercenary
def mercenary
"This warrrior doesn't have a mercenary"
end

def employ
'There is no available mercenary'
end
end
7 changes: 7 additions & 0 deletions lecture_4/homework/app/nulls/no_weapon.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# frozen_string_literal: true

class NoWeapon
def attack
'This warrior has no weapon'
end
end
7 changes: 7 additions & 0 deletions lecture_4/homework/app/queries/buildings_queries.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# frozen_string_literal: true

class BuildingsQueries
def self.find_building(id:, relation: Building)
relation.find(id) if id
end
end
19 changes: 19 additions & 0 deletions lecture_4/homework/app/queries/clans_queries.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# frozen_string_literal: true

class ClansQueries
def self.find(clan_id:, relation: Clan)
if clan_id
relation.find(clan_id)
else
relation.order(warriors_count: :desc).first
end
end

def self.all_clans(relation: Clan)
relation.all
end

def self.create_clan(clan_params:, relation: Clan)
relation.create!(clan_params)
end
end
22 changes: 22 additions & 0 deletions lecture_4/homework/app/queries/mercenaries_query.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# frozen_string_literal: true

class MercenariesQuery
def self.can_be_hired(mercenary_id:, relation: Mercenary)
relation.find(mercenary_id).available_from < Time.now
end

def self.find_best(relation: Mercenary)
relation.all
.where('available_from < ? AND warrior_id IS NULL', Time.now)
.order(experience: :desc)
.first
end

def self.all_mercenaries(relation: Mercenary)
relation.all
end

def self.mercenary(mercenary_id:, relation: Mercenary)
relation.find(mercenary_id)
end
end
Loading