Тема: Алгоритм отримання даних для лідерборду
Добридень. В мене є база з акаунтами користувачів, ця база не якась там mysql, а зовсім інше. У кожного користувача є різні поля, серед них є поле score і поле country. Як ви вже зрозуміли, перше поле це прогрес користувача в грі, чи більше це поле, тим він вище в лідерборді знаходиться, ну а друге поле - код країни.
Я вам поясню за першу задачу, і як я її зробив, аби було зрозуміле питання.
Нехай деякий користувач має score=300, а всього користувачів у нас 1000. Нам потрібно взяти 40 користувачів, у котрих score менше, і 40, у котрих більше. Тобто наш користувач має бути посередині цього списку. При цьому у кожного отриманого запису має бути порядковий номер відносно всього списку з користувачами.
Ось псевдокод, що робить це все
Спершу отримаємо позицію користувача серед усіх користувачів
var userRank = query.orderByDescending("score").lessOrEqual("score", myScore).Count();
а тепер візьмемо 80, або менше юзерів, що знаходяться з обох сторін користувача.
var users = query.OrderByDescending("score").Skip(userRank-40).Limit(80);
Тут ми спочатку сортуємо список по полю score в порядку спадання, тобто юзер з найбільшим score буде першим. Далі ми пропускаємо таку кулькість користувачів, після котрої до запису обраного юзера буде залишатись ще 40 юзерів, і після цього ми беремо перших 80 юзерів за допомогою лімітації.
Тепер у нас є 80 юзерів, і очевидно, що найперший з них буде мати позицію (rank) котра дорівнює userRank-40. Ми проходимось по всім 80 юзерам і присвоюємо кожному свій rank
int i = userRank-40;
foreach(var user in users)
{
user.Rank=i;
i++;
}
Гаразд. З цією задачею все зрозуміло.
А тепер увага, питання!
Як нам дістати 90 юзерів, у котрих поле country дорівнює ua, при цьому нумерація (ranking) повинна бути відносно всього списку з користувачами?
Ось вам приклад з 10 користувачами.
1 2(ua) 3(ua) 4 5(ua) 6 7(ua) 8 9(ua) 10
Тобто є 10 користувачів, і нам потрібно знайти 8 користувачів з центром в 5.
Тут не буде восьми користувачів з полем country=ua, тому результат має бути таким
2,3,5,7,9 і ось ци цифри - це нумерація користувачів відносно всього списку.
Якщо я б зробив от такий запит
var users = query.OrderByDescending("score").WhereEqualTo("country","ua").Skip(userRank-40).Limit(80);
То я б отримав користувачів з полем country=ua, але якби я їх далі пронумерував, то нумерація була б невірна. Різниця в rank між сусідніми користувачами дорівнювала б одиниці, хоча в реальному списку між ними може бути надцять користувачів без поля country, що дорівнює ua.
Так як мені ото зробити? Наразі є лишень одна думка - спершу нумерувати усіх-преусіх користувачів, тобто надати кожному свій rank, незалежно від поля country. Але проблма в тому, що користувачі може бути дуууже багато, а цей запит буде виконуватись кожного разу, коли якийсь з користувачів захоче подивитись, яке він має місце в лідерборді.