Files
euchre_camp/app/services/tournament_csv_importer.rb
T

170 lines
5.2 KiB
Ruby

# frozen_string_literal: true
require "csv"
module EuchreCamp
module Services
class TournamentCsvImporter
# Map table names to numeric IDs
TABLE_NAME_MAP = {
"Clubs" => 1,
"Hearts" => 2,
"Diamonds" => 3,
"Spades" => 4,
"Stars" => 5
}.freeze
def initialize(event_id:)
@event_id = event_id
@rom = EuchreCamp::App["persistence.rom"]
@matches_repo = EuchreCamp::App["repositories.matches"]
@teams_repo = EuchreCamp::App["repositories.teams"]
@events_repo = EuchreCamp::App["repositories.events"]
@rounds_repo = EuchreCamp::App["repositories.tournament_rounds"]
@bracket_matchups_repo = EuchreCamp::App["repositories.bracket_matchups"]
end
def import(csv_file_path)
results = {
matches_created: 0,
teams_created: 0,
rounds_created: 0,
errors: []
}
begin
event = @events_repo.by_id(@event_id)
CSV.foreach(csv_file_path, headers: true, header_converters: :symbol) do |row|
begin
process_row(row, event, results)
rescue => e
results[:errors] << "Row #{row}: #{e.message}"
end
end
rescue => e
results[:errors] << "Fatal error: #{e.message}"
end
results
end
private
def process_row(row, event, results)
# Extract data from CSV row
round_number = row[:round].to_i
table_name = row[:table]
seat_1_name = row[:seat_1]&.strip
seat_3_name = row[:seat_3]&.strip
odds_points = row[:odds_points].to_i
seat_2_name = row[:seat_2]&.strip
seat_4_name = row[:seat_4]&.strip
evens_points = row[:evens_points].to_i
winner = row[:winner]&.strip&.downcase
# Validate required fields
unless seat_1_name && seat_3_name && seat_2_name && seat_4_name
raise "Missing player names in row"
end
# Find or create players
player_1 = find_or_create_player(seat_1_name)
player_2 = find_or_create_player(seat_3_name)
player_3 = find_or_create_player(seat_2_name)
player_4 = find_or_create_player(seat_4_name)
# Find or create teams
team_1 = @teams_repo.find_or_create(@event_id, player_1[:id], player_2[:id], "#{seat_1_name} + #{seat_3_name}")
team_2 = @teams_repo.find_or_create(@event_id, player_3[:id], player_4[:id], "#{seat_2_name} + #{seat_4_name}")
results[:teams_created] += 1 if team_1[:created_at] == team_2[:created_at] # Rough check for new teams
# Find or create round
round = find_or_create_round(round_number)
# Map table name to number
table_number = TABLE_NAME_MAP[table_name] || table_name.to_i
if table_number == 0
raise "Unknown table name: #{table_name}"
end
# Determine winner based on scores or explicit winner column
team_1_score = odds_points
team_2_score = evens_points
# Verify winner matches scores if explicitly stated
if winner
if winner == "odds" && team_1_score <= team_2_score
results[:errors] << "Warning: Row claims Odds won but score is #{team_1_score}-#{team_2_score}"
elsif winner == "evens" && team_2_score <= team_1_score
results[:errors] << "Warning: Row claims Evens won but score is #{team_1_score}-#{team_2_score}"
end
end
# Create match
match_data = {
team_1_p1_id: player_1[:id],
team_1_p2_id: player_2[:id],
team_1_score: team_1_score,
team_2_p1_id: player_3[:id],
team_2_p2_id: player_4[:id],
team_2_score: team_2_score,
played_at: Time.now,
status: 'completed'
}
match = @matches_repo.create(match_data)
results[:matches_created] += 1
# Create bracket matchup entry
bracket_data = {
round_id: round[:id],
event_id: @event_id,
team_1_id: team_1[:id],
team_2_id: team_2[:id],
table_number: table_number,
bracket_position: table_number,
status: 'completed'
}
@bracket_matchups_repo.create(bracket_data)
# Queue Elo calculation
EuchreCamp::Jobs::CalculateEloJob.perform_later(match[:id])
rescue => e
raise "Error processing row: #{e.message}"
end
def find_or_create_player(name)
return nil unless name
player = @rom.relations[:players].where(name: name).one
if player
player
else
# Create player with default rating
@rom.relations[:players].insert(name: name, rating: 0, current_elo: 1000)
@rom.relations[:players].where(name: name).one
end
end
def find_or_create_round(round_number)
round = @rom.relations[:tournament_rounds].where(event_id: @event_id, round_number: round_number).one
if round
round
else
@rounds_repo.create(
event_id: @event_id,
round_number: round_number,
status: 'completed'
)
end
end
end
end
end