23834 бриллианта, какое максимальное количество розыгрышей?

задняя часть внешний интерфейс
23834 бриллианта, какое максимальное количество розыгрышей?

предисловие

Вот в чем дело: прошел месяц с тех пор, как Nuggets запустили лотерею с регистрацией, и прошел 31 день с тех пор, как они настояли на том, чтобы зарегистрироваться.

image.png

Как показано на рисунке, количество сэкономленных бриллиантов составляет 23834. (PS: Часть бриллиантов была потрачена на тестирование и дешевые руки, так что должно быть около 30 000 бриллиантов.)

Итак, 23834 бриллианта, 200 бриллиантов потребляются в каждом розыгрыше, сколько всего требуется розыгрышей?

Ответ прост, результат округления в меньшую сторону:119Второсортный. Если вы каждый раз нажимаете и ждете на странице, это взад и вперед действительно ручная работа.

PS: На самом деле ответ на этот расчет не готов, окончательный ответ скажу позже.153Второсортный.

В соответствии с принципом ничего не делать, если вы можете написать код, полностью использовать преимущества программистов и написать сценарий, который заменит мою лотерею.

анализ проблемы

Одним словом: способ реализации лотереи Nuggets — это front-end анимация + back-end реализация интерфейса. Таким образом, настоящее действие лотереи заключается в вызове интерфейса, а интерфейс отображает логику результата.

Нечего сказать, какой интерфейс вызывается, когда Google Chrome открывает инструменты разработчика, чтобы увидеть лотерею. эмм....

image.png

Как показано на рисунке, интерфейс, вызываемый при входе в системуhttps://api.juejin.cn/growth_api/v1/lottery/draw

Код

Приведенный выше анализ лотереи требует только вызова интерфейса лотереи, после чего круговая лотерея может быть проведена напрямую. Запустите как открытую копию режима разработки и вставьте session_id из файла cookie. Вставьте в скрипт, чтобы разыграть лотерею.


import requests
from requests import cookies

class Juejin(object):

    # 掘金抽奖 URL
    lottery_url = "https://api.juejin.cn/growth_api/v1/lottery/draw"

    def __init__(self, driver_cookies=None, cookie_obj=None):
        self.session = requests.session()
        if driver_cookies:
            for cookie in driver_cookies:
                cookie_obj = requests.cookies.create_cookie(
                    domain=cookie.get("domain"),
                    name=cookie.get("name"),
                    value=cookie.get("value")
                )
                self.session.cookies.set_cookie(cookie_obj)
        elif cookie_obj:
            self.session.cookies.set_cookie(cookie_obj)
        else:
            raise Exception("Cookie is Blank")

    def request(self, *args, **kwargs):

        response = self.session.request(*args, **kwargs)
        if response.status_code != 200:
            raise Exception("Request error")
        return response.json()

    def draw_lottery(self):
        return self.request("post", self.lottery_url)


def lottery():

    # session id 自行设置
    session_id = ""

    cookie = requests.cookies.create_cookie(
        domain=".juejin.cn",
        name="sessionid",
        value=session_id
    )
    juejin = Juejin(cookie_obj=cookie)

    gift = {}
    num = 1

    while True:
        result = juejin.draw_lottery()
        if result.get("err_no") == 0:
            lottery_name = result.get("data", {}).get("lottery_name")
            if gift.get(lottery_name):
                gift[lottery_name] += 1
            else:
                gift[lottery_name] = 1
            print(f"第{num}次-抽奖结果为:{lottery_name}")
            num += 1
        else:
            print(result.get("err_msg"))
            break

    print(f"总抽奖次数为:{num-1}")

    print("最终抽奖结果为:")
    for k, v in gift.items():
        print(f"礼物:{k} ---- 个数:{v}")

Отображение результатов работы программы (здесь протестированы результаты десяти розыгрышей лотереи):

第1次-抽奖结果为:66矿石
第2次-抽奖结果为:66矿石
第3次-抽奖结果为:Bug
第4次-抽奖结果为:66矿石
第5次-抽奖结果为:66矿石
第6次-抽奖结果为:Bug
第7次-抽奖结果为:66矿石
第8次-抽奖结果为:66矿石
第9次-抽奖结果为:Bug
第10次-抽奖结果为:66矿石

总抽奖次数为:{10}

礼物:66矿石 ---- 个数:7
礼物:Bug ---- 个数:3

Витрина результатов лотереи

Всего бриллиантов: 23834 Количество розыгрышей: 153 раза

Подарок-66 Руда: 106 Подарок-жук: 47

Подытожим: вероятность вытянуть 66 руд 69,28%, а вероятность вытянуть жука 30,72%.

Лотерейная вероятность тестирования 10 раз в основном согласуется с лотерейной вероятностью тестирования 153 раза.

划重点:此次试验证明掘金抽到 T恤、抱枕、Switch 的概率基本等于零,各位小伙伴不要心存幻想了。

image.png

Думать и подводить итоги

  • Как использовать программу для реализации алгоритма лотереи, похожей на Наггетс?

Метод реализации очень прост, чтобы контролировать результат лотереи, настраивая интервал. Ниже приведена простая демонстрация кода:

import random


# 66矿石与Bug的比重为 7:3 [0-700)的随机数为66矿石,[700-1000)为Bug
def draw():
    temp = random.randint(0, 1000)

    if temp < 700:
        return "66矿石"
    else:
        return "Bug"
  • Предполагая, что у меня 23834 бриллианта, каково максимальное количество розыгрышей?

# 初始化钻石数
num = 23834

# 66钻石获取概率
rate = 0.7

# 抽奖次数
count = 0

while num >= 200:
    t, r = divmod(num,200)
    count += t
    num = (66 * t + r) * rate
    
print(count) 
# 153.0

JS-версия

Друзья в области комментариев надеются получить версию JS и специально обновить интерфейсные скрипты.

Следующий код можно запустить в консоли браузера (проверено только в хроме).

Примечание. Для запуска скопируйте и вставьте прямо в консоль. Раз операцию нельзя остановить, это очень полезно. . .


stime = Date.parse(new Date());
result = {}
count = 0
flag = true

while (flag) {
    obj = await fetch('https://api.juejin.cn/growth_api/v1/lottery/draw', {
      method: 'POST',
      credentials: "include",
      headers: {
        'Content-type': 'application/json; charset=UTF-8'
      }
    })
    .then(res => {
        obj = res.json()
        return obj
    
    })
    
    if (obj.err_no === 0) {
            
        if (obj.data.lottery_name in result) {
            result[obj.data.lottery_name] += 1
        } else {
            result[obj.data.lottery_name] = 1
        }
        
        count ++

    } else {
        flag = false
    }
 
}
etime = Date.parse(new Date())
console.log("抽奖次数为:" + count)
console.log("抽奖花费时间为:", (etime - stime)/1000 +  " 秒" )
console.log("抽奖奖品明细")
Object.keys(result).forEach(key => console.log("奖品:" + key + "--数量:" + result[key] ))

// 抽奖次数为:3
// 抽奖花费时间为: 1 秒
// 抽奖奖品明细
// 奖品:66矿石--数量:2