Skip to content

Commit

Permalink
Add id_and_faction_date JSON endpoint for tournaments. (#386)
Browse files Browse the repository at this point in the history
  • Loading branch information
plural authored Jan 20, 2025
1 parent 135dde0 commit 2f53b22
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 4 deletions.
7 changes: 7 additions & 0 deletions app/controllers/tournaments_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ class TournamentsController < ApplicationController
show edit update destroy
upload_to_abr save_json cut qr registration timer
close_registration open_registration lock_player_registrations unlock_player_registrations
id_and_faction_data
]

def index
Expand Down Expand Up @@ -221,6 +222,12 @@ def unlock_player_registrations
redirect_back(fallback_location: tournament_rounds_path(@tournament))
end

def id_and_faction_data
authorize @tournament, :show?

render json: @tournament.id_and_faction_data
end

private

def set_tournament
Expand Down
57 changes: 57 additions & 0 deletions app/models/tournament.rb
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,63 @@ def runner_counts
end.sort_by(&:last).reverse
end

def id_and_faction_data
sql = <<~SQL
WITH corp_ids AS (
SELECT
1 AS side,
COALESCE(corp_ids.name, 'Unknown') as id,
COALESCE(corp_ids.faction, 'unknown') AS faction
FROM
players AS p
LEFT JOIN identities AS corp_ids
ON p.corp_identity_ref_id = corp_ids.id
WHERE p.tournament_id = ?
),
runner_ids AS (
SELECT
2 AS side,
COALESCE(runner_ids.name, 'Unknown') as id,
COALESCE(runner_ids.faction, 'unknown') AS faction
FROM
players AS p
LEFT JOIN identities AS runner_ids
ON p.runner_identity_ref_id = runner_ids.id
WHERE p.tournament_id = ?
)
SELECT side, id, faction, COUNT(*) AS num_ids FROM corp_ids GROUP BY 1,2,3
UNION ALL
SELECT side, id, faction, COUNT(*) AS num_ids FROM runner_ids GROUP BY 1,2,3
SQL
sql = ActiveRecord::Base.sanitize_sql([sql, id, id])

results = {
num_players: 0,
corp: {
ids: {},
factions: {}
},
runner: {
ids: {},
factions: {}
}
}
ActiveRecord::Base.connection.exec_query(sql).each do |row|
side = row['side'] == 1 ? :corp : :runner

# We only need to use 1 side to get the total number of players
results[:num_players] += row['num_ids'] if side == :corp

# Only 1 row per id
results[side][:ids][row['id']] = row['num_ids']

# Multiple rows per faction so we need to sum them up
results[side][:factions][row['faction']] ||= 0
results[side][:factions][row['faction']] += row['num_ids']
end
results
end

def generate_slug
self.slug = rand(Integer(36**4)).to_s(36).upcase
generate_slug if Tournament.exists?(slug:)
Expand Down
1 change: 1 addition & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
resources :stages, only: %i[create destroy]
post :upload_to_abr, on: :member
get :save_json, on: :member
get :id_and_faction_data, on: :member
post :cut, on: :member
get :qr, on: :member
get :registration, on: :member
Expand Down
64 changes: 60 additions & 4 deletions spec/requests/tournaments_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,25 @@

RSpec.describe TournamentsController do
let(:tournament) { create(:tournament, name: 'My Tournament') }
let(:player1) { create(:player, tournament:) }
let(:player2) { create(:player, tournament:) }
let(:player3) { create(:player, tournament:) }
let(:player4) { create(:player, tournament:) }

let(:btl) { create(:identity, name: 'Builder of Nations', faction: 'weyland-consortium') }
let(:hoshiko) { create(:identity, name: 'Hoshiko', faction: 'anarch') }
let(:sable) { create(:identity, name: 'Sable', faction: 'criminal') }
let(:az) { create(:identity, name: 'Az', faction: 'criminal') }

let(:player1) do
create(:player, tournament:, corp_identity: btl.name, corp_identity_ref_id: btl.id, runner_identity: hoshiko.name,
runner_identity_ref_id: hoshiko.id)
end
let(:player2) do
create(:player, tournament:, runner_identity: sable.name,
runner_identity_ref_id: sable.id)
end
let(:player3) do
create(:player, tournament:, corp_identity: btl.name, corp_identity_ref_id: btl.id, runner_identity: az.name,
runner_identity_ref_id: az.id)
end
let(:player4) { create(:player, tournament:, corp_identity: btl.name, corp_identity_ref_id: btl.id) }

describe '#save_json' do
before do
Expand Down Expand Up @@ -70,4 +85,45 @@
expect(tournament.swiss?).to be(true)
end
end

describe '#id_and_faction_data' do
it 'returns correct id_and_faction_data JSON' do
player1.save
player2.save
player3.save
player4.save
# puts tournament.name
puts tournament.players.size

get id_and_faction_data_tournament_path(tournament)

expect(JSON.parse(response.body))
.to eq(
'num_players' => 4,
'corp' => {
'factions' => {
'weyland-consortium' => 3,
'unknown' => 1
},
'ids' => {
'Builder of Nations' => 3,
'Unknown' => 1
}
},
'runner' => {
'factions' => {
'unknown' => 1,
'anarch' => 1,
'criminal' => 2
},
'ids' => {
'Az' => 1,
'Hoshiko' => 1,
'Sable' => 1,
'Unknown' => 1
}
}
)
end
end
end

0 comments on commit 2f53b22

Please sign in to comment.