You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

39 lines
1.2 KiB

1 year ago
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
1 year ago
def self.suggest_game(axis)
1 year ago
items = axis.pool.items
ratings = items.to_h { [_1.id, Rating.first(axis:, item: _1) || OS.rating] }
1 year ago
items.combination(2).sort_by {|combo|
game = combo.map { ratings.fetch(_1.id) }
1 year ago
Math.sqrt(
[game, game.reverse]
.map {|game| [game, OS.rate(*game).flatten] }
1 year ago
.sum {|pre,post| pre.zip(post).sum { (_1.sigma - _2.sigma)**2 }}
)
}.last
end
1 year ago
def self.rank(axis, winner:, loser:)
1 year ago
fail unless [winner, loser].all? { _1.pool == axis.pool }
1 year ago
game = [winner, loser].map { Rating.first(axis:, item: _1) || OS.rating }
result = OS.rate(*game).flatten
1 year ago
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