# frozen_string_literal: true module EuchreCamp module Services class PartnershipTracker # Record partnerships when a match completes def self.record_match(match_id) rom = EuchreCamp::App["persistence.rom"] match = rom.relations[:matches].by_pk(match_id).one return unless match games_repo = EuchreCamp::App["repositories.partnership_games"] stats_repo = EuchreCamp::App["repositories.partnership_stats"] # Calculate Elo changes for each player # This is called AFTER Elo calculation, so we get the change from elo_snapshots elo_changes = calculate_elo_changes(match_id) # Record Team 1 partnership record_partnership( games_repo: games_repo, stats_repo: stats_repo, match_id: match_id, player_1_id: match[:team_1_p1_id], player_2_id: match[:team_1_p2_id], team_number: 1, won: match[:team_1_score] > match[:team_2_score], elo_change: elo_changes[match[:team_1_p1_id]] + elo_changes[match[:team_1_p2_id]] ) # Record Team 2 partnership record_partnership( games_repo: games_repo, stats_repo: stats_repo, match_id: match_id, player_1_id: match[:team_2_p1_id], player_2_id: match[:team_2_p2_id], team_number: 2, won: match[:team_2_score] > match[:team_1_score], elo_change: elo_changes[match[:team_2_p1_id]] + elo_changes[match[:team_2_p2_id]] ) end def self.calculate_elo_changes(match_id) rom = EuchreCamp::App["persistence.rom"] # Get the two most recent snapshots before and after this match snapshots = rom.relations[:elo_snapshots] .where(match_id: match_id) .order(:created_at) .to_a # Group by player and calculate change changes = Hash.new(0) snapshots.group_by { |s| s[:player_id] }.each do |player_id, player_snapshots| # For a single match, there should be exactly one snapshot per player # The snapshot contains rating_before and rating_after for this specific match # So we calculate the change directly from that snapshot player_snapshots.each do |snapshot| changes[player_id] = snapshot[:rating_after] - snapshot[:rating_before] end end changes end def self.record_partnership(games_repo:, stats_repo:, match_id:, player_1_id:, player_2_id:, team_number:, won:, elo_change:) # Record the partnership game games_repo.create( match_id: match_id, player_1_id: player_1_id, player_2_id: player_2_id, team_number: team_number, won_match: won ? 1 : 0 ) # Update partnership statistics (using consistent ordering) stats_repo.update_stats(player_1_id, player_2_id, won: won, elo_change: elo_change) end # Get partnership statistics for a player def self.get_player_partnerships(player_id) stats_repo = EuchreCamp::App["repositories.partnership_stats"] players_repo = EuchreCamp::App["repositories.players"] stats = stats_repo.by_player(player_id) all_players = players_repo.all.to_h { |p| [p[:id], p] } stats.map do |stat| partner_id = stat[:player_1_id] == player_id ? stat[:player_2_id] : stat[:player_1_id] partner = all_players[partner_id] { partner: partner, games_played: stat[:games_played], wins: stat[:wins], losses: stat[:losses], win_rate: stat[:games_played] > 0 ? (stat[:wins].to_f / stat[:games_played]).round(3) : 0, total_elo_change: stat[:total_elo_change], avg_elo_change: stat[:games_played] > 0 ? (stat[:total_elo_change].to_f / stat[:games_played]).round(2) : 0, last_played: stat[:last_played] } end.sort_by { |p| -p[:games_played] } end end end end