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

3 天前
 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=='))拉群

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

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

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

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

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

© 2021 V2EX