自已家的赣南脐橙开卖,给 v 友抽几箱

35 天前
 zzerd

抽奖规则和去年一样取上证指数和最后指定日期最高楼。上一年的帖子/996196

今年取 2024-11-22 上证指数收盘价作为随机数种子,有效抽奖用户为 2024-11-22 帖子回复最高楼层前的所有所有人

去年的抽奖代码没有去重所有回复多个的用户中的概率高一点点,今年我用 ai 糊了一下。代码如下

const UA = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36';

async function handleRequest(tid, num, seedParam, maxFloor) {
    if (!tid || isNaN(num)) {
        console.error('请提供有效的帖子 ID 和抽奖人数');
        return;
    }
    console.log(`Fetching OP for TID: ${tid}`);
    const op = await getOp(tid);
    console.log(`OP: ${op}`);
    console.log(`Fetching all users for TID: ${tid}`);
    const uniqueUserList = await getAllUser(tid, maxFloor);
    console.log(`Unique Users: ${uniqueUserList.join(', ')}`);
    const filteredUserList = uniqueUserList.filter(user => user !== op);
    console.log(`Filtered Users: ${filteredUserList.join(', ')}`);
    const userCount = filteredUserList.length;
    console.log(`User Count: ${userCount}`);
    const seed = seedParam !== null ? seedParam : userCount.toString();
    console.log(`Seed: ${seed}`);
    console.log(`Max Floor: ${maxFloor}`);
    const combinedSeed = `${seed}-${maxFloor}`;
    console.log(`Combined Seed: ${combinedSeed}`);
    const shuffledList = shuffle(filteredUserList, combinedSeed);
    console.log(`Shuffled Users: ${shuffledList.join(', ')}`);
    const result = `符合条件的用户共有 ${filteredUserList.length} 人
抽奖结果:
${shuffledList.slice(0, num).join('\n')}`;
    console.log(result);
}

async function getOp(tid) {
    const url = `https://www.v2ex.com/amp/t/${tid}`;
    console.log(`Fetching OP URL: ${url}`);
    const response = await fetch(url, { headers: { 'User-Agent': UA } });
    if (!response.ok) {
        console.log(`Failed to fetch OP: ${response.status} ${response.statusText}`);
        return null;
    }
    const text = await response.text();
    const match = /<div class="topic_author">[\s\S]*?<amp-img[^>]+alt="([^"]+)"[\s\S]*?<\/div>/.exec(text);
    console.log(`OP Match: ${match ? match[1] : null}`);
    return match ? match[1].trim() : null;
}

async function getUserList(url, startIndex, endIndex) {
    console.log(`Fetching User List URL: ${url}`);
    const response = await fetch(url, { headers: { 'User-Agent': UA } });
    if (!response.ok) {
        console.log(`Failed to fetch User List: ${response.status} ${response.statusText}`);
        return [];
    }
    const text = await response.text();
    const replyItemRegex = /<div class="reply_item">([\s\S]*?)<\/div>/g;
    let replyItemMatch;
    const users = [];
    let currentIndex = startIndex || 0;
    while ((replyItemMatch = replyItemRegex.exec(text)) !== null) {
        if (endIndex !== undefined && currentIndex >= endIndex) {
            break;
        }
        const replyItem = replyItemMatch[1];
        const altRegex = /<amp-img[^>]+alt="([^"]+)"[^>]*>/g;
        const altMatch = altRegex.exec(replyItem);
        if (altMatch) {
            users.push(altMatch[1]);
        }
        currentIndex++;
    }
    console.log(`Matches: ${users.join(', ')}`);
    return users;
}

async function getAllPages(tid) {
    const url = `https://www.v2ex.com/amp/t/${tid}`;
    console.log(`Fetching All Pages URL: ${url}`);
    const response = await fetch(url, { headers: { 'User-Agent': UA } });
    if (!response.ok) {
        console.log(`Failed to fetch All Pages: ${response.status} ${response.statusText}`);
        return [];
    }
    const text = await response.text();
    const pageCountMatch = /\u5171 (\d+) \u9875/.exec(text);
    const pageCount = pageCountMatch ? parseInt(pageCountMatch[1], 10) : 1;
    console.log(`Page Count: ${pageCount}`);
    const pages = [];
    for (let i = 1; i <= pageCount; i++) {
        pages.push(`${url}/${i}`);
    }
    return pages;
}

async function getAllUser(tid, maxFloor) {
    const pages = await getAllPages(tid);
    console.log(`Pages: ${pages.join(', ')}`);
    let allUsers = [];
    let currentFloor = 0;
    for (let page of pages) {
        const startIndex = currentFloor;
        const endIndex = maxFloor !== undefined ? maxFloor : undefined;
        const users = await getUserList(page, startIndex, endIndex);
        allUsers = allUsers.concat(users);
        currentFloor += users.length;
        if (endIndex !== undefined && currentFloor >= endIndex) {
            break;
        }
    }
    const uniqueUsers = [];
    const seen = new Set();
    for (const user of allUsers) {
        if (!seen.has(user)) {
            uniqueUsers.push(user);
            seen.add(user);
        }
    }
    console.log(`Unique Users: ${uniqueUsers.join(', ')}`);
    return uniqueUsers;
}

function shuffle(array, seed) {
    const rng = lcg(seed);
    console.log(`Shuffling with Seed: ${seed}`);
    for (let i = array.length - 1; i > 0; i--) {
        const j = Math.floor(rng() * (i + 1));
        console.log(`Shuffling: i=${i}, j=${j}`);
        if (array[i] !== undefined && array[j] !== undefined) {
            [array[i], array[j]] = [array[j], array[i]];
        } else {
            console.log(`Error: array[i] or array[j] is undefined. i=${i}, j=${j}, array[i]=${array[i]}, array[j]=${array[j]}`);
        }
    }
    return array;
}

function lcg(seed) {
    let state = hashCode(seed);
    console.log(`LCG State: ${state}`);
    const a = 1664525;
    const c = 1013904223;
    const m = Math.pow(2, 32);
    return function() {
        state = (a * state + c) % m;
        console.log(`LCG Next: ${state / m}`);
        return state / m;
    }
}

function hashCode(str) {
    l
![]( https://i.v2ex.co/VlpwI4y5.jpeg)
et hash = 0;
    for (let i = 0; i < str.length; i++) {
        const char = str.charCodeAt(i);
        hash = ((hash << 5) - hash) + char;
        hash |= 0;
    }
    return Math.abs(hash);
}

// Example usage:
handleRequest('123456', 3, seed123, 10);
这里的 '123456' 是帖子 ID ,3 是抽奖人数,'seed123' 是种子(可选),10 是最大楼层(可选)。
在 V2EX 网站里用浏览器 consele 运行就可以

为了方便 v 友进行类似抽奖我糊了一个 cloudflare work 来使用直接请求 https://v2ex.240801.xyz/?tid=12345&num=10&seed=12345&maxFloor=11(大佬别打,刚装上访问不了可能 cf 路由没设置好)这里的参数说明为 tid 为帖子 id num 为中奖人数 seed 为随机数种子 maxFloor 为最高楼层

下面是橙子链接请大家按需购买

ps 甜度不用担心,今年我们县的都甜。现摘现发没有清洗打腊,只要老家不下雨一般下单第二天就发货。室温 20 度以内还是很耐放的两三个星期没啥问题。有个卖橙子的微信群想加的加我微信 console.log(atob('enF3MjAwOA=='))拉群

7327 次点击
所在节点    推广
544 条回复
puzzle9
35 天前
尝试中奖 体会 v 友的开心
chinafeng
35 天前
做个分母
YiCherish
35 天前
支持
WeaPoon
35 天前
分子试试~
leo72638
35 天前
试试
gugulaliqi
35 天前
碰运气
243205964
35 天前
抽奖代吗越来越复杂了
Ceylan
35 天前
试试
AppxLite
35 天前
参与一下
RobertLyu
35 天前
我来成为分子!
zsedc
35 天前
分母
moxxun
35 天前
试试
d1456198
35 天前
➕1
youbaoer
35 天前
分母+1
Mrabbit
35 天前
重在参与,爱吃脐橙
abcgoodwei
35 天前
重在参与,爱吃脐橙
c9c2ane
35 天前
有优惠吗
monstericeer
35 天前
+1 !
ch20191
35 天前
我来组成弹幕~~~~~~~~~~~~~~欧皇爱我~~~~~~~~~~~~~
dmdouo12
35 天前
+1

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1091646

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX