10

我想为我的游戏实现互联网高分。并向玩家反馈他们的位置(不仅仅是top100或类似的东西)。在普通 SQL 中,它看起来像这样:

SELECT COUNT(*) FROM Scores WHERE points > :newUsersPoints

和 GQL 有类似的东西

db.GqlQuery("SELECT * FROM Score WHERE points > :1", newUsersPoints).count()

但由于 count() 仅限于 1000,因此在我的情况下它不会很有用。您对如何实现这一点有任何想法吗?

我有两个

第一的:

  1. 使用分片计数器的想法(http://code.google.com/intl/pl/appengine/articles/sharding_counters.html)创建新的“表”来存储在某个范围内的分数(from_points,to_points)

  2. 总结上表中 range.to_points < newUsersPoints 的所有计数器

  3. 在新分数为 db.GqlQuery("SELECT * FROM Score WHERE points > :1 AND points >= :2 AND points < :3", newUsersPoints, range.from_points, range. to_points).count() + sumfrom2

  4. 查找新分数所在的范围并增加其计数器

  5. 拆分计数器大于 1000(或 999)的范围,以便 3. 不会达到限制

  6. 将新分数添加到分数表

这是相当复杂且容易出错的。在添加分数之前,我们可能会增加一些范围和超时。(非交易性)

第二个想法:

不时(每天一次?)按分数对所有分数进行排序并给他们新的位置(脚本可能超时,所以我们必须分块执行)

要找出新分数在哪个地方,我们只需要做

db.GqlQuery("SELECT * FROM Score WHERE points > :1 LIMIT 1", newUsersPoints).get().precalculated_position + 1

还有其他想法吗?

4

2 回答 2

5

我已经在几个 GAE 应用程序中实现了 Ranker。它们是 Facebook 应用程序,有成千上万的人在玩。它运作良好,但就我而言,它有一个很大的缺点:您需要提前声明参与者分数将落入的最终范围。所以这很糟糕,原因有两个:

  1. 如果你有一场没有尽头的比赛,人们的分数可以无上限地继续攀升,那么你就被圈住了。

  2. 在比赛开始时,当每个人都聚集在一起接近零时,ranker.py 使用的树结构效率不高。这棵树很深,几乎没有使用它的任何宽度。

换句话说,ranker.py 非常适合您的参赛者的分数以均匀方式随机分布在已知值范围内的情况。对于其他用途,它不是最佳的。

我希望尽快开发出更通用的排名引擎。发生这种情况时肯定会更新此线程!

于 2009-06-10T06:00:31.950 回答
4

google-appengine 组上的这个线程可能会引起人们的兴趣。看起来也有一个专门用于此的库ranklist

基本上,听起来他们做了类似于分片计数器的事情。

于 2009-03-04T08:57:00.757 回答