From 5f5d0b2d27214db0ddc2c44c978340049b95654c Mon Sep 17 00:00:00 2001 From: notmarkmiranda Date: Mon, 11 Feb 2019 22:23:27 -0700 Subject: [PATCH] [66] Completing game requires finished players --- app/models/game.rb | 13 ++- app/models/player.rb | 12 ++- ...can_complete_and_uncomplete_a_game_spec.rb | 4 +- ...uires_all_players_have_finished_at_spec.rb | 92 +++++++++++++++++++ spec/models/player_spec.rb | 4 +- .../requests/games_controller_request_spec.rb | 4 +- 6 files changed, 121 insertions(+), 8 deletions(-) create mode 100644 spec/features/games/completing_game_requires_all_players_have_finished_at_spec.rb diff --git a/app/models/game.rb b/app/models/game.rb index 400d75e..af4d799 100644 --- a/app/models/game.rb +++ b/app/models/game.rb @@ -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? @@ -23,6 +23,7 @@ def can_be_uncompleted? def complete! return if completed + finish_all_players update(completed: true) end @@ -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 diff --git a/app/models/player.rb b/app/models/player.rb index 010f2f7..86c7060 100644 --- a/app/models/player.rb +++ b/app/models/player.rb @@ -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? @@ -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 diff --git a/spec/features/games/admin_can_complete_and_uncomplete_a_game_spec.rb b/spec/features/games/admin_can_complete_and_uncomplete_a_game_spec.rb index 11c5d79..3adcc79 100644 --- a/spec/features/games/admin_can_complete_and_uncomplete_a_game_spec.rb +++ b/spec/features/games/admin_can_complete_and_uncomplete_a_game_spec.rb @@ -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') diff --git a/spec/features/games/completing_game_requires_all_players_have_finished_at_spec.rb b/spec/features/games/completing_game_requires_all_players_have_finished_at_spec.rb new file mode 100644 index 0000000..e530997 --- /dev/null +++ b/spec/features/games/completing_game_requires_all_players_have_finished_at_spec.rb @@ -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 diff --git a/spec/models/player_spec.rb b/spec/models/player_spec.rb index 661526e..8f617a3 100644 --- a/spec/models/player_spec.rb +++ b/spec/models/player_spec.rb @@ -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 diff --git a/spec/requests/games_controller_request_spec.rb b/spec/requests/games_controller_request_spec.rb index 821cebb..12e9edb 100644 --- a/spec/requests/games_controller_request_spec.rb +++ b/spec/requests/games_controller_request_spec.rb @@ -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 { @@ -120,7 +120,7 @@ end before { game.complete! } - + context 'as an admin' do before { stub_current_user(user) }