require_relative "rank_king/models" require_relative "rank_king/open_skill" module RankKing OS = OpenSkill.new Match = Data.define(:a, :b) def self.suggest_game(axis) items = axis.pool.items items.combination(2).sort_by {|combo| # TODO get all the ratings at once ratings = combo.map {|item| Rating.first(axis:, item:) || OS.rating } Math.sqrt( [ratings, ratings.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