我有一个应用程序,可以为用户提供带有 game_type 的游戏的游戏积分。我想做的是:
- 基于游戏的分数小计
- 确定用户游戏排名(排名 1 = 最高分)基于他们与其他用户相比获得的 game_id 分数
- 根据 game_type 小计积分
- 确定用户 game_type 排名(排名 1 = 最高分)基于他们在 game_type_id 上与其他用户相比有多少分
根据上面的查询结果,我想只显示game_types和games之间的前五名排名。
例如,假设用户的计算是这样的:
game_id = 1, rank 200
game_id = 2, rank 10
game_id = 3, rank 6
game_id = 4, rank 31
game_type_id = 1, rank 500
game_type_id = 2, rank 400
game_type_id = 3, rank 1
game_type_id = 4, rank 7
game_type_id = 5, rank 100
然后我只想显示 games:2, 3, 4 和 game_types: 3, 4,5 的排名,因为这些是该用户的游戏和 game_types 中的前五名。
我考虑在用户表中为每个 game_type 和游戏(即 game_1_rank、game_2_rank、game_type_1_rank 等)创建一个 game_type 和游戏字段,这样我就可以每小时计算后台作业中的点数,然后尝试从中检索最高排名那里,但我认为这不是最好的方法,因为随着时间的推移会添加新游戏和游戏类型。
因此,我认为最好的方法是在加载 users#show 页面时进行计算,然后缓存该页面(并且每小时到期)。
我的模型如下所示:
user
has_many :points
point
belongs_to :game
belongs_to :game_type
belongs_to :user
game
has_many :points
has_one :game_type
game_type
has_many :points
我在 Users#show 中有这段代码来计算所有游戏和游戏类型的总体排名,但我不确定如何调整它,以便我可以访问我认为的最高排名(我的视图中还没有代码显示该用户的前五名以及他们的游戏/游戏类型)。
# calculate ranks for all users for all games in order to find the user's rank
@games = Game.all
@games.each do |game|
@users_by_game = Point.where(“game_id = ?”, game.id).select("sum(amount) as points, user_id").order("points desc").group("user_id")
rank = 0
points = 0
@users_by_game.each_with_index do |user_by_game, index|
if user_by_game.points != points
points = user_by_game.points
rank += 1
end
end
# calculate ranks for all users for all games_types in order to find the user's rank
@game_types = GameType.all
@game_types.each do |game_type|
@users_by_game_type = Point.where(“game_type_id = ?”, game_type.id).select("sum(amount) as points, user_id").order("points desc").group("user_id")
rank = 0
points = 0
@users_by_game_type.each_with_index do |user_by_game_type, index|
if user_by_game_type.points != points
points = user_by_game_type.points
rank += 1
end
end
end
我要确定的是:
- 这是计算这些排名的最佳方法,还是有更节省资源或 DRY 的方法?
- 如果这是最好的方法,我该如何更改我的代码和视图以显示此@user 的最高 5 个游戏/game_type 排名,因为代码现在只计算所有用户的排名?