require_relative "rank_king/models" require_relative "rank_king/open_skill" module RankKing OS = OpenSkill.new Match = Data.define(:a, :b) # rates all possible 1v1 games to find which generally decreases sigma # regardless of the winner/loser - is this mathematically sound? I have # no idea def self.suggest_game(axis) items = axis.pool.items ratings = items.to_h { [_1.id, Rating.first(axis:, item: _1) || OS.rating] } items.combination(2).sort_by {|combo| game = combo.map { ratings.fetch(_1.id) } Math.sqrt( [game, game.reverse] .map {|game| [game, OS.rate(*game).flatten] } .sum {|pre,post| pre.zip(post).sum { (_1.sigma - _2.sigma)**2 }} ) }.last end def self.rank(axis, winner:, loser:) fail unless [winner, loser].all? { _1.pool == axis.pool } game = [winner, loser].map { Rating.first(axis:, item: _1) || OS.rating } result = OS.rate(*game).flatten DB.transaction do Ranking.create(axis:, winner:, loser:) Rating.update_or_create({axis:, item: winner}, result.fetch(0).to_h) Rating.update_or_create({axis:, item: loser}, result.fetch(1).to_h) end end end