開發歷程:樂透「預測」工具——一個確定性函式假裝不確定性

這是 LocalPapa Notes 開發紀錄系列的第十六篇。

這篇的主角是網站上一個最「輕量」的工具——樂透預測。開發時間很短,程式碼很少,但背後有一個值得記錄的設計問題:「預測」這個詞在這裡是真的嗎?

從數學開始:樂透無法被預測

先把話說清楚。台灣大樂透從 1 到 49 選 6 個號碼,每次開獎都是獨立隨機事件。上一期開了 07、14、22、31、38、42,下一期這些號碼「出現的機率」和其他任何組合一模一樣——歷史結果對未來開獎零資訊量

這是機率論的基礎,不是意見,是事實。任何聲稱「根據歷史分析出下期熱門號碼」的工具,要嘛是刻意誤導,要嘛作者自己也沒想清楚。

既然無法預測,我們的「樂透預測工具」在做什麼?

它真正做的事:確定性的娛樂

答案是:把時間當作種子,用確定性演算法生成號碼。

``javascript function getSeed() { const blockSize = 30 * 60 * 1000; // 30 分鐘 return Math.floor(Date.now() / blockSize); } ``

把目前的時間戳除以 30 分鐘的毫秒數,取整數——在同一個 30 分鐘區間內,這個值固定不變。它就是種子。

``javascript function seededRandom(seed) { const m = 0x80000000; // 2^31 const a = 1103515245; // glibc 標準 LCG 乘數 const c = 12345; let state = seed; return function () { state = (a * state + c) % m; return state / (m - 1); } } ``

這是線性同餘生成器(LCG)——acm 的值來自 glibc(GNU C 函式庫)的標準參數,有幾十年的使用歷史。它是偽隨機:給定相同種子,永遠生成相同序列。種子一換,序列就換。

把種子丟進去,生成 6 個不重複、範圍 1–49 的號碼(用 Set 做去重,sorted 排序),就是「這個 30 分鐘的幸運號碼」。

在這 30 分鐘內,不管你點幾次「立即預測」,號碼都一樣。 30 分鐘過去,種子一換,號碼換一組新的。

為什麼是 LCG 而不是 Math.random()

Math.random() 每次呼叫都給不同的值——是真正的(或接近真正的)隨機。用它的話,每次按按鈕都會換號碼,使用者沒有一組「今天的幸運號碼」可以回來查,也無法共享「現在的」號碼。

LCG 的確定性反而是優點:

  • 同一裝置、同一時段,號碼固定——可以截圖分享,朋友看到的是同一組。
  • 跨裝置一致——A 和 B 在同一個 30 分鐘區間打開工具,得到相同號碼,會覺得「有道理」。
  • 倒計時有意義——使用者知道幾點幾分會換新號碼,可以「期待」下一輪。

把不可預測的開獎,用確定性的時間函式包裝成「有節奏的娛樂體驗」——這是設計意圖,不是技術妥協。

滾球動畫:溝通設計

六顆數字球依序出現,每顆有個「滾動」動畫(CSS class toggle + setTimeout stagger 200ms 一顆)。這不是裝飾,是溝通設計

  • 讓使用者有「看開獎」的儀式感,而不是頁面直接印出六個數字。
  • 延遲出現讓號碼被逐一注意,而不是一眼看過去就忘了。
  • 按鈕在動畫期間 disable,避免重複觸發。

娛樂工具的感受很大程度由「程序感」決定,不只是數字本身。

「預測」這個詞的兩面

這個工具叫「樂透預測」。SEO 角度,「樂透預測」是真實搜尋量很高的關鍵詞——很多人確實在搜這個詞,想要這樣的工具。如果工具叫「樂透號碼產生器」,找得到的人就少很多。

但對使用者,一打開就必須澄清。頁面的免責說明:

此預測僅供娛樂,號碼每 30 分鐘根據時間演算法固定生成,非隨機亂數。

這句話做了三件事:

  1. 「僅供娛樂」——不是真的預測。
  2. 「每 30 分鐘根據時間演算法固定生成」——告訴你機制,不神祕化。
  3. 「非隨機亂數」——直接說它是確定性的,不讓你誤以為每次按有不同結果。

標題用「預測」是為了被找到;頁面立刻說清楚它不是真的預測——這是誠實行銷的做法:吸引正確的受眾,然後立刻設定正確的期望。

和命理服務的對照

如果你按照系列讀到這裡,會注意到一個有趣的對照:

  • 紫微斗數、達摩一掌經:算法複雜、有傳統依據、誠實標示為「詮釋性內容、非預測」。
  • 樂透預測:算法極簡、無任何依據、誠實標示為「娛樂、確定性生成」。

兩者都說了「不是預測」,但出發點完全不同。命理服務是說「我有一定的傳統系統,但請不要把它當成客觀預言」;樂透工具是說「我根本就沒有預測能力,這是一個好看的時間函式」。

誠實的邊界不同,但誠實本身是相同的要求。

學到的事

  • 數學上不可能的事,不要包裝成可能的。 樂透開獎獨立隨機,這是事實。工具不能違反它,只能繞開:提供「確定性娛樂」而非「統計預測」。
  • 確定性有時比隨機更好的使用者體驗。 同一 30 分鐘內固定號碼、跨裝置一致、倒計時有意義——都是確定性帶來的好處。
  • LCG 的古老參數是有理由的。 glibc 那組 a/c/m 的統計分布夠均勻、週期夠長,對娛樂用途完全足夠,不需要重新研究。
  • 「吸引受眾」和「誠實說明」可以同時做到。 工具名稱用搜尋量高的詞;頁面立刻澄清機制。不是欺騙,是分層溝通。
  • 滾球動畫是工具的一部分,不是糖衣。 程序感讓數字從「輸出」變成「體驗」。

一以貫之的問題

前面的命理工具問「能不能在瀏覽器完成」。這篇換了個問法:能不能誠實地包裝一個「在數學上根本做不到的事」的工具,讓它有用、有趣,同時不欺騙使用者?

答案是可以的。關鍵是:知道自己在做什麼(確定性時間函式)、把這件事說清楚(免責說明直接解釋機制)、然後讓體驗本身有價值(節奏感、倒計時、滾球動畫)。

一個誠實的娛樂工具,比一個虛假的「預測工具」更值得存在。

系列繼續。下一篇命理篇章——塔羅牌如何用 22 大牌逐張 + 56 小牌花色×階級的組合設計,以最小資料量涵蓋 78 張,同樣是確定性的本地運算、同樣誠實標示為「詮釋工具」。想追蹤系列?把 LocalPapa Notes 加入書籤吧。

Dev Log: The Lottery "Predictor" — A Deterministic Function Pretending to Be Random

This is the sixteenth post in the LocalPapa Notes dev-log series.

Today's subject is one of the site's lightest tools — the Lottery Predictor. Short build time, minimal code, but a design question worth documenting: is the "prediction" in this tool genuine?

Starting with math: lotteries cannot be predicted

Let's say this clearly. Taiwan's Big Lotto picks 6 from 49 numbers; every draw is an independent random event. If last week's draw was 07, 14, 22, 31, 38, 42 — the probability of any particular number appearing next draw is identical to every other possible outcome. Historical results carry zero information about future draws.

This is probability theory fundamentals, not opinion. Any tool claiming to "use historical data to identify hot numbers for the next draw" is either deliberately misleading or not thinking clearly about what it's doing.

So if lottery results can't be predicted, what does our "Lottery Predictor" actually do?

What it actually does: deterministic entertainment

It uses time as a seed and generates numbers with a deterministic algorithm.

``javascript function getSeed() { const blockSize = 30 * 60 * 1000; // 30 minutes return Math.floor(Date.now() / blockSize); } ``

Take the current timestamp, divide by the number of milliseconds in 30 minutes, floor the result — within any given 30-minute window, this value is constant. That's the seed.

``javascript function seededRandom(seed) { const m = 0x80000000; // 2^31 const a = 1103515245; // glibc standard LCG multiplier const c = 12345; let state = seed; return function () { state = (a * state + c) % m; return state / (m - 1); } } ``

This is a Linear Congruential Generator (LCG) — the a, c, m values are glibc's standard parameters, in use for decades. It's pseudo-random: same seed always produces the same sequence. Change the seed and the sequence changes.

Feed that into 6 unique numbers from 1–49 (a Set handles deduplication, sorted ascending) and you have "this 30-minute window's lucky numbers."

Within those 30 minutes, no matter how many times you click "Predict," the numbers are the same. The window closes, seed increments, a new set of numbers appears.

Why LCG over Math.random()

Math.random() gives a different value on every call — genuinely (or near-genuinely) random. Using it, every button press gives different numbers; the user has no "today's lucky numbers" to look up or share, and no "current" number to share with a friend.

LCG's determinism is the feature:

  • Same device, same time window, same numbers — you can screenshot and share; your friend sees the same set.
  • Cross-device consistency — A and B open the tool in the same 30-minute window and get the same numbers, which feels coherent.
  • The countdown has meaning — users know exactly when the numbers change and can "look forward" to the next draw.

Wrapping an unpredictable outcome in a deterministic time function to create "a rhythmic entertainment experience" is a design intent, not a technical compromise.

Rolling ball animations: communication design

Six numbered balls appear in sequence, each with a "rolling" animation (CSS class toggle plus staggered setTimeout at 200ms per ball). This isn't decoration — it's communication design:

  • It gives users the ritual of "watching a draw," not just reading six digits.
  • Staggered appearance makes each number noticed individually, not swept past.
  • The button disables during animation to prevent re-triggering.

The perceived quality of an entertainment tool is largely determined by its procedural feel, not just the underlying numbers.

Two faces of the word "prediction"

This tool is called a Lottery Predictor. From an SEO perspective, "lottery prediction" (樂透預測) is a high-volume search term — many people genuinely search for this and want a tool for it. If the tool were named "Lottery Number Generator," far fewer people would find it.

But for the user, the page must clarify immediately on arrival. The disclaimer:

For entertainment purposes only. Numbers are generated deterministically using time-block algorithms every 30 minutes.

This sentence does three things:

  1. "Entertainment purposes only" — not real prediction.
  2. "Generated deterministically using time-block algorithms every 30 minutes" — tells you the mechanism, no mystification.
  3. Explains it's deterministic — so you know clicking again in the same window won't change the result.

Using "prediction" in the title is for discoverability; explaining it's not real prediction immediately on the page is for honesty. This is honest marketing: attract the right audience, then immediately calibrate expectations correctly.

A contrast with the divination services

If you've read this series in order, there's an interesting parallel to note:

  • Zi Wei Dou Shu, Yi Zhang Jing: complex algorithms, traditional scholarly basis, honestly labelled "interpretive content, not prediction."
  • Lottery Predictor: trivially simple algorithm, no basis whatsoever, honestly labelled "entertainment, deterministically generated."

Both say "not a prediction," but from completely different starting points. The divination services say "I have a traditional system with interpretive value, but don't treat it as objective prophecy." The lottery tool says "I have no predictive capacity at all — this is a nicely packaged time function."

The boundary of honesty differs; the requirement for honesty is the same.

What we learned

  • Don't package mathematically impossible things as possible. Lottery draws are independent random events. The tool can't violate that — it works around it: offering "deterministic entertainment" instead of "statistical prediction."
  • Determinism sometimes beats randomness for user experience. Fixed numbers per 30-minute window, cross-device consistency, a meaningful countdown — all advantages of determinism.
  • The ancient LCG parameters exist for good reason. The glibc a/c/m values have good distribution properties and a long cycle — entirely sufficient for entertainment use, no need to research alternatives.
  • Attracting an audience and honest disclosure can coexist. Title uses the high-volume search term; page immediately clarifies the mechanism. Not deception — layered communication.
  • Rolling ball animation is part of the tool, not sugar-coating. Procedural feel turns "output" into "experience."

The same question, applied to honesty

Earlier tools asked "can this be done in the browser." This one asks: can you honestly package a tool that does something mathematically impossible, make it useful and fun, and not deceive the user?

You can. The key: know what you're actually doing (deterministic time function), say so clearly (the disclaimer explains the mechanism directly), then make the experience itself worth having (rhythm, countdown, rolling animations).

An honest entertainment tool is more worth building than a dishonest "prediction tool."

Series continues. Next in the divination arc — how tarot uses 22 major arcana individually plus "suit × rank" combinations for the 56 minor arcana to cover all 78 cards with minimal data, running the same deterministic local computation, carrying the same honest "interpretive tool" label. Want to follow the series? Bookmark LocalPapa Notes.

探索 39+ 個隱私優先的瀏覽器工具
全程本地運算、檔案不上傳。
前往 LocalPapa →
Explore 39+ privacy-first browser tools
Everything runs locally — your files never leave your device.
Visit LocalPapa →

想看英文版?點右上角 EN 切換語言。

Prefer Chinese? Tap at the top-right to switch.