Skip to content

Commit

Permalink
Merge pull request #83 from notmarkmiranda/66-completing-game-require…
Browse files Browse the repository at this point in the history
…s-all-players-are-finished-at-or-have-place

[66] Completing game requires finished players
  • Loading branch information
notmarkmiranda committed Feb 12, 2019
2 parents 8bb7346 + 5f5d0b2 commit 757530f
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 8 deletions.
13 changes: 12 additions & 1 deletion app/models/game.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def available_players
end

def can_be_completed?
not_completed? && has_enough_players?
not_completed? && has_enough_players? && all_players_finished?
end

def can_be_uncompleted?
Expand All @@ -23,6 +23,7 @@ def can_be_uncompleted?

def complete!
return if completed
finish_all_players
update(completed: true)
end

Expand Down Expand Up @@ -77,6 +78,16 @@ def season_league_season_number

private

def all_players_finished?
players.map(&:finished_at).all?
end

def finish_all_players
players.in_finishing_order.each_with_index do |player, index|
player.finish_player_and_calculate_score(index + 1)
end
end

def has_enough_players?
players_count > 1
end
Expand Down
12 changes: 11 additions & 1 deletion app/models/player.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,17 @@ class Player < ApplicationRecord
delegate :season_number, to: :league, prefix: true

scope :in_place, -> { order(finishing_place: :asc) }
scope :in_finishing_order, -> { order(finished_at: :desc) }

def calculate_score
numerator = game_players_count * game_buy_in ** 2 / total_expense
denominator = finishing_place + 1
((Math.sqrt(numerator) / denominator) * 100).floor / 100.0
((Math.sqrt(numerator) / denominator) * 1000).floor / 1000.0
end

def finish_player_and_calculate_score(place)
update(finishing_place: place)
update_score
end

def has_additional_expense?
Expand Down Expand Up @@ -101,4 +107,8 @@ def self.subquery
def total_expense
game_buy_in + additional_expense
end

def update_score
update(score: calculate_score)
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@
before { stub_current_user(admin) }
context 'with at least 2 finished players' do
before do
create_list(:player, 2, game: game)
create_list(:player, 2, game: game, finished_at: Time.now)
end

it 'allows the game to be completed and redirects back to the game path' do
visit game_path(game)

click_button 'Complete Game'

expect(current_path).to eq(game_path(game))
expect(page).not_to have_button('Complete Game')
expect(page).to have_button('Uncomplete Game')
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
require 'rails_helper'

describe 'Completing a game requires all players have finished_at' do
let(:game) { create :game, buy_in: 15 }
let(:admin) { game.league.user }

before do
stub_current_user(admin)
end

context 'with all players finished' do
let!(:second_place_player) do
create(
:player,
game: game,
finished_at: Time.now,
finishing_place: nil,
score: nil,
additional_expense: 0
)
end

let!(:first_place_player) do
create(
:player,
game: game,
finished_at: (Time.now + 120),
finishing_place: nil,
score: nil,
additional_expense: 0
)
end

it 'completes the game and gives the players a score and place based on time' do
visit game_path game

click_button 'Complete Game'

expect(page).to have_content("1. #{first_place_player.user_full_name}")
expect(page).to have_content('Score: 2.738')
expect(page).to have_content("2. #{second_place_player.user_full_name}")
expect(page).to have_content('Score: 1.825')
end
end

context 'if one of the players is not finished' do
let!(:unfinished_player) do
create(
:player,
game: game,
finished_at: nil,
finishing_place: nil,
score: nil,
additional_expense: 100
)
end

let!(:second_place_player) do
create(
:player,
game: game,
finished_at: Time.now,
finishing_place: nil,
score: nil,
additional_expense: 0
)
end

let!(:first_place_player) do
create(
:player,
game: game,
finished_at: (Time.now + 120),
finishing_place: nil,
score: nil,
additional_expense: 0
)
end

it 'should not complete the game or give players a score or place based on time' do
visit game_path game

click_button 'Complete Game'

expect(page).to have_content(unfinished_player.user_full_name)
expect(page).not_to have_content("2. #{first_place_player.user_full_name}")
expect(page).not_to have_content('Score: 2.236')
expect(page).not_to have_content("3. #{second_place_player.user_full_name}")
expect(page).not_to have_content('Score: 1.677')
end
end
end
4 changes: 2 additions & 2 deletions spec/models/player_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@
subject { player.calculate_score }

it 'scores a single player' do
expect(subject).to eq(4.97)
expect(subject).to eq(4.974)
end

it 'scores with 2 players' do
create(:player, game: game)

expect(subject).to eq(7.03)
expect(subject).to eq(7.035)
end
end

Expand Down
4 changes: 2 additions & 2 deletions spec/requests/games_controller_request_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
before { stub_current_user(user) }

context 'with at least 2 players finished' do
before { create_list(:player, 2, game: game) }
before { create_list(:player, 2, game: game, finished_at: Time.now) }

it 'redirects back to game_path' do
expect {
Expand Down Expand Up @@ -120,7 +120,7 @@
end

before { game.complete! }

context 'as an admin' do
before { stub_current_user(user) }

Expand Down

0 comments on commit 757530f

Please sign in to comment.