Coding4Fun - 用jQuery自動完成來對樂透吧!
今年過年大樂透史無前例地加開了100組百萬獎金,但顯然彩券公司小看了大家想發財的決心,彩券公司網站在昨天晚上八點公佈百組額外獎號,"據說"還很貼心地提供了對獎程式(真的是據說,我到現在還沒看到它長什麼樣子),但河道上持續看到噗友回報,台彩網站始終出現Server Is Busy訊息,連凌晨三點都不例外。

針對這種一窩蜂的使用流量,理論上是使用雲端的大好時機,雲端架構可依臨時需求快速擴充伺服器數量,之後再動態調節回復常態,正是因應此種極端式尖峰離峰落差的有效解決方案。只是不知是流量被低估、技術沒導入,還是經費不充足,彩券網站並未嘗試時下正夯的雲端技術,而在大家發財夢的DDoS猛攻之下,網站到現在都還是處於掛點狀態。
其實,既是純粹的小資料量結果公佈與查詢,理論上用HTML+Client Script寫查詢程式就可滿足需求,應該可大幅提高伺服器負載上限,反正開獎結果項目有限,也無需保密,用Javascript寫未嘗不可。
在網路上找到熱心網友提供的開獎結果,用Excel欄位值過瀘的點子很棒! 對獎後,我也很快就確定今年仍要繼續努力工作...
不過,既然提了HTML + Client Scripting減少伺服器負載的做法,為了證明自己不是嘴砲王,一時興起就改寫了jQuery自動完成懶人包,小調一下就寫成一個完全不需要Server端程式的中獎號碼自動完成範例。
由於傳統jQuery自動完成都是用AJAX呼叫後端程式進行關鍵字查詢,所以我改寫了jquery.autocomplete.js,加入四行程式,如此當我們在options.url中傳入Javascript函數時,就可以取代呼叫Server端程式,直接寫Javascript程式比對使用者輸入的文字,組合出提示結果後傳回。
function requestData(q) {
if (!options.matchCase) q = q.toLowerCase();
//2009-05-21 by Jeffrey, add noCache flag to disable cache
var data = (!options.noCache && options.cacheLength) ? loadFromCache(q) : null;
// recieve the cached data
if (data) {
receiveData(q, data);
// if an AJAX url has been supplied, try loading the data now
}
//2011-02-03 by Jeffrey, support Javascript function as data provider
if (typeof options.url == "function") {
data = options.url(q);
addToCache(q, data);
receiveData(q, data);
}
else if ((typeof options.url == "string") && (options.url.length > 0)) {
$.get(makeUrl(q), function (data) {
data = parseData(data);
addToCache(q, data);
receiveData(q, data);
});
// if there's been no data found, remove the loading class
} else {
$input.removeClass(options.loadingClass);
}
};
加入支援Javascript函數資料源功能後,先製作一個中獎號碼的資料物件陣列,再用簡單的迴圈逐一比對(理論上可以再改成更有效率的演算法,但號碼只有100組,實測此速度已堪用),並透過事前排序縮小比對範圍增加一點速度,就完成了對獎邏輯。
<script type="text/javascript">
var dataPool = [];
dataPool.push({ Key: '01 02 03 04 33 45', Name: '第68組: 01 02 03 04 33 45' });
dataPool.push({ Key: '01 03 09 22 31 34', Name: '第6組: 01 03 09 22 31 34' });
//...省略...
dataPool.push({ Key: '19 32 37 42 47 48', Name: '第29組: 19 32 37 42 47 48' });
dataPool.push({ Key: '22 25 34 36 38 44', Name: '第36組: 22 25 34 36 38 44' });
</script>
<script type="text/javascript">
$(function () {
$("#txtNumbers").autocomplete(
function (q) {
var res = [];
//此處使用逐一列舉比對的單純寫法,要提高效能應改用更有效率的比對演算法
for (var i = 0; i < dataPool.length; i++) {
var data = dataPool[i];
var cmp = data.Key.substr(0, q.length);
if (cmp == q)
res.push([data.Key, data.Name]);
if (cmp > q || res.length >= 10)
break;
}
return res;
},
{
delay: 10,
width: 250,
//...省略...
薑薑薑薑,一個不需要Server端程式的樂透中獎號碼jQuery自動完成網頁就完成囉!

最後,補上產生中獎資料陣列的程式:
<%@ Page Language="C#" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Linq" %>
<script runat="server">
string rawData =
@"1 05 10 16 19 42 44
2 09 12 17 24 30 49
...省略...
98 13 18 25 37 39 46
99 13 39 40 42 43 48
100 03 07 08 12 38 43";
void Page_Load(object sender, EventArgs e)
{
var q = from s in rawData.Split('\n')
select new
{
Seq = s.Substring(0, s.IndexOf(" ")),
Numbers = s.Substring(s.IndexOf(" ") + 1).TrimEnd('\r')
};
Response.ContentType = "text/plain";
Response.Write("var dataPool = [];\r\n");
foreach (var d in q.OrderBy(s => s.Numbers))
Response.Write(
string.Format(
"dataPool.push({{ Key: '{1}', Name: '第{0}組: {1}' }});\r\n",
d.Seq, d.Numbers));
Response.End();
}
</script>
有趣吧! 祝大家新年快樂,早日中奬發大財~~~