Skip to content

Commit

Permalink
added updating oraculs lineups points for cups
Browse files Browse the repository at this point in the history
  • Loading branch information
kortirso committed Feb 29, 2024
1 parent 277825f commit ce379f7
Show file tree
Hide file tree
Showing 13 changed files with 169 additions and 45 deletions.
16 changes: 16 additions & 0 deletions app/controllers/admin/cups/rounds_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ class RoundsController < Admin::BaseController

before_action :find_cups_rounds, only: %i[index]
before_action :find_cup, only: %i[new create]
before_action :find_cups_round, only: %i[refresh_oraculs_points]

def index; end

Expand All @@ -24,6 +25,17 @@ def create
end
end

def refresh_oraculs_points
::Oraculs::Lineups::Points::UpdateJob.perform_later(
periodable_id: @cups_round.id,
periodable_type: 'Cups::Round'
)
redirect_to(
admin_cup_rounds_path(cup_id: @cups_round.cup_id),
notice: t('controllers.admin.cups.rounds.refresh_oraculs_points')
)
end

private

def find_cups_rounds
Expand All @@ -38,6 +50,10 @@ def find_cup
@cup = Cup.find(params[:cup_id])
end

def find_cups_round
@cups_round = ::Cups::Round.find(params[:cups_round_id])
end

def cup_params
params.require(:cups_round).permit(:name, :position)
end
Expand Down
3 changes: 2 additions & 1 deletion app/jobs/games/import_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ def perform(game_ids:, main_external_source:)
)

::Oraculs::Lineups::Points::UpdateJob.perform_later(
week_id: week.id
periodable_id: week.id,
periodable_type: 'Week'
)
end
end
Expand Down
7 changes: 3 additions & 4 deletions app/jobs/oraculs/lineups/points/update_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,9 @@ module Points
class UpdateJob < ApplicationJob
queue_as :default

def perform(week_id:)
update_points.call(week_id: week_id)

Week.find_by(id: week_id)&.season&.oracul_leagues&.each do |oracul_league|
def perform(periodable_id:, periodable_type:)
update_points.call(periodable_id: periodable_id, periodable_type: periodable_type)
periodable_type.constantize.find_by(id: periodable_id)&.placeable&.oracul_leagues&.each do |oracul_league|
update_current_place.call(oracul_league: oracul_league)
end
end
Expand Down
2 changes: 2 additions & 0 deletions app/models/cups/round.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,7 @@ class Round < ApplicationRecord
scope :future, -> { where(status: [ACTIVE, COMING]) }

enum status: { COMING => 0, ACTIVE => 1, FINISHED => 2 }

alias placeable cup
end
end
2 changes: 2 additions & 0 deletions app/models/week.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ class Week < ApplicationRecord

delegate :league, to: :season

alias placeable season

def previous
Week.find_by(season_id: season_id, position: position - 1)
end
Expand Down
40 changes: 23 additions & 17 deletions app/services/oraculs/lineups/points/update_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@ class UpdateService
include Deps[oraculs_update_points: 'services.oraculs.points.update']

# rubocop: disable Metrics/AbcSize
def call(week_id:)
def call(periodable_id:, periodable_type:)
oracul_ids = []
games = games(week_id)
grouped_forecasts = forecasts(games.pluck(:id))
forecastables = forecastables(periodable_id, periodable_type)
grouped_forecasts = forecasts(forecastables.pluck(:id), periodable_type)

lineups = oraculs_lineups(week_id).map do |lineup|
lineups = oraculs_lineups(periodable_id, periodable_type).map do |lineup|
oracul_ids << lineup[:oracul_id]
lineup.merge(
points: games.each_with_index.inject(0) { |acc, (game, index)|
acc + find_points(game, grouped_forecasts[lineup[:id]][index])
points: forecastables.each_with_index.inject(0) { |acc, (forecastable, index)|
acc + find_points(forecastable, grouped_forecasts[lineup[:id]][index])
}
)
end
Expand All @@ -29,41 +29,47 @@ def call(week_id:)

private

def oraculs_lineups(week_id)
def oraculs_lineups(periodable_id, periodable_type)
Oraculs::Lineup
.where(periodable_id: week_id, periodable_type: 'Week')
.where(periodable_id: periodable_id, periodable_type: periodable_type)
.hashable_pluck(:id, :uuid, :oracul_id, :periodable_id, :periodable_type)
end

def games(week_id)
Game
.where(week_id: week_id)
def forecastables(periodable_id, periodable_type)
games_relation(periodable_id, periodable_type)
.where.not(points: [])
.order(id: :asc)
.hashable_pluck(:id, :points)
end

def forecasts(game_ids)
def games_relation(periodable_id, periodable_type)
return Game.where(week_id: periodable_id) if periodable_type == 'Week'

Cups::Pair.where(cups_round_id: periodable_id)
end

def forecasts(forecastable_ids, periodable_type)
forecastable_type = periodable_type == 'Week' ? 'Game' : 'Cups::Pair'
Oraculs::Forecast
.where(forecastable_id: game_ids, forecastable_type: 'Game')
.where(forecastable_id: forecastable_ids, forecastable_type: forecastable_type)
.order(forecastable_id: :asc)
.hashable_pluck(:oraculs_lineup_id, :forecastable_id, :value)
.group_by { |element| element[:oraculs_lineup_id] }
end

# rubocop: disable Metrics/AbcSize
def find_points(game, forecast)
def find_points(forecastable, forecast)
return 0 if forecast[:value].empty?

game_home_score = game[:points][0]
game_home_score = forecastable[:points][0]
forecast_home_score = forecast[:value][0]

game_difference = game[:points][0] - game[:points][1]
game_difference = forecastable[:points][0] - forecastable[:points][1]
forecast_difference = forecast[:value][0] - forecast[:value][1]

return 3 if game_home_score == forecast_home_score && game_difference == forecast_difference
return 2 if game_difference == forecast_difference
return 1 if difference_result(game[:points]) == difference_result(forecast[:value])
return 1 if difference_result(forecastable[:points]) == difference_result(forecast[:value])

0
end
Expand Down
1 change: 1 addition & 0 deletions app/views/controllers/admin/cups/rounds/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
<td><%= cups_round[:position] %></td>
<td>
<%= link_to t('views.admin.cups.rounds.index.pairs'), admin_cups_round_pairs_path(cups_round_id: cups_round[:id]), class: 'btn-primary btn-small' %>
<%= link_to t('views.admin.cups.rounds.index.refresh_oraculs_points'), admin_refresh_oraculs_points_path(cups_round_id: cups_round[:id]), class: 'btn-primary btn-small' %>
</td>
</tr>
<% end %>
Expand Down
2 changes: 2 additions & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ en:
rounds:
create:
success: Cups round is created
refresh_oraculs_points: Refreshing is started
pairs:
create:
success: Cups pair is created
Expand Down Expand Up @@ -195,6 +196,7 @@ en:
name: Name
position: Position
pairs: Games
refresh_oraculs_points: Refresh oraculs
new:
create: Create new cups round
pairs:
Expand Down
2 changes: 2 additions & 0 deletions config/locales/ru.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ ru:
rounds:
create:
success: Кубковый раунд создан
refresh_oraculs_points: Обновление оракулов начато
pairs:
create:
success: Кубковая игры создана
Expand Down Expand Up @@ -195,6 +196,7 @@ ru:
name: Название
position: Положение
pairs: Игры
refresh_oraculs_points: Обновить оракулов
new:
create: Создать новый раунд
pairs:
Expand Down
4 changes: 4 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@
resources :pairs, only: %i[index new edit create update]
end
end
scope module: :cups do
get 'cups_rounds/:cups_round_id/refresh_oraculs_points', to: 'rounds#refresh_oraculs_points',
as: :refresh_oraculs_points
end
resources :weeks, only: %i[index edit update]
end

Expand Down
38 changes: 38 additions & 0 deletions spec/controllers/admin/cups/rounds_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -98,4 +98,42 @@ def do_request
post :create, params: { cup_id: 'unexisting', cups_round: { name: '1/8', position: '1' } }
end
end

describe 'GET#refresh_oraculs_points' do
it_behaves_like 'required auth'
it_behaves_like 'required email confirmation'
it_behaves_like 'required available email'
it_behaves_like 'required admin'

context 'for admin' do
sign_in_admin

before { allow(Oraculs::Lineups::Points::UpdateJob).to receive(:perform_later) }

context 'for unexisting cups round' do
it 'render not found page' do
do_request

expect(response).to render_template 'shared/404'
end
end

context 'for existing cups round' do
let!(:cups_round) { create :cups_round, cup: cup }

it 'runs background job', :aggregate_failures do
get :refresh_oraculs_points, params: { cups_round_id: cups_round.id, locale: 'en' }

expect(Oraculs::Lineups::Points::UpdateJob).to(
have_received(:perform_later).with(periodable_id: cups_round.id, periodable_type: 'Cups::Round')
)
expect(response).to redirect_to admin_cup_rounds_path(cup_id: cup.id)
end
end
end

def do_request
get :refresh_oraculs_points, params: { cups_round_id: 'unexisting', locale: 'en' }
end
end
end
46 changes: 36 additions & 10 deletions spec/jobs/oraculs/lineups/points/update_job_spec.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
# frozen_string_literal: true

describe Oraculs::Lineups::Points::UpdateJob, type: :service do
subject(:job_call) { described_class.perform_now(week_id: week.id) }
subject(:job_call) {
described_class.perform_now(periodable_id: periodable.id, periodable_type: periodable.class.name)
}

let!(:season) { create :season }
let!(:league) { create :league }
let!(:season) { create :season, league: league }
let!(:week) { create :week, season: season }
let!(:oracul_place) { create :oracul_place, placeable: season }
let!(:oracul_league) { create :oracul_league, oracul_place: oracul_place }
Expand All @@ -13,14 +16,37 @@
allow(FantasySports::Container.resolve('services.oracul_leagues.members.update_current_place')).to receive(:call)
end

it 'calls services', :aggregate_failures do
job_call
context 'for week' do
let(:periodable) { week }

expect(FantasySports::Container.resolve('services.oraculs.lineups.points.update')).to(
have_received(:call).with(week_id: week.id)
)
expect(FantasySports::Container.resolve('services.oracul_leagues.members.update_current_place')).to(
have_received(:call).with(oracul_league: oracul_league)
)
it 'calls services', :aggregate_failures do
job_call

expect(FantasySports::Container.resolve('services.oraculs.lineups.points.update')).to(
have_received(:call).with(periodable_id: week.id, periodable_type: 'Week')
)
expect(FantasySports::Container.resolve('services.oracul_leagues.members.update_current_place')).to(
have_received(:call).with(oracul_league: oracul_league)
)
end
end

context 'for cups round' do
let!(:cup) { create :cup, league: league }
let!(:cups_round) { create :cups_round, cup: cup }
let(:periodable) { cups_round }

before { oracul_place.update!(placeable: cup) }

it 'calls services', :aggregate_failures do
job_call

expect(FantasySports::Container.resolve('services.oraculs.lineups.points.update')).to(
have_received(:call).with(periodable_id: cups_round.id, periodable_type: 'Cups::Round')
)
expect(FantasySports::Container.resolve('services.oracul_leagues.members.update_current_place')).to(
have_received(:call).with(oracul_league: oracul_league)
)
end
end
end
51 changes: 38 additions & 13 deletions spec/services/oraculs/lineups/points/update_service_spec.rb
Original file line number Diff line number Diff line change
@@ -1,24 +1,49 @@
# frozen_string_literal: true

describe Oraculs::Lineups::Points::UpdateService, type: :service do
subject(:service_call) { described_class.new.call(week_id: week.id) }
subject(:service_call) {
described_class.new.call(periodable_id: periodable.id, periodable_type: periodable.class.name)
}

let!(:week) { create :week }
let!(:oraculs_lineup) { create :oraculs_lineup, periodable: week }
context 'for week' do
let!(:periodable) { create :week }
let!(:oraculs_lineup) { create :oraculs_lineup, periodable: periodable }

before do
game1 = create :game, week: week, points: [1, 0]
game2 = create :game, week: week, points: [1, 0]
game3 = create :game, week: week, points: [1, 0]
before do
game1 = create :game, week: periodable, points: [1, 0]
game2 = create :game, week: periodable, points: [1, 0]
game3 = create :game, week: periodable, points: [1, 0]

create :oraculs_forecast, oraculs_lineup: oraculs_lineup, forecastable: game1, value: [1, 0]
create :oraculs_forecast, oraculs_lineup: oraculs_lineup, forecastable: game2, value: [2, 0]
create :oraculs_forecast, oraculs_lineup: oraculs_lineup, forecastable: game3, value: [0, 3]
create :oraculs_forecast, oraculs_lineup: oraculs_lineup, forecastable: game1, value: [1, 0]
create :oraculs_forecast, oraculs_lineup: oraculs_lineup, forecastable: game2, value: [2, 0]
create :oraculs_forecast, oraculs_lineup: oraculs_lineup, forecastable: game3, value: [0, 3]
end

it 'updates points' do
service_call

expect(oraculs_lineup.reload.points).to eq 4
end
end

it 'updates points' do
service_call
context 'for cups round' do
let!(:periodable) { create :cups_round }
let!(:oraculs_lineup) { create :oraculs_lineup, periodable: periodable }

before do
cups_pair1 = create :cups_pair, cups_round: periodable, points: [1, 0]
cups_pair2 = create :cups_pair, cups_round: periodable, points: [1, 0]
cups_pair3 = create :cups_pair, cups_round: periodable, points: [1, 0]

create :oraculs_forecast, oraculs_lineup: oraculs_lineup, forecastable: cups_pair1, value: [1, 0]
create :oraculs_forecast, oraculs_lineup: oraculs_lineup, forecastable: cups_pair2, value: [2, 0]
create :oraculs_forecast, oraculs_lineup: oraculs_lineup, forecastable: cups_pair3, value: [0, 3]
end

it 'updates points' do
service_call

expect(oraculs_lineup.reload.points).to eq 4
expect(oraculs_lineup.reload.points).to eq 4
end
end
end

0 comments on commit ce379f7

Please sign in to comment.