Merge pull request #42 from turniere/ticket/TURNIERE-183
Implement statistics endpoint
This commit is contained in:
commit
d47111abb8
|
|
@ -0,0 +1,26 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class StatisticsController < ApplicationController
|
||||||
|
before_action :set_tournament, only: %i[index]
|
||||||
|
|
||||||
|
# GET /tournaments/1/statistics
|
||||||
|
def index
|
||||||
|
group_stage = @tournament.stages.find_by(level: -1)
|
||||||
|
if group_stage
|
||||||
|
service = StatisticsService.new group_stage
|
||||||
|
render json: {
|
||||||
|
most_dominant_score: service.most_dominant_score,
|
||||||
|
least_dominant_score: service.least_dominant_score,
|
||||||
|
group_scores: service.group_scores
|
||||||
|
}
|
||||||
|
else
|
||||||
|
render json: {}, status: :not_implemented
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def set_tournament
|
||||||
|
@tournament = Tournament.find(params[:tournament_id])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -8,8 +8,12 @@ class Stage < ApplicationRecord
|
||||||
delegate :owner, to: :tournament
|
delegate :owner, to: :tournament
|
||||||
|
|
||||||
def teams
|
def teams
|
||||||
return matches.map(&:teams).flatten.uniq unless matches.size.zero?
|
if !matches.size.zero?
|
||||||
|
matches.map(&:teams).flatten.uniq
|
||||||
groups.map(&:teams).flatten.uniq unless groups.size.zero?
|
elsif !groups.size.zero?
|
||||||
|
groups.map(&:teams).flatten.uniq
|
||||||
|
else
|
||||||
|
[]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class StatisticsService
|
||||||
|
def initialize(stage)
|
||||||
|
raise 'Unsupported stage type' if stage.nil? || stage.groups.empty?
|
||||||
|
|
||||||
|
@stage = stage
|
||||||
|
end
|
||||||
|
|
||||||
|
def group_scores
|
||||||
|
sort_group_scores(@stage.groups, :group_points)
|
||||||
|
end
|
||||||
|
|
||||||
|
def most_dominant_score
|
||||||
|
sort_group_scores(@stage.groups, :scored_points).first
|
||||||
|
end
|
||||||
|
|
||||||
|
def least_dominant_score
|
||||||
|
sort_group_scores(@stage.groups, :received_points).first
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
# Sort group scores associated with `groups` by GroupScore#`attr`
|
||||||
|
# in descending order
|
||||||
|
#
|
||||||
|
# @param groups [Array] Groups to take GroupScore objects from
|
||||||
|
# @param attr [Symbol] GroupScore attribute to sort by
|
||||||
|
# @return [Array] Sorted array of group scores
|
||||||
|
def sort_group_scores(groups, attr)
|
||||||
|
groups
|
||||||
|
.map(&:group_scores).flatten # collect all group scores
|
||||||
|
.sort_by(&attr).reverse
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -8,6 +8,8 @@ Rails.application.routes.draw do
|
||||||
|
|
||||||
resources :matches, only: %i[show update]
|
resources :matches, only: %i[show update]
|
||||||
resources :teams, only: %i[show update]
|
resources :teams, only: %i[show update]
|
||||||
resources :tournaments
|
resources :tournaments do
|
||||||
|
resources :statistics, only: %i[index]
|
||||||
|
end
|
||||||
resources :match_scores, only: %i[show update]
|
resources :match_scores, only: %i[show update]
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.describe StatisticsController, type: :controller do
|
||||||
|
describe 'GET #index' do
|
||||||
|
context 'tournament without a group stage' do
|
||||||
|
it 'returns a not implemented response' do
|
||||||
|
get :index, params: { tournament_id: create(:tournament).to_param }
|
||||||
|
expect(response).to have_http_status(:not_implemented)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'tournament with a group stage' do
|
||||||
|
before do
|
||||||
|
@tournament = create(:group_stage_tournament)
|
||||||
|
@group_stage = @tournament.stages.find_by(level: -1)
|
||||||
|
@most_dominant_score = create(:group_score,
|
||||||
|
team: @tournament.teams.first,
|
||||||
|
group_points: 100,
|
||||||
|
scored_points: 100, received_points: 0)
|
||||||
|
@least_dominant_score = create(:group_score,
|
||||||
|
team: @tournament.teams.first,
|
||||||
|
group_points: 0,
|
||||||
|
scored_points: 0, received_points: 100)
|
||||||
|
@tournament.stages.first.groups.first.group_scores << @most_dominant_score
|
||||||
|
@tournament.stages.first.groups.first.group_scores << @least_dominant_score
|
||||||
|
@tournament.save!
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns a success response' do
|
||||||
|
get :index, params: { tournament_id: @tournament.to_param }
|
||||||
|
expect(response).to be_successful
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns a list containing all group scores' do
|
||||||
|
get :index, params: { tournament_id: @tournament.to_param }
|
||||||
|
expect(deserialize_response(response)[:group_scores].length).to eq(GroupScore.count)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns a most dominant group score' do
|
||||||
|
get :index, params: { tournament_id: @tournament.to_param }
|
||||||
|
expect(deserialize_response(response)[:most_dominant_score][:id]).to eq(@most_dominant_score.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns a least dominant group score' do
|
||||||
|
get :index, params: { tournament_id: @tournament.to_param }
|
||||||
|
expect(deserialize_response(response)[:least_dominant_score][:id]).to eq(@least_dominant_score.id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.describe StatisticsController, type: :routing do
|
||||||
|
describe 'routing' do
|
||||||
|
it 'routes to #index' do
|
||||||
|
expect(get: '/tournaments/1/statistics').to route_to('statistics#index', tournament_id: '1')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
RSpec.describe StatisticsService do
|
||||||
|
before do
|
||||||
|
# build tournament with predictable test data
|
||||||
|
tournament = create(:tournament)
|
||||||
|
group_stage = create(:group_stage)
|
||||||
|
group = group_stage.groups.first
|
||||||
|
@most_dominant_score = create(:group_score,
|
||||||
|
group_points: 100,
|
||||||
|
scored_points: 100, received_points: 0)
|
||||||
|
@least_dominant_score = create(:group_score,
|
||||||
|
group_points: 0,
|
||||||
|
scored_points: 0, received_points: 100)
|
||||||
|
group.group_scores << @most_dominant_score
|
||||||
|
group.group_scores << @least_dominant_score
|
||||||
|
tournament.stages << group_stage
|
||||||
|
@service = StatisticsService.new group_stage
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#new' do
|
||||||
|
context 'with a playoff stage' do
|
||||||
|
it 'throws an exception' do
|
||||||
|
expect do
|
||||||
|
StatisticsService.new create(:playoff_stage)
|
||||||
|
end.to raise_error(RuntimeError)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with a group stage' do
|
||||||
|
it 'succeeds' do
|
||||||
|
StatisticsService.new create(:group_stage)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#most_dominant_score' do
|
||||||
|
it 'returns the most dominant group score' do
|
||||||
|
expect(@service.most_dominant_score.id).to eq(@most_dominant_score.id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#least_dominant_score' do
|
||||||
|
it 'returns the least dominant group score' do
|
||||||
|
expect(@service.least_dominant_score.id).to eq(@least_dominant_score.id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#group_scores' do
|
||||||
|
it 'returns an array containing all group scores' do
|
||||||
|
expect(@service.group_scores.length).to eq(GroupScore.count)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
Loading…
Reference in New Issue