class ActiveGenie::Ranking::FreeForAll
def self.call(...)
def self.call(...) new(...).call end
def battle(player_1, player_2)
def battle(player_1, player_2) result = ActiveGenie::Battle.basic( player_1.content, player_2.content, @criteria, config: @config ) winner, loser = case result['winner'] when 'player_1' then [player_1, player_2, result['reasoning']] when 'player_2' then [player_2, player_1, result['reasoning']] when 'draw' then [nil, nil, result['reasoning']] end ActiveGenie::Logger.debug({ code: :free_for_all_battle, player_ids: [player_1.id, player_2.id], winner_id: winner&.id, loser_id: loser&.id, reasoning: result['reasoning'] }) [winner, loser] end
def call
def call ActiveGenie::Logger.with_context(log_context, observer: method(:log_observer)) do matches.each do |player_1, player_2| winner, loser = battle(player_1, player_2) if winner.nil? || loser.nil? player_1.draw! player_2.draw! else winner.win! loser.lose! end end end ActiveGenie::Logger.info({ code: :free_for_all_report, **report }) report end
def free_for_all_id
def free_for_all_id eligible_ids = @players.eligible.map(&:id).join(',') ranking_unique_key = [eligible_ids, @criteria, @config.to_json].join('-') Digest::MD5.hexdigest(ranking_unique_key) end
def initialize(players, criteria, config: {})
def initialize(players, criteria, config: {}) @players = players @criteria = criteria @config = config @start_time = Time.now @total_tokens = 0 end
def log_context
def log_context { free_for_all_id: } end
def log_observer(log)
def log_observer(log) @total_tokens += log[:total_tokens] if log[:code] == :llm_usage end
def matches
TODO: reduce the number of matches based on transitivity.
def matches @players.eligible.combination(2).to_a end
def report
def report { free_for_all_id:, battles_count: matches.size, duration_seconds: Time.now - @start_time, total_tokens: @total_tokens, } end