У меня есть такой запрос PHP: SELECT * FROM `prizes` WHERE `caseid`='{$id}' AND `winner`='0' ORDER BY RAND() LIMIT 1 Я получаю рандомный приз из базы, но есть проблема, при выдачи выдается рандом полный, т.е может 4 раза подряд выпасть дорогой приз а дешевый нет. Я добавил в таблицу параметр chance подскажите как мне получить так-же 1 строку из базы но уже сделать выборку не только рандомно но и по шансу. Шанс до 100, т.е если указано 90 выпадает чаще чем если указано 89 и наоборот. Если указано 10 выпадает реже если указано 90 но выпасть может. В базе 11 тысяч призов. Иван, поместить вопрос в раздел "Сделайте за меня" значит объявить себя тупым и ленивым. Не будь таким — Модераторъ
Очень тяжело найти ответ на этот вопрос, уже три дня ищу нормальный ответ, обошел все форумы, ответа даже в гугле нет. Странно..
Я понимаю, но ведь чёткая последовательность шанса с мнимым рандомом. зависит от владельца сайта? я ведь просто хочу чтобы шанс выпадения какого-то дорогого приза был реже чем дешевых. Как мне это реализовать правильно?
выбираешь например 50 дорогих, 500 средних и 5000 дешёвых призов, перемешиваешь и сохраняешь в БД эту последовательность, таких последовательностей сохраняешь несколько раз, вот тебе "случайные" призы на много лет вперёд, просто берёшь уже не рандомно, а строго в этой сохранённой последовательности по порядку. Если изменятся условия, то перегенерировать подобный список дело считанных секунд.
@#Ivan Подумай о таком трюке как shuffle. Берешь любую последовательность значений без повторов, один раз перемешиваешь её и потом последовательно выбираешь из неё значения. Результат выглядит как "случайно и без повторов". Если надо чтобы шанс выпадения был неодинаковым, ну напихай в исходную последовательность несколько экземпляров того, что должно быть более вероятным. Далее — всё так же. https://ru.stackoverflow.com/a/501992/176610
А это кодом php можно как-то сделать проще? при условии что допустим в базе осталось только 50 призов что тогда делать? очень непонятно.
это и нужно делать на РНР, а потом сохранить в БД PS нет смысла эту генерацию последовательности проводить на уровне СУРБД, если только ради спортивного интереса, но лично мне не настолько скучно.
Легче с помощью php получить число, что-то типа PHP: function getChance(array $arr) { $rand = mt_rand(1, array_sum($arr)); foreach ($arr as $value) { $rand -= $value; if ($rand <= 0) { return $value; } } } $chance = getChance(range(1,100)); Потом делать запрос Код (Text): SELECT * FROM `prizes` WHERE `chance` = $chance ORDER BY RAND() LIMIT 1 Работоспособность не проверял, но скажу заранее, это не гарантирует 100% результат. Вполне возможно что chance 1 будет 1000 раз подряд, хотя и маловероятно)
Вывел циклом 10 раз подряд, вот что получилось. Код (Text): 91 96 74 85 91 30 При таком рандоме, шансы по моему бесполезны. Меня так ограбят
Что значит в базе осталось 50 призов? Сдаётся мне вы еще меньше понимаете, чем спрашиваете. Например у вас есть 10 разных позиций дорогих призов, за месяц вам их надо раздать 50 штук, Вы рандомно выбираете 50 штук из этих 10. В итоге у вас 3 хододильника, 5 телевизоров, 7микроволновок и тд. общее количество 50. То же самое и с остальными ценовыми категориями. Про наличие призов на складе - это уже отдельная тема. Но ничего не мешает при отсутствии выбранного приза на складе взять следующий "по списку". --- Добавлено --- @qdevelopment, код должен гарантировать 100% результат по ТЗ. Иначе такой код абсолютно не имеет смысла.
Вам не будет сложно показать пример как это сделать? я не совсем понимаю как это реализовать. Я объясню по простому: В базе допустим 20 строк, у 5 строк шанс равен 10, у 10 шанс 50, у остальных 10 шанс равен 95. По шансу, чем больше шанс, тем больше он выпадает чем строка у которой нет шанса, но задача усложняется тем чтобы выпадала строка еще с меньшим шансом но намного реже. Я не понимаю как это сделать. Если делать последовательность как я хотел, то я сталкиваюсь с проблемой №2. Допустим пользователь A открыл кейс 4 раза и ему выпал предмет с шансом 95, 95, 95, 95, 50 Пользователь B открыл кейс и ему выпал предмет с шансом 10% --- Добавлено --- Дополню про базу, допустим если в базе нет тех строк с максимальным шансом берется строка с меньшим шансом (меньшим т.е большим числом напр. 90)
Всм? --- Добавлено --- Период в том смысле за сколько выдать? --- Добавлено --- Период не нужен, мне нужно просто выдать приз с малой долей вероятности выпадения дорогого, но под понятием дорогой, средний и дешёвый как раз нужны шансы, разве нет?
Без периода вся затея не имеет смысла. Вот смотри. Допустим сегодня ты рассчитал шанс выпадения одних процентов относительно других процентов. И о чудо выпал главный приз, как ты при том же алгоритме расчёта гарантируеш, что завтра чуда не случится? Ответ. Никак. Поэтому расчёт должен быть относительно периода. И чем больше период, тем точнее расчёт.
Я до сих пор не понимаю для чего нужен расчет периода в моем случае, если допустим у всех призов будут одинаковые проценты. 10% - редкий приз. 60% - не редкий приз. 80% - частый приз. 100% - выпадает всегда. (чисто для примера) --- Добавлено --- Я думаю что я усложняю все то что нужно в конечном итоге получить и это можно реализовать проще.
а если сделать так.... 1. Выбираем число от 1 до 100.. к примеру выпало 34 2. В базе у нас у каждой позиции уже прописаны значений из цитаты допустим в столбце chance. 3. Просто берем Ваш запрос и добавляем условие Код (Text): SELECT * FROM `prizes` WHERE `caseid`='{$id}' AND `winner`='0' AND chance > 34 ORDER BY RAND() LIMIT 1 вот и все.. теперь все популярные призы участвуют.. редкие не участвуют..
@#Ivan, для начала надо определится, что именно нужно простота или гарантии? Можешь пойти по другому принципу. Создаёшь массив из 90 нулей и 10 единиц, перемешиваешь и выбираешь один элемент, если единица, то отдаёшь главный приз, если ноль, то по тако му же принципу рассчитываешь для 60 и тд. Но опять же никаких гарантий, что не отдашь главный приз 100 раз подряд.
Рандом дело такое, может и сразу выпасть 10) и придется отдать главный приз.. а вообще мне на другом форуме сказали следующие: "За ORDER BY RAND() Вам могут отрубить руки"
@#Ivan, программимту могут и отрубить, правда 11 тысяч для бд это не тот порядок, чтоб волноваться. Но проблема с ордер бай ранд давно известна и легко решаема. Но почему владельцу магазина, кто-то будет рубить руки? --- Добавлено --- @#Ivan, Алекс говорил не об этом. Если выпадет 0 или 10 это не значит, что сразу надо отдать главный приз, просто он будет участвовать в рандомной выборке на ровне со всеми. Тоже приемлимый вариант и тоже абсолютно без каких либо гарантий.
хмм сразу не понял что там стоит знак > больше. Идея мне нравится, остановлюсь на ней. --- Добавлено --- Тут даже можно использовать функцию рандома выше? --- Добавлено --- Код (Text): function getChance(array $arr) { $rand = mt_rand(1, array_sum($arr)); foreach ($arr as $value) { $rand -= $value; if ($rand <= 0) { return $value; } } } $chance = getChance(range(1,100)); --- Добавлено --- Проблема этого кода в том что я вывел 100 раз и было 0 строк меньше 15