Как реализовать интернет-рекорды в Google App Engine
Я хочу реализовать интернет-рекорды для своей игры. И дайте отзывы игрокам, которые у них есть (не только top100, либо что-то в этом роде).
В обычном SQL это будет выглядеть так:
SELECT COUNT (*) FROM Scores WHERE points > : newUsersPoints
и GQL имеют нечто подобное
db.GqlQuery( "SELECT * FROM Score WHERE points > : 1", newUsersPoints).count()
но поскольку count() ограничен только 1000, это не будет очень полезно в моем случае.
У вас есть идеи о том, как это реализовать?
У меня есть два
Во-первых:
-
Используйте идею счётчиков (http://code.google.com/intl/pl/appengine/articles/sharding_counters.html)
Создайте новую "таблицу", в которой хранится количество баллов в некотором диапазоне (from_points, to_points)
-
Суммируйте все счетчики из таблицы выше, где range.to_points < newUsersPoints
-
Найдите, сколько очков больше, чем баллы в диапазоне, где новый счет
db.GqlQuery( "SELECT * FROM Score WHERE points > : 1 AND points > =: 2 AND points <: 3", newUsersPoints, range.from_points, range.to_points).count() + sumfrom2
-
Найдите диапазон, в котором находится новый балл, и увеличивайте его счетчик
-
Диапазоны разделения, для которых счетчик больше 1000 (или 999), так что 3. не достигнет предела
-
Добавить новый счет в таблицу баллов
Это довольно сложно и подвержено ошибкам. Мы можем увеличить диапазон и время ожидания до добавления оценки. (не транзакционный)
Вторая идея:
Время от времени (один раз в день?) сортировать все баллы по точкам и давать им новые позиции (script может Timeout, поэтому мы должны делать это в кусках)
Чтобы узнать, в каком месте новый счет, мы просто делаем
db.GqlQuery( "SELECT * FROM Score WHERE points > : 1 LIMIT 1", newUsersPoints).get(). precalculated_position + 1
Любые другие идеи?
Ответы
Ответ 1
Я использовал Ranker в нескольких приложениях GAE. Это приложения Facebook, в которых тысячи и сотни тысяч людей играют. Он работает хорошо, но для моих целей у него есть один большой недостаток: вам нужно заранее объявить окончательный диапазон, по которому будут падать баллы участника. Так что это плохо по двум причинам:
-
Если у вас есть конкурс без конца, где люди могут продолжать подниматься без верхнего предела, вы обручены.
-
в начале конкурса, когда все сгруппированы вместе около нуля, древовидная структура, используемая ranker.py, неэффективна. дерево идет очень глубоко и почти не использует его ширину.
Другими словами, ranker.py отлично подходит для случая, когда у вас есть конкурсанты, чьи оценки случайным образом распределяются равномерно по известному диапазону значений. Для других целей он менее оптимален.
Я надеюсь в ближайшее время разработать более полезный ранжирующий механизм. Если это произойдет, обязательно обновите этот поток!
Ответ 2
Этот поток в группе google-appengine, вероятно, будет интересен. Он также выглядит как библиотека, ranklist, специально для этого.
В принципе, похоже, что они делали что-то похожее на заштрихованные счетчики.